knife-santoku 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +98 -0
- data/Rakefile +2 -0
- data/bin/santoku +32 -0
- data/examples/santoku-after.rb +26 -0
- data/examples/santoku-before.rb +7 -0
- data/examples/santoku-config.yml +8 -0
- data/knife-santoku.gemspec +21 -0
- data/lib/knife-santoku.rb +10 -0
- data/lib/knife_santoku/application.rb +38 -0
- data/lib/knife_santoku/callback.rb +38 -0
- data/lib/knife_santoku/monkey_patches/knife.rb +24 -0
- data/lib/knife_santoku/notification/hipchat_notifier.rb +25 -0
- data/lib/knife_santoku/notifier.rb +19 -0
- data/lib/knife_santoku/version.rb +3 -0
- metadata +113 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Kevin Nuckolls
|
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,98 @@
|
|
1
|
+
# Knife-Santoku
|
2
|
+
A drop in replacement for knife that helps you build out processes around Chef.
|
3
|
+
|
4
|
+
![Santoku](http://upload.wikimedia.org/wikipedia/commons/a/aa/Kitchen-knife-santoku-form.jpg)
|
5
|
+
http://en.wikipedia.org/wiki/Santoku
|
6
|
+
|
7
|
+
## Overview
|
8
|
+
|
9
|
+
Santoku is primarily used for firing off notifications when knife commands are run. There are two concepts in Santoku: callbacks, and notifiers. Santoku fires off callbacks before and after any knife command is run. Callbacks can be any arbitrary ruby code in config/santoku-before.rb or config/santoku-after.rb. However, they are primarily made up of regexp matcher functions that fire off notifications to Santoku notification plugins.
|
10
|
+
|
11
|
+
Right now only Hipchat support has been written. More work will be done to let you drop your own notification classes into the lib/santoku/ folder of your chef repo to build integrations with your favorite systems. If you build out something and would like it added to the master project just send me a pull request.
|
12
|
+
|
13
|
+
You don't have to use Santoku for notifications, that's just what it was originally built for.
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
Just run knife commands with the santoku command instead of knife.
|
18
|
+
|
19
|
+
For example, any time you would have run this:
|
20
|
+
|
21
|
+
knife cookbook upload rabbitmq
|
22
|
+
|
23
|
+
just run it with santoku instead
|
24
|
+
|
25
|
+
santoku cookbook upload rabbitmq
|
26
|
+
|
27
|
+
And if you reallly love santoku just make it an alias, put it in your profile, and forget all about it:
|
28
|
+
|
29
|
+
alias knife="santoku"
|
30
|
+
|
31
|
+
## Configuration
|
32
|
+
|
33
|
+
Put something like this in your config/santoku-before.rb or config/santoku-after.rb. These matchers will make sure that only commands that alter the chef server send off a notification.
|
34
|
+
|
35
|
+
match /spork/ do
|
36
|
+
notify :hipchat, "Someone used the spork plugin"
|
37
|
+
end
|
38
|
+
|
39
|
+
match /from file/ do
|
40
|
+
notify :hipchat
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'etc'
|
44
|
+
match /cookbook upload (.*)/ do |cookbook|
|
45
|
+
notify :hipchat, "#{Etc.getlogin} finished uploading #{cookbook}"
|
46
|
+
end
|
47
|
+
|
48
|
+
match /create/ do
|
49
|
+
notify :hipchat
|
50
|
+
end
|
51
|
+
|
52
|
+
match /delete/ do
|
53
|
+
notify :hipchat
|
54
|
+
end
|
55
|
+
|
56
|
+
match /bootstrap/ do
|
57
|
+
notify :hipchat
|
58
|
+
end
|
59
|
+
|
60
|
+
Put this in config/santoku-config.yml
|
61
|
+
|
62
|
+
hipchat:
|
63
|
+
token: "your_hipchat_api_token"
|
64
|
+
room: "developers"
|
65
|
+
from: "Knife"
|
66
|
+
notify: false
|
67
|
+
color: "yellow"
|
68
|
+
|
69
|
+
After configuring all of that you should start receiving notifications in your hipchat room whenever someone alters something on the server with knife. This can easily be adapted to add in notifications to other services.
|
70
|
+
|
71
|
+
## Installation
|
72
|
+
|
73
|
+
Add this line to your application's Gemfile:
|
74
|
+
|
75
|
+
gem 'knife-santoku'
|
76
|
+
|
77
|
+
And then execute:
|
78
|
+
|
79
|
+
$ bundle
|
80
|
+
|
81
|
+
Or install it yourself as:
|
82
|
+
|
83
|
+
$ gem install knife-santoku
|
84
|
+
|
85
|
+
## Todo
|
86
|
+
* Add in the logic for end user drop in notification plugins
|
87
|
+
* Better tests
|
88
|
+
* Merge real callback functionality into the upstream knife codebase.
|
89
|
+
* Santoku only lets you notify before and after knife commands.
|
90
|
+
* It would be best and most flexible to be able to hook right in with knife inside opscode's codebase.
|
91
|
+
|
92
|
+
## Contributing
|
93
|
+
|
94
|
+
1. Fork it
|
95
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
96
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
97
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
98
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/santoku
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# ./santoku - A flexible wrapper for the 'knife' Chef CLI interface
|
4
|
+
#
|
5
|
+
# Author:: Kevin Nuckolls(<kevin.nuckolls@gmail.com>)
|
6
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
7
|
+
# Copyright:: Copyright (c) 2009 Opscode, Inc.
|
8
|
+
# License:: Apache License, Version 2.0
|
9
|
+
#
|
10
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
11
|
+
# you may not use this file except in compliance with the License.
|
12
|
+
# You may obtain a copy of the License at
|
13
|
+
#
|
14
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
15
|
+
#
|
16
|
+
# Unless required by applicable law or agreed to in writing, software
|
17
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
18
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
19
|
+
# See the License for the specific language governing permissions and
|
20
|
+
# limitations under the License.
|
21
|
+
|
22
|
+
## Adapted from Opscode's knife initializer @ https://github.com/opscode/chef
|
23
|
+
|
24
|
+
require 'rubygems'
|
25
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
26
|
+
require 'chef/application/knife'
|
27
|
+
|
28
|
+
## Contains a monkeypatch for Chef::Application::Knife. Shims in Santoku.
|
29
|
+
require 'knife-santoku'
|
30
|
+
|
31
|
+
Chef::Application::Knife.new.run
|
32
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
## Put this in config/santoku-after.rb
|
2
|
+
|
3
|
+
match /spork/ do
|
4
|
+
notify :hipchat, "Someone used the spork plugin"
|
5
|
+
end
|
6
|
+
|
7
|
+
match /from file/ do
|
8
|
+
notify :hipchat
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'etc'
|
12
|
+
match /cookbook upload (.*)/ do |cookbook|
|
13
|
+
notify :hipchat, "#{Etc.getlogin} finished uploading #{cookbook}"
|
14
|
+
end
|
15
|
+
|
16
|
+
match /create/ do
|
17
|
+
notify :hipchat
|
18
|
+
end
|
19
|
+
|
20
|
+
match /delete/ do
|
21
|
+
notify :hipchat
|
22
|
+
end
|
23
|
+
|
24
|
+
match /bootstrap/ do
|
25
|
+
notify :hipchat
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/knife_santoku/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Kevin Nuckolls"]
|
6
|
+
gem.email = ["kevin.nuckolls@gmail.com"]
|
7
|
+
gem.description = "A drop in replacement for knife that helps you build out processes around Chef"
|
8
|
+
gem.summary = ""
|
9
|
+
gem.homepage = "http://www.github.com/knuckolls/knife-santoku"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "knife-santoku"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = KnifeSantoku::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency "chef"
|
19
|
+
gem.add_dependency "httparty"
|
20
|
+
gem.add_dependency "app_conf"
|
21
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "knife_santoku/version"
|
2
|
+
require "knife_santoku/notifier"
|
3
|
+
require 'knife_santoku/notification/hipchat_notifier'
|
4
|
+
require "knife_santoku/callback"
|
5
|
+
require "knife_santoku/monkey_patches/knife"
|
6
|
+
require "knife_santoku/application"
|
7
|
+
|
8
|
+
module KnifeSantoku
|
9
|
+
|
10
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'app_conf'
|
2
|
+
require 'chef/knife'
|
3
|
+
|
4
|
+
module KnifeSantoku
|
5
|
+
class Application
|
6
|
+
def initialize(argv)
|
7
|
+
|
8
|
+
chef_conf_dir = ::Chef::Knife.chef_config_dir
|
9
|
+
|
10
|
+
config_file = "#{chef_conf_dir}/../config/santoku-config.yml"
|
11
|
+
before_file = "#{chef_conf_dir}/../config/santoku-before.rb"
|
12
|
+
after_file = "#{chef_conf_dir}/../config/santoku-after.rb"
|
13
|
+
lib_folder = Pathname.new("#{chef_conf_dir}/../lib/santoku/")
|
14
|
+
|
15
|
+
|
16
|
+
config = AppConf.new
|
17
|
+
config.load(config_file)
|
18
|
+
|
19
|
+
|
20
|
+
# load up notifiers & custom code out of lib
|
21
|
+
#notifier = Notifier.new(config,lib_folder)
|
22
|
+
notifier = ::KnifeSantoku::Notifier.new(config)
|
23
|
+
|
24
|
+
|
25
|
+
# load up callbacks
|
26
|
+
@before_callbacks = Callback.new(before_file, notifier, argv)
|
27
|
+
@after_callbacks = Callback.new(after_file, notifier, argv)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_before_callbacks
|
31
|
+
@before_callbacks.run
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_after_callbacks
|
35
|
+
@after_callbacks.run
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'chef/mixin/from_file'
|
2
|
+
require 'etc'
|
3
|
+
|
4
|
+
module KnifeSantoku
|
5
|
+
class Callback
|
6
|
+
|
7
|
+
include Chef::Mixin::FromFile
|
8
|
+
|
9
|
+
def initialize(file, notifier, argv)
|
10
|
+
@file = file
|
11
|
+
@notifier = notifier
|
12
|
+
@argv = argv.join(" ")
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
from_file(@file)
|
17
|
+
end
|
18
|
+
|
19
|
+
def match(regexp, &proc)
|
20
|
+
matches = regexp.match(@argv)
|
21
|
+
|
22
|
+
if (matches != nil and matches.length > 1)
|
23
|
+
|
24
|
+
# drop the 'full match' off the front and leave the captures
|
25
|
+
matches = matches.to_a.drop(1)
|
26
|
+
|
27
|
+
proc.call(*matches)
|
28
|
+
elsif @argv =~ regexp
|
29
|
+
proc.call
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def notify(type, msg="#{Etc.getlogin} ran: #{@argv}")
|
34
|
+
@notifier.notify(type, msg)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
## Monkeypatch knife to add in callback support
|
2
|
+
|
3
|
+
|
4
|
+
class Chef::Application::Knife
|
5
|
+
|
6
|
+
# Run knife
|
7
|
+
def run
|
8
|
+
require 'knife-santoku'
|
9
|
+
santoku = ::KnifeSantoku::Application.new(ARGV)
|
10
|
+
|
11
|
+
Mixlib::Log::Formatter.show_time = false
|
12
|
+
validate_and_parse_options
|
13
|
+
quiet_traps
|
14
|
+
|
15
|
+
santoku.run_before_callbacks
|
16
|
+
|
17
|
+
Chef::Knife.run(ARGV, options)
|
18
|
+
|
19
|
+
santoku.run_after_callbacks
|
20
|
+
|
21
|
+
exit 0
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module KnifeSantoku
|
4
|
+
module Notification
|
5
|
+
class HipchatNotifier
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@url = "https://api.hipchat.com/v1/rooms/message"
|
9
|
+
|
10
|
+
@token = config["hipchat"]["token"]
|
11
|
+
@room = config["hipchat"]["room"]
|
12
|
+
@from = config["hipchat"]["from"]
|
13
|
+
@notify = 0 if config["hipchat"]["notify"] == false
|
14
|
+
@notify = 1 if config["hipchat"]["notify"] == true
|
15
|
+
@color = config["hipchat"]["color"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def notify(msg)
|
19
|
+
url = "#{@url}?format=json&auth_token=#{@token}&message=#{URI.escape(msg)}&room_id=#{@room}&from=#{@from}¬ify=#{@notify}&color=#{@color}"
|
20
|
+
HTTParty.post(url)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module KnifeSantoku
|
2
|
+
class Notifier
|
3
|
+
#def initialize(config, lib_folder)
|
4
|
+
def initialize(config)
|
5
|
+
@config = config
|
6
|
+
|
7
|
+
@notifiers = { :hipchat => ::KnifeSantoku::Notification::HipchatNotifier }
|
8
|
+
|
9
|
+
# iterate through our internal folder and our external folder for notification classes
|
10
|
+
end
|
11
|
+
|
12
|
+
def notify(type, msg)
|
13
|
+
klass = @notifiers[type]
|
14
|
+
notifier = klass.new(@config)
|
15
|
+
|
16
|
+
notifier.notify(msg)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: knife-santoku
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kevin Nuckolls
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: chef
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: httparty
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: app_conf
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: A drop in replacement for knife that helps you build out processes around
|
63
|
+
Chef
|
64
|
+
email:
|
65
|
+
- kevin.nuckolls@gmail.com
|
66
|
+
executables:
|
67
|
+
- santoku
|
68
|
+
extensions: []
|
69
|
+
extra_rdoc_files: []
|
70
|
+
files:
|
71
|
+
- .gitignore
|
72
|
+
- .rvmrc
|
73
|
+
- Gemfile
|
74
|
+
- LICENSE
|
75
|
+
- README.md
|
76
|
+
- Rakefile
|
77
|
+
- bin/santoku
|
78
|
+
- examples/santoku-after.rb
|
79
|
+
- examples/santoku-before.rb
|
80
|
+
- examples/santoku-config.yml
|
81
|
+
- knife-santoku.gemspec
|
82
|
+
- lib/knife-santoku.rb
|
83
|
+
- lib/knife_santoku/application.rb
|
84
|
+
- lib/knife_santoku/callback.rb
|
85
|
+
- lib/knife_santoku/monkey_patches/knife.rb
|
86
|
+
- lib/knife_santoku/notification/hipchat_notifier.rb
|
87
|
+
- lib/knife_santoku/notifier.rb
|
88
|
+
- lib/knife_santoku/version.rb
|
89
|
+
homepage: http://www.github.com/knuckolls/knife-santoku
|
90
|
+
licenses: []
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.8.24
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: ''
|
113
|
+
test_files: []
|