From 9b21261f73a7311c2ab9df366aa4028652427d8d Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Sat, 25 Jan 2025 09:04:54 -0800 Subject: [PATCH] button to restart upstream services from status menu --- Dockerfile | 22 +++++++++++++-- Gemfile.lock | 24 ++++++++--------- app/controllers/status_controller.rb | 10 ++++++- app/views/status/_service.html.erb | 21 ++++++++++++++- app/views/status/index.html.erb | 21 --------------- app/views/status/show.html.erb | 21 +++++++++++++++ config/routes.rb | 2 +- .../20250125001320_restart_for_endpoints.rb | 6 +++++ db/schema.rb | 5 +++- ops/production-deploy.tmpl.yaml | 27 +++++++++++++++++++ 10 files changed, 120 insertions(+), 39 deletions(-) delete mode 100644 app/views/status/index.html.erb create mode 100644 app/views/status/show.html.erb create mode 100644 db/migrate/20250125001320_restart_for_endpoints.rb diff --git a/Dockerfile b/Dockerfile index c20f5f6b..62a17e16 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,26 @@ -FROM ghcr.io/samvera/hyku/base:d6ef0431 as hyku-base +FROM ghcr.io/samvera/hyku/base:d6ef0431 AS hyku-base # The bunder and asset build are ONBUILD commands in the base. they still get run # as if they were included right after the from line. See https://docs.docker.com/engine/reference/builder/#onbuild RUN sed -i '/require .enumerator./d' /usr/local/bundle/gems/sass-3.7.4/lib/sass/util.rb RUN ln -sf /app/samvera/branding /app/samvera/hyrax-webapp/public/branding +# Set environment variables for kubectl installation +ENV KUBECTL_VERSION=v1.27.3 +USER root +# Determine the architecture and set the download URL accordingly +RUN ARCH=$(uname -m) && \ + if [ "$ARCH" = "x86_64" ]; then \ + ARCH="amd64"; \ + elif [ "$ARCH" = "aarch64" ]; then \ + ARCH="arm64"; \ + elif [ "$ARCH" = "armv7l" ]; then \ + ARCH="arm"; \ + else \ + echo "Unsupported architecture: $ARCH"; exit 1; \ + fi && \ + curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${ARCH}/kubectl" && \ + install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \ + rm kubectl +USER app -FROM hyku-base as hyku-worker +FROM hyku-base AS hyku-worker CMD ./bin/worker diff --git a/Gemfile.lock b/Gemfile.lock index 8da5af41..7fc2a0f2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,6 +7,18 @@ GIT aws-sdk-sqs (~> 1) rails (>= 4.2) +GIT + remote: https://github.com/notch8/iiif_print.git + revision: 5c5fa6880b3dc22beed738cfcba7af57b698ac36 + branch: main + specs: + iiif_print (1.0.0) + blacklight_iiif_search (>= 1.0, < 3.0) + derivative-rodeo (~> 0.5) + hyrax (>= 2.5, < 6) + nokogiri (>= 1.13.2) + rdf-vocab (~> 3.0) + GIT remote: https://github.com/samvera-labs/allinson_flex.git revision: 581b58d57a90440f71d5d4ad8e1a9e4316ea92a3 @@ -133,18 +145,6 @@ GIT iiif_manifest (1.3.1) activesupport (>= 4) -GIT - remote: https://github.com/notch8/iiif_print.git - revision: 5c5fa6880b3dc22beed738cfcba7af57b698ac36 - branch: main - specs: - iiif_print (1.0.0) - blacklight_iiif_search (>= 1.0, < 3.0) - derivative-rodeo (~> 0.5) - hyrax (>= 2.5, < 6) - nokogiri (>= 1.13.2) - rdf-vocab (~> 3.0) - GIT remote: https://github.com/stanhu/omniauth-cas.git revision: 4211e6d05941b4a981f9a36b49ec166cecd0e271 diff --git a/app/controllers/status_controller.rb b/app/controllers/status_controller.rb index 479c60a6..b99bb333 100644 --- a/app/controllers/status_controller.rb +++ b/app/controllers/status_controller.rb @@ -7,9 +7,17 @@ class StatusController < ApplicationController authorize! :read, :admin_dashboard end - def index + def show add_breadcrumb t(:'hyrax.controls.home'), root_path add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path add_breadcrumb t(:'hyrax.admin.sidebar.system_status'), main_app.status_path end + + def update + @endpoint = Endpoint.find(params[:id]) + result = %x{@endpoint.restart_command} if @endpoint.restart_command.present? && @endpoint.last_restart < 5.minutes.ago + @endpoint.update(last_restart: Time.now) + flash[:notice] = "Restart result was: #{result}" + redirect_to status_path + end end diff --git a/app/views/status/_service.html.erb b/app/views/status/_service.html.erb index e4f1b97f..a1eb20d1 100644 --- a/app/views/status/_service.html.erb +++ b/app/views/status/_service.html.erb @@ -1 +1,20 @@ -
  • <%= name %> <%= status ? t(:'.ok') : t(:'.down') %>
  • +
  • +
    +
    + <%= name %> +
    +
    + + <%= status ? t(:'.ok') : t(:'.down') %> + +
    +
    + <% if endpoint && endpoint.restart_command.present? %> + <% disabled = endpoint.last_restart > 5.minutes.ago %> + <%= button_to 'restart', status_path(id: endpoint.id), disabled: disabled, method: :patch, class: 'btn btn-danger btn-xs', title: disabled ? "You need to wait 5 minutes between restarts" : "Restart endpoint" %> + <% else %> + <%= button_to 'restart', '/', disabled: true, class: 'btn btn-danger btn-xs', title: 'no command specified' %> + <% end %> +
    +
    +
  • diff --git a/app/views/status/index.html.erb b/app/views/status/index.html.erb deleted file mode 100644 index 1be32c08..00000000 --- a/app/views/status/index.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -<% content_for :page_header do %> -

    <%= t(:'hyrax.admin.sidebar.system_status') %>

    -<% end %> - -
    -
    -
    -
    -

    <%= t(:'.services') %>

    -
    -
    -
      - <%= render partial: 'service', locals: { name: 'Fedora', status: current_account.fcrepo_endpoint.ping } %> - <%= render partial: 'service', locals: { name: 'Solr', status: current_account.solr_endpoint.ping } %> - <%= render partial: 'service', locals: { name: 'Redis', status: current_account.redis_endpoint.ping } %> - <%= render partial: 'service', locals: { name: 'Database', status: ActiveRecord::Base.connection.active? } %> -
    -
    -
    -
    -
    diff --git a/app/views/status/show.html.erb b/app/views/status/show.html.erb new file mode 100644 index 00000000..a2377a98 --- /dev/null +++ b/app/views/status/show.html.erb @@ -0,0 +1,21 @@ +<% content_for :page_header do %> +

    <%= t(:'hyrax.admin.sidebar.system_status') %>

    +<% end %> + +
    +
    +
    +
    +

    <%= t(:'.services') %>

    +
    +
    +
      + <%= render partial: 'service', locals: { name: 'Fedora', status: current_account.fcrepo_endpoint.ping, endpoint: current_account.fcrepo_endpoint } %> + <%= render partial: 'service', locals: { name: 'Solr', status: current_account.solr_endpoint.ping, endpoint: current_account.solr_endpoint } %> + <%= render partial: 'service', locals: { name: 'Redis', status: current_account.redis_endpoint.ping, endpoint: current_account.redis_endpoint } %> + <%= render partial: 'service', locals: { name: 'Database', status: ActiveRecord::Base.connection.active?, endpoint: nil } %> +
    +
    +
    +
    +
    diff --git a/config/routes.rb b/config/routes.rb index b167a6b2..5217cb17 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -33,7 +33,7 @@ end end - get 'status', to: 'status#index' + resource :status, only: [:show, :update], controller: 'status' mount BrowseEverything::Engine => '/browse' resource :site, only: [:update] do diff --git a/db/migrate/20250125001320_restart_for_endpoints.rb b/db/migrate/20250125001320_restart_for_endpoints.rb new file mode 100644 index 00000000..e52199b8 --- /dev/null +++ b/db/migrate/20250125001320_restart_for_endpoints.rb @@ -0,0 +1,6 @@ +class RestartForEndpoints < ActiveRecord::Migration[5.2] + def change + add_column :endpoints, :restart_command, :text + add_column :endpoints, :last_restart, :datetime, default: Time.now + end +end diff --git a/db/schema.rb b/db/schema.rb index 56c7fe30..0cfd1167 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: 2024_12_03_010707) do +ActiveRecord::Schema.define(version: 2025_01_25_001320) do # These are extensions that must be enabled in order to support this database enable_extension "hstore" @@ -179,6 +179,7 @@ t.string "status_message", default: "Pending" t.string "error_class" t.index ["identifier", "importerexporter_id", "importerexporter_type"], name: "bulkrax_identifier_idx" + t.index ["importerexporter_id", "importerexporter_type", "id"], name: "index_bulkrax_entries_on_importerexporter_id_type_and_id" t.index ["importerexporter_id", "importerexporter_type"], name: "bulkrax_entries_importerexporter_idx" t.index ["type"], name: "index_bulkrax_entries_on_type" end @@ -385,6 +386,8 @@ t.binary "options" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.text "restart_command" + t.datetime "last_restart", default: "2025-01-25 00:47:14" end create_table "featured_collections", force: :cascade do |t| diff --git a/ops/production-deploy.tmpl.yaml b/ops/production-deploy.tmpl.yaml index 119b0f76..f5638b18 100644 --- a/ops/production-deploy.tmpl.yaml +++ b/ops/production-deploy.tmpl.yaml @@ -254,3 +254,30 @@ externalSolrPassword: $SOLR_ADMIN_PASSWORD externalSolrHost: solr.solr.svc.cluster.local externalSolrUser: admin externalSolrCollection: "utk-hyku" + + +extraDeploy: + - |- + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + namespace: utk-hyku-production + name: deployment-manager + rules: + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "list", "watch", "update", "patch"] + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: hyrax-deployment-manager-binding + namespace: default + subjects: + - kind: ServiceAccount + name: utk-hyku-production-hyrax + namespace: utk-hyku-production + roleRef: + kind: Role + name: deployment-manager + apiGroup: rbac.authorization.k8s.io