vagrant-orchestrate 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9272488db149ae92a448f1338dc9fbc34827651a
4
- data.tar.gz: a55eb060f9ed8a64a9e836906418cf7370b79188
3
+ metadata.gz: 7b77cd8446da22ec260eeafa76cfeca730ead095
4
+ data.tar.gz: ea87fb3abb6f6431d4e059a0e7712dce4bb567c4
5
5
  SHA512:
6
- metadata.gz: ed3c4b84dcadbf1c253d9a6e5c961e6130700e3a5f91e14cfdb2b672066f7ea340aec113a5f9c88b25b19d948a0aa1dbc014f3406be288b8967496a01167c33c
7
- data.tar.gz: 487e3748e44e7b5610fab054f6e4db4e587e0d07d0b03b49cc8aaf74b079cc77852f7eb167f025faa4d9432710ca9b2397b5a739a2caf58af3e414f25d526294
6
+ metadata.gz: 13bc391116a4a4a528182801220960e560a563b510fde0949073d0320f9424af19507f6d99d2b0ada3875cc18c0db6d6bc774728faa853903b8c8d20745d5532
7
+ data.tar.gz: 31cba2e18c9f6262b564b671bdb77067398585089530057e01884e57f6a207a6aedb2557464f3c70a6cdf1ee032d3aadebaae8af6fed2235cb5a3c71e24325d2
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ mkmf.log
16
16
  /.vagrant/
17
17
  Vagrantfile
18
18
  .DS_Store
19
+ servers.json
data/.rubocop.yml CHANGED
@@ -16,3 +16,6 @@ StringLiterals:
16
16
 
17
17
  Style/FileName:
18
18
  Enabled: false
19
+
20
+ Metrics/AbcSize:
21
+ Max: 100
data/README.md CHANGED
@@ -83,8 +83,9 @@ line with `--ssh-username` and `--ssh-private-key-path`. The first line of the f
83
83
  managed servers that the `push` command will operate on.
84
84
 
85
85
  ```ruby
86
- managed_servers = %w( myserver1.mydomain.com myserver2.mydomain.com )
86
+ managed_servers = %w( myserver1.mydomain.com myserver2.mydomain.com )
87
87
  ```
88
+ #### Windows
88
89
 
89
90
  This works for Windows managed servers using WinRM as well
90
91
 
@@ -101,12 +102,98 @@ This works for Windows managed servers using WinRM as well
101
102
  config.winrm.transport = :sspinegotiate
102
103
  ```
103
104
 
105
+ #### Plugins
106
+
104
107
  This also supports a self-contained way to install plugins, just list them in the required_plugins section
105
108
 
106
109
  ```ruby
107
110
  required_plugins = %w( vagrant-managed-servers vagrant-hostsupdater )
108
111
  ```
109
112
 
113
+ #### Working with multiple environments
114
+ It is a very common pattern in software development to have separate environments - e.g. dev, test, and prod.
115
+ Vagrant Orchestrate offers a way to manage multiple environments using a combination of a single servers.json
116
+ file and the name of the current git branch to know which the current environment is.
117
+
118
+ ```javascript
119
+ # servers.json
120
+ {
121
+ "environments": {
122
+ "dev": {
123
+ "servers": [
124
+ "dev.myapp.mydomain.com"
125
+ ]
126
+ },
127
+ "test": {
128
+ "servers": [
129
+ "test1.myapp.mydomain.com",
130
+ "test2.myapp.mydomain.com"
131
+ ]
132
+ },
133
+ "prod": {
134
+ "servers": [
135
+ "prod1.myapp.mydomain.com",
136
+ "prod2.myapp.mydomain.com",
137
+ "prod3.myapp.mydomain.com"
138
+ ]
139
+ }
140
+ }
141
+ }
142
+ ```
143
+
144
+ Add the following line to the top of your `Vagrantfile`
145
+
146
+ ```ruby
147
+ managed_servers = VagrantPlugins::Orchestrate::Plugin.load_servers_for_branch
148
+ ```
149
+
150
+ If you create git branches named `dev`, `test`, and `prod`, your vagrantfile will become environment aware and
151
+ you'll only be able to see the servers appropriate for that environment.
152
+
153
+ ```
154
+ $ git branch
155
+ * dev
156
+ test
157
+ prod
158
+ $ vagrant status
159
+ Current machine states:
160
+
161
+ local not created (virtualbox)
162
+ dev.myapp.mydomain.com not created (managed)
163
+
164
+ $ git checkout test
165
+ Switched to branch 'test'
166
+ $ vagrant status
167
+ Current machine states:
168
+
169
+ local not created (virtualbox)
170
+ test1.myapp.mydomain.com not created (managed)
171
+ test2.myapp.mydomain.com not created (managed)
172
+
173
+ $ git checkout prod
174
+ Switched to branch 'prod'
175
+ $ vagrant status
176
+ Current machine states:
177
+
178
+ local not created (virtualbox)
179
+ prod1.myapp.mydomain.com not created (managed)
180
+ prod2.myapp.mydomain.com not created (managed)
181
+ prod3.myapp.mydomain.com not created (managed)
182
+ ```
183
+
184
+ Any branch that doesn't have a matching environment in the servers.json file will
185
+ not list any managed servers.
186
+
187
+ ```
188
+ $ git checkout -b my_feature_branch
189
+ Switched to a new branch 'my_feature_branch'
190
+ $ vagrant status
191
+ Current machine states:
192
+
193
+ local not created (virtualbox)
194
+ ```
195
+ #### Puppet
196
+
110
197
  Experimental puppet templating support is available as well with the `--puppet` flag and associated options
111
198
 
112
199
  ```ruby
@@ -150,7 +237,7 @@ You can run vagrant with increased verbosity if you run into problems
150
237
  $ vagrant orchestrate push --debug
151
238
 
152
239
  ## Filtering managed commands
153
- 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.
240
+ 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.
154
241
 
155
242
  ```ruby
156
243
  config.orchestrate.filter_managed_commands = true
@@ -15,12 +15,13 @@ module VagrantPlugins
15
15
  DEFAULT_SSH_PRIVATE_KEY_PATH = "{{YOUR_SSH_PRIVATE_KEY_PATH}}"
16
16
  DEFAULT_PLUGINS = ["vagrant-managed-servers"]
17
17
 
18
- # rubocop:disable Metrics/AbcSize, MethodLength, Metrics/CyclomaticComplexity
18
+ # rubocop:disable Metrics/AbcSize, MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
19
19
  def execute
20
20
  options = {}
21
21
 
22
22
  options[:provisioners] = []
23
23
  options[:servers] = []
24
+ options[:environments] = []
24
25
  options[:plugins] = DEFAULT_PLUGINS
25
26
  options[:puppet_librarian_puppet] = true
26
27
  options[:puppet_hiera] = true
@@ -90,10 +91,14 @@ module VagrantPlugins
90
91
  options[:plugins] += p
91
92
  end
92
93
 
93
- o.on("--servers x,y,z", Array, "A comma separated list of servers hostnames or IPs to deploy to") do |list|
94
+ o.on("--servers x,y,z", Array, "A CSV list of FQDNs to target managed servers") do |list|
94
95
  options[:servers] = list
95
96
  end
96
97
 
98
+ o.on("--environments x,y,z", Array, "A CSV list of environments. Takes precedence over --servers") do |list|
99
+ options[:environments] = list
100
+ end
101
+
97
102
  o.on("-f", "--force", "Force overwriting of files") do
98
103
  options[:force] = true
99
104
  end
@@ -102,29 +107,8 @@ module VagrantPlugins
102
107
  argv = parse_options(opts)
103
108
  return unless argv
104
109
 
105
- if options[:provisioners].include? "puppet"
106
- FileUtils.mkdir_p(File.join(@env.cwd, "puppet"))
107
- if options[:puppet_librarian_puppet]
108
- contents = TemplateRenderer.render(Orchestrate.source_root.join("templates/puppet/Puppetfile"))
109
- write_file File.join("puppet", "Puppetfile"), contents, options
110
- FileUtils.mkdir_p(File.join(@env.cwd, "puppet", "modules"))
111
- write_file(File.join(@env.cwd, "puppet", "modules", ".gitignore"), "*", options)
112
- options[:plugins] << "vagrant-librarian-puppet"
113
- end
114
-
115
- if options[:puppet_hiera]
116
- contents = TemplateRenderer.render(Orchestrate.source_root.join("templates/puppet/hiera.yaml"))
117
- write_file(File.join("puppet", "hiera.yaml"), contents, options)
118
- FileUtils.mkdir_p(File.join(@env.cwd, "puppet", "hieradata"))
119
- contents = TemplateRenderer.render(Orchestrate.source_root.join("templates/puppet/hiera/common.yaml"))
120
- write_file(File.join(@env.cwd, "puppet", "hieradata", "common.yaml"), contents, options)
121
- end
122
-
123
- FileUtils.mkdir_p(File.join(@env.cwd, "puppet", "manifests"))
124
- write_file(File.join(@env.cwd, "puppet", "manifests", "default.pp"),
125
- "# Your puppet code goes here",
126
- options)
127
- end
110
+ init_puppet options
111
+ init_environments options
128
112
 
129
113
  options[:shell_paths] ||= options[:shell_inline] ? [] : [DEFAULT_SHELL_PATH]
130
114
  options[:winrm_username] ||= DEFAULT_WINRM_USERNAME
@@ -146,6 +130,7 @@ module VagrantPlugins
146
130
  ssh_password: options[:ssh_password],
147
131
  ssh_private_key_path: options[:ssh_private_key_path],
148
132
  servers: options[:servers],
133
+ environments: options[:environments],
149
134
  plugins: options[:plugins]
150
135
  )
151
136
  write_file("Vagrantfile", contents, options)
@@ -156,10 +141,51 @@ module VagrantPlugins
156
141
  # Success, exit status 0
157
142
  0
158
143
  end
159
- # rubocop:enable Metrics/AbcSize, MethodLength, Metrics/CyclomaticComplexity
144
+ # rubocop:enable Metrics/AbcSize, MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
160
145
 
161
146
  private
162
147
 
148
+ def init_puppet(options)
149
+ return unless options[:provisioners].include? "puppet"
150
+
151
+ FileUtils.mkdir_p(File.join(@env.cwd, "puppet"))
152
+ if options[:puppet_librarian_puppet]
153
+ contents = TemplateRenderer.render(Orchestrate.source_root.join("templates/puppet/Puppetfile"))
154
+ write_file File.join("puppet", "Puppetfile"), contents, options
155
+ FileUtils.mkdir_p(File.join(@env.cwd, "puppet", "modules"))
156
+ write_file(File.join(@env.cwd, "puppet", "modules", ".gitignore"), "*", options)
157
+ options[:plugins] << "vagrant-librarian-puppet"
158
+ end
159
+
160
+ if options[:puppet_hiera]
161
+ contents = TemplateRenderer.render(Orchestrate.source_root.join("templates/puppet/hiera.yaml"))
162
+ write_file(File.join("puppet", "hiera.yaml"), contents, options)
163
+ FileUtils.mkdir_p(File.join(@env.cwd, "puppet", "hieradata"))
164
+ contents = TemplateRenderer.render(Orchestrate.source_root.join("templates/puppet/hiera/common.yaml"))
165
+ write_file(File.join(@env.cwd, "puppet", "hieradata", "common.yaml"), contents, options)
166
+ end
167
+
168
+ FileUtils.mkdir_p(File.join(@env.cwd, "puppet", "manifests"))
169
+ write_file(File.join(@env.cwd, "puppet", "manifests", "default.pp"),
170
+ "# Your puppet code goes here", options)
171
+ end
172
+
173
+ def init_environments(options)
174
+ environments = options[:environments]
175
+ return unless environments.any?
176
+
177
+ contents = TemplateRenderer.render(Orchestrate.source_root.join("templates/environment/servers.json"),
178
+ environments: environments)
179
+ write_file("servers.json", contents, options)
180
+ @env.ui.info("You've created an environment aware configuration.")
181
+ @env.ui.info("To complete the process you need to do the following: ")
182
+ @env.ui.info(" 1. Add the target servers to servers.json")
183
+ @env.ui.info(" 2. Create a git branch for each environment")
184
+ environments.each do |env|
185
+ @env.ui.info(" git branch #{env}")
186
+ end
187
+ end
188
+
163
189
  def write_file(filename, contents, options)
164
190
  save_path = Pathname.new(filename).expand_path(@env.cwd)
165
191
  save_path.delete if save_path.exist? && options[:force]
@@ -76,11 +76,53 @@ module VagrantPlugins
76
76
 
77
77
  # Set the logging level on all "vagrant" namespaced
78
78
  # logs as long as we have a valid level.
79
- if level
80
- Log4r::Logger.new("vagrant_orchestrate").tap do |logger|
81
- logger.outputters = Log4r::Outputter.stderr
82
- logger.level = level
79
+ @logger = Log4r::Logger.new("vagrant_orchestrate").tap do |logger|
80
+ logger.outputters = Log4r::Outputter.stderr
81
+ logger.level = level || 6
82
+ end
83
+ end
84
+
85
+ def self.read_git_branch
86
+ @logger.debug("Reading git branch")
87
+ if ENV["GIT_BRANCH"]
88
+ git_branch = ENV["GIT_BRANCH"]
89
+ @logger.debug("Read git branch #{git_branch} from GIT_BRANCH environment variable")
90
+ else
91
+ command = "git rev-parse --abbrev-ref HEAD"
92
+ git_branch = `#{command}`.chomp
93
+ if git_branch.include? "fatal"
94
+ @logger.error("Unable to determine git branch `#{command}`. Is this a git repo?")
95
+ git_branch = nil
96
+ else
97
+ @logger.debug("Read git branch #{git_branch} using `#{command}`")
98
+ end
99
+ end
100
+ git_branch
101
+ end
102
+
103
+ def self.load_servers_for_branch
104
+ setup_logging
105
+
106
+ git_branch = read_git_branch
107
+ return [] if git_branch.nil?
108
+
109
+ begin
110
+ fail "servers.json not found" unless File.exist?("servers.json")
111
+ @logger.debug("Reading servers.json")
112
+ contents = IO.read("servers.json")
113
+ @logger.debug("Read servers.json:\n: #{contents}")
114
+
115
+ environments = JSON.parse(contents)["environments"]
116
+ if environments.key? git_branch
117
+ return environments[git_branch]["servers"]
118
+ else
119
+ @logger.info("No environment found for #{git_branch}, no servers loaded.")
120
+ return []
83
121
  end
122
+ rescue StandardError => ex
123
+ # Don't break the user's whole vagrantfile if we can't load the environment
124
+ @logger.error(ex.message)
125
+ return []
84
126
  end
85
127
  end
86
128
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Orchestrate
3
- VERSION = "0.2.1"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
@@ -277,6 +277,24 @@ describe VagrantPlugins::Orchestrate::Command::Init do
277
277
  end
278
278
  end
279
279
 
280
+ context "environments" do
281
+ let(:argv) { ["--environments", "a,b,c"] }
282
+ describe "vagrantfile" do
283
+ it "should contain the loading code" do
284
+ subject.execute
285
+ vagrantfile = File.readlines(File.join(iso_env.cwd, "Vagrantfile")).join
286
+ expect(vagrantfile).to include("managed_servers = VagrantPlugins::Orchestrate::Plugin.load_servers_for_branch")
287
+ end
288
+ end
289
+
290
+ describe "servers.json" do
291
+ it "should exist in the target directory" do
292
+ subject.execute
293
+ expect(Dir.entries(iso_env.cwd)).to include("servers.json")
294
+ end
295
+ end
296
+ end
297
+
280
298
  context "box" do
281
299
  describe "dummy.box" do
282
300
  it "winds up in the target directory" do
@@ -0,0 +1,11 @@
1
+ {
2
+ "environments": {
3
+ <% environments.each_with_index do |environment, index| -%>
4
+ "<%= environment %>": {
5
+ "servers": [
6
+
7
+ ]
8
+ }<% if index < environments.length - 1 -%>,<% end -%>
9
+ <% end -%>
10
+ }
11
+ }
@@ -1,4 +1,8 @@
1
+ <% if environments.any? -%>
2
+ managed_servers = VagrantPlugins::Orchestrate::Plugin.load_servers_for_branch
3
+ <% else -%>
1
4
  managed_servers = %w( <% servers.each do |s| -%><%= s %> <% end -%>)
5
+ <% end -%>
2
6
 
3
7
  <% if plugins.any? -%>
4
8
  required_plugins = %w( <% plugins.each do |p| -%><%= p %> <% end -%>)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-orchestrate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Baldauf
@@ -93,6 +93,7 @@ files:
93
93
  - spec/spec_helper.rb
94
94
  - spec/vagrant-orchestrate/command/init_spec.rb
95
95
  - spec/vagrant-orchestrate/command/root_spec.rb
96
+ - templates/environment/servers.json.erb
96
97
  - templates/puppet/Puppetfile.erb
97
98
  - templates/puppet/hiera.yaml.erb
98
99
  - templates/puppet/hiera/common.yaml.erb