knife-nodefu 0.0.2 → 0.0.3
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.
- data/lib/chef/knife/nodefu_base.rb +8 -0
- data/lib/chef/knife/nodefu_create.rb +77 -24
- data/lib/chef/knife/nodefu_destroy.rb +14 -16
- data/lib/knife-nodefu/version.rb +1 -1
- metadata +6 -6
@@ -29,4 +29,12 @@ module NodefuBase
|
|
29
29
|
raise ServerRangeError if end_range.to_i < start_range.to_i
|
30
30
|
return [base_name,start_range,end_range]
|
31
31
|
end
|
32
|
+
|
33
|
+
def failed_nodes(servers)
|
34
|
+
servers.select {|k,v| v['chef_node'].nil? || !v['failure'].nil? }
|
35
|
+
end
|
36
|
+
|
37
|
+
def successful_nodes(servers)
|
38
|
+
servers.select {|k,v| !v['chef_node'].nil? && v['failure'].nil? }
|
39
|
+
end
|
32
40
|
end
|
@@ -6,13 +6,17 @@ class NodefuCreate < Chef::Knife
|
|
6
6
|
require 'fileutils'
|
7
7
|
require 'yaml'
|
8
8
|
require 'thread'
|
9
|
+
require 'fog'
|
9
10
|
Chef::Knife::Ec2ServerCreate.load_deps
|
11
|
+
Chef::Knife::Ec2ServerDelete.load_deps
|
10
12
|
end
|
11
13
|
|
12
14
|
include NodefuBase
|
13
15
|
|
14
16
|
banner "knife nodefu create <server><range> (OPTIONS)"
|
15
17
|
|
18
|
+
attr_reader :servers
|
19
|
+
|
16
20
|
option :node_spec,
|
17
21
|
:short => "-n <node_spec>",
|
18
22
|
:long => "--node_spec <node_spec>",
|
@@ -31,26 +35,49 @@ class NodefuCreate < Chef::Knife
|
|
31
35
|
:description => "yml definitions file",
|
32
36
|
:default => nil
|
33
37
|
|
38
|
+
option :exit_on_fail,
|
39
|
+
:short => "-e",
|
40
|
+
:long => "--exit-on-fail",
|
41
|
+
:description => "Exit if one of the servers fails to come up",
|
42
|
+
:default => nil
|
43
|
+
|
44
|
+
option :destroy_on_fail,
|
45
|
+
:short => "-f",
|
46
|
+
:long => "--destroy-on-fail",
|
47
|
+
:description => "Terminate the ec2 instance on error",
|
48
|
+
:default => nil
|
49
|
+
|
50
|
+
def destroy_instances(servers)
|
51
|
+
ec2_delete = Ec2ServerDelete.new
|
52
|
+
servers.each_pair.with_index do |(k,v),i|
|
53
|
+
if v['server'].nil?
|
54
|
+
ui.msg("No server to delete for #{k}")
|
55
|
+
else
|
56
|
+
ec2_delete.name_args[i] = v['server'].id
|
57
|
+
end
|
58
|
+
end
|
59
|
+
ec2_delete.config[:yes] = true
|
60
|
+
ec2_delete.run
|
61
|
+
end
|
62
|
+
|
34
63
|
def run
|
64
|
+
check_args(1)
|
35
65
|
env = Chef::Config[:environment]
|
36
66
|
definitions_file = config[:definitions_file].nil? ? Chef::Config[:nodefu_definitions_file] : config[:definitions_file]
|
37
67
|
@yml_config = YAML.load_file definitions_file
|
38
68
|
|
39
|
-
|
40
|
-
servers = name_args[0]
|
41
|
-
base_name, start_range, end_range = parse_servers(servers)
|
69
|
+
base_name, start_range, end_range = parse_servers(name_args[0])
|
42
70
|
|
43
71
|
#merge the current environment hash with the defaults
|
44
72
|
merged_configuration = Chef::Mixin::DeepMerge.merge(@yml_config['default'],@yml_config['env'][env])
|
45
73
|
|
46
|
-
domain = merged_configuration['domain']
|
47
|
-
|
48
74
|
if (! config[:node_spec].nil?)
|
49
75
|
node_spec_name = config[:node_spec]
|
50
76
|
else
|
51
77
|
node_spec_name = base_name
|
52
78
|
end
|
53
79
|
|
80
|
+
domain = merged_configuration['domain']
|
54
81
|
node_spec = merged_configuration['node_spec'][node_spec_name]
|
55
82
|
vm_spec_name = node_spec['vm_spec']
|
56
83
|
vm_spec = merged_configuration['vm_spec'][vm_spec_name]
|
@@ -67,27 +94,53 @@ class NodefuCreate < Chef::Knife
|
|
67
94
|
config[:yes] ? user_response = 'yes' : user_response = ui.ask_question("Does this seem right to you? [y/n]").downcase
|
68
95
|
abort("See ya!") unless (['yes','y',].include?(user_response))
|
69
96
|
|
70
|
-
threads = []
|
97
|
+
threads = []
|
71
98
|
for i in (start_range..end_range)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
99
|
+
ec2_server_request = Ec2ServerCreate.new
|
100
|
+
node_name = "#{base_name}#{i}"
|
101
|
+
full_node_name = "#{base_name}#{i}.#{env}.#{domain}"
|
102
|
+
#A handfull of the Ec2ServerCreate command line options use a :proc field so I have to
|
103
|
+
#populate those by hand instead of simply passing a value to its config entry
|
104
|
+
Chef::Config[:knife][:aws_ssh_key_id] = vm_spec['ssh_key']
|
105
|
+
Chef::Config[:knife][:image] = vm_spec['ami']
|
106
|
+
Chef::Config[:knife][:region] = vm_spec['region']
|
107
|
+
ec2_server_request.config[:chef_node_name] = full_node_name
|
108
|
+
ec2_server_request.config[:run_list] = node_spec['run_list']
|
109
|
+
ec2_server_request.config[:flavor] = vm_spec['type']
|
110
|
+
ec2_server_request.config[:security_groups] = (generate_security_groups(node_name,env) + aux_groups).split(',')
|
111
|
+
ec2_server_request.config[:ssh_user] = vm_spec['user']
|
112
|
+
ec2_server_request.config[:availability_zone] = vm_spec['az']
|
113
|
+
ec2_server_request.config[:distro] = vm_spec['bootstrap']
|
114
|
+
threads << Thread.new(full_node_name,ec2_server_request) do |full_node_name,request|
|
115
|
+
e = nil
|
116
|
+
begin
|
117
|
+
request.run
|
118
|
+
rescue => e
|
119
|
+
config[:exit_on_fail] ? raise(e) : puts("#{full_node_name}: #{e.message}")
|
120
|
+
end
|
121
|
+
[full_node_name, { 'server' => request.server, 'failure' => e, 'chef_node' => nil} ]
|
122
|
+
end
|
90
123
|
end
|
91
124
|
threads.each(&:join)
|
125
|
+
|
126
|
+
#Build a servers hash with the node names as they key from the object returned by the threads
|
127
|
+
@servers = threads.inject({}) {|hash,t| hash[t.value[0]] = t.value[1]; hash}
|
128
|
+
|
129
|
+
query = Chef::Search::Query.new
|
130
|
+
query.search('node',"name:#{base_name}*#{env}*") do |n|
|
131
|
+
@servers[n.name]['chef_node'] = n
|
132
|
+
end
|
133
|
+
|
134
|
+
ui.msg('')
|
135
|
+
ui.msg(ui.color('Failed Nodes:',:red))
|
136
|
+
failed = failed_nodes(@servers).each_pair { |k,v| ui.msg("#{k}: #{v['failure']}") }
|
137
|
+
|
138
|
+
ui.msg(ui.color('Successful Nodes:',:green))
|
139
|
+
successful = successful_nodes(@servers).each_pair { |k,v| ui.msg("#{k}: #{v['id']}, #{v['dns_name']}") }
|
140
|
+
|
141
|
+
if config[:destroy_on_fail]
|
142
|
+
ui.msg(ui.color("Destroying failed nodes:",:red))
|
143
|
+
destroy_instances(failed)
|
144
|
+
end
|
92
145
|
end
|
93
146
|
end
|
@@ -7,13 +7,14 @@ class NodefuDestroy < Chef::Knife
|
|
7
7
|
require 'chef/api_client'
|
8
8
|
require 'chef/node'
|
9
9
|
require 'chef/json_compat'
|
10
|
+
require 'chef/search/query'
|
10
11
|
require 'thread'
|
11
12
|
Chef::Knife::Ec2ServerDelete.load_deps
|
12
13
|
end
|
13
14
|
|
14
15
|
include NodefuBase
|
15
16
|
|
16
|
-
banner "knife nodefu destroy
|
17
|
+
banner "knife nodefu destroy QUERY (options)"
|
17
18
|
|
18
19
|
option :yes,
|
19
20
|
:short => "-y",
|
@@ -41,13 +42,13 @@ class NodefuDestroy < Chef::Knife
|
|
41
42
|
|
42
43
|
def run
|
43
44
|
check_args(1)
|
44
|
-
matcher = /#{name_args[0]}/
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
nodes_to_delete, clients_to_delete = {},{}
|
47
|
+
query = Chef::Search::Query.new
|
48
|
+
query.search('node',name_args[0]) do |node|
|
49
|
+
nodes_to_delete[node.name] = node
|
50
|
+
clients_to_delete[node.name] = Chef::ApiClient.load(node.name)
|
51
|
+
end
|
51
52
|
|
52
53
|
#Display all the items that will be removed
|
53
54
|
if config[:skip_clients]
|
@@ -68,9 +69,9 @@ class NodefuDestroy < Chef::Knife
|
|
68
69
|
ui.msg("#{ui.color('Skipping instances...',:cyan)}")
|
69
70
|
else
|
70
71
|
ui.msg("#{ui.color('EC2 instances to be terminated:',:red)}")
|
71
|
-
nodes_to_delete.
|
72
|
-
instance_id = node[
|
73
|
-
ui.msg("#{ui.color(
|
72
|
+
nodes_to_delete.each_pair do |name,node|
|
73
|
+
instance_id = node['ec2']['instance_id']
|
74
|
+
ui.msg("#{ui.color(name,:magenta)}: #{instance_id}")
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
@@ -80,14 +81,11 @@ class NodefuDestroy < Chef::Knife
|
|
80
81
|
unless config[:skip_instances]
|
81
82
|
threads = []
|
82
83
|
#Delete the ec2 server
|
83
|
-
|
84
|
-
threads << Thread.new(i) do |node|
|
84
|
+
nodes_to_delete.each_pair do |name,node|
|
85
85
|
ec2_delete = Ec2ServerDelete.new
|
86
|
-
|
87
|
-
ec2_delete.name_args[0] = instance_id
|
86
|
+
ec2_delete.name_args[0] = node['ec2']['instance_id']
|
88
87
|
ec2_delete.config[:yes] = true
|
89
|
-
ec2_delete.run
|
90
|
-
end
|
88
|
+
threads << Thread.new(node) { |node| ec2_delete.run }
|
91
89
|
end
|
92
90
|
threads.each(&:join)
|
93
91
|
end
|
data/lib/knife-nodefu/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-nodefu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-24 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: knife-ec2
|
16
|
-
requirement: &
|
16
|
+
requirement: &70184212905400 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70184212905400
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: chef
|
27
|
-
requirement: &
|
27
|
+
requirement: &70184212904900 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0.10'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70184212904900
|
36
36
|
description: A knife plugin for simple node creation automation
|
37
37
|
email:
|
38
38
|
- brian.bianco@gmail.com
|