diff --git a/data/update_script.sh.erb b/data/update_script.sh.erb index df208b6..6e84be0 100644 --- a/data/update_script.sh.erb +++ b/data/update_script.sh.erb @@ -67,10 +67,16 @@ set +o allexport cd / -sudo rm -rf "$APP_PATH" -sudo mkdir -p "$APP_PATH" -sudo chown -R ec2-user.ec2-user "$APP_PATH" -tar xzf "$1" -C "$APP_PATH" +# atomically replacing the app files +if file "$APP_PATH" | grep 'directory'; then + sudo rm -rf "$APP_PATH" +fi +sudo mkdir -p "${APP_PATH}_symlink_new" && sudo chown -R ec2-user.ec2-user "${APP_PATH}_symlink_new" && tar xzf "$1" -C "${APP_PATH}_symlink_new" +sudo ln -s "${APP_PATH}_symlink_new" "${APP_PATH}" +sudo rm -rf "${APP_PATH}_symlink_old" || true +sudo mv "${APP_PATH}_symlink_new" "${APP_PATH}_symlink_old" +sudo ln -vfns "${APP_PATH}_symlink_old" "${APP_PATH}" +sudo chown -R ec2-user.ec2-user "${APP_PATH}_symlink_old" cd "$APP_PATH" @@ -95,10 +101,13 @@ for i in {1..5}; do if pull; then break ; fi done -docker-compose up \ - --wait \ - --remove-orphans \ - -d <%= locals.compose_options.join(" ") %> +if [ "$PULLPREVIEW_FIRST_RUN" = false ]; then + echo "Stopping the application..." + docker-compose stop +fi + +echo "Starting up the application..." +docker-compose up --wait --remove-orphans -d <%= locals.compose_options.join(" ") %> sleep 5 diff --git a/lib/pull_preview/down.rb b/lib/pull_preview/down.rb index 36464dd..aea8b14 100644 --- a/lib/pull_preview/down.rb +++ b/lib/pull_preview/down.rb @@ -1,7 +1,14 @@ module PullPreview class Down def self.run(opts) - instance = Instance.new(opts[:name]) + instance = Instance.new(opts[:name], opts) + + # Call the launch so we can get the instance attributes (ip, dns etc) + instance.launch_and_wait_until_ready! + + PullPreview.logger.info "Deleting the subdomain to DNS Zone" + instance.delete_domain_entry + PullPreview.logger.info "Destroying instance name=#{instance.name}" instance.terminate! end diff --git a/lib/pull_preview/github_sync.rb b/lib/pull_preview/github_sync.rb index d4837db..046821f 100644 --- a/lib/pull_preview/github_sync.rb +++ b/lib/pull_preview/github_sync.rb @@ -145,9 +145,10 @@ def sync! when :pr_down, :branch_down instance = Instance.new(instance_name) update_github_status(:destroying) - + tags = default_instance_tags.push(*opts[:tags]).uniq if instance.running? - Down.run(name: instance_name) + Down.run(opts.merge(name: instance_name, subdomain: instance_subdomain, tags: tags)) + else PullPreview.logger.warn "Instance #{instance_name.inspect} already down. Continuing..." end diff --git a/lib/pull_preview/instance.rb b/lib/pull_preview/instance.rb index d46a575..f54f425 100644 --- a/lib/pull_preview/instance.rb +++ b/lib/pull_preview/instance.rb @@ -57,6 +57,16 @@ def launch_and_wait_until_ready! wait_until_ssh_ready! end + def create_domain_entry + logger.info "Adding a domain entry public_dns=#{public_dns} and target #{public_ip} in DNS Zone" + provider.create_domain_entry(dns, public_dns, public_ip) + end + + def delete_domain_entry + logger.info "Deleting a domain entry public_dns=#{public_dns} and target #{public_ip} in DNS Zone" + provider.delete_domain_entry(dns, public_dns, public_ip) + end + def terminate! if provider.terminate!(name) logger.info "Instance successfully destroyed" @@ -89,7 +99,7 @@ def public_dns def url scheme = (default_port == "443" ? "https" : "http") - "#{scheme}://#{public_dns}:#{default_port}" + "#{scheme}://#{public_dns}" end def username @@ -208,7 +218,7 @@ def ssh(command, input: nil) end end [key_file_path].each{|file| FileUtils.chmod 0600, file} - + cmd = "ssh #{"-v " if logger.level == Logger::DEBUG}-o ServerAliveInterval=15 -o IdentitiesOnly=yes -i #{key_file_path} #{ssh_address} #{ssh_options.join(" ")} '#{command}'" if input && input.respond_to?(:path) cmd = "cat #{input.path} | #{cmd}" diff --git a/lib/pull_preview/providers/lightsail.rb b/lib/pull_preview/providers/lightsail.rb index fc39d97..c0746fe 100644 --- a/lib/pull_preview/providers/lightsail.rb +++ b/lib/pull_preview/providers/lightsail.rb @@ -28,6 +28,44 @@ def running?(name) false end + def create_domain_entry(dns, public_dns, public_ip) + domain_entry = { + name: public_dns, + target: public_ip, + type: "A" + } + + begin + resp = client.create_domain_entry(domain_name: dns, domain_entry: domain_entry) + resp.operation.status == "Succeeded" + rescue Aws::Lightsail::Errors::NotFoundException + false + rescue Aws::Lightsail::Errors::InvalidInputException + false + rescue StandardError + false + end + end + + def delete_domain_entry(dns, public_dns, public_ip) + domain_entry = { + name: public_dns, + target: public_ip, + type: "A" + } + + begin + resp = client.delete_domain_entry(domain_name: dns, domain_entry: domain_entry) + resp.operation.status == "Succeeded" + rescue Aws::Lightsail::Errors::NotFoundException + false + rescue Aws::Lightsail::Errors::InvalidInputException + false + rescue StandardError + false + end + end + def terminate!(name) operation = client.delete_instance(instance_name: name).operations.first if operation.error_code.nil? @@ -120,7 +158,7 @@ def latest_snapshot(name) def list_instances(tags: {}) next_page_token = nil begin - result = client.get_instances(next_page_token: next_page_token) + result = client.get_instances(next_page_token: next_page_token) next_page_token = result.next_page_token result.instances.each do |instance| matching_tags = Hash[instance.tags.select{|tag| tags.keys.include?(tag.key)}.map{|tag| [tag.key, tag.value]}] @@ -180,4 +218,4 @@ def bundle_id(size = "M") end end end -end \ No newline at end of file +end diff --git a/lib/pull_preview/up.rb b/lib/pull_preview/up.rb index fddfb52..97cfb00 100644 --- a/lib/pull_preview/up.rb +++ b/lib/pull_preview/up.rb @@ -31,6 +31,9 @@ def self.run(app_path, opts) PullPreview.logger.info "Starting instance name=#{instance.name}" instance.launch_and_wait_until_ready! + PullPreview.logger.info "Setting up the domain entry to DNS Zone" + instance.create_domain_entry + PullPreview.logger.info "Synchronizing instance name=#{instance.name}" instance.setup_ssh_access instance.setup_update_script