vagrant-orchestrate 0.4.7 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +34 -134
- data/Rakefile +2 -2
- data/Vagrantfile +2 -0
- data/acceptance/command/status_spec.rb +35 -0
- data/docs/environments.md +82 -0
- data/docs/puppet.md +32 -0
- data/lib/vagrant-orchestrate/command/command_mixins.rb +40 -0
- data/lib/vagrant-orchestrate/command/init.rb +1 -1
- data/lib/vagrant-orchestrate/command/push.rb +55 -16
- data/lib/vagrant-orchestrate/command/root.rb +5 -2
- data/lib/vagrant-orchestrate/command/status.rb +69 -0
- data/lib/vagrant-orchestrate/repo_status.rb +61 -0
- data/lib/vagrant-orchestrate/version.rb +1 -1
- data/lib/vms.save +24 -0
- data/mytestfile +0 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 819bc31d3db68968306ae9731bfb0c7d65dbb068
|
4
|
+
data.tar.gz: 36ed5193b32ddf55945b36ebc8c241a6e22e154a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 508a675892462b3d0d6615966ba0574ccf749f11ae40fba8a6902ab81b6f10ec2cfec0b40a8fbf0233459af6c1dc6dd8354772f9b3ca314043e56e43006cf19f
|
7
|
+
data.tar.gz: 45002e7db4623f4f193b956d732eb6b7def0d19c3f7d4eaf907c76d269a0b697e5966cfd9fa5bf4b06392c7c0eb0277de57dfb161c0c56eb64d9d4a0e8284201
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
0.5.0 (April 22, 2015)
|
2
|
+
|
3
|
+
- Add guard_clean so that a push will fail if there are uncommitted files. Override with VAGRANT_ORCHESTRATE_NO_GUARD_CLEAN
|
4
|
+
- Push a status file including git remote url, ref, user, and date on a successful provision to /var/status/vagrant_orchestrate (c:\programdata\vagrant_orchestrate)
|
5
|
+
- Retrieve status using `vagrant orchestrate status`
|
data/README.md
CHANGED
@@ -14,7 +14,7 @@ Linux, and Mac**.
|
|
14
14
|
## Quick start
|
15
15
|
|
16
16
|
```
|
17
|
-
$ vagrant orchestrate init --shell --shell-inline "echo Hello" \
|
17
|
+
$ vagrant orchestrate init --shell --shell-inline "echo Hello!" \
|
18
18
|
--servers myserver1.mydomain.com,myserver2.mydomain.com \
|
19
19
|
--ssh-username USERNAME --ssh-private-key-path PATH
|
20
20
|
$ vagrant orchestrate push
|
@@ -109,94 +109,24 @@ This works for Windows managed servers using WinRM as well
|
|
109
109
|
|
110
110
|
#### Plugins
|
111
111
|
|
112
|
-
This also supports a
|
112
|
+
This also supports a portable way to install plugins, just list them in the required_plugins section
|
113
113
|
|
114
114
|
```ruby
|
115
115
|
required_plugins = %w( vagrant-managed-servers vagrant-hostsupdater )
|
116
116
|
```
|
117
117
|
|
118
118
|
#### Working with multiple environments
|
119
|
-
It is a very common pattern in software development to have separate environments - e.g. dev, test, and prod.
|
120
|
-
Vagrant Orchestrate offers a way to manage multiple environments using a combination of a single servers.json
|
121
|
-
file and the name of the current git branch to know which the current environment is.
|
122
|
-
|
123
|
-
```javascript
|
124
|
-
# servers.json
|
125
|
-
{
|
126
|
-
"environments": {
|
127
|
-
"dev": {
|
128
|
-
"servers": [
|
129
|
-
"dev.myapp.mydomain.com"
|
130
|
-
]
|
131
|
-
},
|
132
|
-
"test": {
|
133
|
-
"servers": [
|
134
|
-
"test1.myapp.mydomain.com",
|
135
|
-
"test2.myapp.mydomain.com"
|
136
|
-
]
|
137
|
-
},
|
138
|
-
"prod": {
|
139
|
-
"servers": [
|
140
|
-
"prod1.myapp.mydomain.com",
|
141
|
-
"prod2.myapp.mydomain.com",
|
142
|
-
"prod3.myapp.mydomain.com"
|
143
|
-
]
|
144
|
-
}
|
145
|
-
}
|
146
|
-
}
|
147
|
-
```
|
148
119
|
|
149
|
-
|
120
|
+
Vagrant Orchestrate offers a way to manage multiple environments using a combination of a single servers.json file and the name of the current git branch as an indicator of the current environment.
|
150
121
|
|
151
|
-
|
152
|
-
managed_servers = VagrantPlugins::Orchestrate::Plugin.load_servers_for_branch
|
153
|
-
```
|
122
|
+
To initialize an environment aware Vagrantfile, use
|
154
123
|
|
155
|
-
|
156
|
-
you'll only be able to see the servers appropriate for that environment.
|
124
|
+
$ vagrant orchestrate init --environments dev,test,prod
|
157
125
|
|
158
|
-
|
159
|
-
|
160
|
-
* dev
|
161
|
-
test
|
162
|
-
prod
|
163
|
-
$ vagrant status
|
164
|
-
Current machine states:
|
165
|
-
|
166
|
-
local not created (virtualbox)
|
167
|
-
dev.myapp.mydomain.com not created (managed)
|
168
|
-
|
169
|
-
$ git checkout test
|
170
|
-
Switched to branch 'test'
|
171
|
-
$ vagrant status
|
172
|
-
Current machine states:
|
173
|
-
|
174
|
-
local not created (virtualbox)
|
175
|
-
test1.myapp.mydomain.com not created (managed)
|
176
|
-
test2.myapp.mydomain.com not created (managed)
|
177
|
-
|
178
|
-
$ git checkout prod
|
179
|
-
Switched to branch 'prod'
|
180
|
-
$ vagrant status
|
181
|
-
Current machine states:
|
182
|
-
|
183
|
-
local not created (virtualbox)
|
184
|
-
prod1.myapp.mydomain.com not created (managed)
|
185
|
-
prod2.myapp.mydomain.com not created (managed)
|
186
|
-
prod3.myapp.mydomain.com not created (managed)
|
187
|
-
```
|
126
|
+
You'll need to create git branches with matching names and fill out the servers.json
|
127
|
+
file in order for the Vagrantfile to be git branch aware.
|
188
128
|
|
189
|
-
|
190
|
-
not list any managed servers.
|
191
|
-
|
192
|
-
```
|
193
|
-
$ git checkout -b my_feature_branch
|
194
|
-
Switched to a new branch 'my_feature_branch'
|
195
|
-
$ vagrant status
|
196
|
-
Current machine states:
|
197
|
-
|
198
|
-
local not created (virtualbox)
|
199
|
-
```
|
129
|
+
Learn more about [environments](docs/environments.md)
|
200
130
|
|
201
131
|
#### Credentials
|
202
132
|
|
@@ -206,13 +136,7 @@ by passing the `--credentials-prompt` flag to the `vagrant orchestrate init` com
|
|
206
136
|
or add the following to your Vagrantfile.
|
207
137
|
|
208
138
|
```ruby
|
209
|
-
|
210
|
-
|
211
|
-
...
|
212
|
-
|
213
|
-
config.orchestrate.credentials do |creds|
|
214
|
-
creds.prompt = true
|
215
|
-
end
|
139
|
+
config.orchestrate.credentials.prompt = true
|
216
140
|
```
|
217
141
|
|
218
142
|
The credentials config object can accept one additional parameter, `file_path`. Setting
|
@@ -227,36 +151,7 @@ will be checked.
|
|
227
151
|
|
228
152
|
#### Puppet
|
229
153
|
|
230
|
-
Experimental puppet templating support is available as well with the `--puppet` flag and associated options
|
231
|
-
|
232
|
-
```ruby
|
233
|
-
required_plugins = %w( vagrant-managed-servers vagrant-librarian-puppet )
|
234
|
-
|
235
|
-
...
|
236
|
-
|
237
|
-
config.librarian_puppet.placeholder_filename = ".gitignore"
|
238
|
-
config.vm.provision "puppet" do |puppet|
|
239
|
-
puppet.module_path = 'modules'
|
240
|
-
puppet.hiera_config_path = 'hiera.yaml'
|
241
|
-
end
|
242
|
-
```
|
243
|
-
|
244
|
-
The following files and folders will be placed in the puppet directory
|
245
|
-
|
246
|
-
```
|
247
|
-
Puppetfile
|
248
|
-
Vagrantfile
|
249
|
-
dummy.box
|
250
|
-
hiera/
|
251
|
-
common.yaml
|
252
|
-
hiera.yaml
|
253
|
-
manifests/
|
254
|
-
default.pp
|
255
|
-
modules/
|
256
|
-
.gitignore
|
257
|
-
```
|
258
|
-
|
259
|
-
For a full list of init options, run `vagrant orchestrate init --help`
|
154
|
+
Experimental [puppet templating](docs/puppet.md) support is available as well with the `--puppet` flag and associated options
|
260
155
|
|
261
156
|
### Pushing changes
|
262
157
|
Go ahead and push changes to your managed servers, in serial by default.
|
@@ -267,13 +162,27 @@ The push command is currently limited by convention to vagrant machines that use
|
|
267
162
|
|
268
163
|
#### Deployment Strategy
|
269
164
|
|
270
|
-
Vagrant Orchestrate supports several deployment [strategies](docs/strategy.md) including parallel, canary, and
|
271
|
-
half and half.
|
165
|
+
Vagrant Orchestrate supports several deployment [strategies](docs/strategy.md) including parallel, canary, and half and half.
|
272
166
|
|
273
167
|
You can push changes to all of your servers in parallel with
|
274
168
|
|
275
169
|
$ vagrant orchestrate push --strategy parallel
|
276
170
|
|
171
|
+
### Status
|
172
|
+
The `vagrant orchestrate status` command will reach out to each of the defined
|
173
|
+
managed servers and print information about the last successful push from this
|
174
|
+
repo, including date, ref, and user that performed the push.
|
175
|
+
|
176
|
+
```
|
177
|
+
$ vagrant orchestrate status
|
178
|
+
Current managed server states:
|
179
|
+
|
180
|
+
managed-1 2015-04-19 00:46:22 UTC e983dddd8041c5db77494266328f1d266430f57d cbaldauf
|
181
|
+
managed-2 2015-04-19 00:46:22 UTC e983dddd8041c5db77494266328f1d266430f57d cbaldauf
|
182
|
+
managed-3 Status unavailable.
|
183
|
+
managed-4 2015-04-19 00:43:07 UTC e983dddd8041c5db77494266328f1d266430f57d cbaldauf
|
184
|
+
```
|
185
|
+
|
277
186
|
## Filtering managed commands
|
278
187
|
It can be easy to make mistakes such as rebooting production if you have managed long-lived servers as well as local VMs defined in your Vagrantfile. We add some protection with the `orchestrate.filter_managed_commands` configuration setting, which will cause up, provision, reload, and destroy commands to be ignored for servers with the managed provider.
|
279
188
|
|
@@ -281,14 +190,6 @@ It can be easy to make mistakes such as rebooting production if you have managed
|
|
281
190
|
config.orchestrate.filter_managed_commands = true
|
282
191
|
```
|
283
192
|
|
284
|
-
## Branching strategy
|
285
|
-
|
286
|
-
If you have several environments (e.g. dev, test, prod), it is recommended to create
|
287
|
-
a separate branch for each environment and put the appropriate servers into the
|
288
|
-
managed_servers array at the top of the Vagrantfile for each. To move a change
|
289
|
-
across branches, simply create a feature branch from your earliest branch and then
|
290
|
-
merge that feature into downstream environments to avoid conflicts.
|
291
|
-
|
292
193
|
## Tips for Windows hosts
|
293
194
|
|
294
195
|
* Need rsync? Install [OpenSSH](http://www.mls-software.com/opensshd.html) and then run this [script](https://github.com/joefitzgerald/packer-windows/blob/master/scripts/rsync.bat) to install rsync. Vagrant managed servers currently only works with cygwin based rsync implementations.
|
@@ -302,14 +203,13 @@ merge that feature into downstream environments to avoid conflicts.
|
|
302
203
|
4. Push to the branch (`git push origin my-new-feature`)
|
303
204
|
5. Create a new Pull Request
|
304
205
|
|
305
|
-
## Development
|
306
|
-
|
307
|
-
You'll want Ruby v2.0.0* and bundler for developing changes.
|
308
|
-
|
309
|
-
During the course of development you'll want to run the code you're working on,
|
310
|
-
not the version of Vagrant Orchestrate you've installed. In order to accomplish
|
311
|
-
this, run your vagrant orchestrate commands in the bundler environment.
|
206
|
+
## Development Flow
|
312
207
|
|
313
|
-
|
208
|
+
Prerequisites:
|
209
|
+
* Ruby 2.0 or greater
|
314
210
|
|
315
|
-
|
211
|
+
Flow:
|
212
|
+
1. Develop your feature
|
213
|
+
2. Test locally with `bundle exec vagrant orchestrate *`
|
214
|
+
3. `bundle exec rake build`
|
215
|
+
4. `bundle exec rake acceptance`, which will take a few minutes
|
data/Rakefile
CHANGED
@@ -10,13 +10,13 @@ task default: :build
|
|
10
10
|
|
11
11
|
desc "Run acceptance tests with vagrant-spec"
|
12
12
|
task :acceptance do
|
13
|
-
puts "
|
13
|
+
puts "Bringing up target servers and syncing with NTP"
|
14
14
|
# Spinning up local servers here, which the managed provider will connect to
|
15
15
|
# by IP. See the Vagrantfile in the root of the repo for more info.
|
16
16
|
system("vagrant up /local/ --no-provision")
|
17
17
|
# To ensure the ntp sync happens even if the servers are already up
|
18
18
|
system("vagrant provision /local/")
|
19
|
-
system("bundle exec vagrant-spec test --components=orchestrate/push orchestrate/prompt")
|
19
|
+
system("bundle exec vagrant-spec test --components=orchestrate/push orchestrate/prompt orchestrate/status")
|
20
20
|
puts "Destroying target servers"
|
21
21
|
system("vagrant destroy -f /local/")
|
22
22
|
end
|
data/Vagrantfile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
managed_servers = %w( 192.168.10.80 192.168.10.81 192.168.10.82 192.168.10.83)
|
2
2
|
|
3
3
|
Vagrant.configure(2) do |config|
|
4
|
+
config.orchestrate.filter_managed_commands = true
|
5
|
+
|
4
6
|
# These boxes are defined locally to enable acceptance testing. Spinning up
|
5
7
|
# real boxes in the vagrant-spec environment was expensive because it ignored
|
6
8
|
# the cache and didn't expose a facility to view the vagrant output as it ran.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "vagrant-spec"
|
2
|
+
require "vagrant-orchestrate/repo_status"
|
3
|
+
|
4
|
+
describe "vagrant orchestrate status", component: "orchestrate/status" do
|
5
|
+
include_context "acceptance"
|
6
|
+
|
7
|
+
TEST_REF = "050bfd9c686b06c292a9614662b0ab1bbf652db3"
|
8
|
+
TEST_REMOTE_ORIGIN_URL = "http://github.com/Cimpress-MCP/vagrant-orchestrate.git"
|
9
|
+
|
10
|
+
before do
|
11
|
+
environment.skeleton("basic")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "handles no status file gracefully" do
|
15
|
+
# Make sure we're starting from a clean slate, rspec order isn't guaranteed.
|
16
|
+
execute("vagrant", "ssh", "-c", "\"rm -rf /var/state/vagrant_orchestrate\" /managed-1/")
|
17
|
+
# All commands are executed against a single machine to reduce variability
|
18
|
+
result = execute("vagrant", "orchestrate", "status", "/managed-1/")
|
19
|
+
expect(result.stdout).to include("Status unavailable.")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can push and retrieve status" do
|
23
|
+
# Because vagrant-spec executes in a clean tmp folder, it isn't a git repo,
|
24
|
+
# and the normal git commands don't work. We'll inject some test data using
|
25
|
+
# environment variables. See vagrant-orchestrate/repo_status.rb for impl.
|
26
|
+
ENV["VAGRANT_ORCHESTRATE_STATUS_TEST_REF"] = TEST_REF
|
27
|
+
ENV["VAGRANT_ORCHESTRATE_STATUS_TEST_REMOTE_ORIGIN_URL"] = TEST_REMOTE_ORIGIN_URL
|
28
|
+
execute("vagrant", "orchestrate", "push", "/managed-1/")
|
29
|
+
result = execute("vagrant", "orchestrate", "status", "/managed-1/")
|
30
|
+
status = VagrantPlugins::Orchestrate::RepoStatus.new
|
31
|
+
# Punting on date. Can always add it later if needed
|
32
|
+
expect(result.stdout).to include(status.ref)
|
33
|
+
expect(result.stdout).to include(status.user)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Environments
|
2
|
+
It is a very common pattern in software development to have separate environments - e.g. dev, test, and prod.
|
3
|
+
Vagrant Orchestrate offers a way to manage multiple environments using a combination of a single servers.json
|
4
|
+
file and the name of the current git branch to know which the current environment is.
|
5
|
+
|
6
|
+
```javascript
|
7
|
+
# servers.json
|
8
|
+
{
|
9
|
+
"environments": {
|
10
|
+
"dev": {
|
11
|
+
"servers": [
|
12
|
+
"dev.myapp.mydomain.com"
|
13
|
+
]
|
14
|
+
},
|
15
|
+
"test": {
|
16
|
+
"servers": [
|
17
|
+
"test1.myapp.mydomain.com",
|
18
|
+
"test2.myapp.mydomain.com"
|
19
|
+
]
|
20
|
+
},
|
21
|
+
"prod": {
|
22
|
+
"servers": [
|
23
|
+
"prod1.myapp.mydomain.com",
|
24
|
+
"prod2.myapp.mydomain.com",
|
25
|
+
"prod3.myapp.mydomain.com"
|
26
|
+
]
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
```
|
31
|
+
|
32
|
+
Add the following line to the top of your `Vagrantfile`
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
managed_servers = VagrantPlugins::Orchestrate::Plugin.load_servers_for_branch
|
36
|
+
```
|
37
|
+
|
38
|
+
If you create git branches named `dev`, `test`, and `prod`, your vagrantfile will become environment aware and
|
39
|
+
you'll only be able to see the servers appropriate for that environment.
|
40
|
+
|
41
|
+
```
|
42
|
+
$ git branch
|
43
|
+
* dev
|
44
|
+
test
|
45
|
+
prod
|
46
|
+
$ vagrant status
|
47
|
+
Current machine states:
|
48
|
+
|
49
|
+
local not created (virtualbox)
|
50
|
+
dev.myapp.mydomain.com not created (managed)
|
51
|
+
|
52
|
+
$ git checkout test
|
53
|
+
Switched to branch 'test'
|
54
|
+
$ vagrant status
|
55
|
+
Current machine states:
|
56
|
+
|
57
|
+
local not created (virtualbox)
|
58
|
+
test1.myapp.mydomain.com not created (managed)
|
59
|
+
test2.myapp.mydomain.com not created (managed)
|
60
|
+
|
61
|
+
$ git checkout prod
|
62
|
+
Switched to branch 'prod'
|
63
|
+
$ vagrant status
|
64
|
+
Current machine states:
|
65
|
+
|
66
|
+
local not created (virtualbox)
|
67
|
+
prod1.myapp.mydomain.com not created (managed)
|
68
|
+
prod2.myapp.mydomain.com not created (managed)
|
69
|
+
prod3.myapp.mydomain.com not created (managed)
|
70
|
+
```
|
71
|
+
|
72
|
+
Any branch that doesn't have a matching environment in the servers.json file will
|
73
|
+
not list any managed servers.
|
74
|
+
|
75
|
+
```
|
76
|
+
$ git checkout -b my_feature_branch
|
77
|
+
Switched to a new branch 'my_feature_branch'
|
78
|
+
$ vagrant status
|
79
|
+
Current machine states:
|
80
|
+
|
81
|
+
local not created (virtualbox)
|
82
|
+
```
|
data/docs/puppet.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Puppet
|
2
|
+
|
3
|
+
Experimental [puppet templating](docs/puppet.md) support is available as well with the `--puppet` flag and associated options
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
required_plugins = %w( vagrant-managed-servers vagrant-librarian-puppet )
|
7
|
+
|
8
|
+
...
|
9
|
+
|
10
|
+
config.librarian_puppet.placeholder_filename = ".gitignore"
|
11
|
+
config.vm.provision "puppet" do |puppet|
|
12
|
+
puppet.module_path = 'modules'
|
13
|
+
puppet.hiera_config_path = 'hiera.yaml'
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
The following files and folders will be placed in the puppet directory
|
18
|
+
|
19
|
+
```
|
20
|
+
Puppetfile
|
21
|
+
Vagrantfile
|
22
|
+
dummy.box
|
23
|
+
hiera/
|
24
|
+
common.yaml
|
25
|
+
hiera.yaml
|
26
|
+
manifests/
|
27
|
+
default.pp
|
28
|
+
modules/
|
29
|
+
.gitignore
|
30
|
+
```
|
31
|
+
|
32
|
+
For a full list of init options, run `vagrant orchestrate init --help`
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Orchestrate
|
3
|
+
module Command
|
4
|
+
module CommandMixins
|
5
|
+
# Given an array of vagrant command line args (e.g. the result of calling
|
6
|
+
# parse_options), filter out unmanaged servers and provide the resulting list.
|
7
|
+
def filter_unmanaged(argv)
|
8
|
+
machines = []
|
9
|
+
with_target_vms(argv) do |machine|
|
10
|
+
if machine.provider_name.to_sym == :managed
|
11
|
+
machines << machine
|
12
|
+
else
|
13
|
+
@logger.debug("Skipping #{machine.name} because it doesn't use the :managed provider")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
if machines.empty?
|
18
|
+
@env.ui.info("No servers with :managed provider found. Exiting.")
|
19
|
+
end
|
20
|
+
|
21
|
+
machines
|
22
|
+
end
|
23
|
+
|
24
|
+
# Delete a file in a way that works on windows
|
25
|
+
def super_delete(filepath)
|
26
|
+
# Thanks, Windows. http://alx.github.io/2009/01/27/ruby-wundows-unlink.html
|
27
|
+
10.times do
|
28
|
+
begin
|
29
|
+
File.delete(filepath)
|
30
|
+
break
|
31
|
+
rescue
|
32
|
+
@logger.warn("Unable to delete file #{filepath}")
|
33
|
+
sleep 0.05
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -142,7 +142,7 @@ module VagrantPlugins
|
|
142
142
|
environments: options[:environments],
|
143
143
|
plugins: options[:plugins],
|
144
144
|
creds_prompt: options[:creds_prompt]
|
145
|
-
|
145
|
+
)
|
146
146
|
write_file("Vagrantfile", contents, options)
|
147
147
|
FileUtils.cp(Orchestrate.source_root.join("templates", "vagrant", "dummy.box"),
|
148
148
|
File.join(@env.cwd, "dummy.box"))
|
@@ -1,6 +1,9 @@
|
|
1
|
+
require "English"
|
1
2
|
require "optparse"
|
2
3
|
require "vagrant"
|
3
4
|
require "vagrant-orchestrate/action/setcredentials"
|
5
|
+
require "vagrant-orchestrate/repo_status"
|
6
|
+
require_relative "command_mixins"
|
4
7
|
|
5
8
|
# Borrowed from http://stackoverflow.com/questions/12374645/splitting-an-array-into-equal-parts-in-ruby
|
6
9
|
class Array
|
@@ -16,6 +19,7 @@ module VagrantPlugins
|
|
16
19
|
module Command
|
17
20
|
class Push < Vagrant.plugin("2", :command)
|
18
21
|
include Vagrant::Util
|
22
|
+
include CommandMixins
|
19
23
|
|
20
24
|
@logger = Log4r::Logger.new("vagrant_orchestrate::command::push")
|
21
25
|
|
@@ -44,19 +48,10 @@ module VagrantPlugins
|
|
44
48
|
argv = parse_options(opts)
|
45
49
|
return unless argv
|
46
50
|
|
47
|
-
|
48
|
-
with_target_vms(argv) do |machine|
|
49
|
-
if machine.provider_name.to_sym == :managed
|
50
|
-
machines << machine
|
51
|
-
else
|
52
|
-
@logger.debug("Skipping #{machine.name} because it doesn't use the :managed provider")
|
53
|
-
end
|
54
|
-
end
|
51
|
+
guard_clean unless ENV["VAGRANT_ORCHESTRATE_NO_GUARD_CLEAN"]
|
55
52
|
|
56
|
-
|
57
|
-
|
58
|
-
return 0
|
59
|
-
end
|
53
|
+
machines = filter_unmanaged(argv)
|
54
|
+
return 0 if machines.empty?
|
60
55
|
|
61
56
|
retrieve_creds(machines) if @env.vagrantfile.config.orchestrate.credentials
|
62
57
|
|
@@ -94,6 +89,7 @@ module VagrantPlugins
|
|
94
89
|
return 1 unless result
|
95
90
|
0
|
96
91
|
end
|
92
|
+
# rubocop:enable Metrics/AbcSize, MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
97
93
|
|
98
94
|
def split(machines)
|
99
95
|
groups = machines.in_groups(2)
|
@@ -103,6 +99,7 @@ module VagrantPlugins
|
|
103
99
|
groups
|
104
100
|
end
|
105
101
|
|
102
|
+
# rubocop:disable Metrics/AbcSize, MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
106
103
|
def deploy(options, *groups)
|
107
104
|
groups.select! { |g| g.size > 0 }
|
108
105
|
groups.each_with_index do |machines, index|
|
@@ -115,6 +112,7 @@ module VagrantPlugins
|
|
115
112
|
begin
|
116
113
|
batchify(machines, :up, options)
|
117
114
|
batchify(machines, :provision, options)
|
115
|
+
upload_status_all(machines)
|
118
116
|
batchify(machines, :reload, options) if options[:reboot]
|
119
117
|
ensure
|
120
118
|
batchify(machines, :destroy, options)
|
@@ -159,12 +157,53 @@ module VagrantPlugins
|
|
159
157
|
creds.apply_creds(machine, username, password)
|
160
158
|
end
|
161
159
|
else
|
162
|
-
@env.ui.warn
|
163
|
-
Vagrant-orchestrate could not gather credentials. \
|
164
|
-
Continuing with default credentials."
|
165
|
-
WARNING
|
160
|
+
@env.ui.warn "Vagrant-orchestrate could not gather credentials. Continuing with default credentials."
|
166
161
|
end
|
167
162
|
end
|
163
|
+
|
164
|
+
def guard_clean
|
165
|
+
clean? && committed? || abort("ERROR!\nThere are files that need to be committed first.")
|
166
|
+
end
|
167
|
+
|
168
|
+
def clean?
|
169
|
+
`git diff --exit-code 2>&1`
|
170
|
+
$CHILD_STATUS == 0
|
171
|
+
end
|
172
|
+
|
173
|
+
def committed?
|
174
|
+
`git diff-index --quiet --cached HEAD 2>&1`
|
175
|
+
$CHILD_STATUS == 0
|
176
|
+
end
|
177
|
+
|
178
|
+
def upload_status_all(machines)
|
179
|
+
status = RepoStatus.new
|
180
|
+
source = File.join(@env.tmp_path, "vagrant_orchestrate_status")
|
181
|
+
File.write(source, status.to_json)
|
182
|
+
machines.each do |machine|
|
183
|
+
upload_status_one(source, status, machine)
|
184
|
+
end
|
185
|
+
ensure
|
186
|
+
super_delete(source) if File.exist?(source)
|
187
|
+
end
|
188
|
+
|
189
|
+
def upload_status_one(source, status, machine)
|
190
|
+
destination = status.remote_path(machine.config.vm.communicator)
|
191
|
+
parent_folder = File.split(destination)[0]
|
192
|
+
machine.communicate.wait_for_ready(5)
|
193
|
+
@logger.debug("Ensuring vagrant_orchestrate status directory exists")
|
194
|
+
machine.communicate.sudo("mkdir -p #{parent_folder}")
|
195
|
+
machine.communicate.sudo("chmod 777 #{parent_folder}")
|
196
|
+
@logger.debug("Uploading vagrant_orchestrate status file")
|
197
|
+
@logger.debug(" source: #{source}")
|
198
|
+
@logger.debug(" dest: #{destination}")
|
199
|
+
machine.communicate.upload(source, destination)
|
200
|
+
@logger.debug("Setting uploaded file world-writable")
|
201
|
+
machine.communicate.sudo("chmod 777 #{destination}")
|
202
|
+
rescue => ex
|
203
|
+
@logger.error(ex)
|
204
|
+
@env.ui.warn("An error occurred when trying to upload status to #{machine.name}. Continuing")
|
205
|
+
@env.ui.warn(ex.message)
|
206
|
+
end
|
168
207
|
end
|
169
208
|
end
|
170
209
|
end
|
@@ -25,6 +25,11 @@ module VagrantPlugins
|
|
25
25
|
require_relative "push"
|
26
26
|
Push
|
27
27
|
end
|
28
|
+
|
29
|
+
@subcommands.register(:status) do
|
30
|
+
require_relative "status"
|
31
|
+
Status
|
32
|
+
end
|
28
33
|
end
|
29
34
|
|
30
35
|
def execute
|
@@ -44,7 +49,6 @@ module VagrantPlugins
|
|
44
49
|
end
|
45
50
|
|
46
51
|
# Prints the help out for this command
|
47
|
-
# rubocop:disable Metrics/AbcSize
|
48
52
|
def help
|
49
53
|
opts = OptionParser.new do |o|
|
50
54
|
o.banner = "Usage: vagrant orchestrate <subcommand> [<args>]"
|
@@ -66,7 +70,6 @@ module VagrantPlugins
|
|
66
70
|
|
67
71
|
@env.ui.info(opts.help, prefix: false)
|
68
72
|
end
|
69
|
-
# rubocop:enable Metrics/AbcSize
|
70
73
|
end
|
71
74
|
end
|
72
75
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "json"
|
2
|
+
require "optparse"
|
3
|
+
require "vagrant"
|
4
|
+
require "vagrant-orchestrate/repo_status"
|
5
|
+
require_relative "command_mixins"
|
6
|
+
|
7
|
+
module VagrantPlugins
|
8
|
+
module Orchestrate
|
9
|
+
module Command
|
10
|
+
class Status < Vagrant.plugin("2", :command)
|
11
|
+
include Vagrant::Util
|
12
|
+
include CommandMixins
|
13
|
+
|
14
|
+
@logger = Log4r::Logger.new("vagrant_orchestrate::command::status")
|
15
|
+
|
16
|
+
def execute
|
17
|
+
opts = OptionParser.new do |o|
|
18
|
+
o.banner = "Usage: vagrant orchestrate status"
|
19
|
+
o.separator ""
|
20
|
+
end
|
21
|
+
|
22
|
+
argv = parse_options(opts)
|
23
|
+
return unless argv
|
24
|
+
|
25
|
+
machines = filter_unmanaged(argv)
|
26
|
+
return 0 if machines.empty?
|
27
|
+
|
28
|
+
print_status machines
|
29
|
+
end
|
30
|
+
|
31
|
+
def print_status(machines)
|
32
|
+
# There is some detail output fromt he communicator.download that I
|
33
|
+
# don't want to suppress, but I also don't want it to be interspersed
|
34
|
+
# with the actual status information. Let's buffer the status output.
|
35
|
+
output = []
|
36
|
+
@logger.debug("About to download machine status")
|
37
|
+
machines.each do |machine|
|
38
|
+
output << get_status(RepoStatus.new.remote_path(machine.config.vm.communicator), machine)
|
39
|
+
end
|
40
|
+
@env.ui.info("Current managed server states:")
|
41
|
+
@env.ui.info("")
|
42
|
+
output.each do |line|
|
43
|
+
@env.ui.info line
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_status(remote, machine)
|
48
|
+
machine.communicate.wait_for_ready(5)
|
49
|
+
local = File.join(@env.tmp_path, "#{machine.name}_status")
|
50
|
+
@logger.debug("Downloading orchestrate status for #{machine.name}")
|
51
|
+
@logger.debug(" remote file: #{remote}")
|
52
|
+
@logger.debug(" local file: #{local}")
|
53
|
+
machine.communicate.download(remote, local)
|
54
|
+
content = File.read(local)
|
55
|
+
@logger.debug("File content:")
|
56
|
+
@logger.debug(content)
|
57
|
+
status = JSON.parse(content)
|
58
|
+
return machine.name.to_s + " " + status["last_sync"] + " " + status["ref"] + " " + status["user"]
|
59
|
+
rescue => ex
|
60
|
+
@env.ui.warn("Error downloading status for #{machine.name}.")
|
61
|
+
@env.ui.warn(ex.message)
|
62
|
+
return machine.name.to_s + " Status unavailable."
|
63
|
+
ensure
|
64
|
+
super_delete(local) if File.exist?(local)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Orchestrate
|
5
|
+
class RepoStatus
|
6
|
+
attr_reader :last_sync
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@last_sync = Time.now.utc # Managed servers could be in different timezones
|
10
|
+
end
|
11
|
+
|
12
|
+
def ref
|
13
|
+
# Env vars are here only for testing, since vagrant-spec is executed from
|
14
|
+
# a temp directory and can't use git to get repository information
|
15
|
+
@ref ||= ENV["VAGRANT_ORCHESTRATE_STATUS_TEST_REF"]
|
16
|
+
@ref ||= `git log --pretty=format:'%H' --abbrev-commit -1`
|
17
|
+
@ref
|
18
|
+
end
|
19
|
+
|
20
|
+
def remote_origin_url
|
21
|
+
@remote_origin_url ||= ENV["VAGRANT_ORCHESTRATE_STATUS_TEST_REMOTE_ORIGIN_URL"]
|
22
|
+
@remote_origin_url ||= `git config --get remote.origin.url`.chomp
|
23
|
+
@remote_origin_url
|
24
|
+
end
|
25
|
+
|
26
|
+
def repo
|
27
|
+
@repo ||= File.basename(remote_origin_url, ".git")
|
28
|
+
@repo
|
29
|
+
end
|
30
|
+
|
31
|
+
def user
|
32
|
+
user = ENV["USER"] || ENV["USERNAME"] || "unknown"
|
33
|
+
user = ENV["USERDOMAIN"] + "\\" + user if ENV["USERDOMAIN"]
|
34
|
+
|
35
|
+
@user ||= user
|
36
|
+
@user
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_json
|
40
|
+
contents = {
|
41
|
+
repo: repo,
|
42
|
+
remote_url: remote_origin_url,
|
43
|
+
ref: ref,
|
44
|
+
user: user,
|
45
|
+
last_sync: last_sync
|
46
|
+
}
|
47
|
+
JSON.pretty_generate(contents)
|
48
|
+
end
|
49
|
+
|
50
|
+
# The path to where this should be stored on a remote machine, inclusive
|
51
|
+
# of the file name.
|
52
|
+
def remote_path(communicator)
|
53
|
+
if communicator == :winrm
|
54
|
+
File.join("c:", "programdata", "vagrant_orchestrate", repo)
|
55
|
+
else
|
56
|
+
File.join("/var", "state", "vagrant_orchestrate", repo)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/vms.save
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# R&D work that may be used in a future version, but can be ignored for now.
|
2
|
+
module ManagedServers
|
3
|
+
module Action
|
4
|
+
include Vagrant::Action::Builtin
|
5
|
+
def self.action_push
|
6
|
+
Vagrant::Action::Builder.new.tap do |b|
|
7
|
+
b.use HandleBox
|
8
|
+
b.use ConfigValidate
|
9
|
+
b.use WarnNetworks
|
10
|
+
b.use Call, IsLinked do |env, b2|
|
11
|
+
if env[:result]
|
12
|
+
b2.use MessageAlreadyLinked
|
13
|
+
next
|
14
|
+
end
|
15
|
+
|
16
|
+
b2.use LinkServer
|
17
|
+
end
|
18
|
+
b.use Provision
|
19
|
+
b.use SyncFolders
|
20
|
+
b.use UnlinkServer
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/mytestfile
ADDED
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-orchestrate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Baldauf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- .rspec
|
78
78
|
- .rubocop.yml
|
79
79
|
- .travis.yml
|
80
|
+
- CHANGELOG.md
|
80
81
|
- Gemfile
|
81
82
|
- LICENSE
|
82
83
|
- README.md
|
@@ -84,22 +85,30 @@ files:
|
|
84
85
|
- Vagrantfile
|
85
86
|
- acceptance/command/prompt_spec.rb
|
86
87
|
- acceptance/command/push_spec.rb
|
88
|
+
- acceptance/command/status_spec.rb
|
87
89
|
- acceptance/support-skeletons/basic/Vagrantfile
|
88
90
|
- acceptance/support-skeletons/basic/dummy.box
|
89
91
|
- acceptance/support-skeletons/prompt/Vagrantfile
|
90
92
|
- acceptance/support-skeletons/prompt/dummy.box
|
93
|
+
- docs/environments.md
|
94
|
+
- docs/puppet.md
|
91
95
|
- docs/strategy.md
|
92
96
|
- dummy.box
|
93
97
|
- lib/vagrant-orchestrate.rb
|
94
98
|
- lib/vagrant-orchestrate/action/filtermanaged.rb
|
95
99
|
- lib/vagrant-orchestrate/action/setcredentials.rb
|
100
|
+
- lib/vagrant-orchestrate/command/command_mixins.rb
|
96
101
|
- lib/vagrant-orchestrate/command/init.rb
|
97
102
|
- lib/vagrant-orchestrate/command/push.rb
|
98
103
|
- lib/vagrant-orchestrate/command/root.rb
|
104
|
+
- lib/vagrant-orchestrate/command/status.rb
|
99
105
|
- lib/vagrant-orchestrate/config.rb
|
100
106
|
- lib/vagrant-orchestrate/plugin.rb
|
107
|
+
- lib/vagrant-orchestrate/repo_status.rb
|
101
108
|
- lib/vagrant-orchestrate/version.rb
|
109
|
+
- lib/vms.save
|
102
110
|
- locales/en.yml
|
111
|
+
- mytestfile
|
103
112
|
- spec/spec_helper.rb
|
104
113
|
- spec/vagrant-orchestrate/command/init_spec.rb
|
105
114
|
- spec/vagrant-orchestrate/command/root_spec.rb
|