smart_proxy_acd 0.1.0 → 0.4.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
  SHA256:
3
- metadata.gz: 80a978c97059f5794f0edf5f62699f12e45a022b3332870159ca4a1c8114576a
4
- data.tar.gz: 65b8540e1cdba88109ab89fda19b0f1dd2bc9efb6efa6e463b562b475814642a
3
+ metadata.gz: 183250a25f2479402b6eb73acd841ec985da00ebe17cb4b836df7b1e3d37ae48
4
+ data.tar.gz: d9b0c52df1fad8c9a998930252617eb971a8319a3f53fdd0e910b17bcef8b439
5
5
  SHA512:
6
- metadata.gz: 9631b51f3a5b85eab8fa4312b2a887a7a5907ba5dc5ec52767c307e21502d386051448be42997dc8be24bcf6784ac010bf04d2f56c35d28eff8a96f8b1521e65
7
- data.tar.gz: bb80129d8c7111f8e9f28002accbc96f48c3863b71439866d3466baa29f8f4ce0907c6af24972b6b16039a87e8cf29e5d1af950f97dadc544395c0a0ec380f2e
6
+ metadata.gz: 88664606e79721dc883ee637bf749f54d6bfd3481ba42366abb4c0725a727fad4ec94d1029b25f0142b889b6bcdbde07f6e1142f419a939e8b3d4ae9ccddc5fa
7
+ data.tar.gz: 23cc133598f5d3888e0298bf5b2c3786d6a429ff6ba3625d673efdc0f61f338e64d749811c8dcbab8ff0cce544d7ec5672c813dbb38492cf2293f16d59c30f33
data/README.md CHANGED
@@ -14,7 +14,6 @@ This plug-in adds support for [Application Centric Deployment](https://github.co
14
14
 
15
15
  We expect your proxy to also have
16
16
  [smart_proxy_dynflow](https://github.com/theforeman/smart_proxy_dynflow)
17
- and [foreman-tasks-core](https://github.com/theforeman/foreman-tasks) as
18
17
  a gem requirement.
19
18
 
20
19
  ### Get the code
@@ -5,8 +5,19 @@ module Proxy
5
5
  # Implement a SmartProxy Plugin
6
6
  class Plugin < ::Proxy::Plugin
7
7
  plugin 'acd', Proxy::Acd::VERSION
8
- http_rackup_path File.expand_path('acd_http_config.ru', File.expand_path('../', __FILE__))
9
- https_rackup_path File.expand_path('acd_http_config.ru', File.expand_path('../', __FILE__))
8
+ rackup_path File.expand_path('acd_http_config.ru', __dir__)
9
+
10
+ load_classes do
11
+ require 'smart_proxy_dynflow'
12
+ require 'smart_proxy_acd/acd_runner'
13
+ require 'smart_proxy_acd/acd_task_launcher'
14
+ end
15
+
16
+ default_settings :timeout => 60
17
+
18
+ load_dependency_injection_wirings do |_container_instance, _settings|
19
+ Proxy::Dynflow::TaskLauncherRegistry.register('acd', AcdTaskLauncher)
20
+ end
10
21
  end
11
22
  end
12
23
  end
@@ -5,6 +5,17 @@ module Proxy
5
5
  extend ::Proxy::Log
6
6
 
7
7
  class << self
8
+ def plugin_settings
9
+ # rubocop:disable ClassVars
10
+ @@settings ||= OpenStruct.new(read_settings)
11
+ # rubocop:enable ClassVars
12
+ end
13
+
14
+ def read_settings
15
+ ::Proxy::Acd::Plugin.default_settings.merge(
16
+ YAML.load_file(File.join(::Proxy::SETTINGS.settings_directory, ::Proxy::Acd::Plugin.settings_file))
17
+ )
18
+ end
8
19
  end
9
20
  end
10
21
  end
@@ -0,0 +1,164 @@
1
+ require 'smart_proxy_dynflow/runner/base'
2
+ require 'smart_proxy_dynflow/runner/command_runner'
3
+ require 'tempfile'
4
+ require 'rest-client'
5
+ require 'tmpdir'
6
+ require 'socket'
7
+ require 'proxy/request'
8
+
9
+ # rubocop:disable ClassLength
10
+
11
+ module Proxy
12
+ module Acd
13
+ # Implements the AcdRunner to be used by foreman_remote_execution
14
+ class AcdRunner < Proxy::Dynflow::Runner::CommandRunner
15
+ DEFAULT_REFRESH_INTERVAL = 1
16
+
17
+ def initialize(options, suspended_action:)
18
+ super(options, :suspended_action => suspended_action)
19
+ @options = options
20
+ end
21
+
22
+ def get_playbook(playbook_id)
23
+ logger.debug("Get playbook with id #{playbook_id}")
24
+ response = playbook_resource(playbook_id)
25
+ if response.code.to_s != '200'
26
+ raise "Failed performing callback to Foreman server: #{response.code} #{response.body}"
27
+ end
28
+ tmp_file = Tempfile.new.path
29
+ File.write(tmp_file, response.body)
30
+ @playbook_tmp_base64_file = tmp_file
31
+ end
32
+
33
+ def playbook_resource(playbook_id)
34
+ playbook_download_path = "/acd/api/v2/ansible_playbooks/#{playbook_id}/grab"
35
+ foreman_request = Proxy::HttpRequest::ForemanRequest.new
36
+ req = foreman_request.request_factory.create_get(playbook_download_path)
37
+ foreman_request.http.read_timeout = Proxy::Acd::Plugin.settings.timeout
38
+ foreman_request.send_request(req)
39
+ end
40
+
41
+ def store_playbook
42
+ logger.debug('Unpack ansible playbook')
43
+ dir = Dir.mktmpdir
44
+ raise 'Could not create temporary directory to run ansible playbook' if dir.nil? || !Dir.exist?(dir)
45
+ command = "base64 -d #{@playbook_tmp_base64_file} | tar xz -C #{dir}"
46
+ system(command)
47
+ @playbook_tmp_dir = dir
48
+ end
49
+
50
+ def cleanup
51
+ File.unlink(@playbook_tmp_base64_file) if File.exist?(@playbook_tmp_base64_file)
52
+ FileUtils.rm_rf(@playbook_tmp_dir) if Dir.exist?(@playbook_tmp_dir)
53
+ end
54
+
55
+ def start
56
+ parse_acd_job
57
+
58
+ publish_data("Grab playbook to configure application #{@application_name}...", 'stdout')
59
+ get_playbook(@playbook_id)
60
+ store_playbook
61
+
62
+ @playbook_path = File.join(@playbook_tmp_dir, @playbook_file)
63
+ raise "Could not run playbook: playbook file #{@playbook_file} not found in playbook dir #{@playbook_tmp_dir}" unless File.exist?(@playbook_path)
64
+
65
+ publish_data('Write temporary inventory', 'stdout')
66
+ write_inventory
67
+
68
+ command = generate_command
69
+ logger.debug("Running command #{command.join(' ')}")
70
+ initialize_command(*command)
71
+ end
72
+
73
+ def close
74
+ logger.debug("Cleanup ansible playbook #{@playbook_tmp_dir} and #{@playbook_tmp_base64_file}")
75
+ cleanup
76
+ end
77
+
78
+ def kill
79
+ publish_data('== TASK ABORTED BY USER ==', 'stdout')
80
+ publish_exit_status(1)
81
+ ::Process.kill('SIGTERM', @command_pid)
82
+ end
83
+
84
+ private
85
+
86
+ def parse_acd_job
87
+ @acd_job = YAML.safe_load(@options['script'])
88
+ @application_name = @acd_job['application_name']
89
+ @playbook_id = @acd_job['playbook_id']
90
+ @playbook_file = @acd_job['playbook_file']
91
+
92
+ raise "'playbook_file' need to be specified" if @playbook_file.nil? || @playbook_file.empty?
93
+ raise "'playbook_id' need to be specified" if @playbook_id.nil?
94
+ end
95
+
96
+ def proxy_hostname
97
+ Socket.gethostbyname(Socket.gethostname).first
98
+ end
99
+
100
+ def write_inventory
101
+ complete_inventory = YAML.safe_load(@acd_job['inventory'])
102
+ my_inventory = complete_inventory[proxy_hostname]
103
+
104
+ my_inventory['all']['children'].each_value do |group|
105
+ group['hosts'].each_value do |host_vars|
106
+ host_vars['ansible_ssh_private_key_file'] ||= Proxy::RemoteExecution::Ssh::Plugin.settings[:ssh_identity_key_file]
107
+ end
108
+ end
109
+
110
+ tmp_inventory_file = Tempfile.new('acd_inventory')
111
+ tmp_inventory_file << my_inventory.to_yaml
112
+ tmp_inventory_file << "\n"
113
+ tmp_inventory_file.close
114
+ @inventory_path = tmp_inventory_file.path
115
+ end
116
+
117
+ def environment
118
+ env = {}
119
+ env['ANSIBLE_CALLBACK_WHITELIST'] = ''
120
+ env['ANSIBLE_LOAD_CALLBACK_PLUGINS'] = '0'
121
+ env
122
+ end
123
+
124
+ def setup_verbosity
125
+ verbosity = ''
126
+ if @acd_job['verbose']
127
+ verbosity_level = @acd_job['verbose'].split(' ').first.to_i
128
+ if verbosity_level.positive?
129
+ verbosity = '-'
130
+ verbosity_level.times do
131
+ verbosity += 'v'
132
+ end
133
+ end
134
+ end
135
+ verbosity
136
+ end
137
+
138
+ def valid_tags(tag)
139
+ re = /^\w+(\s*,\s*\w+)*$/
140
+ return true if @acd_job[tag] && @acd_job[tag].match?(re)
141
+ end
142
+
143
+ def generate_command
144
+ logger.debug("Generate command with #{@inventory_path} to run #{@playbook_id} with path #{@playbook_path}")
145
+ command = [environment]
146
+ command << 'ansible-playbook'
147
+ command << '-i'
148
+ command << @inventory_path
149
+ verbose = setup_verbosity
150
+ command << verbose unless verbose.empty?
151
+ command << "--tags '#{@acd_job['tags']}'" if valid_tags('tags')
152
+ command << "--skip-tags '#{@acd_job['skip_tags']}'" if valid_tags('skip_tags')
153
+ if @acd_job.key?('extra_vars') && !@acd_job['extra_vars'].nil? && !@acd_job['extra_vars'].empty?
154
+ command << '--extra-vars'
155
+ command << "'#{@acd_job['extra_vars']}'"
156
+ end
157
+ command << @playbook_path.to_s
158
+ command
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ # rubocop:enable ClassLength
@@ -0,0 +1,27 @@
1
+ require 'smart_proxy_dynflow/task_launcher'
2
+
3
+ module Proxy
4
+ module Acd
5
+ # Implements the TaskLauncher::Batch for Acd
6
+ class AcdTaskLauncher < Proxy::Dynflow::TaskLauncher::Batch
7
+ # Implements the Runner::Action for Acd
8
+ class AcdRunnerAction < Proxy::Dynflow::Action::Runner
9
+ def initiate_runner
10
+ additional_options = {
11
+ :step_id => run_step_id,
12
+ :uuid => execution_plan_id
13
+ }
14
+ ::Proxy::Acd::AcdRunner.new(
15
+ input.merge(additional_options),
16
+ :suspended_action => suspended_action
17
+ )
18
+ end
19
+ end
20
+
21
+ def child_launcher(parent)
22
+ Proxy::Dynflow::TaskLauncher::Single.new(world, callback, :parent => parent,
23
+ :action_class_override => AcdRunnerAction)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  module Proxy
2
2
  module Acd
3
- VERSION = '0.1.0'.freeze
3
+ VERSION = '0.4.0'.freeze
4
4
  end
5
5
  end
@@ -1,2 +1,4 @@
1
1
  ---
2
2
  :enabled: true
3
+ # The time we wait till the request to download the ansible playbook should be answered by the Foreman, in seconds.
4
+ :timeout: 60
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_acd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Bucher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-09 00:00:00.000000000 Z
11
+ date: 2022-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.50.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: smart_proxy_dynflow
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.5.0
27
41
  description: Application Centric Deployment smart proxy plugin
28
42
  email: info@atix.de
29
43
  executables: []
@@ -40,6 +54,8 @@ files:
40
54
  - lib/smart_proxy_acd/acd_api.rb
41
55
  - lib/smart_proxy_acd/acd_http_config.ru
42
56
  - lib/smart_proxy_acd/acd_main.rb
57
+ - lib/smart_proxy_acd/acd_runner.rb
58
+ - lib/smart_proxy_acd/acd_task_launcher.rb
43
59
  - lib/smart_proxy_acd/version.rb
44
60
  - settings.d/acd.yml.example
45
61
  homepage: http://github.com/ATIX-AG/smart_proxy_acd