diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/mini_environments.js | 2 | ||||
-rw-r--r-- | app/controllers/govuk_guix/revisions_controller.rb | 4 | ||||
-rw-r--r-- | app/controllers/mini_environments_controller.rb | 36 | ||||
-rw-r--r-- | app/controllers/que_jobs_controller.rb | 19 | ||||
-rw-r--r-- | app/helpers/govuk_guix/revisions_helper.rb | 2 | ||||
-rw-r--r-- | app/jobs/destroy_job.rb | 1 | ||||
-rw-r--r-- | app/jobs/govuk_guix/build_job.rb | 33 | ||||
-rw-r--r-- | app/jobs/govuk_guix/fetch_revision_job.rb | 49 | ||||
-rw-r--r-- | app/jobs/govuk_guix/job.rb | 24 | ||||
-rw-r--r-- | app/jobs/start_job.rb (renamed from app/jobs/setup_job.rb) | 6 | ||||
-rw-r--r-- | app/models/govuk_guix.rb | 5 | ||||
-rw-r--r-- | app/models/govuk_guix/revision.rb | 3 | ||||
-rw-r--r-- | app/models/mini_environment.rb | 1 | ||||
-rw-r--r-- | app/views/govuk_guix/revisions/index.html.erb | 10 | ||||
-rw-r--r-- | app/views/layouts/application.html.erb | 1 | ||||
-rw-r--r-- | app/views/mini_environments/new.html.erb | 13 | ||||
-rw-r--r-- | app/views/mini_environments/show.html.erb | 64 | ||||
-rw-r--r-- | app/views/que_jobs/cancel.html.erb | 2 | ||||
-rw-r--r-- | app/views/que_jobs/retry_now.html.erb | 2 |
19 files changed, 257 insertions, 20 deletions
diff --git a/app/assets/javascripts/mini_environments.js b/app/assets/javascripts/mini_environments.js deleted file mode 100644 index dee720f..0000000 --- a/app/assets/javascripts/mini_environments.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/app/controllers/govuk_guix/revisions_controller.rb b/app/controllers/govuk_guix/revisions_controller.rb new file mode 100644 index 0000000..a890fd0 --- /dev/null +++ b/app/controllers/govuk_guix/revisions_controller.rb @@ -0,0 +1,4 @@ +class GovukGuix::RevisionsController < ApplicationController + def index + end +end diff --git a/app/controllers/mini_environments_controller.rb b/app/controllers/mini_environments_controller.rb index c45ed4a..8009777 100644 --- a/app/controllers/mini_environments_controller.rb +++ b/app/controllers/mini_environments_controller.rb @@ -8,14 +8,38 @@ class MiniEnvironmentsController < ApplicationController end def create - ActiveRecord::Base.transaction do - @mini_environment = MiniEnvironment.create( - params.require(:mini_environment).permit(:name) - ) + @mini_environment = MiniEnvironment.create( + params + .require(:mini_environment) + .permit( + :name, + :govuk_guix_revision_id + ) + ) - SetupJob.enqueue(@mini_environment.id) - end + GovukGuix::BuildJob.enqueue(@mini_environment.id) redirect_to @mini_environment end + + def perform_action + @mini_environment = MiniEnvironment.find(params[:mini_environment_id]) + + action = params.require(:commit) + + case action + when 'Destroy' + DestroyJob.enqueue(@mini_environment.id) + + flash[:notice] = "Destroying mini environment" + when 'Start' + StartJob.enqueue(@mini_environment.id) + + flash[:notice] = "Starting mini environment" + else + flash[:error] = "Unknown action #{action}" + end + + render 'show' + end end diff --git a/app/controllers/que_jobs_controller.rb b/app/controllers/que_jobs_controller.rb new file mode 100644 index 0000000..bab2c47 --- /dev/null +++ b/app/controllers/que_jobs_controller.rb @@ -0,0 +1,19 @@ +class QueJobsController < ApplicationController + def cancel + ActiveRecord::Base.connection.execute( + "DELETE FROM que_jobs WHERE job_id = #{job_id}::bigint" + ) + end + + def retry_now + ActiveRecord::Base.connection.execute( + "UPDATE que_jobs + SET run_at = now() + WHERE job_id = #{job_id}::bigint" + ) + end + + def job_id + params[:id].to_i + end +end diff --git a/app/helpers/govuk_guix/revisions_helper.rb b/app/helpers/govuk_guix/revisions_helper.rb new file mode 100644 index 0000000..eb84706 --- /dev/null +++ b/app/helpers/govuk_guix/revisions_helper.rb @@ -0,0 +1,2 @@ +module GovukGuix::RevisionsHelper +end diff --git a/app/jobs/destroy_job.rb b/app/jobs/destroy_job.rb index 7f13fdd..2bc72c1 100644 --- a/app/jobs/destroy_job.rb +++ b/app/jobs/destroy_job.rb @@ -12,6 +12,7 @@ class DestroyJob < TerraformJob aws_region: 'eu-west-1', slug: @mini_environment.name.parameterize, ssh_public_key: ssh_public_key, + start_command: @mini_environment.start_command }, force: true ) diff --git a/app/jobs/govuk_guix/build_job.rb b/app/jobs/govuk_guix/build_job.rb new file mode 100644 index 0000000..381a717 --- /dev/null +++ b/app/jobs/govuk_guix/build_job.rb @@ -0,0 +1,33 @@ +require 'ruby_terraform' +require 'open3' + +class GovukGuix::BuildJob < GovukGuix::Job + @retry_interval = 30 + + def run(mini_environment_id) + logger.info "GovukGuix::BuildJob: 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", + ] + + run_command(command) do |output| + store_path = output.last.strip + logger.debug("GovukGuix::BuildJob: start_command: #{store_path}") + + mini_environment.update(start_command: store_path) + end + end +end diff --git a/app/jobs/govuk_guix/fetch_revision_job.rb b/app/jobs/govuk_guix/fetch_revision_job.rb new file mode 100644 index 0000000..b1cb171 --- /dev/null +++ b/app/jobs/govuk_guix/fetch_revision_job.rb @@ -0,0 +1,49 @@ +require 'ruby_terraform' +require 'git' +require 'open3' + +class GovukGuix::FetchRevisionJob < GovukGuix::Job + @retry_interval = 30 + + def run(commit_hash) + repository.fetch + + repository.checkout(commit_hash) + + command = [ + "#{repository_directory}/guix-pre-inst-env", + "guix", + "build", + "-e", + "(begin (use-modules (gds packages govuk)) (current-govuk-guix))" + ] + + run_command(command) do |output| + store_path = output.last.strip + logger.debug("FetchRevisionJob: store_path: #{store_path}") + + GovukGuix::Revision.create( + commit_hash: commit_hash, + store_path: store_path + ) + end + end + + def repository + @_repository ||= begin + if File.exists? repository_directory + Git.open(repository_directory, :log => Rails.logger) + else + Git.clone(repository_remote_location, repository_directory) + end + end + end + + def repository_directory + 'tmp/cache/govuk-guix' + end + + def repository_remote_location + 'git@git.cbaines.net:gds/govuk-guix' + end +end diff --git a/app/jobs/govuk_guix/job.rb b/app/jobs/govuk_guix/job.rb new file mode 100644 index 0000000..0161cb1 --- /dev/null +++ b/app/jobs/govuk_guix/job.rb @@ -0,0 +1,24 @@ +class GovukGuix::Job < Que::Job + def run_command(command) + logger.debug("#{self.class}: Running command #{command}") + + 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}") + output << line + end + + exit_status = wait_thr.value + unless exit_status == 0 + logger.error("#{self.class}: failed, exit status #{exit_status}") + + raise "#{output.join}\n" + end + + yield(output) + end + end +end diff --git a/app/jobs/setup_job.rb b/app/jobs/start_job.rb index 6791dd6..ec17732 100644 --- a/app/jobs/setup_job.rb +++ b/app/jobs/start_job.rb @@ -1,10 +1,10 @@ require 'ruby_terraform' -class SetupJob < TerraformJob +class StartJob < TerraformJob @retry_interval = 30 def run_terraform - puts "Setting up #{@mini_environment.name}" + logger.info "Setting up #{@mini_environment.name}" Dir.chdir('terraform/aws') do RubyTerraform.init( @@ -15,11 +15,11 @@ class SetupJob < TerraformJob ) RubyTerraform.apply( - directory: 'mini_environment', vars: { aws_region: 'eu-west-1', slug: @mini_environment.name.parameterize, ssh_public_key: ssh_public_key, + start_command: @mini_environment.start_command }, auto_approve: true ) diff --git a/app/models/govuk_guix.rb b/app/models/govuk_guix.rb new file mode 100644 index 0000000..e98da8e --- /dev/null +++ b/app/models/govuk_guix.rb @@ -0,0 +1,5 @@ +module GovukGuix + def self.table_name_prefix + 'govuk_guix_' + end +end diff --git a/app/models/govuk_guix/revision.rb b/app/models/govuk_guix/revision.rb new file mode 100644 index 0000000..147b6d6 --- /dev/null +++ b/app/models/govuk_guix/revision.rb @@ -0,0 +1,3 @@ +class GovukGuix::Revision < ApplicationRecord + self.primary_key = "commit_hash" +end diff --git a/app/models/mini_environment.rb b/app/models/mini_environment.rb index 2d6d8ae..87ecff8 100644 --- a/app/models/mini_environment.rb +++ b/app/models/mini_environment.rb @@ -1,5 +1,6 @@ class MiniEnvironment < ApplicationRecord has_many :finished_terraform_jobs, dependent: :destroy + belongs_to :govuk_guix_revision, class_name: 'GovukGuix::Revision' def enqueued_terraform_jobs Que.execute("SELECT * FROM que_jobs WHERE args->>0 = '#{id}'") diff --git a/app/views/govuk_guix/revisions/index.html.erb b/app/views/govuk_guix/revisions/index.html.erb new file mode 100644 index 0000000..54f9e4a --- /dev/null +++ b/app/views/govuk_guix/revisions/index.html.erb @@ -0,0 +1,10 @@ + +<% GovukGuix::Revision.all.each do |revision| %> + + <div> + + <%= revision.inspect %> + + </div> + +<% end %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5b90ace..35ea5ff 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,6 +1,5 @@ <% content_for :head do %> <%= stylesheet_link_tag "application", :media => "all" %> - <%= javascript_include_tag "application" %> <%= csrf_meta_tag %> <%= yield :extra_headers %> <% end %> diff --git a/app/views/mini_environments/new.html.erb b/app/views/mini_environments/new.html.erb index 84d2316..7d3f2f2 100644 --- a/app/views/mini_environments/new.html.erb +++ b/app/views/mini_environments/new.html.erb @@ -1,8 +1,8 @@ <div class="row"> <div class="col-md-8"> - <%= form_for @mini_environment, - url: { action: "create" }, - html: { class: 'form-horizontal' } do |f| %> + <%= form_with(model: @mini_environment, + url: { action: "create" }, + html: { class: 'form-horizontal' }) do |f| %> <div class="form-group"> <%= f.label :name, class: 'col-sm-2 control-label' %> @@ -10,6 +10,13 @@ <%= f.text_field :name, class: 'form-control' %> </div> </div> + + <div class="form-group"> + <%= f.label :govuk_guix_revision_id, class: 'col-sm-2 control-label' %> + <div class="col-sm-10"> + <%= f.collection_select :govuk_guix_revision_id, GovukGuix::Revision.all, :commit_hash, :commit_hash %> + </div> + </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> diff --git a/app/views/mini_environments/show.html.erb b/app/views/mini_environments/show.html.erb index 0cc6bc6..a852e6c 100644 --- a/app/views/mini_environments/show.html.erb +++ b/app/views/mini_environments/show.html.erb @@ -1,5 +1,21 @@ <h1>Name: <%= @mini_environment.name %></h1> +<%= form_with(url: mini_environment_perform_action_path(@mini_environment), + local: true, + method: "post") do %> + <%= submit_tag('Start', + disabled: !@mini_environment.start_command.present?, + role: 'button', + class: 'btn btn-lg btn-success') + %> + + <%= submit_tag("Destroy", + #disabled: !@mini_environment.start_command.present?, + role: 'button', + class: 'btn btn-lg btn-danger') + %> +<% end %> + <a href="https://signon.<%= @mini_environment.name.parameterize %>.aws.cbaines.net">View</a> <h2>Finished jobs</h2> @@ -11,10 +27,48 @@ <h2>Enqueued jobs</h2> -<% @mini_environment.enqueued_terraform_jobs.each do |job| %> - <%= job['job_class'] %> +<div class="panel-group" + id="accordion" + role="tablist" + aria-multiselectable="true"> + + <% @mini_environment.enqueued_terraform_jobs.each do |job| %> - <pre> - <%= job['last_error'] %> - </pre> + <div class="panel panel-default"> + <div class="panel-heading" role="tab" id="headingOne"> + <h4 class="panel-title"> + <a role="button" + data-toggle="collapse" + data-parent="#accordion" + href="#collapseOne" + aria-expanded="true" + aria-controls="collapseOne"> + <%= job['job_class'] %> + </a> + <span class="pull-right"> + Retrying next in <%= distance_of_time_in_words_to_now(job['run_at'], include_seconds: true) %> + </span> + </h4> + </div> + <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne"> + <div class="panel-body"> + This job has failed <%= job['error_count'] %> times. + + <div class="pull-right"> + <%= form_with(url: retry_now_que_job_path(job['job_id'])) do %> + <%= submit_tag('Retry now', class: 'btn btn-default') + %> + <% end %> + <%= form_with(url: cancel_que_job_path(job['job_id'])) do %> + <%= submit_tag('Cancel', class: 'btn btn-default') + %> + <% end %> + </div> + + <pre><%= job['last_error'] %></pre> + </div> + </div> + </div> <% end %> + +</div> diff --git a/app/views/que_jobs/cancel.html.erb b/app/views/que_jobs/cancel.html.erb new file mode 100644 index 0000000..5886237 --- /dev/null +++ b/app/views/que_jobs/cancel.html.erb @@ -0,0 +1,2 @@ +<h1>QueJobs#cancel</h1> +<p>Find me in app/views/que_jobs/cancel.html.erb</p> diff --git a/app/views/que_jobs/retry_now.html.erb b/app/views/que_jobs/retry_now.html.erb new file mode 100644 index 0000000..1c8ecee --- /dev/null +++ b/app/views/que_jobs/retry_now.html.erb @@ -0,0 +1,2 @@ +<h1>QueJobs#retry_now</h1> +<p>Find me in app/views/que_jobs/retry_now.html.erb</p> |