foreman-mco 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +15 -0
  2. data/Rakefile +40 -0
  3. data/app/assets/javascripts/foreman_mco/application.js +22 -0
  4. data/app/assets/javascripts/foreman_mco/mco_hosts_extensions.js +49 -0
  5. data/app/assets/stylesheets/foreman-mco/application.css +13 -0
  6. data/app/controllers/foreman_mco/command_histories_controller.rb +26 -0
  7. data/app/controllers/foreman_mco/command_statuses_controller.rb +49 -0
  8. data/app/controllers/foreman_mco/commands_controller.rb +48 -0
  9. data/app/controllers/foreman_mco/detailed_command_histories_controller.rb +27 -0
  10. data/app/helpers/foreman_mco/application_helper.rb +4 -0
  11. data/app/helpers/foreman_mco/command_histories_helper.rb +6 -0
  12. data/app/models/concerns/foreman_mco/hosts_helper.rb +25 -0
  13. data/app/models/foreman_mco/command/base.rb +24 -0
  14. data/app/models/foreman_mco/command/filter.rb +15 -0
  15. data/app/models/foreman_mco/command/package_commands.rb +33 -0
  16. data/app/models/foreman_mco/command/ping.rb +11 -0
  17. data/app/models/foreman_mco/command/puppet_commands.rb +31 -0
  18. data/app/models/foreman_mco/command/service_commands.rb +43 -0
  19. data/app/models/foreman_mco/command_status.rb +27 -0
  20. data/app/models/foreman_mco/commands.rb +4 -0
  21. data/app/models/foreman_mco/host_command_status.rb +12 -0
  22. data/app/models/services/foreman_mco/mco_proxy_api.rb +57 -0
  23. data/app/models/setting/mco.rb +15 -0
  24. data/app/overrides/enable_mco_actions_on_hosts.rb +9 -0
  25. data/app/views/foreman_mco/command_histories/index.html.erb +46 -0
  26. data/app/views/foreman_mco/commands/install_package.html.erb +9 -0
  27. data/app/views/foreman_mco/commands/ping.html.erb +6 -0
  28. data/app/views/foreman_mco/commands/puppet_disable.html.erb +8 -0
  29. data/app/views/foreman_mco/commands/puppet_enable.html.erb +8 -0
  30. data/app/views/foreman_mco/commands/puppet_runonce.html.erb +8 -0
  31. data/app/views/foreman_mco/commands/service_status.html.erb +9 -0
  32. data/app/views/foreman_mco/commands/start_service.html.erb +9 -0
  33. data/app/views/foreman_mco/commands/stop_service.html.erb +9 -0
  34. data/app/views/foreman_mco/commands/uninstall_package.html.erb +9 -0
  35. data/app/views/foreman_mco/detailed_command_histories/index.html.erb +26 -0
  36. data/app/views/layouts/foreman-mco/application.html.erb +14 -0
  37. data/config/routes.rb +24 -0
  38. data/db/migrate/20131030154603_create_command_statuses.rb +15 -0
  39. data/db/migrate/20131031113547_add_mcollective_proxy_feature.rb +8 -0
  40. data/db/migrate/20131125123644_create_host_command_statuses.rb +17 -0
  41. data/db/migrate/20131209192923_add_discovered_agents.rb +20 -0
  42. data/lib/foreman-mco.rb +4 -0
  43. data/lib/foreman-mco/engine.rb +60 -0
  44. data/lib/foreman-mco/version.rb +3 -0
  45. data/lib/tasks/foreman-mco_tasks.rake +4 -0
  46. data/test/dummy/README.rdoc +261 -0
  47. data/test/dummy/Rakefile +7 -0
  48. data/test/dummy/app/assets/javascripts/application.js +15 -0
  49. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  50. data/test/dummy/app/controllers/application_controller.rb +3 -0
  51. data/test/dummy/app/helpers/application_helper.rb +2 -0
  52. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  53. data/test/dummy/config.ru +4 -0
  54. data/test/dummy/config/application.rb +59 -0
  55. data/test/dummy/config/boot.rb +10 -0
  56. data/test/dummy/config/database.yml +25 -0
  57. data/test/dummy/config/environment.rb +5 -0
  58. data/test/dummy/config/environments/development.rb +37 -0
  59. data/test/dummy/config/environments/production.rb +67 -0
  60. data/test/dummy/config/environments/test.rb +37 -0
  61. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  62. data/test/dummy/config/initializers/inflections.rb +15 -0
  63. data/test/dummy/config/initializers/mime_types.rb +5 -0
  64. data/test/dummy/config/initializers/secret_token.rb +7 -0
  65. data/test/dummy/config/initializers/session_store.rb +8 -0
  66. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  67. data/test/dummy/config/locales/en.yml +5 -0
  68. data/test/dummy/config/routes.rb +4 -0
  69. data/test/dummy/public/404.html +26 -0
  70. data/test/dummy/public/422.html +26 -0
  71. data/test/dummy/public/500.html +25 -0
  72. data/test/dummy/public/favicon.ico +0 -0
  73. data/test/dummy/script/rails +6 -0
  74. data/test/foreman-mco_test.rb +7 -0
  75. data/test/integration/navigation_test.rb +10 -0
  76. data/test/test_helper.rb +15 -0
  77. metadata +181 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzdkZDcyMTM0YmFkYmJhNDFjMzMzYTY5ZTc2ZmFhYmM2ZDU5ZjFhOQ==
5
+ data.tar.gz: !binary |-
6
+ Y2YyM2M5ZThlMDExNzdjZjhkYzhhNGVjOTFjZTVmZjMxMzA1OTdkMw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZjY2MWZhODg5ZTM3YzAyYTQ2OTg2ZTNlMzc4ZjViYjNjZjQ3NDI2Y2ZkYmMy
10
+ MGRmYjYxNmQyNTgwOTU0OTgzOGU5YWVmZTkxNGE2YjU2YjhhNTM5MzhhYjkw
11
+ MTdjOTEyMGE2OGVmMWE4OTg1ZTM3YmIwZmMxZjhjNWFkNGI3NTA=
12
+ data.tar.gz: !binary |-
13
+ NjkxZTllM2FiMDE4MWY0ZmVhNzZkMDczMjQ4YmI3MmYyYWVhMTcxMDY4ZTBm
14
+ OWRhZTZkM2UzZGVmODJlYzM5Mzc3YTc4Njk1Y2NiNjZiNjkyNDVmNzgxYjNh
15
+ YzI4Mzc3NTliYTkwOTY3MzdkODE0NjAzMDI4ZmVkYzk0OWE5NmQ=
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'ForemanMco'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new(:test) do |t|
33
+ t.libs << 'lib'
34
+ t.libs << 'test'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = false
37
+ end
38
+
39
+
40
+ task :default => :test
@@ -0,0 +1,22 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
16
+ //= require scoped_search
17
+ //= require twitter/bootstrap
18
+ //= require topbar
19
+ //= require two-pane
20
+ //= require vendor
21
+ //= require about
22
+ //= require jquery.extentions
@@ -0,0 +1,49 @@
1
+ $(function() {
2
+ $('#mco_submit_multiple a').click(function(){
3
+ if ($(this).hasClass('dropdown-toggle')) { return false }
4
+ if ($(this).hasClass('disabled')) { return false }
5
+ var title = $(this).attr('data-original-title');
6
+ var url = $(this).attr('href') + "?" + $.param({host_ids: $.foremanSelectedHosts});
7
+ $('#confirmation-modal .modal-header h3').text(title);
8
+ $('#confirmation-modal .modal-body').empty().append("<img class='modal-loading' src='/assets/spinner.gif'>");
9
+ $('#confirmation-modal').modal({show: "true", backdrop: "static"});
10
+ $("#confirmation-modal .modal-body").load(url + " #content",
11
+ function(response, status, xhr) {
12
+ $("#loading").hide();
13
+ $('#submit_multiple').val('');
14
+ var b = $("#confirmation-modal .btn-primary");
15
+ if ($(response).find('#content form select').size() > 0)
16
+ b.addClass("disabled").attr("disabled", true);
17
+ else
18
+ b.removeClass("disabled").attr("disabled", false);
19
+ });
20
+ return false;
21
+ });
22
+
23
+ $('#confirmation-modal .btn-primary').click(function(){
24
+ $("#confirmation-modal form").submit();
25
+ $('#confirmation-modal').modal('hide');
26
+ });
27
+
28
+ $('#confirmation-modal .secondary').click(function(){
29
+ $('#confirmation-modal').modal('hide');
30
+ });
31
+ });
32
+
33
+ original_toggle_actions = toggle_actions
34
+ function mco_toggle_actions() {
35
+ original_toggle_actions();
36
+ var dropdown = $("ul.dropdown-menu li a.mco-filtered");
37
+ if ($.foremanSelectedHosts.length == 0) {
38
+ dropdown.each(function() {
39
+ $(this).addClass('disabled')
40
+ $(this).css({'color': 'lightgray'})
41
+ });
42
+ } else {
43
+ dropdown.each(function() {
44
+ $(this).removeClass('disabled')
45
+ $(this).css({'color': 'black'})
46
+ });
47
+ }
48
+ }
49
+ toggle_actions = mco_toggle_actions
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,26 @@
1
+ module ForemanMco
2
+ class CommandHistoriesController < ::ApplicationController
3
+ include Foreman::Controller::TaxonomyMultiple
4
+ include Foreman::Controller::AutoCompleteSearch
5
+
6
+ SEARCHABLE_ACTIONS= %w[index]
7
+
8
+ def index
9
+ begin
10
+ search = CommandStatus.search_for(params[:search],:order => params[:order])
11
+ rescue => e
12
+ error e.to_s
13
+ search = CommandStatus.search_for ''
14
+ end
15
+ @command_statuses = search.paginate(:page => params[:page])
16
+ end
17
+
18
+ def detailed
19
+ @details = HostCommandStatus.where(:command_status_id => params[:id])
20
+ end
21
+
22
+ def model_of_controller
23
+ CommandStatus
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ module ForemanMco
2
+ class CommandStatusesController < ::Api::V2::BaseController
3
+ include ::Foreman::Controller::SmartProxyAuth
4
+
5
+ add_puppetmaster_filters([:update])
6
+
7
+ before_filter :find_status, :only => [:update]
8
+ before_filter :parse_results, :only => [:update]
9
+
10
+ def update
11
+ process_response @command_status.update_attributes!(params[:command_status])
12
+ end
13
+
14
+ def find_status
15
+ @command_status = ForemanMco::CommandStatus.find_by_jid(params[:id])
16
+ render_error 'not_found', :status => :not_found and return false unless @command_status
17
+ end
18
+
19
+ def parse_results
20
+ return if params[:command_status][:result].nil?
21
+ @host_statuses = params[:command_status][:result].each {|host_status| @command_status.host_command_statuses.build(to_foreman_schema(host_status))}
22
+ end
23
+
24
+ def to_foreman_schema(a_hash)
25
+ to_ret = {}
26
+ our_schema = { "sender" => "host", "statuscode" => "status_code", "statusmsg" => "status_message", "data" => "result" }
27
+
28
+ a_hash.each_pair do |k,v|
29
+ our_schema.has_key?(k) ? to_ret[our_schema[k]] = v : to_ret[k] = v
30
+ end
31
+
32
+ to_ret
33
+ end
34
+
35
+ def require_mco_proxy_or_login
36
+ if auth_smart_proxy(SmartProxy.mcollective_proxies, false)
37
+ set_admin_user
38
+ return true
39
+ end
40
+
41
+ require_login
42
+ unless User.current
43
+ render_error 'access_denied', :status => :forbidden unless performed? and api_request?
44
+ return false
45
+ end
46
+ authorize
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,48 @@
1
+ require 'foreman_mco/commands'
2
+
3
+ module ForemanMco
4
+ class CommandsController < ::ApplicationController
5
+ COMMANDS = [:install_package, :uninstall_package, :service_status, :start_service,
6
+ :stop_service, :install_package, :uninstall_package,
7
+ :puppet_runonce, :puppet_enable, :puppet_disable,
8
+ :ping]
9
+
10
+ attr_reader :command
11
+ before_filter :find_command, :only => [:submit_command]
12
+ before_filter :filter_by_hosts, :only => COMMANDS
13
+
14
+ COMMANDS.each do |cmd|
15
+ define_method(cmd) {}
16
+ end
17
+
18
+ #TODO: a possible race condition here -- proxy *can* process remote job before we get to CommandStatus creation
19
+ def submit_command
20
+ if @command.execute
21
+ process_success :success_redirect => :back, :success_msg => _("'%s' command has been queued up for execution") % command
22
+ else
23
+ process_error :redirect => :back, :error_msg => _("'%s' command has not been queued up: %s") % [command, 'fail!']
24
+ end
25
+ rescue => e
26
+ process_error :redirect => :back, :error_msg => _("'%s' command has not been queued up: %s") % [command, e]
27
+ end
28
+
29
+ def find_command
30
+ return process_error :redirect => :back, :error_msg => _("No command to execute") unless params[:command]
31
+
32
+ command_hash = params[:command]
33
+ clazz = ("ForemanMco::Command::" + command_hash[:command].camelize).constantize
34
+ @command = clazz.new(command_hash)
35
+
36
+ return process_error(:redirect => :back, :object => @command, :error_msg => _("Invalid command parametres: %s") % command.errors.full_messages) unless @command.valid?
37
+
38
+ @command
39
+ rescue NameError => e
40
+ return process_error(:redirect => :back, :object => @command, :error_msg => _("Invalid command '%s'") % params[:command])
41
+ end
42
+
43
+ def filter_by_hosts
44
+ @hosts = params[:host_ids].nil? ? [] : Host.select(:name).where(:id => params[:host_ids])
45
+ @filters = @hosts.collect(&:name).collect {|n| ::ForemanMco::Command::Filter.identity_filter(n)}.to_json
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,27 @@
1
+ module ForemanMco
2
+ class DetailedCommandHistoriesController < ::ApplicationController
3
+ include Foreman::Controller::TaxonomyMultiple
4
+ include Foreman::Controller::AutoCompleteSearch
5
+
6
+ SEARCHABLE_ACTIONS= %w[index]
7
+
8
+ def index
9
+ begin
10
+ search = HostCommandStatus.where(:command_status_id => params[:command_history_id]).search_for(params[:search],:order => params[:order])
11
+ rescue => e
12
+ error e.to_s
13
+ search = HostCommandStatus.where(:command_status_id => params[:command_history_id])
14
+ end
15
+ @details = search.paginate(:page => params[:page])
16
+ @hosts = Host.my_hosts.select([:id, :name]).where(:name => @details.collect(&:host)).index_by(&:name)
17
+ end
18
+
19
+ def controller_name
20
+ "command_history_detailed_command_histories"
21
+ end
22
+
23
+ def model_of_controller
24
+ HostCommandStatus
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,4 @@
1
+ module ForemanMco
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module ForemanMco::CommandHistoriesHelper
2
+ def any_commands_run?
3
+ return true unless (@command_statuses.count == 0)
4
+ false
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ module ForemanMco::HostsHelper
2
+ extend ActiveSupport::Concern
3
+
4
+ def mco_multiple_actions_select
5
+ actions = []
6
+
7
+ if Setting[:use_mco]
8
+ actions << [_('Ping'), ping_commands_path, 'pencil']
9
+ actions << [_('Install Package'), install_package_commands_path, 'pencil', 'mco-filtered']
10
+ actions << [_('Uninstall Package'), uninstall_package_commands_path, 'pencil', 'mco-filtered']
11
+ actions << [_('Service Status'), service_status_commands_path, 'pencil', 'mco-filtered']
12
+ actions << [_('Start Service'), start_service_commands_path, 'pencil', 'mco-filtered']
13
+ actions << [_('Stop Service'), stop_service_commands_path, 'pencil', 'mco-filtered']
14
+ actions << [_('Puppet Runonce'), puppet_runonce_commands_path, 'pencil', 'mco-filtered']
15
+ actions << [_('Puppet Enable'), puppet_enable_commands_path, 'pencil', 'mco-filtered']
16
+ actions << [_('Puppet Disable'), puppet_disable_commands_path, 'pencil', 'mco-filtered']
17
+ end
18
+
19
+ content_tag :span, :id => 'mco_submit_multiple' do
20
+ select_action_button( _("Select MCO Action"), actions.map do |action|
21
+ link_to(icon_text(action[2], action[0]) , action[1], :class=>'btn ' + (action.try(:[], 3) || ''), :title => _("%s - The following hosts are about to be changed") % action[0])
22
+ end.flatten)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ module ForemanMco::Command
2
+ class Base
3
+ include ::ActiveModel::Validations
4
+ attr_reader :filters
5
+
6
+ def initialize(attrs = {})
7
+ @filters = attrs[:filters] || []
8
+ end
9
+
10
+ def execute
11
+ response = remote_call
12
+ ::ForemanMco::CommandStatus.create!(:command => self.to_s, :jid => response.split("/tasks/")[1])
13
+ end
14
+
15
+ def mco_proxy
16
+ return @mco_proxy if @mco_proxy
17
+
18
+ db_proxy_record = SmartProxy.joins(:features).where("features.name" => "MCollective").first
19
+ raise ::Foreman::Exception.new(N_("There are no configured mcollective proxies")) unless db_proxy_record
20
+
21
+ @mco_proxy = ForemanMco::McoProxyApi.new(:url => db_proxy_record.url)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ module ForemanMco::Command
2
+ class Filter
3
+ def self.identity_filter(val)
4
+ {:identity => val}
5
+ end
6
+
7
+ def self.class_filter(val)
8
+ {:class => val}
9
+ end
10
+
11
+ def self.fact_filter(val)
12
+ {:fact => val}
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ module ForemanMco::Command
2
+ class BasePackage < Base
3
+ include ::ActiveModel::Validations
4
+
5
+ attr_reader :package_name
6
+ validates :package_name, :presence => true
7
+
8
+ def initialize(attrs)
9
+ super
10
+ @package_name = attrs[:package_name]
11
+ end
12
+ end
13
+
14
+ class InstallPackage < BasePackage
15
+ def remote_call
16
+ mco_proxy.install_package(@package_name, filters)
17
+ end
18
+
19
+ def to_s
20
+ "package install #{package_name}"
21
+ end
22
+ end
23
+
24
+ class UninstallPackage < BasePackage
25
+ def remote_call
26
+ mco_proxy.uninstall_package(@package_name, filters)
27
+ end
28
+
29
+ def to_s
30
+ "package uninstall #{package_name}"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ module ForemanMco::Command
2
+ class Ping < Base
3
+ def remote_call
4
+ mco_proxy.ping(filters)
5
+ end
6
+
7
+ def to_s
8
+ "ping"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ module ForemanMco::Command
2
+ class PuppetRunOnce < Base
3
+ def remote_call
4
+ mco_proxy.puppet_runonce(filters)
5
+ end
6
+
7
+ def to_s
8
+ "puppet runonce"
9
+ end
10
+ end
11
+
12
+ class PuppetEnable < Base
13
+ def remote_call
14
+ mco_proxy.puppet_enable(filters)
15
+ end
16
+
17
+ def to_s
18
+ "puppet start"
19
+ end
20
+ end
21
+
22
+ class PuppetDisable < Base
23
+ def remote_call
24
+ mco_proxy.puppet_disable(filters)
25
+ end
26
+
27
+ def to_s
28
+ "puppet stop"
29
+ end
30
+ end
31
+ end