knife-vagrant2 0.0.5
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 +51 -0
- data/Gemfile +2 -0
- data/LICENSE +13 -0
- data/README.md +48 -0
- data/Rakefile +2 -0
- data/knife-vagrant2.gemspec +21 -0
- data/lib/chef/knife/vagrant_base.rb +165 -0
- data/lib/chef/knife/vagrant_box.rb +15 -0
- data/lib/chef/knife/vagrant_server_create.rb +423 -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: 1ee941f5425873c296f1813ea350eee29f1c1320
|
4
|
+
data.tar.gz: c7254238b04f65993b8fb7de035b0d581ff62c5d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 21875e807264aaeaaeebd2577c3ef99b2ff921b865be5e341dc988f2f7488d37a2bfb505b9d48807a6f6dd0baca3b0e79cf7b222a2a1bc7ccb966de9f8838d99
|
7
|
+
data.tar.gz: 4508b2332c2c063871df1b3ddd376b61883ef495f7ca311868d0680ce5ac233002513f2f3e8e06e31280f82fd4a331a6402e4041f1ba97b5ea783bc84c517c8c
|
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# 0.0.5 (2014-12-11)
|
2
|
+
|
3
|
+
## Changes and new features
|
4
|
+
|
5
|
+
* Added --vmx-customize option to pass arbitrary parameters to VMware providers
|
6
|
+
* Added --vagrant-config option to extend Vagrantfile with custom options
|
7
|
+
|
8
|
+
|
9
|
+
## Fixes
|
10
|
+
|
11
|
+
* Fix missing `ostruct` dependency with newer Chef versions
|
12
|
+
* Fix `--distro` default value change in newer Chef versions
|
13
|
+
|
14
|
+
|
15
|
+
# 0.0.4 (2014-03-14)
|
16
|
+
|
17
|
+
## Changes and new features
|
18
|
+
|
19
|
+
* Added --provider option to use vagrant providers other than virtualbox
|
20
|
+
|
21
|
+
|
22
|
+
# 0.0.3 (2014-01-28)
|
23
|
+
|
24
|
+
## Fixes
|
25
|
+
|
26
|
+
* Fixed error when not using --vb-customize option
|
27
|
+
* Removed unneeded dependency on knife-ec2
|
28
|
+
|
29
|
+
|
30
|
+
# 0.0.2 (2013-12-17)
|
31
|
+
|
32
|
+
## Changes and new features
|
33
|
+
|
34
|
+
* BREAKING: --share-folders option now takes HOST_PATH::GUEST_PATH instead of NAME::GUEST_PATH::HOST_PATH
|
35
|
+
* Added --port-forward option to map host ports to VMs
|
36
|
+
* Added --vb-customize option to pass arbitrary VirtualBox options to Vagrant
|
37
|
+
|
38
|
+
|
39
|
+
# 0.0.1 (2013-12-11)
|
40
|
+
|
41
|
+
## Changes and new features
|
42
|
+
|
43
|
+
* Initial release
|
44
|
+
|
45
|
+
|
46
|
+
# Thanks to our contributors
|
47
|
+
|
48
|
+
* [Jāzeps Baško](https://github.com/jbasko)
|
49
|
+
* [Robert J. Berger](https://github.com/rberger)
|
50
|
+
* [xsunsmile](https://github.com/xsunsmile)
|
51
|
+
* [Mevan Samaratunga](https://github.com/mevansam)
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2013-2014 Markus Kern
|
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
@@ -0,0 +1,48 @@
|
|
1
|
+
knife-vagrant2
|
2
|
+
==============
|
3
|
+
|
4
|
+
This plugin gives knife the ability to create, bootstrap, and manage Vagrant instances.
|
5
|
+
|
6
|
+
The plugin is a rewrite of the original [knife-vagrant](https://github.com/garrettux/knife-vagrant) but more closely resembles knife-ec2 behaviour. Specifically it does _not_ use Vagrant's built in Chef provisioner and instead relies on knife to bootstrap the VM. It will work nicely with [knife-solo](https://github.com/matschaffer/knife-solo) and doesn't require a Chef server.
|
7
|
+
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
If you are using bundler, simply add Chef and knife-vagrant2 to your `Gemfile`:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'chef'
|
15
|
+
gem 'knife-vagrant2'
|
16
|
+
```
|
17
|
+
|
18
|
+
If you are not using bundler, you can install the gem manually:
|
19
|
+
|
20
|
+
$ gem install knife-vagrant2
|
21
|
+
|
22
|
+
|
23
|
+
Usage
|
24
|
+
-----
|
25
|
+
knife-vagrant2 creates a `/vagrant` subfolder in your project which it uses to manage Vagrant files for all the instances you launch. You should add this folder to your `.gitignore` file so it is never checked into version control.
|
26
|
+
|
27
|
+
To launch a new VM use the `server create` command:
|
28
|
+
|
29
|
+
knife vagrant server create --box-url http://files.vagrantup.com/precise32.box -N db -r role[db]
|
30
|
+
|
31
|
+
This will launch a new VM using the `precise32` box, give the node a Chef name of `db` and then use knife to provision the VM with the `db` role.
|
32
|
+
|
33
|
+
If a box is already installed into vagrant use `--box` instead of `--box-url` to reference it.
|
34
|
+
|
35
|
+
By default knife-vagrant2 picks a private IP address from a predefined pool and assigns it to the VM. You can specify the IP pool using `--subnet` or assign a specfic IP with `--private-ip-address`.
|
36
|
+
|
37
|
+
To map folders between host and VM use `--share-folders NAME::GUEST_PATH::HOST_PATH`.
|
38
|
+
|
39
|
+
After a VM has been created its Chef name is used to reference it in future commands. Most commands map directly to the Vagrant ones:
|
40
|
+
|
41
|
+
knife vagrant server suspend SERVER [SERVER]
|
42
|
+
knife vagrant server resume SERVER [SERVER]
|
43
|
+
knife vagrant server halt SERVER [SERVER]
|
44
|
+
knife vagrant server up SERVER [SERVER]
|
45
|
+
knife vagrant server delete SERVER [SERVER] (options)
|
46
|
+
knife vagrant server list
|
47
|
+
|
48
|
+
All commands can be applied to one or more VMs.
|
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-vagrant2'
|
7
|
+
s.version = Knife::Vagrant::VERSION
|
8
|
+
s.authors = ['Markus Kern']
|
9
|
+
s.email = ['makern@users.noreply.github.com']
|
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,165 @@
|
|
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
|
+
cwd = Dir.getwd()
|
28
|
+
Dir.chdir(File.join(locate_config_value(:vagrant_dir), instance))
|
29
|
+
end
|
30
|
+
|
31
|
+
cmd = "vagrant #{cmd}"
|
32
|
+
output = nil
|
33
|
+
if defined? Bundler
|
34
|
+
# Needed if we are run from inside a bundler environment and vagrant
|
35
|
+
# is installed as global gem. If this causes problems for anyone please
|
36
|
+
# file a bug report.
|
37
|
+
Bundler.with_clean_env do
|
38
|
+
output = fetch_output ? %x(#{cmd}) : system(cmd)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
output = fetch_output ? %x(#{cmd}) : system(cmd)
|
42
|
+
end
|
43
|
+
|
44
|
+
unless no_cwd_change
|
45
|
+
Dir.chdir(cwd)
|
46
|
+
end
|
47
|
+
output
|
48
|
+
end
|
49
|
+
|
50
|
+
def vagrant_instance_state(instance)
|
51
|
+
output = vagrant_exec(instance, 'status', fetch_output: true)
|
52
|
+
state = /Current machine states:.+?default\s+(.+?)\s+\((.+?)\)/m.match(output)
|
53
|
+
unless state
|
54
|
+
ui.warn("Couldn't parse state of instance #{instance}")
|
55
|
+
return ['', '']
|
56
|
+
end
|
57
|
+
return [state[1], state[2]]
|
58
|
+
end
|
59
|
+
|
60
|
+
def vagrant_instance_list
|
61
|
+
# Memoize so we don't have to parse files multiple times
|
62
|
+
if @vagrant_instances
|
63
|
+
return @vagrant_instances
|
64
|
+
end
|
65
|
+
|
66
|
+
vangrant_dir = locate_config_value(:vagrant_dir)
|
67
|
+
@vagrant_instances = []
|
68
|
+
|
69
|
+
unless File.exist? vangrant_dir
|
70
|
+
return @vagrant_instances
|
71
|
+
end
|
72
|
+
|
73
|
+
Dir.foreach(vangrant_dir) { |subdir|
|
74
|
+
vagrant_file = File.join(vangrant_dir, subdir, 'Vagrantfile')
|
75
|
+
if File.exist? vagrant_file
|
76
|
+
instance = { :name => subdir,
|
77
|
+
:vagrant_file => vagrant_file
|
78
|
+
}
|
79
|
+
# Read settings from vagrant file
|
80
|
+
content = IO.read(vagrant_file)
|
81
|
+
instance[:ip_address] = /config\.vm\.network[^,]+,\s*ip:\s*"([0-9\.]+)"/.match(content) { |m| m[1] }
|
82
|
+
unless instance[:ip_address]
|
83
|
+
ui.warn("Couldn't find IP address in #{vagrant_file}. Is it malformed?")
|
84
|
+
end
|
85
|
+
|
86
|
+
instance[:box] = /config\.vm\.box[^=]*=\s*"([^"]+)"/.match(content) { |m| m[1] }
|
87
|
+
unless instance[:box]
|
88
|
+
ui.warn("Couldn't find box in #{vagrant_file}. Is it malformed?")
|
89
|
+
end
|
90
|
+
@vagrant_instances.push(instance)
|
91
|
+
end
|
92
|
+
}
|
93
|
+
@vagrant_instances
|
94
|
+
end
|
95
|
+
|
96
|
+
def write_insecure_key
|
97
|
+
# The private key most vagrant boxes use.
|
98
|
+
insecure_key = <<-EOF
|
99
|
+
-----BEGIN RSA PRIVATE KEY-----
|
100
|
+
MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI
|
101
|
+
w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP
|
102
|
+
kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2
|
103
|
+
hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO
|
104
|
+
Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW
|
105
|
+
yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd
|
106
|
+
ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1
|
107
|
+
Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf
|
108
|
+
TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK
|
109
|
+
iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A
|
110
|
+
sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf
|
111
|
+
4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP
|
112
|
+
cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk
|
113
|
+
EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN
|
114
|
+
CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX
|
115
|
+
3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG
|
116
|
+
YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj
|
117
|
+
3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+
|
118
|
+
dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz
|
119
|
+
6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC
|
120
|
+
P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF
|
121
|
+
llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ
|
122
|
+
kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH
|
123
|
+
+vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ
|
124
|
+
NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s=
|
125
|
+
-----END RSA PRIVATE KEY-----
|
126
|
+
EOF
|
127
|
+
insecure_key
|
128
|
+
|
129
|
+
# Write key to vagrant folder if it's not there yet.
|
130
|
+
key_file = File.join(locate_config_value(:vagrant_dir), 'insecure_key')
|
131
|
+
unless File.exist? key_file
|
132
|
+
ui.msg("Creating #{key_file}")
|
133
|
+
FileUtils.mkdir_p(locate_config_value(:vagrant_dir))
|
134
|
+
File.open(key_file, 'w') { |f| f.write(insecure_key) }
|
135
|
+
File.chmod(0600, key_file)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def locate_config_value(key)
|
140
|
+
key = key.to_sym
|
141
|
+
config[key] || Chef::Config[:knife][key]
|
142
|
+
end
|
143
|
+
|
144
|
+
def msg_pair(label, value, color=:cyan)
|
145
|
+
if value && !value.to_s.empty?
|
146
|
+
puts "#{ui.color(label, color)}: #{value}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def colored_vagrant_state(state)
|
151
|
+
case state
|
152
|
+
when 'saved','paused','poweroff', 'stuck', 'aborted', 'gurumeditation', 'inaccessible'
|
153
|
+
ui.color(state, :red)
|
154
|
+
when 'saving'
|
155
|
+
ui.color(state, :yellow)
|
156
|
+
else
|
157
|
+
ui.color(state, :green)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
|
@@ -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,423 @@
|
|
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_customize,
|
161
|
+
:long => "--vmx-customize VMX_PARAMETERS",
|
162
|
+
:description => "List of parameters for the vmware vagrant providers 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 :vagrant_config,
|
170
|
+
:long => "--vagrant-config SETTINGS",
|
171
|
+
:description => "Lines of configuration to be inserted into the Vagrantfile separated by ::"
|
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)
|
220
|
+
customize.split(/::/).collect { |k| "v.vmx [ #{k} ]" }.join("\n") if customize
|
221
|
+
end
|
222
|
+
|
223
|
+
def build_shares(share_folders)
|
224
|
+
share_folders.collect do |share|
|
225
|
+
host, guest = share.chomp.split "::"
|
226
|
+
"config.vm.synced_folder '#{host}', '#{guest}'"
|
227
|
+
end.join("\n")
|
228
|
+
end
|
229
|
+
|
230
|
+
def write_vagrantfile
|
231
|
+
additions = []
|
232
|
+
if @server.use_cachier
|
233
|
+
additions << 'config.cache.auto_detect = true' # enable vagarant-cachier
|
234
|
+
end
|
235
|
+
if @server.vagrant_config
|
236
|
+
additions << @server.vagrant_config.split(/::/)
|
237
|
+
end
|
238
|
+
|
239
|
+
file = <<-EOF
|
240
|
+
Vagrant.configure("2") do |config|
|
241
|
+
config.vm.box = "#{@server.box}"
|
242
|
+
config.vm.box_url = "#{@server.box_url}"
|
243
|
+
config.vm.hostname = "#{@server.name}"
|
244
|
+
|
245
|
+
config.vm.network :private_network, ip: "#{@server.ip_address}"
|
246
|
+
#{build_port_forwards(@server.port_forward)}
|
247
|
+
|
248
|
+
#{build_shares(@server.share_folders)}
|
249
|
+
|
250
|
+
config.vm.provider :virtualbox do |vb|
|
251
|
+
vb.customize [ "modifyvm", :id, "--memory", #{@server.memsize} ]
|
252
|
+
#{build_vb_customize(@server.vb_customize)}
|
253
|
+
end
|
254
|
+
|
255
|
+
config.vm.provider :vmware_fusion do |v|
|
256
|
+
v.vmx["memsize"] = "#{@server.memsize}"
|
257
|
+
#{build_vmx_customize(@server.vmx_customize)}
|
258
|
+
end
|
259
|
+
|
260
|
+
config.vm.provider :vmware_workstation do |v|
|
261
|
+
v.vmx["memsize"] = "#{@server.memsize}"
|
262
|
+
#{build_vmx_customize(@server.vmx_customize)}
|
263
|
+
end
|
264
|
+
|
265
|
+
#{additions.join("\n")}
|
266
|
+
end
|
267
|
+
EOF
|
268
|
+
file
|
269
|
+
|
270
|
+
# Create folder and write Vagrant file
|
271
|
+
instance_dir = File.join(locate_config_value(:vagrant_dir), @server.name)
|
272
|
+
instance_file = File.join(instance_dir, 'Vagrantfile')
|
273
|
+
ui.msg("Creating #{instance_file}")
|
274
|
+
FileUtils.mkdir_p(instance_dir)
|
275
|
+
File.open(instance_file, 'w') { |f| f.write(file) }
|
276
|
+
end
|
277
|
+
|
278
|
+
def bootstrap_node(server,ssh_host)
|
279
|
+
bootstrap = Chef::Knife::Bootstrap.new
|
280
|
+
bootstrap.name_args = [ssh_host]
|
281
|
+
bootstrap.config[:ssh_user] = config[:ssh_user]
|
282
|
+
bootstrap.config[:ssh_port] = config[:ssh_port]
|
283
|
+
bootstrap.config[:ssh_gateway] = config[:ssh_gateway]
|
284
|
+
bootstrap.config[:identity_file] = config[:identity_file] || File.join(locate_config_value(:vagrant_dir), 'insecure_key')
|
285
|
+
bootstrap.config[:chef_node_name] = locate_config_value(:chef_node_name) || server.ip
|
286
|
+
bootstrap.config[:distro] = locate_config_value(:distro) || "chef-full"
|
287
|
+
bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
|
288
|
+
bootstrap.config[:host_key_verify] = config[:host_key_verify]
|
289
|
+
|
290
|
+
bootstrap.config[:run_list] = config[:run_list]
|
291
|
+
bootstrap.config[:prerelease] = config[:prerelease]
|
292
|
+
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
293
|
+
bootstrap.config[:distro] = locate_config_value(:distro)
|
294
|
+
bootstrap.config[:template_file] = locate_config_value(:template_file)
|
295
|
+
bootstrap.config[:environment] = locate_config_value(:environment)
|
296
|
+
bootstrap.config[:prerelease] = config[:prerelease]
|
297
|
+
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
298
|
+
bootstrap.config[:first_boot_attributes] = locate_config_value(:json_attributes) || {}
|
299
|
+
bootstrap.config[:encrypted_data_bag_secret] = locate_config_value(:encrypted_data_bag_secret)
|
300
|
+
bootstrap.config[:encrypted_data_bag_secret_file] = locate_config_value(:encrypted_data_bag_secret_file)
|
301
|
+
bootstrap.config[:secret] = locate_config_value(:secret)
|
302
|
+
bootstrap.config[:secret_file] = locate_config_value(:secret_file)
|
303
|
+
# Modify global configuration state to ensure hint gets set by
|
304
|
+
# knife-bootstrap
|
305
|
+
Chef::Config[:knife][:hints] ||= {}
|
306
|
+
Chef::Config[:knife][:hints]["vagrant"] ||= {} # Cargo Cult programming FTW?
|
307
|
+
|
308
|
+
msg_pair("SSH User", bootstrap.config[:ssh_user])
|
309
|
+
msg_pair("SSH identity file", bootstrap.config[:identity_file])
|
310
|
+
bootstrap
|
311
|
+
end
|
312
|
+
|
313
|
+
def validate!
|
314
|
+
unless locate_config_value(:box) || locate_config_value(:box_url)
|
315
|
+
ui.error("You need to either specify --box or --box-url")
|
316
|
+
exit 1
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def find_available_ip
|
321
|
+
subnet = locate_config_value('subnet')
|
322
|
+
IPAddr.new(subnet).to_range().each { |ip|
|
323
|
+
# 192.168.3.0/24 should yield 192.168.3.2 through 192.168.3.254
|
324
|
+
# 192.168.3.1 cannot be used because virtual box uses it for the router
|
325
|
+
mask = IPAddr::IN4MASK ^ ip.instance_variable_get("@mask_addr")
|
326
|
+
unless [0, 1, mask].include? (ip & mask) or vagrant_instance_list.detect { |i| i[:ip_address] == ip.to_s }
|
327
|
+
return ip.to_s
|
328
|
+
end
|
329
|
+
}
|
330
|
+
ui.error("No unused IP address available in subnet #{subnet}")
|
331
|
+
exit 1
|
332
|
+
end
|
333
|
+
|
334
|
+
def create_server_def
|
335
|
+
server_def = {
|
336
|
+
:box => locate_config_value(:box),
|
337
|
+
:box_url => locate_config_value(:box_url),
|
338
|
+
:memsize => locate_config_value(:memsize),
|
339
|
+
:share_folders => config[:share_folders],
|
340
|
+
:port_forward => config[:port_forward],
|
341
|
+
:use_cachier => config[:use_cachier],
|
342
|
+
:vb_customize => locate_config_value(:vb_customize),
|
343
|
+
:vmx_customize => locate_config_value(:vmx_customize),
|
344
|
+
:vagrant_config => locate_config_value(:vagrant_config)
|
345
|
+
}
|
346
|
+
|
347
|
+
# Get specified IP address for new instance or pick an unused one from the subnet pool.
|
348
|
+
server_def[:ip_address] = config[:ip_address] || find_available_ip
|
349
|
+
|
350
|
+
collision = vagrant_instance_list.detect { |i| i[:ip_address] == server_def[:ip_address] }
|
351
|
+
if collision
|
352
|
+
ui.error("IP address #{server_def[:ip_address]} already in use by instance #{collision[:name]}")
|
353
|
+
exit 1
|
354
|
+
end
|
355
|
+
|
356
|
+
# Derive name for vagrant instance from chef node name or IP
|
357
|
+
server_def[:name] = locate_config_value(:chef_node_name) || server_def[:ip_address]
|
358
|
+
|
359
|
+
# Turn it into and object like thing
|
360
|
+
OpenStruct.new(server_def)
|
361
|
+
end
|
362
|
+
|
363
|
+
def wait_for_sshd(hostname)
|
364
|
+
config[:ssh_gateway] ? wait_for_tunnelled_sshd(hostname) : wait_for_direct_sshd(hostname, config[:ssh_port])
|
365
|
+
end
|
366
|
+
|
367
|
+
def wait_for_tunnelled_sshd(hostname)
|
368
|
+
print(".")
|
369
|
+
print(".") until tunnel_test_ssh(hostname) {
|
370
|
+
sleep @initial_sleep_delay ||= 2
|
371
|
+
puts("done")
|
372
|
+
}
|
373
|
+
end
|
374
|
+
|
375
|
+
def tunnel_test_ssh(hostname, &block)
|
376
|
+
gw_host, gw_user = config[:ssh_gateway].split('@').reverse
|
377
|
+
gw_host, gw_port = gw_host.split(':')
|
378
|
+
gateway = Net::SSH::Gateway.new(gw_host, gw_user, :port => gw_port || 22)
|
379
|
+
status = false
|
380
|
+
gateway.open(hostname, config[:ssh_port]) do |local_tunnel_port|
|
381
|
+
status = tcp_test_ssh('localhost', local_tunnel_port, &block)
|
382
|
+
end
|
383
|
+
status
|
384
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
385
|
+
sleep 2
|
386
|
+
false
|
387
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
388
|
+
false
|
389
|
+
end
|
390
|
+
|
391
|
+
def wait_for_direct_sshd(hostname, ssh_port)
|
392
|
+
print(".") until tcp_test_ssh(hostname, ssh_port) {
|
393
|
+
sleep @initial_sleep_delay ||= 2
|
394
|
+
puts("done")
|
395
|
+
}
|
396
|
+
end
|
397
|
+
|
398
|
+
def tcp_test_ssh(hostname, ssh_port)
|
399
|
+
tcp_socket = TCPSocket.new(hostname, ssh_port)
|
400
|
+
readable = IO.select([tcp_socket], nil, nil, 5)
|
401
|
+
if readable
|
402
|
+
Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
|
403
|
+
yield
|
404
|
+
true
|
405
|
+
else
|
406
|
+
false
|
407
|
+
end
|
408
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
409
|
+
sleep 2
|
410
|
+
false
|
411
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
412
|
+
false
|
413
|
+
# This happens on some mobile phone networks
|
414
|
+
rescue Errno::ECONNRESET
|
415
|
+
sleep 2
|
416
|
+
false
|
417
|
+
ensure
|
418
|
+
tcp_socket && tcp_socket.close
|
419
|
+
end
|
420
|
+
|
421
|
+
end
|
422
|
+
end
|
423
|
+
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-vagrant2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
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
|
+
- makern@users.noreply.github.com
|
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-vagrant2.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.2.2
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: Vagrant support for Chef's knife command
|
89
|
+
test_files: []
|