diff options
author | Christopher Baines <mail@cbaines.net> | 2018-03-27 23:04:41 +0100 |
---|---|---|
committer | Christopher Baines <mail@cbaines.net> | 2018-04-03 21:58:55 +0100 |
commit | 94f9e2a768327479c8b2da99cd57ac717cf1589a (patch) | |
tree | 819c093f8fb7c37c6017ede36db4f01854a8bcc8 | |
parent | fa06e98228d8dd80a46622c9f393bb90e680d254 (diff) | |
download | govuk-mini-environment-admin-94f9e2a768327479c8b2da99cd57ac717cf1589a.tar govuk-mini-environment-admin-94f9e2a768327479c8b2da99cd57ac717cf1589a.tar.gz |
Add domains to backends, and rework build jobs
Add a domain to the libvirt and AWS Terraform backends. Along the way,
improve the backend controllers and views, and rework the build jobs,
simplifying them in to a single new class GovukGuix::BuildJob, which
uses configuration from the respective backend.
-rw-r--r-- | app/controllers/backends/terraform_aws_controller.rb | 34 | ||||
-rw-r--r-- | app/controllers/backends/terraform_libvirt_controller.rb | 47 | ||||
-rw-r--r-- | app/jobs/govuk_guix/build_job.rb | 55 | ||||
-rw-r--r-- | app/jobs/govuk_guix/generate_start_command_job.rb | 36 | ||||
-rw-r--r-- | app/jobs/govuk_guix/generate_vm_image_and_system_job.rb | 39 | ||||
-rw-r--r-- | app/jobs/govuk_guix/job.rb | 22 | ||||
-rw-r--r-- | app/models/backends/terraform_aws.rb | 22 | ||||
-rw-r--r-- | app/models/backends/terraform_libvirt.rb | 25 | ||||
-rw-r--r-- | app/views/backends/terraform_aws/new.html.erb | 24 | ||||
-rw-r--r-- | app/views/backends/terraform_aws/show.html.erb | 25 | ||||
-rw-r--r-- | app/views/backends/terraform_libvirt/new.html.erb | 10 | ||||
-rw-r--r-- | app/views/backends/terraform_libvirt/show.html.erb | 13 | ||||
-rw-r--r-- | app/views/mini_environments/show.html.erb | 2 | ||||
-rw-r--r-- | db/migrate/20180327204244_add_domain_to_terraform_libvirt_backends.rb | 5 | ||||
-rw-r--r-- | db/migrate/20180327204322_add_domain_to_terraform_aws_backends.rb | 5 | ||||
-rw-r--r-- | db/schema.rb | 4 |
16 files changed, 252 insertions, 116 deletions
diff --git a/app/controllers/backends/terraform_aws_controller.rb b/app/controllers/backends/terraform_aws_controller.rb index 72c7e3a..5669eb1 100644 --- a/app/controllers/backends/terraform_aws_controller.rb +++ b/app/controllers/backends/terraform_aws_controller.rb @@ -4,17 +4,22 @@ class Backends::TerraformAwsController < ApplicationController end def create - backend = Backends::TerraformAws.create(backend_params) + backend = Backends::TerraformAws.create(create_params) - flash[:success] = "#{backend.label} created" + flash[:success] = "Backend #{backend.label} created" - redirect_to setup_path + redirect_to terraform_aws_backend_path(backend) end def update - backend = Backends::TerraformAws.update(params[:id], backend_params) + @backend = Backends::TerraformAws.update( + params[:id], + update_params + ) + + flash[:success] = "Backend #{@backend.label} updated" - flash[:success] = "#{backend.label} updated" + render :show end def show @@ -24,18 +29,33 @@ class Backends::TerraformAwsController < ApplicationController def destroy backend = Backends::TerraformAws.find(params[:id]) + flash[:success] = "Backend #{backend.label} deleted" backend.delete + + redirect_to setup_path end private - def backend_params + def create_params params + .require(:backends_terraform_aws) .permit( :label, + :domain, :aws_region, :aws_access_key_id, - :aws_secret_access_key, + :aws_secret_access_key + ) + end + + def update_params + params + .require(:backends_terraform_aws) + .permit( + :label, + :aws_access_key_id, + :aws_secret_access_key ) end end diff --git a/app/controllers/backends/terraform_libvirt_controller.rb b/app/controllers/backends/terraform_libvirt_controller.rb index f854bc2..6dcba17 100644 --- a/app/controllers/backends/terraform_libvirt_controller.rb +++ b/app/controllers/backends/terraform_libvirt_controller.rb @@ -1,30 +1,26 @@ class Backends::TerraformLibvirtController < ApplicationController def new @backend = Backends::TerraformLibvirt.new - @backend.uri = "qemu:///system" + @backend.uri = 'qemu:///system' end def create - backend = Backends::TerraformLibvirt.create( - params - .require(:backends_terraform_libvirt) - .permit(:label, :uri) - ) + backend = Backends::TerraformLibvirt.create(create_params) - flash[:success] = "#{backend.label} created" + flash[:success] = "Backend #{backend.label} created" - redirect_to setup_path + redirect_to terraform_libvirt_backend_path(backend) end def update - backend = Backends::TerraformLibvirt.update( - params[:id], - params - .require(:backends_terraform_libvirt) - .permit(:label, :uri) + @backend = Backends::TerraformLibvirt.update( + params['id'], + update_params ) - flash[:success] = "#{backend.label} updated" + flash[:success] = "Backend #{@backend.label} updated" + + render :show end def show @@ -34,6 +30,29 @@ class Backends::TerraformLibvirtController < ApplicationController def destroy backend = Backends::TerraformLibvirt.find(params['id']) + flash[:success] = "Backend #{backend.label} deleted" backend.delete + + redirect_to setup_path + end + + private + + def create_params + params + .require(:backends_terraform_libvirt) + .permit( + :label, + :domain, + :uri + ) + end + + def update_params + params + .require(:backends_terraform_libvirt) + .permit( + :label + ) end end diff --git a/app/jobs/govuk_guix/build_job.rb b/app/jobs/govuk_guix/build_job.rb new file mode 100644 index 0000000..d09fc68 --- /dev/null +++ b/app/jobs/govuk_guix/build_job.rb @@ -0,0 +1,55 @@ +class GovukGuix::BuildJob < GovukGuix::Job + DEFAULT_ARGUMENTS = { + 'rails-environment' => 'production', + 'use-high-ports' => 'false', + 'fallback' => true + }.freeze + + @retry_interval = 30 + + def run(mini_environment_id, services, arguments) + logger.info(self.class) do + "Building mini environment #{mini_environment_id}" + end + + mini_environment = MiniEnvironment.find(mini_environment_id) + + output = run_command( + "#{mini_environment.govuk_guix_revision.store_path}/bin/govuk", + 'system', + 'build', + *hash_to_arguments( + DEFAULT_ARGUMENTS.merge(arguments) + ), + *signon_user_arguments(mini_environment.signon_users), + *services + ) + + build_output = output.last.strip + logger.debug(self.class) { "build_output: #{build_output}" } + + mini_environment.update( + backend_data: { + build_output: build_output + } + ) + end + + def signon_user_to_sexp(signon_user) + keys = %w(name email role) + + sexp_contents = keys.zip( + signon_user.values_at(*keys) + ).map do |(key, value)| + "#:#{key} \"#{value}\"" + end + + "(#{sexp_contents.join(' ')})" + end + + def signon_user_arguments(signon_users) + signon_users.map do |signon_user| + "--signon-user=#{signon_user_to_sexp(signon_user)}" + end + end +end diff --git a/app/jobs/govuk_guix/generate_start_command_job.rb b/app/jobs/govuk_guix/generate_start_command_job.rb deleted file mode 100644 index 9820dcc..0000000 --- a/app/jobs/govuk_guix/generate_start_command_job.rb +++ /dev/null @@ -1,36 +0,0 @@ -class GovukGuix::GenerateStartCommandJob < GovukGuix::Job - @retry_interval = 30 - - def run(mini_environment_id) - logger.info "#{self.class}: Building mini environment #{mini_environment_id}" - - mini_environment = MiniEnvironment.find(mini_environment_id) - - slug = mini_environment.name.parameterize - - command = [ - "#{mini_environment.govuk_guix_revision.store_path}/bin/govuk", - 'system', - 'build', - '--rails-environment=production', - "--app-domain=#{slug}.aws.cbaines.net", - "--web-domain=www.#{slug}.aws.cbaines.net", - '--use-high-ports=false', - '--use-https=certbot', - '--fallback', - 'whitehall', - 'government-frontend' - ] - - run_command(command) do |output| - store_path = output.last.strip - logger.debug("#{self.class}: start_command: #{store_path}") - - mini_environment.update( - backend_data: { - start_command: store_path - } - ) - end - end -end diff --git a/app/jobs/govuk_guix/generate_vm_image_and_system_job.rb b/app/jobs/govuk_guix/generate_vm_image_and_system_job.rb deleted file mode 100644 index 1c84577..0000000 --- a/app/jobs/govuk_guix/generate_vm_image_and_system_job.rb +++ /dev/null @@ -1,39 +0,0 @@ -class GovukGuix::GenerateVmImageAndSystemJob < GovukGuix::Job - @retry_interval = 30 - - def run(mini_environment_id) - logger.info( - "#{self.class}: Building mini environment #{mini_environment_id}" - ) - - mini_environment = MiniEnvironment.find(mini_environment_id) - - slug = mini_environment.name.parameterize - - command = [ - "#{mini_environment.govuk_guix_revision.store_path}/bin/govuk", - 'system', - 'build', - '--type=vm-image-and-system', - '--rails-environment=production', - "--app-domain=#{slug}.aws.cbaines.net", - "--web-domain=www.#{slug}.aws.cbaines.net", - '--use-high-ports=false', - '--use-https=certbot', - '--fallback', - 'whitehall', - 'government-frontend' - ] - - run_command(command) do |output| - store_path = output.last.strip - logger.debug "#{self.class}: vm_image_and_system: #{store_path}" - - mini_environment.update( - backend_data: { - vm_image_and_system: store_path - } - ) - end - end -end diff --git a/app/jobs/govuk_guix/job.rb b/app/jobs/govuk_guix/job.rb index 295f77d..577ead9 100644 --- a/app/jobs/govuk_guix/job.rb +++ b/app/jobs/govuk_guix/job.rb @@ -1,7 +1,7 @@ require 'open3' class GovukGuix::Job < Que::Job - def run_command(command) + def run_command(*command) logger.debug("#{self.class}: Running command #{command.join(' ')}") Open3.popen2e(*command) do |_stdin, stdout_and_stderr, wait_thr| @@ -9,18 +9,30 @@ class GovukGuix::Job < Que::Job output = [] stdout_and_stderr.each_line do |line| - logger.debug("#{self.class}: #{line}") + logger.debug(self.class) { line.chomp } output << line end exit_status = wait_thr.value unless exit_status == 0 - logger.error("#{self.class}: failed, exit status #{exit_status}") + logger.error(self.class) { "failed, exit status #{exit_status}" } - raise "#{output.join}\n" + raise "Running #{command.join(' ')} failed:\n\n#{output.join}\n" end - yield(output) + output + end + end + + def hash_to_arguments(hash) + hash.map do |(key, value)| + transfomed_key = key.tr('_', '-') + + if value == true + "--#{transfomed_key}" + else + "--#{transfomed_key}=#{value}" + end end end end diff --git a/app/models/backends/terraform_aws.rb b/app/models/backends/terraform_aws.rb index 6741204..bc131ef 100644 --- a/app/models/backends/terraform_aws.rb +++ b/app/models/backends/terraform_aws.rb @@ -9,6 +9,7 @@ # aws_secret_access_key :string # created_at :datetime not null # updated_at :datetime not null +# domain :string # require 'ruby_terraform' @@ -29,8 +30,15 @@ class Backends::TerraformAws < ApplicationRecord end def build(mini_environment) - GovukGuix::GenerateStartCommandJob.enqueue( - mini_environment.id + slug = mini_environment.name.parameterize + + 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' ) end @@ -54,13 +62,17 @@ class Backends::TerraformAws < ApplicationRecord end end + def signon_url(mini_environment) + "https://signon.#{mini_environment.name.parameterize}.#{domain}" + end + def terraform_variables(mini_environment) - mini_environment.backend_data.merge( + { aws_region: aws_region, slug: mini_environment.name.parameterize, ssh_public_key: ssh_public_key, - start_command: mini_environment.start_command - ) + start_command: mini_environment.backend_data['build_output'] + } end def ssh_public_key diff --git a/app/models/backends/terraform_libvirt.rb b/app/models/backends/terraform_libvirt.rb index 2cb46c6..9b92176 100644 --- a/app/models/backends/terraform_libvirt.rb +++ b/app/models/backends/terraform_libvirt.rb @@ -7,6 +7,7 @@ # uri :string # created_at :datetime not null # updated_at :datetime not null +# domain :string # require 'ruby_terraform' @@ -27,8 +28,17 @@ class Backends::TerraformLibvirt < ApplicationRecord end def build(mini_environment) - GovukGuix::GenerateVmImageAndSystemJob.enqueue( - mini_environment.id + slug = mini_environment.name.parameterize + + 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' ) end @@ -52,10 +62,15 @@ class Backends::TerraformLibvirt < ApplicationRecord end end + def signon_url(mini_environment) + "https://signon.#{mini_environment.name.parameterize}.#{domain}" + end + def terraform_variables(mini_environment) - mini_environment.backend_data.merge( + { uri: uri, - machine_name: mini_environment.name.parameterize - ) + machine_name: mini_environment.name.parameterize, + vm_image_and_system: mini_environment.backend_data['build_output'] + } end end diff --git a/app/views/backends/terraform_aws/new.html.erb b/app/views/backends/terraform_aws/new.html.erb index 0d33fcf..a6f2f6a 100644 --- a/app/views/backends/terraform_aws/new.html.erb +++ b/app/views/backends/terraform_aws/new.html.erb @@ -23,6 +23,30 @@ </div> <div class="form-group form-group-lg"> + <%= f.label :domain, class: 'col-sm-4 control-label' %> + <div class="col-sm-8"> + <%= f.text_field( + :domain, + class: 'form-control', + placeholder: 'Domain within which to host mini environments' + ) %> + <span class="help-block"> + <p> + For example, if you entered <samp>example.com</samp> for + the backend domain, and then created a mini environment + called "Test" using this backend, then the application + domain for the mini environment would be + <samp>test.example.com</samp>. + </p> + <p> + A Route53 Hosted Zone will be created for this domain, + and records added for the mini environments. + </p> + </span> + </div> + </div> + + <div class="form-group form-group-lg"> <%= f.label :aws_region, 'AWS Region', class: 'col-sm-4 control-label' %> <div class="col-sm-8"> <%= f.text_field( diff --git a/app/views/backends/terraform_aws/show.html.erb b/app/views/backends/terraform_aws/show.html.erb index 1a8c20c..c061d75 100644 --- a/app/views/backends/terraform_aws/show.html.erb +++ b/app/views/backends/terraform_aws/show.html.erb @@ -26,6 +26,31 @@ </div> <div class="form-group form-group-lg"> + <%= f.label :domain, class: 'col-sm-4 control-label' %> + <div class="col-sm-8"> + <%= f.text_field( + :domain, + class: 'form-control', + placeholder: 'Domain within which to host mini environments', + readonly: true + ) %> + <span class="help-block"> + <p> + For example, if you entered <samp>example.com</samp> for + the backend domain, and then created a mini environment + called "Test" using this backend, then the application + domain for the mini environment would be + <samp>test.example.com</samp>. + </p> + <p> + A Route53 Hosted Zone will be created for this domain, + and records added for the mini environments. + </p> + </span> + </div> + </div> + + <div class="form-group form-group-lg"> <%= f.label :aws_region, 'AWS Region', class: 'col-sm-4 control-label' %> <div class="col-sm-8"> <%= f.text_field( diff --git a/app/views/backends/terraform_libvirt/new.html.erb b/app/views/backends/terraform_libvirt/new.html.erb index ab32ab3..9de3e34 100644 --- a/app/views/backends/terraform_libvirt/new.html.erb +++ b/app/views/backends/terraform_libvirt/new.html.erb @@ -23,6 +23,16 @@ </div> <div class="form-group form-group-lg"> + <%= f.label :domain, class: 'col-sm-2 control-label' %> + <div class="col-sm-10"> + <%= f.text_field( + :domain, + class: 'form-control' + ) %> + </div> + </div> + + <div class="form-group form-group-lg"> <%= f.label :uri, 'URI', class: 'col-sm-2 control-label' %> <div class="col-sm-10"> <%= f.text_field( diff --git a/app/views/backends/terraform_libvirt/show.html.erb b/app/views/backends/terraform_libvirt/show.html.erb index 14b02dc..cfbc51c 100644 --- a/app/views/backends/terraform_libvirt/show.html.erb +++ b/app/views/backends/terraform_libvirt/show.html.erb @@ -22,12 +22,19 @@ </div> <div class="form-group form-group-lg"> - <%= f.label :uri, class: 'col-sm-2 control-label' %> + <%= f.label :domain, class: 'col-sm-2 control-label' %> <div class="col-sm-10"> - <%= f.text_field :uri, class: 'form-control' %> + <%= f.text_field :domain, class: 'form-control', readonly: true %> </div> </div> - + + <div class="form-group form-group-lg"> + <%= f.label :uri, 'URI', class: 'col-sm-2 control-label' %> + <div class="col-sm-10"> + <%= f.text_field :uri, class: 'form-control', readonly: true %> + </div> + </div> + <div class="form-group form-group-lg"> <div class="col-sm-offset-2 col-sm-10"> <%= f.submit "Save", class: 'btn btn-lg btn-success' %> diff --git a/app/views/mini_environments/show.html.erb b/app/views/mini_environments/show.html.erb index 2895330..fab9e44 100644 --- a/app/views/mini_environments/show.html.erb +++ b/app/views/mini_environments/show.html.erb @@ -7,7 +7,7 @@ <div class="row"> <div class="col-md-9"> <a class="btn btn-primary btn-lg" - href="https://signon.<%= @mini_environment.name.parameterize %>.aws.cbaines.net"> + href="<%= @mini_environment.backend.signon_url(@mini_environment) %>"> View </a> diff --git a/db/migrate/20180327204244_add_domain_to_terraform_libvirt_backends.rb b/db/migrate/20180327204244_add_domain_to_terraform_libvirt_backends.rb new file mode 100644 index 0000000..5ef99d1 --- /dev/null +++ b/db/migrate/20180327204244_add_domain_to_terraform_libvirt_backends.rb @@ -0,0 +1,5 @@ +class AddDomainToTerraformLibvirtBackends < ActiveRecord::Migration[5.1] + def change + add_column :terraform_libvirt_backends, :domain, :string + end +end diff --git a/db/migrate/20180327204322_add_domain_to_terraform_aws_backends.rb b/db/migrate/20180327204322_add_domain_to_terraform_aws_backends.rb new file mode 100644 index 0000000..9eff4f7 --- /dev/null +++ b/db/migrate/20180327204322_add_domain_to_terraform_aws_backends.rb @@ -0,0 +1,5 @@ +class AddDomainToTerraformAwsBackends < ActiveRecord::Migration[5.1] + def change + add_column :terraform_aws_backends, :domain, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 5c53432..36f0983 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180326201857) do +ActiveRecord::Schema.define(version: 20180327204322) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -61,6 +61,7 @@ ActiveRecord::Schema.define(version: 20180326201857) do t.string "aws_secret_access_key" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "domain" end create_table "terraform_libvirt_backends", force: :cascade do |t| @@ -68,6 +69,7 @@ ActiveRecord::Schema.define(version: 20180326201857) do t.string "uri" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "domain" end create_table "terraform_states", force: :cascade do |t| |