vagrant-orchestrate 0.4.7 → 0.5.0
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 +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
|