knife-stackbuilder 0.5.9 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef/knife/stack_build.rb +1 -1
- data/lib/chef/knife/stack_delete.rb +3 -4
- data/lib/stackbuilder.rb +5 -3
- data/lib/stackbuilder/chef/stack_container_node.rb +2 -2
- data/lib/stackbuilder/chef/stack_generic_node.rb +71 -9
- data/lib/stackbuilder/chef/stack_node_manager.rb +61 -52
- data/lib/stackbuilder/chef/stack_provider.rb +3 -1
- data/lib/stackbuilder/chef/stack_vagrant_node.rb +57 -7
- data/lib/stackbuilder/common/config.rb +1 -1
- data/lib/stackbuilder/common/helpers.rb +53 -26
- data/lib/stackbuilder/resources/vagrant.rb +27 -0
- data/lib/stackbuilder/stack/node_task.rb +4 -2
- data/lib/stackbuilder/stack/stack.rb +7 -1
- data/lib/stackbuilder/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f785f195082e19cce38b6ed050c7c372058cc91
|
4
|
+
data.tar.gz: 1bffb5f8a0834b0b94ed27b2df4379b7b556e71e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e36a47c1b0745433163df25eda03f5266979a3629f5b4d999d50948c576cbc11c8c72df6bcd2f79e5f5d8fc48e30d04fcb8214ebb5a5ead5e9962cfb0429c0f1
|
7
|
+
data.tar.gz: 8b1cf1c3387e9d8465f562abf578c082275bac61d06266bc6c0d73c2b78c6f1b2058ae4b742fa938b6e36d87b798ef0f85a7d4fd031620e1d8f331a21edfd766
|
@@ -56,7 +56,7 @@ class Chef
|
|
56
56
|
repo_path = getConfig(:repo_path)
|
57
57
|
environment = getConfig(:environment) || '_default'
|
58
58
|
|
59
|
-
stack_id = getConfig(:stack_id) || ENV['STACK_ID']
|
59
|
+
stack_id = getConfig(:stack_id) || ENV['STACK_ID'] || environment
|
60
60
|
stack_overrides = getConfig(:overrides) || ENV['STACK_OVERRIDES']
|
61
61
|
|
62
62
|
stack_file = name_args.first
|
@@ -13,8 +13,7 @@ class Chef
|
|
13
13
|
|
14
14
|
option :stack_id,
|
15
15
|
:long => "--stack-id STACK_ID",
|
16
|
-
:description => "The ID of the stack to delete."
|
17
|
-
:required => true
|
16
|
+
:description => "The ID of the stack to delete."
|
18
17
|
|
19
18
|
option :repo_path,
|
20
19
|
:long => "--repo_path REPO_PATH",
|
@@ -25,7 +24,7 @@ class Chef
|
|
25
24
|
def run
|
26
25
|
StackBuilder::Common::Config.logger.level = Chef::Log.logger.level
|
27
26
|
|
28
|
-
environment = getConfig(:environment) || '_default'
|
27
|
+
environment = getConfig(:environment) || '_default'
|
29
28
|
stack_file = name_args.first
|
30
29
|
|
31
30
|
if stack_file=~/[-_+=.0-9a-zA-Z]+/
|
@@ -40,7 +39,7 @@ class Chef
|
|
40
39
|
stack = StackBuilder::Stack::Stack.new(
|
41
40
|
StackBuilder::Chef::NodeProvider.new(getConfig(:repo_path), environment),
|
42
41
|
stack_file,
|
43
|
-
getConfig(:stack_id) )
|
42
|
+
getConfig(:stack_id) || ENV['STACK_ID'] || environment )
|
44
43
|
|
45
44
|
stack.destroy
|
46
45
|
end
|
data/lib/stackbuilder.rb
CHANGED
@@ -12,12 +12,14 @@ require 'fileutils'
|
|
12
12
|
require 'tmpdir'
|
13
13
|
require 'tempfile'
|
14
14
|
require "stringio"
|
15
|
+
require 'set'
|
15
16
|
require 'json'
|
16
17
|
require 'timeout'
|
17
18
|
require 'openssl'
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
19
|
+
require 'net/ssh'
|
20
|
+
require 'net/ssh/multi'
|
21
|
+
require 'ipaddr'
|
22
|
+
require 'highline/import'
|
21
23
|
|
22
24
|
require 'chef'
|
23
25
|
require 'chef/knife'
|
@@ -39,8 +39,8 @@ module StackBuilder::Chef
|
|
39
39
|
ipaddress = node.attributes['ipaddress']
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
ssh_user, ssh_password, ssh_identity_file = target.get_ssh_credentials(target_node_instance)
|
43
|
+
ssh = ssh_create(ipaddress, ssh_user, ssh_password || ssh_identity_file)
|
44
44
|
|
45
45
|
image_exists = @name==ssh_exec!(ssh, "docker images | awk '$1==\"@name\" { print $1 }'")[:out].strip
|
46
46
|
|
@@ -6,34 +6,65 @@ module StackBuilder::Chef
|
|
6
6
|
|
7
7
|
class GenericNodeManager < StackBuilder::Chef::NodeManager
|
8
8
|
|
9
|
+
def initialize(id, node_config, repo_path, environment, static_ips)
|
10
|
+
|
11
|
+
super(id, node_config, repo_path, environment)
|
12
|
+
|
13
|
+
@static_ips = static_ips
|
14
|
+
unless @static_ips.nil?
|
15
|
+
get_stack_node_resources
|
16
|
+
@nodes.each { |n| @static_ips.delete_if { |ip| ip.split('/').first==n["ipaddress"] } }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
9
20
|
def create_vm(index, name, knife_config)
|
10
21
|
|
22
|
+
pre_create = knife_config['pre_create']
|
23
|
+
pre_create.each { |c| self.run_knife_cmd(name, knife_config, c) } unless pre_create.nil?
|
24
|
+
|
11
25
|
create_class_name = knife_config['create']['class']
|
12
26
|
raise ArgumentError, "Knife plugin's server 'create' class name not provided." \
|
13
27
|
if create_class_name.nil?
|
14
28
|
|
15
29
|
knife_cmd = eval(create_class_name + '.new')
|
16
30
|
|
17
|
-
|
18
|
-
|
31
|
+
create_options = knife_config['create']
|
32
|
+
|
33
|
+
if create_options.has_key?('name_key')
|
34
|
+
name_key = create_options['name_key']
|
19
35
|
knife_cmd.config[name_key.to_sym] = name
|
20
36
|
else
|
21
37
|
knife_cmd.name_args = [ name ]
|
22
38
|
end
|
23
39
|
|
24
|
-
if
|
40
|
+
if create_options.has_key?('pool_key')
|
25
41
|
|
26
|
-
pool_key =
|
42
|
+
pool_key = create_options['pool_key']
|
27
43
|
|
28
44
|
placement_pools = knife_config['placement_pools']
|
29
45
|
raise ArgumentError, "Knife plugin 'placement_pools' list was not provided." \
|
30
46
|
if placement_pools.nil?
|
31
47
|
|
32
48
|
knife_cmd.config[pool_key.to_sym] = placement_pools[index % placement_pools.size]
|
33
|
-
end
|
49
|
+
end
|
50
|
+
|
51
|
+
self.config_knife(name, knife_cmd, knife_config['create']['options'] || { })
|
52
|
+
self.config_knife(name, knife_cmd, knife_config['options'] || { })
|
53
|
+
|
54
|
+
if create_options.has_key?('static_ip_key') && !@static_ips.nil?
|
55
|
+
|
56
|
+
static_ip = @static_ips.shift
|
57
|
+
raise Common::StackBuilder::StackBuilderError, "Static IP pool is empty." \
|
58
|
+
if static_ip.nil?
|
59
|
+
|
60
|
+
static_ip_key = create_options['static_ip_key']
|
61
|
+
ip_data = knife_config['create']['options'][static_ip_key]
|
62
|
+
static_ip += "#{ip_data}" unless ip_data.nil?
|
63
|
+
|
64
|
+
knife_cmd.config[static_ip_key.to_sym] = static_ip
|
65
|
+
end
|
34
66
|
|
35
|
-
|
36
|
-
config_knife(knife_cmd, knife_config['options'] || { })
|
67
|
+
@logger.info("Executing knife to create VM: #{knife_cmd} / #{knife_cmd.name_args} / #{knife_cmd.config}")
|
37
68
|
|
38
69
|
if knife_config['create']['synchronized']
|
39
70
|
@@sync ||= Mutex.new
|
@@ -43,6 +74,35 @@ module StackBuilder::Chef
|
|
43
74
|
else
|
44
75
|
run_knife_forked(knife_cmd)
|
45
76
|
end
|
77
|
+
|
78
|
+
post_create = knife_config['post_create']
|
79
|
+
post_create.each { |c| self.run_knife_cmd(name, knife_config, c) } unless post_create.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
def run_knife_cmd(name, knife_config, knife_command)
|
83
|
+
|
84
|
+
class_name = knife_command['class']
|
85
|
+
raise ArgumentError, "Knife command action class name not provided: #{knife_command}" \
|
86
|
+
if class_name.nil?
|
87
|
+
|
88
|
+
knife_cmd = eval(class_name + '.new')
|
89
|
+
|
90
|
+
if knife_command.has_key?('name_key')
|
91
|
+
name_key = knife_command['name_key']
|
92
|
+
knife_cmd.config[name_key.to_sym] = name
|
93
|
+
else
|
94
|
+
knife_cmd.name_args = [ name ]
|
95
|
+
end
|
96
|
+
|
97
|
+
name_args = knife_command['args'].to_s
|
98
|
+
knife_cmd.name_args += name_args.start_with?('"') ?
|
99
|
+
name_args.split(/\"\s+\"/).collect { |s| s.gsub(/^\"|\"$/, '') } : name_args.split unless name_args.nil?
|
100
|
+
|
101
|
+
self.config_knife(name, knife_cmd, knife_command['options'] || { })
|
102
|
+
self.config_knife(name, knife_cmd, knife_config['options'] || { })
|
103
|
+
|
104
|
+
@logger.info("Executing knife: #{knife_cmd} / #{knife_cmd.name_args} / #{knife_cmd.config}")
|
105
|
+
run_knife_forked(knife_cmd)
|
46
106
|
end
|
47
107
|
|
48
108
|
def delete_vm(name, knife_config)
|
@@ -62,11 +122,13 @@ module StackBuilder::Chef
|
|
62
122
|
knife_cmd.name_args = [ name ]
|
63
123
|
end
|
64
124
|
|
65
|
-
config_knife(knife_cmd, knife_config['delete']['options'] || { })
|
66
|
-
config_knife(knife_cmd, knife_config['options'] || { })
|
125
|
+
self.config_knife(name, knife_cmd, knife_config['delete']['options'] || { })
|
126
|
+
self.config_knife(name, knife_cmd, knife_config['options'] || { })
|
67
127
|
|
68
128
|
knife_cmd.config[:yes] = true
|
69
129
|
|
130
|
+
@logger.info("Executing knife to delete VM: #{knife_cmd} / #{knife_cmd.name_args} / #{knife_cmd.config}")
|
131
|
+
|
70
132
|
if knife_config['delete']['synchronized']
|
71
133
|
@@sync ||= Mutex.new
|
72
134
|
@@sync.synchronize {
|
@@ -14,9 +14,7 @@ module StackBuilder::Chef
|
|
14
14
|
attr_accessor :run_list
|
15
15
|
attr_accessor :run_on_event
|
16
16
|
|
17
|
-
|
18
|
-
attr_accessor :ssh_password
|
19
|
-
attr_accessor :ssh_identity_file
|
17
|
+
SSH_CREDENTIAL_KEYS = Set.new(['ssh_user', 'ssh_password', 'identity_file'])
|
20
18
|
|
21
19
|
def initialize(id, node_config, repo_path, environment)
|
22
20
|
|
@@ -32,12 +30,27 @@ module StackBuilder::Chef
|
|
32
30
|
@run_on_event = node_config['run_on_event']
|
33
31
|
|
34
32
|
@knife_config = node_config['knife']
|
35
|
-
if @knife_config && @knife_config.has_key?('options')
|
36
33
|
|
37
|
-
|
34
|
+
@env_key_file = "#{repo_path}/secrets/#{environment}"
|
35
|
+
@env_key_file = nil unless File.exist?(@env_key_file)
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_name
|
39
|
+
@name
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_scale
|
43
|
+
get_stack_node_resources
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_ssh_credentials(name)
|
47
|
+
|
48
|
+
if @ssh_user.nil?
|
49
|
+
|
50
|
+
raise ArgumentError, 'An ssh user is required to create ssh sessions.' \
|
38
51
|
unless @knife_config['options'].has_key?('ssh_user')
|
39
52
|
|
40
|
-
raise ArgumentError, 'An ssh key file or password
|
53
|
+
raise ArgumentError, 'An ssh key file or password is required to create ssh sessions.' \
|
41
54
|
unless @knife_config['options'].has_key?('identity_file') ||
|
42
55
|
@knife_config['options'].has_key?('ssh_password')
|
43
56
|
|
@@ -47,16 +60,7 @@ module StackBuilder::Chef
|
|
47
60
|
@ssh_identity_file.gsub!(/~\//, Dir.home + '/') unless @ssh_identity_file.nil?
|
48
61
|
end
|
49
62
|
|
50
|
-
@
|
51
|
-
@env_key_file = nil unless File.exist?(@env_key_file)
|
52
|
-
end
|
53
|
-
|
54
|
-
def get_name
|
55
|
-
@name
|
56
|
-
end
|
57
|
-
|
58
|
-
def get_scale
|
59
|
-
get_stack_node_resources
|
63
|
+
[ @ssh_user, @ssh_password, @ssh_identity_file ]
|
60
64
|
end
|
61
65
|
|
62
66
|
def node_attributes
|
@@ -191,17 +195,30 @@ module StackBuilder::Chef
|
|
191
195
|
raise StackBuilder::Common::NotImplemented, 'HostNodeManager.delete_vm'
|
192
196
|
end
|
193
197
|
|
194
|
-
def config_knife(knife_cmd, options)
|
198
|
+
def config_knife(name, knife_cmd, options)
|
195
199
|
|
196
200
|
options.each_pair do |k, v|
|
197
201
|
|
198
|
-
|
202
|
+
unless SSH_CREDENTIAL_KEYS.include?(k)
|
199
203
|
|
200
|
-
|
201
|
-
v.gsub!(/~\//, Dir.home + '/') if arg.end_with?('_dir') && v.start_with?('~/')
|
204
|
+
arg = k.gsub(/-/, '_')
|
202
205
|
|
203
|
-
|
206
|
+
# Fix issue where '~/' is not expanded to home dir
|
207
|
+
v.gsub!(/~\//, Dir.home + '/') if arg.end_with?('_dir') && v.start_with?('~/')
|
208
|
+
|
209
|
+
knife_cmd.config[arg.to_sym] = v
|
210
|
+
end
|
204
211
|
end
|
212
|
+
|
213
|
+
unless @env_key_file.nil?
|
214
|
+
env_key = IO.read(@env_key_file)
|
215
|
+
knife_cmd.config[:secret] = env_key
|
216
|
+
end
|
217
|
+
|
218
|
+
ssh_user, ssh_password, ssh_identity_file = self.get_ssh_credentials(name)
|
219
|
+
knife_cmd.config[:ssh_user] = ssh_user
|
220
|
+
knife_cmd.config[:ssh_password] = ssh_password unless ssh_password.nil?
|
221
|
+
knife_cmd.config[:identity_file] = ssh_identity_file unless ssh_identity_file.nil?
|
205
222
|
end
|
206
223
|
|
207
224
|
private
|
@@ -213,47 +230,18 @@ module StackBuilder::Chef
|
|
213
230
|
@nodes.size
|
214
231
|
end
|
215
232
|
|
216
|
-
def knife_ssh(name, cmd)
|
217
|
-
|
218
|
-
knife_config_options = @knife_config['options'] || { }
|
219
|
-
|
220
|
-
sudo = knife_config_options['sudo'] ? 'sudo -i su -c ' : ''
|
221
|
-
|
222
|
-
ssh_cmd = "TMPFILE=`mktemp` && " +
|
223
|
-
"echo -e \"#{cmd.gsub(/\"/, "\\\"").gsub(/\$/, "\\$").gsub(/\`/, '\\' + '\`')}\" > $TMPFILE && " +
|
224
|
-
"chmod 0744 $TMPFILE && " +
|
225
|
-
"#{sudo}$TMPFILE && " +
|
226
|
-
"rm $TMPFILE"
|
227
|
-
|
228
|
-
knife_cmd = Chef::Knife::Ssh.new
|
229
|
-
knife_cmd.name_args = [ "name:#{name}", ssh_cmd ]
|
230
|
-
knife_cmd.config[:attribute] = knife_config_options['ip_attribute'] || 'ipaddress'
|
231
|
-
|
232
|
-
config_knife(knife_cmd, knife_config_options)
|
233
|
-
|
234
|
-
if @logger.info? || @logger.debug?
|
235
|
-
|
236
|
-
output = StackBuilder::Common::TeeIO.new($stdout)
|
237
|
-
error = StackBuilder::Common::TeeIO.new($stderr)
|
238
|
-
|
239
|
-
@logger.info("Running '#{cmd}' on node 'name:#{name}'.")
|
240
|
-
run_knife(knife_cmd, output, error)
|
241
|
-
else
|
242
|
-
run_knife(knife_cmd)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
233
|
def node_search(search_query, timeout = 0)
|
247
234
|
|
248
235
|
query = Chef::Search::Query.new
|
249
236
|
escaped_query = URI.escape(search_query, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
250
237
|
|
251
238
|
if timeout>0
|
252
|
-
@logger.info("Waiting '#{search_query}' to return results.")
|
239
|
+
@logger.info("#{@name} - Waiting '#{search_query}' to return results.")
|
253
240
|
results = Timeout::timeout(timeout) {
|
254
241
|
|
255
242
|
while true do
|
256
243
|
results = query.search('node', escaped_query, nil, 0, 999999)
|
244
|
+
sleep 5
|
257
245
|
return results if results[0].size>0
|
258
246
|
end
|
259
247
|
}
|
@@ -264,5 +252,26 @@ module StackBuilder::Chef
|
|
264
252
|
results
|
265
253
|
end
|
266
254
|
|
255
|
+
def knife_ssh(name, cmd)
|
256
|
+
|
257
|
+
knife_config = @knife_config['options'] || { }
|
258
|
+
|
259
|
+
sudo = knife_config['sudo'] ? 'sudo -i su -c ' : ''
|
260
|
+
|
261
|
+
ssh_cmd = "TMPFILE=`mktemp` && " +
|
262
|
+
"echo -e \"#{cmd.gsub(/\"/, "\\\"").gsub(/\$/, "\\$").gsub(/\`/, '\\' + '\`')}\" > $TMPFILE && " +
|
263
|
+
"chmod 0744 $TMPFILE && " +
|
264
|
+
"#{sudo}$TMPFILE && " +
|
265
|
+
"rm $TMPFILE"
|
266
|
+
|
267
|
+
knife_cmd = Chef::Knife::Ssh.new
|
268
|
+
knife_cmd.name_args = [ "name:#{name}", ssh_cmd ]
|
269
|
+
knife_cmd.config[:attribute] = knife_config['ip_attribute'] || 'ipaddress'
|
270
|
+
|
271
|
+
self.config_knife(name, knife_cmd, knife_config)
|
272
|
+
|
273
|
+
@logger.info("#{@name} - Running '#{cmd}' on node 'name:#{name}'.")
|
274
|
+
run_knife(knife_cmd)
|
275
|
+
end
|
267
276
|
end
|
268
277
|
end
|
@@ -46,6 +46,8 @@ module StackBuilder::Chef
|
|
46
46
|
stack['chef']['knife_config'].each { |k,v| Chef::Config[:knife][k.to_sym] = v } \
|
47
47
|
if stack['chef'].has_key?('knife_config')
|
48
48
|
end
|
49
|
+
|
50
|
+
@static_ips = stack['static_ips']
|
49
51
|
end
|
50
52
|
|
51
53
|
def get_env_vars
|
@@ -77,7 +79,7 @@ module StackBuilder::Chef
|
|
77
79
|
end
|
78
80
|
|
79
81
|
elsif knife_config.has_key?('create')
|
80
|
-
return StackBuilder::Chef::GenericNodeManager.new(@id, node_config, @repo_path, @environment)
|
82
|
+
return StackBuilder::Chef::GenericNodeManager.new(@id, node_config, @repo_path, @environment, @static_ips)
|
81
83
|
|
82
84
|
else
|
83
85
|
return StackBuilder::Chef::NodeManager.new(@id, node_config, @repo_path, @environment)
|
@@ -6,6 +6,37 @@ module StackBuilder::Chef
|
|
6
6
|
|
7
7
|
class VagrantNodeManager < StackBuilder::Chef::NodeManager
|
8
8
|
|
9
|
+
VAGRANT_PROVIDER = 'virtualbox'
|
10
|
+
VAGRANT_DIR = File.join(Dir.home, '/.vagrant')
|
11
|
+
INSECURE_KEY_PATH = "#{VAGRANT_DIR}/insecure_key"
|
12
|
+
|
13
|
+
def vagrant_version
|
14
|
+
@@vagrant_version ||= begin
|
15
|
+
`vagrant -v`[/Vagrant\s+([0-9\.]+)/, 1]
|
16
|
+
rescue Exception => msg
|
17
|
+
raise StackBuilder::Common::StackBuilderError, "Unable to locate vagrant."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_ssh_credentials(name)
|
22
|
+
|
23
|
+
ssh_user = @knife_config['options']['ssh_user'] || 'vagrant'
|
24
|
+
ssh_identity_file = @knife_config['options']['identity_file']
|
25
|
+
|
26
|
+
if ssh_identity_file.nil?
|
27
|
+
|
28
|
+
provider = @knife_config['options']['provider'] || VAGRANT_PROVIDER
|
29
|
+
vagrant_dir = @knife_config['options']['vagrant_dir'] || VAGRANT_DIR
|
30
|
+
|
31
|
+
ssh_identity_file = ( vagrant_version<'1.7' ? INSECURE_KEY_PATH :
|
32
|
+
"#{vagrant_dir}/#{name}/.vagrant/machines/default/#{provider}/private_key" )
|
33
|
+
else
|
34
|
+
ssh_identity_file.gsub!(/~\//, Dir.home + '/')
|
35
|
+
end
|
36
|
+
|
37
|
+
[ ssh_user, nil, ssh_identity_file ]
|
38
|
+
end
|
39
|
+
|
9
40
|
def create_vm(index, name, knife_config)
|
10
41
|
|
11
42
|
handle_vagrant_box_additions(name, knife_config)
|
@@ -18,8 +49,8 @@ module StackBuilder::Chef
|
|
18
49
|
knife_cmd.config[:distro] = 'chef-full'
|
19
50
|
knife_cmd.config[:template_file] = false
|
20
51
|
|
21
|
-
knife_cmd.config[:vagrant_dir] =
|
22
|
-
knife_cmd.config[:provider] =
|
52
|
+
knife_cmd.config[:vagrant_dir] = VAGRANT_DIR
|
53
|
+
knife_cmd.config[:provider] = VAGRANT_PROVIDER
|
23
54
|
knife_cmd.config[:memsize] = 1024
|
24
55
|
knife_cmd.config[:subnet] = '192.168.67.0/24'
|
25
56
|
knife_cmd.config[:port_forward] = { }
|
@@ -30,7 +61,10 @@ module StackBuilder::Chef
|
|
30
61
|
knife_cmd.config[:ssh_user] = 'vagrant'
|
31
62
|
knife_cmd.config[:ssh_port] = '22'
|
32
63
|
|
33
|
-
config_knife(knife_cmd, knife_config['options'] || { })
|
64
|
+
self.config_knife(name, knife_cmd, knife_config['options'] || { })
|
65
|
+
|
66
|
+
# Let vagrant use auto-generated private key for ssh during bootstrap
|
67
|
+
knife_cmd.config[:identity_file] = nil if vagrant_version>'1.7'
|
34
68
|
|
35
69
|
ip_address = knife_cmd.config[:ip_address]
|
36
70
|
knife_cmd.config[:ip_address] = ip_address[/(\d+\.\d+\.\d+\.)/, 1] + \
|
@@ -45,13 +79,10 @@ module StackBuilder::Chef
|
|
45
79
|
|
46
80
|
def delete_vm(name, knife_config)
|
47
81
|
|
48
|
-
puts "deleting #{name}"
|
49
|
-
exit 1
|
50
|
-
|
51
82
|
knife_cmd = Chef::Knife::VagrantServerDelete.new
|
52
83
|
knife_cmd.name_args = [ name ]
|
53
84
|
knife_cmd.config[:yes] = true
|
54
|
-
knife_cmd.config[:vagrant_dir] =
|
85
|
+
knife_cmd.config[:vagrant_dir] = VAGRANT_DIR
|
55
86
|
|
56
87
|
@@sync ||= Mutex.new
|
57
88
|
@@sync.synchronize {
|
@@ -76,12 +107,31 @@ module StackBuilder::Chef
|
|
76
107
|
end
|
77
108
|
end
|
78
109
|
|
110
|
+
def config_knife(name, knife_cmd, options)
|
111
|
+
|
112
|
+
super(name, knife_cmd, options)
|
113
|
+
|
114
|
+
# Add ohai plugin to change the ohai ipaddress
|
115
|
+
# value to the non NAT'ed eth1 interface. This
|
116
|
+
# is required so you can SSH into vagrant VMs
|
117
|
+
# via knife ssh
|
118
|
+
ohai_plugin_resource = File.expand_path('../../resources/vagrant.rb', __FILE__)
|
119
|
+
|
120
|
+
knife_cmd.config[:vagrant_config] = \
|
121
|
+
"config.vm.provision \"file\", source: \"#{ohai_plugin_resource}\", destination: \"~/vagrant.rb\"::" +
|
122
|
+
'config.vm.provision "shell", inline: "mkdir -p /etc/chef/ohai_plugins"::' +
|
123
|
+
'config.vm.provision "shell", inline: "mv /home/vagrant/vagrant.rb /etc/chef/ohai_plugins"::' +
|
124
|
+
'config.vm.provision "shell", inline: \'echo {\"primary_nic\":\"eth1\"} > /etc/chef/ohai_plugins/vagrant.json\'::' +
|
125
|
+
(knife_cmd.config[:vagrant_config] || '')
|
126
|
+
end
|
127
|
+
|
79
128
|
def handle_vagrant_box_additions(name, knife_config)
|
80
129
|
|
81
130
|
# Create add-on provider specific infrastructure
|
82
131
|
knife_options = knife_config['options']
|
83
132
|
provider = knife_options['provider']
|
84
133
|
|
134
|
+
# Create disks for vagrant vms on vmware if requested
|
85
135
|
if !provider.nil? && provider.start_with?('vmware')
|
86
136
|
|
87
137
|
vmx_customize = knife_options['vmx_customize']
|
@@ -4,6 +4,8 @@ module StackBuilder::Common
|
|
4
4
|
|
5
5
|
module Helpers
|
6
6
|
|
7
|
+
MAGIC_VARS = Set.new(%w(env my))
|
8
|
+
|
7
9
|
#
|
8
10
|
# Returns whether platform is a nix OS
|
9
11
|
#
|
@@ -48,7 +50,8 @@ module StackBuilder::Common
|
|
48
50
|
yield(job)
|
49
51
|
Marshal.dump([stdout.string, stderr.string], write)
|
50
52
|
rescue Exception => msg
|
51
|
-
|
53
|
+
StackBuilder::Common::Config.logger.debug("Exception in forked job: #{msg}\n" + msg.backtrace.join("\n\t"))
|
54
|
+
Marshal.dump([stdout.string, stderr.string, StackBuilder::Common::StackBuilderError.new(msg.to_s) ], write)
|
52
55
|
ensure
|
53
56
|
$stdout = previous_stdout
|
54
57
|
$stderr = previous_stderr
|
@@ -91,7 +94,7 @@ module StackBuilder::Common
|
|
91
94
|
def load_yaml(file, env_vars, my = nil)
|
92
95
|
|
93
96
|
yaml = YAML.load_file(file)
|
94
|
-
eval_map_values(yaml, env_vars, file, my)
|
97
|
+
eval_map_values(yaml, env_vars, file, my || yaml)
|
95
98
|
end
|
96
99
|
|
97
100
|
#
|
@@ -104,21 +107,11 @@ module StackBuilder::Common
|
|
104
107
|
|
105
108
|
if v.is_a?(String)
|
106
109
|
|
107
|
-
if v=~/#\{.*\}/
|
108
|
-
begin
|
109
|
-
return eval("\"#{v.gsub(/\"/, "\\\"")}\"")
|
110
|
-
|
111
|
-
rescue Exception => msg
|
112
|
-
|
113
|
-
StackBuilder::Common::Config.logger.debug( "Error evaluating configuration " +
|
114
|
-
"variable '#{v}': #{msg}\nenv = #{env}\nmy = #{my}")
|
110
|
+
v = eval("\"#{v.gsub(/\"/, "\\\"")}\"") if v=~/#\{.*\}/
|
115
111
|
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
|
-
elsif v.start_with?('<<')
|
112
|
+
if v.start_with?('<<')
|
120
113
|
|
121
|
-
k1 = v[/<<(\w*)[
|
114
|
+
k1 = v[/<<(\w*)[\*\$\@\+]/,1]
|
122
115
|
env_val = k1.nil? || k1.empty? ? nil : ENV[k1]
|
123
116
|
|
124
117
|
i = k1.length + 3
|
@@ -144,27 +137,45 @@ module StackBuilder::Common
|
|
144
137
|
end
|
145
138
|
return v
|
146
139
|
|
140
|
+
when '@'
|
141
|
+
if env_val.nil?
|
142
|
+
tuple = k2.split(':')
|
143
|
+
else
|
144
|
+
tuple = env_val.split(':')
|
145
|
+
end
|
146
|
+
|
147
|
+
ipaddress = IPAddr.new(tuple[0])
|
148
|
+
num_ips, cidr_mask = tuple[1].split('/')
|
149
|
+
|
150
|
+
ipaddresses = [ ipaddress ]
|
151
|
+
ipaddresses += (0..num_ips.to_i-2).to_a.collect { |i| ipaddress = ipaddress.succ }
|
152
|
+
return ipaddresses.collect { |i| i.to_s + (cidr_mask.nil? ? '' : "/#{cidr_mask}") }
|
153
|
+
|
147
154
|
when '+'
|
148
|
-
lookup_keys = (env_val || k2).split(/[\[\]]/).reject { |k| k.empty? }
|
155
|
+
lookup_keys = (env_val || k2).split(/[\[\]']/).reject { |k| k.empty? }
|
149
156
|
|
150
157
|
key = lookup_keys.shift
|
151
|
-
|
158
|
+
if MAGIC_VARS.include?(key)
|
159
|
+
v = eval(key + lookup_keys.collect { |v| "['#{v}']" }.join)
|
160
|
+
else
|
161
|
+
include_file = key.start_with?('/') || key.nil? ? key : File.expand_path('../' + key, file)
|
152
162
|
|
153
|
-
|
154
|
-
|
163
|
+
begin
|
164
|
+
yaml = load_yaml(include_file, env, my)
|
155
165
|
|
156
|
-
|
157
|
-
|
166
|
+
return lookup_keys.empty? ? yaml
|
167
|
+
: eval('yaml' + lookup_keys.collect { |v| "['#{v}']" }.join)
|
158
168
|
|
159
|
-
|
160
|
-
|
161
|
-
|
169
|
+
rescue Exception => msg
|
170
|
+
puts "ERROR: Unable to include referenced data '#{v}'."
|
171
|
+
raise msg
|
172
|
+
end
|
162
173
|
end
|
163
|
-
else
|
164
|
-
return v
|
165
174
|
end
|
166
175
|
end
|
167
176
|
|
177
|
+
return v
|
178
|
+
|
168
179
|
elsif v.is_a?(Hash)
|
169
180
|
|
170
181
|
new_keys = { }
|
@@ -189,6 +200,13 @@ module StackBuilder::Common
|
|
189
200
|
end
|
190
201
|
|
191
202
|
v
|
203
|
+
|
204
|
+
rescue Exception => msg
|
205
|
+
|
206
|
+
StackBuilder::Common::Config.logger.debug( "Error evaluating configuration " +
|
207
|
+
"variable '#{v}': #{msg}\nenv = #{env}\nmy = #{my}")
|
208
|
+
|
209
|
+
v
|
192
210
|
end
|
193
211
|
|
194
212
|
#
|
@@ -375,6 +393,15 @@ module StackBuilder::Common
|
|
375
393
|
#
|
376
394
|
def run_knife(knife_cmd, output = StringIO.new, error = StringIO.new)
|
377
395
|
|
396
|
+
logger = StackBuilder::Common::Config.logger
|
397
|
+
if logger.info? || logger.debug?
|
398
|
+
output = StackBuilder::Common::TeeIO.new($stdout)
|
399
|
+
error = StackBuilder::Common::TeeIO.new($stderr)
|
400
|
+
else
|
401
|
+
output = StringIO.new
|
402
|
+
error = StringIO.new
|
403
|
+
end
|
404
|
+
|
378
405
|
knife_cmd.ui = Chef::Knife::UI.new(output, error, STDIN, knife_cmd.config) \
|
379
406
|
unless output.nil? && error.nil?
|
380
407
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Ohai.plugin(:Vboxipaddress) do
|
2
|
+
|
3
|
+
provides "ipaddress"
|
4
|
+
depends "ipaddress", "network/interfaces", "virtualization/system", "etc/passwd"
|
5
|
+
|
6
|
+
Chef::Log.info("Running Vagrant plugin to reset node ipaddress attribute.")
|
7
|
+
|
8
|
+
if File.exist?('/etc/chef/ohai_plugins/vagrant.json')
|
9
|
+
vagrant = JSON.parse(IO.read('/etc/chef/ohai_plugins/vagrant.json'))
|
10
|
+
|
11
|
+
collect_data(:default) do
|
12
|
+
if virtualization["system"] == "vbox" || virtualization["system"] == "vmware"
|
13
|
+
if etc["passwd"].any? { |k,v| k == "vagrant"}
|
14
|
+
primary_nic = vagrant["primary_nic"]
|
15
|
+
if primary_nic && network["interfaces"][primary_nic]
|
16
|
+
network["interfaces"][primary_nic]["addresses"].each do |ip, params|
|
17
|
+
if params['family'] == ('inet')
|
18
|
+
Chef::Log.info("Setting node ipaddress attribute to: #{ip}")
|
19
|
+
ipaddress ip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -9,6 +9,7 @@ module StackBuilder::Stack
|
|
9
9
|
attr_reader :name
|
10
10
|
|
11
11
|
attr_accessor :scale
|
12
|
+
attr_accessor :max_scale
|
12
13
|
attr_accessor :prev_scale
|
13
14
|
attr_accessor :sync
|
14
15
|
|
@@ -38,7 +39,7 @@ module StackBuilder::Stack
|
|
38
39
|
@counter = 0
|
39
40
|
|
40
41
|
@name = node_config['node']
|
41
|
-
@attributes =
|
42
|
+
@attributes = node_config['attributes'] || { }
|
42
43
|
|
43
44
|
case node_config['sync']
|
44
45
|
when "first"
|
@@ -51,10 +52,11 @@ module StackBuilder::Stack
|
|
51
52
|
|
52
53
|
current_scale = manager.get_scale
|
53
54
|
if current_scale==0
|
54
|
-
@scale =
|
55
|
+
@scale = node_config["scale"] || 1
|
55
56
|
else
|
56
57
|
@scale = current_scale
|
57
58
|
end
|
59
|
+
@max_scale = node_config["max_scale"] || @scale
|
58
60
|
|
59
61
|
raise ArgumentError, "The scale for node \"#{@name}\" must be greater than 0." if @scale < 1
|
60
62
|
@prev_scale = @scale
|
@@ -104,7 +104,13 @@ module StackBuilder::Stack
|
|
104
104
|
raise StackBuilder::Common::StackBuilderError, "Invalid node name \"#{name}'\"." if node.nil?
|
105
105
|
|
106
106
|
unless scale.nil?
|
107
|
-
raise ArgumentError,
|
107
|
+
raise ArgumentError, \
|
108
|
+
"The scale for node \"#{node.name}\" must be greater than 0." \
|
109
|
+
if scale < 1
|
110
|
+
raise ArgumentError, \
|
111
|
+
"The scale for node \"#{node.name}\" cannot be greater than #{node.max_scale}." \
|
112
|
+
if scale > node.max_scale
|
113
|
+
|
108
114
|
node.scale = scale
|
109
115
|
end
|
110
116
|
end
|
data/lib/stackbuilder/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-stackbuilder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mevan Samaratunga
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- lib/stackbuilder/resources/Environment.rb.erb
|
132
132
|
- lib/stackbuilder/resources/Stack.yml.erb
|
133
133
|
- lib/stackbuilder/resources/openssl.cnf
|
134
|
+
- lib/stackbuilder/resources/vagrant.rb
|
134
135
|
- lib/stackbuilder/stack/node_manager.rb
|
135
136
|
- lib/stackbuilder/stack/node_provider.rb
|
136
137
|
- lib/stackbuilder/stack/node_task.rb
|
@@ -155,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
156
|
version: '0'
|
156
157
|
requirements: []
|
157
158
|
rubyforge_project:
|
158
|
-
rubygems_version: 2.4.
|
159
|
+
rubygems_version: 2.4.6
|
159
160
|
signing_key:
|
160
161
|
specification_version: 4
|
161
162
|
summary: Knife Stackbuilder plugin
|