ansible_spec 0.2.23 → 0.3.2

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.
Files changed (31) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +7 -4
  3. data/CHANGELOG.md +19 -0
  4. data/Gemfile +5 -0
  5. data/README.md +1 -1
  6. data/ansible_spec.gemspec +2 -1
  7. data/lib/ansible_spec/load_ansible.rb +106 -9
  8. data/lib/ansible_spec/version.rb +1 -1
  9. data/lib/src/spec/spec_helper.rb +5 -4
  10. data/spec/case/get_variable/empty_group/group_vars/group_a.yml +2 -0
  11. data/spec/case/get_variable/empty_group/group_vars/group_b.yml +2 -0
  12. data/spec/case/get_variable/empty_group/hosts +3 -0
  13. data/spec/case/get_variable/empty_group/site.yml +9 -0
  14. data/spec/case/get_variable/group_each_vars_parent_child/group_vars/all.yml +6 -0
  15. data/spec/case/get_variable/group_each_vars_parent_child/group_vars/group1/vars +4 -0
  16. data/spec/case/get_variable/group_each_vars_parent_child/group_vars/group2/vars +4 -0
  17. data/spec/case/get_variable/group_each_vars_parent_child/group_vars/parentgroup/vars +5 -0
  18. data/spec/case/get_variable/group_each_vars_parent_child/hosts +13 -0
  19. data/spec/case/get_variable/group_each_vars_parent_child/site.yml +6 -0
  20. data/spec/case/get_variable/group_each_vars_parent_child/site1.yml +6 -0
  21. data/spec/case/get_variable/group_each_vars_parent_child/site2.yml +6 -0
  22. data/spec/case/get_variable/group_each_vars_parent_child/site3.yml +6 -0
  23. data/spec/case/get_variable/resolve_variables/group_vars/all.yml +24 -0
  24. data/spec/case/get_variable/resolve_variables/hosts +5 -0
  25. data/spec/case/get_variable/resolve_variables/site.yml +3 -0
  26. data/spec/case/load_vars_file/vault_dir/ansible.cfg +2 -0
  27. data/spec/case/load_vars_file/vault_dir/group_vars/all/vault_file +6 -0
  28. data/spec/case/load_vars_file/vault_dir/vault-password-file +1 -0
  29. data/spec/get_variable_spec.rb +239 -25
  30. data/spec/load_ansible_spec.rb +303 -4
  31. metadata +80 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ea92ad1db5c6331ab0f51cb0cc9f8357d6fad5a1
4
- data.tar.gz: 3529e094be9910fb8acb9c1e3df7661e4e21135e
2
+ SHA256:
3
+ metadata.gz: d77ce9fa38453ab6f652cc6c20a79509c722d615790cb49b59ec8e37154aad7b
4
+ data.tar.gz: 27384622e2d91ad928ee5b37fa061efa3b80af5baad5b887823ec3df7e83dded
5
5
  SHA512:
6
- metadata.gz: 4f8121627c3ffb1b2011e8b77d2ef0704b8f64ab59075c2973e7768c7fb26a1c21606332acdb7a6faedc1d4d17be4287abf354de010fc4c72ded2d7db003aa88
7
- data.tar.gz: ded735c540319da5a2443d9639390f3e0a5d915a5249e410d0295f3f32b99b09bcc6625384d2778784bf8f7484f4f199a6a5c52b6dce9eb2f0a6149927f59d3b
6
+ metadata.gz: 2591637e35a8fa5fe8f2add17e24d5f32844030d9fd1f268ec4a0e607bb4f2500ef8a75c166c337d20c8e97c8db979dc1bdf317f64f5f93095493699bef37665
7
+ data.tar.gz: e1124d4328dc3430545f94a87306fc9148f3b91bc5074d84180edac293966115b15794e5ecd142335a2c972415143f7893bf6516d951bfb4b4ffd1f2855d561d
@@ -1,12 +1,15 @@
1
1
  language: ruby
2
+ dist: trusty # work at Ubuntu 14.04 for install Ruby 1.9.3
2
3
  sudo: false
3
4
  rvm:
4
5
  - 1.9.3
5
6
  - 2.0.0
6
7
  - 2.1.10
7
- - 2.2.9
8
- - 2.3.6
9
- - 2.4.3
10
- - 2.5.0
8
+ - 2.2.10
9
+ - 2.3.8
10
+ - 2.4.10
11
+ - 2.5.8
12
+ - 2.6.6
13
+ - 2.7.1
11
14
  script:
12
15
  - rspec spec
@@ -1,3 +1,22 @@
1
+ # v0.3.2
2
+ - Merge [#135 Fix wrong index by empty group](https://github.com/volanja/ansible_spec/pull/135) by [mamiya312](https://github.com/mamiya312)
3
+
4
+ # v0.3.1
5
+ - Fix [#126 no implicit conversion of nil into Array Error when process get_parent](https://github.com/volanja/ansible_spec/issues/126) by [shogos3](https://github.com/shogos3)
6
+
7
+ # v0.3
8
+ - Support Ansible Vault (Run Ruby 2.1.0 and higher.)
9
+ - Merge [#116 Feature ansible vault](https://github.com/volanja/ansible_spec/pull/116) by [RebelCodeBase](https://github.com/RebelCodeBase)
10
+ - Merge [#123 skip test at unsupported version ref ansible vault](https://github.com/volanja/ansible_spec/pull/123) by volanja
11
+
12
+ And Some Bug Fixed. See [Milestone v0.3](https://github.com/volanja/ansible_spec/milestone/13?closed=1)
13
+
14
+ # v0.2.25
15
+ - Merge [#118 Incorporate group parent child relationships into variable assignment hierarchy](https://github.com/volanja/ansible_spec/pull/118) by [rbramwell](https://github.com/rbramwell)
16
+
17
+ # v0.2.24
18
+ - Merge [#117 Feature resolve variables](https://github.com/volanja/ansible_spec/pull/117) by [RebelCodeBase](https://github.com/RebelCodeBase)
19
+
1
20
  # v0.2.23
2
21
  - Merge [#115 Support import_playbook](https://github.com/volanja/ansible_spec/pull/115) by [seiji](https://github.com/seiji)
3
22
  - Merge [#113 Make ENV variables override SSH config file options](https://github.com/volanja/ansible_spec/pull/113) by [Jonnymcc](https://github.com/Jonnymcc)
data/Gemfile CHANGED
@@ -13,3 +13,8 @@ if Gem::Version.new(RUBY_VERSION.dup) <= Gem::Version.new('1.9.3')
13
13
  # winrm 2.1.1 dropped Ruby 1.9 support.
14
14
  gem 'winrm', '< 2.1.1'
15
15
  end
16
+
17
+ if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1')
18
+ # Ansible::Vault support Ruby 2.1.0 and higher.
19
+ gem 'ansible-vault'
20
+ end
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ansible_spec
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/ansible_spec.svg)](http://badge.fury.io/rb/ansible_spec)
3
+ [![Gem Version](https://badge.fury.io/rb/ansible_spec.svg)](https://badge.fury.io/rb/ansible_spec)
4
4
  [![Build Status](https://travis-ci.org/volanja/ansible_spec.svg?branch=master)](https://travis-ci.org/volanja/ansible_spec)
5
5
 
6
6
  This is a Ruby gem that implements an Ansible Config Parser for Serverspec.
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_development_dependency "bundler", "~> 1.3"
21
+ gem.add_development_dependency "bundler"
22
22
  gem.add_development_dependency "rake"
23
23
  gem.add_development_dependency "diff-lcs"
24
24
  gem.add_development_dependency "simplecov"
@@ -28,5 +28,6 @@ Gem::Specification.new do |gem|
28
28
  gem.add_runtime_dependency "oj"
29
29
  gem.add_runtime_dependency "winrm"
30
30
  gem.add_runtime_dependency "inifile"
31
+ gem.add_runtime_dependency "ansible-vault"
31
32
 
32
33
  end
@@ -5,12 +5,21 @@ require 'open3'
5
5
  require 'yaml'
6
6
  require 'inifile'
7
7
  require 'ansible_spec/vendor/hash'
8
+ if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1')
9
+ require 'ansible/vault'
10
+ end
8
11
 
9
12
  module AnsibleSpec
10
13
  # param: inventory file of Ansible
14
+ # param: return_type 'groups' or 'groups_parent_child_relationships'
11
15
  # return: Hash {"group" => ["192.168.0.1","192.168.0.2"]}
12
16
  # return: Hash {"group" => [{"name" => "192.168.0.1","uri" => "192.168.0.1", "port" => 22},...]}
13
- def self.load_targets(file)
17
+ # return: Hash {"pg" => ["server", "databases"]}
18
+ def self.load_targets(file, return_type = 'groups')
19
+ if not ['groups', 'groups_parent_child_relationships'].include?(return_type)
20
+ raise ArgumentError, "Variable return_type must be value 'groups' or 'groups_parent_child_relationships'"
21
+ end
22
+
14
23
  if File.executable?(file)
15
24
  return get_dynamic_inventory(file)
16
25
  end
@@ -20,7 +29,7 @@ module AnsibleSpec
20
29
  hosts = Hash.new
21
30
  hosts.default = Hash.new
22
31
  f.each_line{|line|
23
- line = line.chomp
32
+ line = line.strip
24
33
  # skip
25
34
  next if line.start_with?('#') #comment
26
35
  next if line.empty? == true #null
@@ -67,8 +76,12 @@ module AnsibleSpec
67
76
 
68
77
  # parse children [group:children]
69
78
  search = Regexp.new(":children".to_s)
79
+ groups_parent_child_relationships = Hash.new
70
80
  groups.keys.each{|k|
71
81
  unless (k =~ search).nil?
82
+ # get parent child relationships
83
+ k_parent = k.gsub(search,'')
84
+ groups_parent_child_relationships["#{k_parent}"] = groups["#{k}"]
72
85
  # get group parent & merge parent
73
86
  groups.merge!(get_parent(groups,search,k))
74
87
  # delete group children
@@ -77,7 +90,15 @@ module AnsibleSpec
77
90
  end
78
91
  end
79
92
  }
80
- return groups
93
+
94
+ return_value = groups # default
95
+ if return_type == 'groups'
96
+ return_value = groups
97
+ elsif return_type == 'groups_parent_child_relationships'
98
+ return_value = groups_parent_child_relationships
99
+ end
100
+
101
+ return return_value
81
102
  end
82
103
 
83
104
  # param hash {"server"=>["192.168.0.103"], "databases"=>["192.168.0.104"], "pg:children"=>["server", "databases"]}
@@ -140,6 +161,7 @@ module AnsibleSpec
140
161
  # 初期値
141
162
  host['name'] = line
142
163
  host['port'] = 22
164
+ host['connection'] = "ssh"
143
165
  if line.include?(":") # 192.168.0.1:22
144
166
  host['uri'] = line.split(":")[0]
145
167
  host['port'] = line.split(":")[1].to_i
@@ -347,15 +369,39 @@ module AnsibleSpec
347
369
  if File.directory?(vars_file)
348
370
  Dir.glob(File.join(vars_file, '*')).each { |f|
349
371
  vars = load_vars_file(vars, f)
350
- }
372
+ }
351
373
  else
352
- yaml = YAML.load_file(vars_file)
353
- vars = merge_variables(vars, yaml)
374
+ # you can use Ansible::Vault when use ruby 2.1.0 and higher.
375
+ # Ansible::Vault support Ruby 2.1.0 and higher.
376
+ if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1')
377
+ if Ansible::Vault.encrypted?(vars_file)
378
+ yaml = load_encrypted_file(vars_file)
379
+ else
380
+ yaml = YAML.load_file(vars_file)
381
+ end
382
+ vars = merge_variables(vars, yaml)
383
+ else
384
+ # Ruby 1.9 and 2.0
385
+ yaml = YAML.load_file(vars_file)
386
+ vars = merge_variables(vars, yaml)
387
+ end
354
388
  end
355
389
  end
356
390
  return vars
357
391
  end
358
392
 
393
+ # param: variable file
394
+ # return: be merged hash
395
+ def self.load_encrypted_file(vars_file)
396
+ cfg = AnsibleSpec::AnsibleCfg.new
397
+ vault_password_file = cfg.get('defaults', 'vault_password_file')
398
+ if vault_password_file
399
+ vault_password = File.open(vault_password_file).read.chomp
400
+ yaml = YAML.load(Ansible::Vault.read(path: vars_file, password: vault_password))
401
+ end
402
+ return yaml
403
+ end
404
+
359
405
  # param: target hash
360
406
  # param: be merged hash
361
407
  def self.merge_variables(vars, hash)
@@ -431,9 +477,46 @@ module AnsibleSpec
431
477
  target_host.keys[0]
432
478
  end
433
479
 
480
+ # query replace jinja2 templates with target values
481
+ # param: hash (cf. result self.get_variables)
482
+ # param: number of iterations if found_template
483
+ # return: hash
484
+ def self.resolve_variables(vars, max_level=100)
485
+ vars_yaml = vars.to_yaml
486
+ level = 0
487
+ begin
488
+ found_template = false
489
+ level += 1
490
+
491
+ # query replace jinja2 templates in yaml
492
+ # replace in-place (gsub!)
493
+ # use non-greedy regex (.*?)
494
+ vars_yaml.gsub!(/{{.*?}}/) do |template|
495
+
496
+ # grab target variable
497
+ # ignore whitespaces (\s*)
498
+ # use non-greedy regex (.*?)
499
+ target = template.gsub(/{{\s*(.*?)\s*}}/, '\1')
500
+
501
+ # lookup value of target variable
502
+ value = vars[target]
503
+
504
+ # return lookup value if it exists
505
+ # or leave template alone
506
+ if value.nil?
507
+ template
508
+ else
509
+ found_template = true
510
+ value
511
+ end
512
+ end
513
+ end while found_template and level <= max_level
514
+ return YAML.load(vars_yaml)
515
+ end
516
+
434
517
  def self.get_variables(host, group_idx, hosts=nil)
435
518
  vars = {}
436
- p = self.get_properties
519
+ p = self.get_properties.compact.reject{|e| e["hosts"].length == 0}
437
520
 
438
521
  # roles default
439
522
  p[group_idx]['roles'].each do |role|
@@ -451,7 +534,21 @@ module AnsibleSpec
451
534
 
452
535
  # each group vars
453
536
  if p[group_idx].has_key?('group')
454
- vars = load_vars_file(vars ,"#{vars_dirs_path}group_vars/#{p[group_idx]['group']}", true)
537
+ # get groups parent child relationships
538
+ playbook, inventoryfile = load_ansiblespec
539
+ groups_rels = load_targets(inventoryfile, return_type='groups_parent_child_relationships')
540
+ # get parental lineage
541
+ g = p[group_idx]['group']
542
+ groups_stack = Array.new
543
+ groups_stack << g
544
+ groups_rels.keys.each{|k|
545
+ groups_stack << k if (groups_rels[k].include?(g))
546
+ }
547
+ # get vars from parents groups then child group
548
+ groups_parents_then_child = groups_stack.reverse.flatten
549
+ groups_parents_then_child.each{|group|
550
+ vars = load_vars_file(vars ,"#{vars_dirs_path}group_vars/#{group}", true)
551
+ }
455
552
  end
456
553
 
457
554
  # each host vars
@@ -479,7 +576,7 @@ module AnsibleSpec
479
576
  end
480
577
  end
481
578
 
482
- return vars
579
+ return resolve_variables(vars)
483
580
 
484
581
  end
485
582
 
@@ -1,3 +1,3 @@
1
1
  module AnsibleSpec
2
- VERSION = "0.2.23"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -23,15 +23,16 @@ when 'ssh'
23
23
  #
24
24
  set :backend, :ssh
25
25
 
26
+ # Ansible use `BECOME`, But Serverspec use `SUDO`.
26
27
  if ENV['ASK_BECOME_PASSWORD']
27
28
  begin
28
29
  require 'highline/import'
29
30
  rescue LoadError
30
31
  fail "highline is not available. Try installing it."
31
32
  end
32
- set :become_password, ask("Enter become password: ") { |q| q.echo = false }
33
+ set :sudo_password, ask("Enter become password: ") { |q| q.echo = false }
33
34
  else
34
- set :become_password, ENV['BECOME_PASSWORD']
35
+ set :sudo_password, ENV['BECOME_PASSWORD']
35
36
  end
36
37
 
37
38
  options = Net::SSH::Config.for(host)
@@ -48,8 +49,8 @@ when 'ssh'
48
49
  set :host, options[:host_name] || host
49
50
  set :ssh_options, options
50
51
 
51
- # Disable become
52
- # set :become, false
52
+ # Disable become (Serverspec use sudo)
53
+ # set :disable_sudo, true
53
54
 
54
55
 
55
56
  # Set environment variables
@@ -0,0 +1,2 @@
1
+ ---
2
+ group_a_var: hoge
@@ -0,0 +1,2 @@
1
+ ---
2
+ group_b_var: fuga
@@ -0,0 +1,3 @@
1
+ [group_a]
2
+ [group_b]
3
+ localhost.localdomain ansible_ssh_private_key_file=~/.ssh/id_rsa
@@ -0,0 +1,9 @@
1
+ ---
2
+ - name: playbook_a
3
+ hosts: group_a
4
+ roles:
5
+ - role_a
6
+ - name: playbook_b
7
+ hosts: group_b
8
+ roles:
9
+ - role_b
@@ -0,0 +1,6 @@
1
+ ---
2
+ role_var: "group all"
3
+ site_var: "group all"
4
+ host_var: "group all"
5
+ group_var: "group all"
6
+ group_all_var: "group all"
@@ -0,0 +1,4 @@
1
+ role_var: "group1"
2
+ site_var: "group1"
3
+ host_var: "group1"
4
+ group_var: 'group1'
@@ -0,0 +1,4 @@
1
+ role_var: "group2"
2
+ site_var: "group2"
3
+ host_var: "group2"
4
+ group_var: 'group2'
@@ -0,0 +1,5 @@
1
+ role_var: "parentgroup"
2
+ site_var: "parentgroup"
3
+ host_var: "parentgroup"
4
+ group_var: 'parentgroup'
5
+ group_var_parent: 'parentgroup'
@@ -0,0 +1,13 @@
1
+ [group1]
2
+ 192.168.1.1
3
+
4
+ [group2]
5
+ 192.168.1.2
6
+
7
+ [all]
8
+ 192.168.1.1
9
+ 192.168.1.2
10
+
11
+ [parentgroup:children]
12
+ group1
13
+ group2
@@ -0,0 +1,6 @@
1
+ - name: group1
2
+ hosts: group1
3
+ connection: local
4
+ roles:
5
+ - test
6
+ - test/nested
@@ -0,0 +1,6 @@
1
+ - name: group1
2
+ hosts: group1
3
+ connection: local
4
+ roles:
5
+ - test
6
+ - test/nested
@@ -0,0 +1,6 @@
1
+ - name: group2
2
+ hosts: group2
3
+ connection: local
4
+ roles:
5
+ - test
6
+ - test/nested
@@ -0,0 +1,6 @@
1
+ - name: parentgroup
2
+ hosts: parentgroup
3
+ connection: local
4
+ roles:
5
+ - test
6
+ - test/nested
@@ -0,0 +1,24 @@
1
+ ---
2
+ var_nested_one_1: 'val_nested_one'
3
+ var_nested_one_2: "{{ var_nested_one_1 }}"
4
+
5
+ var_nested_two_1: 'val_nested_two'
6
+ var_nested_two_2: "{{ var_nested_two_1 }}"
7
+ var_nested_two_3: "{{ var_nested_two_2 }}"
8
+
9
+ var_nested_hash_1: 'val_hash'
10
+ var_nested_hash_2:
11
+ key: "{{ var_nested_hash_1 }}"
12
+
13
+ var_nested_array_1: 'val_array'
14
+ var_nested_array_2:
15
+ - "{{ var_nested_array_1 }}"
16
+
17
+ var_nested_array_hash_1: 'val_array_hash'
18
+ var_nested_array_hash_2:
19
+ - key: "{{ var_nested_array_hash_1 }}"
20
+
21
+ var_nested_whitespace_1: val_nested_whitespace
22
+ var_nested_whitespace_2: "{{var_nested_whitespace_1 }}"
23
+
24
+ var_missingtarget_2: "{{ var_missingtarget_1 }}"
@@ -0,0 +1,5 @@
1
+ [resolve]
2
+ 192.168.1.1
3
+
4
+
5
+