vagrant-flow 1.0.10 → 1.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +112 -16
- data/VAGRANT-FLOW +23 -0
- data/create_sample_hostfile_digitalocean_input-file.rb +25 -0
- data/create_sample_multiinit_input-file_digitalocean.rb +34 -0
- data/create_sample_playbook_input-file.rb +27 -0
- data/lib/vagrant-flow/command/digitalocean_api.rb +51 -0
- data/lib/vagrant-flow/command/hostfile.rb +87 -39
- data/lib/vagrant-flow/command/playbook.rb +127 -0
- data/lib/vagrant-flow/command/root.rb +5 -0
- data/lib/vagrant-flow/templates/multiinit.erb +17 -0
- data/lib/vagrant-flow/version.rb +1 -1
- metadata +7 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d3ded31cb6dedca2fa9b995903b2efb9fbef217
|
4
|
+
data.tar.gz: 4877689ebcecd0ecf990a3245fbfe46518c4d040
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e64d23a40b362c4497bbbacbcd4bba7771cdb86385075d9c2ab8dba59b3b6d4b14373311cc15198f89353bb35d2527cc9c1a8bca836e94cf22f0a218bc1da64
|
7
|
+
data.tar.gz: 7edfa6e7af03f6ec087d2cfa3643ab5d7a46cf7c4180a96dc16f79f094c5f8518c99a05ab3bcb81907af2f22aa05caba4a0262647fca359815e080205f6eb956
|
data/README.md
CHANGED
@@ -1,29 +1,76 @@
|
|
1
1
|
# Vagrant-Flow
|
2
2
|
|
3
|
-
Vagrant
|
3
|
+
Vagrant-Flow enables a seamless development to production workflow.
|
4
4
|
|
5
|
+
Vagrant-Flow is a vagrant plugin which allows for a separation of ansible playbooks from vagrant, mimicing how development works. It enables the generates ansible inventory files, vagrant templates and inter-machine communication to easily prepare to run ansible playbooks and machine communication.
|
5
6
|
|
6
|
-
|
7
|
+
- This is part of [NeverwinterDP the Data Pipeline for Hadoop](https://github.com/DemandCube/NeverwinterDP)
|
7
8
|
|
8
|
-
`vagrant plugin install vagrant-flow`
|
9
9
|
|
10
|
+
## Installation
|
10
11
|
|
11
|
-
|
12
|
+
```
|
13
|
+
#This is so 'vagrant flow hostfile' can automatically connect to digital ocean machines
|
14
|
+
#Otherwise it will hang when dealing with remote hosts
|
15
|
+
echo "StrictHostKeyChecking no" >> ~/.ssh/config
|
12
16
|
|
13
|
-
|
17
|
+
#If you're on OSX
|
18
|
+
brew install curl-ca-bundle
|
14
19
|
|
15
|
-
gem 'vagrant-flow'
|
16
20
|
|
17
|
-
|
21
|
+
vagrant plugin install vagrant-digitalocean
|
22
|
+
vagrant plugin install vagrant-flow
|
23
|
+
```
|
18
24
|
|
19
|
-
|
25
|
+
## Contributing
|
20
26
|
|
21
|
-
|
27
|
+
See the [NeverwinterDP Guide to Contributing] (https://github.com/DemandCube/NeverwinterDP#how-to-contribute)
|
22
28
|
|
23
|
-
$ gem install vagrant-flow
|
24
29
|
|
25
30
|
* * *
|
26
31
|
|
32
|
+
## Usage and Specs
|
33
|
+
vagrant-flow has 1 command `flow` and the following subcommands:
|
34
|
+
|
35
|
+
```
|
36
|
+
multiinit
|
37
|
+
hostfile
|
38
|
+
ansibleinventory
|
39
|
+
playbook
|
40
|
+
```
|
41
|
+
|
42
|
+
- multiinit
|
43
|
+
- Creates a template Vagrantfile based on the machines you specify
|
44
|
+
- hostfile
|
45
|
+
- Creates a hostfile and copies it to each VM so that machine can talk to each other
|
46
|
+
- ansibleinventory
|
47
|
+
- Create a ansible machine inventory file so that you can use ansible to provision the machines
|
48
|
+
- playbook
|
49
|
+
- Uses a confile to run ansible-play book to provision one or more VM's
|
50
|
+
|
51
|
+
Example flow to be enabled
|
52
|
+
```
|
53
|
+
vagrant plugin install vagrant-flow
|
54
|
+
git clone http://github.com/DemandCube/DeveloperPlaybooks
|
55
|
+
mkdir devsetup
|
56
|
+
cd devsetup
|
57
|
+
vagrant flow multiinit -l boxname1:demandcube/centos-65_x86_64-VB-4.3.8,boxname2:demandcube/centos-65_x86_65-VB-4.3.8
|
58
|
+
vagrant up
|
59
|
+
vagrant flow hostfile
|
60
|
+
vagrant flow ansibleinventory
|
61
|
+
|
62
|
+
# Then
|
63
|
+
|
64
|
+
vagrant flow playbook
|
65
|
+
# or
|
66
|
+
ansible-playbook -i ansible-flow_inventoryfile ../DeveloperPlaybooks/site.yml
|
67
|
+
|
68
|
+
#communication test
|
69
|
+
vagrant ssh boxname1 ping boxname2
|
70
|
+
vagrant ssh boxname2 ping boxname1
|
71
|
+
```
|
72
|
+
|
73
|
+
|
27
74
|
# Usage
|
28
75
|
|
29
76
|
|
@@ -229,7 +276,46 @@ servergroup
|
|
229
276
|
```
|
230
277
|
|
231
278
|
* * *
|
279
|
+
##playbook
|
280
|
+
```
|
281
|
+
Usage: vagrant flow playbook [-hpf]
|
282
|
+
Reads in config from flow-playbook.yml by default to be able to run ansible-playbook more easily
|
232
283
|
|
284
|
+
-f, --file-playbook FILE (Optional) Use a specified playbook config file instead of default (flow-playbook.yml)
|
285
|
+
-p, --print-only (Optional) Don't actually ansible-playbook, but just output what would be run to STDOUT
|
286
|
+
-q, --quiet (Optional) Suppress output to STDOUT and STDERR
|
287
|
+
-h, --help Print this help
|
288
|
+
```
|
289
|
+
|
290
|
+
This will run ansible-playbook based on the config in flow-playbook.yml
|
291
|
+
```
|
292
|
+
vagrant flow playbook
|
293
|
+
```
|
294
|
+
|
295
|
+
This will run ansible-playbook based on the config in myOwnConfig.yml
|
296
|
+
```
|
297
|
+
vagrant flow playbook -f myOwnConfig.yml
|
298
|
+
```
|
299
|
+
|
300
|
+
This will not actually run ansible-playbook, but will only output the command it would run to STDOUT
|
301
|
+
```
|
302
|
+
vagrant flow playbook -p
|
303
|
+
```
|
304
|
+
The output from the above command using -p will look like this:
|
305
|
+
```
|
306
|
+
ansible-playbook -i vagrant-flow_ansible_inventory myPlaybooks/main.yml
|
307
|
+
```
|
308
|
+
|
309
|
+
###Expectations:
|
310
|
+
Example flow-playbook.yml file
|
311
|
+
```
|
312
|
+
---
|
313
|
+
:playbook: defaultplaybook.yml #Required
|
314
|
+
:inventory: vagrant-flow_ansible_inventory #Required
|
315
|
+
:pattern: '*' #Optional. Will be used in conjunction like so 'ansible-playbook -l [pattern] -i [inventory] -p [playbook]'
|
316
|
+
```
|
317
|
+
|
318
|
+
* * *
|
233
319
|
|
234
320
|
## Future Usage and Specs
|
235
321
|
Looking for vagrant-flow to have the following commands:
|
@@ -262,13 +348,7 @@ vagrant ssh frontend1 ping frontend2
|
|
262
348
|
vagrant ssh frontend2 ping frontend1
|
263
349
|
```
|
264
350
|
|
265
|
-
## Contributing
|
266
351
|
|
267
|
-
1. Fork it ( http://github.com/DemandCube/vagrant-flow/fork )
|
268
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
269
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
270
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
271
|
-
5. Create new Pull Request
|
272
352
|
|
273
353
|
|
274
354
|
## Development Flow
|
@@ -314,6 +394,22 @@ Creating a Gem
|
|
314
394
|
* Tutorial <>
|
315
395
|
* <http://railscasts.com/episodes/245-new-gem-with-bundler>
|
316
396
|
|
397
|
+
Below is how to install as a regular gem which won't work
|
398
|
+
|
399
|
+
Add this line to your application's Gemfile:
|
400
|
+
|
401
|
+
gem 'vagrant-flow'
|
402
|
+
|
403
|
+
And then execute:
|
404
|
+
|
405
|
+
$ bundle
|
406
|
+
|
407
|
+
Or install it yourself as:
|
408
|
+
|
409
|
+
$ gem install vagrant-flow
|
410
|
+
|
411
|
+
* * *
|
412
|
+
|
317
413
|
Commands
|
318
414
|
|
319
415
|
```
|
data/VAGRANT-FLOW
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
__ __ _____ _____ _ _ _______ ______ _ ______ __
|
2
|
+
\ \ / /\ / ____| __ \ /\ | \ | |__ __| | ____| | / __ \ \ / /
|
3
|
+
\ \ / / \ | | __| |__) | / \ | \| | | |______| |__ | | | | | \ \ /\ / /
|
4
|
+
\ \/ / /\ \| | |_ | _ / / /\ \ | . ` | | |______| __| | | | | | |\ \/ \/ /
|
5
|
+
\ / ____ \ |__| | | \ \ / ____ \| |\ | | | | | | |___| |__| | \ /\ /
|
6
|
+
\/_/ \_\_____|_| \_\/_/ \_\_| \_| |_| |_| |______\____/ \/ \/
|
7
|
+
/\
|
8
|
+
/ \
|
9
|
+
/ /\ \
|
10
|
+
/ ____ \
|
11
|
+
/_/___ \_\ _ _____ _
|
12
|
+
| __ \ | |/ ____| | |
|
13
|
+
| | | | ___ _ __ ___ __ _ _ __ __| | | _ _| |__ ___
|
14
|
+
| | | |/ _ \ '_ ` _ \ / _` | '_ \ / _` | | | | | | '_ \ / _ \
|
15
|
+
| |__| | __/ | | | | | (_| | | | | (_| | |___| |_| | |_) | __/
|
16
|
+
|_____/ \___|_| |_| |_|\__,_|_| |_|\__,_|\_____\__,_|_.__/ \___|
|
17
|
+
| __ \ (_) | |
|
18
|
+
| |__) | __ ___ _ ___ ___| |_
|
19
|
+
| ___/ '__/ _ \| |/ _ \/ __| __|
|
20
|
+
| | | | | (_) | | __/ (__| |_
|
21
|
+
|_| |_| \___/| |\___|\___|\__|
|
22
|
+
_/ |
|
23
|
+
|__/
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
###This shows how to make a valid configuration file in YAML format for vagrant-flow to consume with the ansible-inventory command
|
6
|
+
|
7
|
+
x = {
|
8
|
+
:api_key => "apikeygoeshere",
|
9
|
+
:client_id => "clientidgoeshere",
|
10
|
+
}
|
11
|
+
|
12
|
+
begin
|
13
|
+
File.open('hostfile_do.yml', 'w') {|f| f.write x.to_yaml }
|
14
|
+
rescue
|
15
|
+
warn "Could not write file hostfile_do.yml"
|
16
|
+
end
|
17
|
+
|
18
|
+
y = YAML.load(x.to_yaml)
|
19
|
+
|
20
|
+
y.each {|key,value|
|
21
|
+
puts key
|
22
|
+
puts value
|
23
|
+
puts "\n"
|
24
|
+
}
|
25
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
###This shows how to make a valid configuration file in YAML format for vagrant-flow to consume with the ansible-inventory command
|
6
|
+
x = {
|
7
|
+
:sshPrivateKeyPath =>"~/.ssh/id_rsa",
|
8
|
+
:digitalOceanApiKey => "digitaloceanapikeygoeshere",
|
9
|
+
:digitalOceanClientId => "digitaloceanclientidgoeshere",
|
10
|
+
:digitalOceanRegion => "San Francisco 1",
|
11
|
+
:intnetName=>"neverwinterDP",
|
12
|
+
"machines" => [
|
13
|
+
{"name"=>"sparkngin1", "url"=>"demandcube/centos-65_x86_64-VB-4.3.8", "digitalOceanImage"=>"CentOS 6.5 x64"},
|
14
|
+
{"name"=>"sparkngin2", "url"=>"demandcube/centos-65_x86_64-VB-4.3.8", "digitalOceanImage"=>"CentOS 6.5 x64"},
|
15
|
+
{"name"=>"jenkinsdp", "url"=>"demandcube/centos-65_x86_64-VB-4.3.8", "digitalOceanImage"=>"CentOS 6.5 x64"},
|
16
|
+
]
|
17
|
+
}
|
18
|
+
|
19
|
+
begin
|
20
|
+
File.open('multiinitconfig.yml', 'w') {|f|
|
21
|
+
f.write x.to_yaml
|
22
|
+
}
|
23
|
+
rescue
|
24
|
+
warn "Could not write file multiinit.yml"
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
y = YAML.load(x.to_yaml)
|
29
|
+
|
30
|
+
y.each {|key,value|
|
31
|
+
puts key
|
32
|
+
puts value
|
33
|
+
puts "\n"
|
34
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
###This shows how to make a valid configuration file in YAML format for vagrant-flow to consume with the ansible-inventory command
|
6
|
+
x = {
|
7
|
+
:playbook => "defaultplaybook.yml",
|
8
|
+
:inventory => "vagrant-flow_ansible_inventory",
|
9
|
+
#:pattern => "*", #:pattern is optional
|
10
|
+
}
|
11
|
+
|
12
|
+
begin
|
13
|
+
File.open('flow-playbook.yml', 'w') {|f|
|
14
|
+
f.write x.to_yaml
|
15
|
+
}
|
16
|
+
rescue
|
17
|
+
warn "Could not write file flow-playbook.yml"
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
y = YAML.load(x.to_yaml)
|
22
|
+
|
23
|
+
y.each {|key,value|
|
24
|
+
puts key
|
25
|
+
puts value
|
26
|
+
puts "\n"
|
27
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
class DigitalOcean_Api
|
6
|
+
|
7
|
+
def initialize(digitaloceanurl= 'https://api.digitalocean.com/droplets/?')
|
8
|
+
@DIGITALOCEAN_URL=digitaloceanurl
|
9
|
+
end
|
10
|
+
|
11
|
+
#getparams should be a hash that will get turned into a url
|
12
|
+
def makeApiCall(getparams)
|
13
|
+
url = @DIGITALOCEAN_URL
|
14
|
+
getparams.each {|key,val|
|
15
|
+
url+=key+"="+val+"&"
|
16
|
+
}
|
17
|
+
url = url.chomp("&")
|
18
|
+
|
19
|
+
response = Net::HTTP.get_response(URI.parse(url))
|
20
|
+
|
21
|
+
return JSON.parse(response.body)
|
22
|
+
end
|
23
|
+
|
24
|
+
#https://api.digitalocean.com/droplets/?client_id=xxxxxxx&api_key=yyyyyyyyyy
|
25
|
+
#returns parsed hash object from returned json
|
26
|
+
def showAllActiveDroplets(clientId,apiKey)
|
27
|
+
x = {
|
28
|
+
"client_id" => clientId,
|
29
|
+
"api_key" => apiKey,
|
30
|
+
}
|
31
|
+
return makeApiCall(x)
|
32
|
+
end
|
33
|
+
|
34
|
+
#Calls showAllActiveDroplets and then parses the info for just hostname and ip
|
35
|
+
def getHostNamesAndIps(clientId,apiKey)
|
36
|
+
hash = showAllActiveDroplets(clientId,apiKey)
|
37
|
+
returnHash = []
|
38
|
+
hash["droplets"].each {|droplet|
|
39
|
+
returnHash.push({
|
40
|
+
:hostname => droplet["name"],
|
41
|
+
:ip => droplet["ip_address"]
|
42
|
+
})
|
43
|
+
}
|
44
|
+
return returnHash
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
|
@@ -1,19 +1,25 @@
|
|
1
1
|
require "vagrant"
|
2
2
|
require 'optparse'
|
3
3
|
require 'tempfile'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
#Require my library for talking to digitalocean
|
7
|
+
require File.expand_path(File.dirname(__FILE__) ) +"/digitalocean_api"
|
4
8
|
|
5
9
|
module VagrantPlugins
|
6
10
|
module CommandVagrantFlow
|
7
11
|
module Command
|
8
12
|
class HostFile < Vagrant.plugin("2", :command)
|
9
|
-
|
13
|
+
@@begin_tag_line = "##BEGIN: ADDED BY NEVERWINTERDP'S VAGRANT-FLOW HOSTFILE COMMAND"
|
14
|
+
@@end_tag_line = "##END: ADDED BY NEVERWINTERDP'S VAGRANT-FLOW HOSTFILE COMMAND"
|
15
|
+
|
10
16
|
# Builtin from Command class
|
11
17
|
# Must override to provide a description
|
12
18
|
def self.synopsis
|
13
19
|
"Sets /etc/hosts so that all your machines can communicate with each other"
|
14
20
|
end
|
15
|
-
|
16
|
-
|
21
|
+
|
22
|
+
|
17
23
|
# Builtin from Command class
|
18
24
|
# Must override to provide core functionality
|
19
25
|
def execute
|
@@ -23,60 +29,86 @@ module VagrantPlugins
|
|
23
29
|
options[:provision_ignore_sentinel] = false
|
24
30
|
options[:nowrite] = false
|
25
31
|
options[:quiet] = false
|
26
|
-
|
27
|
-
|
32
|
+
options[:digitalocean] = false
|
33
|
+
options[:digitalocean_file] = "hostfile_do.yml"
|
34
|
+
|
35
|
+
#Parse option, look up OptionParser documentation
|
28
36
|
opts = OptionParser.new do |o|
|
29
37
|
# o.banner = "Usage: vagrant ansible-inventory [vm-name] [options] [-h]"
|
30
38
|
o.banner = "A NeverWinterDP technology from the Department of Badass.\n\n"+
|
31
39
|
"Usage: vagrant flow hostfile [-hnkq]\n"+
|
32
40
|
"Edits all your VMs /etc/hosts file to be able to find all the machines on your private network"
|
33
41
|
o.separator ""
|
34
|
-
|
42
|
+
|
35
43
|
o.on("-q", "--quiet", "(Optional) Suppress output to STDOUT and STDERR") do |f|
|
36
44
|
options[:quiet] = true
|
37
45
|
end
|
38
|
-
|
46
|
+
|
39
47
|
o.on("-n", "--no-write-hosts", "(Optional) Don't actually write a new hosts file to the guest machine") do |f|
|
40
48
|
options[:nowrite] = true
|
41
49
|
end
|
50
|
+
|
51
|
+
o.on("-d", "--digitalocean", "(Optional) Writes your digital ocean's hostnames and IP addresses to hosts file. Default file is hostfile_do.yml") do |f|
|
52
|
+
options[:digitalocean] = true
|
53
|
+
end
|
54
|
+
|
55
|
+
o.on("-o", "--digitaloceanfile FILE", "(Optional) File to read in for -d option instead of hostfile_do.yml") do |f|
|
56
|
+
options[:digitalocean_file] = f
|
57
|
+
end
|
42
58
|
end
|
43
59
|
argv = parse_options(opts)
|
44
60
|
return if !argv
|
45
61
|
|
46
62
|
|
63
|
+
|
47
64
|
hostinfo=[]
|
48
65
|
#Go through config
|
49
66
|
#Map hostnames to IP's
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
67
|
+
if options[:digitalocean]
|
68
|
+
config = YAML.load_file(options[:digitalocean_file])
|
69
|
+
digitalocean = DigitalOcean_Api.new()
|
70
|
+
hostinfo = digitalocean.getHostNamesAndIps(config[:client_id],config[:api_key])
|
71
|
+
else
|
72
|
+
with_target_vms(argv, :provider => options[:provider]) do |machine|
|
73
|
+
return unless machine.communicate.ready?
|
74
|
+
hostname = machine.config.vm.hostname
|
75
|
+
machine.config.vm.networks.each {|networks|
|
76
|
+
networks.each {|net|
|
77
|
+
if net.is_a?(Hash) and net.has_key?(:ip)
|
78
|
+
hostinfo.push(
|
79
|
+
{
|
80
|
+
:hostname=>hostname,
|
81
|
+
:ip=>net[:ip]
|
82
|
+
})
|
83
|
+
end
|
84
|
+
}
|
62
85
|
}
|
63
|
-
|
86
|
+
end
|
64
87
|
end
|
65
88
|
|
89
|
+
|
90
|
+
#Print out Hostname and IP
|
91
|
+
if not options[:quiet]
|
92
|
+
puts "HOSTS FILE INFO:"
|
93
|
+
hostinfo.each {|x|
|
94
|
+
puts x[:hostname]+": "+x[:ip]
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
66
98
|
#What we're going to add to the end of the guest's hostfile
|
67
99
|
#A combination of IP's and hostnames
|
68
|
-
toconcatenate="\n"+"
|
100
|
+
toconcatenate="\n"+@@begin_tag_line+"\n"
|
69
101
|
hostinfo.each {|x|
|
70
|
-
toconcatenate+=x[:ip]+" "+x[:hostname]+"\n"
|
102
|
+
toconcatenate += x[:ip]+" "+x[:hostname]+"\n"
|
71
103
|
}
|
72
|
-
|
73
|
-
|
104
|
+
toconcatenate += @@end_tag_line+"\n"
|
105
|
+
|
74
106
|
#Read in guest's current hosts file
|
75
107
|
#Append our new entries to it
|
76
108
|
#Write it out onto the guest's hosts file
|
77
109
|
with_target_vms(argv, :provider => options[:provider]) do |machine|
|
78
110
|
return unless machine.communicate.ready?
|
79
|
-
|
111
|
+
|
80
112
|
#This block of code was shamelessly stolen from
|
81
113
|
#https://github.com/smdahlen/vagrant-hostmanager/blob/master/lib/vagrant-hostmanager/hosts_file.rb
|
82
114
|
#Why reinvent the wheel?
|
@@ -87,35 +119,51 @@ module VagrantPlugins
|
|
87
119
|
elsif (machine.communicate.test("test -d $Env:SystemRoot"))
|
88
120
|
realhostfile = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
|
89
121
|
move_cmd = 'mv -force'
|
90
|
-
else
|
122
|
+
else
|
91
123
|
realhostfile = '/etc/hosts'
|
92
124
|
move_cmd = 'mv'
|
93
125
|
end
|
94
|
-
|
126
|
+
|
95
127
|
#Back to my code
|
96
128
|
#Grab Vagrant's temp file location
|
129
|
+
guesthostfilepath_original = @env.tmp_path.join("hosts."+machine.config.vm.hostname+".og")
|
97
130
|
guesthostfilepath = @env.tmp_path.join("hosts."+machine.config.vm.hostname)
|
131
|
+
|
98
132
|
#Download guest's hosts file
|
99
|
-
machine.communicate.download(realhostfile,
|
100
|
-
|
133
|
+
machine.communicate.download(realhostfile, guesthostfilepath_original)
|
134
|
+
|
135
|
+
#Skip everything between ##BEGIN and ##END
|
136
|
+
guesthostfile = File.open(guesthostfilepath, "w")
|
137
|
+
skip = false
|
138
|
+
File.open(guesthostfilepath_original, "r") do |infile|
|
139
|
+
while (line = infile.gets)
|
140
|
+
if line.strip() == @@begin_tag_line
|
141
|
+
skip = true
|
142
|
+
elsif line.strip() == @@end_tag_line
|
143
|
+
skip = false
|
144
|
+
else
|
145
|
+
guesthostfile.write(line) if not skip
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
101
150
|
#Append our hostname/IP info to the end of the hosts file
|
102
|
-
guesthostfile = File.open(guesthostfilepath,"a")
|
103
151
|
guesthostfile.write(toconcatenate)
|
104
152
|
guesthostfile.close()
|
105
|
-
|
106
|
-
if not options[:nowrite]
|
153
|
+
|
154
|
+
if not options[:nowrite]
|
107
155
|
#Upload updated hosts file to guest to temp location
|
108
156
|
machine.communicate.upload(guesthostfile.path, '/tmp/hosts')
|
109
157
|
#Move temp file over on top of hosts file
|
110
|
-
machine.communicate.sudo(move_cmd+" /tmp/hosts "+realhostfile)
|
158
|
+
machine.communicate.sudo(move_cmd+" /tmp/hosts "+realhostfile)
|
111
159
|
end
|
112
160
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
161
|
+
|
162
|
+
|
163
|
+
|
116
164
|
end
|
117
|
-
|
118
|
-
end
|
119
|
-
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
120
168
|
end
|
121
169
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
#Flush stdout immediately
|
2
|
+
$stdout.sync = true
|
3
|
+
|
4
|
+
require "vagrant"
|
5
|
+
require 'optparse'
|
6
|
+
require 'yaml'
|
7
|
+
require 'pty'
|
8
|
+
|
9
|
+
module VagrantPlugins
|
10
|
+
module CommandVagrantFlow
|
11
|
+
module Command
|
12
|
+
class Playbook < Vagrant.plugin("2", :command)
|
13
|
+
|
14
|
+
# Builtin from Command class
|
15
|
+
# Must override to provide a description
|
16
|
+
def self.synopsis
|
17
|
+
"Runs ansible-playbook so you don't have to!"
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# Builtin from Command class
|
22
|
+
# Must override to provide core functionality
|
23
|
+
def execute
|
24
|
+
options = {}
|
25
|
+
options[:destroy_on_error] = true
|
26
|
+
options[:parallel] = false
|
27
|
+
options[:provision_ignore_sentinel] = false
|
28
|
+
options[:configfile] = "flow-playbook.yml"
|
29
|
+
options[:print] = false
|
30
|
+
options[:quiet] = false
|
31
|
+
|
32
|
+
#Parse option, look up OptionParser documentation
|
33
|
+
opts = OptionParser.new do |o|
|
34
|
+
o.banner = "A NeverWinterDP technology from the Department of Badass.\n\n"+
|
35
|
+
"Usage: vagrant flow playbook [-hfpq]\n"+
|
36
|
+
"Reads in config from flow-playbook.yml by default to be able to run ansible-playbook more easily"
|
37
|
+
o.separator ""
|
38
|
+
|
39
|
+
o.on("-f", "--file-playbook FILE", "(Optional) Use a specified playbook config file instead of default (flow-playbook.yml)") do |f|
|
40
|
+
options[:configfile] = f
|
41
|
+
end
|
42
|
+
|
43
|
+
o.on("-p", "--print-only", "(Optional) Don't actually ansible-playbook, but just output what would be run to STDOUT") do |f|
|
44
|
+
options[:print] = true
|
45
|
+
end
|
46
|
+
|
47
|
+
o.on("-q", "--quiet", "(Optional) Suppress output to STDOUT and STDERR") do |f|
|
48
|
+
options[:quiet] = true
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
argv = parse_options(opts)
|
53
|
+
return if !argv
|
54
|
+
|
55
|
+
config={}
|
56
|
+
begin
|
57
|
+
#Load YAML
|
58
|
+
config = YAML.load_file(options[:configfile])
|
59
|
+
rescue
|
60
|
+
#Give warning if no file could be found
|
61
|
+
if not options[:quiet]
|
62
|
+
warn "Could not open file: "+options[:configfile].to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
#Bail out if config is fubar
|
67
|
+
if not config.has_key?(:playbook)
|
68
|
+
if not options[:quiet]
|
69
|
+
warn options[:configfile].to_s+" is missing \":playbook\" key"
|
70
|
+
end
|
71
|
+
return
|
72
|
+
end
|
73
|
+
|
74
|
+
if not config.has_key?(:inventory)
|
75
|
+
if not options[:quiet]
|
76
|
+
warn options[:configfile].to_s+" is missing \":inventory\" key"
|
77
|
+
end
|
78
|
+
return
|
79
|
+
end
|
80
|
+
|
81
|
+
#Build the ansible-playbook command
|
82
|
+
command = "ansible-playbook "
|
83
|
+
if config.has_key?(:pattern)
|
84
|
+
command+= "-l "+config[:pattern]+" "
|
85
|
+
end
|
86
|
+
command+= "-i "+config[:inventory]+" "
|
87
|
+
command+= config[:playbook]
|
88
|
+
|
89
|
+
#If print is specified, only output the command
|
90
|
+
if options[:print]
|
91
|
+
#But only print if the quiet command isn't specified
|
92
|
+
if not options[:quiet]
|
93
|
+
puts command
|
94
|
+
end
|
95
|
+
else
|
96
|
+
|
97
|
+
|
98
|
+
#Run the command
|
99
|
+
#this fancy block of code outputs the output in real time
|
100
|
+
begin
|
101
|
+
PTY.spawn( "#{command}" ) do |stdin, stdout, pid|
|
102
|
+
begin
|
103
|
+
stdin.each { |line|
|
104
|
+
if not options[:quiet]
|
105
|
+
puts line
|
106
|
+
end
|
107
|
+
}
|
108
|
+
#This wait() is required to set the exit code
|
109
|
+
Process.wait(pid)
|
110
|
+
rescue Errno::EIO
|
111
|
+
end
|
112
|
+
end
|
113
|
+
rescue PTY::ChildExited
|
114
|
+
#If there was an error, throw an error ourselves
|
115
|
+
raise Vagrant::Errors::AnsibleFailed
|
116
|
+
end
|
117
|
+
|
118
|
+
#If there was an error, throw an error ourselves
|
119
|
+
raise Vagrant::Errors::AnsibleFailed if not $?.success?
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -19,11 +19,28 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
19
19
|
<%= machine["name"]%>.vm.network :private_network, ip: "<%= machine["ip"]%>", virtualbox__intnet: "<%= @intnetName %>"
|
20
20
|
<%= machine["name"]%>.vm.hostname = "<%= machine["name"]%>"
|
21
21
|
|
22
|
+
#digitalOcean provider
|
23
|
+
<% if machine.has_key?("digitalOceanImage") and @digitalOceanApiKey and @digitalOceanClientId and @sshPrivateKeyPath and @digitalOceanRegion%>
|
24
|
+
<%= machine["name"]%>.vm.synced_folder ".", "/vagrant", disabled: true
|
25
|
+
config.vm.provider :digital_ocean do |provider, override|
|
26
|
+
override.ssh.private_key_path = '<%= @sshPrivateKeyPath %>'
|
27
|
+
provider.client_id = '<%= @digitalOceanClientId %>'
|
28
|
+
provider.api_key = '<%= @digitalOceanApiKey %>'
|
29
|
+
provider.private_networking = 'true'
|
30
|
+
provider.region = '<%= @digitalOceanRegion %>'
|
31
|
+
provider.image = '<%= machine["digitalOceanImage"] %>'
|
32
|
+
end
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
|
36
|
+
#VirtualBox provider
|
22
37
|
config.vm.provider :virtualbox do |vb|
|
23
38
|
vb.name = "<%= machine["name"]%>"
|
24
39
|
# vb.customize ["modifyvm", :id, "--memory", "1024"]
|
25
40
|
# vb.customize ["modifyvm", :id, "--cpus", "2"]
|
26
41
|
end
|
42
|
+
|
27
43
|
end
|
28
44
|
<% end %>
|
29
45
|
end
|
46
|
+
|
data/lib/vagrant-flow/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-flow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Morin
|
@@ -50,12 +50,18 @@ files:
|
|
50
50
|
- NEVERWINTERDP
|
51
51
|
- README.md
|
52
52
|
- Rakefile
|
53
|
+
- VAGRANT-FLOW
|
53
54
|
- create_sample_ansible-inventory_input-file.rb
|
55
|
+
- create_sample_hostfile_digitalocean_input-file.rb
|
54
56
|
- create_sample_multiinit_input-file.rb
|
57
|
+
- create_sample_multiinit_input-file_digitalocean.rb
|
58
|
+
- create_sample_playbook_input-file.rb
|
55
59
|
- lib/vagrant-flow.rb
|
56
60
|
- lib/vagrant-flow/command/ansibleinventory.rb
|
61
|
+
- lib/vagrant-flow/command/digitalocean_api.rb
|
57
62
|
- lib/vagrant-flow/command/hostfile.rb
|
58
63
|
- lib/vagrant-flow/command/multiinit.rb
|
64
|
+
- lib/vagrant-flow/command/playbook.rb
|
59
65
|
- lib/vagrant-flow/command/root.rb
|
60
66
|
- lib/vagrant-flow/plugin.rb
|
61
67
|
- lib/vagrant-flow/templates/multiinit.erb
|