Skip to content

Commit db14259

Browse files
committed
(maint) uncouple from the puppet_litmus gem
vagrant is still todo
1 parent a134735 commit db14259

12 files changed

+182
-127
lines changed

README.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ $ cat ~/.fog
103103
##### Setting up a new machine
104104

105105
```ruby
106-
$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::abs --targets localhost action=provision platform=ubuntu-1604-x86_64 inventory=/Users/tp/workspace/git/provision/inventory.yaml
106+
$ bundle exec bolt task run provision::abs --targets localhost action=provision platform=ubuntu-1604-x86_64
107107

108108
Started on localhost...
109109
Finished on localhost:
@@ -118,7 +118,7 @@ Ran on 1 node in 1.44 seconds
118118
##### Tearing down a finished machine
119119

120120
```ruby
121-
$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::abs --targets localhost action=tear_down inventory=/Users/tp/workspace/git/provision/inventory.yaml node_name=yh6f4djvz7o3te6.delivery.puppetlabs.net
121+
$ bundle exec bolt task run provision::abs --targets localhost action=tear_down node_name=yh6f4djvz7o3te6.delivery.puppetlabs.net
122122

123123
Started on localhost...
124124
Finished on localhost:
@@ -139,7 +139,7 @@ Containers by default will be managed in the current [docker context](https://do
139139
#### Provision
140140

141141
```ruby
142-
$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 inventory=/Users/tp/workspace/git/provision/inventory.yaml
142+
$ bundle exec bolt task run provision::docker --targets localhost action=provision platform=ubuntu:14.04
143143

144144
Started on localhost...
145145
Finished on localhost:
@@ -166,13 +166,13 @@ These defaults can be overriden by passing the flags with different values i.e.
166166
```
167167

168168
```ruby
169-
bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 inventory=/Users/tp/workspace/git/provision/inventory.yaml vars='{ "docker_run_opts": ["-p 8086:8086", "-p 3000:3000"]}'
169+
bundle exec bolt task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 vars='{ "docker_run_opts": ["-p 8086:8086", "-p 3000:3000"]}'
170170
```
171171

172172
#### Tear down
173173

174174
```ruby
175-
$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::docker --targets localhost action=tear_down inventory=/Users/tp/workspace/git/provision/inventory.yaml node_name=localhost:2222
175+
$ bundle exec bolt task run provision::docker --targets localhost action=tear_down node_name=localhost:2222
176176

177177
Started on localhost...
178178
Finished on localhost:
@@ -197,7 +197,7 @@ Tested with vagrant images:
197197
provision
198198

199199
```ruby
200-
$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::vagrant --targets localhost action=provision platform=ubuntu/xenial64 inventory=/Users/tp/workspace/git/provision/inventory.yaml
200+
$ bundle exec bolt task run provision::vagrant --targets localhost action=provision platform=ubuntu/xenial64
201201

202202
Started on localhost...
203203
Finished on localhost:
@@ -217,7 +217,7 @@ This leads to errors when anything tries to execute `puppet` commands on the tes
217217
To add the Puppet agent binary path to the *secure_path* please run the `provision::fix_secure_path` Bolt task:
218218

219219
```ruby
220-
$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::fix_secure_path path=/opt/puppetlabs/bin -i inventory.yaml -t ssh_nodes
220+
$ bundle exec bolt task run provision::fix_secure_path path=/opt/puppetlabs/bin -i inventory.yaml -t ssh_nodes
221221

222222
Started on 127.0.0.1:2222...
223223
Finished on 127.0.0.1:2222:
@@ -229,7 +229,7 @@ Ran on 1 target in 0.84 sec
229229
tear_down
230230

231231
```ruby
232-
$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::vagrant --targets localhost action=tear_down inventory=/Users/tp/workspace/git/provision/inventory.yaml node_name=127.0.0.1:2222
232+
$ bundle exec bolt task run provision::vagrant --targets localhost action=tear_down node_name=127.0.0.1:2222
233233

234234
Started on localhost...
235235
Finished on localhost:
@@ -284,7 +284,7 @@ In the provision step you can invoke bundle exec rake 'litmus:provision_list[tes
284284
Manual invocation of the provision service task from a workflow can be done using:
285285

286286
```ruby
287-
bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::provision_service --targets localhost action=provision platform=centos-7-v20200813 inventory=/Users/tp/workspace/git/provision/inventory.yaml
287+
bolt task run provision::provision_service --targets localhost action=provision platform=centos-7-v20200813
288288
```
289289

290290
Or using Litmus:
@@ -320,7 +320,7 @@ provision
320320

321321
```powershell
322322
PS> $env:LITMUS_HYPERV_VSWITCH = 'internal_nat'
323-
PS> bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::vagrant --targets localhost action=provision platform=centos/7 inventory=/Users/tp/workspace/git/provision/inventory.yaml hyperv_smb_username=tp hyperv_smb_password=notMyrealPassword
323+
PS> bundle exec bolt task run provision::vagrant --targets localhost action=provision platform=centos/7 hyperv_smb_username=tp hyperv_smb_password=notMyrealPassword
324324
325325
Started on localhost...
326326
Finished on localhost:
@@ -353,7 +353,7 @@ Testing/development/debugging it is better to use ruby directly, you will need t
353353
Testing using bolt, the second step
354354

355355
```ruby
356-
bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 inventory=/Users/tp/workspace/git/provision/inventory.yaml
356+
bundle exec bolt task run provision::docker --targets localhost action=provision platform=ubuntu:14.04
357357
```
358358

359359
## License

lib/docker_helper.rb

+2-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# frozen_string_literal: true
22

33
require 'json'
4-
require 'puppet_litmus'
54

65
def docker_exec(container, command)
76
run_local_command("docker exec #{container} #{command}")
@@ -34,18 +33,8 @@ def docker_image_os_release_facts(image)
3433
os_release_facts
3534
end
3635

37-
def docker_tear_down(node_name, inventory_location)
38-
extend PuppetLitmus::InventoryManipulation
39-
inventory_full_path = File.join(inventory_location, '/spec/fixtures/litmus_inventory.yaml')
40-
raise "Unable to find '#{inventory_full_path}'" unless File.file?(inventory_full_path)
41-
42-
inventory_hash = inventory_hash_from_inventory_file(inventory_full_path)
43-
node_facts = facts_from_node(inventory_hash, node_name)
44-
remove_docker = "docker rm -f #{node_facts['container_id']}"
45-
run_local_command(remove_docker)
46-
remove_node(inventory_hash, node_name)
47-
puts "Removed #{node_name}"
48-
File.open(inventory_full_path, 'w') { |f| f.write inventory_hash.to_yaml }
36+
def docker_tear_down(node)
37+
run_local_command("docker rm -f #{node['facts']['container_id']}")
4938
{ status: 'ok' }
5039
end
5140

lib/inventory_helper.rb

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# frozen_string_literal: true
2+
3+
require 'yaml'
4+
require 'delegate'
5+
6+
class InventoryHelper < SimpleDelegator
7+
def initialize(location)
8+
@location = location
9+
super(refresh)
10+
end
11+
12+
# Load inventory from location in YAML format
13+
# or generate a default structure
14+
#
15+
# @return [Hash]
16+
def refresh
17+
x = YAML.load_file(@location) if File.file?(@location)
18+
{ 'version' => 2, 'groups' => [] }.merge(x || {})
19+
end
20+
21+
# Save inventory to location in yaml format
22+
def save
23+
File.open(@location, 'wb+') { |f| f.write(self.to_yaml) }
24+
end
25+
26+
# Adds a node to a group specified, if group_name exists in inventory hash.
27+
#
28+
# @param node [Hash] node to add to the group
29+
# @param group [String] group of nodes to limit the search for the node_name in
30+
# @return [Hash] inventory_hash with node added to group if group_name exists in inventory hash.
31+
def add(node, group)
32+
# check if group exists
33+
if self['groups'].any? { |g| g['name'] == group }
34+
self['groups'].each do |g|
35+
g['targets'].push(node) if g['name'] == group
36+
end
37+
else
38+
# add new group
39+
self['groups'].push({ 'name' => group, 'targets' => [node] })
40+
end
41+
42+
self
43+
end
44+
45+
# Lookup a node
46+
#
47+
# @param uri [String] uri of node to find
48+
# @param name [String] name of node to find
49+
# @param group [String] limit search to group
50+
# @return [Hash] inventory target
51+
def lookup(uri=nil, name: nil, group: nil)
52+
value = uri || name
53+
key = uri.nil? ? 'name' : 'uri'
54+
55+
self['groups'].each do |g|
56+
if (group && group == g['name']) || group.nil?
57+
g['targets'].each do |t|
58+
return t if t[key] == value
59+
end
60+
end
61+
end
62+
63+
raise "Failed to lookup target for #{key} #{value} in inventory"
64+
end
65+
66+
# Remove node
67+
#
68+
# @param node [Hash]
69+
# @return [Hash] inventory_hash with node of node_name removed.
70+
def remove(node)
71+
self['groups'].map! do |g|
72+
g['targets'].select! { |target| target != node }
73+
g
74+
end
75+
76+
self
77+
end
78+
79+
class << self
80+
attr_accessor :instances
81+
82+
def open(location = nil)
83+
# Inventory location is an optional task parameter.
84+
location = location.nil? ? Dir.pwd : location
85+
location = if File.directory?(location)
86+
# DEPRECATED: puppet_litmus <= 1.3.0 support
87+
if Gem.loaded_specs['puppet_litmus'] && Gem.loaded_specs['puppet_litmus'].version <= Gem::Version.new('1.3.0')
88+
File.join(location, 'spec', 'fixtures', 'litmus_inventory.yaml')
89+
else
90+
File.join(location, 'inventory.yaml')
91+
end
92+
else
93+
location
94+
end
95+
96+
@instances ||= Hash.new
97+
@instances[location] = self.new(location) unless @instances.key? location
98+
return @instances[location]
99+
end
100+
end
101+
102+
protected
103+
104+
attr_accessor :location
105+
end

lib/task_helper.rb

-24
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,5 @@
11
# frozen_string_literal: true
22

3-
def sanitise_inventory_location(location)
4-
# Inventory location is an optional task parameter.
5-
location = location.nil? ? Dir.pwd : location
6-
# If not specified use the current directory + inventory.yaml
7-
if File.exist?(location) && File.directory?(location)
8-
# DEPRECATED: puppet_litmus <= 1.3.0 support
9-
if Gem.loaded_specs['puppet_litmus'].version <= Gem::Version.new('1.3.0')
10-
File.join(location, 'spec', 'fixtures', 'litmus_inventory.yaml')
11-
else
12-
File.join(location, 'inventory.yaml')
13-
end
14-
else
15-
location
16-
end
17-
end
18-
19-
def get_inventory_hash(inventory_full_path)
20-
if File.file?(inventory_full_path)
21-
inventory_hash_from_inventory_file(inventory_full_path)
22-
else
23-
{ 'version' => 2, 'groups' => [{ 'name' => 'docker_nodes', 'targets' => [] }, { 'name' => 'ssh_nodes', 'targets' => [] }, { 'name' => 'winrm_nodes', 'targets' => [] }] }
24-
end
25-
end
26-
273
def run_local_command(command, dir = Dir.pwd)
284
require 'open3'
295
stdout, stderr, status = Open3.capture3(command, chdir: dir)

tasks/abs.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
}
2727
},
2828
"files": [
29-
"provision/lib/task_helper.rb"
29+
"provision/lib/task_helper.rb",
30+
"provision/lib/inventory_helper.rb"
3031
]
3132
}

tasks/abs.rb

+19-22
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@
44
require 'json'
55
require 'net/http'
66
require 'yaml'
7-
require 'puppet_litmus'
87
require 'etc'
98
require 'date'
109
require_relative '../lib/task_helper'
10+
require_relative '../lib/inventory_helper'
1111

1212
# Provision and teardown vms through ABS.
1313
class ABSProvision
14-
include PuppetLitmus::InventoryManipulation
15-
1614
# Enforces a k8s.infracore.puppet.net domain, but allows selection of prod,
1715
# stage, etc hostname from the environment variable +ABS_SUBDOMAIN+ so that
1816
# CI can test vms from staging.
@@ -23,7 +21,7 @@ def abs_host
2321
"#{subdomain}.k8s.infracore.puppet.net"
2422
end
2523

26-
def provision(platform, inventory_location, vars)
24+
def provision(platform, inventory, vars)
2725
uri = URI.parse("https://#{abs_host}/api/v2/request")
2826
jenkins_build_url = if ENV['CI'] == 'true' && ENV['TRAVIS'] == 'true'
2927
ENV.fetch('TRAVIS_JOB_WEB_URL', nil)
@@ -85,7 +83,6 @@ def provision(platform, inventory_location, vars)
8583

8684
raise "Timeout: unable to get a 200 response in #{poll_duration} seconds" if reply.code != '200'
8785

88-
inventory_hash = get_inventory_hash(inventory_location)
8986
data = JSON.parse(reply.body)
9087
data.each do |host|
9188
if platform_uses_ssh(host['type'])
@@ -109,27 +106,26 @@ def provision(platform, inventory_location, vars)
109106
var_hash = YAML.safe_load(vars)
110107
node['vars'] = var_hash
111108
end
112-
add_node_to_group(inventory_hash, node, group_name)
109+
inventory.add(node, group_name)
113110
end
114111

115-
File.open(inventory_location, 'w') { |f| f.write inventory_hash.to_yaml }
112+
inventory.save
116113
{ status: 'ok', nodes: data.length }
117114
end
118115

119-
def tear_down(node_name, inventory_location)
120-
if File.file?(inventory_location)
121-
inventory_hash = inventory_hash_from_inventory_file(inventory_location)
122-
facts = facts_from_node(inventory_hash, node_name)
123-
platform = facts['platform']
124-
job_id = facts['job_id']
125-
end
116+
def tear_down(node_name, inventory)
117+
node = inventory.lookup(name: node_name)
118+
facts = node['facts']
119+
platform = facts['platform']
120+
job_id = facts['job_id']
126121

127122
targets_to_remove = []
128-
inventory_hash['groups'].each do |group|
123+
inventory['groups'].each do |group|
129124
group['targets'].each do |node|
130-
targets_to_remove.push(node['uri']) if node['facts']['job_id'] == job_id
125+
targets_to_remove.push(node) if node['facts']['job_id'] == job_id
131126
end
132127
end
128+
133129
uri = URI.parse("https://#{abs_host}/api/v2/return")
134130
headers = { 'X-AUTH-TOKEN' => token_from_fogfile('abs'), 'Content-Type' => 'application/json' }
135131
payload = { 'job_id' => job_id,
@@ -143,16 +139,17 @@ def tear_down(node_name, inventory_location)
143139
raise "Error: #{reply}: #{reply.message}" unless reply.code == '200'
144140

145141
targets_to_remove.each do |target|
146-
remove_node(inventory_hash, target)
142+
inventory.remove(target)
147143
end
148-
File.open(inventory_location, 'w') { |f| f.write inventory_hash.to_yaml }
149-
{ status: 'ok', removed: targets_to_remove }
144+
inventory.save
145+
146+
{ status: 'ok', removed: targets_to_remove.map { |t| t['name'] } }
150147
end
151148

152149
def task(action:, platform: nil, node_name: nil, inventory: nil, vars: nil, **_kwargs)
153-
inventory_location = sanitise_inventory_location(inventory)
154-
result = provision(platform, inventory_location, vars) if action == 'provision'
155-
result = tear_down(node_name, inventory_location) if action == 'tear_down'
150+
inventory = InventoryHelper.open(inventory)
151+
result = provision(platform, inventory, vars) if action == 'provision'
152+
result = tear_down(node_name, inventory) if action == 'tear_down'
156153
result
157154
end
158155

tasks/docker.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
},
2828
"files": [
2929
"provision/lib/task_helper.rb",
30-
"provision/lib/docker_helper.rb"
30+
"provision/lib/docker_helper.rb",
31+
"provision/lib/inventory_helper.rb"
3132
]
3233
}

0 commit comments

Comments
 (0)