# Conflicts: # bubble-webpull/20/head
@@ -16,8 +16,9 @@ | |||
# | |||
# Environment variables: | |||
# | |||
# INSTALL_WEB : if this is equal to 'web' then the frontend will be built and included in the jar | |||
# DEBUG_BUILD : if this is equal to 'debug' then nothing will be done, the jar will be left as-is | |||
# INSTALL_WEB : if this is equal to 'web' then the frontend will be built and included in the jar | |||
# DEBUG_BUILD : if this is equal to 'debug' then nothing will be done, the jar will be left as-is | |||
# BUBBLE_PRODUCTION : if this is set to anything, then a production build will be made. | |||
# | |||
SCRIPT="${0}" | |||
SCRIPT_DIR=$(cd $(dirname ${SCRIPT}) && pwd) | |||
@@ -42,10 +43,15 @@ done | |||
cd ${CLASSES_DIR} && jar uvf ${BUBBLE_JAR} scripts || die "Error updating ${BUBBLE_JAR} with scripts" | |||
if [[ ! -z "${INSTALL_WEB}" && "${INSTALL_WEB}" == "web" ]] ; then | |||
if [[ ! -z "${BUBBLE_PRODUCTION}" || ( ! -z "${INSTALL_WEB}" && "${INSTALL_WEB}" == "web" ) ]] ; then | |||
mkdir -p ${CLASSES_DIR}/site | |||
BUBBLE_WEB="$(cd "${SCRIPT_DIR}/../bubble-web" && pwd)" | |||
cd ${BUBBLE_WEB} && npm install && webpack || die "Error building bubble-web" | |||
if [[ ! -z "${BUBBLE_PRODUCTION}" ]] ; then | |||
WEBPACK_OPTIONS="--mode=production" | |||
else | |||
WEBPACK_OPTIONS="" | |||
fi | |||
cd ${BUBBLE_WEB} && npm install && webpack ${WEBPACK_OPTIONS} || die "Error building bubble-web" | |||
cp -R ${BUBBLE_WEB}/dist/* ${CLASSES_DIR}/site/ || die "Error copying ${BUBBLE_WEB}/dist/* -> ${CLASSES_DIR}/site/" | |||
cd ${CLASSES_DIR} && jar uvf ${BUBBLE_JAR} site || die "Error updating ${BUBBLE_JAR} with site" | |||
echo "Installed bubble-web to ${CLASSES_DIR}/site/" | |||
@@ -7,18 +7,15 @@ package bubble.cloud.compute; | |||
import bubble.dao.cloud.BubbleDomainDAO; | |||
import bubble.dao.cloud.BubbleNodeDAO; | |||
import bubble.dao.cloud.CloudServiceDAO; | |||
import bubble.model.cloud.BubbleDomain; | |||
import bubble.model.cloud.BubbleNode; | |||
import bubble.model.cloud.CloudService; | |||
import bubble.server.BubbleConfiguration; | |||
import lombok.NonNull; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.cobbzilla.util.daemon.SimpleDaemon; | |||
import org.cobbzilla.util.network.NetworkUtil; | |||
import org.cobbzilla.util.string.StringUtil; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import java.util.Set; | |||
import static java.util.concurrent.TimeUnit.MINUTES; | |||
import static org.cobbzilla.util.system.Sleep.sleep; | |||
@@ -51,33 +48,35 @@ public class NodeReaper extends SimpleDaemon { | |||
} | |||
} | |||
private void processNode(BubbleNode node) { | |||
final BubbleNode found = nodeDAO.findByIp4(node.getIp4()); | |||
if (found == null) { | |||
if (wouldKillSelf(node)) return; | |||
log.warn(prefix()+"processNode: no node exists with ip4="+node.getIp4()+", killing it"); | |||
final BubbleDomain domain = domainDAO.findByUuid(node.getDomain()); | |||
final CloudService dns = cloudDAO.findByUuid(domain.getPublicDns()); | |||
private void processNode(@NonNull final BubbleNode node) { | |||
final var found = nodeDAO.findByIp4(node.getIp4()); | |||
if (found == null && !wouldKillSelf(node)) { | |||
log.warn(prefix() + "processNode: no node exists with ip4=" + node.getIp4() + ", killing it"); | |||
final var domain = domainDAO.findByUuid(node.getDomain()); | |||
final var dns = domain != null ? cloudDAO.findByUuid(domain.getPublicDns()) : null; | |||
try { | |||
dns.getDnsDriver(configuration).deleteNode(node); | |||
if (dns != null) dns.getDnsDriver(configuration).deleteNode(node); | |||
compute.stop(node); | |||
} catch (Exception e) { | |||
log.error(prefix()+"processNode: error stopping node "+node.getIp4()+": "+e); | |||
log.error(prefix() + "processNode: error stopping node " + node.getIp4(), e); | |||
} | |||
} | |||
} | |||
private boolean wouldKillSelf(BubbleNode node) { | |||
private boolean wouldKillSelf(@NonNull final BubbleNode node) { | |||
if (node.hasSameIp(configuration.getThisNode())) { | |||
log.debug("processNode: not killing configuration.thisNode: "+node.getIp4()+"/"+node.getIp6()); | |||
log.debug(prefix() + "wouldKillSelf: not killing configuration.thisNode: " | |||
+ node.getIp4() + "/" + node.getIp6()); | |||
return true; | |||
} | |||
final Set<String> localIps = NetworkUtil.configuredIps(); | |||
final var localIps = NetworkUtil.configuredIps(); | |||
if (localIps.contains(node.getIp4()) || localIps.contains(node.getIp6())) { | |||
log.debug("processNode: not killing self, IP matches one of: "+ StringUtil.toString(localIps)); | |||
log.debug(prefix() + "wouldKillSelf: not killing self, IP matches one of: " | |||
+ StringUtil.toString(localIps)); | |||
return true; | |||
} | |||
return false; | |||
} | |||
@@ -81,6 +81,8 @@ public class AnsiblePrepService { | |||
} | |||
ctx.put("sslPort", network.getSslPort()); | |||
ctx.put("publicBaseUri", network.getPublicUri()); | |||
ctx.put("support", configuration.getSupport()); | |||
ctx.put("appLinks", configuration.getAppLinks()); | |||
if (network.sendErrors() && configuration.hasErrorApi()) { | |||
final ErrorApiConfiguration errorApi = configuration.getErrorApi(); | |||
@@ -58,11 +58,11 @@ public class NodeProgressMeterConstants { | |||
{METER_TICK_VALIDATING_NODE_NETWORK_AND_PLAN, 1}, | |||
{METER_TICK_CREATING_NODE, 1}, | |||
{METER_TICK_LAUNCHING_NODE, 1}, | |||
{METER_TICK_PREPARING_ROLES, 2}, | |||
{METER_TICK_PREPARING_INSTALL, 4}, | |||
{METER_TICK_STARTING_INSTALL, 6}, | |||
{METER_TICK_COPYING_ANSIBLE, 7}, | |||
{METER_TICK_RUNNING_ANSIBLE, 15} | |||
{METER_TICK_PREPARING_ROLES, 5}, | |||
{METER_TICK_PREPARING_INSTALL, 7}, | |||
{METER_TICK_STARTING_INSTALL, 33}, | |||
{METER_TICK_COPYING_ANSIBLE, 34}, | |||
{METER_TICK_RUNNING_ANSIBLE, 37} | |||
}); | |||
public static List<NodeProgressMeterTick> getStandardTicks(NewNodeNotification nn) { | |||
@@ -74,7 +74,8 @@ import static bubble.service.boot.StandardSelfNodeService.*; | |||
import static bubble.service.cloud.NodeProgressMeter.getProgressMeterKey; | |||
import static bubble.service.cloud.NodeProgressMeter.getProgressMeterPrefix; | |||
import static bubble.service.cloud.NodeProgressMeterConstants.*; | |||
import static java.util.concurrent.TimeUnit.*; | |||
import static java.util.concurrent.TimeUnit.MINUTES; | |||
import static java.util.concurrent.TimeUnit.SECONDS; | |||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric; | |||
import static org.cobbzilla.util.daemon.Await.awaitAll; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
@@ -1 +1 @@ | |||
bubble.version=0.11.2 | |||
bubble.version=0.11.3 |
@@ -25,9 +25,19 @@ | |||
{"name": "restore_key", "value": "[[restoreKey]]"}, | |||
{"name": "restore_timeout", "value": "[[restoreTimeoutSeconds]]"}, | |||
{"name": "test_mode", "value": "[[testMode]]"}, | |||
{"name": "error_url", "value": "[[error_url]]"}, | |||
{"name": "error_key", "value": "[[error_key]]"}, | |||
{"name": "error_env", "value": "[[error_env]]"} | |||
{"name": "error_env", "value": "[[error_env]]"}, | |||
{"name": "support_email", "value": "[[support.email]]"}, | |||
{"name": "support_site", "value": "[[support.site]]"}, | |||
{"name": "app_link_ios", "value": "[[appLinks.ios]]"}, | |||
{"name": "app_link_android", "value": "[[appLinks.android]]"}, | |||
{"name": "app_link_windows", "value": "[[appLinks.windows]]"}, | |||
{"name": "app_link_macosx", "value": "[[appLinks.macosx]]"}, | |||
{"name": "app_link_linux", "value": "[[appLinks.linux]]"} | |||
], | |||
"optionalConfigNames": ["restore_key", "restore_timeout", "error_url", "error_key", "error_env"] | |||
} |
@@ -7,6 +7,16 @@ export LETSENCRYPT_EMAIL={{ letsencrypt_email }} | |||
export BUBBLE_SERVER_PORT={{ admin_port }} | |||
export BUBBLE_TEST_MODE={{ test_mode }} | |||
export BUBBLE_DEFAULT_LOCALE={{ default_locale }} | |||
export ERRBIT_URL={{ error_url | default('') }} | |||
export ERRBIT_KEY={{ error_key | default('') }} | |||
export ERRBIT_ENV={{ error_env | default('') }} | |||
export SUPPORT_EMAIL={{ support_email }} | |||
export SUPPORT_SITE={{ support_site }} | |||
export APP_LINK_IOS={{ app_link_ios }} | |||
export APP_LINK_ANDROID={{ app_link_android }} | |||
export APP_LINK_WINDOWS={{ app_link_windows }} | |||
export APP_LINK_MACOSX={{ app_link_macosx }} | |||
export APP_LINK_LINUX={{ app_link_linux }} |
@@ -1,24 +1,13 @@ | |||
[ | |||
{ "percent": 15,"messageKey":"apt_update", "match": "prefix", "pattern":"Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease" }, | |||
{ "percent": 16,"messageKey":"apt_upgrade", "match": "exact", "pattern":"Calculating upgrade..." }, | |||
{ "percent": 18,"messageKey":"lib_ssl", "match": "prefix", "pattern":"Setting up libssl1.1:amd64" }, | |||
{ "percent": 22,"messageKey":"apt_install_done","match":"exact", "pattern":"Installation finished. No error reported." }, | |||
{ "percent": 25,"messageKey":"pip_install", "match":"exact", "pattern":"python3 set to manually installed." }, | |||
{ "percent": 28,"messageKey":"pyyaml_pycparser","match":"exact", "pattern":"Successfully built ansible PyYAML pycparser" }, | |||
{ "percent": 29,"messageKey":"playbook_start", "pattern":"PLAY \\[[\\w\\s]+] \\*{5,}" }, | |||
{ "percent": 30,"messageKey":"role_common", "pattern":"TASK \\[common : [\\w\\s]+] \\*{5,}" }, | |||
{ "percent": 35,"messageKey":"role_common_packages", "pattern":"TASK \\[common : Install common packages] \\*{5,}" }, | |||
{ "percent": 38,"messageKey":"role_firewall", "pattern":"TASK \\[firewall : [\\w\\s]+] \\*{5,}" }, | |||
{ "percent": 40,"messageKey":"role_bubble", "pattern":"TASK \\[bubble : [\\w\\s]+] \\*{5,}" }, | |||
{ "percent": 44,"messageKey":"role_bubble_jar", "pattern":"TASK \\[bubble : Install bubble jar] \\*{5,}" }, | |||
{ "percent": 48,"messageKey":"role_bubble_db", "pattern":"TASK \\[bubble : Populate database] \\*{5,}" }, | |||
{ "percent": 51,"messageKey":"role_bubble_restore", "pattern":"TASK \\[bubble : Install restore helper scripts] \\*{5,}" }, | |||
{ "percent": 52,"messageKey":"role_bubble_algo", "pattern":"TASK \\[algo : [\\w\\s]+] \\*{5,}" }, | |||
{ "percent": 76,"messageKey":"role_nginx", "pattern":"TASK \\[nginx : [\\w\\s]+] \\*{5,}" }, | |||
{ "percent": 81,"messageKey":"role_nginx_certbot", "pattern":"TASK \\[nginx : Init certbot] \\*{5,}" }, | |||
{ "percent": 91,"messageKey":"role_mitmproxy", "pattern":"TASK \\[mitmproxy : [\\w\\s]+] \\*{5,}" }, | |||
{ "percent": 94,"messageKey":"role_finalizer", "pattern":"TASK \\[finalizer : [\\w\\s]+] \\*{5,}" }, | |||
{ "percent": 98,"messageKey":"role_finalizer_touch", "pattern":"TASK \\[finalizer : Touch first-time setup file] \\*{5,}" }, | |||
{ "percent": 99,"messageKey":"role_finalizer_start", "pattern":"TASK \\[finalizer : Ensure bubble is started] \\*{5,}" }, | |||
{"percent": 100,"messageKey":"install_complete", "pattern":"PLAY RECAP \\*{5,}" } | |||
{ "percent": 38,"messageKey":"ansible_deps", "match": "prefix", "pattern":"Building wheel for PyYAML (setup.py): started" }, | |||
{ "percent": 41,"messageKey":"config_node", "match": "prefix", "pattern":"PLAY [Configure new bubble node]" }, | |||
{ "percent": 42,"messageKey":"nginx_dhparam", "match": "prefix", "pattern":"TASK [nginx : Create a strong dhparam.pem]" }, | |||
{ "percent": 55,"messageKey":"nginx_dh_conf", "match": "prefix", "pattern":"TASK [Create dhparam nginx conf]" }, | |||
{ "percent": 56,"messageKey":"nginx_certbot", "match": "prefix", "pattern":"TASK [nginx : Init certbot]" }, | |||
{ "percent": 58,"messageKey":"bubble_db", "match": "prefix", "pattern":"TASK [bubble : Populate database]" }, | |||
{ "percent": 65,"messageKey":"algo_sh", "match": "prefix", "pattern":"TASK [Write install_algo.sh template]" }, | |||
{ "percent": 92,"messageKey":"restart_algo", "match": "prefix", "pattern":"TASK [Restart algo monitors]" }, | |||
{ "percent": 95,"messageKey":"snapshot_ansible", "match": "prefix", "pattern":"TASK [finalizer : Snapshot ansible roles]" }, | |||
{ "percent": 98,"messageKey":"touch_first_setup","match": "prefix", "pattern":"TASK [finalizer : Touch first-time setup file]" }, | |||
{ "percent": 99,"messageKey":"ssh_keys", "match": "prefix", "pattern":"TASK [finalizer : Ensure authorized SSH keys are up-to-date]" } | |||
] |
@@ -333,39 +333,48 @@ footprint_name_Worldwide=World-wide | |||
footprint_description_Worldwide=Your Bubble can run anywhere in the world | |||
# Launch progress meter: pre-launch (standard) ticks | |||
meter_tick_confirming_network_lock=Confirming network lock | |||
meter_tick_validating_node_network_and_plan=Verifying settings for Bubble | |||
meter_tick_creating_node=Creating Bubble node | |||
meter_tick_launching_node=Launching Bubble node | |||
meter_tick_preparing_roles=Preparing installation parameters | |||
meter_tick_preparing_install=Creating installation package | |||
meter_tick_starting_install=Connecting to node to install Bubble | |||
meter_tick_copying_ansible=Copying files required to install Bubble | |||
meter_tick_running_ansible=Starting Bubble installation | |||
meter_tick_confirming_network_lock=Thinking about baking a pie | |||
meter_tick_validating_node_network_and_plan=Grabbing the cookbook... | |||
meter_tick_creating_node=Finding the best pie recipe ever... | |||
meter_tick_launching_node=Assembling pie ingredients... | |||
meter_tick_preparing_roles=Pre-heating the oven... | |||
meter_tick_preparing_install=Peeling the apples... | |||
meter_tick_starting_install=Slicing the apples... | |||
meter_tick_copying_ansible=Rolling out the pie dough... | |||
meter_tick_running_ansible=Whipping the batter... | |||
#meter_tick_confirming_network_lock=Confirming network lock | |||
#meter_tick_validating_node_network_and_plan=Verifying settings for Bubble | |||
#meter_tick_creating_node=Creating Bubble node | |||
#meter_tick_launching_node=Launching Bubble node | |||
#meter_tick_preparing_roles=Preparing installation parameters | |||
#meter_tick_preparing_install=Creating installation package | |||
#meter_tick_starting_install=Connecting to node to install Bubble | |||
#meter_tick_copying_ansible=Copying files required to install Bubble | |||
#meter_tick_running_ansible=Starting Bubble installation | |||
# Launch progress meter: install ticks | |||
meter_tick_apt_update=Updating system packages | |||
meter_tick_apt_upgrade=Upgrading system packages | |||
meter_tick_lib_ssl=Installing SSL libraries | |||
meter_tick_apt_install_done=Installing system packages | |||
meter_tick_pip_install=Installing python packages | |||
meter_tick_pyyaml_pycparser=Continuing to install python packages | |||
meter_tick_playbook_start=Running configuration playbook | |||
meter_tick_role_common=Installing core system packages | |||
meter_tick_role_common_packages=Installing Bubble packages | |||
meter_tick_role_firewall=Setting up firewall | |||
meter_tick_role_bubble=Installing Bubble API | |||
meter_tick_role_bubble_jar=Installing Bubble JAR | |||
meter_tick_role_bubble_db=Setting up Bubble database | |||
meter_tick_role_bubble_restore=Setting up Bubble backup/restore services | |||
meter_tick_role_bubble_algo=Setting up VPN | |||
meter_tick_role_nginx=Setting up web server | |||
meter_tick_role_nginx_certbot=Installing SSL certificates | |||
meter_tick_role_mitmproxy=Setting up MITM server | |||
meter_tick_role_finalizer=Finalizing Bubble installation | |||
meter_tick_role_finalizer_touch=Turning on "first-time" setting to allow you to unlock your Bubble | |||
meter_tick_role_finalizer_start=Starting Bubble API services | |||
meter_tick_install_complete=Bubble installation completed | |||
meter_tick_ansible_deps=Mixing the pie filling... | |||
meter_tick_config_node=Filling the pie... | |||
meter_tick_nginx_dhparam=Gently adding the lattice top crust... | |||
meter_tick_nginx_dh_conf=Glazing the top crust... | |||
meter_tick_nginx_certbot=Checking the temperature... | |||
meter_tick_bubble_db=Putting pie into the oven... | |||
meter_tick_algo_sh=Baking the pie... | |||
meter_tick_restart_algo=Removing pie from the oven... | |||
meter_tick_snapshot_ansible=Letting the pie cool a bit... | |||
meter_tick_touch_first_setup=Setting the table... | |||
meter_tick_ssh_keys=Get everybody, the pie is ready! | |||
#meter_tick_ansible_deps=Installing installer dependencies | |||
#meter_tick_config_node=Configuration installation | |||
#meter_tick_nginx_dhparam=Securing SSL libraries | |||
#meter_tick_nginx_dh_conf=Setting up web server | |||
#meter_tick_nginx_certbot=Installing SSL certificate | |||
#meter_tick_bubble_db=Writing bubble database | |||
#meter_tick_algo_sh=Setting up VPN | |||
#meter_tick_restart_algo=Setting up device subsystem | |||
#meter_tick_snapshot_ansible=Snapshotting installation | |||
#meter_tick_touch_first_setup=Finalizing installation | |||
#meter_tick_ssh_keys=Setting up SSH keys | |||
# Launch progress meter: success marker | |||
meter_completed=Bubble installation completed successfully! On to your Bubble! | |||
@@ -390,13 +399,10 @@ meter_unknown_error=An unknown error occurred | |||
# Help text shown during launch | |||
title_launch_help_html=Next Steps | |||
message_launch_help_html=<p>Your Bubble will take about 10 minutes to launch and configure itself.</p>\ | |||
<p>If you run into any trouble setting up your Bubble, please contact <a href="mailto:support@getbubblenow.com">support@getbubblenow.com</a></p> | |||
message_launch_help_html=<p>Your Bubble will take about 10 minutes to launch and configure itself.</p> | |||
message_launch_help_apps=While you wait for your Bubble to be ready, please install the Bubble app on each of your devices. | |||
message_launch_success_help_html=<p>Congratulations! Your Bubble is now running.</p>\ | |||
<p>If you run into any trouble setting up your Bubble, please contact <a href="mailto:support@getbubblenow.com">support@getbubblenow.com</a></p> | |||
message_launch_success_help_html=<p>Congratulations! Your Bubble is now running.</p> | |||
message_launch_support=<p>Having trouble? Any questions? Check our our <a target="_blank" rel="noopener noreferrer" href="/support">{{messages.link_support}}</a> resources.</p> | |||
message_launch_success_apps=Install the Bubble app on each of your devices and get connected to your Bubble! | |||
@@ -18,6 +18,7 @@ support_preamble=To get help with Bubble: | |||
support_site_link=Visit our Support Website | |||
support_email_link=Send us an email | |||
support_not_available=Sorry, no support options are available | |||
link_support=Support | |||
# Legal page links | |||
title_legal_topics=Legal Stuff | |||
@@ -1 +1 @@ | |||
Subproject commit e18e5b9b9757f0c542ffb62a40b90c2e5e95aa4e | |||
Subproject commit e22459cf88f255a9eb577b4b3e9576a1a5474a03 |