ansible_spec 0.2.23 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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
+