chef-handler-sns 0.1.1 → 0.2.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/README.md +94 -45
- data/lib/chef/handler/sns.rb +23 -37
- data/lib/chef/handler/sns/templates/body.erb +36 -0
- data/lib/chef/handler/sns/version.rb +1 -1
- metadata +19 -2
data/README.md
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
-
|
2
|
-
===========
|
1
|
+
# Chef Handler SNS
|
3
2
|
|
4
3
|
A simple Chef report handler that reports status of a Chef run through Amazon SNS.
|
5
4
|
|
5
|
+
This Chef Handler is heavily based on [Joshua Timberman](https://github.com/jtimberman) examples.
|
6
|
+
|
6
7
|
* http://wiki.opscode.com/display/chef/Exception+and+Report+Handlers
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
[](http://badge.fury.io/rb/chef-handler-sns)
|
10
|
+
[](https://gemnasium.com/onddo/chef-handler-sns)
|
11
|
+
|
12
|
+
## Requirements
|
10
13
|
|
11
14
|
* Amazon AWS: uses Amazon SNS service.
|
12
15
|
* Uses the `right_aws` library.
|
13
16
|
|
14
|
-
Usage
|
15
|
-
=====
|
17
|
+
## Usage
|
16
18
|
|
17
19
|
You can install this handler in two ways:
|
18
20
|
|
@@ -24,55 +26,102 @@ You can install the RubyGem and configure Chef to use it:
|
|
24
26
|
|
25
27
|
Then add to the configuration (`/etc/chef/solo.rb` for chef-solo or `/etc/chef/client.rb` for chef-client):
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
29
|
+
```ruby
|
30
|
+
require "chef/handler/sns"
|
31
|
+
|
32
|
+
# Create the handler
|
33
|
+
sns_handler = Chef::Handler::Sns.new
|
34
|
+
|
35
|
+
# Your Amazon AWS credentials
|
36
|
+
sns_handler.access_key = "***AMAZON-KEY***"
|
37
|
+
sns_handler.secret_key = "***AMAZON-SECRET***"
|
38
|
+
|
39
|
+
# Some Amazon SNS configurations
|
40
|
+
sns_handler.topic_arn = "arn:aws:sns:***"
|
41
|
+
sns_handler.region = "us-east-1" # optional
|
42
|
+
|
43
|
+
# Add your handler
|
44
|
+
exception_handlers << sns_handler
|
45
|
+
```
|
42
46
|
|
43
47
|
### Method 2: In a recipe with the chef_handler LWRP
|
44
48
|
|
45
49
|
Use the [chef_handler LWRP](http://community.opscode.com/cookbooks/chef_handler), creating a recipe with the following:
|
46
50
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
51
|
+
```ruby
|
52
|
+
# Handler configuration options
|
53
|
+
argument_array = [
|
54
|
+
:access_key => "***AMAZON-KEY***",
|
55
|
+
:secret_key => "***AMAZON-SECRET***",
|
56
|
+
:topic_arn => "arn:aws:sns:***",
|
57
|
+
]
|
58
|
+
|
59
|
+
# Install the `chef-handler-sns` RubyGem during the compile phase
|
60
|
+
chef_gem "chef-handler-sns"
|
61
|
+
|
62
|
+
# Then activate the handler with the `chef_handler` LWRP
|
63
|
+
chef_handler "Chef::Handler::Sns" do
|
64
|
+
source "#{Gem::Specification.find_by_name("chef-handler-sns").lib_dirs_glob}/chef/handler/sns"
|
65
|
+
arguments argument_array
|
66
|
+
supports :exception => true
|
67
|
+
action :enable
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
If you have an old version of gem package (< 1.8.6) without `find_by_name` or old chef-client (< 0.10.10) without `chef_gem`, you can try creating a recipe similar to the following:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
# Handler configuration options
|
75
|
+
argument_array = [
|
76
|
+
:access_key => "***AMAZON-KEY***",
|
77
|
+
:secret_key => "***AMAZON-SECRET***",
|
78
|
+
:topic_arn => "arn:aws:sns:***",
|
79
|
+
]
|
80
|
+
|
81
|
+
# Install the `chef-handler-sns` RubyGem during the compile phase
|
82
|
+
if defined?(Chef::Resource::ChefGem)
|
83
|
+
chef_gem "chef-handler-sns"
|
84
|
+
else
|
85
|
+
gem_package("chef-handler-sns") do
|
86
|
+
action :nothing
|
87
|
+
end.run_action(:install)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get the installed `chef-handler-sns` gem path
|
91
|
+
sns_handler_path = Gem::Specification.respond_to?("find_by_name") ?
|
92
|
+
Gem::Specification.find_by_name("chef-handler-sns").lib_dirs_glob :
|
93
|
+
Gem.all_load_paths.grep(/chef-handler-sns/).first
|
94
|
+
|
95
|
+
# Then activate the handler with the `chef_handler` LWRP
|
96
|
+
chef_handler "Chef::Handler::Sns" do
|
97
|
+
source "#{sns_handler_path}/chef/handler/sns"
|
98
|
+
arguments argument_array
|
99
|
+
supports :exception => true
|
100
|
+
action :enable
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
## Handler Configuration Options
|
105
|
+
|
106
|
+
The following options are available to configure the handler:
|
107
|
+
|
108
|
+
* `access_key` - AWS access key (required).
|
109
|
+
* `secret_key` - AWS secret key (required).
|
110
|
+
* `topic_arn` - AWS topic ARN name (required).
|
111
|
+
* `region` - AWS region (optional).
|
112
|
+
* `subject` - Message subject string in erubis format (optional). Example:
|
113
|
+
```
|
114
|
+
sns_handler.subject: "Chef-run: <%= node.name %> - <%= run_status.success? ? 'ok' : 'error' %>"
|
115
|
+
```
|
116
|
+
* `body_template` - Full path of an erubis template file to use for the message body (optional).
|
117
|
+
|
118
|
+
## Roadmap
|
69
119
|
|
70
120
|
* rspec tests.
|
71
121
|
|
72
122
|
Pull requests are welcome.
|
73
123
|
|
74
|
-
License and Author
|
75
|
-
==================
|
124
|
+
## License and Author
|
76
125
|
|
77
126
|
| | |
|
78
127
|
|:---------------------|:-----------------------------------------|
|
data/lib/chef/handler/sns.rb
CHANGED
@@ -18,11 +18,12 @@
|
|
18
18
|
|
19
19
|
require 'chef/handler'
|
20
20
|
require 'right_aws'
|
21
|
+
require 'erubis'
|
21
22
|
|
22
23
|
class Chef
|
23
24
|
class Handler
|
24
25
|
class Sns < ::Chef::Handler
|
25
|
-
attr_writer :access_key, :secret_key, :region, :token, :topic_arn
|
26
|
+
attr_writer :access_key, :secret_key, :region, :token, :topic_arn, :subject, :body_template
|
26
27
|
|
27
28
|
def initialize(config={})
|
28
29
|
Chef::Log.debug("#{self.class.to_s} initialized.")
|
@@ -31,6 +32,8 @@ class Chef
|
|
31
32
|
@region = config[:region] if config.has_key?(:region)
|
32
33
|
@token = config[:token] if config.has_key?(:token)
|
33
34
|
@topic_arn = config[:topic_arn]
|
35
|
+
@subject = config[:subject] if config.has_key?(:subject)
|
36
|
+
@body_template = config[:body_template] if config.has_key?(:body_template)
|
34
37
|
end
|
35
38
|
|
36
39
|
def report
|
@@ -46,8 +49,13 @@ class Chef
|
|
46
49
|
raise "access_key not properly set" unless @access_key.kind_of?(String)
|
47
50
|
raise "secret_key not properly set" unless @secret_key.kind_of?(String)
|
48
51
|
raise "region not properly set" unless @region.kind_of?(String) or @region.nil?
|
49
|
-
raise "topic_arn not properly set" unless @topic_arn.kind_of?(String)
|
50
52
|
raise "token not properly set" unless @token.kind_of?(String) or @token.nil?
|
53
|
+
raise "topic_arn not properly set" unless @topic_arn.kind_of?(String)
|
54
|
+
raise "subject not properly set" unless @subject.kind_of?(String) or @subject.nil?
|
55
|
+
unless @body_template.nil?
|
56
|
+
raise "body_template not properly set" unless @body_template.kind_of?(String)
|
57
|
+
raise "body_template file not found: #{@body_template}" unless ::File.exists?(@body_template)
|
58
|
+
end
|
51
59
|
end
|
52
60
|
|
53
61
|
def sns
|
@@ -62,44 +70,22 @@ class Chef
|
|
62
70
|
end
|
63
71
|
|
64
72
|
def sns_subject
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
if @subject
|
74
|
+
context = self
|
75
|
+
eruby = Erubis::Eruby.new(@subject)
|
76
|
+
eruby.evaluate(context)
|
77
|
+
else
|
78
|
+
chef_client = Chef::Config[:solo] ? 'Chef Solo' : 'Chef Client'
|
79
|
+
status = run_status.success? ? 'success' : 'failure'
|
80
|
+
"#{chef_client} #{status} in #{node.name}"
|
81
|
+
end
|
68
82
|
end
|
69
83
|
|
70
84
|
def sns_body
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
message << "\n"
|
76
|
-
|
77
|
-
message << "Chef Run List: #{node.run_list.to_s}\n"
|
78
|
-
message << "Chef Environment: #{node.chef_environment}\n"
|
79
|
-
message << "\n"
|
80
|
-
|
81
|
-
if node.attribute?('ec2')
|
82
|
-
message << "Instance Id: #{node.ec2.instance_id}\n"
|
83
|
-
message << "Instance Public Hostname: #{node.ec2.public_hostname}\n"
|
84
|
-
message << "Instance Hostname: #{node.ec2.hostname}\n"
|
85
|
-
message << "Instance Public IPv4: #{node.ec2.public_ipv4}\n"
|
86
|
-
message << "Instance Local IPv4: #{node.ec2.local_ipv4}\n"
|
87
|
-
end
|
88
|
-
message << "\n"
|
89
|
-
|
90
|
-
message << "Chef Client Elapsed Time: #{elapsed_time.to_s}\n"
|
91
|
-
message << "Chef Client Start Time: #{start_time.to_s}\n"
|
92
|
-
message << "Chef Client Start Time: #{end_time.to_s}\n"
|
93
|
-
message << "\n"
|
94
|
-
|
95
|
-
if exception
|
96
|
-
message << "Exception: #{run_status.formatted_exception}\n"
|
97
|
-
message << "Stacktrace:\n"
|
98
|
-
message << Array(backtrace).join("\n")
|
99
|
-
message << "\n"
|
100
|
-
end
|
101
|
-
|
102
|
-
message
|
85
|
+
template = IO.read(@body_template || "#{File.dirname(__FILE__)}/sns/templates/body.erb")
|
86
|
+
context = self
|
87
|
+
eruby = Erubis::Eruby.new(template)
|
88
|
+
eruby.evaluate(context)
|
103
89
|
end
|
104
90
|
|
105
91
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
Node Name: <%= node.name %>
|
2
|
+
<% if node.attribute?('fqdn') -%>
|
3
|
+
Hostname: <%= node.fqdn %>
|
4
|
+
<% end -%>
|
5
|
+
|
6
|
+
Chef Run List: <%= node.run_list.to_s %>
|
7
|
+
Chef Environment: <%= node.chef_environment %>
|
8
|
+
|
9
|
+
<% if node.attribute?('ec2') -%>
|
10
|
+
<% if node.ec2.attribute?('instance_id') -%>
|
11
|
+
Instance Id: <%= node.ec2.instance_id %>
|
12
|
+
<% end -%>
|
13
|
+
<% if node.ec2.attribute?('public_hostname') -%>
|
14
|
+
Instance Public Hostname: <%= node.ec2.public_hostname %>
|
15
|
+
<% end -%>
|
16
|
+
<% if node.ec2.attribute?('hostname') -%>
|
17
|
+
Instance Hostname: <%= node.ec2.hostname %>
|
18
|
+
<% end -%>
|
19
|
+
<% if node.ec2.attribute?('public_ipv4') -%>
|
20
|
+
Instance Public IPv4: <%= node.ec2.public_ipv4 %>
|
21
|
+
<% end -%>
|
22
|
+
<% if node.ec2.attribute?('local_ipv4') -%>
|
23
|
+
Instance Local IPv4: <%= node.ec2.local_ipv4 %>
|
24
|
+
<% end -%>
|
25
|
+
<% end -%>
|
26
|
+
|
27
|
+
Chef Client Elapsed Time: <%= elapsed_time.to_s %>
|
28
|
+
Chef Client Start Time: <%= start_time.to_s %>
|
29
|
+
Chef Client Start Time: <%= end_time.to_s %>
|
30
|
+
|
31
|
+
<% if exception -%>
|
32
|
+
Exception: <%= run_status.formatted_exception %>
|
33
|
+
Stacktrace:
|
34
|
+
<%= Array(backtrace).join("\n") %>
|
35
|
+
|
36
|
+
<% end -%>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-handler-sns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02
|
12
|
+
date: 2013-03-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: right_aws
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '3.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: erubis
|
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'
|
30
46
|
description: Chef report handler to send SNS notifications on failures or changes
|
31
47
|
email: team@onddo.com
|
32
48
|
executables: []
|
@@ -35,6 +51,7 @@ extra_rdoc_files: []
|
|
35
51
|
files:
|
36
52
|
- LICENSE
|
37
53
|
- README.md
|
54
|
+
- lib/chef/handler/sns/templates/body.erb
|
38
55
|
- lib/chef/handler/sns/version.rb
|
39
56
|
- lib/chef/handler/sns.rb
|
40
57
|
homepage: http://github.com/onddo/chef-handler-sns
|