knife-topo 1.1.0 → 1.1.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.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/lib/chef/knife/topo/version.rb +1 -1
- data/lib/chef/knife/topo_bootstrap.rb +32 -34
- data/lib/chef/knife/topo_cookbook_create.rb +1 -1
- data/lib/chef/knife/topo_create.rb +53 -13
- data/lib/chef/knife/topo_delete.rb +2 -2
- data/lib/chef/knife/topo_list.rb +6 -2
- data/lib/chef/knife/topology_helper.rb +52 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5982dbdd98f486734b60e5f8f7d6db46c18daf2
|
4
|
+
data.tar.gz: 8ba53f9163e5c9883f7098319c9a3955d9c24d14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a273459319db01f84a3bdfd1507ef5a1c9f201829087d439473fc38aeb2c68c1eec8c4699971b551081bb4f1ce2e6d85d1e7630eae07ba945326d073d833613
|
7
|
+
data.tar.gz: 644dd730a1e628f4adc3cf2d6f7b3e1f6dcacbb1f1e5e762df157aed9484a14aa0f998d583e760aa9337324ddca0ddc07d18bead4173488d59ed97a73cda9abb
|
data/README.md
CHANGED
@@ -338,7 +338,7 @@ The following will create the 'test1' topology, and bootstrap it.
|
|
338
338
|
The following will create the 'test1' topology but will not bootstrap it
|
339
339
|
or upload topology cookbooks.
|
340
340
|
|
341
|
-
$ knife topo create test1 --disable-upload
|
341
|
+
$ knife topo create test1 --disable-upload
|
342
342
|
|
343
343
|
## knife topo delete <a name="delete"></a>
|
344
344
|
|
@@ -378,17 +378,17 @@ Option | Description
|
|
378
378
|
The following will export the data for nodes n1 and n2 as part of a
|
379
379
|
topology called 'my_topo':
|
380
380
|
|
381
|
-
$ knife topo export n1 n2 --topo
|
381
|
+
$ knife topo export n1 n2 --topo my_topo > new_topo.json
|
382
382
|
|
383
383
|
|
384
|
-
The following will export all topologies to a file called 'all_topos.json'.
|
384
|
+
The following will export all existing topologies to a file called 'all_topos.json'.
|
385
385
|
|
386
386
|
$ knife topo export --all > all_topos.json
|
387
387
|
|
388
388
|
The following will create an outline for a new topology called
|
389
389
|
'christine_test', or export the current details if it already exists:
|
390
390
|
|
391
|
-
$ knife topo export --topo
|
391
|
+
$ knife topo export --topo christine_test > christine_test.json
|
392
392
|
|
393
393
|
|
394
394
|
## knife topo import <a name="import"></a>
|
@@ -34,6 +34,11 @@ class Chef
|
|
34
34
|
:short => '-D DATA_BAG',
|
35
35
|
:long => "--data-bag DATA_BAG",
|
36
36
|
:description => "The data bag the topologies are stored in"
|
37
|
+
|
38
|
+
option :overwrite,
|
39
|
+
:long => "--overwrite",
|
40
|
+
:description => "Whether to overwrite existing nodes",
|
41
|
+
:boolean => true
|
37
42
|
|
38
43
|
# Make the base bootstrap options available on topo bootstrap
|
39
44
|
self.options = (Chef::Knife::Bootstrap.options).merge(self.options)
|
@@ -65,50 +70,43 @@ class Chef
|
|
65
70
|
|
66
71
|
# load and bootstrap each node that has a ssh_host
|
67
72
|
nodes = merge_topo_properties(topo['nodes'], topo)
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
|
74
|
+
bootstrapped = []
|
75
|
+
skipped = []
|
76
|
+
existed = []
|
77
|
+
failed = []
|
78
|
+
|
71
79
|
if nodes.length > 0
|
72
80
|
nodes.each do |node_data|
|
73
|
-
|
74
|
-
|
75
|
-
|
81
|
+
node_name = node_data['name']
|
82
|
+
exists = resource_exists?("nodes/#{node_name}")
|
83
|
+
if(node_data['ssh_host'] && (config[:overwrite] || !exists))
|
84
|
+
if run_bootstrap(node_data, @bootstrap_args, exists)
|
85
|
+
bootstrapped << node_name
|
86
|
+
else
|
87
|
+
failed << node_name
|
88
|
+
end
|
76
89
|
else
|
77
|
-
|
78
|
-
|
90
|
+
if(exists)
|
91
|
+
existed << node_name
|
92
|
+
else
|
93
|
+
skipped << node_name
|
94
|
+
end
|
79
95
|
end
|
80
|
-
|
81
96
|
end
|
82
|
-
ui.info
|
83
|
-
ui.
|
97
|
+
ui.info("Bootstrapped #{bootstrapped.length} nodes [ #{bootstrapped.join(', ')} ]")
|
98
|
+
ui.info("Skipped #{skipped.length} nodes [ #{skipped.join(', ')} ] because they had no ssh_host information") if skipped.length > 0
|
99
|
+
if existed.length > 0
|
100
|
+
ui.info("Skipped #{existed.length} nodes [ #{existed.join(', ')} ] because they already exist. " +
|
101
|
+
"Specify --overwrite to re-bootstrap existing nodes. " +
|
102
|
+
"If you are using Chef Vault, you may need to use --bootstrap-vault options in this case.")
|
103
|
+
end
|
104
|
+
ui.warn("#{failed.length} nodes [ #{failed.join(', ')} ] failed to bootstrap due to errors") if failed.length > 0
|
84
105
|
else
|
85
106
|
ui.info "No nodes found for topology #{display_name(topo)}"
|
86
107
|
end
|
87
108
|
end
|
88
109
|
|
89
|
-
# Setup the bootstrap args and run the bootstrap command
|
90
|
-
def run_bootstrap(node_data)
|
91
|
-
node_name = node_data['name']
|
92
|
-
|
93
|
-
args = @bootstrap_args
|
94
|
-
args += ['-N', node_name] if(node_name)
|
95
|
-
args += ['-E', node_data['chef_environment']] if(node_data['chef_environment'])
|
96
|
-
args[1] = node_data['ssh_host']
|
97
|
-
args += [ '--ssh-port', node_data['ssh_port']] if node_data['ssh_port']
|
98
|
-
args += [ '--run-list' , node_data['run_list'].join(',')] if node_data['run_list']
|
99
|
-
args += [ '--json-attributes' , node_data['normal'].to_json] if node_data['normal']
|
100
|
-
|
101
|
-
ui.info "Bootstrapping node #{node_name}"
|
102
|
-
begin
|
103
|
-
run_cmd(Chef::Knife::Bootstrap, args)
|
104
|
-
rescue Exception => e
|
105
|
-
raise if Chef::Config[:verbosity] == 2
|
106
|
-
@failed << node_name
|
107
|
-
ui.warn "bootstrap of node #{node_name} exited with error"
|
108
|
-
humanize_exception(e)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
110
|
include Chef::Knife::TopologyHelper
|
113
111
|
|
114
112
|
end
|
@@ -151,7 +151,7 @@ class Chef
|
|
151
151
|
|
152
152
|
# Print out qualified attributes
|
153
153
|
def print_qualified_attr(file, qualifier_hash)
|
154
|
-
file.puts "if node['topo']['#{qualifier_hash['qualifier']}'] == \"#{qualifier_hash['value']}\""
|
154
|
+
file.puts "if node['topo'] && node['topo']['#{qualifier_hash['qualifier']}'] == \"#{qualifier_hash['value']}\""
|
155
155
|
print_priority_attrs(file, qualifier_hash, 2)
|
156
156
|
file.puts "end"
|
157
157
|
end
|
@@ -27,7 +27,7 @@ class Chef
|
|
27
27
|
|
28
28
|
deps do
|
29
29
|
Chef::Knife::TopoCookbookUpload.load_deps
|
30
|
-
Chef::Knife::
|
30
|
+
Chef::Knife::Bootstrap.load_deps
|
31
31
|
end
|
32
32
|
|
33
33
|
banner "knife topo create TOPOLOGY (options)"
|
@@ -46,19 +46,24 @@ class Chef
|
|
46
46
|
:long => "--disable-upload",
|
47
47
|
:description => "Do not upload topo cookbooks",
|
48
48
|
:boolean => true
|
49
|
+
|
50
|
+
option :overwrite,
|
51
|
+
:long => "--overwrite",
|
52
|
+
:description => "Whether to overwrite existing nodes",
|
53
|
+
:boolean => true
|
49
54
|
|
50
55
|
# Make called command options available
|
51
56
|
opts = self.options
|
52
|
-
self.options = (Chef::Knife::
|
57
|
+
self.options = (Chef::Knife::Bootstrap.options).merge(Chef::Knife::TopoCookbookUpload.options)
|
53
58
|
self.options.merge!(opts)
|
54
59
|
|
55
60
|
def initialize (args)
|
56
61
|
super
|
57
|
-
@
|
62
|
+
@bootstrap_args = initialize_cmd_args(args, [ 'bootstrap', '' ])
|
58
63
|
@topo_upload_args = initialize_cmd_args(args, [ 'topo', 'cookbook', 'upload', @name_args[0] ])
|
59
64
|
|
60
65
|
# All called commands need to accept union of options
|
61
|
-
Chef::Knife::
|
66
|
+
Chef::Knife::Bootstrap.options = options
|
62
67
|
Chef::Knife::TopoCookbookUpload.options = options
|
63
68
|
end
|
64
69
|
|
@@ -99,20 +104,55 @@ class Chef
|
|
99
104
|
nodes = merge_topo_properties(topo_hash['nodes'], topo_hash)
|
100
105
|
config[:disable_editing] = true
|
101
106
|
|
107
|
+
bootstrapped = []
|
108
|
+
updated = []
|
109
|
+
skipped = []
|
110
|
+
failed = []
|
111
|
+
|
102
112
|
if nodes && nodes.length > 0
|
103
|
-
|
104
|
-
|
105
|
-
|
113
|
+
|
114
|
+
nodes.each do |node_data|
|
115
|
+
node_name = node_data['name']
|
116
|
+
|
117
|
+
exists = resource_exists?("nodes/#{node_name}")
|
118
|
+
if(node_data['ssh_host'] && config[:bootstrap] && (config[:overwrite] || !exists))
|
119
|
+
if run_bootstrap(node_data, @bootstrap_args, exists)
|
120
|
+
bootstrapped << node_name
|
121
|
+
else
|
122
|
+
failed << node_name
|
123
|
+
end
|
124
|
+
else
|
125
|
+
if(exists)
|
126
|
+
updated << node_name
|
127
|
+
node = update_node(node_data)
|
128
|
+
else
|
129
|
+
skipped << node_name
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
ui.info("Topology #{display_name(topo_hash)} created, containing #{nodes.length} nodes")
|
135
|
+
ui.info("Build information: " + topo_hash['buildstamp']) if topo_hash['buildstamp']
|
136
|
+
|
137
|
+
if(config[:bootstrap])
|
138
|
+
ui.info("Bootstrapped #{bootstrapped.length} nodes [ #{bootstrapped.join(', ')} ]")
|
139
|
+
if updated.length > 0
|
140
|
+
ui.info("Updated #{updated.length} nodes [ #{updated.join(', ')} ] because they already exist. " +
|
141
|
+
"Specify --overwrite to re-bootstrap existing nodes. " +
|
142
|
+
"If you are using Chef Vault, you may need to use --bootstrap-vault options in this case.")
|
143
|
+
end
|
144
|
+
ui.info("Skipped #{skipped.length} nodes [ #{skipped.join(', ')} ] because they had no ssh_host information") if skipped.length > 0
|
145
|
+
else
|
146
|
+
ui.info("Updated #{updated.length} nodes [ #{updated.join(', ')} ]")
|
147
|
+
ui.info("Skipped #{skipped.length} nodes [ #{skipped.join(', ')} ] because they do not exist") if skipped.length > 0
|
106
148
|
end
|
107
|
-
|
108
|
-
|
149
|
+
|
150
|
+
ui.warn("#{failed.length} nodes [ #{failed.join(', ')} ] failed to bootstrap due to errors") if failed.length > 0
|
151
|
+
|
109
152
|
else
|
110
153
|
ui.info "No nodes found for topology #{display_name(topo_hash)}"
|
111
154
|
end
|
112
|
-
|
113
|
-
ui.info("Topology #{display_name(topo_hash)} created")
|
114
|
-
ui.info("Build information: " + topo_hash['buildstamp']) if topo_hash['buildstamp']
|
115
|
-
|
155
|
+
|
116
156
|
end
|
117
157
|
|
118
158
|
include Chef::Knife::TopologyHelper
|
@@ -75,8 +75,8 @@ class Chef
|
|
75
75
|
# load then update and save the node
|
76
76
|
node = Chef::Node.load(node_name)
|
77
77
|
|
78
|
-
if node
|
79
|
-
node.
|
78
|
+
if node['topo'] && node['topo']['name'] == @topo_name
|
79
|
+
node.rm('topo','name')
|
80
80
|
ui.info "Removing node #{node.name} from topology"
|
81
81
|
node.save
|
82
82
|
end
|
data/lib/chef/knife/topo_list.rb
CHANGED
@@ -37,8 +37,12 @@ class Chef
|
|
37
37
|
|
38
38
|
def run
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
begin
|
41
|
+
topo_bag = topo_bag_name(config[:data_bag])
|
42
|
+
output(format_list_for_display(Chef::DataBag.load(topo_bag)))
|
43
|
+
rescue Net::HTTPServerException => e
|
44
|
+
raise unless e.to_s =~ /^404/
|
45
|
+
end
|
42
46
|
|
43
47
|
end
|
44
48
|
|
@@ -21,6 +21,7 @@ require 'chef/node'
|
|
21
21
|
require 'chef/encrypted_data_bag_item'
|
22
22
|
require 'chef/environment'
|
23
23
|
require 'chef/knife/core/object_loader'
|
24
|
+
require 'chef/rest'
|
24
25
|
|
25
26
|
class Chef
|
26
27
|
class Knife
|
@@ -104,7 +105,8 @@ class Chef
|
|
104
105
|
merged_nodes = nodes ? nodes.clone : []
|
105
106
|
merged_nodes.each do |nodeprops|
|
106
107
|
|
107
|
-
normal_defaults = topo_hash['normal'] ?
|
108
|
+
normal_defaults = topo_hash['normal'] ?
|
109
|
+
Marshal.load(Marshal.dump(topo_hash['normal'])) : {}
|
108
110
|
nodeprops['normal'] ||= {}
|
109
111
|
nodeprops['normal'] = prop_merge!(normal_defaults, nodeprops['normal'])
|
110
112
|
nodeprops['normal'] = prop_merge!(nodeprops['normal'], nodeprops['attributes']) if nodeprops['attributes']
|
@@ -309,6 +311,55 @@ class Chef
|
|
309
311
|
|
310
312
|
version
|
311
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
|
312
363
|
|
313
364
|
end
|
314
365
|
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: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christine Draper
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-15 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
|
@@ -53,7 +53,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
53
|
version: '0'
|
54
54
|
requirements: []
|
55
55
|
rubyforge_project:
|
56
|
-
rubygems_version: 2.4.
|
56
|
+
rubygems_version: 2.4.8
|
57
57
|
signing_key:
|
58
58
|
specification_version: 4
|
59
59
|
summary: Knife plugin to manage topologies of nodes
|