foreman_salt 13.2.4 → 14.0.0
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.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/app/controllers/foreman_salt/api/v2/salt_autosign_controller.rb +31 -1
- data/app/lib/proxy_api/salt.rb +16 -2
- data/app/models/foreman_salt/concerns/host_managed_extensions.rb +64 -15
- data/app/models/foreman_salt/salt_status.rb +12 -0
- data/app/services/foreman_salt/report_importer.rb +1 -1
- data/config/routes.rb +1 -0
- data/db/migrate/20210312150333_add_salt_autosign_to_host.rb +6 -0
- data/db/seeds.d/76-job_templates.rb +1 -1
- data/lib/foreman_salt/engine.rb +2 -4
- data/lib/foreman_salt/extensions.rb +0 -3
- data/lib/foreman_salt/version.rb +1 -1
- data/test/functional/api/v2/salt_autosign_controller_test.rb +2 -0
- data/test/integration/salt_autosign_test.rb +2 -2
- data/test/integration/salt_keys_test.rb +2 -3
- data/test/unit/host_extensions_test.rb +55 -11
- metadata +6 -13
- data/app/models/foreman_salt/fact_name.rb +0 -14
- data/app/services/foreman_salt/fact_importer.rb +0 -15
- data/app/services/foreman_salt/fact_parser.rb +0 -114
- data/test/unit/grains_centos.json +0 -113
- data/test/unit/salt_fact_importer_test.rb +0 -24
- data/test/unit/salt_fact_parser_test.rb +0 -44
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 287507e11ca2f63bc8341eae5bc832e7d95ad5b848922b9eba44b85486fd9dc3
|
|
4
|
+
data.tar.gz: e1a70ace048abbcf30d57e0631f8b1ad1627bbad3c5261b2196d0a92663ef833
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08395ab98cb79f8dfc725268cfcb9dc8b11c015562625ea56f90315edaa9bcf1c76601d123481d57eed865212cc7212cfa36be6ea1506d8e59d1ac15afaa5f2b'
|
|
7
|
+
data.tar.gz: f7a59b6f52e80340520a8ed4523e39727659612a737fb848c33731013684f09dcbe83e27c02c928a22614f18842120ce3d53908bc2ec4176a153bb69c2124527
|
data/README.md
CHANGED
|
@@ -4,7 +4,15 @@ module ForemanSalt
|
|
|
4
4
|
module Api
|
|
5
5
|
module V2
|
|
6
6
|
class SaltAutosignController < ::ForemanSalt::Api::V2::BaseController
|
|
7
|
-
|
|
7
|
+
include ::Foreman::Controller::SmartProxyAuth
|
|
8
|
+
include ::Foreman::Controller::Parameters::Host
|
|
9
|
+
|
|
10
|
+
# The add_smart_proxy_filters must be executed first! Otherwise, resource_finder won't work properly
|
|
11
|
+
add_smart_proxy_filters :auth
|
|
12
|
+
|
|
13
|
+
before_action :find_proxy, except: [:auth]
|
|
14
|
+
before_action :find_host, :find_proxy_via_host, only: [:auth]
|
|
15
|
+
before_action :setup_proxy
|
|
8
16
|
|
|
9
17
|
api :GET, '/salt_autosign/:smart_proxy_id', N_('List all autosign records')
|
|
10
18
|
param :smart_proxy_id, :identifier_dottable, :required => true
|
|
@@ -28,6 +36,18 @@ module ForemanSalt
|
|
|
28
36
|
render :json => { root_node_name => _('Record deleted.') }
|
|
29
37
|
end
|
|
30
38
|
|
|
39
|
+
api :PUT, '/salt_autosign_auth', N_("Set the salt_status as \'successful authentication\' and remove the corresponding autosign key from the Smart Proxy")
|
|
40
|
+
param :name, String, :required => true
|
|
41
|
+
def auth
|
|
42
|
+
Rails.logger.info("Removing Salt autosign key and update status for host #{@host}")
|
|
43
|
+
@api.autosign_remove_key(@host.salt_autosign_key) unless @host.salt_autosign_key.nil?
|
|
44
|
+
@host.update(:salt_status => ForemanSalt::SaltStatus.minion_auth_success)
|
|
45
|
+
render :json => { :message => "Removed autosign key and updated status succesfully" }, :status => 204
|
|
46
|
+
rescue ::Foreman::Exception => e
|
|
47
|
+
Rails.logger.warn("Cannot delete autosign key of host (id => #{params[:name]}) state: #{e}")
|
|
48
|
+
render :json => { :message => e.to_s }, :status => :unprocessable_entity
|
|
49
|
+
end
|
|
50
|
+
|
|
31
51
|
def metadata_total
|
|
32
52
|
@total ||= all_autosign.count
|
|
33
53
|
end
|
|
@@ -50,11 +70,21 @@ module ForemanSalt
|
|
|
50
70
|
@_autosigns ||= @api.autosign_list.map { |record| OpenStruct.new(:record => record) }
|
|
51
71
|
end
|
|
52
72
|
|
|
73
|
+
def find_host
|
|
74
|
+
@host = resource_finder(Host.authorized(:view_hosts), params[:name])
|
|
75
|
+
not_found unless @host
|
|
76
|
+
end
|
|
77
|
+
|
|
53
78
|
def find_proxy
|
|
54
79
|
@proxy = ::SmartProxy.friendly.find(params[:smart_proxy_id])
|
|
55
80
|
not_found unless @proxy
|
|
56
81
|
end
|
|
57
82
|
|
|
83
|
+
def find_proxy_via_host
|
|
84
|
+
@proxy = ::SmartProxy.friendly.find(@host.salt_proxy.id)
|
|
85
|
+
not_found unless @proxy
|
|
86
|
+
end
|
|
87
|
+
|
|
58
88
|
def setup_proxy
|
|
59
89
|
@api = ProxyAPI::Salt.new(:url => @proxy.url)
|
|
60
90
|
end
|
data/app/lib/proxy_api/salt.rb
CHANGED
|
@@ -14,7 +14,7 @@ module ::ProxyAPI
|
|
|
14
14
|
def autosign_create(name)
|
|
15
15
|
parse(post('', "autosign/#{URI.escape(name)}"))
|
|
16
16
|
rescue => e
|
|
17
|
-
raise ProxyException.new(url, e, N_('Unable to set Salt autosign for %s'), name)
|
|
17
|
+
raise ProxyException.new(url, e, N_('Unable to set Salt autosign hostname for %s'), name)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def autosign_remove(name)
|
|
@@ -22,7 +22,21 @@ module ::ProxyAPI
|
|
|
22
22
|
rescue RestClient::ResourceNotFound
|
|
23
23
|
true # entry doesn't exists anyway
|
|
24
24
|
rescue => e
|
|
25
|
-
raise ProxyException.new(url, e, N_('Unable to delete Salt autosign for %s'), name)
|
|
25
|
+
raise ProxyException.new(url, e, N_('Unable to delete Salt autosign hostname for %s'), name)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def autosign_create_key(key)
|
|
29
|
+
parse(post('', "autosign_key/#{URI.escape(key)}"))
|
|
30
|
+
rescue => e
|
|
31
|
+
raise ProxyException.new(url, e, N_('Unable to create Salt autosign key %s'), key)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def autosign_remove_key(key)
|
|
35
|
+
parse(delete("autosign_key/#{URI.escape(key)}"))
|
|
36
|
+
rescue RestClient::ResourceNotFound
|
|
37
|
+
true # entry doesn't exists anyway
|
|
38
|
+
rescue => e
|
|
39
|
+
raise ProxyException.new(url, e, N_('Unable to delete Salt autosign key %s'), key)
|
|
26
40
|
end
|
|
27
41
|
|
|
28
42
|
def environments_list
|
|
@@ -42,9 +42,8 @@ module ForemanSalt
|
|
|
42
42
|
|
|
43
43
|
validate :salt_modules_in_host_environment
|
|
44
44
|
|
|
45
|
-
after_build
|
|
46
|
-
|
|
47
|
-
before_destroy :delete_salt_key, :if => ->(host) { host.salt_proxy }
|
|
45
|
+
after_build :ensure_salt_autosign, :if => ->(host) { host.salt_proxy }
|
|
46
|
+
before_destroy :remove_salt_minion, :if => ->(host) { host.salt_proxy }
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
def salt_params
|
|
@@ -58,6 +57,14 @@ module ForemanSalt
|
|
|
58
57
|
end
|
|
59
58
|
end
|
|
60
59
|
|
|
60
|
+
def host_params_grains_name
|
|
61
|
+
"salt_grains"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def autosign_grain_name
|
|
65
|
+
"autosign_key"
|
|
66
|
+
end
|
|
67
|
+
|
|
61
68
|
def salt_modules_for_enc
|
|
62
69
|
all_salt_modules.collect(&:name).uniq
|
|
63
70
|
end
|
|
@@ -95,24 +102,66 @@ module ForemanSalt
|
|
|
95
102
|
end
|
|
96
103
|
end
|
|
97
104
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def accept_salt_key
|
|
105
|
+
def derive_salt_grains(use_autosign: False)
|
|
106
|
+
grains = {}
|
|
101
107
|
begin
|
|
102
|
-
Rails.logger.info("
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
Rails.logger.info("Derive Salt Grains from host_params and autosign_key")
|
|
109
|
+
grains[autosign_grain_name] = salt_autosign_key if use_autosign && !salt_autosign_key.nil?
|
|
110
|
+
unless host_params[host_params_grains_name].nil? ||
|
|
111
|
+
host_params[host_params_grains_name].class != Hash
|
|
112
|
+
grains.merge!(host_params[host_params_grains_name])
|
|
113
|
+
end
|
|
105
114
|
rescue Foreman::Exception => e
|
|
106
|
-
Rails.logger.warn("Unable to
|
|
115
|
+
Rails.logger.warn("Unable to derive Salt Grains: #{e}")
|
|
107
116
|
end
|
|
117
|
+
grains
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
private
|
|
121
|
+
|
|
122
|
+
def ensure_salt_autosign
|
|
123
|
+
remove_salt_autosign
|
|
124
|
+
create_salt_autosign
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def remove_salt_minion
|
|
128
|
+
remove_salt_autosign
|
|
129
|
+
remove_salt_key
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def remove_salt_key
|
|
133
|
+
Rails.logger.info("Remove salt key for host #{fqdn}")
|
|
134
|
+
api = ProxyAPI::Salt.new(:url => salt_proxy.url)
|
|
135
|
+
api.key_delete(name)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def remove_salt_autosign
|
|
139
|
+
key = self.salt_autosign_key
|
|
140
|
+
unless key.nil?
|
|
141
|
+
Rails.logger.info("Remove salt autosign key for host #{fqdn}")
|
|
142
|
+
begin
|
|
143
|
+
api = ProxyAPI::Salt.new(:url => salt_proxy.url)
|
|
144
|
+
api.autosign_remove_key(key)
|
|
145
|
+
rescue Foreman::Exception => e
|
|
146
|
+
Rails.logger.warn("Unable to remove salt autosign for #{fqdn}: #{e}")
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def generate_provisioning_key
|
|
152
|
+
SecureRandom.hex(10)
|
|
108
153
|
end
|
|
109
154
|
|
|
110
|
-
def
|
|
155
|
+
def create_salt_autosign
|
|
111
156
|
begin
|
|
112
|
-
key
|
|
113
|
-
|
|
157
|
+
Rails.logger.info("Create salt autosign key for host #{fqdn}")
|
|
158
|
+
api = ProxyAPI::Salt.new(:url => salt_proxy.url)
|
|
159
|
+
key = generate_provisioning_key
|
|
160
|
+
api.autosign_create_key(key)
|
|
161
|
+
update(:salt_autosign_key => key)
|
|
162
|
+
update(:salt_status => ForemanSalt::SaltStatus.minion_auth_waiting)
|
|
114
163
|
rescue Foreman::Exception => e
|
|
115
|
-
Rails.logger.warn("Unable to
|
|
164
|
+
Rails.logger.warn("Unable to create salt autosign for #{fqdn}: #{e}")
|
|
116
165
|
end
|
|
117
166
|
end
|
|
118
167
|
end
|
|
@@ -120,5 +169,5 @@ module ForemanSalt
|
|
|
120
169
|
end
|
|
121
170
|
|
|
122
171
|
class ::Host::Managed::Jail < Safemode::Jail
|
|
123
|
-
allow :salt_environment
|
|
172
|
+
allow :salt_environment, :salt_master, :derive_salt_grains
|
|
124
173
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module ForemanSalt
|
|
2
|
+
# Define the class that holds different states a Salt host become
|
|
3
|
+
class SaltStatus
|
|
4
|
+
def self.minion_auth_waiting
|
|
5
|
+
'Waiting for Salt Minion to authenticate'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.minion_auth_success
|
|
9
|
+
'Salt Minion was authenticated successfully to Salt Master'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -43,7 +43,7 @@ module ForemanSalt
|
|
|
43
43
|
|
|
44
44
|
@host.save(:validate => false)
|
|
45
45
|
@host.reload
|
|
46
|
-
@host.refresh_statuses
|
|
46
|
+
@host.refresh_statuses([HostStatus.find_status_by_humanized_name("configuration")])
|
|
47
47
|
|
|
48
48
|
logger.info("Imported report for #{@host} in #{(Time.zone.now - start_time).round(2)} seconds")
|
|
49
49
|
end
|
data/config/routes.rb
CHANGED
|
@@ -38,6 +38,7 @@ Rails.application.routes.draw do
|
|
|
38
38
|
scope '(:apiv)', :defaults => { :apiv => 'v2' },
|
|
39
39
|
:apiv => /v1|v2/, :constraints => ApiConstraints.new(:version => 2) do
|
|
40
40
|
match '/jobs/upload' => 'foreman_salt/api/v2/jobs#upload', :via => :post
|
|
41
|
+
match '/salt_autosign_auth' => 'foreman_salt/api/v2/salt_autosign#auth', :via => :put
|
|
41
42
|
|
|
42
43
|
constraints(:smart_proxy_id => /[\w\.-]+/, :name => /[\w\.-]+/, :record => /[^\/]+/) do
|
|
43
44
|
match '/salt_keys/:smart_proxy_id' => 'foreman_salt/api/v2/salt_keys#index', :via => :get
|
|
@@ -20,7 +20,7 @@ if ForemanSalt.with_remote_execution?
|
|
|
20
20
|
sync = !Rails.env.test? && Setting[:remote_execution_sync_templates]
|
|
21
21
|
template = JobTemplate.import_raw!(File.read(template),
|
|
22
22
|
:default => true,
|
|
23
|
-
:
|
|
23
|
+
:lock => true,
|
|
24
24
|
:update => sync)
|
|
25
25
|
template.organizations = organizations if template.present?
|
|
26
26
|
template.locations = locations if template.present?
|
data/lib/foreman_salt/engine.rb
CHANGED
|
@@ -38,16 +38,14 @@ module ForemanSalt
|
|
|
38
38
|
|
|
39
39
|
initializer 'foreman_salt.assets.precompile' do |app|
|
|
40
40
|
app.config.assets.precompile += %w(foreman_salt/states.js)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
initializer 'foreman_salt.assets.precompile' do |app|
|
|
44
41
|
app.config.assets.precompile += %w[foreman_salt/Salt.png]
|
|
45
42
|
end
|
|
46
43
|
|
|
47
44
|
initializer 'foreman_salt.configure_assets', :group => :assets do
|
|
48
45
|
SETTINGS[:foreman_salt] = {
|
|
49
46
|
:assets => {
|
|
50
|
-
:precompile => ['foreman_salt/
|
|
47
|
+
:precompile => ['foreman_salt/Salt.png',
|
|
48
|
+
'foreman_salt/states.js']
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
51
|
end
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
begin
|
|
2
|
-
::Foreman::Plugin.fact_importer_registry.register(:foreman_salt, ForemanSalt::FactImporter)
|
|
3
|
-
::FactParser.register_fact_parser(:foreman_salt, ForemanSalt::FactParser)
|
|
4
|
-
|
|
5
2
|
# Helper Extensions
|
|
6
3
|
::HostsHelper.send :include, ForemanSalt::HostsHelperExtensions
|
|
7
4
|
::SmartProxiesHelper.send :include, ForemanSalt::SmartProxiesHelperExtensions
|
data/lib/foreman_salt/version.rb
CHANGED
|
@@ -3,6 +3,8 @@ require 'test_plugin_helper'
|
|
|
3
3
|
class ::ForemanSalt::Api::V2::SaltAutosignControllerTest < ActionController::TestCase
|
|
4
4
|
setup do
|
|
5
5
|
@proxy = FactoryBot.create(:smart_proxy, :with_salt_feature)
|
|
6
|
+
@host = FactoryBot.create(:host, :managed)
|
|
7
|
+
@host.salt_proxy = @proxy
|
|
6
8
|
ProxyAPI::Salt.any_instance.stubs(:autosign_list).returns((%w(foo bar baz)))
|
|
7
9
|
end
|
|
8
10
|
|
|
@@ -19,13 +19,13 @@ module ForemanSalt
|
|
|
19
19
|
visit smart_proxy_path(@proxy)
|
|
20
20
|
assert page.has_link? "Salt Autosign"
|
|
21
21
|
click_link "Salt Autosign"
|
|
22
|
-
assert page.
|
|
22
|
+
assert page.has_title?("Autosign entries for #{@proxy.hostname}"), 'Page title does not appear'
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
test 'index page' do
|
|
26
26
|
visit smart_proxy_salt_autosign_index_path(:smart_proxy_id => @proxy.id)
|
|
27
27
|
assert find_link('Keys').visible?, 'Keys is not visible'
|
|
28
|
-
assert
|
|
28
|
+
assert has_title?("Autosign entries for #{@proxy.hostname}"), 'Page title does not appear'
|
|
29
29
|
assert has_content?('Displaying'), 'Pagination "Display ..." does not appear'
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -22,13 +22,12 @@ module ForemanSalt
|
|
|
22
22
|
visit smart_proxy_path(@proxy)
|
|
23
23
|
assert page.has_link? "Salt Keys"
|
|
24
24
|
click_link "Salt Keys"
|
|
25
|
-
assert page.
|
|
25
|
+
assert page.has_title?("Salt Keys on #{@proxy}"), 'Page title does not appear'
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
test 'index page' do
|
|
29
29
|
visit smart_proxy_salt_keys_path(:smart_proxy_id => @proxy.id)
|
|
30
|
-
assert
|
|
31
|
-
assert has_content?("Salt Keys on #{@proxy.hostname}"), 'Page title does not appear'
|
|
30
|
+
assert has_title?("Salt Keys on #{@proxy}"), 'Page title does not appear'
|
|
32
31
|
assert has_content?('Displaying'), 'Pagination "Display ..." does not appear'
|
|
33
32
|
end
|
|
34
33
|
|
|
@@ -56,23 +56,67 @@ module ForemanSalt
|
|
|
56
56
|
assert host.configuration?
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
context '
|
|
59
|
+
context 'autosign handling' do
|
|
60
60
|
before do
|
|
61
|
-
@host = FactoryBot.create(:host, :managed
|
|
61
|
+
@host = FactoryBot.create(:host, :managed)
|
|
62
62
|
@host.salt_proxy = @proxy
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
stub_request(:post, "#{@proxy.url}/salt/autosign_key/asdfasdfasfasdf").
|
|
64
|
+
to_return(status: 200, body: "", headers: {})
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
test 'host
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@host.
|
|
67
|
+
test 'host autosign is created when host is built' do
|
|
68
|
+
autosign_key = "asdfasdfasfasdf"
|
|
69
|
+
@host.expects(:generate_provisioning_key).returns(autosign_key)
|
|
70
|
+
@host.build = true
|
|
71
|
+
assert @host.save!
|
|
72
|
+
@host.clear_host_parameters_cache!
|
|
73
|
+
assert_equal autosign_key, @host.salt_autosign_key
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context 'function derive_salt_grains' do
|
|
78
|
+
before do
|
|
79
|
+
@host = FactoryBot.create(:host, :managed)
|
|
80
|
+
@host.salt_proxy = @proxy
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
test 'host returns autosign when deriving salt grains' do
|
|
84
|
+
autosign_key = "asdfasdfasfasdf"
|
|
85
|
+
expected_hash = { @host.autosign_grain_name => autosign_key }
|
|
86
|
+
@host.salt_autosign_key = autosign_key
|
|
87
|
+
assert_equal expected_hash, @host.instance_eval { derive_salt_grains(:use_autosign => true) }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
test 'host returns empty hash when deriving salt grains without any given' do
|
|
91
|
+
expected_hash = {}
|
|
92
|
+
assert_equal expected_hash, @host.instance_eval { derive_salt_grains(:use_autosign => true) }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
test 'host returns empty hash when deriving salt grains without autosign' do
|
|
96
|
+
expected_hash = {}
|
|
97
|
+
assert_equal expected_hash, @host.instance_eval { derive_salt_grains(:use_autosign => false) }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
test 'host returns host param grains when deriving salt grains' do
|
|
101
|
+
expected_hash = { "Some key": "Some value", "Another key": "An extraordinary value" }
|
|
102
|
+
@host.host_params[@host.host_params_grains_name] = expected_hash
|
|
103
|
+
assert_equal expected_hash, @host.instance_eval { derive_salt_grains(:use_autosign => false) }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
test 'host returns only host param grains when deriving salt grains' do
|
|
107
|
+
expected_hash = { "Some key": "Some value", "Another key": "An extraordinary value" }
|
|
108
|
+
@host.host_params[@host.host_params_grains_name] = expected_hash
|
|
109
|
+
assert_equal expected_hash, @host.instance_eval { derive_salt_grains(:use_autosign => true) }
|
|
71
110
|
end
|
|
72
111
|
|
|
73
|
-
test 'host
|
|
74
|
-
|
|
75
|
-
|
|
112
|
+
test 'host returns host param grains plus autosign when deriving salt grains' do
|
|
113
|
+
autosign_key = "asdfasdfasfasdf"
|
|
114
|
+
host_param_grains = { "Some key": "Some value",
|
|
115
|
+
"Another key": "An extraordinary value" }
|
|
116
|
+
expected_hash = host_param_grains.merge(@host.autosign_grain_name => autosign_key)
|
|
117
|
+
@host.salt_autosign_key = autosign_key
|
|
118
|
+
@host.host_params[@host.host_params_grains_name] = host_param_grains
|
|
119
|
+
assert_equal expected_hash, @host.instance_eval { derive_salt_grains(:use_autosign => true) }
|
|
76
120
|
end
|
|
77
121
|
end
|
|
78
122
|
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:
|
|
4
|
+
version: 14.0.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:
|
|
11
|
+
date: 2021-08-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: deface
|
|
@@ -56,14 +56,14 @@ dependencies:
|
|
|
56
56
|
name: rubocop
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- - "
|
|
59
|
+
- - ">="
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
61
|
version: 0.71.0
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
|
-
- - "
|
|
66
|
+
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: 0.71.0
|
|
69
69
|
description: Foreman Plug-in for Salt
|
|
@@ -110,21 +110,19 @@ files:
|
|
|
110
110
|
- app/lib/proxy_api/salt.rb
|
|
111
111
|
- app/models/foreman_salt/concerns/host_managed_extensions.rb
|
|
112
112
|
- app/models/foreman_salt/concerns/hostgroup_extensions.rb
|
|
113
|
-
- app/models/foreman_salt/fact_name.rb
|
|
114
113
|
- app/models/foreman_salt/host_salt_module.rb
|
|
115
114
|
- app/models/foreman_salt/hostgroup_salt_module.rb
|
|
116
115
|
- app/models/foreman_salt/salt_environment.rb
|
|
117
116
|
- app/models/foreman_salt/salt_module.rb
|
|
118
117
|
- app/models/foreman_salt/salt_module_environment.rb
|
|
119
118
|
- app/models/foreman_salt/salt_provider.rb
|
|
119
|
+
- app/models/foreman_salt/salt_status.rb
|
|
120
120
|
- app/models/foreman_salt/salt_variable.rb
|
|
121
121
|
- app/models/setting/salt.rb
|
|
122
122
|
- app/overrides/salt_environment_host_selector.rb
|
|
123
123
|
- app/overrides/salt_environment_hostgroup_selector.rb
|
|
124
124
|
- app/overrides/salt_modules_selector.rb
|
|
125
125
|
- app/overrides/salt_proxy_selector.rb
|
|
126
|
-
- app/services/foreman_salt/fact_importer.rb
|
|
127
|
-
- app/services/foreman_salt/fact_parser.rb
|
|
128
126
|
- app/services/foreman_salt/report_importer.rb
|
|
129
127
|
- app/services/foreman_salt/smart_proxies/salt_keys.rb
|
|
130
128
|
- app/views/foreman_salt/api/v2/salt_autosign/base.json.rabl
|
|
@@ -190,6 +188,7 @@ files:
|
|
|
190
188
|
- db/migrate/20150509101505_add_primary_keys.rb
|
|
191
189
|
- db/migrate/20161103104146_add_index_to_join_tables.rb
|
|
192
190
|
- db/migrate/20190515112233_add_salt_module_id_to_lookup_keys.rb
|
|
191
|
+
- db/migrate/20210312150333_add_salt_autosign_to_host.rb
|
|
193
192
|
- db/seeds.d/75-salt_seeds.rb
|
|
194
193
|
- db/seeds.d/76-job_templates.rb
|
|
195
194
|
- lib/foreman_salt.rb
|
|
@@ -258,15 +257,12 @@ files:
|
|
|
258
257
|
- test/integration/salt_module_test.rb
|
|
259
258
|
- test/integration/salt_variable_test.rb
|
|
260
259
|
- test/test_plugin_helper.rb
|
|
261
|
-
- test/unit/grains_centos.json
|
|
262
260
|
- test/unit/grains_importer_test.rb
|
|
263
261
|
- test/unit/highstate.json
|
|
264
262
|
- test/unit/highstate_pchanges.json
|
|
265
263
|
- test/unit/host_extensions_test.rb
|
|
266
264
|
- test/unit/hostgroup_extensions_test.rb
|
|
267
265
|
- test/unit/report_importer_test.rb
|
|
268
|
-
- test/unit/salt_fact_importer_test.rb
|
|
269
|
-
- test/unit/salt_fact_parser_test.rb
|
|
270
266
|
- test/unit/salt_keys_test.rb
|
|
271
267
|
- test/unit/salt_modules_test.rb
|
|
272
268
|
- test/unit/salt_variables_test.rb
|
|
@@ -306,10 +302,7 @@ test_files:
|
|
|
306
302
|
- test/unit/highstate_pchanges.json
|
|
307
303
|
- test/unit/hostgroup_extensions_test.rb
|
|
308
304
|
- test/unit/highstate.json
|
|
309
|
-
- test/unit/salt_fact_parser_test.rb
|
|
310
305
|
- test/unit/salt_modules_test.rb
|
|
311
|
-
- test/unit/grains_centos.json
|
|
312
|
-
- test/unit/salt_fact_importer_test.rb
|
|
313
306
|
- test/unit/report_importer_test.rb
|
|
314
307
|
- test/unit/salt_variables_test.rb
|
|
315
308
|
- test/unit/salt_keys_test.rb
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
module ForemanSalt
|
|
2
|
-
# Define the class that fact names that come from Salt should have
|
|
3
|
-
# It allows us to filter facts by origin, and also to display the origin
|
|
4
|
-
# in the fact values table (/fact_values)
|
|
5
|
-
class FactName < ::FactName
|
|
6
|
-
def origin
|
|
7
|
-
'Salt'
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def icon_path
|
|
11
|
-
'foreman_salt/Salt'
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
module ForemanSalt
|
|
2
|
-
class FactParser < ::FactParser
|
|
3
|
-
attr_reader :facts
|
|
4
|
-
|
|
5
|
-
def operatingsystem
|
|
6
|
-
os = Operatingsystem.where(os_hash).first_or_initialize
|
|
7
|
-
if os.new_record?
|
|
8
|
-
os.deduce_family
|
|
9
|
-
os.release_name = facts[:lsb_distrib_codename]
|
|
10
|
-
os.save
|
|
11
|
-
end
|
|
12
|
-
os if os.persisted?
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def architecture
|
|
16
|
-
name = facts[:osarch]
|
|
17
|
-
name = 'x86_64' if name == 'amd64'
|
|
18
|
-
Architecture.where(:name => name).first_or_create unless name.blank?
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def environment
|
|
22
|
-
# Don't touch the Puppet environment field
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def model
|
|
26
|
-
name = facts[:productname]
|
|
27
|
-
Model.where(:name => name.strip).first_or_create unless name.blank?
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def domain
|
|
31
|
-
name = facts[:domain]
|
|
32
|
-
Domain.where(:name => name).first_or_create unless name.blank?
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def ip
|
|
36
|
-
ip = facts.find { |fact, value| fact =~ /^fqdn_ip4/ && value && value != '127.0.0.1' }
|
|
37
|
-
ip[1] if ip
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def primary_interface
|
|
41
|
-
interface = interfaces.find { |_, value| value[:ipaddress] == ip }
|
|
42
|
-
interface[0] if interface
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def mac
|
|
46
|
-
interface = interfaces.find { |_, value| value[:ipaddress] == ip }
|
|
47
|
-
interface[1][:macaddress] if interface
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def ipmi_interface
|
|
51
|
-
nil
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def interfaces
|
|
55
|
-
interfaces = {}
|
|
56
|
-
|
|
57
|
-
facts.each do |fact, value|
|
|
58
|
-
next unless value && fact.to_s =~ /^ip_interfaces/
|
|
59
|
-
|
|
60
|
-
(_, interface_name) = fact.split(FactName::SEPARATOR)
|
|
61
|
-
|
|
62
|
-
next if (IPAddr.new('fe80::/10').include?(value) rescue false)
|
|
63
|
-
|
|
64
|
-
if !interface_name.blank? && interface_name != 'lo'
|
|
65
|
-
interface = interfaces.fetch(interface_name, {})
|
|
66
|
-
interface[:macaddress] = macs[interface_name]
|
|
67
|
-
if Net::Validations.validate_ip6(value)
|
|
68
|
-
interface[:ipaddress6] = value unless interface.include?(:ipaddress6)
|
|
69
|
-
else
|
|
70
|
-
interface[:ipaddress] = value unless interface.include?(:ipaddress)
|
|
71
|
-
end
|
|
72
|
-
interfaces[interface_name] = interface
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
interfaces.each do |name, interface|
|
|
77
|
-
set_additional_attributes(interface, name)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
interfaces
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def support_interfaces_parsing?
|
|
84
|
-
true
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
private
|
|
88
|
-
|
|
89
|
-
def os_hash
|
|
90
|
-
name = facts[:os]
|
|
91
|
-
(_, major, minor, sub) = /(\d+)\.?(\d+)?\.?(\d+)?/.match(facts[:osrelease]).to_a
|
|
92
|
-
if name == 'CentOS'
|
|
93
|
-
if sub
|
|
94
|
-
minor += '.' + sub
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
{ :name => name, :major => major, :minor => minor }
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def macs
|
|
101
|
-
unless @macs
|
|
102
|
-
@macs = {}
|
|
103
|
-
facts.each do |fact, value|
|
|
104
|
-
next unless value && fact.to_s =~ /^hwaddr_interfaces/
|
|
105
|
-
|
|
106
|
-
data = fact.split(FactName::SEPARATOR)
|
|
107
|
-
interface = data[1]
|
|
108
|
-
macs[interface] = value
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
@macs
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"facts": {
|
|
3
|
-
"kernelrelease": "2.6.32-431.23.3.el6.x86_64",
|
|
4
|
-
"ipv6::0": "::1",
|
|
5
|
-
"ipv6::1": "fe80::5054:ff:fe35:302a",
|
|
6
|
-
"saltversioninfo": [
|
|
7
|
-
2014,
|
|
8
|
-
1,
|
|
9
|
-
7
|
|
10
|
-
],
|
|
11
|
-
"operatingsystem": "CentOS",
|
|
12
|
-
"lsb_distrib_id": "CentOS",
|
|
13
|
-
"pythonversion::2": 6,
|
|
14
|
-
"pythonversion::3": "final",
|
|
15
|
-
"pythonversion::0": 2,
|
|
16
|
-
"pythonversion::1": 6,
|
|
17
|
-
"cpu_model": "QEMU Virtual CPU version (cpu64-rhel6)",
|
|
18
|
-
"pythonversion::4": 0,
|
|
19
|
-
"oscodename": "Final",
|
|
20
|
-
"num_gpus": 1,
|
|
21
|
-
"productname": "KVM",
|
|
22
|
-
"osarch": "x86_64",
|
|
23
|
-
"biosversion": "0.5.1",
|
|
24
|
-
"kernel": "Linux",
|
|
25
|
-
"domain": "example.com",
|
|
26
|
-
"pythonpath::4": "/usr/lib64/python2.6/lib-tk",
|
|
27
|
-
"pythonpath::5": "/usr/lib64/python2.6/lib-old",
|
|
28
|
-
"pythonpath::6": "/usr/lib64/python2.6/lib-dynload",
|
|
29
|
-
"pythonpath::7": "/usr/lib64/python2.6/site-packages",
|
|
30
|
-
"pythonpath::0": "/usr/bin",
|
|
31
|
-
"mem_total": 742,
|
|
32
|
-
"pythonpath::2": "/usr/lib64/python2.6",
|
|
33
|
-
"pythonpath::3": "/usr/lib64/python2.6/plat-linux2",
|
|
34
|
-
"pythonpath::8": "/usr/lib/python2.6/site-packages",
|
|
35
|
-
"cpu_flags::25": "pni",
|
|
36
|
-
"cpu_flags::24": "unfair_spinlock",
|
|
37
|
-
"cpu_flags::27": "hypervisor",
|
|
38
|
-
"cpu_flags::26": "cx16",
|
|
39
|
-
"cpu_flags::21": "nx",
|
|
40
|
-
"cpu_flags::20": "syscall",
|
|
41
|
-
"cpu_flags::23": "up",
|
|
42
|
-
"cpu_flags::22": "lm",
|
|
43
|
-
"cpu_flags::28": "lahf_lm",
|
|
44
|
-
"defaultlanguage": "en_US",
|
|
45
|
-
"osfullname": "CentOS",
|
|
46
|
-
"localhost": "saltclient01.example.com",
|
|
47
|
-
"lsb_distrib_release": "6.5",
|
|
48
|
-
"saltpath": "/usr/lib/python2.6/site-packages/salt",
|
|
49
|
-
"biosreleasedate": "01/01/2007",
|
|
50
|
-
"host": "saltclient01",
|
|
51
|
-
"defaultencoding": "UTF8",
|
|
52
|
-
"path": "/sbin:/usr/sbin:/bin:/usr/bin",
|
|
53
|
-
"ip_interfaces::eth0::0": "10.7.13.141",
|
|
54
|
-
"ip_interfaces::eth0::1": "10.7.23.141",
|
|
55
|
-
"manufacturer": "Red Hat",
|
|
56
|
-
"fqdn": "saltclient01.example.com",
|
|
57
|
-
"os": "CentOS",
|
|
58
|
-
"osfinger": "CentOS-6",
|
|
59
|
-
"ps": "ps -efH",
|
|
60
|
-
"server_id": 654860635,
|
|
61
|
-
"zmqversion": "3.2.4",
|
|
62
|
-
"osmajorrelease::1": "5",
|
|
63
|
-
"osmajorrelease::0": "6",
|
|
64
|
-
"ip_interfaces::lo::0": "127.0.0.1",
|
|
65
|
-
"master": "saltstack.example.com",
|
|
66
|
-
"shell": "/bin/sh",
|
|
67
|
-
"saltversion": "2014.1.7",
|
|
68
|
-
"hwaddr_interfaces::lo": "00:00:00:00:00:00",
|
|
69
|
-
"_timestamp": "2014-08-28 10:02:16 ",
|
|
70
|
-
"cpu_flags::18": "sse",
|
|
71
|
-
"cpu_flags::19": "sse2",
|
|
72
|
-
"cpu_flags::14": "pse36",
|
|
73
|
-
"cpu_flags::15": "clflush",
|
|
74
|
-
"cpu_flags::16": "mmx",
|
|
75
|
-
"cpu_flags::17": "fxsr",
|
|
76
|
-
"cpu_flags::10": "mtrr",
|
|
77
|
-
"cpu_flags::11": "pge",
|
|
78
|
-
"cpu_flags::12": "mca",
|
|
79
|
-
"cpu_flags::13": "cmov",
|
|
80
|
-
"cpuarch": "x86_64",
|
|
81
|
-
"pythonpath::1": "/usr/lib64/python26.zip",
|
|
82
|
-
"cpu_flags::6": "mce",
|
|
83
|
-
"cpu_flags::7": "cx8",
|
|
84
|
-
"cpu_flags::4": "msr",
|
|
85
|
-
"cpu_flags::5": "pae",
|
|
86
|
-
"cpu_flags::2": "pse",
|
|
87
|
-
"cpu_flags::3": "tsc",
|
|
88
|
-
"cpu_flags::0": "fpu",
|
|
89
|
-
"cpu_flags::1": "de",
|
|
90
|
-
"serialnumber": "Not Specified",
|
|
91
|
-
"hwaddr_interfaces::eth0": "52:54:00:35:30:2a",
|
|
92
|
-
"cpu_flags::8": "apic",
|
|
93
|
-
"cpu_flags::9": "sep",
|
|
94
|
-
"gpus::0::model": "GD 5446",
|
|
95
|
-
"id": "saltclient01.example.com",
|
|
96
|
-
"osrelease": "6.5",
|
|
97
|
-
"num_cpus": 1,
|
|
98
|
-
"virtual": "kvm",
|
|
99
|
-
"ipv4::0": "10.7.23.141",
|
|
100
|
-
"ipv4::1": "10.7.13.141",
|
|
101
|
-
"ipv4::2": "127.0.0.1",
|
|
102
|
-
"_type": "foreman_salt",
|
|
103
|
-
"nodename": "saltclient01.example.com",
|
|
104
|
-
"os_family": "RedHat",
|
|
105
|
-
"operatingsystemrelease": "6.5",
|
|
106
|
-
"gpus::0::vendor": "unknown",
|
|
107
|
-
"lsb_distrib_codename": "Final",
|
|
108
|
-
"fqdn_ip4::0": "10.7.13.141",
|
|
109
|
-
"ip_interfaces::eth1::0": "1.2.3.4",
|
|
110
|
-
"hwaddr_interfaces::eth1": "DE:AD:BE:EF:07:13"
|
|
111
|
-
},
|
|
112
|
-
"name": "saltclient01.example.com"
|
|
113
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
require 'test_plugin_helper'
|
|
2
|
-
|
|
3
|
-
module ForemanSalt
|
|
4
|
-
class SaltFactImpoterTest < ActiveSupport::TestCase
|
|
5
|
-
def setup
|
|
6
|
-
@host = FactoryBot.build(:host)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
test 'should have fact set' do
|
|
10
|
-
importer = FactImporter.new(@host, 'a' => 'b')
|
|
11
|
-
assert_equal({ 'a' => 'b' }, importer.send(:facts))
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
test 'should have Salt as origin' do
|
|
15
|
-
importer = FactImporter.new(@host, 'a' => 'b')
|
|
16
|
-
importer.stubs(:ensure_no_active_transaction).returns(true)
|
|
17
|
-
importer.import!
|
|
18
|
-
imported_fact = FactName.find_by_name('a')
|
|
19
|
-
assert_equal 'a', imported_fact.name
|
|
20
|
-
assert_equal 'Salt', imported_fact.origin
|
|
21
|
-
assert_equal 'foreman_salt/Salt', imported_fact.icon_path
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
require 'test_plugin_helper'
|
|
2
|
-
|
|
3
|
-
module ForemanSalt
|
|
4
|
-
class SaltFactsParserTest < ActiveSupport::TestCase
|
|
5
|
-
def setup
|
|
6
|
-
grains = JSON.parse(File.read(File.join(Engine.root, 'test', 'unit', 'grains_centos.json')))
|
|
7
|
-
@facts_parser = FactParser.new grains["facts"]
|
|
8
|
-
User.current = users :admin
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
test "should return list of interfaces" do
|
|
12
|
-
assert @facts_parser.interfaces.present?
|
|
13
|
-
assert_not_nil @facts_parser.suggested_primary_interface(FactoryBot.build(:host))
|
|
14
|
-
assert @facts_parser.interfaces.key?(@facts_parser.suggested_primary_interface(FactoryBot.build(:host)).first)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
test "should set operatingsystem correctly" do
|
|
18
|
-
os = @facts_parser.operatingsystem
|
|
19
|
-
assert os.present?
|
|
20
|
-
assert_equal 'CentOS', os.name
|
|
21
|
-
assert_equal '6', os.major
|
|
22
|
-
assert_equal '5', os.minor
|
|
23
|
-
assert_equal 'CentOS 6.5', os.title
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
test "should set domain correctly" do
|
|
27
|
-
domain = @facts_parser.domain
|
|
28
|
-
assert domain.present?
|
|
29
|
-
assert_equal 'example.com', domain.name
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
test "should set ip correctly" do
|
|
33
|
-
assert_equal '10.7.13.141', @facts_parser.ip
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
test "should set primary_interface correctly" do
|
|
37
|
-
assert_equal 'eth0', @facts_parser.primary_interface
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
test "should set mac correctly" do
|
|
41
|
-
assert_equal '52:54:00:35:30:2a', @facts_parser.mac
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|