foreman_salt 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3958e07e3ba51a52ed71666da0a710088a5f33f6
4
- data.tar.gz: df6214da1df13e4ec5eea3026c5237528d88deea
3
+ metadata.gz: 763554c758fd70adb3a4feef13ceb720c6711caa
4
+ data.tar.gz: 0b86628a2277d95a26cc75bf6ef45070361c35d0
5
5
  SHA512:
6
- metadata.gz: 7d6dc7e5d6b97d0fc09ebc34df7d6172ceab5e052d779ec907fca754fd6edea1ce82df6e5c56a135dc7db91147b4953aa643b4afec3ab05dd4b1dd59b29c04d0
7
- data.tar.gz: b30c5d22dfd590fc398f26893ba1910452e9fc21b0fceca6974217c24fc58cb57142c0b586fd832ceedaeec9115f9553a5c4c88a8203662d2b8a9e39d6eb8250
6
+ metadata.gz: 8d874dcf278f82b3b5bce1da5373bc37ccd758a5ee3ab9cccca65bc7cd8e0518a74a4cb9580d47e9d3187b4b2191e9b5d4b69b102cb420b4815719344eae35de
7
+ data.tar.gz: 5fd385f82b6dd1a8f9fef3d8061e221e127123176afeda78ea07b1075092b62ac7cab162d8b143a60f4bb6f88c991657fcf3c5511602977b825fa1aa9127d37e
@@ -0,0 +1,65 @@
1
+ require 'uri'
2
+
3
+ module ForemanSalt
4
+ module Api
5
+ module V2
6
+ class JobsController < ::Api::V2::BaseController
7
+ include ::Api::Version2
8
+ include ::Foreman::Controller::SmartProxyAuth
9
+ include ForemanSalt::Concerns::SmartProxyAuthExtensions
10
+
11
+ add_puppetmaster_filters :upload
12
+
13
+ resource_description do
14
+ api_base_url "/salt/api"
15
+ end
16
+
17
+ def_param_group :job do
18
+ param :job, Hash, :required => true, :action_aware => true do
19
+ param :job_id, Integer, :required => true, :desc => N_("JID")
20
+ param :function, String, :required => true, :desc => N_("Function")
21
+ param :result, Hash, :required => true, :desc => N_("Result")
22
+ end
23
+ end
24
+
25
+ api :POST, '/upload/', N_('Upload a Job')
26
+ param_group :job, :as => :upload
27
+
28
+ def upload
29
+ Rails.logger.info("Processing job #{params[:job][:job_id]} from Salt.")
30
+ case params[:job][:function]
31
+ when 'state.highstate'
32
+ # Dynflowize the action if we can, otherwise we'll do it live
33
+ if defined? ForemanTasks
34
+ task = ForemanTasks.async_task(::Actions::ForemanSalt::ReportImport, params[:job], detected_proxy.try(:id))
35
+ render :json => {:task_id => task.id}
36
+ else
37
+ reports = ForemanSalt::ReportImporter.import(params[:job][:result], detected_proxy.try(:id))
38
+ render :json => {:message => "Imported #{reports.count} new reports."}
39
+ end
40
+ else
41
+ render :json => {:message => 'Unsupported function'}, :status => :unprocessable_entity
42
+ end
43
+ rescue ::Foreman::Exception => e
44
+ render :json => {:message => e.to_s}, :status => :unprocessable_entity
45
+ end
46
+
47
+ def resource_class
48
+ ::Report
49
+ end
50
+
51
+ private
52
+
53
+ def action_permission
54
+ case params[:action]
55
+ when 'upload'
56
+ :create
57
+ else
58
+ super
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,29 @@
1
+ module Actions
2
+ module ForemanSalt
3
+ if defined? ForemanTasks
4
+ class ReportImport < Actions::EntryAction
5
+
6
+ def resource_locks
7
+ :report_import
8
+ end
9
+
10
+ def plan(job, proxy_id)
11
+ plan_self(:job_id => job[:job_id], :report => job[:result], :proxy_id => proxy_id)
12
+ end
13
+
14
+ def run
15
+ ::User.as_anonymous_admin do
16
+ reports = ::ForemanSalt::ReportImporter.import(input[:report], input[:proxy_id])
17
+
18
+ output[:state] = {:message => "Imported #{reports.count} new reports"}
19
+ output[:hosts] = reports.map { |report| report.host.name }
20
+ end
21
+ end
22
+
23
+ def humanized_name
24
+ _("Process Highstate Report: #{input[:job_id]}")
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -51,7 +51,7 @@ module ForemanSalt
51
51
 
52
52
  def set_hostgroup_defaults_with_salt_proxy
53
53
  return unless hostgroup
54
- assign_hostgroup_attributes(%w{salt_proxy_id})
54
+ assign_hostgroup_attributes(%w{salt_proxy_id salt_environment_id})
55
55
  set_hostgroup_defaults_without_salt_proxy
56
56
  end
57
57
 
@@ -0,0 +1,152 @@
1
+ module ForemanSalt
2
+ class ReportImporter
3
+ delegate :logger, :to => :Rails
4
+ attr_reader :report
5
+
6
+ def self.import(raw, proxy_id = nil)
7
+ raise ::Foreman::Exception.new(_('Invalid report')) unless raw.is_a?(Hash)
8
+ raw.map do |host, report|
9
+ importer = ForemanSalt::ReportImporter.new(host, report, proxy_id)
10
+ importer.import
11
+ importer.report
12
+ end
13
+ end
14
+
15
+ def initialize(host, raw, proxy_id = nil)
16
+ @host = find_or_create_host(host)
17
+ @raw = raw
18
+ @proxy_id = proxy_id
19
+ end
20
+
21
+ def import
22
+ logger.info "processing report for #{@host}"
23
+ logger.debug { "Report: #{@raw.inspect}" }
24
+
25
+ if @host.new_record? && !Setting[:create_new_host_when_report_is_uploaded]
26
+ logger.info("skipping report for #{@host} as its an unknown host and create_new_host_when_report_is_uploaded setting is disabled")
27
+ return Report.new
28
+ end
29
+
30
+ @host.salt_proxy_id ||= @proxy_id
31
+ @host.last_report = start_time
32
+
33
+ if @raw.is_a? Array
34
+ process_failures # If Salt sends us only an array, it's a list of fatal failures
35
+ else
36
+ process_normal
37
+ end
38
+
39
+ @host.save(:validate => false)
40
+ logger.info("Imported report for #{@host} in #{(Time.now - start_time).round(2)} seconds")
41
+ end
42
+
43
+ private
44
+
45
+ def find_or_create_host(host)
46
+ @host ||= Host::Base.find_by_name(host)
47
+
48
+ unless @host
49
+ new = Host::Managed.new(:name => host)
50
+ new.save(:validate => false)
51
+ @host = new
52
+ end
53
+
54
+ @host
55
+ end
56
+
57
+ def import_log_messages
58
+ @raw.each do |resource, result|
59
+ level = if result['changes'].blank? && result['result']
60
+ :info
61
+ elsif result['result'] == false
62
+ :err
63
+ else
64
+ :notice
65
+ end
66
+
67
+ source = Source.find_or_create(resource)
68
+
69
+ message = if result['changes']['diff']
70
+ result['changes']['diff']
71
+ elsif !result['comment'].blank?
72
+ result['comment']
73
+ else
74
+ 'No message available'
75
+ end
76
+
77
+ message = Message.find_or_create(message)
78
+ Log.create(:message_id => message.id, :source_id => source.id, :report => @report, :level => level)
79
+ end
80
+ end
81
+
82
+ def calculate_metrics
83
+ success = 0
84
+ failed = 0
85
+ changed = 0
86
+ restarted = 0
87
+ restarted_failed = 0
88
+
89
+ time = {}
90
+
91
+ @raw.each do |resource, result|
92
+ next unless result.is_a? Hash
93
+
94
+ if result['result'] == true
95
+ success += 1
96
+ if resource.match(/^service_/) && result['comment'].include?('restarted')
97
+ restarted += 1
98
+ elsif !result['changes'].blank?
99
+ changed += 1
100
+ end
101
+ elsif result['result'] == false
102
+ if resource.match(/^service_/) && result['comment'].include?('restarted')
103
+ restarted_failed += 1
104
+ else
105
+ failed += 1
106
+ end
107
+ end
108
+
109
+ time[resource] = result['duration'] if result['duration']
110
+ end
111
+
112
+ time[:total] = time.values.inject(&:+)
113
+ events = {:total => changed + failed + restarted + restarted_failed, :success => success + restarted, :failure => failed + restarted_failed}
114
+
115
+ changes = {:total => changed + restarted}
116
+
117
+ resources = {'total' => @raw.size, 'applied' => changed, 'restarted' => restarted, 'failed' => failed,
118
+ 'failed_restarts' => restarted_failed, 'skipped' => 0, 'scheduled' => 0}
119
+
120
+ {:events => events, :resources => resources, :changes => changes, :time => time}
121
+ end
122
+
123
+ def process_normal
124
+ metrics = calculate_metrics
125
+ status = ReportStatusCalculator.new(:counters => metrics[:resources].slice(*::Report::METRIC)).calculate
126
+
127
+ @host.puppet_status = status
128
+
129
+ @report = Report.new(:host => @host, :reported_at => start_time, :status => status, :metrics => metrics)
130
+ return @report unless @report.save
131
+ import_log_messages
132
+ end
133
+
134
+
135
+ def process_failures
136
+ status = ReportStatusCalculator.new({:counters => {'failed' => @raw.size}}).calculate
137
+ @report = Report.create(:host => @host, :reported_at => Time.now, :status => status, :metrics => {})
138
+
139
+ @host.puppet_status = status
140
+
141
+ source = Source.find_or_create('Salt')
142
+ @raw.each do |failure|
143
+ message = Message.find_or_create(failure)
144
+ Log.create(:message_id => message.id, :source_id => source.id, :report => @report, :level => :err)
145
+ end
146
+ end
147
+
148
+ def start_time
149
+ @start_time ||= Time.now
150
+ end
151
+ end
152
+ end
data/config/routes.rb CHANGED
@@ -14,6 +14,10 @@ Rails.application.routes.draw do
14
14
  get 'auto_complete_search'
15
15
  end
16
16
  end
17
+
18
+ scope :api, :defaults => {:format => 'json'}, :constraints => ApiConstraints.new(:version => 2) do
19
+ match 'api/v2/jobs/upload' => 'foreman_salt/api/v2/jobs#upload', :via => :post
20
+ end
17
21
  end
18
22
 
19
23
  constraints(:smart_proxy_id => /[^\/]+/) do
data/lib/foreman_salt.rb CHANGED
@@ -1,4 +1,10 @@
1
- require "foreman_salt/engine"
1
+ require 'foreman_salt/engine'
2
+
3
+ begin
4
+ require 'foreman-tasks'
5
+ rescue LoadError
6
+ # Foreman Tasks isn't available
7
+ end
2
8
 
3
9
  module ForemanSalt
4
10
  end
@@ -10,6 +10,12 @@ module ForemanSalt
10
10
  config.autoload_paths += Dir["#{config.root}/app/services"]
11
11
  config.autoload_paths += Dir["#{config.root}/app/lib"]
12
12
 
13
+ if defined? ForemanTasks
14
+ initializer "foreman_salt.require_dynflow", :before => "foreman_tasks.initialize_dynflow" do |app|
15
+ ForemanTasks.dynflow.require!
16
+ end
17
+ end
18
+
13
19
  # Add any db migrations
14
20
  initializer "foreman_salt.load_app_instance_data" do |app|
15
21
  app.config.paths['db/migrate'] += ForemanSalt::Engine.paths['db/migrate'].existent
@@ -66,6 +72,10 @@ module ForemanSalt
66
72
  permission :view_smart_proxies_salt_autosign, {:'foreman_salt/salt_autosign' => [:index]}, :resource_type => "SmartProxy"
67
73
  end
68
74
 
75
+ security_block :api do |map|
76
+ permission :create_reports, {:'foreman_salt/api/v2/jobs' => [:upload]}, :resource_type => "Report"
77
+ end
78
+
69
79
  role "Salt admin", [:saltrun_hosts, :create_salt_modules, :view_salt_modules, :edit_salt_modules, :destroy_salt_modules,
70
80
  :view_smart_proxies_salt_keys, :destroy_smart_proxies_salt_keys, :edit_smart_proxies_salt_keys,
71
81
  :create_smart_proxies_salt_autosign, :view_smart_proxies_salt_autosign, :destroy_smart_proxies_salt_autosign,
@@ -1,3 +1,3 @@
1
1
  module ForemanSalt
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -0,0 +1,196 @@
1
+ {
2
+ "saltclient713.example.com": {
3
+ "pkg_|-postfix_|-postfix_|-installed": {
4
+ "comment": "Package postfix is already installed.",
5
+ "name": "postfix",
6
+ "start_time": "00:18:06.518702",
7
+ "result": true,
8
+ "duration": 1.575,
9
+ "__run_num__": 13,
10
+ "changes": {
11
+ },
12
+ "retcode": 2
13
+ },
14
+ "file_|-mysql_config_|-/etc/my.cnf_|-managed": {
15
+ "comment": "File /etc/my.cnf updated",
16
+ "name": "/etc/my.cnf",
17
+ "start_time": "00:18:00.901791",
18
+ "result": true,
19
+ "duration": 978.938,
20
+ "__run_num__": 6,
21
+ "changes": {
22
+ "diff": "--- \n+++ \n@@ -1,10 +1,39 @@\n-[mysqld]\n-datadir=/var/lib/mysql\n-socket=/var/lib/mysql/mysql.sock\n-user=mysql\n-# Disabling symbolic-links is recommended to prevent assorted security risks\n-symbolic-links=0\n+# DO NOT CHANGE THIS FILE!\n+# This config is generated by SALTSTACK\n+# and all change will be overrided on next salt call\n+\n+\n+[myisampack]\n+\n+[mysqlimport]\n+\n+[mysqlcheck]\n \n [mysqld_safe]\n-log-error=/var/log/mysqld.log\n-pid-file=/var/run/mysqld/mysqld.pid\n+log-error = /var/log/mysqld.log\n+pid-file = /var/run/mysqld/mysqld.pid\n+\n+[mysqladmin]\n+\n+[mysqlshow]\n+\n+[myisamchk]\n+\n+[client]\n+\n+[mysqlhotcopy]\n+\n+[mysqldump]\n+\n+[mysql]\n+\n+[mysqld]\n+bind-address = 127.0.0.1\n+datadir = /var/lib/mysql\n+port = 3306\n+socket = /var/lib/mysql/mysql.sock\n+symbolic-links = 0\n+user = mysql\n+\n+[isamchk]\n+\n"
23
+ },
24
+ "retcode": 2
25
+ },
26
+ "mysql_database_|-mysql remove test database_|-test_|-absent": {
27
+ "comment": "Database test has been removed",
28
+ "name": "test",
29
+ "start_time": "00:18:06.511324",
30
+ "result": true,
31
+ "duration": 7.266,
32
+ "__run_num__": 12,
33
+ "changes": {
34
+ "test": "Absent"
35
+ },
36
+ "retcode": 2
37
+ },
38
+ "service_|-postfix_|-postfix_|-running": {
39
+ "comment": "Service postfix is already enabled, and is in the desired state",
40
+ "name": "postfix",
41
+ "start_time": "00:18:06.520605",
42
+ "result": true,
43
+ "duration": 53.025,
44
+ "__run_num__": 14,
45
+ "changes": {
46
+ }
47
+ },
48
+ "mysql_user_|-mysql_delete_anonymous_user_saltclient713.example.com_|-_|-absent": {
49
+ "comment": "An exception occurred in this state: Traceback (most recent call last):\n File \"/usr/lib/python2.6/site-packages/salt/state.py\", line 1533, in call\n **cdata['kwargs'])\n File \"/usr/lib/python2.6/site-packages/salt/states/mysql_user.py\", line 239, in absent\n if __salt__['mysql.user_exists'](name, host, **connection_args):\n File \"/usr/lib/python2.6/site-packages/salt/modules/mysql.py\", line 1023, in user_exists\n dbc = _connect(**connection_args)\n File \"/usr/lib/python2.6/site-packages/salt/modules/mysql.py\", line 287, in _connect\n dbc = MySQLdb.connect(**connargs)\n File \"/usr/lib64/python2.6/site-packages/MySQLdb/__init__.py\", line 81, in Connect\n return Connection(*args, **kwargs)\n File \"/usr/lib64/python2.6/site-packages/MySQLdb/connections.py\", line 187, in __init__\n super(Connection, self).__init__(*args, **kwargs2)\nTypeError: connect() argument 3 must be string, not int\n",
50
+ "name": "",
51
+ "start_time": "00:18:06.510447",
52
+ "result": false,
53
+ "duration": 0.752,
54
+ "__run_num__": 11,
55
+ "changes": {
56
+ }
57
+ },
58
+ "mysql_user_|-mysql_delete_anonymous_user_localhost_|-_|-absent": {
59
+ "comment": "An exception occurred in this state: Traceback (most recent call last):\n File \"/usr/lib/python2.6/site-packages/salt/state.py\", line 1533, in call\n **cdata['kwargs'])\n File \"/usr/lib/python2.6/site-packages/salt/states/mysql_user.py\", line 239, in absent\n if __salt__['mysql.user_exists'](name, host, **connection_args):\n File \"/usr/lib/python2.6/site-packages/salt/modules/mysql.py\", line 1023, in user_exists\n dbc = _connect(**connection_args)\n File \"/usr/lib/python2.6/site-packages/salt/modules/mysql.py\", line 287, in _connect\n dbc = MySQLdb.connect(**connargs)\n File \"/usr/lib64/python2.6/site-packages/MySQLdb/__init__.py\", line 81, in Connect\n return Connection(*args, **kwargs)\n File \"/usr/lib64/python2.6/site-packages/MySQLdb/connections.py\", line 187, in __init__\n super(Connection, self).__init__(*args, **kwargs2)\nTypeError: connect() argument 3 must be string, not int\n",
60
+ "_stamp": "2014-11-16T01:18:06.783560",
61
+ "return": "Error: mysql_user.absent",
62
+ "name": "",
63
+ "success": false,
64
+ "start_time": "00:18:06.488962",
65
+ "jid": "20141116011706024672",
66
+ "duration": 19.798,
67
+ "result": false,
68
+ "fun": "state.highstate",
69
+ "__run_num__": 9,
70
+ "changes": {
71
+ },
72
+ "id": "saltclient713.example.com",
73
+ "retcode": 2
74
+ },
75
+ "service_|-mysqld_|-mysqld_|-running": {
76
+ "comment": "Service mysqld has been enabled, and is running",
77
+ "name": "mysqld",
78
+ "start_time": "00:18:01.881541",
79
+ "result": true,
80
+ "duration": 4566.262,
81
+ "__run_num__": 7,
82
+ "changes": {
83
+ "mysqld": true
84
+ }
85
+ },
86
+ "mysql_user_|-mysql_delete_anonymous_user_localhost.localdomain_|-_|-absent": {
87
+ "comment": "An exception occurred in this state: Traceback (most recent call last):\n File \"/usr/lib/python2.6/site-packages/salt/state.py\", line 1533, in call\n **cdata['kwargs'])\n File \"/usr/lib/python2.6/site-packages/salt/states/mysql_user.py\", line 239, in absent\n if __salt__['mysql.user_exists'](name, host, **connection_args):\n File \"/usr/lib/python2.6/site-packages/salt/modules/mysql.py\", line 1023, in user_exists\n dbc = _connect(**connection_args)\n File \"/usr/lib/python2.6/site-packages/salt/modules/mysql.py\", line 287, in _connect\n dbc = MySQLdb.connect(**connargs)\n File \"/usr/lib64/python2.6/site-packages/MySQLdb/__init__.py\", line 81, in Connect\n return Connection(*args, **kwargs)\n File \"/usr/lib64/python2.6/site-packages/MySQLdb/connections.py\", line 187, in __init__\n super(Connection, self).__init__(*args, **kwargs2)\nTypeError: connect() argument 3 must be string, not int\n",
88
+ "name": "",
89
+ "start_time": "00:18:06.509230",
90
+ "result": false,
91
+ "duration": 0.8,
92
+ "__run_num__": 10,
93
+ "changes": {
94
+ }
95
+ },
96
+ "pkg_|-mysqld_|-mysql-server_|-installed": {
97
+ "comment": "The following packages were installed/updated: mysql-server.",
98
+ "name": "mysql-server",
99
+ "start_time": "00:17:41.058929",
100
+ "result": true,
101
+ "duration": 19842.654,
102
+ "__run_num__": 5,
103
+ "changes": {
104
+ "perl-DBI": {
105
+ "new": "1.609-4.el6",
106
+ "old": ""
107
+ },
108
+ "perl-DBD-MySQL": {
109
+ "new": "4.013-3.el6",
110
+ "old": ""
111
+ },
112
+ "mysql-server": {
113
+ "new": "5.1.73-3.el6_5",
114
+ "old": ""
115
+ },
116
+ "mysql": {
117
+ "new": "5.1.73-3.el6_5",
118
+ "old": ""
119
+ }
120
+ }
121
+ },
122
+ "cmd_|-mysql_root_password_|-mysqladmin --user root password '434510094'_|-run": {
123
+ "comment": "Command \"mysqladmin --user root password '434510094'\" run",
124
+ "name": "mysqladmin --user root password '434510094'",
125
+ "start_time": "00:18:06.448367",
126
+ "result": true,
127
+ "duration": 39.196,
128
+ "__run_num__": 8,
129
+ "changes": {
130
+ "pid": 2709,
131
+ "retcode": 0,
132
+ "stderr": "",
133
+ "stdout": ""
134
+ }
135
+ },
136
+ "pkg_|-mysql_python_|-MySQL-python_|-installed": {
137
+ "comment": "The following packages were installed/updated: MySQL-python.",
138
+ "name": "MySQL-python",
139
+ "start_time": "00:17:14.059753",
140
+ "result": true,
141
+ "duration": 26997.765,
142
+ "__run_num__": 4,
143
+ "changes": {
144
+ "MySQL-python": {
145
+ "new": "1.2.3-0.3.c1.1.el6",
146
+ "old": ""
147
+ }
148
+ },
149
+ "retcode": 2
150
+ },
151
+ "file_|-enable_epel_|-/etc/yum.repos.d/epel.repo_|-sed": {
152
+ "comment": "sed ran without error",
153
+ "name": "/etc/yum.repos.d/epel.repo",
154
+ "start_time": "00:17:14.024416",
155
+ "result": true,
156
+ "duration": 35.098,
157
+ "__run_num__": 3,
158
+ "changes": {
159
+ "diff": "--- \n+++ \n@@ -12,7 +12,7 @@\n #baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch/debug\n mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-debug-6&arch=$basearch\n failovermethod=priority\n-enabled=0\n+enabled=1\n gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6\n gpgcheck=1\n \n@@ -21,6 +21,6 @@\n #baseurl=http://download.fedoraproject.org/pub/epel/6/SRPMS\n mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-source-6&arch=$basearch\n failovermethod=priority\n-enabled=0\n+enabled=1\n gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6\n gpgcheck=1\n"
160
+ }
161
+ },
162
+ "pkg_|-epel_release_|-epel_release_|-installed": {
163
+ "comment": "All specified packages are already installed.",
164
+ "name": "epel_release",
165
+ "start_time": "00:17:13.178528",
166
+ "result": true,
167
+ "duration": 845.684,
168
+ "__run_num__": 2,
169
+ "changes": {
170
+ }
171
+ },
172
+ "file_|-/etc/motd_|-/etc/motd_|-managed": {
173
+ "comment": "File /etc/motd updated",
174
+ "name": "/etc/motd",
175
+ "start_time": "00:17:11.971247",
176
+ "result": true,
177
+ "duration": 163.144,
178
+ "__run_num__": 0,
179
+ "changes": {
180
+ "diff": "--- \n+++ \n@@ -1,0 +1,7 @@\n+_| _| _| _| _|\n+_|_|_| _|_|_|_| _|_|_| _|_|_|\n+_| _| _| _| _| _| _| _| _|\n+_| _| _| _| _| _| _| _| _|\n+_|_|_| _| _|_| _|_|_| _| _| _|\n+\n+saltclient713.example.com\n"
181
+ }
182
+ },
183
+ "file_|-install_pubkey_|-/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL_|-managed": {
184
+ "comment": "File /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL updated",
185
+ "name": "/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL",
186
+ "start_time": "00:17:12.134782",
187
+ "result": true,
188
+ "duration": 1042.983,
189
+ "__run_num__": 1,
190
+ "changes": {
191
+ "diff": "New file",
192
+ "mode": "0644"
193
+ }
194
+ }
195
+ }
196
+ }
@@ -0,0 +1,32 @@
1
+ require 'test_plugin_helper'
2
+
3
+ module ForemanSalt
4
+ class ReportImporterTest < ActiveSupport::TestCase
5
+ setup do
6
+ User.current = User.find_by_login 'admin'
7
+ Setting[:create_new_host_when_facts_are_uploaded] = true
8
+
9
+ @report = JSON.parse(File.read(File.join(Engine.root, 'test', 'unit', 'highstate.json')))
10
+
11
+ @host = 'saltclient713.example.com'
12
+ end
13
+
14
+ test 'importing report creates a host' do
15
+ refute Host.find_by_name(@host)
16
+ ForemanSalt::ReportImporter.import(@report)
17
+ assert Host.find_by_name(@host)
18
+ end
19
+
20
+ test "importing report updates host status" do
21
+ ForemanSalt::ReportImporter.import(@report)
22
+ assert_equal Host.find_by_name(@host).host_status, 'Error'
23
+ end
24
+
25
+ test 'importing report has correct status' do
26
+ ForemanSalt::ReportImporter.import(@report)
27
+ status = Host.find_by_name(@host).reports.last.status
28
+ assert_equal status['applied'], 9
29
+ assert_equal status['failed'], 3
30
+ end
31
+ end
32
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_salt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Benjamin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-11 00:00:00.000000000 Z
11
+ date: 2014-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -52,6 +52,7 @@ files:
52
52
  - app/views/foreman_salt/salt_autosign/new.html.erb
53
53
  - app/views/foreman_salt/salt_autosign/_form.html.erb
54
54
  - app/services/foreman_salt/smart_proxies/salt_keys.rb
55
+ - app/services/foreman_salt/report_importer.rb
55
56
  - app/services/foreman_salt/fact_importer.rb
56
57
  - app/models/foreman_salt/salt_module.rb
57
58
  - app/models/foreman_salt/concerns/hostgroup_extensions.rb
@@ -67,8 +68,10 @@ files:
67
68
  - app/controllers/foreman_salt/concerns/smart_proxy_auth_extensions.rb
68
69
  - app/controllers/foreman_salt/concerns/hosts_controller_extensions.rb
69
70
  - app/controllers/foreman_salt/concerns/unattended_controller_extensions.rb
71
+ - app/controllers/foreman_salt/api/v2/jobs_controller.rb
70
72
  - app/controllers/foreman_salt/salt_environments_controller.rb
71
73
  - app/lib/proxy_api/salt.rb
74
+ - app/lib/actions/foreman_salt/report_import.rb
72
75
  - config/routes.rb
73
76
  - db/seeds.d/75-salt-seeds.rb
74
77
  - db/migrate/20140920232200_create_salt_environments.rb
@@ -90,8 +93,10 @@ files:
90
93
  - test/unit/grains_centos.json
91
94
  - test/unit/host_extensions_test.rb
92
95
  - test/unit/salt_modules_test.rb
96
+ - test/unit/highstate.json
93
97
  - test/unit/grains_importer_test.rb
94
98
  - test/unit/hostgroup_extensions_test.rb
99
+ - test/unit/report_importer_test.rb
95
100
  - test/test_plugin_helper.rb
96
101
  - test/factories/foreman_salt_factories.rb
97
102
  - test/functional/hosts_controller_test.rb
@@ -128,8 +133,10 @@ test_files:
128
133
  - test/unit/grains_centos.json
129
134
  - test/unit/host_extensions_test.rb
130
135
  - test/unit/salt_modules_test.rb
136
+ - test/unit/highstate.json
131
137
  - test/unit/grains_importer_test.rb
132
138
  - test/unit/hostgroup_extensions_test.rb
139
+ - test/unit/report_importer_test.rb
133
140
  - test/test_plugin_helper.rb
134
141
  - test/factories/foreman_salt_factories.rb
135
142
  - test/functional/hosts_controller_test.rb