kitchen-ansiblepush 0.5.3 → 0.6.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: cb4b5ceb255051cc628af09ac710a0fadd99931d
4
- data.tar.gz: d54177928e491e1f6d73e851c6d3baee468b0c5b
3
+ metadata.gz: 2a0b0a4fa393de63e8bd3466018bb8f615fa71c4
4
+ data.tar.gz: 28c252f822f9d7a1a95c33023a2f7acf25733720
5
5
  SHA512:
6
- metadata.gz: 7cd93aaac94558292f01820391fd742989db1e901cef5031ed12a6ba1548476861590962e608ab97e782abd1e7ae965c7672aeb3fd57ae7cf935581c23b4c412
7
- data.tar.gz: 5a4d583388acd1eb84e7a182d811f00628a39ad1c4828c8cb7f5a9b403e6906b9994eb79358dbeb6c6f0b531cd144fd3924058685d828424f0a5b93af581803a
6
+ metadata.gz: 619db0de823c83576045e5895b72003acfe3440b151fff0b678722f8f5d271fb79d5af34632ba32d81c86505666d1b6ad8917046d48b49fc3c1012d361f77024
7
+ data.tar.gz: d628391563eac8b09f20ef5865b05c72a877525bdc727ed4e2e38143bf182335e8e86de0bc145f0820dd7c1e3dce4313f55ddc33a35de5e109689400242e91fe
@@ -1,45 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
- require 'yaml'
3
- require 'json'
4
- require 'kitchen-ansible/util_inventory.rb'
5
2
 
6
- all = []
7
- groups = Hash.new
8
- hosts = Hash.new
9
- if File.exist?(TEMP_GROUP_FILE)
10
- groups = YAML::load_file TEMP_GROUP_FILE
11
- end
3
+ require 'kitchen-ansible/print_inventory_cli.rb'
12
4
 
13
- Dir.glob(TEMP_INV_DIR + '/ansiblepush_host_*.yml') do |inv_yml|
14
- vm = YAML::load_file inv_yml
15
- vm.each do |host, host_attr|
16
- if host_attr["mygroup"]
17
- if host_attr["mygroup"].is_a?(Hash)
18
- host_attr["mygroup"].each do | group |
19
- groups[group] ||= []
20
- groups[group] << host
21
- end
22
- elsif host_attr["mygroup"].kind_of?(String)
23
- groups[host_attr["mygroup"]] ||= []
24
- groups[host_attr["mygroup"]] << host
25
- elsif host_attr["mygroup"].kind_of?(Array)
26
- host_attr["mygroup"].each do | group |
27
- groups[group] ||= []
28
- groups[group] << host
29
- end
30
- end
31
- end
32
- host_attr.delete("mygroup")
33
- hosts[host] = host_attr
34
- all << host
35
- end
36
- end
37
-
38
- inventory = { "all" => all, "_meta" => { "hostvars" => hosts }}
39
-
40
-
41
-
42
- inventory = groups.merge(inventory)
43
-
44
- # Print our inventory
45
- puts JSON.pretty_generate(inventory)
5
+ print_inventory = PrintInventory.new
6
+ print_inventory.run
data/callback/changes.py CHANGED
@@ -29,7 +29,7 @@ class CallbackModule(CallbackBase):
29
29
  os.remove(self.change_file)
30
30
  except OSError as e: # this would be "except OSError, e:" before Python 2.6
31
31
  if e.errno != errno.ENOENT: # errno.ENOENT = no such file or directory
32
- raise # re-raise exception if a different error occured
32
+ raise # re-raise exception if a different error occurred
33
33
 
34
34
 
35
35
  def write_changed_to_file(self, host, res, name=None):
@@ -108,4 +108,4 @@ class CallbackModule(CallbackBase):
108
108
  pass
109
109
 
110
110
  def playbook_on_stats(self, stats):
111
- pass
111
+ print "Call back end"
@@ -27,6 +27,4 @@ Supports running ansible in push mode
27
27
  EOF
28
28
 
29
29
  gem.add_runtime_dependency 'test-kitchen', '~> 1.4'
30
- gem.add_development_dependency 'rspec'
31
- gem.add_development_dependency 'pry'
32
30
  end
@@ -0,0 +1,30 @@
1
+ require 'securerandom'
2
+
3
+ def idempotency_test
4
+ info('*************** idempotency test ***************')
5
+ file_path = "/tmp/kitchen_ansible_callback/#{SecureRandom.uuid}.changes"
6
+ exec_ansible_command(
7
+ command_env.merge(
8
+ 'ANSIBLE_CALLBACK_PLUGINS' => "#{File.dirname(__FILE__)}/../../callback/",
9
+ 'ANSIBLE_CALLBACK_WHITELIST' => 'changes',
10
+ 'PLUGIN_CHANGES_FILE' => file_path
11
+ ), command, 'ansible-playbook'
12
+ )
13
+ debug("idempotency file #{file_path}")
14
+ # Check ansible callback if changes has occured in the second run
15
+ if File.file?(file_path)
16
+ task = 0
17
+ info('idempotency test [Failed]')
18
+ File.open(file_path, 'r') do |f|
19
+ f.each_line do |line|
20
+ task += 1
21
+ info(" #{task}> #{line.strip}")
22
+ end
23
+ end
24
+ raise "idempotency test Failed. Number of non idempotent tasks: #{task}" if conf[:fail_non_idempotent]
25
+ # If we reach this point we should give a warning
26
+ info('Warning idempotency test [failed]')
27
+ else
28
+ info('idempotency test [passed]')
29
+ end
30
+ end
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ require 'yaml'
3
+ require 'json'
4
+ require 'kitchen-ansible/util_inventory.rb'
5
+
6
+ class PrintInventory
7
+ def initialize
8
+ @inventory = {}
9
+ @all = []
10
+ @groups = if File.exist?(TEMP_GROUP_FILE)
11
+ read_from_yaml TEMP_GROUP_FILE
12
+ else
13
+ {}
14
+ end
15
+ @hosts = {}
16
+ end
17
+
18
+ def read_from_yaml(yaml_file)
19
+ YAML.load_file yaml_file
20
+ end
21
+
22
+ def read_all_hosts
23
+ Dir.glob(TEMP_INV_DIR + '/ansiblepush_host_*.yml')
24
+ end
25
+
26
+ def construct
27
+ read_all_hosts.each do |inv_yml|
28
+ vm = read_from_yaml inv_yml
29
+ vm.each do |host, host_attr|
30
+ if host_attr['mygroup']
31
+ if host_attr['mygroup'].is_a?(Hash)
32
+ host_attr['mygroup'].each do |group|
33
+ @groups[group] ||= []
34
+ @groups[group] << host
35
+ end
36
+ elsif host_attr['mygroup'].is_a?(String)
37
+ @groups[host_attr['mygroup']] ||= []
38
+ @groups[host_attr['mygroup']] << host
39
+ elsif host_attr['mygroup'].is_a?(Array)
40
+ host_attr['mygroup'].each do |group|
41
+ @groups[group] ||= []
42
+ @groups[group] << host
43
+ end
44
+ end
45
+ end
46
+ host_attr.delete('mygroup')
47
+ @hosts[host] = host_attr
48
+ @all << host
49
+ end
50
+ end
51
+
52
+ @inventory = { 'all' => @all, '_meta' => { 'hostvars' => @hosts } }
53
+ @groups.merge(@inventory)
54
+ end
55
+
56
+ def output_json
57
+ puts JSON.pretty_generate(@inventory)
58
+ end
59
+
60
+ def run
61
+ @inventory = construct
62
+ output_json
63
+ end
64
+ end
@@ -1,5 +1,5 @@
1
1
  module Kitchen
2
2
  module AnsiblePush
3
- VERSION = '0.5.3'.freeze
3
+ VERSION = '0.6.0'.freeze
4
4
  end
5
5
  end
@@ -1,10 +1,11 @@
1
+ require 'json'
1
2
  require 'open3'
2
3
  require 'kitchen'
4
+ require 'kitchen/errors'
3
5
  require 'kitchen/provisioner/base'
4
- require 'kitchen-ansible/util_inventory.rb'
5
- require 'kitchen-ansible/chef_installation.rb'
6
- require 'json'
7
- require 'securerandom'
6
+ require 'kitchen-ansible/util_inventory'
7
+ require 'kitchen-ansible/chef_installation'
8
+ require 'kitchen-ansible/idempotancy'
8
9
 
9
10
  module Kitchen
10
11
  class Busser
@@ -23,6 +24,9 @@ module Kitchen
23
24
  default_config :groups, nil
24
25
  default_config :extra_vars, nil
25
26
  default_config :sudo, nil
27
+ default_config :become, nil
28
+ default_config :become_user, nil
29
+ default_config :become_method, nil
26
30
  default_config :sudo_user, nil
27
31
  default_config :remote_user, nil
28
32
  default_config :private_key, nil
@@ -42,6 +46,15 @@ module Kitchen
42
46
  default_config :fail_non_idempotent, true
43
47
  default_config :use_instance_name, false
44
48
  default_config :ansible_connection, 'smart'
49
+ default_config :timeout, nil
50
+ default_config :force_handlers, nil
51
+ default_config :step, nil
52
+ default_config :module_path, nil
53
+ default_config :scp_extra_args, nil
54
+ default_config :sftp_extra_args, nil
55
+ default_config :ssh_extra_args, nil
56
+ default_config :ssh_common_args, nil
57
+ default_config :module_path, nil
45
58
 
46
59
  # For tests disable if not needed
47
60
  default_config :chef_bootstrap_url, 'https://omnitruck.chef.io/install.sh'
@@ -51,12 +64,12 @@ module Kitchen
51
64
  def conf
52
65
  return @validated_config if defined? @validated_config
53
66
 
54
- raise 'No playbook defined. Please specify one in .kitchen.yml' unless config[:playbook]
67
+ raise UserError, 'No playbook defined. Please specify one in .kitchen.yml' unless config[:playbook]
55
68
 
56
- raise "playbook '#{config[:playbook]}' could not be found. Please check path" unless File.exist?(config[:playbook])
69
+ raise UserError, "playbook '#{config[:playbook]}' could not be found. Please check path" unless File.exist?(config[:playbook])
57
70
 
58
71
  if config[:vault_password_file] && !File.exist?(config[:vault_password_file])
59
- raise "Vault password '#{config[:vault_password_file]}' could not be found. Please check path"
72
+ raise UserError, "Vault password '#{config[:vault_password_file]}' could not be found. Please check path"
60
73
  end
61
74
 
62
75
  # Validate that extra_vars is either a hash, or a path to an existing file
@@ -72,7 +85,7 @@ module Kitchen
72
85
  @extra_vars = '@' + extra_vars_path if extra_vars_is_valid
73
86
  end
74
87
 
75
- raise "ansible extra_vars is in valid type: #{config[:extra_vars].class} value: #{config[:extra_vars]}" unless extra_vars_is_valid
88
+ raise UserError, "ansible extra_vars is in valid type: #{config[:extra_vars].class} value: #{config[:extra_vars]}" unless extra_vars_is_valid
76
89
  end
77
90
  info('Ansible push config validated')
78
91
  @validated_config = config
@@ -89,32 +102,53 @@ module Kitchen
89
102
  @machine_name
90
103
  end
91
104
 
105
+ def options_user
106
+ ## Support sudo and become
107
+ temp_options = []
108
+ raise UserError, '"sudo" and "become" are mutually_exclusive' if conf[:sudo] && conf[:become]
109
+ temp_options << '--become' if conf[:sudo] || conf[:become]
110
+
111
+ raise UserError, '"sudo_user" and "become_user" are mutually_exclusive' if conf[:sudo_user] && conf[:become_user]
112
+ if conf[:sudo_user]
113
+ temp_options << "--become-user=#{conf[:sudo_user]}"
114
+ elsif conf[:become_user]
115
+ temp_options << "--become-user=#{conf[:become_user]}"
116
+ end
117
+ temp_options << "--user=#{conf[:remote_user]}" if remote_user
118
+ temp_options << "--become-method=#{conf[:become_method]}" if conf[:become_method]
119
+ temp_options << '--ask-sudo-pass' if conf[:ask_sudo_pass]
120
+ temp_options
121
+ end
122
+
92
123
  def options
93
124
  return @options if defined? @options
94
- options = []
125
+ # options = options_user | options
126
+ options = options_user
95
127
  options << "--extra-vars='#{extra_vars_argument}'" if conf[:extra_vars]
96
- options << '--sudo' if conf[:sudo]
97
- options << "--sudo-user=#{conf[:sudo_user]}" if conf[:sudo_user]
98
- options << "--user=#{conf[:remote_user]}" if remote_user
99
128
  options << "--private-key=#{conf[:private_key]}" if conf[:private_key]
100
- options << verbosity_argument.to_s if conf[:verbose]
101
129
  options << '--diff' if conf[:diff]
102
- options << '--ask-sudo-pass' if conf[:ask_sudo_pass]
103
130
  options << '--ask-vault-pass' if conf[:ask_vault_pass]
104
131
  options << "--vault-password-file=#{conf[:vault_password_file]}" if conf[:vault_password_file]
105
132
  options << '--tags=#{as_list_argument(conf[:tags])}' if conf[:tags]
106
133
  options << '--skip-tags=#{as_list_argument(conf[:skip_tags])}' if conf[:skip_tags]
107
134
  options << "--start-at-task=#{conf[:start_at_task]}" if conf[:start_at_task]
108
135
  options << "--inventory-file=#{conf[:generate_inv_path]}" if conf[:generate_inv]
109
-
136
+ options << verbosity_argument.to_s if conf[:verbose]
110
137
  # By default we limit by the current machine,
111
138
  options << if conf[:limit]
112
139
  "--limit=#{as_list_argument(conf[:limit])}"
113
140
  else
114
141
  "--limit=#{machine_name}"
115
142
  end
116
-
117
- # Add raw argument as final thing
143
+ options << "--timeout=#{conf[:timeout]}" if conf[:timeout]
144
+ options << "--force-handlers=#{conf[:force_handlers]}" if conf[:force_handlers]
145
+ options << "--step=#{conf[:step]}" if conf[:step]
146
+ options << "--module-path=#{conf[:module_path]}" if conf[:module_path]
147
+ options << "--scp-extra-args=#{conf[:scp_extra_args]}" if conf[:scp_extra_args]
148
+ options << "--sftp-extra-args=#{conf[:sftp_extra_args]}" if conf[:sftp_extra_args]
149
+ options << "--ssh-common-args=#{conf[:ssh_common_args]}" if conf[:ssh_common_args]
150
+ options << "--ssh-extra-args=#{conf[:ssh_extra_args]}" if conf[:ssh_extra_args]
151
+ # Add raw argument at the end
118
152
  options << conf[:raw_arguments] if conf[:raw_arguments]
119
153
  @options = options
120
154
  end
@@ -154,15 +188,12 @@ module Kitchen
154
188
  end
155
189
 
156
190
  def install_command
157
- # Must install chef for busser and serverspec to work :(
158
191
  info('*************** AnsiblePush install_command ***************')
159
192
  # Test if ansible-playbook is installed and give a meaningful error message
160
193
  version_check = command + ' --version'
161
194
  _, stdout, stderr, wait_thr = Open3.popen3(command_env, version_check)
162
195
  exit_status = wait_thr.value
163
-
164
- raise "#{version_check} returned a non zero '#{exit_status}' stdout : #{stdout}, stderr: #{stderr}" unless exit_status.success?
165
-
196
+ raise UserError, "#{version_check} returned a non zero '#{exit_status}' stdout : #{stdout}, stderr: #{stderr}" unless exit_status.success?
166
197
  omnibus_download_dir = conf[:omnibus_cachier] ? '/tmp/vagrant-cache/omnibus_chef' : '/tmp'
167
198
  chef_installation(conf[:chef_bootstrap_url], omnibus_download_dir)
168
199
  end
@@ -176,45 +207,17 @@ module Kitchen
176
207
  sh -c #{scripts.join("\n")}
177
208
  INSTALL
178
209
  else
179
- true_command
210
+ true_command # Place holder so a string is returned. This will execute true on remote host
180
211
  end
181
212
  end
182
213
 
183
214
  def run_command
184
215
  info('*************** AnsiblePush run ***************')
185
216
  exec_ansible_command(command_env, command, 'ansible-playbook')
186
- # idempotency test
187
- if conf[:idempotency_test]
188
- info('*************** idempotency test ***************')
189
- file_path = "/tmp/kitchen_ansible_callback/#{SecureRandom.uuid}.changes"
190
- exec_ansible_command(
191
- command_env.merge(
192
- 'ANSIBLE_CALLBACK_PLUGINS' => "#{File.dirname(__FILE__)}/../../../callback/",
193
- 'PLUGIN_CHANGES_FILE' => file_path
194
- ), command, 'ansible-playbook'
195
- )
196
- debug("idempotency file #{file_path}")
197
- # Check ansible callback if changes has occured in the second run
198
- if File.file?(file_path)
199
- task = 0
200
- info('idempotency test [Failed]')
201
- File.open(file_path, 'r') do |f|
202
- f.each_line do |line|
203
- task += 1
204
- info(" #{task}> #{line.strip}")
205
- end
206
- end
207
- raise "idempotency test Failed. Number of non idempotent tasks: #{task}" if conf[:fail_non_idempotent]
208
- # If we reach this point we should give a warning
209
- info('Warning idempotency test [failed]')
210
- else
211
- info('idempotency test [passed]')
212
- end
213
- end
217
+ idempotency_test if conf[:idempotency_test]
214
218
  info('*************** AnsiblePush end run *******************')
215
219
  debug("[#{name}] Converge completed (#{conf[:sleep]}s).")
216
- # Place holder so a string is returned. This will execute true on remote host
217
- true_command
220
+ true_command # Place holder so a string is returned. This will execute true on remote host
218
221
  end
219
222
 
220
223
  protected
@@ -224,7 +227,7 @@ module Kitchen
224
227
  system(env, command.to_s)
225
228
  exit_code = $CHILD_STATUS.exitstatus
226
229
  debug("ansible-playbook exit code = #{exit_code}")
227
- raise "#{desc} returned a non zero #{exit_code}. Please see the output above." if exit_code.to_i != 0
230
+ raise UserError, "#{desc} returned a non zero #{exit_code}. Please see the output above." if exit_code.to_i != 0
228
231
  end
229
232
 
230
233
  def instance_connection_option
@@ -254,11 +257,10 @@ module Kitchen
254
257
 
255
258
  def extra_vars_argument
256
259
  if conf[:extra_vars].is_a?(String) && conf[:extra_vars] =~ /^@.+$/
257
- # A JSON or YAML file is referenced (requires Ansible 1.3+)
260
+ # A JSON or YAML file is referenced
258
261
  conf[:extra_vars]
259
262
  else
260
- # Expected to be a Hash after config validation. (extra_vars as
261
- # JSON requires Ansible 1.2+, while YAML requires Ansible 1.3+)
263
+ # Expected to be a Hash after config validation.
262
264
  conf[:extra_vars].to_json
263
265
  end
264
266
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-ansiblepush
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adham Helal
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-31 00:00:00.000000000 Z
11
+ date: 2017-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-kitchen
@@ -24,34 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.4'
27
- - !ruby/object:Gem::Dependency
28
- name: rspec
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: pry
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
27
  description: |+
56
28
  == DESCRIPTION:
57
29
 
@@ -73,6 +45,8 @@ files:
73
45
  - callback/changes.py
74
46
  - kitchen-ansiblepush.gemspec
75
47
  - lib/kitchen-ansible/chef_installation.rb
48
+ - lib/kitchen-ansible/idempotancy.rb
49
+ - lib/kitchen-ansible/print_inventory_cli.rb
76
50
  - lib/kitchen-ansible/util_inventory.rb
77
51
  - lib/kitchen-ansible/version.rb
78
52
  - lib/kitchen/provisioner/ansible_push.rb