infochimps-guard-chef 0.1.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.
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: