diff --git a/bin/prep_bubble_jar b/bin/prep_bubble_jar index c5a0c611..1cd99555 100755 --- a/bin/prep_bubble_jar +++ b/bin/prep_bubble_jar @@ -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/" diff --git a/bubble-server/src/main/java/bubble/cloud/compute/NodeReaper.java b/bubble-server/src/main/java/bubble/cloud/compute/NodeReaper.java index aca546bc..057104ed 100644 --- a/bubble-server/src/main/java/bubble/cloud/compute/NodeReaper.java +++ b/bubble-server/src/main/java/bubble/cloud/compute/NodeReaper.java @@ -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 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; } diff --git a/bubble-server/src/main/java/bubble/service/cloud/AnsiblePrepService.java b/bubble-server/src/main/java/bubble/service/cloud/AnsiblePrepService.java index a3f6fb68..d1806f94 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/AnsiblePrepService.java +++ b/bubble-server/src/main/java/bubble/service/cloud/AnsiblePrepService.java @@ -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(); diff --git a/bubble-server/src/main/java/bubble/service/cloud/NodeProgressMeterConstants.java b/bubble-server/src/main/java/bubble/service/cloud/NodeProgressMeterConstants.java index 7892d393..befc83e3 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/NodeProgressMeterConstants.java +++ b/bubble-server/src/main/java/bubble/service/cloud/NodeProgressMeterConstants.java @@ -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 getStandardTicks(NewNodeNotification nn) { diff --git a/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java b/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java index 73f98638..21ad7286 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java +++ b/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java @@ -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.*; diff --git a/bubble-server/src/main/resources/META-INF/bubble/bubble.properties b/bubble-server/src/main/resources/META-INF/bubble/bubble.properties index d1685e3b..0c69ea9f 100644 --- a/bubble-server/src/main/resources/META-INF/bubble/bubble.properties +++ b/bubble-server/src/main/resources/META-INF/bubble/bubble.properties @@ -1 +1 @@ -bubble.version=0.11.2 +bubble.version=0.11.3 diff --git a/bubble-server/src/main/resources/ansible/roles/bubble/files/bubble_role.json b/bubble-server/src/main/resources/ansible/roles/bubble/files/bubble_role.json index 5b603a86..e6eeaaba 100644 --- a/bubble-server/src/main/resources/ansible/roles/bubble/files/bubble_role.json +++ b/bubble-server/src/main/resources/ansible/roles/bubble/files/bubble_role.json @@ -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"] } \ No newline at end of file diff --git a/bubble-server/src/main/resources/ansible/roles/bubble/templates/bubble.env.j2 b/bubble-server/src/main/resources/ansible/roles/bubble/templates/bubble.env.j2 index 19c47f68..c20748ca 100644 --- a/bubble-server/src/main/resources/ansible/roles/bubble/templates/bubble.env.j2 +++ b/bubble-server/src/main/resources/ansible/roles/bubble/templates/bubble.env.j2 @@ -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 }} diff --git a/bubble-server/src/main/resources/bubble/node_progress_meter_ticks.json b/bubble-server/src/main/resources/bubble/node_progress_meter_ticks.json index cce08462..d7e4e03e 100644 --- a/bubble-server/src/main/resources/bubble/node_progress_meter_ticks.json +++ b/bubble-server/src/main/resources/bubble/node_progress_meter_ticks.json @@ -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]" } ] diff --git a/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties b/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties index 10286316..ccef420d 100644 --- a/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties +++ b/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties @@ -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=

Your Bubble will take about 10 minutes to launch and configure itself.

\ -

If you run into any trouble setting up your Bubble, please contact support@getbubblenow.com

- +message_launch_help_html=

Your Bubble will take about 10 minutes to launch and configure itself.

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=

Congratulations! Your Bubble is now running.

\ -

If you run into any trouble setting up your Bubble, please contact support@getbubblenow.com

+message_launch_success_help_html=

Congratulations! Your Bubble is now running.

+message_launch_support=

Having trouble? Any questions? Check our our {{messages.link_support}} resources.

message_launch_success_apps=Install the Bubble app on each of your devices and get connected to your Bubble! diff --git a/bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties b/bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties index d5a8d048..ba51e064 100644 --- a/bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties +++ b/bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties @@ -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 diff --git a/bubble-web b/bubble-web index e18e5b9b..e22459cf 160000 --- a/bubble-web +++ b/bubble-web @@ -1 +1 @@ -Subproject commit e18e5b9b9757f0c542ffb62a40b90c2e5e95aa4e +Subproject commit e22459cf88f255a9eb577b4b3e9576a1a5474a03