vagrant-soa 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9bad216eb549f706c4703ddce8629bf2bd37630
4
+ data.tar.gz: cde6e442ca52860d4b2ca09db2f50a62d25517dc
5
+ SHA512:
6
+ metadata.gz: f849a15385437ad9e59b00f21dbf9fce34413eb04b38f29567696e048b3a07e18c81757bfba4fe5e5acb9061b865802c107f32d9b70f96a4cac2c5078392afde
7
+ data.tar.gz: 3766e2e26edb30b200257f00941cff9f72d7e19a64161a546db69d0bc37733a08f6e9153f0928377a4ffad767c2552379f6fc874483bea1ca9cf145c46688061
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.rbc
2
+ .bundle
3
+ .config
4
+ .yardoc
5
+ Gemfile.lock
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ rdoc
12
+ spec/reports
13
+ test/tmp
14
+ test/version_tmp
15
+ tmp
16
+ pkg
17
+
18
+ # ignore vagrant directory
19
+ .vagrant
20
+
21
+ # ignore dev files
22
+ .SERVICES
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem "vagrant", github: "mitchellh/vagrant"
7
+ gem "debugger"
8
+ end
9
+
10
+ group :plugins do
11
+ gem 'vagrant-puppet-fact-generator', :git => 'git@github.com:eventbrite/vagrant-puppet-fact-generator.git'
12
+ gem 'vagrant-puppet-module-registry', :git => 'git@github.com:eventbrite/vagrant-puppet-module-registry.git'
13
+ gem 'vagrant-soa', path: '.'
14
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Michael Hahn
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # vagrant-soa
2
+
3
+ A [Vagrant](http://www.vagrantup.com/) plugin to handle our SOA infrastructre within vagrant.
4
+
5
+ ## Installation
6
+
7
+ ``` bash
8
+ vagrant plugin install vagrant-soa
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ This plugin allows you to specify one or more services to run within the VM. By
14
+ "services", we mean github repos that define puppet modules which can then be
15
+ included in the main manifest.
16
+
17
+ This structure allows developers of services to easily distribute services to
18
+ the rest of the team. Any changes to the service will be synced when users
19
+ provision.
20
+
21
+ Services are defined within the ``Vagrantfile``::
22
+
23
+ config.soa.services = {
24
+ 'example_service' => {
25
+ 'puppet_path' => 'services/example_service/puppet',
26
+ 'github_url' => 'git@github.com:eventbrite/vagrant-soa.git',
27
+ 'home_dir' => 'services/example_service',
28
+ 'branch' => 'test_branch',
29
+ },
30
+ }
31
+
32
+ The attributes of the service are optional, with the following defaults:
33
+
34
+ * puppet_path: The location of the puppet module from the root of the service
35
+ repository. If this isn't specified, we'll default to "puppet"
36
+ * github_url: The github url for the service. If this isn't provided, we'll
37
+ fallback to: #{config.soa.github_base}/#{service}.git
38
+ * branch: The specific branch we want to checkout. Defaults to "master".
39
+ * home_dir: The home directory of the service. This is useful if the service
40
+ isn't contained within its own repo.
41
+
42
+ ## Development
43
+
44
+ ``` bash
45
+ $ bundle
46
+ $ bundle exec vagrant up
47
+ ```
48
+
49
+ ## Contributing
50
+
51
+ 1. Create your feature branch (`git checkout -b my-new-feature`)
52
+ 2. Commit your changes (`git commit -am 'Add some feature'`)
53
+ 3. Push to the branch (`git push origin my-new-feature`)
54
+ 4. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/Vagrantfile ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+ # vi: set ft=ruby :
4
+
5
+ Vagrant.configure('2') do |config|
6
+ config.vm.box = 'precise64'
7
+ config.vm.box_url = 'http://files.vagrantup.com/precise64.box'
8
+
9
+ config.soa.services = {
10
+ 'example_service' => {
11
+ 'puppet_path' => 'services/example_service/puppet',
12
+ 'github_url' => 'git@github.com:eventbrite/vagrant-soa.git'
13
+ },
14
+ }
15
+
16
+ config.vm.provision 'puppet' do |puppet|
17
+ puppet.manifests_path = 'manifests'
18
+ puppet.manifest_file = 'init.pp'
19
+ puppet.module_path = config.puppet_module_registry.get_puppet_module_paths()
20
+ end
21
+
22
+ end
@@ -0,0 +1,196 @@
1
+ require_relative '../errors'
2
+
3
+ module VagrantPlugins
4
+ module Soa
5
+ class Action
6
+ class InstallServices
7
+
8
+ def initialize(app, env)
9
+ @app = app
10
+ @env = env
11
+ @soa = env[:machine].config.soa
12
+ @puppet_fact_generator = env[:machine].config.puppet_fact_generator
13
+ @puppet_module_registry = env[:machine].config.puppet_module_registry
14
+ @git = get_local_git()
15
+ # we use the local_data_path of the machine since vagrant ensures it
16
+ # exists as well as mounts it to the VM for us.
17
+ @install_dir = env[:machine].env.local_data_path.join('services')
18
+ # this "/vagrant" dir is hard coded in vagrant as well:
19
+ # https://github.com/mitchellh/vagrant/blob/master/plugins/kernel_v2/config/vm.rb#L385-L389
20
+ @vagrant_install_dir = '/vagrant/.vagrant/services'
21
+ end
22
+
23
+ # Get the proper git to clone the service repos.
24
+ def get_local_git
25
+ git = `which git`.chomp
26
+ if git == ""
27
+ raise Soa::Errors::GitRequired.new
28
+ else
29
+ return git
30
+ end
31
+ end
32
+
33
+ def update_repo(service, target_branch, pwd, chdir_on_success=true)
34
+ # make sure the branch is up to date
35
+ updated = system "#{@git} pull --rebase"
36
+ if not updated
37
+ # pop back to the original directory
38
+ Dir.chdir pwd
39
+ raise Soa::Errors::UpdatingRepoFailed,
40
+ target_branch: target_branch,
41
+ service: service
42
+ else
43
+ # pop back to the original directory
44
+ if chdir_on_success
45
+ Dir.chdir pwd
46
+ end
47
+ @env[:ui].success(
48
+ "Successfully updated branch: #{target_branch} for #{service}"
49
+ )
50
+ end
51
+ end
52
+
53
+ # When installing a service we have to clone the service repository.
54
+ # Ideally, we would manage these modules with librarian-puppet and the
55
+ # Puppetfile, but because services depend on files that aren't
56
+ # contained within their puppet module (ie. requirements.txt or uwsgi
57
+ # handlers etc.), cloning the repo is the next best solution.
58
+ def clone_service_repo(service, config)
59
+ target_directory = File.join @install_dir, service
60
+
61
+ # make sure the repo is checked out
62
+ if File.directory? target_directory
63
+ @env[:ui].info "Service: #{service} is already checked out"
64
+ else
65
+ if not config['github_url'] || @soa.github_base
66
+ raise Soa::Errors::NoGithubUrlProvided,
67
+ service: service
68
+ end
69
+
70
+ github_target = config['github_url'] ? config['github_url'] : "#{@soa.github_base}/#{service}.git"
71
+ @env[:ui].info(
72
+ "Cloning service: #{service} (#{github_target}) to target directory:"\
73
+ " #{target_directory}"
74
+ )
75
+ success = system "#{@git} clone --recurse-submodules #{github_target} #{target_directory}"
76
+ if not success
77
+ raise Soa::Errors::CloningServiceFailed,
78
+ service: service
79
+ else
80
+ @env[:ui].success "Successfully checked out service: #{service}"
81
+ end
82
+ end
83
+
84
+ # move to the target_directory so we can examine it with git
85
+ pwd = Dir.pwd
86
+ Dir.chdir(target_directory)
87
+ update_repo = true
88
+
89
+ # don't attempt to auto-update if we've found any changes in the repo we
90
+ # already have checked out (stolen from boxen)
91
+ clean = `#{@git} status --porcelain`.empty?
92
+ current_branch = `#{@git} rev-parse --abbrev-ref HEAD`.chomp
93
+ fast_forwardable = `#{@git} rev-list --count origin/master..master`.chomp == '0'
94
+ if current_branch.empty?
95
+ ref = `#{@git} log -1 --pretty=format:%h`
96
+ @env[:ui].warn "#{service} not currently on any branch (ref: #{ref}), won't auto-update!"
97
+ update_repo = false
98
+ elsif !fast_forwardable
99
+ @env[:ui].warn "#{service}'s master branch is out of sync, won't auto-update!"
100
+ update_repo = false
101
+ elsif !clean
102
+ @env[:ui].warn "#{service} has a dirty tree, won't auto-update!"
103
+ update_repo = false
104
+ end
105
+
106
+ # make sure we're on the correct branch
107
+ target_branch = config.fetch('branch', 'master')
108
+ if !update_repo
109
+ # pop back to the original directory
110
+ Dir.chdir(pwd)
111
+ return target_directory
112
+ elsif target_branch != current_branch
113
+ # we have to pull first to ensure that we have all available branches
114
+ update_repo(service, current_branch, pwd, false)
115
+ checkout_target = system("#{@git} checkout #{target_branch}")
116
+ if not checkout_target
117
+ # pop back to the original directory
118
+ Dir.chdir(pwd)
119
+ raise Soa::Errors::BranchCheckoutFailed,
120
+ target_branch: target_branch,
121
+ service: service
122
+ else
123
+ @env[:ui].success(
124
+ "Successfully checked out branch: #{target_branch}"\
125
+ " for service #{service}"
126
+ )
127
+ end
128
+ end
129
+
130
+ if clean
131
+ update_repo(service, target_branch, pwd)
132
+ end
133
+ return target_directory
134
+ end
135
+
136
+ # When services are installed they can specify a 'home_dir' in their
137
+ # vagrant config. This needs to be a path that exists within the VM and
138
+ # points to their desired home directory.
139
+ #
140
+ # These custom facts will be of the form: "#{service}_home_dir"
141
+ def register_service_home_fact(service, config)
142
+ home_dir = config.fetch('home_dir', nil)
143
+ # not sure if there is a better way to do this in ruby, we don't want a
144
+ # trailing slash if "home_dir" is empty
145
+ if home_dir
146
+ full_path = File.join(
147
+ @vagrant_install_dir,
148
+ service,
149
+ home_dir
150
+ )
151
+ else
152
+ full_path = File.join(
153
+ @vagrant_install_dir,
154
+ service
155
+ )
156
+ end
157
+ if File.directory?(full_path)
158
+ @env[:ui].warn "Invalid home_dir passed for service:"\
159
+ " #{service}, home_dir: #{full_path}"
160
+ else
161
+ @puppet_fact_generator.add_fact("#{service}_home_dir", full_path)
162
+ end
163
+ end
164
+
165
+ # To install a service we clone the service repo and add the puppet
166
+ # path to @puppet_module_registry.puppet_module_paths.
167
+ def install_service(service, config)
168
+ target_directory = clone_service_repo(service, config)
169
+ puppet_path = config.fetch('puppet_path', 'puppet')
170
+ full_path = File.join(target_directory, puppet_path)
171
+ register_service_home_fact(service, config)
172
+ @puppet_module_registry.register_module_path(service, full_path)
173
+ end
174
+
175
+ # If any services are specified, install them
176
+ def install_services()
177
+ if @soa.services
178
+ @soa.services.each_pair do |service, config|
179
+ install_service(service, config)
180
+ end
181
+ end
182
+ end
183
+
184
+ def call(env)
185
+ # determine if provision is enabled, if we provided the
186
+ # "--no-provision" flag this would be false. if it isn't present, we
187
+ # should consider provision enabled
188
+ provision_enabled = env.has_key?(:provision_enabled) ? env[:provision_enabled] : true
189
+ install_services() if provision_enabled
190
+ @app.call(env)
191
+ end
192
+
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,36 @@
1
+ module VagrantPlugins
2
+ module Soa
3
+ class Config < Vagrant.plugin(2, :config)
4
+ attr_accessor :services
5
+ attr_accessor :github_base
6
+
7
+ def initialize
8
+ @services = UNSET_VALUE
9
+ @github_base = UNSET_VALUE
10
+ end
11
+
12
+ def finalize!
13
+ @services = nil if @services == UNSET_VALUE
14
+ @github_base = nil if @github_base == UNSET_VALUE
15
+ end
16
+
17
+ def validate(machine)
18
+ errors = []
19
+
20
+ if @services
21
+ if not @services.kind_of?(Hash)
22
+ errors << '`services` must be a hash of form service => {service config hash}'
23
+ end
24
+ @services.each_pair do |service, config|
25
+ if not config.kind_of?(Hash)
26
+ errors << "Invalid configuration for #{service}, config must be a hash, not #{config}"
27
+ end
28
+ end
29
+ end
30
+
31
+ return { 'soa' => errors }
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ module VagrantPlugins
2
+ module Soa
3
+ module Errors
4
+
5
+ class GitRequired < Vagrant::Errors::VagrantError
6
+ error_key('git_required')
7
+ end
8
+
9
+ class UpdatingRepoFailed < Vagrant::Errors::VagrantError
10
+ error_key('git_update_failed')
11
+ end
12
+
13
+ class CloningServiceFailed < Vagrant::Errors::VagrantError
14
+ error_key('git_clone_failed')
15
+ end
16
+
17
+ class BranchCheckoutFailed < Vagrant::Errors::VagrantError
18
+ error_key('git_checkout_failed')
19
+ end
20
+
21
+ class NoGithubUrlProvided < Vagrant::Errors::VagrantError
22
+ error_key('missing_github_url')
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ abort 'vagrant-soa must be loaded in a Vagrant environment.'
5
+ end
6
+
7
+ begin
8
+ require 'vagrant-puppet-module-registry'
9
+ rescue LoadError
10
+ abort 'vagrant-soa depends on the `vagrant-puppet-module-registry` plugin.'
11
+ end
12
+
13
+ # Add our custom translations to the load path
14
+ I18n.load_path << File.expand_path("../../../locales/en.yml", __FILE__)
15
+
16
+ module VagrantPlugins
17
+ module Soa
18
+ class Plugin < Vagrant.plugin('2')
19
+ name 'vagrant-soa'
20
+ description <<-DESC
21
+ A Vagrant plugin to manage vagrant SOA infrastructure.
22
+ DESC
23
+
24
+ # define configs
25
+ config 'soa' do
26
+ require_relative 'config'
27
+ Config
28
+ end
29
+
30
+ # define hooks
31
+ action_hook 'install_services' do |hook|
32
+ require_relative 'actions/install_services'
33
+ # we need to install services before we AddModuleFacts
34
+ hook.before VagrantPlugins::PuppetModuleRegistry::Action::AddModuleFacts, Action::InstallServices
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module Soa
3
+ VERSION = "0.3.0"
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ require "vagrant-soa/version"
2
+ require "vagrant-soa/plugin"
data/locales/en.yml ADDED
@@ -0,0 +1,15 @@
1
+ en:
2
+ vagrant:
3
+ errors:
4
+ git_required: |-
5
+ Please install `git` before continuing.
6
+ git_update_failed: |-
7
+ Error updating branch: '%{target_branch}' for '%{service}'.
8
+ git_clone_faield: |-
9
+ Error cloning service: '%{service}'.
10
+ git_checkout_failed: |-
11
+ Error checking out branch: '%{target_branch}' for '%{service}'.
12
+ missing_github_url: |-
13
+ No `github_url` specified for service: '%{service}'. Either
14
+ specify the `github_url` or set `cofing.soa.github_base` to
15
+ the organization's github.
data/manifests/init.pp ADDED
@@ -0,0 +1,6 @@
1
+ class dev {
2
+ notify { 'Development provision!':}
3
+ include example_service
4
+ }
5
+
6
+ include dev
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ class example_service {
2
+ notify { 'including example service': }
3
+ }
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vagrant-soa/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "vagrant-soa"
8
+ spec.version = VagrantPlugins::Soa::VERSION
9
+ spec.authors = ["Michael Hahn"]
10
+ spec.email = ["mhahn@eventbrite.com"]
11
+ spec.description = %q{Vagrant plugin to manage vagrant SOA infrastructure.}
12
+ spec.summary = spec.description
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-soa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Hahn
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Vagrant plugin to manage vagrant SOA infrastructure.
42
+ email:
43
+ - mhahn@eventbrite.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - Vagrantfile
54
+ - lib/vagrant-soa.rb
55
+ - lib/vagrant-soa/actions/install_services.rb
56
+ - lib/vagrant-soa/config.rb
57
+ - lib/vagrant-soa/errors.rb
58
+ - lib/vagrant-soa/plugin.rb
59
+ - lib/vagrant-soa/version.rb
60
+ - locales/en.yml
61
+ - manifests/init.pp
62
+ - pkg/vagrant-soa-0.1.0.gem
63
+ - pkg/vagrant-soa-0.2.0.gem
64
+ - pkg/vagrant-soa-0.2.1.gem
65
+ - pkg/vagrant-soa-0.3.0.gem
66
+ - services/example_service/puppet/example_service/manifests/init.pp
67
+ - vagrant-soa.gemspec
68
+ homepage: ''
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.0.3
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Vagrant plugin to manage vagrant SOA infrastructure.
92
+ test_files: []
93
+ has_rdoc: