knife-topo 1.1.2 → 2.0.1
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.
- checksums.yaml +4 -4
- data/README.md +125 -148
- data/knife-topo.gemspec +12 -12
- data/lib/chef/knife/topo/bootstrap_helper.rb +75 -0
- data/lib/chef/knife/topo/command_helper.rb +71 -0
- data/lib/chef/knife/topo/consts.rb +4 -0
- data/lib/chef/knife/topo/loader.rb +137 -0
- data/lib/chef/knife/topo/node_update_helper.rb +111 -0
- data/lib/chef/knife/topo/processor.rb +76 -0
- data/lib/chef/knife/topo/processor/via_cookbook.rb +118 -0
- data/lib/chef/knife/topo/processor/via_cookbook_print.rb +97 -0
- data/lib/chef/knife/topo/version.rb +3 -4
- data/lib/chef/knife/topo_bootstrap.rb +107 -79
- data/lib/chef/knife/topo_cookbook_create.rb +41 -144
- data/lib/chef/knife/topo_cookbook_upload.rb +40 -54
- data/lib/chef/knife/topo_create.rb +120 -132
- data/lib/chef/knife/topo_delete.rb +67 -65
- data/lib/chef/knife/topo_export.rb +108 -133
- data/lib/chef/knife/topo_import.rb +62 -76
- data/lib/chef/knife/topo_list.rb +18 -25
- data/lib/chef/knife/topo_search.rb +61 -61
- data/lib/chef/knife/topo_update.rb +25 -110
- data/lib/chef/topo/converter.rb +75 -0
- data/lib/chef/topo/converter/topo_v1.rb +123 -0
- data/lib/chef/topology.rb +137 -0
- metadata +13 -3
- data/lib/chef/knife/topology_helper.rb +0 -366
@@ -0,0 +1,137 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/data_bag_item'
|
20
|
+
require 'chef/topo/converter'
|
21
|
+
require 'chef/mixin/deep_merge'
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
# Topology
|
25
|
+
class Topology < Chef::DataBagItem
|
26
|
+
attr_accessor :strategy
|
27
|
+
|
28
|
+
PRIORITIES = %w(default force_default normal override force_override)
|
29
|
+
|
30
|
+
# Have to override and say this is a data bag json_class
|
31
|
+
# or get error on upload re 'must specify id'
|
32
|
+
def to_json(*a)
|
33
|
+
result = {
|
34
|
+
'name' => object_name,
|
35
|
+
'json_class' => Chef::DataBagItem.name,
|
36
|
+
'chef_type' => 'data_bag_item',
|
37
|
+
'data_bag' => data_bag,
|
38
|
+
'raw_data' => raw_data
|
39
|
+
}
|
40
|
+
Chef::JSONCompat.to_json(result, *a)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.convert_from(format, data)
|
44
|
+
from_json((Chef::Topo::Converter.convert(format, data)))
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.from_json(data)
|
48
|
+
topo = new
|
49
|
+
topo.raw_data = data
|
50
|
+
topo
|
51
|
+
end
|
52
|
+
|
53
|
+
# Make sure the JSON has an id and other expected fields
|
54
|
+
def raw_data=(new_data)
|
55
|
+
new_data['id'] ||= (new_data['name'] || 'undefined')
|
56
|
+
new_data['nodes'] ||= []
|
57
|
+
super(normalize(new_data))
|
58
|
+
@strategy = raw_data['strategy'] || 'direct_to_node'
|
59
|
+
end
|
60
|
+
|
61
|
+
# clean up some variations so we only have to process one way
|
62
|
+
# in particular, allow 'attributes' as a synonym for 'normal'
|
63
|
+
def normalize(data)
|
64
|
+
data['nodes'] = data['nodes'].map do |n|
|
65
|
+
if n.key?('attributes')
|
66
|
+
n['normal'] = Chef::Mixin::DeepMerge.merge(
|
67
|
+
n['normal'], n['attributes']
|
68
|
+
)
|
69
|
+
n.delete('attributes')
|
70
|
+
end
|
71
|
+
n
|
72
|
+
end
|
73
|
+
data
|
74
|
+
end
|
75
|
+
|
76
|
+
def display_info
|
77
|
+
buildstamp = raw_data['buildstamp']
|
78
|
+
info = buildstamp ? ' buildstamp: ' + buildstamp : ''
|
79
|
+
display_name + info
|
80
|
+
end
|
81
|
+
|
82
|
+
def display_name
|
83
|
+
version = topo_version ? ' version: ' + topo_version : ''
|
84
|
+
topo_name + version
|
85
|
+
end
|
86
|
+
|
87
|
+
def topo_version
|
88
|
+
version = raw_data['version']
|
89
|
+
if version
|
90
|
+
version = version + '-' + raw_data['buildid'] if raw_data['buildid']
|
91
|
+
end
|
92
|
+
version
|
93
|
+
end
|
94
|
+
|
95
|
+
def topo_name
|
96
|
+
raw_data['name']
|
97
|
+
end
|
98
|
+
|
99
|
+
def nodes
|
100
|
+
raw_data['nodes']
|
101
|
+
end
|
102
|
+
|
103
|
+
# nodes with topo properties merged in
|
104
|
+
def merged_nodes
|
105
|
+
nodes.map do |n|
|
106
|
+
Chef::Mixin::DeepMerge.merge(node_defaults, n)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def node_defaults
|
111
|
+
defaults = {}
|
112
|
+
%w(chef_environment tags).each do |k|
|
113
|
+
defaults[k] = raw_data[k] if raw_data[k]
|
114
|
+
end
|
115
|
+
|
116
|
+
PRIORITIES.reverse_each do |p|
|
117
|
+
a = default_attrs(p)
|
118
|
+
defaults[p] = a if a
|
119
|
+
end
|
120
|
+
# Make sure we're not sharing objects
|
121
|
+
Mash.from_hash(Marshal.load(Marshal.dump(defaults)))
|
122
|
+
end
|
123
|
+
|
124
|
+
def default_attrs(priority)
|
125
|
+
return raw_data[priority] unless priority == 'normal'
|
126
|
+
add_topo_attrs(raw_data['normal'])
|
127
|
+
end
|
128
|
+
|
129
|
+
def add_topo_attrs(attrs)
|
130
|
+
a = attrs || {}
|
131
|
+
a['topo'] ||= {}
|
132
|
+
a['topo']['name'] = topo_name
|
133
|
+
a['topo']['node_type'] = a['node_type'] if a['node_type']
|
134
|
+
a
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-topo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christine Draper
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Knife-topo uses a JSON file to capture a topology of nodes, which can
|
14
14
|
be loaded into Chef and bootstrapped
|
@@ -21,6 +21,14 @@ files:
|
|
21
21
|
- LICENSE
|
22
22
|
- README.md
|
23
23
|
- knife-topo.gemspec
|
24
|
+
- lib/chef/knife/topo/bootstrap_helper.rb
|
25
|
+
- lib/chef/knife/topo/command_helper.rb
|
26
|
+
- lib/chef/knife/topo/consts.rb
|
27
|
+
- lib/chef/knife/topo/loader.rb
|
28
|
+
- lib/chef/knife/topo/node_update_helper.rb
|
29
|
+
- lib/chef/knife/topo/processor.rb
|
30
|
+
- lib/chef/knife/topo/processor/via_cookbook.rb
|
31
|
+
- lib/chef/knife/topo/processor/via_cookbook_print.rb
|
24
32
|
- lib/chef/knife/topo/version.rb
|
25
33
|
- lib/chef/knife/topo_bootstrap.rb
|
26
34
|
- lib/chef/knife/topo_cookbook_create.rb
|
@@ -32,7 +40,9 @@ files:
|
|
32
40
|
- lib/chef/knife/topo_list.rb
|
33
41
|
- lib/chef/knife/topo_search.rb
|
34
42
|
- lib/chef/knife/topo_update.rb
|
35
|
-
- lib/chef/
|
43
|
+
- lib/chef/topo/converter.rb
|
44
|
+
- lib/chef/topo/converter/topo_v1.rb
|
45
|
+
- lib/chef/topology.rb
|
36
46
|
homepage: https://github.com/christinedraper/knife-topo
|
37
47
|
licenses:
|
38
48
|
- Apache License (2.0)
|
@@ -1,366 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
-
# Copyright:: Copyright (c) 2014 ThirdWave Insights LLC
|
4
|
-
# License:: Apache License, Version 2.0
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
#
|
18
|
-
|
19
|
-
require 'chef/data_bag'
|
20
|
-
require 'chef/node'
|
21
|
-
require 'chef/encrypted_data_bag_item'
|
22
|
-
require 'chef/environment'
|
23
|
-
require 'chef/knife/core/object_loader'
|
24
|
-
require 'chef/rest'
|
25
|
-
|
26
|
-
class Chef
|
27
|
-
class Knife
|
28
|
-
module TopologyHelper
|
29
|
-
|
30
|
-
# load one or more topologies from file
|
31
|
-
def load_topologies(topology_file_path)
|
32
|
-
|
33
|
-
if ! topology_file_path.end_with?('.js', '.json')
|
34
|
-
show_usage
|
35
|
-
ui.fatal "TOPOLOGY_FILE must be a '.js' or '.json' file"
|
36
|
-
exit(1)
|
37
|
-
end
|
38
|
-
|
39
|
-
topologies = loader.object_from_file(topology_file_path)
|
40
|
-
topologies = [topologies] if !topologies.kind_of?(Array)
|
41
|
-
|
42
|
-
topologies
|
43
|
-
end
|
44
|
-
|
45
|
-
# create the topology data bag
|
46
|
-
def create_bag(bag_name)
|
47
|
-
# check that the name is valid
|
48
|
-
begin
|
49
|
-
Chef::DataBag.validate_name!(bag_name)
|
50
|
-
rescue Chef::Exceptions::InvalidDataBagName => e
|
51
|
-
ui.fatal(e.message)
|
52
|
-
exit(1)
|
53
|
-
end
|
54
|
-
|
55
|
-
# create the data bag
|
56
|
-
begin
|
57
|
-
data_bag = Chef::DataBag.new
|
58
|
-
data_bag.name(bag_name)
|
59
|
-
data_bag.create
|
60
|
-
ui.info("Created topology data bag [#{bag_name}]")
|
61
|
-
rescue Net::HTTPServerException => e
|
62
|
-
raise unless e.to_s =~ /^409/
|
63
|
-
data_bag = Chef::DataBag.load(bag_name)
|
64
|
-
ui.info("Topology data bag #{bag_name} already exists")
|
65
|
-
end
|
66
|
-
|
67
|
-
data_bag
|
68
|
-
end
|
69
|
-
|
70
|
-
# make sure the chef environment exists
|
71
|
-
def check_chef_env(chef_env_name)
|
72
|
-
|
73
|
-
if chef_env_name
|
74
|
-
begin
|
75
|
-
chef_env = Chef::Environment.load(chef_env_name)
|
76
|
-
rescue Net::HTTPServerException => e
|
77
|
-
raise unless e.to_s =~ /^404/
|
78
|
-
ui.info "Creating chef environment " + chef_env_name
|
79
|
-
chef_env = Chef::Environment.new()
|
80
|
-
chef_env.name(chef_env_name)
|
81
|
-
chef_env.create
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
chef_env
|
86
|
-
end
|
87
|
-
|
88
|
-
# recursive merge that retains all keys
|
89
|
-
def prop_merge!(hash, other_hash)
|
90
|
-
other_hash.each do |key, val|
|
91
|
-
if val.kind_of?(Hash) && hash[key]
|
92
|
-
prop_merge!(hash[key], val)
|
93
|
-
else
|
94
|
-
hash[key] = val
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
hash
|
99
|
-
end
|
100
|
-
|
101
|
-
# Merges topology properties into nodes, returning the merged nodes
|
102
|
-
def merge_topo_properties(nodes, topo_hash)
|
103
|
-
|
104
|
-
if nodes && nodes.length > 0
|
105
|
-
merged_nodes = nodes ? nodes.clone : []
|
106
|
-
merged_nodes.each do |nodeprops|
|
107
|
-
|
108
|
-
normal_defaults = topo_hash['normal'] ?
|
109
|
-
Marshal.load(Marshal.dump(topo_hash['normal'])) : {}
|
110
|
-
nodeprops['normal'] ||= {}
|
111
|
-
nodeprops['normal'] = prop_merge!(normal_defaults, nodeprops['normal'])
|
112
|
-
nodeprops['normal'] = prop_merge!(nodeprops['normal'], nodeprops['attributes']) if nodeprops['attributes']
|
113
|
-
nodeprops['normal'] = prop_merge!(nodeprops['normal'], { "topo" => { "name" => topo_hash['name'] }})
|
114
|
-
|
115
|
-
nodeprops['chef_environment'] ||= topo_hash['chef_environment'] if topo_hash['chef_environment']
|
116
|
-
|
117
|
-
# merge in the topology tags
|
118
|
-
nodeprops['tags'] ||= []
|
119
|
-
nodeprops['tags'] |= topo_hash['tags'] if topo_hash['tags'] && topo_hash['tags'].length > 0
|
120
|
-
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
merged_nodes
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
# Update an existing node
|
130
|
-
def update_node(node_updates)
|
131
|
-
|
132
|
-
config[:disable_editing] = true
|
133
|
-
|
134
|
-
node_name = node_updates['name']
|
135
|
-
begin
|
136
|
-
|
137
|
-
# load then update and save the node
|
138
|
-
node = Chef::Node.load(node_name)
|
139
|
-
|
140
|
-
if node_updates['chef_environment'] && node_updates['chef_environment'] != node['chef_environment']
|
141
|
-
check_chef_env(node_updates['chef_environment'])
|
142
|
-
end
|
143
|
-
|
144
|
-
if updated_values = update_node_with_values(node, node_updates)
|
145
|
-
ui.info "Updating #{updated_values.join(', ')} on node #{node.name}"
|
146
|
-
node.save
|
147
|
-
ui.output(format_for_display(node)) if config[:print_after]
|
148
|
-
else
|
149
|
-
ui.info "No updates found for node #{node.name}"
|
150
|
-
end
|
151
|
-
|
152
|
-
rescue Net::HTTPServerException => e
|
153
|
-
raise unless e.to_s =~ /^404/
|
154
|
-
# Node has not been created
|
155
|
-
end
|
156
|
-
|
157
|
-
return node
|
158
|
-
end
|
159
|
-
|
160
|
-
# Make updates into the original node, returning the list of updated properties.
|
161
|
-
def update_node_with_values(node, updates)
|
162
|
-
updated_properties = []
|
163
|
-
|
164
|
-
# merge the normal attributes (but not tags)
|
165
|
-
normal_updates = updates['normal'] || {}
|
166
|
-
normal_updates.delete('tags')
|
167
|
-
original_normal = node.normal.clone()
|
168
|
-
prop_merge!(node.normal, normal_updates)
|
169
|
-
updated_properties << 'normal' if (original_normal != node.normal)
|
170
|
-
|
171
|
-
# merge with existing runlist
|
172
|
-
if updates['run_list']
|
173
|
-
updated_run_list = RunList.new
|
174
|
-
updates['run_list'].each { |e| updated_run_list << e }
|
175
|
-
if (updated_run_list != node.run_list)
|
176
|
-
updated_properties << 'run_list'
|
177
|
-
node.run_list(*updated_run_list)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
# update chef env
|
182
|
-
new_chef_environment = updates['chef_environment']
|
183
|
-
if new_chef_environment && new_chef_environment != node.chef_environment
|
184
|
-
updated_properties << 'chef_environment'
|
185
|
-
node.chef_environment(new_chef_environment)
|
186
|
-
end
|
187
|
-
|
188
|
-
# merge tags
|
189
|
-
orig_num_tags = node.tags.length
|
190
|
-
updates['tags'] ||= [] # make sure tags are initialized
|
191
|
-
node.tag(*updates['tags'])
|
192
|
-
updated_properties << 'tags' if node.tags.length > orig_num_tags
|
193
|
-
|
194
|
-
# return false if no updates, else return array of property names
|
195
|
-
updated_properties.length > 0 && updated_properties
|
196
|
-
end
|
197
|
-
|
198
|
-
# Load a topology from local data bag item file
|
199
|
-
def load_from_file(bag_name, topo_name)
|
200
|
-
|
201
|
-
topo_file = File.join(Dir.pwd, "#{topologies_path}", bag_name, topo_name + '.json')
|
202
|
-
return unless (loader.file_exists_and_is_readable?(topo_file))
|
203
|
-
|
204
|
-
item_data = loader.object_from_file(topo_file)
|
205
|
-
item_data = if use_encryption
|
206
|
-
secret = read_secret
|
207
|
-
Chef::EncryptedDataBagItem.encrypt_data_bag_item(item_data, secret)
|
208
|
-
else
|
209
|
-
item_data
|
210
|
-
end
|
211
|
-
item = Chef::DataBagItem.new
|
212
|
-
item.data_bag(bag_name)
|
213
|
-
item.raw_data = item_data
|
214
|
-
item
|
215
|
-
end
|
216
|
-
|
217
|
-
# read in the topology bag item
|
218
|
-
def load_from_server(bag_name, item_name = nil)
|
219
|
-
begin
|
220
|
-
if (item_name)
|
221
|
-
item = Chef::DataBagItem.load(bag_name, item_name)
|
222
|
-
item = Chef::EncryptedDataBagItem.new(item.raw_data, read_secret) if use_encryption
|
223
|
-
else
|
224
|
-
item = Chef::DataBag.load(bag_name)
|
225
|
-
end
|
226
|
-
rescue Net::HTTPServerException => e
|
227
|
-
raise unless e.to_s =~ /^404/
|
228
|
-
end
|
229
|
-
item
|
230
|
-
end
|
231
|
-
|
232
|
-
# Replace existing run list in a node
|
233
|
-
def set_run_list(node, entries)
|
234
|
-
node.run_list.run_list_items.clear
|
235
|
-
entries.each { |e| node.run_list << e }
|
236
|
-
end
|
237
|
-
|
238
|
-
# Name of the topology bag
|
239
|
-
def topo_bag_name(name=nil)
|
240
|
-
@topo_bag_name = name if (name)
|
241
|
-
@topo_bag_name ||= "topologies"
|
242
|
-
end
|
243
|
-
|
244
|
-
# Path for the topologies data bags.
|
245
|
-
# For now, use the standard data_bags path for our topologies bags
|
246
|
-
def topologies_path
|
247
|
-
@topologies_path ||= "data_bags"
|
248
|
-
end
|
249
|
-
|
250
|
-
# Loader to get data bag items from file
|
251
|
-
def loader
|
252
|
-
@loader ||= Knife::Core::ObjectLoader.new(DataBagItem, ui)
|
253
|
-
end
|
254
|
-
|
255
|
-
# Determine if the bag items are/should be encrypted on server
|
256
|
-
# NOTE: This option isnt currently enabled
|
257
|
-
def use_encryption
|
258
|
-
if config[:secret] && config[:secret_file]
|
259
|
-
ui.fatal("please specify only one of --secret, --secret-file")
|
260
|
-
exit(1)
|
261
|
-
end
|
262
|
-
config[:secret] || config[:secret_file]
|
263
|
-
end
|
264
|
-
|
265
|
-
# Return the secret key to encrypt/decrypt data bag items
|
266
|
-
def read_secret
|
267
|
-
if config[:secret]
|
268
|
-
config[:secret]
|
269
|
-
else
|
270
|
-
Chef::EncryptedDataBagItem.load_secret(config[:secret_file])
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
# initialize args for another knife command
|
275
|
-
def initialize_cmd_args(args, new_name_args)
|
276
|
-
args = args.dup
|
277
|
-
args.shift(2 + @name_args.length)
|
278
|
-
cmd_args = new_name_args + args
|
279
|
-
end
|
280
|
-
|
281
|
-
# run another knife command
|
282
|
-
def run_cmd(command_class, args)
|
283
|
-
command = command_class.new(args)
|
284
|
-
command.config[:config_file] = config[:config_file]
|
285
|
-
command.configure_chef
|
286
|
-
command.run
|
287
|
-
|
288
|
-
command
|
289
|
-
end
|
290
|
-
|
291
|
-
# upload cookbooks - will warn and continue if upload fails (e.g. may be frozen)
|
292
|
-
def upload_cookbooks(args)
|
293
|
-
begin
|
294
|
-
run_cmd(Chef::Knife::TopoCookbookUpload, args)
|
295
|
-
rescue Exception => e
|
296
|
-
raise if Chef::Config[:verbosity] == 2
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
def display_name (topo)
|
301
|
-
topo['name'] + ((topo['version']) ? " version " + format_topo_version(topo) : "")
|
302
|
-
end
|
303
|
-
|
304
|
-
# Topology version
|
305
|
-
def format_topo_version(topo)
|
306
|
-
version = nil
|
307
|
-
if topo['version']
|
308
|
-
version = topo['version']
|
309
|
-
version = version + '-' + topo['buildid'] if (topo['buildid'])
|
310
|
-
end
|
311
|
-
|
312
|
-
version
|
313
|
-
end
|
314
|
-
|
315
|
-
# check if resource exists
|
316
|
-
def resource_exists?(relative_path)
|
317
|
-
rest.get_rest(relative_path)
|
318
|
-
true
|
319
|
-
rescue Net::HTTPServerException => e
|
320
|
-
raise unless e.response.code == "404"
|
321
|
-
false
|
322
|
-
end
|
323
|
-
|
324
|
-
# Setup the bootstrap args and run the bootstrap command
|
325
|
-
def run_bootstrap(node_data, bootstrap_args, overwrite=false)
|
326
|
-
node_name = node_data['name']
|
327
|
-
|
328
|
-
args = bootstrap_args
|
329
|
-
|
330
|
-
# We need to remove the --bootstrap option, if it exists, because its not valid for knife bootstrap
|
331
|
-
args -= ['--bootstrap']
|
332
|
-
|
333
|
-
# And set up the node-specific data
|
334
|
-
args += ['-N', node_name] if(node_name)
|
335
|
-
args += ['-E', node_data['chef_environment']] if(node_data['chef_environment'])
|
336
|
-
args[1] = node_data['ssh_host']
|
337
|
-
args += [ '--ssh-port', node_data['ssh_port']] if node_data['ssh_port']
|
338
|
-
args += [ '--run-list' , node_data['run_list'].join(',')] if node_data['run_list']
|
339
|
-
args += [ '--json-attributes' , node_data['normal'].to_json] if node_data['normal']
|
340
|
-
|
341
|
-
if overwrite
|
342
|
-
ui.info("Node #{node_name} exists and will be overwritten")
|
343
|
-
# delete node first so vault refresh does not pick up existing node
|
344
|
-
begin
|
345
|
-
rest.delete("nodes/#{node_name}")
|
346
|
-
rest.delete("clients/#{node_name}")
|
347
|
-
rescue Net::HTTPServerException => e
|
348
|
-
raise unless e.response.code == "404"
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
ui.info "Bootstrapping node #{node_name}"
|
353
|
-
begin
|
354
|
-
run_cmd(Chef::Knife::Bootstrap, args)
|
355
|
-
true
|
356
|
-
rescue Exception => e
|
357
|
-
raise if Chef::Config[:verbosity] == 2
|
358
|
-
ui.warn "bootstrap of node #{node_name} exited with error"
|
359
|
-
humanize_exception(e)
|
360
|
-
false
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
end
|
365
|
-
end
|
366
|
-
end
|