knife-vagrant3 0.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 +7 -0
- data/.gitignore +9 -0
- data/CHANGELOG.md +43 -0
- data/Gemfile +2 -0
- data/LICENSE +13 -0
- data/README.md +4 -0
- data/Rakefile +2 -0
- data/knife-vagrant3.gemspec +21 -0
- data/lib/chef/knife/vagrant_base.rb +173 -0
- data/lib/chef/knife/vagrant_box.rb +15 -0
- data/lib/chef/knife/vagrant_server_create.rb +473 -0
- data/lib/chef/knife/vagrant_server_delete.rb +73 -0
- data/lib/chef/knife/vagrant_server_halt.rb +33 -0
- data/lib/chef/knife/vagrant_server_list.rb +39 -0
- data/lib/chef/knife/vagrant_server_resume.rb +35 -0
- data/lib/chef/knife/vagrant_server_suspend.rb +33 -0
- data/lib/chef/knife/vagrant_server_up.rb +33 -0
- data/lib/knife-vagrant/version.rb +6 -0
- metadata +89 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 903e63d91b1390d43259125945d61be2da6e0d94
|
|
4
|
+
data.tar.gz: a6639aab2fa6aa981343c1f81331b5a5f763a6d3
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ca1a239ff9aa4719786ae503ea52836262d7b80260aa7a32213468279036208fd84a5c5abbadf54a6d64fc96b2b8a12263c8768dea7d9438c620edc6639d3620
|
|
7
|
+
data.tar.gz: b98869c57ad6d4bd9be1ed25b20f0c67f40985a00803a4216da3788b4778728077e84afae20c0e2ffc7a4e8ce1df00cc289292bc3df6c60a95a92e7bf0cb4d9a
|
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# 0.0.5 (unreleased)
|
|
2
|
+
|
|
3
|
+
## Changes and new features
|
|
4
|
+
|
|
5
|
+
## Fixes
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# 0.0.4 (2014-03-14)
|
|
9
|
+
|
|
10
|
+
## Changes and new features
|
|
11
|
+
|
|
12
|
+
* Added --provider option to use vagrant providers other than virtualbox
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# 0.0.3 (2014-01-28)
|
|
16
|
+
|
|
17
|
+
## Fixes
|
|
18
|
+
|
|
19
|
+
* Fixed error when not using --vb-customize option
|
|
20
|
+
* Removed unneeded dependency on knife-ec2
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# 0.0.2 (2013-12-17)
|
|
24
|
+
|
|
25
|
+
## Changes and new features
|
|
26
|
+
|
|
27
|
+
* BREAKING: --share-folders option now takes HOST_PATH::GUEST_PATH instead of NAME::GUEST_PATH::HOST_PATH
|
|
28
|
+
* Added --port-forward option to map host ports to VMs
|
|
29
|
+
* Added --vb-customize option to pass arbitrary VirtualBox options to Vagrant
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# 0.0.1 (2013-12-11)
|
|
33
|
+
|
|
34
|
+
## Changes and new features
|
|
35
|
+
|
|
36
|
+
* Initial release
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Thanks to our contributors
|
|
40
|
+
|
|
41
|
+
* [Jāzeps Baško](https://github.com/jbasko)
|
|
42
|
+
* [Robert J. Berger](https://github.com/rberger)
|
|
43
|
+
* [xsunsmile](https://github.com/xsunsmile)
|
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2013 Markus Kern <chef@mkern.fastmail.fm>
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
data/Rakefile
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
|
3
|
+
require 'knife-vagrant/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = 'knife-vagrant3'
|
|
7
|
+
s.version = Knife::Vagrant::VERSION
|
|
8
|
+
s.authors = ['Markus Kern']
|
|
9
|
+
s.email = ['chef@mkern.fastmail.fm']
|
|
10
|
+
s.homepage = 'https://github.com/makern/knife-vagrant2'
|
|
11
|
+
s.summary = %q{Vagrant support for Chef's knife command}
|
|
12
|
+
s.description = s.summary
|
|
13
|
+
s.license = 'Apache 2.0'
|
|
14
|
+
|
|
15
|
+
s.files = `git ls-files`.split("\n")
|
|
16
|
+
|
|
17
|
+
s.add_dependency 'chef', '>= 0.10.10'
|
|
18
|
+
s.add_development_dependency 'rake'
|
|
19
|
+
|
|
20
|
+
s.require_paths = ['lib']
|
|
21
|
+
end
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
require 'chef/knife'
|
|
2
|
+
|
|
3
|
+
class Chef
|
|
4
|
+
class Knife
|
|
5
|
+
module VagrantBase
|
|
6
|
+
|
|
7
|
+
# :nodoc:
|
|
8
|
+
# Would prefer to do this in a rational way, but can't be done b/c of
|
|
9
|
+
# Mixlib::CLI's design :(
|
|
10
|
+
def self.included(includer)
|
|
11
|
+
includer.class_eval do
|
|
12
|
+
|
|
13
|
+
option :vagrant_dir,
|
|
14
|
+
:short => '-D PATH',
|
|
15
|
+
:long => '--vagrant-dir PATH',
|
|
16
|
+
:description => "Path to where Vagrant files are stored. Defaults to cwd/vagrant (#{Dir.pwd}/vagrant)",
|
|
17
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:vagrant_dir] = key },
|
|
18
|
+
:default => File.join(Dir.pwd, '/vagrant')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def vagrant_exec(instance, cmd, opts = {})
|
|
23
|
+
fetch_output = opts[:fetch_output] || false
|
|
24
|
+
no_cwd_change = opts[:no_cwd_change] || false
|
|
25
|
+
|
|
26
|
+
unless no_cwd_change
|
|
27
|
+
|
|
28
|
+
# Dir.getwd throws an unknown exception when this plugin
|
|
29
|
+
# is run in a multi-threaded environment
|
|
30
|
+
begin
|
|
31
|
+
cwd = Dir.getwd()
|
|
32
|
+
rescue
|
|
33
|
+
no_cwd_change = true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
Dir.chdir(File.join(locate_config_value(:vagrant_dir), instance))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
cmd = "vagrant #{cmd}"
|
|
40
|
+
output = nil
|
|
41
|
+
if defined? Bundler
|
|
42
|
+
# Needed if we are run from inside a bundler environment and vagrant
|
|
43
|
+
# is installed as global gem. If this causes problems for anyone please
|
|
44
|
+
# file a bug report.
|
|
45
|
+
Bundler.with_clean_env do
|
|
46
|
+
output = fetch_output ? %x(#{cmd}) : system(cmd)
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
output = fetch_output ? %x(#{cmd}) : system(cmd)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
unless no_cwd_change
|
|
53
|
+
Dir.chdir(cwd)
|
|
54
|
+
end
|
|
55
|
+
output
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def vagrant_instance_state(instance)
|
|
59
|
+
output = vagrant_exec(instance, 'status', fetch_output: true)
|
|
60
|
+
state = /Current machine states:.+?default\s+(.+?)\s+\((.+?)\)/m.match(output)
|
|
61
|
+
unless state
|
|
62
|
+
ui.warn("Couldn't parse state of instance #{instance}")
|
|
63
|
+
return ['', '']
|
|
64
|
+
end
|
|
65
|
+
return [state[1], state[2]]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def vagrant_instance_list
|
|
69
|
+
# Memoize so we don't have to parse files multiple times
|
|
70
|
+
if @vagrant_instances
|
|
71
|
+
return @vagrant_instances
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
vangrant_dir = locate_config_value(:vagrant_dir)
|
|
75
|
+
@vagrant_instances = []
|
|
76
|
+
|
|
77
|
+
unless File.exist? vangrant_dir
|
|
78
|
+
return @vagrant_instances
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
Dir.foreach(vangrant_dir) { |subdir|
|
|
82
|
+
vagrant_file = File.join(vangrant_dir, subdir, 'Vagrantfile')
|
|
83
|
+
if File.exist? vagrant_file
|
|
84
|
+
instance = { :name => subdir,
|
|
85
|
+
:vagrant_file => vagrant_file
|
|
86
|
+
}
|
|
87
|
+
# Read settings from vagrant file
|
|
88
|
+
content = IO.read(vagrant_file)
|
|
89
|
+
instance[:ip_address] = /config\.vm\.network[^,]+,\s*ip:\s*"([0-9\.]+)"/.match(content) { |m| m[1] }
|
|
90
|
+
unless instance[:ip_address]
|
|
91
|
+
ui.warn("Couldn't find IP address in #{vagrant_file}. Is it malformed?")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
instance[:box] = /config\.vm\.box[^=]*=\s*"([^"]+)"/.match(content) { |m| m[1] }
|
|
95
|
+
unless instance[:box]
|
|
96
|
+
ui.warn("Couldn't find box in #{vagrant_file}. Is it malformed?")
|
|
97
|
+
end
|
|
98
|
+
@vagrant_instances.push(instance)
|
|
99
|
+
end
|
|
100
|
+
}
|
|
101
|
+
@vagrant_instances
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def write_insecure_key
|
|
105
|
+
# The private key most vagrant boxes use.
|
|
106
|
+
insecure_key = <<-EOF
|
|
107
|
+
-----BEGIN RSA PRIVATE KEY-----
|
|
108
|
+
MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI
|
|
109
|
+
w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP
|
|
110
|
+
kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2
|
|
111
|
+
hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO
|
|
112
|
+
Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW
|
|
113
|
+
yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd
|
|
114
|
+
ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1
|
|
115
|
+
Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf
|
|
116
|
+
TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK
|
|
117
|
+
iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A
|
|
118
|
+
sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf
|
|
119
|
+
4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP
|
|
120
|
+
cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk
|
|
121
|
+
EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN
|
|
122
|
+
CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX
|
|
123
|
+
3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG
|
|
124
|
+
YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj
|
|
125
|
+
3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+
|
|
126
|
+
dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz
|
|
127
|
+
6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC
|
|
128
|
+
P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF
|
|
129
|
+
llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ
|
|
130
|
+
kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH
|
|
131
|
+
+vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ
|
|
132
|
+
NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s=
|
|
133
|
+
-----END RSA PRIVATE KEY-----
|
|
134
|
+
EOF
|
|
135
|
+
insecure_key
|
|
136
|
+
|
|
137
|
+
# Write key to vagrant folder if it's not there yet.
|
|
138
|
+
key_file = File.join(locate_config_value(:vagrant_dir), 'insecure_key')
|
|
139
|
+
unless File.exist? key_file
|
|
140
|
+
ui.msg("Creating #{key_file}")
|
|
141
|
+
FileUtils.mkdir_p(locate_config_value(:vagrant_dir))
|
|
142
|
+
File.open(key_file, 'w') { |f| f.write(insecure_key) }
|
|
143
|
+
File.chmod(0600, key_file)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def locate_config_value(key)
|
|
148
|
+
key = key.to_sym
|
|
149
|
+
config[key] || Chef::Config[:knife][key]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def msg_pair(label, value, color=:cyan)
|
|
153
|
+
if value && !value.to_s.empty?
|
|
154
|
+
puts "#{ui.color(label, color)}: #{value}"
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def colored_vagrant_state(state)
|
|
159
|
+
case state
|
|
160
|
+
when 'saved','paused','poweroff', 'stuck', 'aborted', 'gurumeditation', 'inaccessible'
|
|
161
|
+
ui.color(state, :red)
|
|
162
|
+
when 'saving'
|
|
163
|
+
ui.color(state, :yellow)
|
|
164
|
+
else
|
|
165
|
+
ui.color(state, :green)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'chef/knife/vagrant_base'
|
|
2
|
+
|
|
3
|
+
class Chef
|
|
4
|
+
class Knife
|
|
5
|
+
|
|
6
|
+
class VagrantBoxList < Knife
|
|
7
|
+
include Knife::VagrantBase
|
|
8
|
+
banner "knife vagrant box list"
|
|
9
|
+
def run
|
|
10
|
+
vagrant_exec('.', 'box list', no_cwd_change: true)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
require 'chef/knife/vagrant_base'
|
|
2
|
+
|
|
3
|
+
class Chef
|
|
4
|
+
class Knife
|
|
5
|
+
class VagrantServerCreate < Knife
|
|
6
|
+
|
|
7
|
+
include Knife::VagrantBase
|
|
8
|
+
deps do
|
|
9
|
+
require 'ostruct'
|
|
10
|
+
require 'ipaddr'
|
|
11
|
+
require 'chef/knife/bootstrap'
|
|
12
|
+
Chef::Knife::Bootstrap.load_deps
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
banner "knife vagrant server create (options)"
|
|
16
|
+
|
|
17
|
+
option :box,
|
|
18
|
+
:short => "-b BOX",
|
|
19
|
+
:long => "--box BOX",
|
|
20
|
+
:description => "The vagrant box to use for the server",
|
|
21
|
+
:proc => Proc.new { |b| Chef::Config[:knife][:box] = b }
|
|
22
|
+
|
|
23
|
+
option :box_url,
|
|
24
|
+
:short => '-U URL',
|
|
25
|
+
:long => '--box-url URL',
|
|
26
|
+
:description => 'URL of pre-packaged vbox template. Can be a local path or an HTTP URL.',
|
|
27
|
+
:proc => Proc.new { |b| Chef::Config[:knife][:box_url] = b }
|
|
28
|
+
|
|
29
|
+
option :memsize,
|
|
30
|
+
:short => '-m MEMORY',
|
|
31
|
+
:long => '--memsize MEMORY',
|
|
32
|
+
:description => 'Amount of RAM to allocate to provisioned VM, in MB. Defaults to 1024',
|
|
33
|
+
:proc => Proc.new { |m| Chef::Config[:knife][:memsize] = m },
|
|
34
|
+
:default => 1024
|
|
35
|
+
|
|
36
|
+
option :share_folders,
|
|
37
|
+
:short => '-F',
|
|
38
|
+
:long => '--share-folders SHARES',
|
|
39
|
+
:description => 'Comma separated list of share folders in the form of HOST_PATH::GUEST_PATH',
|
|
40
|
+
:proc => lambda { |o| o.split(/[\s,]+/) },
|
|
41
|
+
:default => []
|
|
42
|
+
|
|
43
|
+
option :use_cachier,
|
|
44
|
+
:short => '-C',
|
|
45
|
+
:long => '--use-cachier',
|
|
46
|
+
:description => 'Enables VM to use the vagrant-cachier plugin',
|
|
47
|
+
:boolean => true,
|
|
48
|
+
:default => false
|
|
49
|
+
|
|
50
|
+
option :chef_node_name,
|
|
51
|
+
:short => "-N NAME",
|
|
52
|
+
:long => "--node-name NAME",
|
|
53
|
+
:description => "The Chef node name for your new node"
|
|
54
|
+
# :proc => Proc.new { |key| Chef::Config[:knife][:chef_node_name] = key }
|
|
55
|
+
|
|
56
|
+
option :ssh_user,
|
|
57
|
+
:short => "-x USERNAME",
|
|
58
|
+
:long => "--ssh-user USERNAME",
|
|
59
|
+
:description => "The ssh username",
|
|
60
|
+
:default => "vagrant"
|
|
61
|
+
|
|
62
|
+
option :ssh_password,
|
|
63
|
+
:short => "-P PASSWORD",
|
|
64
|
+
:long => "--ssh-password PASSWORD",
|
|
65
|
+
:description => "The ssh password"
|
|
66
|
+
|
|
67
|
+
option :ssh_port,
|
|
68
|
+
:short => "-p PORT",
|
|
69
|
+
:long => "--ssh-port PORT",
|
|
70
|
+
:description => "The ssh port",
|
|
71
|
+
:default => "22",
|
|
72
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }
|
|
73
|
+
|
|
74
|
+
option :ssh_gateway,
|
|
75
|
+
:short => "-w GATEWAY",
|
|
76
|
+
:long => "--ssh-gateway GATEWAY",
|
|
77
|
+
:description => "The ssh gateway server",
|
|
78
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
|
|
79
|
+
|
|
80
|
+
option :identity_file,
|
|
81
|
+
:short => "-i IDENTITY_FILE",
|
|
82
|
+
:long => "--identity-file IDENTITY_FILE",
|
|
83
|
+
:description => "The SSH identity file used for authentication"
|
|
84
|
+
|
|
85
|
+
option :prerelease,
|
|
86
|
+
:long => "--prerelease",
|
|
87
|
+
:description => "Install the pre-release chef gems"
|
|
88
|
+
|
|
89
|
+
option :bootstrap_version,
|
|
90
|
+
:long => "--bootstrap-version VERSION",
|
|
91
|
+
:description => "The version of Chef to install",
|
|
92
|
+
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
|
93
|
+
|
|
94
|
+
option :distro,
|
|
95
|
+
:short => "-d DISTRO",
|
|
96
|
+
:long => "--distro DISTRO",
|
|
97
|
+
:description => "Bootstrap a distro using a template; default is 'chef-full'",
|
|
98
|
+
:default => 'chef-full',
|
|
99
|
+
:proc => Proc.new { |d| Chef::Config[:knife][:distro] = d }
|
|
100
|
+
|
|
101
|
+
option :template_file,
|
|
102
|
+
:long => "--template-file TEMPLATE",
|
|
103
|
+
:description => "Full path to location of template to use",
|
|
104
|
+
:proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
|
|
105
|
+
:default => false
|
|
106
|
+
|
|
107
|
+
option :run_list,
|
|
108
|
+
:short => "-r RUN_LIST",
|
|
109
|
+
:long => "--run-list RUN_LIST",
|
|
110
|
+
:description => "Comma separated list of roles/recipes to apply",
|
|
111
|
+
:proc => lambda { |o| o.split(/[\s,]+/) }
|
|
112
|
+
|
|
113
|
+
option :secret,
|
|
114
|
+
:short => "-s SECRET",
|
|
115
|
+
:long => "--secret ",
|
|
116
|
+
:description => "The secret key to use to encrypt data bag item values",
|
|
117
|
+
:proc => lambda { |s| Chef::Config[:knife][:secret] = s }
|
|
118
|
+
|
|
119
|
+
option :secret_file,
|
|
120
|
+
:long => "--secret-file SECRET_FILE",
|
|
121
|
+
:description => "A file containing the secret key to use to encrypt data bag item values",
|
|
122
|
+
:proc => lambda { |sf| Chef::Config[:knife][:secret_file] = sf }
|
|
123
|
+
|
|
124
|
+
option :json_attributes,
|
|
125
|
+
:short => "-j JSON",
|
|
126
|
+
:long => "--json-attributes JSON",
|
|
127
|
+
:description => "A JSON string to be added to the first run of chef-client",
|
|
128
|
+
:proc => lambda { |o| JSON.parse(o) }
|
|
129
|
+
|
|
130
|
+
option :subnet,
|
|
131
|
+
:short => "-s SUBNET",
|
|
132
|
+
:long => "--subnet SUBNET",
|
|
133
|
+
:description => "Subnet from which to pick instance IP address. Default: 192.168.67/24",
|
|
134
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:subnet] = key },
|
|
135
|
+
:default => '192.168.67.0/24'
|
|
136
|
+
|
|
137
|
+
option :ip_address,
|
|
138
|
+
:short => "-I IP-ADDRESS",
|
|
139
|
+
:long => "--private-ip-address IP-ADDRESS",
|
|
140
|
+
:description => "Use this IP address for the new instance"
|
|
141
|
+
# :proc => Proc.new { |ip| Chef::Config[:knife][:ip_address] = ip }
|
|
142
|
+
|
|
143
|
+
option :port_forward,
|
|
144
|
+
:short => '-f PORTS',
|
|
145
|
+
:long => '--port-forward PORTS',
|
|
146
|
+
:description => "Comma separated list of HOST:GUEST ports to forward",
|
|
147
|
+
:proc => lambda { |o| Hash[o.split(/,/).collect { |a| a.split(/:/) }] },
|
|
148
|
+
:default => {}
|
|
149
|
+
|
|
150
|
+
option :host_key_verify,
|
|
151
|
+
:long => "--[no-]host-key-verify",
|
|
152
|
+
:description => "Verify host key, enabled by default.",
|
|
153
|
+
:boolean => true,
|
|
154
|
+
:default => true
|
|
155
|
+
|
|
156
|
+
option :vb_customize,
|
|
157
|
+
:long => "--vb-customize VBOXMANAGE_COMMANDS",
|
|
158
|
+
:description => "List of customize options for the virtualbox vagrant provider separated by ::"
|
|
159
|
+
|
|
160
|
+
option :vmx_parameters,
|
|
161
|
+
:long => "--vmx-parameters VMX_PARAMETERS",
|
|
162
|
+
:description => "List of parameters for the vmware fusion/workstation vagrant provider separated by::"
|
|
163
|
+
|
|
164
|
+
option :provider,
|
|
165
|
+
:long => "--provider Provider",
|
|
166
|
+
:description => "The vagrant provider to use for the server",
|
|
167
|
+
:default => 'virtualbox'
|
|
168
|
+
|
|
169
|
+
option :inline_config,
|
|
170
|
+
:long => "--inline_config snippet",
|
|
171
|
+
:description => "A snippet of configuration to be inserted into the Vagrantfile."
|
|
172
|
+
|
|
173
|
+
def run
|
|
174
|
+
$stdout.sync = true
|
|
175
|
+
validate!
|
|
176
|
+
|
|
177
|
+
@server = create_server_def
|
|
178
|
+
|
|
179
|
+
msg_pair("Instance name", @server.name)
|
|
180
|
+
msg_pair("Instance IP", @server.ip_address)
|
|
181
|
+
msg_pair("Box", @server.box || @server.box_url)
|
|
182
|
+
|
|
183
|
+
if vagrant_instance_list.detect { |i| i[:name] == @server.name }
|
|
184
|
+
ui.error("Instance #{@server.name} already exists")
|
|
185
|
+
exit 1
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Create Vagrant file for new instance
|
|
189
|
+
print "\n#{ui.color("Launching instance", :magenta)}\n"
|
|
190
|
+
write_vagrantfile
|
|
191
|
+
cmd = "up --provider #{locate_config_value(:provider)}"
|
|
192
|
+
vagrant_exec(@server.name, cmd)
|
|
193
|
+
|
|
194
|
+
write_insecure_key
|
|
195
|
+
print "\n#{ui.color("Waiting for sshd", :magenta)}"
|
|
196
|
+
wait_for_sshd(@server.ip_address)
|
|
197
|
+
|
|
198
|
+
print "\n#{ui.color("Bootstraping instance", :magenta)}\n"
|
|
199
|
+
bootstrap_node(@server,@server.ip_address).run
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
puts "\n"
|
|
203
|
+
msg_pair("Instance Name", @server.name)
|
|
204
|
+
msg_pair("Box", @server.box || @server.box_url)
|
|
205
|
+
msg_pair("IP Address", @server.ip_address)
|
|
206
|
+
msg_pair("Environment", locate_config_value(:environment) || '_default')
|
|
207
|
+
msg_pair("Run List", (config[:run_list] || []).join(', '))
|
|
208
|
+
msg_pair("JSON Attributes", config[:json_attributes]) unless !config[:json_attributes] || config[:json_attributes].empty?
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def build_port_forwards(ports)
|
|
212
|
+
ports.collect { |k, v| "config.vm.network :forwarded_port, host: #{k}, guest: #{v}, host_ip: '127.0.0.1'" }.join("\n")
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def build_vb_customize(customize)
|
|
216
|
+
customize.split(/::/).collect { |k| "vb.customize [ #{k} ]" }.join("\n") if customize
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def build_vmx_customize(customize,instance_dir)
|
|
220
|
+
vmx_params = ""
|
|
221
|
+
if customize
|
|
222
|
+
customize.chomp! if customize.end_with?("\n")
|
|
223
|
+
disks = {}
|
|
224
|
+
customize.split(/::/).each do |p|
|
|
225
|
+
kv = p.split('=')
|
|
226
|
+
k = kv[0].strip
|
|
227
|
+
v = kv[1].strip
|
|
228
|
+
if v
|
|
229
|
+
if k.start_with?('scsi')
|
|
230
|
+
ss = k.split('.')
|
|
231
|
+
disks[ss[0]] ||= {}
|
|
232
|
+
case ss[1]
|
|
233
|
+
when 'fileName'
|
|
234
|
+
if v.start_with?('/')
|
|
235
|
+
disks[ss[0]]['fileName'] = v
|
|
236
|
+
else
|
|
237
|
+
v = File.expand_path(v,instance_dir)
|
|
238
|
+
disks[ss[0]]['fileName'] = v
|
|
239
|
+
end
|
|
240
|
+
when 'fileSize'
|
|
241
|
+
disks[ss[0]]['fileSize'] = v
|
|
242
|
+
next
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
vmx_params += "v.vmx[\"#{k}\"] = \"#{v}\"\n"
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
if locate_config_value(:provider).start_with?('vmware')
|
|
249
|
+
# Create extra disks as unlike virtual box vmware-fusion/workstation
|
|
250
|
+
# will not create disks automatically based on configuration params
|
|
251
|
+
disks.each_value do |f|
|
|
252
|
+
vdiskmgr = %x(which vmware-vdiskmanager)
|
|
253
|
+
vdiskmgr = "/Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager" if vdiskmgr.empty?
|
|
254
|
+
if File.exist?(vdiskmgr)
|
|
255
|
+
disk = f['fileName']
|
|
256
|
+
%x("#{vdiskmgr}" -c -t 0 -s #{f['fileSize']} -a ide #{disk}) unless File.exist?(f['fileName'])
|
|
257
|
+
unless File.exist?(disk)
|
|
258
|
+
ui.error("Disk #{disk} could not be created.")
|
|
259
|
+
exit 1
|
|
260
|
+
end
|
|
261
|
+
else
|
|
262
|
+
ui.error("Unable to determine path to vmware-vdiskmanager to create the requested additional disk.")
|
|
263
|
+
exit 1
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
vmx_params
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def build_shares(share_folders)
|
|
272
|
+
share_folders.collect do |share|
|
|
273
|
+
host, guest = share.chomp.split "::"
|
|
274
|
+
"config.vm.synced_folder '#{host}', '#{guest}'"
|
|
275
|
+
end.join("\n")
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def write_vagrantfile
|
|
279
|
+
|
|
280
|
+
# Create folder and write Vagrant file
|
|
281
|
+
instance_dir = File.join(locate_config_value(:vagrant_dir), @server.name)
|
|
282
|
+
FileUtils.mkdir_p(instance_dir)
|
|
283
|
+
|
|
284
|
+
additions = []
|
|
285
|
+
if @server.use_cachier
|
|
286
|
+
additions << 'config.cache.auto_detect = true' # enable vagarant-cachier
|
|
287
|
+
end
|
|
288
|
+
if @server.inline_config
|
|
289
|
+
additions << @server.inline_config
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
file = <<-EOF
|
|
293
|
+
Vagrant.configure("2") do |config|
|
|
294
|
+
config.vm.box = "#{@server.box}"
|
|
295
|
+
config.vm.box_url = "#{@server.box_url}"
|
|
296
|
+
config.vm.hostname = "#{@server.name}"
|
|
297
|
+
|
|
298
|
+
config.vm.network :private_network, ip: "#{@server.ip_address}"
|
|
299
|
+
#{build_port_forwards(@server.port_forward)}
|
|
300
|
+
|
|
301
|
+
#{build_shares(@server.share_folders)}
|
|
302
|
+
|
|
303
|
+
config.vm.provider :virtualbox do |vb|
|
|
304
|
+
vb.customize [ "modifyvm", :id, "--memory", #{@server.memsize} ]
|
|
305
|
+
#{build_vb_customize(@server.vb_customize)}
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
config.vm.provider :vmware_fusion do |v|
|
|
309
|
+
v.vmx["memsize"] = "#{@server.memsize}"
|
|
310
|
+
#{build_vmx_customize(@server.vmx_parameters,instance_dir)}
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
config.vm.provider :vmware_workstation do |v|
|
|
314
|
+
v.vmx["memsize"] = "#{@server.memsize}"
|
|
315
|
+
#{build_vmx_customize(@server.vmx_parameters,instance_dir)}
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
#{additions.join("\n")}
|
|
319
|
+
end
|
|
320
|
+
EOF
|
|
321
|
+
file
|
|
322
|
+
|
|
323
|
+
instance_file = File.join(instance_dir, 'Vagrantfile')
|
|
324
|
+
ui.msg("Creating #{instance_file}")
|
|
325
|
+
File.open(instance_file, 'w') { |f| f.write(file) }
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def bootstrap_node(server,ssh_host)
|
|
329
|
+
bootstrap = Chef::Knife::Bootstrap.new
|
|
330
|
+
bootstrap.name_args = [ssh_host]
|
|
331
|
+
bootstrap.config[:ssh_user] = config[:ssh_user]
|
|
332
|
+
bootstrap.config[:ssh_port] = config[:ssh_port]
|
|
333
|
+
bootstrap.config[:ssh_gateway] = config[:ssh_gateway]
|
|
334
|
+
bootstrap.config[:identity_file] = config[:identity_file] || File.join(locate_config_value(:vagrant_dir), 'insecure_key')
|
|
335
|
+
bootstrap.config[:chef_node_name] = locate_config_value(:chef_node_name) || server.ip
|
|
336
|
+
bootstrap.config[:distro] = locate_config_value(:distro) || "chef-full"
|
|
337
|
+
bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
|
|
338
|
+
bootstrap.config[:host_key_verify] = config[:host_key_verify]
|
|
339
|
+
|
|
340
|
+
bootstrap.config[:run_list] = config[:run_list]
|
|
341
|
+
bootstrap.config[:prerelease] = config[:prerelease]
|
|
342
|
+
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
|
343
|
+
bootstrap.config[:distro] = locate_config_value(:distro)
|
|
344
|
+
bootstrap.config[:template_file] = locate_config_value(:template_file)
|
|
345
|
+
bootstrap.config[:environment] = locate_config_value(:environment)
|
|
346
|
+
bootstrap.config[:prerelease] = config[:prerelease]
|
|
347
|
+
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
|
348
|
+
bootstrap.config[:first_boot_attributes] = locate_config_value(:json_attributes) || {}
|
|
349
|
+
bootstrap.config[:encrypted_data_bag_secret] = locate_config_value(:encrypted_data_bag_secret)
|
|
350
|
+
bootstrap.config[:encrypted_data_bag_secret_file] = locate_config_value(:encrypted_data_bag_secret_file)
|
|
351
|
+
bootstrap.config[:secret] = locate_config_value(:secret)
|
|
352
|
+
bootstrap.config[:secret_file] = locate_config_value(:secret_file)
|
|
353
|
+
# Modify global configuration state to ensure hint gets set by
|
|
354
|
+
# knife-bootstrap
|
|
355
|
+
Chef::Config[:knife][:hints] ||= {}
|
|
356
|
+
Chef::Config[:knife][:hints]["vagrant"] ||= {} # Cargo Cult programming FTW?
|
|
357
|
+
|
|
358
|
+
msg_pair("SSH User", bootstrap.config[:ssh_user])
|
|
359
|
+
msg_pair("SSH identity file", bootstrap.config[:identity_file])
|
|
360
|
+
bootstrap
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def validate!
|
|
364
|
+
unless locate_config_value(:box) || locate_config_value(:box_url)
|
|
365
|
+
ui.error("You need to either specify --box or --box-url")
|
|
366
|
+
exit 1
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def find_available_ip
|
|
371
|
+
subnet = locate_config_value('subnet')
|
|
372
|
+
IPAddr.new(subnet).to_range().each { |ip|
|
|
373
|
+
# 192.168.3.0/24 should yield 192.168.3.2 through 192.168.3.254
|
|
374
|
+
# 192.168.3.1 cannot be used because virtual box uses it for the router
|
|
375
|
+
mask = IPAddr::IN4MASK ^ ip.instance_variable_get("@mask_addr")
|
|
376
|
+
unless [0, 1, mask].include? (ip & mask) or vagrant_instance_list.detect { |i| i[:ip_address] == ip.to_s }
|
|
377
|
+
return ip.to_s
|
|
378
|
+
end
|
|
379
|
+
}
|
|
380
|
+
ui.error("No unused IP address available in subnet #{subnet}")
|
|
381
|
+
exit 1
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def create_server_def
|
|
385
|
+
server_def = {
|
|
386
|
+
:box => locate_config_value(:box),
|
|
387
|
+
:box_url => locate_config_value(:box_url),
|
|
388
|
+
:memsize => locate_config_value(:memsize),
|
|
389
|
+
:share_folders => config[:share_folders],
|
|
390
|
+
:port_forward => config[:port_forward],
|
|
391
|
+
:use_cachier => config[:use_cachier],
|
|
392
|
+
:vb_customize => locate_config_value(:vb_customize),
|
|
393
|
+
:vmx_parameters => locate_config_value(:vmx_parameters),
|
|
394
|
+
:inline_config => config[:inline_config]
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
# Get specified IP address for new instance or pick an unused one from the subnet pool.
|
|
398
|
+
server_def[:ip_address] = config[:ip_address] || find_available_ip
|
|
399
|
+
|
|
400
|
+
collision = vagrant_instance_list.detect { |i| i[:ip_address] == server_def[:ip_address] }
|
|
401
|
+
if collision
|
|
402
|
+
ui.error("IP address #{server_def[:ip_address]} already in use by instance #{collision[:name]}")
|
|
403
|
+
exit 1
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Derive name for vagrant instance from chef node name or IP
|
|
407
|
+
server_def[:name] = locate_config_value(:chef_node_name) || server_def[:ip_address]
|
|
408
|
+
|
|
409
|
+
# Turn it into and object like thing
|
|
410
|
+
OpenStruct.new(server_def)
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def wait_for_sshd(hostname)
|
|
414
|
+
config[:ssh_gateway] ? wait_for_tunnelled_sshd(hostname) : wait_for_direct_sshd(hostname, config[:ssh_port])
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def wait_for_tunnelled_sshd(hostname)
|
|
418
|
+
print(".")
|
|
419
|
+
print(".") until tunnel_test_ssh(hostname) {
|
|
420
|
+
sleep @initial_sleep_delay ||= 2
|
|
421
|
+
puts("done")
|
|
422
|
+
}
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def tunnel_test_ssh(hostname, &block)
|
|
426
|
+
gw_host, gw_user = config[:ssh_gateway].split('@').reverse
|
|
427
|
+
gw_host, gw_port = gw_host.split(':')
|
|
428
|
+
gateway = Net::SSH::Gateway.new(gw_host, gw_user, :port => gw_port || 22)
|
|
429
|
+
status = false
|
|
430
|
+
gateway.open(hostname, config[:ssh_port]) do |local_tunnel_port|
|
|
431
|
+
status = tcp_test_ssh('localhost', local_tunnel_port, &block)
|
|
432
|
+
end
|
|
433
|
+
status
|
|
434
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
|
435
|
+
sleep 2
|
|
436
|
+
false
|
|
437
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
|
438
|
+
false
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def wait_for_direct_sshd(hostname, ssh_port)
|
|
442
|
+
print(".") until tcp_test_ssh(hostname, ssh_port) {
|
|
443
|
+
sleep @initial_sleep_delay ||= 2
|
|
444
|
+
puts("done")
|
|
445
|
+
}
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def tcp_test_ssh(hostname, ssh_port)
|
|
449
|
+
tcp_socket = TCPSocket.new(hostname, ssh_port)
|
|
450
|
+
readable = IO.select([tcp_socket], nil, nil, 5)
|
|
451
|
+
if readable
|
|
452
|
+
Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
|
|
453
|
+
yield
|
|
454
|
+
true
|
|
455
|
+
else
|
|
456
|
+
false
|
|
457
|
+
end
|
|
458
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
|
459
|
+
sleep 2
|
|
460
|
+
false
|
|
461
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
|
462
|
+
false
|
|
463
|
+
# This happens on some mobile phone networks
|
|
464
|
+
rescue Errno::ECONNRESET
|
|
465
|
+
sleep 2
|
|
466
|
+
false
|
|
467
|
+
ensure
|
|
468
|
+
tcp_socket && tcp_socket.close
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'chef/knife/vagrant_base'
|
|
2
|
+
|
|
3
|
+
# These two are needed for the '--purge' deletion case
|
|
4
|
+
require 'chef/node'
|
|
5
|
+
require 'chef/api_client'
|
|
6
|
+
|
|
7
|
+
class Chef
|
|
8
|
+
class Knife
|
|
9
|
+
class VagrantServerDelete < Knife
|
|
10
|
+
|
|
11
|
+
include Knife::VagrantBase
|
|
12
|
+
|
|
13
|
+
banner "knife vagrant server delete SERVER [SERVER] (options)"
|
|
14
|
+
|
|
15
|
+
attr_reader :server
|
|
16
|
+
|
|
17
|
+
option :purge,
|
|
18
|
+
:short => "-P",
|
|
19
|
+
:long => "--purge",
|
|
20
|
+
:boolean => true,
|
|
21
|
+
:default => false,
|
|
22
|
+
:description => "Destroy corresponding node and client on the Chef Server, in addition to destroying the Vagrant node itself."
|
|
23
|
+
|
|
24
|
+
# Extracted from Chef::Knife.delete_object, because it has a
|
|
25
|
+
# confirmation step built in... By specifying the '--purge'
|
|
26
|
+
# flag (and also explicitly confirming the server destruction!)
|
|
27
|
+
# the user is already making their intent known. It is not
|
|
28
|
+
# necessary to make them confirm two more times.
|
|
29
|
+
def destroy_item(klass, name, type_name)
|
|
30
|
+
begin
|
|
31
|
+
object = klass.load(name)
|
|
32
|
+
object.destroy
|
|
33
|
+
ui.warn("Deleted #{type_name} #{name}")
|
|
34
|
+
rescue Net::HTTPServerException
|
|
35
|
+
ui.warn("Could not find a #{type_name} named #{name} to delete!")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def run
|
|
40
|
+
|
|
41
|
+
@name_args.each do |name|
|
|
42
|
+
instance = vagrant_instance_list.detect { |i| i[:name] == name }
|
|
43
|
+
unless instance
|
|
44
|
+
ui.error("No instance named #{name}")
|
|
45
|
+
next
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
msg_pair("Instance Name", instance[:name])
|
|
49
|
+
msg_pair("Box", instance[:box])
|
|
50
|
+
msg_pair("Vagrant File", instance[:vagrant_file])
|
|
51
|
+
msg_pair("IP Address", instance[:ip_address])
|
|
52
|
+
|
|
53
|
+
puts "\n"
|
|
54
|
+
confirm("Do you really want to delete this instance")
|
|
55
|
+
|
|
56
|
+
vagrant_exec(instance[:name], 'destroy -f')
|
|
57
|
+
instance_dir = File.join(locate_config_value(:vagrant_dir), instance[:name])
|
|
58
|
+
FileUtils.rm_rf(instance_dir)
|
|
59
|
+
|
|
60
|
+
ui.warn("Deleted instance #{instance[:name]}")
|
|
61
|
+
|
|
62
|
+
if config[:purge]
|
|
63
|
+
destroy_item(Chef::Node, instance[:name], "node")
|
|
64
|
+
destroy_item(Chef::ApiClient, instance[:name], "client")
|
|
65
|
+
else
|
|
66
|
+
ui.warn("Corresponding node and client for the #{instance[:name]} instance were not deleted and remain registered with the Chef Server")
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'chef/knife/vagrant_base'
|
|
2
|
+
|
|
3
|
+
class Chef
|
|
4
|
+
class Knife
|
|
5
|
+
class VagrantServerHalt < Knife
|
|
6
|
+
|
|
7
|
+
include Knife::VagrantBase
|
|
8
|
+
|
|
9
|
+
banner "knife vagrant server halt SERVER [SERVER]"
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
$stdout.sync = true
|
|
13
|
+
|
|
14
|
+
@name_args.each do |instance|
|
|
15
|
+
unless vagrant_instance_list.detect { |i| i[:name] == instance }
|
|
16
|
+
ui.error("No instance named #{instance}")
|
|
17
|
+
next
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
state, provider = vagrant_instance_state(instance)
|
|
21
|
+
|
|
22
|
+
unless state == 'running' or state == 'saved'
|
|
23
|
+
ui.error("Instance #{instance} needs to be running or suspended for halt. Current state is #{colored_vagrant_state(state)}")
|
|
24
|
+
next
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
vagrant_exec(instance, 'halt')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'chef/knife/vagrant_base'
|
|
2
|
+
|
|
3
|
+
class Chef
|
|
4
|
+
class Knife
|
|
5
|
+
class VagrantServerList < Knife
|
|
6
|
+
|
|
7
|
+
include Knife::VagrantBase
|
|
8
|
+
|
|
9
|
+
banner "knife vagrant server list"
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
$stdout.sync = true
|
|
13
|
+
|
|
14
|
+
server_list = [
|
|
15
|
+
ui.color('Instance Name', :bold),
|
|
16
|
+
ui.color('IP Address', :bold),
|
|
17
|
+
ui.color('Box', :bold),
|
|
18
|
+
ui.color('Provider', :bold),
|
|
19
|
+
ui.color('State', :bold)
|
|
20
|
+
].flatten.compact
|
|
21
|
+
|
|
22
|
+
output_column_count = server_list.length
|
|
23
|
+
|
|
24
|
+
vagrant_instance_list.each do |server|
|
|
25
|
+
server_list << server[:name]
|
|
26
|
+
server_list << server[:ip_address]
|
|
27
|
+
server_list << server[:box]
|
|
28
|
+
|
|
29
|
+
state, provider = vagrant_instance_state(server[:name])
|
|
30
|
+
server_list << provider
|
|
31
|
+
server_list << colored_vagrant_state(state)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
puts ui.list(server_list, :uneven_columns_across, output_column_count)
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'chef/knife/vagrant_base'
|
|
2
|
+
|
|
3
|
+
class Chef
|
|
4
|
+
class Knife
|
|
5
|
+
class VagrantServerResume < Knife
|
|
6
|
+
|
|
7
|
+
include Knife::VagrantBase
|
|
8
|
+
|
|
9
|
+
banner "knife vagrant server resume SERVER [SERVER]"
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
$stdout.sync = true
|
|
13
|
+
|
|
14
|
+
@name_args.each do |instance|
|
|
15
|
+
unless vagrant_instance_list.detect { |i| i[:name] == instance }
|
|
16
|
+
ui.error("No instance named #{instance}")
|
|
17
|
+
next
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
state, provider = vagrant_instance_state(instance)
|
|
21
|
+
|
|
22
|
+
# saved: VirtualBox
|
|
23
|
+
# suspended: VMWare Fusion
|
|
24
|
+
unless state == 'saved' or state == 'suspended'
|
|
25
|
+
ui.error("Instance #{instance} needs to be suspended for resume. Current state is #{colored_vagrant_state(state)}")
|
|
26
|
+
next
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
vagrant_exec(instance, 'resume')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'chef/knife/vagrant_base'
|
|
2
|
+
|
|
3
|
+
class Chef
|
|
4
|
+
class Knife
|
|
5
|
+
class VagrantServerSuspend < Knife
|
|
6
|
+
|
|
7
|
+
include Knife::VagrantBase
|
|
8
|
+
|
|
9
|
+
banner "knife vagrant server suspend SERVER [SERVER]"
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
$stdout.sync = true
|
|
13
|
+
|
|
14
|
+
@name_args.each do |instance|
|
|
15
|
+
unless vagrant_instance_list.detect { |i| i[:name] == instance }
|
|
16
|
+
ui.error("No instance named #{instance}")
|
|
17
|
+
next
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
state, provider = vagrant_instance_state(instance)
|
|
21
|
+
|
|
22
|
+
unless state == 'running'
|
|
23
|
+
ui.error("Instance #{instance} needs to be running for suspend. Current state is #{colored_vagrant_state(state)}")
|
|
24
|
+
next
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
vagrant_exec(instance, 'suspend')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'chef/knife/vagrant_base'
|
|
2
|
+
|
|
3
|
+
class Chef
|
|
4
|
+
class Knife
|
|
5
|
+
class VagrantServerUp < Knife
|
|
6
|
+
|
|
7
|
+
include Knife::VagrantBase
|
|
8
|
+
|
|
9
|
+
banner "knife vagrant server up SERVER [SERVER]"
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
$stdout.sync = true
|
|
13
|
+
|
|
14
|
+
@name_args.each do |instance|
|
|
15
|
+
unless vagrant_instance_list.detect { |i| i[:name] == instance }
|
|
16
|
+
ui.error("No instance named #{instance}")
|
|
17
|
+
next
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
state, provider = vagrant_instance_state(instance)
|
|
21
|
+
|
|
22
|
+
unless state == 'poweroff'
|
|
23
|
+
ui.error("Instance #{instance} needs to be powered off for up. Current state is #{colored_vagrant_state(state)}")
|
|
24
|
+
next
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
vagrant_exec(instance, 'up')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: knife-vagrant3
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Markus Kern
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-12-12 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: chef
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.10.10
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 0.10.10
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
description: Vagrant support for Chef's knife command
|
|
42
|
+
email:
|
|
43
|
+
- chef@mkern.fastmail.fm
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- ".gitignore"
|
|
49
|
+
- CHANGELOG.md
|
|
50
|
+
- Gemfile
|
|
51
|
+
- LICENSE
|
|
52
|
+
- README.md
|
|
53
|
+
- Rakefile
|
|
54
|
+
- knife-vagrant3.gemspec
|
|
55
|
+
- lib/chef/knife/vagrant_base.rb
|
|
56
|
+
- lib/chef/knife/vagrant_box.rb
|
|
57
|
+
- lib/chef/knife/vagrant_server_create.rb
|
|
58
|
+
- lib/chef/knife/vagrant_server_delete.rb
|
|
59
|
+
- lib/chef/knife/vagrant_server_halt.rb
|
|
60
|
+
- lib/chef/knife/vagrant_server_list.rb
|
|
61
|
+
- lib/chef/knife/vagrant_server_resume.rb
|
|
62
|
+
- lib/chef/knife/vagrant_server_suspend.rb
|
|
63
|
+
- lib/chef/knife/vagrant_server_up.rb
|
|
64
|
+
- lib/knife-vagrant/version.rb
|
|
65
|
+
homepage: https://github.com/makern/knife-vagrant2
|
|
66
|
+
licenses:
|
|
67
|
+
- Apache 2.0
|
|
68
|
+
metadata: {}
|
|
69
|
+
post_install_message:
|
|
70
|
+
rdoc_options: []
|
|
71
|
+
require_paths:
|
|
72
|
+
- lib
|
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
requirements: []
|
|
84
|
+
rubyforge_project:
|
|
85
|
+
rubygems_version: 2.4.3
|
|
86
|
+
signing_key:
|
|
87
|
+
specification_version: 4
|
|
88
|
+
summary: Vagrant support for Chef's knife command
|
|
89
|
+
test_files: []
|