chef-rabbit 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +0 -0
- data/README.rdoc +82 -0
- data/Rakefile +1 -0
- data/chef-rabbit.gemspec +23 -0
- data/lib/chef/rabbit.rb +115 -0
- data/lib/chef/rabbit/version.rb +28 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MTdjY2I2MWNjNDQ5NDg4ZWU1NDQ3OTQwYjFjZGQ3NmEwMGE4NDk3ZQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
N2M4NDhlMzQ4N2FlMGFiMzk5MTI0MzU0MDEyYWJlODc1NTczZjdlYw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YWQ5ZGM0YzM5NTU2YmFjMWFmZWMwYjhhM2ZhZDRlODM5NzdiMzczZDQyNjU2
|
10
|
+
YzA3MjdhYzBkNDViZmFlOGQxNjY3NzQxMWM0NTk2ZTNmN2Y0NmVjZTJmM2Mw
|
11
|
+
ZWJiMzA0MzgzYWVmNDQ1ZGMzNWFjMjRhNGIyNGE2MzdkMzZjYTg=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
Y2JjNTQyNTM2YzRmMmZkNDQ2YTZjYTk4Mjc5MTU0OTAyMTRmMTQ5M2Q1MzYx
|
14
|
+
Yzk0NDJkOTUzODRmN2E0YjE0NjA1ZDE4YTUzNTM2NTUyOTNlZDc5MmQ1MjIy
|
15
|
+
YmNkMzRiYzUzYmNlZjM0ODVmZjYyMGE4YWMxYTNiOTRkMDBiMWY=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
File without changes
|
data/README.rdoc
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
= DESCRIPTION:
|
2
|
+
|
3
|
+
Provides a Chef handler which can report run status, including any changes that were made, to a rabbit server. In the case of failed runs a backtrace will be included in the details reported. Based on the Graylog Gelf handler by Jon Wood (<jon@blankpad.net>) https://github.com/jellybob/chef-gelf
|
4
|
+
|
5
|
+
= REQUIREMENTS:
|
6
|
+
|
7
|
+
* A Rabbit server running somewhere.
|
8
|
+
|
9
|
+
= USAGE:
|
10
|
+
|
11
|
+
This example makes of the chef_handler cookbook, place some thing like this in cookbooks/chef_handler/recipes/rabbit.rb and add it to your run list.
|
12
|
+
|
13
|
+
include_recipe "chef_handler::default"
|
14
|
+
|
15
|
+
gem_package "chef-rabbit" do
|
16
|
+
action :nothing
|
17
|
+
end.run_action(:install)
|
18
|
+
|
19
|
+
# Make sure the newly installed Gem is loaded.
|
20
|
+
Gem.clear_paths
|
21
|
+
require 'chef/rabbit'
|
22
|
+
|
23
|
+
chef_handler "Chef::RABBIT::Handler" do
|
24
|
+
source "chef/rabbit"
|
25
|
+
arguments({
|
26
|
+
:host => your_rabbit_server,
|
27
|
+
:user => rabbit_user,
|
28
|
+
:pass => rabbit_pass,
|
29
|
+
:queue => your_queue,
|
30
|
+
:exchange => your_exchange,
|
31
|
+
:timestamp_tag => "@timestamp"
|
32
|
+
})
|
33
|
+
|
34
|
+
supports :exception => true, :report => true
|
35
|
+
end.run_action(:enable)
|
36
|
+
|
37
|
+
Arguments take the form of an options hash, with the following options:
|
38
|
+
|
39
|
+
* bunny client attributes - http://rubybunny.info/articles/connecting.html
|
40
|
+
* :queue - name of the rabbit queue to use. "chef-client" by default
|
41
|
+
* :exchange - name of exchange to use .default_exchange otherwise
|
42
|
+
* :timestamp_tag - tag for timestamp "timestamp" by default
|
43
|
+
* :blacklist ({}) - A hash of cookbooks, resources and actions to ignore in the change list.
|
44
|
+
|
45
|
+
= BLACKLISTING:
|
46
|
+
|
47
|
+
Some resources report themselves as having updated on every run even if nothing changed, or are just things you don't care about. To reduce the amount of noise in your logs these can be ignored by providing a blacklist. In this example we don't want to be told about the GELF handler being activated:
|
48
|
+
|
49
|
+
chef_handler "Chef::RABBIT::Handler" do
|
50
|
+
source "chef/rabbit"
|
51
|
+
arguments({
|
52
|
+
:blacklist => {
|
53
|
+
"chef_handler" => {
|
54
|
+
"chef_handler" => [ "nothing", "enable" ]
|
55
|
+
}
|
56
|
+
}
|
57
|
+
})
|
58
|
+
|
59
|
+
supports :exception => true, :report => true
|
60
|
+
end.run_action(:enable)
|
61
|
+
|
62
|
+
= LICENSE and AUTHOR:
|
63
|
+
|
64
|
+
Copyright 2014 by MTN Sattelite Communications
|
65
|
+
|
66
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
67
|
+
of this software and associated documentation files (the "Software"), to
|
68
|
+
deal in the Software without restriction, including without limitation the
|
69
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
70
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
71
|
+
furnished to do so, subject to the following conditions:
|
72
|
+
|
73
|
+
The above copyright notice and this permission notice shall be included in
|
74
|
+
all copies or substantial portions of the Software.
|
75
|
+
|
76
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
77
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
78
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
79
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
80
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
81
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
82
|
+
IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/chef-rabbit.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "chef/rabbit/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "chef-rabbit"
|
7
|
+
s.version = Chef::RABBIT::VERSION
|
8
|
+
s.authors = ["MTN Satellite Communications"]
|
9
|
+
s.email = ["marat.garafutdinov@mtnsart.com"]
|
10
|
+
s.homepage = "https://github.com/MTNSatelliteComm/chef-rabbit"
|
11
|
+
s.summary = %q{Provides a Chef handler which reports run failures and changes to a Rabbit server.}
|
12
|
+
s.description = File.read("README.rdoc")
|
13
|
+
|
14
|
+
s.rubyforge_project = "chef-rabbit"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency "bunny"
|
22
|
+
s.add_dependency "chef"
|
23
|
+
end
|
data/lib/chef/rabbit.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#--
|
2
|
+
|
3
|
+
# Copyright 2014 by MTN Sattelite Communications
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to
|
7
|
+
# deal in the Software without restriction, including without limitation the
|
8
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
9
|
+
# sell copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
+
# IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require "chef/rabbit/version"
|
25
|
+
require 'bunny'
|
26
|
+
require 'chef/log'
|
27
|
+
|
28
|
+
class Chef
|
29
|
+
module RABBIT
|
30
|
+
class Handler < Chef::Handler
|
31
|
+
attr_reader :connection
|
32
|
+
attr_reader :options
|
33
|
+
|
34
|
+
def options=(value = {})
|
35
|
+
@options = {
|
36
|
+
:host => "127.0.0.1",
|
37
|
+
:port => 5672,
|
38
|
+
:ssl => false,
|
39
|
+
:vhost => "/",
|
40
|
+
:user => "guest",
|
41
|
+
:pass => "guest",
|
42
|
+
:queue => "chef-rabbit",
|
43
|
+
:heartbeat => :server, # will use RabbitMQ setting
|
44
|
+
:frame_max => 131072
|
45
|
+
}.merge(value)
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(options = {})
|
49
|
+
self.options = options
|
50
|
+
|
51
|
+
Chef::Log.debug "Initialised RABBIT handler for amqp://#{self.options[:server]}:#{self.options[:server]}@#{self.options[:server]}:#{self.options[:port]}/#{self.options[:vhost]}"
|
52
|
+
@connection = Bunny.new(self.options)
|
53
|
+
@connection.start
|
54
|
+
end
|
55
|
+
|
56
|
+
def report
|
57
|
+
Chef::Log.debug "Reporting #{run_status.inspect}"
|
58
|
+
|
59
|
+
channel = @connection.create_channel
|
60
|
+
exchange = (@options[:exchange] == nil) ? channel.default_echange : channel.direct(@options[:exchange])
|
61
|
+
timestamp = (@options[:timestamp_tag] == nil) ? "timestamp" : @options[:timestamp_tag]
|
62
|
+
|
63
|
+
if run_status.failed?
|
64
|
+
Chef::Log.debug "Notifying Rabbit server of failure."
|
65
|
+
exchange.publish(
|
66
|
+
{
|
67
|
+
timestamp.to_sym => Time.now.getutc.to_s,
|
68
|
+
:short_message => "Chef run failed on #{node.name}. Updated #{changes[:count]} resources.",
|
69
|
+
:full_message => run_status.formatted_exception + "\n" + Array(backtrace).join("\n") + changes[:message]
|
70
|
+
}.to_json,
|
71
|
+
:routing_key => @options[:queue])
|
72
|
+
else
|
73
|
+
Chef::Log.debug "Notifying Rabbit server of success."
|
74
|
+
exchange.publish(
|
75
|
+
{
|
76
|
+
timestamp.to_sym => Time.now.getutc.to_s,
|
77
|
+
:short_message => "Chef run completed on #{node.name} in #{elapsed_time}. Updated #{changes[:count]} resources.",
|
78
|
+
:full_message => changes[:message]
|
79
|
+
}.to_json,
|
80
|
+
:routing_key => @options[:queue])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def changes
|
85
|
+
@changes unless @changes.nil?
|
86
|
+
|
87
|
+
lines = sanitised_changes.collect do |resource|
|
88
|
+
"recipe[#{resource.cookbook_name}::#{resource.recipe_name}] ran '#{resource.action}' on #{resource.resource_name} '#{resource.name}'"
|
89
|
+
end
|
90
|
+
|
91
|
+
count = lines.size
|
92
|
+
|
93
|
+
message = if count > 0
|
94
|
+
"Updated #{count} resources:\n\n#{lines.join("\n")}"
|
95
|
+
else
|
96
|
+
"No changes made."
|
97
|
+
end
|
98
|
+
|
99
|
+
@changes = { :lines => lines, :count => count, :message => message }
|
100
|
+
end
|
101
|
+
|
102
|
+
def sanitised_changes
|
103
|
+
run_status.updated_resources.reject do |updated|
|
104
|
+
cookbook = @options[:blacklist][updated.cookbook_name]
|
105
|
+
if cookbook
|
106
|
+
resource = cookbook[updated.resource_name.to_s] || []
|
107
|
+
else
|
108
|
+
resource = []
|
109
|
+
end
|
110
|
+
cookbook && resource.include?(updated.action.to_s)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#--
|
2
|
+
|
3
|
+
# Copyright 2014 by MTN Sattelite Communications
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to
|
7
|
+
# deal in the Software without restriction, including without limitation the
|
8
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
9
|
+
# sell copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
+
# IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
class Chef
|
25
|
+
module RABBIT
|
26
|
+
VERSION = "1.0.0"
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chef-rabbit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MTN Satellite Communications
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bunny
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: chef
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: ! "= DESCRIPTION:\n\nProvides a Chef handler which can report run status,
|
42
|
+
including any changes that were made, to a rabbit server. In the case of failed
|
43
|
+
runs a backtrace will be included in the details reported. Based on the Graylog
|
44
|
+
Gelf handler by Jon Wood (<jon@blankpad.net>) https://github.com/jellybob/chef-gelf\n\n=
|
45
|
+
REQUIREMENTS:\n\n* A Rabbit server running somewhere.\n\n= USAGE:\n\nThis example
|
46
|
+
makes of the chef_handler cookbook, place some thing like this in cookbooks/chef_handler/recipes/rabbit.rb
|
47
|
+
and add it to your run list. \n\n include_recipe \"chef_handler::default\"\n\n
|
48
|
+
\ gem_package \"chef-rabbit\" do\n action :nothing\n end.run_action(:install)\n
|
49
|
+
\ \n # Make sure the newly installed Gem is loaded.\n Gem.clear_paths\n require
|
50
|
+
'chef/rabbit'\n \n chef_handler \"Chef::RABBIT::Handler\" do\n source \"chef/rabbit\"\n
|
51
|
+
\ arguments({\n :host => your_rabbit_server,\n :user => rabbit_user,\n
|
52
|
+
\ :pass => rabbit_pass,\n :queue => your_queue,\n :exchange => your_exchange,\n
|
53
|
+
\ :timestamp_tag => \"@timestamp\"\n })\n\n supports :exception => true,
|
54
|
+
:report => true\n end.run_action(:enable)\n\nArguments take the form of an options
|
55
|
+
hash, with the following options:\n\n* bunny client attributes - http://rubybunny.info/articles/connecting.html\n*
|
56
|
+
:queue - name of the rabbit queue to use. \"chef-client\" by default\n*
|
57
|
+
:exchange - name of exchange to use .default_exchange otherwise\n*
|
58
|
+
:timestamp_tag - tag for timestamp \"timestamp\" by default\n* :blacklist
|
59
|
+
({}) - A hash of cookbooks, resources and actions to ignore in the change
|
60
|
+
list.\n\n= BLACKLISTING:\n\nSome resources report themselves as having updated on
|
61
|
+
every run even if nothing changed, or are just things you don't care about. To reduce
|
62
|
+
the amount of noise in your logs these can be ignored by providing a blacklist.
|
63
|
+
In this example we don't want to be told about the GELF handler being activated:\n\n
|
64
|
+
\ chef_handler \"Chef::RABBIT::Handler\" do\n source \"chef/rabbit\"\n arguments({\n
|
65
|
+
\ :blacklist => {\n \"chef_handler\" => {\n \"chef_handler\"
|
66
|
+
=> [ \"nothing\", \"enable\" ]\n }\n }\n })\n\n supports
|
67
|
+
:exception => true, :report => true\n end.run_action(:enable)\n\n= LICENSE and
|
68
|
+
AUTHOR:\n\nCopyright 2014 by MTN Sattelite Communications\n\nPermission is hereby
|
69
|
+
granted, free of charge, to any person obtaining a copy\nof this software and associated
|
70
|
+
documentation files (the \"Software\"), to\ndeal in the Software without restriction,
|
71
|
+
including without limitation the\nrights to use, copy, modify, merge, publish, distribute,
|
72
|
+
sublicense, and/or\nsell copies of the Software, and to permit persons to whom the
|
73
|
+
Software is\nfurnished to do so, subject to the following conditions:\n\nThe above
|
74
|
+
copyright notice and this permission notice shall be included in\nall copies or
|
75
|
+
substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT
|
76
|
+
WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
77
|
+
OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
78
|
+
EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
79
|
+
OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM,
|
80
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n"
|
81
|
+
email:
|
82
|
+
- marat.garafutdinov@mtnsart.com
|
83
|
+
executables: []
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- .gitignore
|
88
|
+
- Gemfile
|
89
|
+
- README.md
|
90
|
+
- README.rdoc
|
91
|
+
- Rakefile
|
92
|
+
- chef-rabbit.gemspec
|
93
|
+
- lib/chef/rabbit.rb
|
94
|
+
- lib/chef/rabbit/version.rb
|
95
|
+
homepage: https://github.com/MTNSatelliteComm/chef-rabbit
|
96
|
+
licenses: []
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ! '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project: chef-rabbit
|
114
|
+
rubygems_version: 2.2.2
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Provides a Chef handler which reports run failures and changes to a Rabbit
|
118
|
+
server.
|
119
|
+
test_files: []
|