vagrant-orchestrate 0.2.1 → 0.3.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 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