smart_proxy_ansible 2.0.3 → 2.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
- SHA256:
3
- metadata.gz: 9d28a2511a0408d6a44c81eef3be111c62cda0a3b261a65c41421acfb761d0f6
4
- data.tar.gz: 2077acfca79312a7461f2163767620d066522b08208a898a661078435807c635
2
+ SHA1:
3
+ metadata.gz: ce925932dfc2ddf578d2ae15b293ee1a223b8808
4
+ data.tar.gz: 54f6dd7b4d48229be33aef44b7445d8284a7d734
5
5
  SHA512:
6
- metadata.gz: f7416e850bc1db8497ed812172e8f950ffa840154b10df984d22b3f656a430b380228c0cfe18cf1cfc876371be72d26ff088f30d1de03060fdb3b3bea2015298
7
- data.tar.gz: 8cbe2314b24f686a306a781ace03be10254c5ac8021f1c1cc9c1b60f34ce2af3ee7cf78b9aae186c0924a80aa5f87d2e87489b5a3700e7ff2045044afb47bf33
6
+ metadata.gz: a88b68d82b25d7baeff478651fdf159c512be92262d2c7c5ed5af5ed204915043ab08dbe3d7b3200a7261226f0ece19f2e803be10d3e25e105caa3f6d46bc97e
7
+ data.tar.gz: 0c57bf4282a7f4e9699b9108e3e89817a2e2ded17ef448d8d51ae5eeede0a93d8947673d3df034d775fee2238fdb5c2fc40a707c1acc77aa5044953c062c0e97
@@ -1,8 +1,11 @@
1
1
  require 'smart_proxy_dynflow'
2
2
 
3
3
  module Proxy
4
+ # Basic requires for this plugin
4
5
  module Ansible
5
6
  require 'smart_proxy_ansible/version'
6
7
  require 'smart_proxy_ansible/plugin'
8
+ require 'smart_proxy_ansible/roles_reader'
9
+ require 'smart_proxy_ansible/variables_extractor'
7
10
  end
8
11
  end
@@ -1,24 +1,34 @@
1
- require 'foreman_ansible_core'
2
-
3
1
  module Proxy
4
2
  module Ansible
3
+ # API endpoints. Most of the code should be calling other classes,
4
+ # please keep the actual implementation of the endpoints outside
5
+ # of this class.
5
6
  class Api < Sinatra::Base
6
7
  get '/roles' do
7
- ::ForemanAnsibleCore::RolesReader.list_roles.to_json
8
+ RolesReader.list_roles.to_json
9
+ end
10
+
11
+ get '/roles/variables' do
12
+ variables = {}
13
+ RolesReader.list_roles.each do |role_name|
14
+ variables[role_name] = extract_variables(role_name)[role_name]
15
+ end
16
+ variables.to_json
8
17
  end
9
18
 
10
19
  get '/roles/:role_name/variables' do |role_name|
11
- # not anything matching item, }}, {{, ansible_hostname or 'if'
12
- ansible_config = '/etc/ansible/ansible.cfg'
13
- roles_path = ::ForemanAnsibleCore::RolesReader.roles_path(ansible_config)
14
- role_files = Dir.glob("#{roles_path}/#{role_name}/**/*.yml")
15
- variables = role_files.map do |role_file|
16
- File.read(role_file).scan(/{{(.*?)}}/).select do |param|
17
- param.first.scan(/item/) == [] && param.first.scan(/if/) == []
18
- end.first
19
- end.compact
20
- variables.uniq!
21
- variables = variables.map(&:first).map(&:strip).to_json
20
+ extract_variables(role_name).to_json
21
+ end
22
+
23
+ private
24
+
25
+ def extract_variables(role_name)
26
+ variables = {}
27
+ RolesReader.roles_path.split(':').each do |path|
28
+ variables[role_name] = VariablesExtractor
29
+ .extract_variables("#{path}/#{role_name}")
30
+ end
31
+ variables
22
32
  end
23
33
  end
24
34
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Proxy
4
+ module Ansible
5
+ # Taken from Foreman core, this class creates an error code for any
6
+ # exception
7
+ class Exception < ::StandardError
8
+ def initialize(message, *params)
9
+ @message = message
10
+ @params = params
11
+ end
12
+
13
+ def self.calculate_error_code(classname, message)
14
+ return 'ERF00-0000' if classname.nil? || message.nil?
15
+ basename = classname.split(':').last
16
+ class_hash = Zlib.crc32(basename) % 100
17
+ msg_hash = Zlib.crc32(message) % 10_000
18
+ format 'ERF%02d-%04d', class_hash, msg_hash
19
+ end
20
+
21
+ def code
22
+ @code ||= Exception.calculate_error_code(self.class.name, @message)
23
+ @code
24
+ end
25
+
26
+ def message
27
+ # make sure it works without gettext too
28
+ translated_msg = @message % @params
29
+ "#{code} [#{self.class.name}]: #{translated_msg}"
30
+ end
31
+
32
+ def to_s
33
+ message
34
+ end
35
+ end
36
+
37
+ class ReadConfigFileException < Proxy::Ansible::Exception; end
38
+ class ReadRolesException < Proxy::Ansible::Exception; end
39
+ end
40
+ end
@@ -1,20 +1,14 @@
1
- module Proxy::Ansible
2
- class Plugin < Proxy::Plugin
3
- http_rackup_path File.expand_path("http_config.ru", File.expand_path("../", __FILE__))
4
- https_rackup_path File.expand_path("http_config.ru", File.expand_path("../", __FILE__))
1
+ module Proxy
2
+ module Ansible
3
+ # Calls for the smart-proxy API to register the plugin
4
+ class Plugin < Proxy::Plugin
5
+ http_rackup_path File.expand_path('http_config.ru',
6
+ File.expand_path('../', __FILE__))
7
+ https_rackup_path File.expand_path('http_config.ru',
8
+ File.expand_path('../', __FILE__))
5
9
 
6
- settings_file "ansible.yml"
7
- plugin :ansible, Proxy::Ansible::VERSION
8
-
9
- after_activation do
10
- begin
11
- require 'smart_proxy_dynflow_core'
12
- require 'foreman_ansible_core'
13
- ForemanAnsibleCore.initialize_settings(Proxy::Ansible::Plugin.settings.to_h)
14
- rescue LoadError => _
15
- # Dynflow core is not available in the proxy, will be handled
16
- # by standalone Dynflow core
17
- end
10
+ settings_file 'ansible.yml'
11
+ plugin :ansible, Proxy::Ansible::VERSION
18
12
  end
19
13
  end
20
14
  end
@@ -0,0 +1,65 @@
1
+ require_relative 'exception'
2
+
3
+ module Proxy
4
+ module Ansible
5
+ # Implements the logic needed to read the roles and associated information
6
+ class RolesReader
7
+ class << self
8
+ DEFAULT_CONFIG_FILE = '/etc/ansible/ansible.cfg'.freeze
9
+ DEFAULT_ROLES_PATH = '/etc/ansible/roles'.freeze
10
+
11
+ def list_roles
12
+ roles_path.split(':').map { |path| read_roles(path) }.flatten
13
+ end
14
+
15
+ def roles_path(roles_line = roles_path_from_config)
16
+ # Default to /etc/ansible/roles if none found
17
+ return DEFAULT_ROLES_PATH if roles_line.empty?
18
+ roles_path_key = roles_line.first.split('=').first.strip
19
+ # In case of commented roles_path key "#roles_path", return default
20
+ return DEFAULT_ROLES_PATH unless roles_path_key == 'roles_path'
21
+ roles_line.first.split('=').last.strip
22
+ end
23
+
24
+ def logger
25
+ # Return a different logger depending on where ForemanAnsibleCore is
26
+ # running from
27
+ if defined?(::Foreman::Logging)
28
+ ::Foreman::Logging.logger('foreman_ansible')
29
+ else
30
+ ::Proxy::LogBuffer::Decorator.instance
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def read_roles(roles_path)
37
+ rescue_and_raise_file_exception ReadRolesException,
38
+ roles_path, 'roles' do
39
+ Dir.glob("#{roles_path}/*").map do |path|
40
+ path.split('/').last
41
+ end
42
+ end
43
+ end
44
+
45
+ def roles_path_from_config
46
+ rescue_and_raise_file_exception ReadConfigFileException,
47
+ DEFAULT_CONFIG_FILE, 'config file' do
48
+ File.readlines(DEFAULT_CONFIG_FILE).select do |line|
49
+ line =~ /^\s*roles_path/
50
+ end
51
+ end
52
+ end
53
+
54
+ def rescue_and_raise_file_exception(exception, path, type)
55
+ yield
56
+ rescue Errno::ENOENT, Errno::EACCES => e
57
+ logger.debug(e.backtrace)
58
+ exception_message = "Could not read Ansible #{type} "\
59
+ "#{path} - #{e.message}"
60
+ raise exception.new(exception_message), exception_message
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,33 @@
1
+ module Proxy
2
+ module Ansible
3
+ # Implements the logic needed to read the roles and associated information
4
+ class VariablesExtractor
5
+ class << self
6
+ def extract_variables(role_path)
7
+ role_files = Dir.glob("#{role_path}/defaults/**/*.yml") +
8
+ Dir.glob("#{role_path}/defaults/**/*.yaml")
9
+ # not anything matching item, }}, {{, ansible_hostname or 'if'
10
+ variables = role_files.map do |role_file|
11
+ candidates = File.read(role_file)
12
+ .scan(/{{(.*?)}}/).select do |param|
13
+ param.first.scan(/item/) == [] && param.first.scan(/if/) == []
14
+ end.flatten
15
+ # Sometimes inside the {{ }} there's a OR condition. In such a case,
16
+ # let's split and choose possible variables (variables cannot
17
+ # contain parenthesis)
18
+
19
+ candidates.map do |variable|
20
+ variable.split('|').map(&:strip).select do |var|
21
+ !var.include?('(') && # variables are not parenthesis
22
+ !var.include?('[') && # variables are not arrays
23
+ !var.include?('.') && # variables are not objects
24
+ !var.include?("'") # variables are not plain strings
25
+ end
26
+ end unless candidates.nil?
27
+ end.compact.flatten.uniq.map(&:strip)
28
+ variables
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,7 @@
1
1
  module Proxy
2
+ # Version, this allows the proxy and other plugins know
3
+ # what version of the Ansible plugin is running
2
4
  module Ansible
3
- VERSION = '2.0.3'
5
+ VERSION = '2.1.0'
4
6
  end
5
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_ansible
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-05-23 00:00:00.000000000 Z
12
+ date: 2018-12-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -109,6 +109,34 @@ dependencies:
109
109
  - - '='
110
110
  - !ruby/object:Gem::Version
111
111
  version: 0.32.1
112
+ - !ruby/object:Gem::Dependency
113
+ name: logger
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: smart_proxy
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
112
140
  - !ruby/object:Gem::Dependency
113
141
  name: smart_proxy_dynflow
114
142
  requirement: !ruby/object:Gem::Requirement
@@ -137,19 +165,13 @@ files:
137
165
  - README.md
138
166
  - bin/json_inventory.sh
139
167
  - bundler.plugins.d/smart_proxy_ansible.rb
140
- - lib/foreman_ansible_core.rb
141
- - lib/foreman_ansible_core/actions.rb
142
- - lib/foreman_ansible_core/command_creator.rb
143
- - lib/foreman_ansible_core/exception.rb
144
- - lib/foreman_ansible_core/playbook_runner.rb
145
- - lib/foreman_ansible_core/remote_execution_core/ansible_runner.rb
146
- - lib/foreman_ansible_core/remote_execution_core/settings_override.rb
147
- - lib/foreman_ansible_core/roles_reader.rb
148
- - lib/foreman_ansible_core/version.rb
149
168
  - lib/smart_proxy_ansible.rb
150
169
  - lib/smart_proxy_ansible/api.rb
170
+ - lib/smart_proxy_ansible/exception.rb
151
171
  - lib/smart_proxy_ansible/http_config.ru
152
172
  - lib/smart_proxy_ansible/plugin.rb
173
+ - lib/smart_proxy_ansible/roles_reader.rb
174
+ - lib/smart_proxy_ansible/variables_extractor.rb
153
175
  - lib/smart_proxy_ansible/version.rb
154
176
  - settings.d/ansible.yml.example
155
177
  homepage: https://github.com/theforeman/smart_proxy_ansible
@@ -172,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
194
  version: '0'
173
195
  requirements: []
174
196
  rubyforge_project:
175
- rubygems_version: 2.7.3
197
+ rubygems_version: 2.6.8
176
198
  signing_key:
177
199
  specification_version: 4
178
200
  summary: Smart-Proxy Ansible plugin
@@ -1,37 +0,0 @@
1
- begin
2
- require 'foreman_tasks_core'
3
- require 'foreman_remote_execution_core'
4
- rescue LoadError
5
- # These gems are not available in a proxy SCLed context
6
- puts 'Running Foreman Ansible Core in non-SCL context'
7
- end
8
-
9
- # Core actions for Foreman Ansible, used by both Foreman and Foreman proxy
10
- # This comprises running playbooks for the moment
11
- module ForemanAnsibleCore
12
- require 'foreman_ansible_core/exception'
13
- require 'foreman_ansible_core/roles_reader'
14
- require 'foreman_ansible_core/version'
15
-
16
- if defined? ForemanTasksCore
17
- extend ForemanTasksCore::SettingsLoader
18
- register_settings(:ansible, :ansible_dir => '/etc/ansible',
19
- :working_dir => nil)
20
-
21
- if ForemanTasksCore.dynflow_present?
22
- require 'foreman_tasks_core/runner'
23
- require 'foreman_ansible_core/playbook_runner'
24
- require 'foreman_ansible_core/actions'
25
- end
26
- end
27
-
28
- if defined? ForemanTasksCore
29
- require 'foreman_remote_execution_core/actions'
30
- require 'foreman_ansible_core/remote_execution_core/ansible_runner'
31
- require 'foreman_ansible_core/remote_execution_core/settings_override'
32
- ForemanRemoteExecutionCore::Actions::RunScript.send(
33
- :prepend,
34
- ForemanAnsibleCore::RemoteExecutionCore::SettingsOverride
35
- )
36
- end
37
- end
@@ -1,17 +0,0 @@
1
- require 'foreman_tasks_core/shareable_action'
2
-
3
- module ForemanAnsibleCore
4
- module Actions
5
- # Action that can be run both on Foreman or Foreman proxy side
6
- # to execute the playbook run
7
- class RunPlaybook < ForemanTasksCore::Runner::Action
8
- def initiate_runner
9
- ForemanAnsibleCore::PlaybookRunner.new(
10
- input[:inventory],
11
- input[:playbook],
12
- input[:options]
13
- )
14
- end
15
- end
16
- end
17
- end
@@ -1,44 +0,0 @@
1
- module ForemanAnsibleCore
2
- # Creates the actual command to be passed to foreman_tasks_core to run
3
- class CommandCreator
4
- attr_reader :command
5
-
6
- def initialize(inventory_file, playbook_file, options = {})
7
- @options = options
8
- @command = [{ 'JSON_INVENTORY_FILE' => inventory_file }]
9
- @command << 'ansible-playbook'
10
- @command = command_options(@command)
11
- @command << playbook_file
12
- end
13
-
14
- private
15
-
16
- def command_options(command)
17
- command.concat(['-i', json_inventory_script])
18
- command.concat([setup_verbosity]) if verbose?
19
- command.concat(['-T', @options[:timeout]]) unless @options[:timeout].nil?
20
- command
21
- end
22
-
23
- def json_inventory_script
24
- File.expand_path('../../bin/json_inventory.sh', File.dirname(__FILE__))
25
- end
26
-
27
- def setup_verbosity
28
- verbosity_level = @options[:verbosity_level].to_i
29
- verbosity = '-'
30
- verbosity_level.times do
31
- verbosity += 'v'
32
- end
33
- verbosity
34
- end
35
-
36
- def verbose?
37
- verbosity_level = @options[:verbosity_level]
38
- # rubocop:disable Rails/Present
39
- !verbosity_level.nil? && !verbosity_level.empty? &&
40
- verbosity_level.to_i > 0
41
- # rubocop:enable Rails/Present
42
- end
43
- end
44
- end
@@ -1,35 +0,0 @@
1
- module ForemanAnsibleCore
2
- # Taken from Foreman core, this class creates an error code for any exception
3
- class Exception < ::StandardError
4
- def initialize(message, *params)
5
- @message = message
6
- @params = params
7
- end
8
-
9
- def self.calculate_error_code(classname, message)
10
- return 'ERF00-0000' if classname.nil? || message.nil?
11
- basename = classname.split(':').last
12
- class_hash = Zlib.crc32(basename) % 100
13
- msg_hash = Zlib.crc32(message) % 10_000
14
- format 'ERF%02d-%04d', class_hash, msg_hash
15
- end
16
-
17
- def code
18
- @code ||= Exception.calculate_error_code(self.class.name, @message)
19
- @code
20
- end
21
-
22
- def message
23
- # make sure it works without gettext too
24
- translated_msg = @message % @params
25
- "#{code} [#{self.class.name}]: #{translated_msg}"
26
- end
27
-
28
- def to_s
29
- message
30
- end
31
- end
32
-
33
- class ReadConfigFileException < ForemanAnsibleCore::Exception; end
34
- class ReadRolesException < ForemanAnsibleCore::Exception; end
35
- end
@@ -1,98 +0,0 @@
1
- require 'foreman_tasks_core/runner/command_runner'
2
- require_relative 'command_creator'
3
- require 'tmpdir'
4
-
5
- module ForemanAnsibleCore
6
- # Implements ForemanTasksCore::Runner::Base interface for running
7
- # Ansible playbooks, used by the Foreman Ansible plugin and Ansible proxy
8
- class PlaybookRunner < ForemanTasksCore::Runner::CommandRunner
9
- attr_reader :command_out, :command_in, :command_pid
10
-
11
- def initialize(inventory, playbook, options = {})
12
- super
13
- @inventory = inventory
14
- @playbook = playbook
15
- @options = options
16
- initialize_dirs
17
- end
18
-
19
- def start
20
- write_inventory
21
- write_playbook
22
- command = CommandCreator.new(inventory_file,
23
- playbook_file,
24
- @options).command
25
- logger.debug('[foreman_ansible] - Initializing Ansible Runner')
26
- Dir.chdir(@ansible_dir) do
27
- initialize_command(*command)
28
- logger.debug("[foreman_ansible] - Running command #{command}")
29
- end
30
- end
31
-
32
- def kill
33
- publish_data('== TASK ABORTED BY USER ==', 'stdout')
34
- publish_exit_status(1)
35
- ::Process.kill('SIGTERM', @command_pid)
36
- close
37
- end
38
-
39
- def close
40
- super
41
- FileUtils.remove_entry(@working_dir) if @tmp_working_dir
42
- end
43
-
44
- private
45
-
46
- def write_inventory
47
- ensure_directory(File.dirname(inventory_file))
48
- File.write(inventory_file, @inventory)
49
- end
50
-
51
- def write_playbook
52
- ensure_directory(File.dirname(playbook_file))
53
- File.write(playbook_file, @playbook)
54
- end
55
-
56
- def inventory_file
57
- File.join(@working_dir, 'foreman-inventories', id)
58
- end
59
-
60
- def playbook_file
61
- File.join(@working_dir, "foreman-playbook-#{id}.yml")
62
- end
63
-
64
- def events_dir
65
- File.join(@working_dir, 'events', id.to_s)
66
- end
67
-
68
- def ensure_directory(path)
69
- if File.exist?(path)
70
- raise "#{path} expected to be a directory" unless File.directory?(path)
71
- else
72
- FileUtils.mkdir_p(path)
73
- end
74
- path
75
- end
76
-
77
- def initialize_dirs
78
- settings = ForemanAnsibleCore.settings
79
- initialize_working_dir(settings[:working_dir])
80
- initialize_ansible_dir(settings[:ansible_dir])
81
- end
82
-
83
- def initialize_working_dir(working_dir)
84
- if working_dir.nil?
85
- @working_dir = Dir.mktmpdir
86
- @tmp_working_dir = true
87
- else
88
- @working_dir = File.expand_path(working_dir)
89
- end
90
- end
91
-
92
- def initialize_ansible_dir(ansible_dir)
93
- raise "Ansible dir #{ansible_dir} does not exist" unless
94
- !ansible_dir.nil? && File.exist?(ansible_dir)
95
- @ansible_dir = ansible_dir
96
- end
97
- end
98
- end
@@ -1,42 +0,0 @@
1
- module ForemanAnsibleCore
2
- module RemoteExecutionCore
3
- # Takes an inventory and runs it through REXCore CommandRunner
4
- class AnsibleRunner < ::ForemanTasksCore::Runner::CommandRunner
5
- DEFAULT_REFRESH_INTERVAL = 1
6
-
7
- def initialize(options)
8
- super(options)
9
- @playbook_runner = ForemanAnsibleCore::PlaybookRunner.new(
10
- options['ansible_inventory'],
11
- options['script'],
12
- options
13
- )
14
- end
15
-
16
- def start
17
- @playbook_runner.start
18
- rescue StandardError => e
19
- logger.error(
20
- 'error while initalizing command'\
21
- " #{e.class} #{e.message}:\n #{e.backtrace.join("\n")}"
22
- )
23
- publish_exception('Error initializing command', e)
24
- end
25
-
26
- def fill_continuous_output(continuous_output)
27
- delegated_output.fetch('result', []).each do |raw_output|
28
- continuous_output.add_raw_output(raw_output)
29
- end
30
- rescue StandardError => e
31
- continuous_output.add_exception(_('Error loading data from proxy'), e)
32
- end
33
-
34
- def refresh
35
- @command_out = @playbook_runner.command_out
36
- @command_in = @playbook_runner.command_in
37
- @command_pid = @playbook_runner.command_pid
38
- super
39
- end
40
- end
41
- end
42
- end
@@ -1,18 +0,0 @@
1
- module ForemanAnsibleCore
2
- module RemoteExecutionCore
3
- # Ensure the Ansible provider is used whenever a JobTemplate using this
4
- # provider is called.
5
- module SettingsOverride
6
- def initiate_runner
7
- return super unless input['ansible_inventory']
8
- additional_options = {
9
- :step_id => run_step_id,
10
- :uuid => execution_plan_id
11
- }
12
- ::ForemanAnsibleCore::RemoteExecutionCore::AnsibleRunner.new(
13
- input.merge(additional_options)
14
- )
15
- end
16
- end
17
- end
18
- end
@@ -1,61 +0,0 @@
1
- module ForemanAnsibleCore
2
- # Implements the logic needed to read the roles and associated information
3
- class RolesReader
4
- class << self
5
- DEFAULT_CONFIG_FILE = '/etc/ansible/ansible.cfg'.freeze
6
- DEFAULT_ROLES_PATH = '/etc/ansible/roles'.freeze
7
-
8
- def list_roles
9
- roles_path.split(':').map { |path| read_roles(path) }.flatten
10
- end
11
-
12
- def roles_path(roles_line = roles_path_from_config)
13
- # Default to /etc/ansible/roles if none found
14
- return DEFAULT_ROLES_PATH if roles_line.empty?
15
- roles_path_key = roles_line.first.split('=').first.strip
16
- # In case of commented roles_path key "#roles_path", return default
17
- return DEFAULT_ROLES_PATH unless roles_path_key == 'roles_path'
18
- roles_line.first.split('=').last.strip
19
- end
20
-
21
- def logger
22
- # Return a different logger depending on where ForemanAnsibleCore is
23
- # running from
24
- if defined?(::Foreman::Logging)
25
- ::Foreman::Logging.logger('foreman_ansible')
26
- else
27
- ::Proxy::LogBuffer::Decorator.instance
28
- end
29
- end
30
-
31
- private
32
-
33
- def read_roles(roles_path)
34
- rescue_and_raise_file_exception ReadRolesException,
35
- roles_path, 'roles' do
36
- Dir.glob("#{roles_path}/*").map do |path|
37
- path.split('/').last
38
- end
39
- end
40
- end
41
-
42
- def roles_path_from_config
43
- rescue_and_raise_file_exception ReadConfigFileException,
44
- DEFAULT_CONFIG_FILE, 'config file' do
45
- File.readlines(DEFAULT_CONFIG_FILE).select do |line|
46
- line =~ /roles_path/
47
- end
48
- end
49
- end
50
-
51
- def rescue_and_raise_file_exception(exception, path, type)
52
- yield
53
- rescue Errno::ENOENT, Errno::EACCES => e
54
- logger.debug(e.backtrace)
55
- exception_message = "Could not read Ansible #{type} "\
56
- "#{path} - #{e.message}"
57
- raise exception.new(exception_message)
58
- end
59
- end
60
- end
61
- end
@@ -1,3 +0,0 @@
1
- module ForemanAnsibleCore
2
- VERSION = '2.0.2'.freeze
3
- end