infochimps-guard-chef 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Dreamr OKelly
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ = Guard::Chef
2
+
3
+ Chef guard allows to automatically & intelligently update roles, cookbooks, and databags for chef.
4
+
5
+ - Compatible with Bundler 1.0.x
6
+ - Tested on Ruby 1.8.6, 1.8.7 & 1.9.2.
7
+
8
+ == Install
9
+
10
+ Please be sure to have {Guard}[https://github.com/guard/guard] installed before continue.
11
+
12
+ Install the gem:
13
+
14
+ gem install guard-chef
15
+
16
+ Add it to your Gemfile (inside test group):
17
+
18
+ gem 'guard-chef'
19
+
20
+ Add guard definition to your Guardfile by running this command:
21
+
22
+ guard init chef
23
+
24
+ == Usage
25
+
26
+ Please read {Guard usage doc}[https://github.com/guard/guard#readme]
27
+
28
+ == Guardfile
29
+
30
+ Bundler guard can be really be adapted to all kind of projects.
31
+ Advice: place Bundler guard before other is recommended.
32
+
33
+ === Standard
34
+
35
+ group 'backend' do
36
+
37
+ guard 'chef' do
38
+ watch(%r{^cookbooks/(.+)/})
39
+ watch(%r{^roles/(.+).rb})
40
+ watch(%r{^data_bags/(.+)/})
41
+ end
42
+ end
43
+
44
+ == Options
45
+
46
+ Nothing yet!
47
+
48
+ Please read {Guard doc}[https://github.com/guard/guard#readme] for more info about Guardfile DSL.
49
+
50
+ == Development
51
+
52
+ - Source hosted at {GitHub}[https://github.com/dreamr/guard-chef]
53
+ - Report issues/Questions/Feature requests on {GitHub Issues}[https://github.com/dreamr/guard-chef/issues]
54
+
55
+ Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change
56
+ you make.
57
+
58
+ == Authors
59
+
60
+ {Dreamr OKelly}[https://github.com/dreamr]
@@ -0,0 +1,109 @@
1
+ require 'guard'
2
+ require 'guard/guard'
3
+
4
+ module Guard
5
+ class Chef < Guard
6
+
7
+ require 'guard/chef/base'
8
+ Dir[File.expand_path('../chef/*_job.rb', __FILE__)].each {|f| require f}
9
+
10
+ def initialize(watchers=[], options={})
11
+ super
12
+ @base_dir = ::File.expand_path('../../../', __FILE__)
13
+ # init stuff here, thx!
14
+ end
15
+
16
+ # =================
17
+ # = Guard methods =
18
+ # =================
19
+
20
+ # If one of those methods raise an exception, the Guard::GuardName instance
21
+ # will be removed from the active guards.
22
+
23
+ # Called once when Guard starts
24
+ # Please override initialize method to init stuff
25
+ def start
26
+ true
27
+ end
28
+
29
+ # Called on Ctrl-C signal (when Guard quits)
30
+ def stop
31
+ true
32
+ end
33
+
34
+ # Called on Ctrl-Z signal
35
+ # This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
36
+ def reload
37
+ true
38
+ end
39
+
40
+ # Called on Ctrl-/ signal
41
+ # This method should be principally used for long action like running all specs/tests/...
42
+ def run_all
43
+ true
44
+ end
45
+
46
+ # Called on file modifications and additions
47
+ def run_on_changes(paths)
48
+ paths.each do |path|
49
+ unless updated?(path)
50
+ return false
51
+ end
52
+ end
53
+ true
54
+ end
55
+
56
+ # warn a user that we don't do anything to handle deleted files.
57
+ # does not call super, so guard action isn't triggered
58
+ def run_on_removals(paths)
59
+ paths.each do |path|
60
+ warn "file #{path} removed -- it's up to you to remove it from the server if desired"
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def updated?(path)
67
+ target = perform(path) or return false
68
+ target.update
69
+ true
70
+ end
71
+
72
+ # cookbooks is last because it is most likely to be in a confounding container dir
73
+ CHEF_OBJECT_RE = %r{.*(roles|data_?bags|environments|cookbooks)/([^/]+)}
74
+
75
+ # finds
76
+ # site-cookbooks/flume/recipes/default.rb # => ["cookbooks", "flume" ]
77
+ # alices-cookbooks/cookbooks/bob/templates/default/charlie.rb # => ["cookbooks", "bob" ]
78
+ def split_path(path)
79
+ m = CHEF_OBJECT_RE.match(path)
80
+ unless m
81
+ warn "Skipping '#{path}' -- it doesn't look like '*cookbooks/**/*', '*roles/*.{rb,json}', '*environments/*.{rb,json}' or '*data_bags/*.{rb,json}'"
82
+ return
83
+ else
84
+ parent_seg, child_seg = m.captures
85
+ child_seg.gsub!(/\.(rb|json)$/, "")
86
+ extension = $1
87
+ [parent_seg, child_seg, extension]
88
+ end
89
+ end
90
+
91
+ def jobklass_for(parent_seg)
92
+ case parent_seg
93
+ when /cookbooks/ then CookbookJob
94
+ when /roles/ then RoleJob
95
+ when /data_?bags/ then DataBagJob
96
+ when /environments/ then EnvironmentJob
97
+ else nil
98
+ end
99
+ end
100
+
101
+ def perform(path)
102
+ parent_seg, target_name, extension = split_path(path)
103
+ jobklass = jobklass_for(parent_seg)
104
+ return unless parent_seg && target_name && jobklass
105
+ return unless jobklass.accepts?(path, extension)
106
+ jobklass.new(path, target_name)
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,27 @@
1
+ class Guard::Chef::Base
2
+ attr_reader :target, :name
3
+
4
+ def initialize(target, name)
5
+ @target, @name = target, name
6
+ end
7
+
8
+ def self.accepts?(path, extension)
9
+ true
10
+ end
11
+
12
+ def kind
13
+ self.class.to_s.gsub(/Job/, '').downcase
14
+ end
15
+
16
+ def update
17
+ puts "uploading changed #{kind} '#{target}'. Please wait."
18
+ output = `#{command}`
19
+ if output =~ sentinel_re
20
+ puts "#{kind} '#{name}' uploaded."
21
+ true
22
+ else
23
+ puts "#{kind} '#{name}' could not be uploaded."
24
+ false
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ class CookbookJob < Guard::Chef::Base
2
+
3
+ def command
4
+ "knife cookbook upload -VV '#{name}'"
5
+ end
6
+
7
+ def sentinel_re
8
+ /(?:upload complete|uploaded \d+ cookbook)/i
9
+ end
10
+
11
+ end
@@ -0,0 +1,15 @@
1
+ class DataBagJob < Guard::Chef::Base
2
+
3
+ def command
4
+ "rake databag:upload['#{name}']"
5
+ end
6
+
7
+ def sentinel_re
8
+ /Updated data_bag_item/
9
+ end
10
+
11
+ def self.accepts?(path, extension)
12
+ extension.nil? && path =~ /(rb|json)$/
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ class EnvironmentJob < Guard::Chef::Base
2
+
3
+ def command
4
+ "knife environment from file -VV '#{target}'"
5
+ end
6
+
7
+ def sentinel_re
8
+ /Updated Environment #{name}/
9
+ end
10
+
11
+ def self.accepts?(path, extension)
12
+ !! (extension =~ /(rb|json)/)
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ class RoleJob < Guard::Chef::Base
2
+
3
+ def command
4
+ "knife role from file -VV '#{target}'"
5
+ end
6
+
7
+ def sentinel_re
8
+ /Updated Role #{name}!/
9
+ end
10
+
11
+ def self.accepts?(path, extension)
12
+ !! (extension =~ /(rb|json)/)
13
+ end
14
+
15
+ end
@@ -0,0 +1,13 @@
1
+
2
+ # run the right knife command on changes within the cookbooks, roles and data_bags directories
3
+ guard 'chef' do
4
+ # # uncomment if you follow the "symlink into vendor" practice:
5
+ # # this turns notification for vendor/infochimps-labs/foo/recipes.rb
6
+ # # into a notification for cookbooks/foo/recipes.rb if cookbooks/foo exists
7
+ # watch(%r{vendor/[^/]+/(.+)}){|m| fn = "cookbooks/#{m[1]}" ; fn if File.exists?(fn) }
8
+
9
+ watch(%r{^.*cookbooks/(.+)/})
10
+ watch(%r{^roles/(.+)\.(rb|json)\z})
11
+ watch(%r{^data_bags/(.+)/})
12
+ watch(%r{^environments/.*\.(rb|json)\z})
13
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ module Guard
3
+ module ChefVersion
4
+ VERSION = '0.1.0'
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ task :upload_cookbook do
2
+ # noop
3
+ end
4
+
5
+ namespace :databag do
6
+ task :upload do
7
+ # noop
8
+ end
9
+ end
10
+
11
+ task :role do
12
+ # noop
13
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: infochimps-guard-chef
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dreamr OKelly
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: guard
16
+ requirement: &70233827387680 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '1.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70233827387680
25
+ - !ruby/object:Gem::Dependency
26
+ name: bundler
27
+ requirement: &70233827386820 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '1.1'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70233827386820
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70233827385720 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '2.5'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70233827385720
47
+ description: Guard::Chef allows to automatically & intelligently update roles, cookbooks,
48
+ and databags for chef.
49
+ email:
50
+ - james@rubyloves.me
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - lib/guard/chef/base.rb
56
+ - lib/guard/chef/cookbook_job.rb
57
+ - lib/guard/chef/data_bag_job.rb
58
+ - lib/guard/chef/enviroment_job.rb
59
+ - lib/guard/chef/role_job.rb
60
+ - lib/guard/chef/templates/Guardfile
61
+ - lib/guard/chef/version.rb
62
+ - lib/guard/chef.rb
63
+ - lib/tasks/dummy.rake
64
+ - LICENSE
65
+ - README.rdoc
66
+ homepage: http://rubygems.org/gems/guard-chef
67
+ licenses: []
68
+ post_install_message:
69
+ rdoc_options:
70
+ - --charset=UTF-8
71
+ - --main=README.rdoc
72
+ - --exclude='(lib|test|spec)|(Gem|Guard|Rake)file'
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: 1.3.6
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.11
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: Guard gem for Chef
93
+ test_files: []
94
+ has_rdoc: