From 1fcb11bb31d0ffbf37de3ce704231bdcdaf787ca Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Fri, 22 Jun 2018 07:34:07 +0100 Subject: Replace the GovukGuix::BuildJob With a service that performs the same function, and use the MiniEnvironmentJob instead. --- app/controllers/mini_environments_controller.rb | 7 +- app/jobs/govuk_guix/build_job.rb | 98 ---------------------- app/jobs/govuk_guix/create_data_snapshot_job.rb | 3 +- app/jobs/govuk_guix/fetch_revision_job.rb | 3 +- app/jobs/govuk_guix/job.rb | 96 --------------------- app/models/backends/terraform_aws.rb | 2 +- .../terraform_libvirt/mini_environment_methods.rb | 2 +- app/services/govuk_guix/build_mini_environment.rb | 89 ++++++++++++++++++++ app/views/mini_environments/show.html.erb | 33 -------- app/views/shared/_jobs.html.erb | 10 +++ 10 files changed, 107 insertions(+), 236 deletions(-) delete mode 100644 app/jobs/govuk_guix/build_job.rb delete mode 100644 app/jobs/govuk_guix/job.rb create mode 100644 app/services/govuk_guix/build_mini_environment.rb (limited to 'app') diff --git a/app/controllers/mini_environments_controller.rb b/app/controllers/mini_environments_controller.rb index 9b8a16c..837a503 100644 --- a/app/controllers/mini_environments_controller.rb +++ b/app/controllers/mini_environments_controller.rb @@ -133,7 +133,7 @@ class MiniEnvironmentsController < ApplicationController end end - @mini_environment.backend.build(@mini_environment) + MiniEnvironmentJob.enqueue(@mini_environment.id, :build) redirect_to @mini_environment end end @@ -160,10 +160,7 @@ class MiniEnvironmentsController < ApplicationController end def jobs - [ - MiniEnvironmentJob.jobs(@mini_environment.id), - GovukGuix::BuildJob.jobs(@mini_environment.id) - ].flatten + MiniEnvironmentJob.jobs(@mini_environment.id) end helper_method :jobs diff --git a/app/jobs/govuk_guix/build_job.rb b/app/jobs/govuk_guix/build_job.rb deleted file mode 100644 index 94acd70..0000000 --- a/app/jobs/govuk_guix/build_job.rb +++ /dev/null @@ -1,98 +0,0 @@ -# GOV.UK Mini Environment Admin -# Copyright © 2018 Christopher Baines -# -# This file is part of the GOV.UK Mini Environment Admin. -# -# The GOV.UK Mini Environment Admin is free software: you can -# redistribute it and/or modify it under the terms of the GNU Affero -# General Public License as published by the Free Software Foundation, -# either version 3 of the License, or (at your option) any later -# version. -# -# The GOV.UK Mini Environment Admin is distributed in the hope that it -# will be useful, but WITHOUT ANY WARRANTY; without even the implied -# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public -# License along with the GOV.UK Mini Environment Admin. If not, see -# . - -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, 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 - # 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 - ) - end - - output = run_command( - "#{mini_environment.govuk_guix_revision.store_path}/bin/govuk", - 'system', - 'build', - *hash_to_arguments( - DEFAULT_ARGUMENTS.merge(options[:arguments]) - ), - *signon_user_arguments(mini_environment.signon_users), - *options[:services], - run_remotely_on_host: remote_host - ) - - 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 passphrase) - - 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 - - def self.jobs(mini_environment_id) - QueJob - .where( - job_class: name - ).where( - "args->>0 = '#{mini_environment_id}'" - ).to_a - end -end diff --git a/app/jobs/govuk_guix/create_data_snapshot_job.rb b/app/jobs/govuk_guix/create_data_snapshot_job.rb index f2075c7..91f3904 100644 --- a/app/jobs/govuk_guix/create_data_snapshot_job.rb +++ b/app/jobs/govuk_guix/create_data_snapshot_job.rb @@ -18,8 +18,9 @@ # License along with the GOV.UK Mini Environment Admin. If not, see # . -class GovukGuix::CreateDataSnapshotJob < GovukGuix::Job +class GovukGuix::CreateDataSnapshotJob < Que::Job extend EnqueuedJobs + include ::ShellUtils @retry_interval = 30 diff --git a/app/jobs/govuk_guix/fetch_revision_job.rb b/app/jobs/govuk_guix/fetch_revision_job.rb index c747c13..2787156 100644 --- a/app/jobs/govuk_guix/fetch_revision_job.rb +++ b/app/jobs/govuk_guix/fetch_revision_job.rb @@ -20,8 +20,9 @@ require 'git' -class GovukGuix::FetchRevisionJob < GovukGuix::Job +class GovukGuix::FetchRevisionJob < Que::Job extend EnqueuedJobs + include ::ShellUtils REPOSITORY_DIRECTORY = 'tmp/cache/govuk-guix'.freeze diff --git a/app/jobs/govuk_guix/job.rb b/app/jobs/govuk_guix/job.rb deleted file mode 100644 index 5f95f4d..0000000 --- a/app/jobs/govuk_guix/job.rb +++ /dev/null @@ -1,96 +0,0 @@ -# GOV.UK Mini Environment Admin -# Copyright © 2018 Christopher Baines -# -# This file is part of the GOV.UK Mini Environment Admin. -# -# The GOV.UK Mini Environment Admin is free software: you can -# redistribute it and/or modify it under the terms of the GNU Affero -# General Public License as published by the Free Software Foundation, -# either version 3 of the License, or (at your option) any later -# version. -# -# The GOV.UK Mini Environment Admin is distributed in the hope that it -# will be useful, but WITHOUT ANY WARRANTY; without even the implied -# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public -# License along with the GOV.UK Mini Environment Admin. If not, see -# . - -require 'open3' -require 'shellwords' - -class GovukGuix::Job < Que::Job - def run_command(*command, run_remotely_on_host: nil) - if run_remotely_on_host - command = command.map do |arg| - Shellwords.escape(arg) - end - - command = [ - 'ssh', - run_remotely_on_host, - *command - ] - end - - logger.debug("#{self.class}: Running command #{command.join(' ')}") - - Open3.popen2e(*command) do |_stdin, stdout_and_stderr, wait_thr| - logger.info("#{self.class}: commmand running, pid #{wait_thr.pid}") - - output = [] - stdout_and_stderr.each_line do |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}" } - - raise "Running #{command.join(' ')} failed:\n\n#{output.join}\n" - end - - output - end - end - - def read_json_file(filename, from_remote_host: nil) - if from_remote_host - command = [ - 'ssh', - from_remote_host, - 'cat', - filename - ] - - stdout_str, status = Open3.capture2(*command) - - unless status.exitstatus == 0 - logger.error(self.class) { "failed, exit status #{exit_status}" } - - raise "Running #{command.join(' ')} failed:\n\n#{output.join}\n" - end - - JSON.parse(stdout_str) - else - JSON.parse(File.read(filename)) - end - end - - def hash_to_arguments(hash) - hash.flat_map do |(key, value)| - transformed_key = key.to_s.tr('_', '-') - - if value == true - ["--#{transformed_key}"] - elsif value.kind_of?(Array) - value.map { |x| "--#{transformed_key}=#{x}" } - else - ["--#{transformed_key}=#{value}"] - end - end - end -end diff --git a/app/models/backends/terraform_aws.rb b/app/models/backends/terraform_aws.rb index db8d6cd..1f16188 100644 --- a/app/models/backends/terraform_aws.rb +++ b/app/models/backends/terraform_aws.rb @@ -52,7 +52,7 @@ class Backends::TerraformAws < ApplicationRecord def build(mini_environment) slug = mini_environment.name.parameterize - GovukGuix::BuildJob.enqueue( + GovukGuix::BuildMiniEnvironment.build( mini_environment.id, services: mini_environment.services.map(&:build_argument_string), arguments: { diff --git a/app/models/backends/terraform_libvirt/mini_environment_methods.rb b/app/models/backends/terraform_libvirt/mini_environment_methods.rb index c931a5d..4ed8835 100644 --- a/app/models/backends/terraform_libvirt/mini_environment_methods.rb +++ b/app/models/backends/terraform_libvirt/mini_environment_methods.rb @@ -22,7 +22,7 @@ module Backends::TerraformLibvirt::MiniEnvironmentMethods def build(mini_environment) slug = mini_environment.name.parameterize - GovukGuix::BuildJob.enqueue( + GovukGuix::BuildMiniEnvironment.build( mini_environment.id, services: mini_environment.services.map(&:build_argument_string), arguments: { diff --git a/app/services/govuk_guix/build_mini_environment.rb b/app/services/govuk_guix/build_mini_environment.rb new file mode 100644 index 0000000..5e5fd85 --- /dev/null +++ b/app/services/govuk_guix/build_mini_environment.rb @@ -0,0 +1,89 @@ +# GOV.UK Mini Environment Admin +# Copyright © 2018 Christopher Baines +# +# This file is part of the GOV.UK Mini Environment Admin. +# +# The GOV.UK Mini Environment Admin is free software: you can +# redistribute it and/or modify it under the terms of the GNU Affero +# General Public License as published by the Free Software Foundation, +# either version 3 of the License, or (at your option) any later +# version. +# +# The GOV.UK Mini Environment Admin is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with the GOV.UK Mini Environment Admin. If not, see +# . + +module GovukGuix::BuildMiniEnvironment + extend ::ShellUtils + + DEFAULT_ARGUMENTS = { + 'rails-environment' => 'production', + 'use-high-ports' => 'false', + 'fallback' => true + }.freeze + + def self.build(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 + # 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 + ) + end + + output = run_command( + "#{mini_environment.govuk_guix_revision.store_path}/bin/govuk", + 'system', + 'build', + *hash_to_arguments( + DEFAULT_ARGUMENTS.merge(options[:arguments]) + ), + *signon_user_arguments(mini_environment.signon_users), + *options[:services], + run_remotely_on_host: remote_host + ) + + build_output = output.last.strip + logger.debug(self.class) { "build_output: #{build_output}" } + + mini_environment.update( + backend_data: { + build_output: build_output + } + ) + end + + def self.signon_user_to_sexp(signon_user) + keys = %w(name email role passphrase) + + sexp_contents = keys.zip( + signon_user.values_at(*keys) + ).map do |(key, value)| + "#:#{key} \"#{value}\"" + end + + "(#{sexp_contents.join(' ')})" + end + + def self.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/views/mini_environments/show.html.erb b/app/views/mini_environments/show.html.erb index 7f3432a..a4d8588 100644 --- a/app/views/mini_environments/show.html.erb +++ b/app/views/mini_environments/show.html.erb @@ -60,39 +60,6 @@ License along with the GOV.UK Mini Environment Admin. If not, see <% end %>
- <% if @mini_environment.backend_data.present? %> -
- -
-
-
- <% @mini_environment.backend_data.each do |(key, value)| %> -
<%= key %>
-
<%= value %>
- <% end %> -
-
-
-
- <% end %> - <%= render( partial: 'shared/jobs', locals: { jobs: jobs } diff --git a/app/views/shared/_jobs.html.erb b/app/views/shared/_jobs.html.erb index 5b559c1..417f8a0 100644 --- a/app/views/shared/_jobs.html.erb +++ b/app/views/shared/_jobs.html.erb @@ -61,6 +61,16 @@ <% elsif job.finished_at %>
Finished after <%= job['error_count'] %> errors. + + <% if job.args.last == 'build' %> + <%# TODO: Generalise this somehow %> +
+ <% @mini_environment.backend_data.each do |(key, value)| %> +
<%= key %>
+
<%= value %>
+ <% end %> +
+ <% end %>
<% else %>
-- cgit v1.2.3