cookbook_sdk 1.2.0 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c80a28ba6401d141a2ca1bea0df40521ae9b69f
4
- data.tar.gz: de10b825bfd323009a9ef816bda208d895d3713d
3
+ metadata.gz: db20953f625842a05cb9c9b4052ba82f6130ddbe
4
+ data.tar.gz: c7959d2a228be21d3bb71005afa87728d582f061
5
5
  SHA512:
6
- metadata.gz: 320961d47ae94f7a36e6b42a88d048f5b93310eaa79464e2f707275c5d6ad7c0533bc1b3f26867e15332b4ca1a727172c70d55725286d5d62aeb20be7c151559
7
- data.tar.gz: 061e1e29a110d101241289c3c0ca6dbf82d4242322ddde86bb2d32d50051f666950042d8bcde9789305b7c3cbe1857c0fe8eca48f72b7e4ee52385b43576df38
6
+ metadata.gz: e59c713b5aeddaa4cef7563a45ea2b87184d936e1bd17771dcee3c25250de2c624ea91d21c75cc9e031d80c4238da0f5100f675b4de9fb176c353c47941c09c1
7
+ data.tar.gz: a5175b5ff37fd4e5bca2a7788c5ed9e01598d31dcad145be7450bd8768ef7d27daad5d287bf28e8d7558a82ed6e238c67c6483fecf882bc3c68bbf1d01cbd235
data/.rubocop.yml CHANGED
@@ -14,3 +14,11 @@ Metrics/AbcSize:
14
14
 
15
15
  Metrics/PerceivedComplexity:
16
16
  Max: 15
17
+
18
+ HashSyntax:
19
+ EnforcedStyle: hash_rockets
20
+ Exclude:
21
+ - Rakefile
22
+ - Berksfile
23
+ - Gemfile
24
+ - Policyfile.rb
data/.travis.yml CHANGED
@@ -14,5 +14,5 @@ script:
14
14
  - /opt/chefdk/embedded/bin/chef --version
15
15
  - /opt/chefdk/embedded/bin/rubocop --version
16
16
  - /opt/chefdk/embedded/bin/foodcritic --version
17
- - chef exec bundle exec rake install
18
- - chef exec rake test:rubocop
17
+ - chef exec bundle install
18
+ - chef exec rake test:ci
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # cookbook_sdk
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/cookbook_sdk.svg)](https://badge.fury.io/rb/cookbook_sdk)
3
4
  [![Build Status](https://travis-ci.org/Mindera/cookbook_sdk.svg?branch=master)](https://travis-ci.org/Mindera/cookbook_sdk)
5
+ [![Coverage Status](https://coveralls.io/repos/Mindera/cookbook_sdk/badge.svg?branch=master&service=github)](https://coveralls.io/github/Mindera/cookbook_sdk?branch=master)
4
6
 
5
7
  Helpers for chef cookbook development and provisioning.
data/cookbook_sdk.gemspec CHANGED
@@ -21,5 +21,11 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_dependency 'bundler', '~> 1.9'
23
23
  spec.add_dependency 'rake', '~> 10.4'
24
- spec.add_dependency 'highline', '~> 1.6', '>= 1.6.9'
24
+ spec.add_dependency 'highline', '~> 1.7.8'
25
+
26
+ spec.add_development_dependency 'chef'
27
+ spec.add_development_dependency 'minitest'
28
+ spec.add_development_dependency 'mocha'
29
+ spec.add_development_dependency 'simplecov'
30
+ spec.add_development_dependency 'coveralls'
25
31
  end
@@ -1,3 +1,4 @@
1
+ require 'chef/exceptions'
1
2
  require 'chef/handler'
2
3
  require 'net/http'
3
4
  require 'uri'
@@ -8,18 +9,19 @@ class Chef
8
9
  # Slack Handler goal is send messages to a Slack channel with Chef run status.
9
10
  # It can be used as a start, failure or success handler.
10
11
  class Slack < Chef::Handler
12
+ attr_reader :token, :channel, :username, :on_start, :on_success, :on_failure
13
+
11
14
  def initialize(options = {})
12
- @token = options[:token]
13
- @channel = options[:channel] || '#chef'
14
- @username = options[:username] || 'Chef'
15
- @on_start = options[:on_start].nil? ? true : options[:on_start]
16
- @on_success = options[:on_success].nil? ? true : options[:on_success]
17
- @on_failure = options[:on_failure].nil? ? true : options[:on_failure]
15
+ @token = options.fetch(:token) { raise Exceptions::ConfigurationError, "Slack 'token' should be provided!" }
16
+ @channel = options.fetch(:channel, '#chef')
17
+ @username = options.fetch(:username, 'Chef')
18
+ @on_start = options.fetch(:on_start, true)
19
+ @on_success = options.fetch(:on_success, true)
20
+ @on_failure = options.fetch(:on_failure, true)
18
21
  end
19
22
 
20
23
  def report
21
- options = {}
22
- options[:pretext] = "Run at #{run_status.node.name}"
24
+ options = { :pretext => "Run at #{run_status.node.name}" }
23
25
 
24
26
  if !run_status.is_a?(Chef::RunStatus) || elapsed_time.nil?
25
27
  report_start(options)
@@ -30,6 +32,8 @@ class Chef
30
32
  end
31
33
  end
32
34
 
35
+ private
36
+
33
37
  def report_start(options)
34
38
  return exit_without_sending('start') unless @on_start
35
39
  options[:title] = 'Chef run started!'
@@ -51,34 +55,32 @@ class Chef
51
55
  def report_failure(options)
52
56
  return exit_without_sending('failure') unless @on_failure
53
57
 
54
- options[:title] = 'Chef FAILED!'
58
+ options[:title] = 'Chef run FAILED!'
55
59
  options[:color] = 'danger'
56
60
  options[:body] = "Running #{node.run_list} failed in #{run_status.elapsed_time} seconds."
57
- options[:fallback] = "Chef FAILED! #{run_status.node.name} failed to run #{node.run_list}." \
61
+ options[:fallback] = "Chef FAILED! #{run_status.node.name} failed to run #{node.run_list}" \
58
62
  " in #{run_status.elapsed_time.to_i} seconds."
59
63
  send_attachment(options)
60
64
 
61
65
  return if run_status.exception.nil?
62
-
63
- text = '```' + run_status.formatted_exception.encode(
66
+ options[:text] = '```' + run_status.formatted_exception.encode(
64
67
  'UTF-8',
65
- invalid: 'replace', undef: 'replace', replace: '?'
68
+ :invalid => :replace, :undef => :replace, :replace => '?'
66
69
  ) + '```'
67
- options[:text] = text
68
70
  send_text(options)
69
71
  end
70
72
 
71
73
  def send_attachment(options)
72
- fail 'No message defined to be send to slack' if options[:body].nil?
74
+ raise 'No message defined to be send to slack' if options[:body].nil?
73
75
  params = {
74
- color: options[:color],
75
- attachments: [{
76
- pretext: options[:pretext],
77
- title: options[:title],
78
- title_link: options[:title_link],
79
- color: options[:color],
80
- text: options[:body],
81
- fallback: options[:fallback]
76
+ :color => options[:color],
77
+ :attachments => [{
78
+ :pretext => options[:pretext],
79
+ :title => options[:title],
80
+ :title_link => options[:title_link],
81
+ :color => options[:color],
82
+ :text => options[:body],
83
+ :fallback => options[:fallback]
82
84
  }]
83
85
  }
84
86
  send_slack_message(params)
@@ -89,15 +91,15 @@ class Chef
89
91
  end
90
92
 
91
93
  def send_text(options)
92
- fail 'No message defined to be send to slack' if options[:text].nil?
94
+ raise 'No message defined to be send to slack' if options[:text].nil?
93
95
  params = {
94
- text: options[:text]
96
+ :text => options[:text]
95
97
  }
96
98
  send_slack_message(params)
97
99
  end
98
100
 
99
101
  def send_slack_message(specif_params)
100
- params = { username: @username, channel: @channel, token: @token }.merge(specif_params)
102
+ params = { :username => @username, :channel => @channel, :token => @token }.merge(specif_params)
101
103
 
102
104
  uri = URI("https://hooks.slack.com/services/#{@token}")
103
105
  http = Net::HTTP.new(uri.host, uri.port)
@@ -105,7 +107,7 @@ class Chef
105
107
 
106
108
  begin
107
109
  req = Net::HTTP::Post.new("#{uri.path}?#{uri.query}")
108
- req.set_form_data(payload: params.to_json)
110
+ req.set_form_data(:payload => params.to_json)
109
111
  res = http.request(req)
110
112
  if res.code != '200'
111
113
  Chef::Log.error("We got an error while posting a message to Slack: #{res.code} - #{res.msg}")
@@ -2,6 +2,8 @@ require 'cookbook_sdk/ext/string'
2
2
  require 'cookbook_sdk/rake_tasks/test_tasks'
3
3
  require 'cookbook_sdk/rake_tasks/helper_tasks'
4
4
  require 'cookbook_sdk/rake_tasks/provisioning_tasks'
5
+ require 'cookbook_sdk/rake_tasks/jenkins_tasks'
6
+ require 'cookbook_sdk/rake_tasks/go_tasks'
5
7
  require 'English'
6
8
 
7
9
  # Runs a shell command.
@@ -0,0 +1,56 @@
1
+ require 'cookbook_sdk/rake_tasks'
2
+ require 'json'
3
+
4
+ namespace :go do
5
+ desc 'Generate attribute json file for image creation'
6
+ task :image_attr_json do
7
+ rpm_version_file = File.join('../rpm_version')
8
+
9
+ base_dir = Dir.pwd
10
+ base_dir += '/provision' if File.directory?('provision')
11
+ attributes_file = File.join(base_dir, 'attributes.json')
12
+
13
+ version = nil
14
+ File.open(rpm_version_file, 'r') do |output|
15
+ version = output.read.strip
16
+ end
17
+
18
+ raise "'rpm_version' file should have a valid rpm version" if version.nil? || version.empty?
19
+
20
+ attributes = { 'pipeline' => { 'app_version' => version } }
21
+
22
+ File.open(attributes_file, 'w') do |f|
23
+ f.write(attributes.to_json)
24
+ end
25
+ end
26
+
27
+ desc 'Create attribute json file for cluster deployment'
28
+ task :cluster_attr_json do
29
+ begin
30
+ image_output_file = File.read('../_aws_image.output.json')
31
+ image_output = JSON.parse(image_output_file)
32
+ rescue StandardError => err
33
+ raise err
34
+ end
35
+
36
+ environment = ENV['ENVIRONMENT']
37
+ environment = 'test' if environment.nil? || environment.empty?
38
+
39
+ action = ENV['ACTION'] || nil
40
+ actions = %w(create destroy update)
41
+ raise "'ACTION' should be one of #{actions}" unless actions.include? action
42
+
43
+ attributes_file = File.join('provision', 'attributes.json')
44
+ attributes = {
45
+ 'pipeline' => {
46
+ 'ami_id' => image_output['ami_id'],
47
+ 'environment' => environment,
48
+ 'action' => action
49
+ }
50
+ }
51
+
52
+ File.open(attributes_file, 'w') do |f|
53
+ f.write(attributes.to_json)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,43 @@
1
+ require 'cookbook_sdk/rake_tasks'
2
+ require 'json'
3
+
4
+ namespace :jenkins do
5
+ desc 'Generate attribute json file for image creation'
6
+ task :pipeline_version do
7
+ attributes_file = File.join('provision', 'attributes.json')
8
+ pipeline_version = ENV['PIPELINE_VERSION']
9
+
10
+ raise '$PIPELINE_VERSION cannot be null or empty' if pipeline_version.nil? || pipeline_version.empty?
11
+
12
+ attributes = {
13
+ 'pipeline_version' => pipeline_version
14
+ }
15
+
16
+ File.open(attributes_file, 'w') do |f|
17
+ f.write(attributes.to_json)
18
+ end
19
+ end
20
+
21
+ desc 'Create attribute json file for cluster deployment'
22
+ task :attributes do
23
+ begin
24
+ image_output_file = File.read(File.join('.', '_aws_image.output.json'))
25
+ image_output = JSON.parse(image_output_file)
26
+ rescue StandardError => err
27
+ raise err
28
+ end
29
+
30
+ environment = ENV['ENVIRONMENT']
31
+ environment = 'test' if environment.nil? || environment.empty?
32
+
33
+ attributes_file = File.join('provision', 'attributes.json')
34
+ attributes = {
35
+ 'image_id' => image_output['ami_id'],
36
+ 'environment' => environment
37
+ }
38
+
39
+ File.open(attributes_file, 'w') do |f|
40
+ f.write(attributes.to_json)
41
+ end
42
+ end
43
+ end
@@ -9,14 +9,14 @@ module CookbookSDK
9
9
  base_dir = Dir.pwd
10
10
  base_dir += '/provision' if File.directory?('provision')
11
11
  TARGET_FOLDER = File.join(base_dir, '.target')
12
- SDK_CONFIGURATION = 'cookbook_sdk.json'
12
+ SDK_CONFIGURATION = 'cookbook_sdk.json'.freeze
13
13
  CUSTOM_NAMED_LIST = ENV['NAMED_RUN_LIST']
14
14
  RUN_LIST = ENV['RUN_LIST']
15
15
  DEBUG = ENV['DEBUG']
16
- BERKS = ENV['BERKS'] || false
16
+ BERKS = ENV['BERKS'] || true
17
17
 
18
18
  desc 'Prepare chef-zero environment, and run it.'
19
- task all: ['chef:prepare', 'chef:run', 'chef:clean']
19
+ task :all => ['chef:prepare', 'chef:run', 'chef:clean']
20
20
 
21
21
  namespace :chef do
22
22
  desc 'Prepare chef-zero environment to run.'
@@ -81,7 +81,7 @@ def read_configuration(configuration_file)
81
81
  end
82
82
  return nil if file.nil?
83
83
 
84
- data_hash = JSON.parse(file, symbolize_names: true)
84
+ data_hash = JSON.parse(file, :symbolize_names => true)
85
85
  data_hash
86
86
  rescue Errno::ENOENT, Errno::EACCES, JSON::ParserError => e
87
87
  puts "Problem reading #{configuration_file} - #{e}"
@@ -162,22 +162,27 @@ def run_chef_zero(target_folder, custom_named_run_list = nil, run_list = nil, de
162
162
  named_run_list = custom_named_run_list.nil? ? '' : "-n #{custom_named_run_list}"
163
163
  run_list = run_list.nil? ? '' : "-o #{run_list}"
164
164
  debug = !debug ? '' : '-l debug'
165
+ log_format = '--force-formatter'
165
166
 
166
- attributes_file = File.join(target_folder, 'attributes.json')
167
- attributes = File.exist?(attributes_file) ? '-j attributes.json' : ''
167
+ attributes_file_path = File.join(target_folder, 'attributes.json')
168
+ attributes_flag = File.exist?(attributes_file_path) ? '-j attributes.json' : ''
168
169
 
169
170
  timestamp = Time.now.to_i
170
171
  cache_pid_file = "#{target_folder}/.chef/cache/chef-client-running_#{timestamp}.pid"
171
172
  lockfile = "--lockfile=#{cache_pid_file}"
172
173
 
173
174
  cmd = 'chef exec chef-client -c custom_client.rb -z '
174
- cmd += "#{named_run_list} #{run_list} #{debug} #{attributes} #{lockfile}"
175
+ cmd += "#{named_run_list} #{run_list} #{debug} #{attributes_flag} #{lockfile} #{log_format}"
175
176
 
176
- banner("Running '#{cmd}' inside folder '#{target_folder}' ...")
177
+ if attributes_flag != ''
178
+ file = File.read(attributes_file_path)
179
+ data_hash = JSON.pretty_generate(JSON.parse(file))
177
180
 
178
- Dir.chdir target_folder do
179
- run_command(cmd, true)
181
+ banner('Attributes are:')
182
+ banner(data_hash)
180
183
  end
184
+
185
+ _run_command(cmd, target_folder)
181
186
  end
182
187
 
183
188
  def clean(target_folder)
@@ -5,7 +5,7 @@ module CookbookSdk
5
5
  extend Rake::DSL
6
6
 
7
7
  desc 'Run all fast tests.'
8
- task test: ['test:foodcritic', 'test:rubocop', 'test:rspec']
8
+ task :test => ['test:foodcritic', 'test:rubocop', 'test:rspec']
9
9
 
10
10
  namespace :test do
11
11
  desc 'Runs Foodcritic linting'
@@ -24,7 +24,7 @@ module CookbookSdk
24
24
  end
25
25
 
26
26
  ### Continous Integration
27
- desc 'Runs all tests to be run in a CI environment'
27
+ desc 'Runs all tests when run in a CI environment'
28
28
  task :ci do
29
29
  error = false
30
30
  error = foodcritic(false) || error
@@ -44,8 +44,8 @@ def foodcritic(exit_on_error = true)
44
44
  end
45
45
 
46
46
  def rspec(exit_on_error = true)
47
- files = FileList[File.join(Dir.pwd, 'spec', 'unit', '**/*_spec.rb')]
48
- cmd = "chef exec rspec #{files}"
47
+ files = FileList[File.join(Dir.pwd, 'test', 'unit', '**/test_*.rb')]
48
+ cmd = "chef exec rspec #{files} --format doc"
49
49
  banner("Running '#{cmd}' ...")
50
50
  run_command(cmd, exit_on_error)
51
51
  end
@@ -1,4 +1,4 @@
1
1
  # Define gem version
2
2
  module CookbookSDK
3
- VERSION = '1.2.0'
3
+ VERSION = '2.0.0'.freeze
4
4
  end
@@ -0,0 +1,249 @@
1
+ require_relative '../helpers'
2
+
3
+ require 'webmock/rspec'
4
+ require 'cookbook_sdk/handlers/slack'
5
+
6
+ WebMock.disable_net_connect!(:allow_localhost => true)
7
+
8
+ describe Chef::Handler::Slack do
9
+ let(:node) do
10
+ node = Chef::Node.new
11
+ node.name('test')
12
+ node.run_list('recipe[fake_cookbook::fake_recipe]')
13
+ node
14
+ end
15
+
16
+ let(:url) do
17
+ "https://hooks.slack.com/services/#{config[:token]}"
18
+ end
19
+
20
+ let(:config) do
21
+ {
22
+ :token => 'fake_token',
23
+ :channel => '#fake_channel',
24
+ :username => 'fake_user',
25
+ :on_start => true,
26
+ :on_success => true,
27
+ :on_failure => true
28
+ }
29
+ end
30
+
31
+ before do
32
+ Chef::Handler::Slack.any_instance.stubs(:node).returns(node)
33
+ end
34
+
35
+ it 'should read the configuration options on initialization' do
36
+ @slack_handler = Chef::Handler::Slack.new(config)
37
+ expect(@slack_handler.token).to eq(config[:token])
38
+ expect(@slack_handler.channel).to eq(config[:channel])
39
+ expect(@slack_handler.username).to eq(config[:username])
40
+ expect(@slack_handler.on_start).to eq(config[:on_start])
41
+ expect(@slack_handler.on_success).to eq(config[:on_success])
42
+ expect(@slack_handler.on_failure).to eq(config[:on_failure])
43
+ end
44
+
45
+ it 'should set configuration defaults when not provide on initialization' do
46
+ @slack_handler = Chef::Handler::Slack.new(:token => 'fake_token')
47
+ expect(@slack_handler.token).to eq('fake_token')
48
+ expect(@slack_handler.channel).to eq('#chef')
49
+ expect(@slack_handler.username).to eq('Chef')
50
+ expect(@slack_handler.on_start).to eq(true)
51
+ expect(@slack_handler.on_success).to eq(true)
52
+ expect(@slack_handler.on_failure).to eq(true)
53
+ end
54
+
55
+ it 'should throw an exception when the slack token is not provided on initialization' do
56
+ expect { Chef::Handler::Slack.new({}) }.to raise_error(ChefConfig::ConfigurationError)
57
+ end
58
+
59
+ describe '#report' do
60
+ before do
61
+ @slack_handler = Chef::Handler::Slack.new(config)
62
+ @run_status = Chef::RunStatus.new(node, {})
63
+ end
64
+
65
+ describe 'when chef run is not over' do
66
+ before do
67
+ @run_status.start_clock
68
+ end
69
+
70
+ it 'should call report_start function at start of the run' do
71
+ @slack_handler.stubs(:report_start)
72
+
73
+ expect(@slack_handler).to receive(:report_start)
74
+ expect(@slack_handler).not_to receive(:report_success)
75
+ expect(@slack_handler).not_to receive(:report_failure)
76
+
77
+ @slack_handler.run_report_unsafe(@run_status)
78
+ end
79
+
80
+ it 'should skip the sending of the starting message when on_start option is false' do
81
+ new_config = config
82
+ new_config[:on_start] = false
83
+ @slack_handler = Chef::Handler::Slack.new(new_config)
84
+ expect(Chef::Log).to receive(:debug).with("Slack 'start' handler is not active.")
85
+ expect(@slack_handler).not_to receive(:send_attachment)
86
+ expect(@slack_handler).not_to receive(:send_slack_message)
87
+
88
+ @slack_handler.run_report_unsafe(@run_status)
89
+ end
90
+
91
+ it 'should send the starting message when on_start option is true' do
92
+ stub_request(:post, url).to_return(:status => 200, :headers => {})
93
+
94
+ expect(@slack_handler).not_to receive(:exit_without_sending)
95
+ expect(Chef::Log).to receive(:debug).with("Slack handler sent a message to channel '#{config[:channel]}'")
96
+
97
+ @slack_handler.run_report_unsafe(@run_status)
98
+
99
+ payload = {
100
+ :username => config[:username],
101
+ :channel => config[:channel],
102
+ :token => config[:token],
103
+ :color => nil,
104
+ :attachments => [{
105
+ :pretext => 'Run at test',
106
+ :title => 'Chef run started!',
107
+ :title_link => nil,
108
+ :color => nil,
109
+ :text => "Will run #{node.run_list}",
110
+ :fallback => "Chef run started! test will run #{node.run_list}."
111
+ }]
112
+ }
113
+ expect(WebMock).to have_requested(:post, url).with(:body => { :payload => payload.to_json })
114
+ end
115
+ end
116
+
117
+ describe 'when chef is over' do
118
+ before do
119
+ @run_status.start_clock
120
+ @run_status.stop_clock
121
+ end
122
+
123
+ describe 'and run successfully' do
124
+ it 'should call report_success function at end of the run' do
125
+ expect(@slack_handler).not_to receive(:report_start)
126
+ expect(@slack_handler).to receive(:report_success)
127
+ expect(@slack_handler).not_to receive(:report_failure)
128
+
129
+ @slack_handler.run_report_unsafe(@run_status)
130
+ end
131
+
132
+ it 'should skip the sending of the success message when on_success option is false' do
133
+ new_config = config
134
+ new_config[:on_success] = false
135
+ @slack_handler = Chef::Handler::Slack.new(new_config)
136
+ expect(Chef::Log).to receive(:debug).with("Slack 'success' handler is not active.")
137
+ expect(@slack_handler).not_to receive(:send_attachment)
138
+ expect(@slack_handler).not_to receive(:send_slack_message)
139
+
140
+ @slack_handler.run_report_unsafe(@run_status)
141
+ end
142
+
143
+ it 'should send the success message when on_success option is true' do
144
+ stub_request(:post, url).to_return(:status => 200)
145
+
146
+ expect(@slack_handler).not_to receive(:exit_without_sending)
147
+ expect(Chef::Log).to receive(:debug).with("Slack handler sent a message to channel '#{config[:channel]}'")
148
+
149
+ @slack_handler.run_report_unsafe(@run_status)
150
+ payload = {
151
+ :username => config[:username],
152
+ :channel => config[:channel],
153
+ :token => config[:token],
154
+ :color => 'good',
155
+ :attachments => [{
156
+ :pretext => 'Run at test',
157
+ :title => 'Chef run successfully!',
158
+ :title_link => nil,
159
+ :color => 'good',
160
+ :text => "Just run #{node.run_list} successfully in #{@run_status.elapsed_time} seconds.",
161
+ :fallback => "Chef run successfully! test run #{node.run_list} successfully "\
162
+ "in #{@run_status.elapsed_time.to_i} seconds."
163
+ }]
164
+ }
165
+ expect(WebMock).to have_requested(:post, url).with(:body => { :payload => payload.to_json })
166
+ end
167
+ end
168
+
169
+ describe 'and failed' do
170
+ before do
171
+ @run_status.start_clock
172
+ @run_status.stop_clock
173
+ @run_status.exception = ChefConfig::ConfigurationError.new('A fake error.')
174
+ end
175
+
176
+ it 'should call report_failed function at end of the run' do
177
+ expect(@slack_handler).not_to receive(:report_start)
178
+ expect(@slack_handler).not_to receive(:report_success)
179
+ expect(@slack_handler).to receive(:report_failure)
180
+
181
+ @slack_handler.run_report_unsafe(@run_status)
182
+ end
183
+
184
+ it 'should skip the sending of the failed message when on_failure option is false' do
185
+ new_config = config
186
+ new_config[:on_failure] = false
187
+ @slack_handler = Chef::Handler::Slack.new(new_config)
188
+ expect(Chef::Log).to receive(:debug).with("Slack 'failure' handler is not active.")
189
+ expect(@slack_handler).not_to receive(:send_attachment)
190
+ expect(@slack_handler).not_to receive(:send_slack_message)
191
+
192
+ @slack_handler.run_report_unsafe(@run_status)
193
+ end
194
+
195
+ it 'should send the failure message when on_failure option is true' do
196
+ stub_request(:post, url).to_return(:status => 200, :headers => {})
197
+
198
+ expect(@slack_handler).not_to receive(:exit_without_sending)
199
+ expect(Chef::Log).to receive(:debug)
200
+ .with("Slack handler sent a message to channel '#{config[:channel]}'").twice
201
+
202
+ @slack_handler.run_report_unsafe(@run_status)
203
+
204
+ # Message as attachment
205
+ payload = {
206
+ :username => config[:username],
207
+ :channel => config[:channel],
208
+ :token => config[:token],
209
+ :color => 'danger',
210
+ :attachments => [{
211
+ :pretext => 'Run at test',
212
+ :title => 'Chef run FAILED!',
213
+ :title_link => nil,
214
+ :color => 'danger',
215
+ :text => "Running #{node.run_list} failed in #{@run_status.elapsed_time} seconds.",
216
+ :fallback => "Chef FAILED! #{@run_status.node.name} failed to run #{node.run_list}" \
217
+ " in #{@run_status.elapsed_time.to_i} seconds."
218
+ }]
219
+ }
220
+ expect(WebMock).to have_requested(:post, url).with(:body => { :payload => payload.to_json })
221
+
222
+ # Exception
223
+ payload = {
224
+ :username => config[:username],
225
+ :channel => config[:channel],
226
+ :token => config[:token],
227
+ :text => '```ChefConfig::ConfigurationError: A fake error.```'
228
+ }
229
+ expect(WebMock).to have_requested(:post, url).with(:body => { :payload => payload.to_json })
230
+ end
231
+ end
232
+ end
233
+
234
+ describe 'when tries to send an http request but it fails' do
235
+ it 'should log a error when receive a http response different than 200 OK' do
236
+ stub_request(:post, url).to_return(:status => 400)
237
+ expect(Chef::Log).to receive(:error).with('We got an error while posting a message to Slack: 400 - ')
238
+ @slack_handler.run_report_unsafe(@run_status)
239
+ end
240
+
241
+ it 'should log a error when got any exception related with the request' do
242
+ stub_request(:post, url).to_return(:should_timeout => true)
243
+ expect(Chef::Log).to receive(:error)
244
+ .with('An unhandled exception occurred while posting a message to Slack: execution expired')
245
+ @slack_handler.run_report_unsafe(@run_status)
246
+ end
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,9 @@
1
+ require 'simplecov'
2
+ if ENV['TRAVIS']
3
+ require 'coveralls'
4
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
5
+ end
6
+ SimpleCov.start
7
+
8
+ require 'minitest'
9
+ require 'mocha/mini_test'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cookbook_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mindera
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-18 00:00:00.000000000 Z
11
+ date: 2016-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -44,24 +44,90 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.6'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 1.6.9
47
+ version: 1.7.8
51
48
  type: :runtime
52
49
  prerelease: false
53
50
  version_requirements: !ruby/object:Gem::Requirement
54
51
  requirements:
55
52
  - - "~>"
56
53
  - !ruby/object:Gem::Version
57
- version: '1.6'
54
+ version: 1.7.8
55
+ - !ruby/object:Gem::Dependency
56
+ name: chef
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mocha
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: coveralls
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
58
122
  - - ">="
59
123
  - !ruby/object:Gem::Version
60
- version: 1.6.9
124
+ version: '0'
61
125
  description: |
62
126
  # cookbook_sdk
63
127
 
128
+ [![Gem Version](https://badge.fury.io/rb/cookbook_sdk.svg)](https://badge.fury.io/rb/cookbook_sdk)
64
129
  [![Build Status](https://travis-ci.org/Mindera/cookbook_sdk.svg?branch=master)](https://travis-ci.org/Mindera/cookbook_sdk)
130
+ [![Coverage Status](https://coveralls.io/repos/Mindera/cookbook_sdk/badge.svg?branch=master&service=github)](https://coveralls.io/github/Mindera/cookbook_sdk?branch=master)
65
131
 
66
132
  Helpers for chef cookbook development and provisioning.
67
133
  email:
@@ -81,11 +147,15 @@ files:
81
147
  - lib/cookbook_sdk/ext/string.rb
82
148
  - lib/cookbook_sdk/handlers/slack.rb
83
149
  - lib/cookbook_sdk/rake_tasks.rb
150
+ - lib/cookbook_sdk/rake_tasks/go_tasks.rb
84
151
  - lib/cookbook_sdk/rake_tasks/helper_tasks.rb
152
+ - lib/cookbook_sdk/rake_tasks/jenkins_tasks.rb
85
153
  - lib/cookbook_sdk/rake_tasks/provisioning_tasks.rb
86
154
  - lib/cookbook_sdk/rake_tasks/test_tasks.rb
87
155
  - lib/cookbook_sdk/version.rb
88
156
  - lib/foodcritic/rules/etsy.rb
157
+ - test/unit/handlers/test_slack.rb
158
+ - test/unit/helpers.rb
89
159
  homepage: https://github.com/mindera/cookbook_sdk
90
160
  licenses:
91
161
  - MIT
@@ -106,9 +176,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
176
  version: '0'
107
177
  requirements: []
108
178
  rubyforge_project:
109
- rubygems_version: 2.4.8
179
+ rubygems_version: 2.5.2
110
180
  signing_key:
111
181
  specification_version: 4
112
182
  summary: cookbook sdk
113
- test_files: []
183
+ test_files:
184
+ - test/unit/handlers/test_slack.rb
185
+ - test/unit/helpers.rb
114
186
  has_rdoc: