From 39feeccc88ecf074ecd31a91c1a69106905b4ded Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 26 May 2016 23:40:10 +0200 Subject: [PATCH] Added auto restart of zammad after changing object attributes. --- .gitlab-ci.yml | 23 ++++++++ .../app/controllers/widget/maintenance.coffee | 58 ++++++++++++++----- app/controllers/sessions_controller.rb | 6 ++ app/models/object_manager/attribute.rb | 17 +++++- config/routes/auth.rb | 2 + lib/app_version.rb | 21 +++++-- lib/sessions.rb | 4 +- test/browser/admin_object_manager_test.rb | 21 +++++-- 8 files changed, 126 insertions(+), 26 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ecdb222fd..b1471d4a8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -334,6 +334,7 @@ test:browser:twitter_ff: - twitter script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - RAILS_ENV=test rake db:create - cp contrib/auto_wizard_test.json auto_wizard.json - script/bootstrap.sh @@ -350,6 +351,7 @@ test:browser:facebook_ff: - facebook script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - RAILS_ENV=test rake db:create - cp contrib/auto_wizard_test.json auto_wizard.json - script/bootstrap.sh @@ -365,6 +367,7 @@ test:browser:autowizard_ff: - browser-ff script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - RAILS_ENV=test rake db:create - cp contrib/auto_wizard_example.json auto_wizard.json - script/bootstrap.sh @@ -381,6 +384,7 @@ test:browser:core:ff_1_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -401,6 +405,7 @@ test:browser:core:ff_2_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -421,6 +426,7 @@ test:browser:core:ff_3_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - script/build/test_slice_tests.sh 3 - RAILS_ENV=test rake db:create - script/bootstrap.sh @@ -437,6 +443,7 @@ test:browser:core:ff_4_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -457,6 +464,7 @@ test:browser:core:ff_5_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -477,6 +485,7 @@ test:browser:core:ff_1_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -497,6 +506,7 @@ test:browser:core:ff_2_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -517,6 +527,7 @@ test:browser:core:ff_3_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - script/build/test_slice_tests.sh 3 - RAILS_ENV=test rake db:create - script/bootstrap.sh @@ -533,6 +544,7 @@ test:browser:core:ff_4_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -553,6 +565,7 @@ test:browser:core:ff_5_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -573,6 +586,7 @@ test:browser:core:chrome_1_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -593,6 +607,7 @@ test:browser:core:chrome_2_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -613,6 +628,7 @@ test:browser:core:chrome_3_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -633,6 +649,7 @@ test:browser:core:chrome_4_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -653,6 +670,7 @@ test:browser:core:chrome_5_mysql: - mysql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -673,6 +691,7 @@ test:browser:core:chrome_1_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -693,6 +712,7 @@ test:browser:core:chrome_2_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -713,6 +733,7 @@ test:browser:core:chrome_3_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -733,6 +754,7 @@ test:browser:core:chrome_4_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 @@ -753,6 +775,7 @@ test:browser:core:chrome_5_postgresql: - postgresql script: - export BROWSER_URL=http://$IP:$BROWSER_PORT + - export APP_RESTART_CMD="script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT && script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT" - unset MAILBOX_AUTO1 - unset MAILBOX_AUTO2 - unset MAILBOX_MANUAL1 diff --git a/app/assets/javascripts/app/controllers/widget/maintenance.coffee b/app/assets/javascripts/app/controllers/widget/maintenance.coffee index f6a0dd057..d6b9d47c4 100644 --- a/app/assets/javascripts/app/controllers/widget/maintenance.coffee +++ b/app/assets/javascripts/app/controllers/widget/maintenance.coffee @@ -1,4 +1,5 @@ class Widget extends App.Controller + errorCount: 0 constructor: -> super @@ -13,8 +14,10 @@ class Widget extends App.Controller @maintanaceAppVersion(data) if data.type is 'config_changed' @maintanaceConfigChanged(data) - if data.type is 'restart' - @maintanaceRestart(data) + if data.type is 'restart_auto' + @maintanaceRestartAuto(data) + if data.type is 'restart_manual' + @maintanaceRestartManual(data) 'maintenance' ) @@ -41,12 +44,12 @@ class Widget extends App.Controller return if !@authenticate(true) @navigate '#logout' - #App.Event.trigger('maintenance', {type:'restart'}) - maintanaceRestart: (data) => - return if @messageRestart - @messageRestart = new App.SessionMessage( - head: 'Restarting...' - message: 'Zammad is restarting... waiting...' + #App.Event.trigger('maintenance', {type:'restart_auto'}) + maintanaceRestartAuto: (data) => + return if @messageRestartAuto + @messageRestartAuto = new App.SessionMessage( + head: 'Zammad is restarting...' + message: 'Some system settings have changed, Zammad is restarting. Please wait until Zammad is back again.' keyboard: false backdrop: false buttonClose: false @@ -54,12 +57,24 @@ class Widget extends App.Controller small: true forceReload: true ) + @disconnectClient() + @checkAvailability() - # disconnect - - # try if backend is reachable again - - # reload app + #App.Event.trigger('maintenance', {type:'restart_manual'}) + maintanaceRestartManual: (data) => + return if @messageRestartManual + @messageRestartManual = new App.SessionMessage( + head: 'Zammad need a restart!' + message: 'Some system settings have changed, please restart all Zammad processes! If you want to do this automatically, set environment variable APP___RESTART___CMD="/path/to/your___app___script.sh restart".' + keyboard: false + backdrop: false + buttonClose: false + buttonSubmit: false + small: true + forceReload: true + ) + @disconnectClient() + @checkAvailability() maintanaceConfigChanged: (data) => return if @messageConfigChanged @@ -94,4 +109,21 @@ class Widget extends App.Controller ) @delay(message, 2000) + checkAvailability: (delay) => + delay = => + @ajax( + id: 'check_availability' + type: 'get' + url: "#{@apiPath}/available" + success: (data) => + if @errorCount is 0 + @checkAvailability() + return + @windowReload() + error: => + @errorCount += 1 + @checkAvailability() + ) + @delay(delay, 2000) + App.Config.set('maintenance', Widget, 'Widgets') diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index a5ae7695e..9e93bce87 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -273,6 +273,12 @@ class SessionsController < ApplicationController ) end + def available + render json: { + app_version: AppVersion.get + } + end + def list return if deny_if_not_role(Z_ROLENAME_ADMIN) assets = {} diff --git a/app/models/object_manager/attribute.rb b/app/models/object_manager/attribute.rb index 891559913..fe774102b 100644 --- a/app/models/object_manager/attribute.rb +++ b/app/models/object_manager/attribute.rb @@ -591,9 +591,18 @@ returns execute_count += 1 } - # sent reload to clients + # sent maintenance message to clients if execute_count != 0 - AppVersion.set(true) + if ENV['APP_RESTART_CMD'] + AppVersion.set(true, 'restart_auto') + pid = fork do + sleep 5 + system(ENV['APP_RESTART_CMD']) + Process.exit!(true) + end + else + AppVersion.set(true, 'restart_manual') + end end true end @@ -611,6 +620,10 @@ returns raise 'Spaces in name are not allowed' elsif name !~ /^[a-z0-9_]+$/ raise 'Only letters from a-z, numbers from 0-9, and _ are allowed' + elsif name !~ /[a-z]/ + raise 'At least one letters is needed' + elsif name =~ /^(destroy|true|false|integer|select|drop|create|alter|index|table)$/i + raise "#{name} is a reserved word, please choose a different one" end true end diff --git a/config/routes/auth.rb b/config/routes/auth.rb index 6807b69b3..50a77195f 100644 --- a/config/routes/auth.rb +++ b/config/routes/auth.rb @@ -12,6 +12,8 @@ Zammad::Application.routes.draw do match api_path + '/signshow', to: 'sessions#show', via: [:get, :post] match api_path + '/signout', to: 'sessions#destroy', via: [:get, :delete] + match api_path + '/available', to: 'sessions#available', via: :get + match api_path + '/sessions/switch/:id', to: 'sessions#switch_to_user', via: :get match api_path + '/sessions/switch_back', to: 'sessions#switch_back_to_user', via: :get match api_path + '/sessions', to: 'sessions#list', via: :get diff --git a/lib/app_version.rb b/lib/app_version.rb index 978c85272..909b5c8d2 100644 --- a/lib/app_version.rb +++ b/lib/app_version.rb @@ -24,22 +24,33 @@ set new app version and if browser reload is required AppVersion.set(true) # true == reload is required / false == no reload is required +send also reload type to clients + + AppVersion.set(true, 'restart_auto') + =end - def self.set(reload_required = false) + def self.set(reload_required = false, type = false) return false if !Setting.find_by(name: 'app_version') version = "#{Time.zone.now.strftime('%Y%m%d%H%M%S')}:#{reload_required}" Setting.set('app_version', version) # broadcast to clients - Sessions.broadcast(event_data) + Sessions.broadcast(event_data(type), 'public') end =begin get event data - AppVersion.event_data + AppVersion.event_data(type) + +types: + + app_version -> new app version + restart_manual -> app needs restart + restart_auto -> app is restarting + config_changed -> config has changed returnes @@ -53,11 +64,11 @@ returnes =end - def self.event_data + def self.event_data(type = 'app_version') { event: 'maintenance', data: { - type: 'app_version', + type: type, app_version: get, } } diff --git a/lib/sessions.rb b/lib/sessions.rb index ed53c0838..35b4f3e53 100644 --- a/lib/sessions.rb +++ b/lib/sessions.rb @@ -355,7 +355,7 @@ returns broadcase also to not authenticated client - Sessions.broadcast(data, 'public') + Sessions.broadcast(data, 'public') # public|authenticated broadcase also not to sender @@ -363,7 +363,7 @@ broadcase also not to sender =end - def self.broadcast(data, recipient = 'autenticated', sender_user_id = nil) + def self.broadcast(data, recipient = 'authenticated', sender_user_id = nil) # list all current clients recipients = [] diff --git a/test/browser/admin_object_manager_test.rb b/test/browser/admin_object_manager_test.rb index 4739eba71..b429d9dec 100644 --- a/test/browser/admin_object_manager_test.rb +++ b/test/browser/admin_object_manager_test.rb @@ -68,9 +68,16 @@ class AdminObjectManagerTest < TestCase click(css: '#content .tab-pane.active div.js-execute') watch_for( css: '.modal', - value: 'New Version', + value: 'restart', + ) + watch_for_disappear( + css: '.modal', + timeout: 26, + ) + sleep 5 + watch_for( + css: '#content', ) - click(css: '.modal button.js-submit') # create new ticket ticket = ticket_create( @@ -126,10 +133,16 @@ class AdminObjectManagerTest < TestCase click(css: '#content .tab-pane.active div.js-execute') watch_for( css: '.modal', - value: 'New Version', + value: 'restart', + ) + watch_for_disappear( + css: '.modal', + timeout: 26, ) - click(css: '.modal button.js-submit') sleep 5 + watch_for( + css: '#content', + ) match_not( css: '#content', value: 'Database Update required',