From fc1e5260603ff0f6030c4aed7874c8ea3b532e5c Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Thu, 3 May 2018 21:44:06 +0100 Subject: Improve the AWS backend This gets the AWS backend to the point where you can deploy the backend, and then a mini environment without any actions outside of the govuk-mini-environment-admin. --- app/jobs/govuk_guix/build_job.rb | 26 ++++++++++-- app/jobs/govuk_guix/job.rb | 8 ++-- app/models/backends/terraform_aws.rb | 72 ++++++++++++++++++++++++++++---- app/models/backends/terraform_libvirt.rb | 24 ++++++----- 4 files changed, 103 insertions(+), 27 deletions(-) (limited to 'app') diff --git a/app/jobs/govuk_guix/build_job.rb b/app/jobs/govuk_guix/build_job.rb index a74b928..fb5e256 100644 --- a/app/jobs/govuk_guix/build_job.rb +++ b/app/jobs/govuk_guix/build_job.rb @@ -27,22 +27,40 @@ class GovukGuix::BuildJob < GovukGuix::Job @retry_interval = 30 - def run(mini_environment_id, services, arguments) + def run(mini_environment_id, options) logger.info(self.class) do "Building mini environment #{mini_environment_id}" end mini_environment = MiniEnvironment.find(mini_environment_id) + remote_host = options[:run_remotely_on_host] + + if remote_host + ssh_command = ['ssh', remote_host] + + # Copy the revision to the remote host, to ensure it's available + # there + run_command( + 'guix', + 'copy', + "--to=#{remote_host}", + mini_environment.govuk_guix_revision.store_path + ) + else + ssh_command = [] + end + output = run_command( + *ssh_command, "#{mini_environment.govuk_guix_revision.store_path}/bin/govuk", 'system', 'build', *hash_to_arguments( - DEFAULT_ARGUMENTS.merge(arguments) + DEFAULT_ARGUMENTS.merge(options[:arguments]) ), *signon_user_arguments(mini_environment.signon_users), - *services + *options[:services] ) build_output = output.last.strip @@ -69,7 +87,7 @@ class GovukGuix::BuildJob < GovukGuix::Job def signon_user_arguments(signon_users) signon_users.map do |signon_user| - "--signon-user=#{signon_user_to_sexp(signon_user)}" + "--signon-user='#{signon_user_to_sexp(signon_user)}'" end end diff --git a/app/jobs/govuk_guix/job.rb b/app/jobs/govuk_guix/job.rb index c20b9de..b79d380 100644 --- a/app/jobs/govuk_guix/job.rb +++ b/app/jobs/govuk_guix/job.rb @@ -46,12 +46,14 @@ class GovukGuix::Job < Que::Job def hash_to_arguments(hash) hash.map do |(key, value)| - transfomed_key = key.tr('_', '-') + transformed_key = key.tr('_', '-') if value == true - "--#{transfomed_key}" + "--#{transformed_key}" + elsif value.include? ' ' + "--#{transformed_key}='#{value}'" else - "--#{transfomed_key}=#{value}" + "--#{transformed_key}=#{value}" end end end diff --git a/app/models/backends/terraform_aws.rb b/app/models/backends/terraform_aws.rb index d45dfc7..c50e2de 100644 --- a/app/models/backends/terraform_aws.rb +++ b/app/models/backends/terraform_aws.rb @@ -55,11 +55,19 @@ class Backends::TerraformAws < ApplicationRecord GovukGuix::BuildJob.enqueue( mini_environment.id, - %w(whitehall government-frontend), - type: 'container-start-script', - app_domain: "#{slug}.#{domain}", - web_domain: "www.#{slug}.#{domain}", - use_https: 'certbot' + services: %w(whitehall government-frontend), + arguments: { + type: 'container-start-script', + app_domain: "#{slug}.#{domain}", + web_domain: "www.#{slug}.#{domain}", + use_https: 'certbot', + http_ports_mode: 'alternative', + read_bundle_install_input_as_tar_archive: true, + signon_instance_name: slug, + admin_environment_label: mini_environment.name, + read_bundle_install_input_as_tar_archive: 'true' + }, + run_remotely_on_host: "ubuntu@guix-daemon.#{domain}" ) end @@ -83,10 +91,33 @@ class Backends::TerraformAws < ApplicationRecord end end + def deploy_backend + public_ip_address = ENV[ + 'GOVUK_MINI_ENVIRONMENT_ADMIN_PUBLIC_IP_ADDRESS' + ] + + raise 'missing public ip address' if public_ip_address.nil? + + TerraformWorkingDirectory.new( + terraform_state_id, + 'terraform/aws/backend' + ).within_working_directory do + RubyTerraform.apply( + vars: common_terraform_variables.merge( + aws_vpc_id: vpc_id, + ssh_public_key: ssh_public_key, + mini_environment_admin_guix_public_key: guix_public_key, + mini_environment_admin_public_ip_address: public_ip_address + ), + auto_approve: true + ) + end + end + def within_terraform_working_directory(mini_environment, &block) TerraformWorkingDirectory.new( "mini_environment/#{mini_environment.id}", - 'terraform/aws' + 'terraform/aws/mini_environment' ).within_working_directory(&block) end @@ -94,18 +125,41 @@ class Backends::TerraformAws < ApplicationRecord "https://signon.#{mini_environment.name.parameterize}.#{domain}" end - def terraform_variables(mini_environment) + def common_terraform_variables { aws_access_key: aws_access_key_id, aws_secret_key: aws_secret_access_key, aws_region: aws_region, - slug: mini_environment.name.parameterize, ssh_public_key: ssh_public_key, - start_command: mini_environment.backend_data['build_output'] + aws_route_53_zone_id: route_53_zone_id, + aws_efs_file_system_id: efs_file_system_id } end + def terraform_variables(mini_environment) + common_terraform_variables.merge( + slug: mini_environment.name.parameterize, + start_command: mini_environment.backend_data['build_output'], + backend_remote_state_address: ( + 'http://localhost:3000' + + Rails + .application + .routes + .url_helpers + .terraform_http_backend_path(terraform_state_id) + ) + ) + end + + def terraform_state_id + "backend/terraform_aws/#{id}" + end + def ssh_public_key File.open("#{ENV['HOME']}/.ssh/id_rsa.pub", &:readline) end + + def guix_public_key + "(entry #{File.read("/etc/guix/signing-key.pub")} (tag (guix import)))" + end end diff --git a/app/models/backends/terraform_libvirt.rb b/app/models/backends/terraform_libvirt.rb index b069b70..de29bed 100644 --- a/app/models/backends/terraform_libvirt.rb +++ b/app/models/backends/terraform_libvirt.rb @@ -50,17 +50,19 @@ class Backends::TerraformLibvirt < ApplicationRecord GovukGuix::BuildJob.enqueue( mini_environment.id, - %w(whitehall government-frontend), - type: 'vm-image-and-system', - app_domain: "#{slug}.#{domain}", - web_domain: "www.#{slug}.#{domain}", - # Assume that this is a local environment, and not externally - # accessible - use_https: 'development', - http_ports_mode: 'standard', - host_name: "#{slug}.#{domain}", - admin_environment_label: mini_environment.name, - signon_instance_name: slug + services: %w(whitehall government-frontend), + arguments: { + type: 'vm-image-and-system', + app_domain: "#{slug}.#{domain}", + web_domain: "www.#{slug}.#{domain}", + # Assume that this is a local environment, and not externally + # accessible + use_https: 'development', + http_ports_mode: 'standard', + host_name: "#{slug}.#{domain}", + admin_environment_label: mini_environment.name, + signon_instance_name: slug + } ) end -- cgit v1.2.3