cookbook_sdk 1.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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +16 -0
- data/.travis.yml +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +5 -0
- data/Rakefile +2 -0
- data/cookbook_sdk.gemspec +25 -0
- data/lib/cookbook_sdk/ext/string.rb +20 -0
- data/lib/cookbook_sdk/handlers/slack.rb +122 -0
- data/lib/cookbook_sdk/rake_tasks/helper_tasks.rb +49 -0
- data/lib/cookbook_sdk/rake_tasks/provisioning_tasks.rb +187 -0
- data/lib/cookbook_sdk/rake_tasks/test_tasks.rb +57 -0
- data/lib/cookbook_sdk/rake_tasks.rb +25 -0
- data/lib/cookbook_sdk/version.rb +4 -0
- data/lib/foodcritic/rules/etsy.rb +47 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3c80a28ba6401d141a2ca1bea0df40521ae9b69f
|
4
|
+
data.tar.gz: de10b825bfd323009a9ef816bda208d895d3713d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 320961d47ae94f7a36e6b42a88d048f5b93310eaa79464e2f707275c5d6ad7c0533bc1b3f26867e15332b4ca1a727172c70d55725286d5d62aeb20be7c151559
|
7
|
+
data.tar.gz: 061e1e29a110d101241289c3c0ca6dbf82d4242322ddde86bb2d32d50051f666950042d8bcde9789305b7c3cbe1857c0fe8eca48f72b7e4ee52385b43576df38
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
sudo: false
|
2
|
+
language: ruby
|
3
|
+
addons:
|
4
|
+
apt:
|
5
|
+
sources:
|
6
|
+
- chef-current-precise
|
7
|
+
packages:
|
8
|
+
- chefdk
|
9
|
+
rvm:
|
10
|
+
- 2.1.6
|
11
|
+
before_script:
|
12
|
+
- eval "$(/opt/chefdk/bin/chef shell-init bash)"
|
13
|
+
script:
|
14
|
+
- /opt/chefdk/embedded/bin/chef --version
|
15
|
+
- /opt/chefdk/embedded/bin/rubocop --version
|
16
|
+
- /opt/chefdk/embedded/bin/foodcritic --version
|
17
|
+
- chef exec bundle exec rake install
|
18
|
+
- chef exec rake test:rubocop
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2015 Mindera
|
2
|
+
|
3
|
+
MIT License
|
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 deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
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 FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cookbook_sdk/version'
|
5
|
+
require 'English'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'cookbook_sdk'
|
9
|
+
spec.version = CookbookSDK::VERSION
|
10
|
+
spec.authors = ['Mindera']
|
11
|
+
spec.email = ['social@mindera.com']
|
12
|
+
spec.summary = 'cookbook sdk'
|
13
|
+
spec.description = IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
14
|
+
spec.homepage = 'https://github.com/mindera/cookbook_sdk'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_dependency 'bundler', '~> 1.9'
|
23
|
+
spec.add_dependency 'rake', '~> 10.4'
|
24
|
+
spec.add_dependency 'highline', '~> 1.6', '>= 1.6.9'
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'highline'
|
2
|
+
|
3
|
+
# Extend String Class
|
4
|
+
class String
|
5
|
+
def bold
|
6
|
+
colorize(:bold)
|
7
|
+
end
|
8
|
+
|
9
|
+
def gray
|
10
|
+
colorize(:gray)
|
11
|
+
end
|
12
|
+
|
13
|
+
def cyan
|
14
|
+
colorize(:cyan)
|
15
|
+
end
|
16
|
+
|
17
|
+
def colorize(color)
|
18
|
+
HighLine.new.color(self, color)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'chef/handler'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
class Chef
|
7
|
+
class Handler
|
8
|
+
# Slack Handler goal is send messages to a Slack channel with Chef run status.
|
9
|
+
# It can be used as a start, failure or success handler.
|
10
|
+
class Slack < Chef::Handler
|
11
|
+
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]
|
18
|
+
end
|
19
|
+
|
20
|
+
def report
|
21
|
+
options = {}
|
22
|
+
options[:pretext] = "Run at #{run_status.node.name}"
|
23
|
+
|
24
|
+
if !run_status.is_a?(Chef::RunStatus) || elapsed_time.nil?
|
25
|
+
report_start(options)
|
26
|
+
elsif run_status.success?
|
27
|
+
report_success(options)
|
28
|
+
else
|
29
|
+
report_failure(options)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def report_start(options)
|
34
|
+
return exit_without_sending('start') unless @on_start
|
35
|
+
options[:title] = 'Chef run started!'
|
36
|
+
options[:body] = "Will run #{node.run_list}"
|
37
|
+
options[:fallback] = "Chef run started! #{run_status.node.name} will run #{node.run_list}."
|
38
|
+
send_attachment(options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def report_success(options)
|
42
|
+
return exit_without_sending('success') unless @on_success
|
43
|
+
options[:title] = 'Chef run successfully!'
|
44
|
+
options[:color] = 'good'
|
45
|
+
options[:body] = "Just run #{node.run_list} successfully in #{run_status.elapsed_time} seconds."
|
46
|
+
options[:fallback] = "Chef run successfully! #{run_status.node.name} run #{node.run_list} successfully"\
|
47
|
+
" in #{run_status.elapsed_time.to_i} seconds."
|
48
|
+
send_attachment(options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def report_failure(options)
|
52
|
+
return exit_without_sending('failure') unless @on_failure
|
53
|
+
|
54
|
+
options[:title] = 'Chef FAILED!'
|
55
|
+
options[:color] = 'danger'
|
56
|
+
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}." \
|
58
|
+
" in #{run_status.elapsed_time.to_i} seconds."
|
59
|
+
send_attachment(options)
|
60
|
+
|
61
|
+
return if run_status.exception.nil?
|
62
|
+
|
63
|
+
text = '```' + run_status.formatted_exception.encode(
|
64
|
+
'UTF-8',
|
65
|
+
invalid: 'replace', undef: 'replace', replace: '?'
|
66
|
+
) + '```'
|
67
|
+
options[:text] = text
|
68
|
+
send_text(options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def send_attachment(options)
|
72
|
+
fail 'No message defined to be send to slack' if options[:body].nil?
|
73
|
+
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]
|
82
|
+
}]
|
83
|
+
}
|
84
|
+
send_slack_message(params)
|
85
|
+
end
|
86
|
+
|
87
|
+
def exit_without_sending(handler_type)
|
88
|
+
Chef::Log.debug("Slack '#{handler_type}' handler is not active.")
|
89
|
+
end
|
90
|
+
|
91
|
+
def send_text(options)
|
92
|
+
fail 'No message defined to be send to slack' if options[:text].nil?
|
93
|
+
params = {
|
94
|
+
text: options[:text]
|
95
|
+
}
|
96
|
+
send_slack_message(params)
|
97
|
+
end
|
98
|
+
|
99
|
+
def send_slack_message(specif_params)
|
100
|
+
params = { username: @username, channel: @channel, token: @token }.merge(specif_params)
|
101
|
+
|
102
|
+
uri = URI("https://hooks.slack.com/services/#{@token}")
|
103
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
104
|
+
http.use_ssl = true
|
105
|
+
|
106
|
+
begin
|
107
|
+
req = Net::HTTP::Post.new("#{uri.path}?#{uri.query}")
|
108
|
+
req.set_form_data(payload: params.to_json)
|
109
|
+
res = http.request(req)
|
110
|
+
if res.code != '200'
|
111
|
+
Chef::Log.error("We got an error while posting a message to Slack: #{res.code} - #{res.msg}")
|
112
|
+
else
|
113
|
+
Chef::Log.debug("Slack handler sent a message to channel '#{params[:channel]}'")
|
114
|
+
end
|
115
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
116
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
117
|
+
Chef::Log.error("An unhandled exception occurred while posting a message to Slack: #{e}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
namespace :help do
|
3
|
+
desc 'Help about how to bump your cookbook.'
|
4
|
+
task :bump do
|
5
|
+
help_bump
|
6
|
+
end
|
7
|
+
|
8
|
+
desc 'Help about how to bump your cookbook.'
|
9
|
+
task :kitchen do
|
10
|
+
help_kitchen
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def help_bump
|
15
|
+
title = 'Help: Bumping cookbooks'.gray.bold
|
16
|
+
body = <<BODY
|
17
|
+
|
18
|
+
To bump your cookbook run the following command:
|
19
|
+
chef exec knife spork bump -z
|
20
|
+
|
21
|
+
Note: -z stands for local mode (chef-zero)
|
22
|
+
For more about 'knife spork' go to: http://jonlives.github.io/knife-spork/
|
23
|
+
|
24
|
+
BODY
|
25
|
+
|
26
|
+
output_help(title, body)
|
27
|
+
end
|
28
|
+
|
29
|
+
def help_kitchen
|
30
|
+
title = 'Help: Test Kitchen'.gray.bold
|
31
|
+
body = <<BODY
|
32
|
+
|
33
|
+
Test kitchen is an awsome testing tool. It enables you to test your cookbook against
|
34
|
+
some virtual machine, container, or an instance in several cloud virtualization tecnologies.
|
35
|
+
|
36
|
+
Run rhe folling command to have the real kitchen help
|
37
|
+
chef exec knife --help
|
38
|
+
|
39
|
+
Note: You don't get nothing when run chef-provisioning cookbooks with kitchen.
|
40
|
+
For more about 'kitchen' go to: http://kitchen.ci/
|
41
|
+
BODY
|
42
|
+
|
43
|
+
output_help(title, body)
|
44
|
+
end
|
45
|
+
|
46
|
+
def output_help(title, body)
|
47
|
+
puts title
|
48
|
+
puts body
|
49
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module CookbookSDK
|
5
|
+
# Provisioning Tasks
|
6
|
+
module Raketasks
|
7
|
+
extend Rake::DSL
|
8
|
+
|
9
|
+
base_dir = Dir.pwd
|
10
|
+
base_dir += '/provision' if File.directory?('provision')
|
11
|
+
TARGET_FOLDER = File.join(base_dir, '.target')
|
12
|
+
SDK_CONFIGURATION = 'cookbook_sdk.json'
|
13
|
+
CUSTOM_NAMED_LIST = ENV['NAMED_RUN_LIST']
|
14
|
+
RUN_LIST = ENV['RUN_LIST']
|
15
|
+
DEBUG = ENV['DEBUG']
|
16
|
+
BERKS = ENV['BERKS'] || false
|
17
|
+
|
18
|
+
desc 'Prepare chef-zero environment, and run it.'
|
19
|
+
task all: ['chef:prepare', 'chef:run', 'chef:clean']
|
20
|
+
|
21
|
+
namespace :chef do
|
22
|
+
desc 'Prepare chef-zero environment to run.'
|
23
|
+
task :prepare do
|
24
|
+
clean(TARGET_FOLDER)
|
25
|
+
if BERKS
|
26
|
+
berks_update(base_dir)
|
27
|
+
berks_vendor(base_dir, TARGET_FOLDER)
|
28
|
+
else
|
29
|
+
chefdk_update(base_dir)
|
30
|
+
chefdk_export(base_dir, TARGET_FOLDER)
|
31
|
+
end
|
32
|
+
copy_attributes_file(base_dir, TARGET_FOLDER)
|
33
|
+
copy_data_bags(base_dir, TARGET_FOLDER)
|
34
|
+
create_custom_client_rb(TARGET_FOLDER, SDK_CONFIGURATION, !BERKS)
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Run chef-zero in a pre prepared environment.'
|
38
|
+
task :run do
|
39
|
+
run_chef_zero(TARGET_FOLDER, CUSTOM_NAMED_LIST, RUN_LIST, DEBUG)
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Clean generated folder'
|
43
|
+
task :clean do
|
44
|
+
clean(TARGET_FOLDER)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def _run_command(cmd, base_dir)
|
51
|
+
banner("Running '#{cmd}' in #{base_dir}...")
|
52
|
+
Dir.chdir base_dir do
|
53
|
+
run_command(cmd, true)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def berks_update(base_dir)
|
58
|
+
_run_command('berks install', base_dir)
|
59
|
+
_run_command('berks update', base_dir)
|
60
|
+
end
|
61
|
+
|
62
|
+
def berks_vendor(base_dir, target_folder)
|
63
|
+
_run_command("berks vendor #{target_folder}/cookbooks", base_dir)
|
64
|
+
end
|
65
|
+
|
66
|
+
def chefdk_update(base_dir)
|
67
|
+
_run_command('chef update', base_dir)
|
68
|
+
end
|
69
|
+
|
70
|
+
def chefdk_export(base_dir, target_folder)
|
71
|
+
_run_command("chef export #{target_folder} --force", base_dir)
|
72
|
+
end
|
73
|
+
|
74
|
+
def read_configuration(configuration_file)
|
75
|
+
file = nil
|
76
|
+
|
77
|
+
if File.exist?(configuration_file)
|
78
|
+
file = File.read(configuration_file)
|
79
|
+
elsif File.exist?("../#{configuration_file}")
|
80
|
+
file = File.read(configuration_file)
|
81
|
+
end
|
82
|
+
return nil if file.nil?
|
83
|
+
|
84
|
+
data_hash = JSON.parse(file, symbolize_names: true)
|
85
|
+
data_hash
|
86
|
+
rescue Errno::ENOENT, Errno::EACCES, JSON::ParserError => e
|
87
|
+
puts "Problem reading #{configuration_file} - #{e}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def prepare_handlers(handlers)
|
91
|
+
config_rb = ''
|
92
|
+
|
93
|
+
handlers[:enabled].each do |enabled_handler|
|
94
|
+
handler_config = handlers[:config][enabled_handler.to_sym]
|
95
|
+
config_rb += %(
|
96
|
+
|
97
|
+
# #{enabled_handler} handler configuration
|
98
|
+
require 'cookbook_sdk/handlers/#{enabled_handler}'
|
99
|
+
#{enabled_handler}_handler_options = #{handler_config}
|
100
|
+
#{enabled_handler}_handler = Chef::Handler::Slack.new(#{enabled_handler}_handler_options)
|
101
|
+
start_handlers << #{enabled_handler}_handler
|
102
|
+
report_handlers << #{enabled_handler}_handler
|
103
|
+
exception_handlers << #{enabled_handler}_handler
|
104
|
+
|
105
|
+
)
|
106
|
+
end
|
107
|
+
config_rb
|
108
|
+
end
|
109
|
+
|
110
|
+
def cache_path_config(target_folder)
|
111
|
+
%(
|
112
|
+
# To enable chef-client without sudo.
|
113
|
+
# https://docs.chef.io/ctl_chef_client.html#run-as-non-root-user
|
114
|
+
cache_path "#{target_folder}/.chef"
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
def create_custom_client_rb(target_folder, configuration_file, copy_original)
|
119
|
+
banner("Creating custom 'client.rb' in #{target_folder} ...")
|
120
|
+
original_client_rb = File.join(target_folder, 'client.rb')
|
121
|
+
custom_client_rb = File.join(target_folder, 'custom_client.rb')
|
122
|
+
|
123
|
+
config = read_configuration(configuration_file)
|
124
|
+
|
125
|
+
begin
|
126
|
+
FileUtils.copy_file(original_client_rb, custom_client_rb) if copy_original
|
127
|
+
open_mode = copy_original ? 'a' : 'w'
|
128
|
+
|
129
|
+
File.open(custom_client_rb, open_mode) do |output|
|
130
|
+
output.write(cache_path_config(target_folder))
|
131
|
+
|
132
|
+
if config.nil?
|
133
|
+
puts 'No configuration file found: custom_client.rb will not have any user custom configuration.'
|
134
|
+
else
|
135
|
+
output.write(prepare_handlers(config[:handlers]))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
rescue Errno::EACCES => e
|
139
|
+
puts "Problem creating #{custom_client_rb} - #{e}"
|
140
|
+
end
|
141
|
+
|
142
|
+
puts "Writed a custom client.rb to '#{custom_client_rb}"
|
143
|
+
end
|
144
|
+
|
145
|
+
def copy_data_bags(base_dir, target_folder)
|
146
|
+
data_bags_directory = File.join(base_dir, 'data_bags')
|
147
|
+
return unless File.directory?(data_bags_directory)
|
148
|
+
|
149
|
+
banner("Copying data_bags folder from #{data_bags_directory} to #{target_folder}...")
|
150
|
+
FileUtils.cp_r(data_bags_directory, target_folder)
|
151
|
+
end
|
152
|
+
|
153
|
+
def copy_attributes_file(base_dir, target_folder)
|
154
|
+
attributes_file = File.join(base_dir, 'attributes.json')
|
155
|
+
return unless File.exist?(attributes_file)
|
156
|
+
|
157
|
+
banner("Copying attributes file from #{attributes_file} to #{target_folder}...")
|
158
|
+
FileUtils.cp_r(attributes_file, target_folder)
|
159
|
+
end
|
160
|
+
|
161
|
+
def run_chef_zero(target_folder, custom_named_run_list = nil, run_list = nil, debug = false)
|
162
|
+
named_run_list = custom_named_run_list.nil? ? '' : "-n #{custom_named_run_list}"
|
163
|
+
run_list = run_list.nil? ? '' : "-o #{run_list}"
|
164
|
+
debug = !debug ? '' : '-l debug'
|
165
|
+
|
166
|
+
attributes_file = File.join(target_folder, 'attributes.json')
|
167
|
+
attributes = File.exist?(attributes_file) ? '-j attributes.json' : ''
|
168
|
+
|
169
|
+
timestamp = Time.now.to_i
|
170
|
+
cache_pid_file = "#{target_folder}/.chef/cache/chef-client-running_#{timestamp}.pid"
|
171
|
+
lockfile = "--lockfile=#{cache_pid_file}"
|
172
|
+
|
173
|
+
cmd = 'chef exec chef-client -c custom_client.rb -z '
|
174
|
+
cmd += "#{named_run_list} #{run_list} #{debug} #{attributes} #{lockfile}"
|
175
|
+
|
176
|
+
banner("Running '#{cmd}' inside folder '#{target_folder}' ...")
|
177
|
+
|
178
|
+
Dir.chdir target_folder do
|
179
|
+
run_command(cmd, true)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def clean(target_folder)
|
184
|
+
cmd = "rm -rf #{target_folder}/cookbooks"
|
185
|
+
banner("Cleanning up the cookbooks cache folder with '#{cmd}' ...")
|
186
|
+
run_command(cmd, true)
|
187
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
module CookbookSdk
|
3
|
+
# Test Tasks
|
4
|
+
module Raketasks
|
5
|
+
extend Rake::DSL
|
6
|
+
|
7
|
+
desc 'Run all fast tests.'
|
8
|
+
task test: ['test:foodcritic', 'test:rubocop', 'test:rspec']
|
9
|
+
|
10
|
+
namespace :test do
|
11
|
+
desc 'Runs Foodcritic linting'
|
12
|
+
task :foodcritic do
|
13
|
+
foodcritic
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Runs unit tests'
|
17
|
+
task :rspec do
|
18
|
+
rspec
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Runs unit tests'
|
22
|
+
task :rubocop do
|
23
|
+
rubocop
|
24
|
+
end
|
25
|
+
|
26
|
+
### Continous Integration
|
27
|
+
desc 'Runs all tests to be run in a CI environment'
|
28
|
+
task :ci do
|
29
|
+
error = false
|
30
|
+
error = foodcritic(false) || error
|
31
|
+
error = rubocop(false) || error
|
32
|
+
error = rspec(false) || error
|
33
|
+
exit error ? 1 : 0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def foodcritic(exit_on_error = true)
|
40
|
+
foodcritic_rules = File.join(File.dirname(__FILE__), '../../foodcritic/rules')
|
41
|
+
cmd = "chef exec foodcritic -f any -P --include #{foodcritic_rules} ."
|
42
|
+
banner("Running '#{cmd}' ...")
|
43
|
+
run_command(cmd, exit_on_error)
|
44
|
+
end
|
45
|
+
|
46
|
+
def rspec(exit_on_error = true)
|
47
|
+
files = FileList[File.join(Dir.pwd, 'spec', 'unit', '**/*_spec.rb')]
|
48
|
+
cmd = "chef exec rspec #{files}"
|
49
|
+
banner("Running '#{cmd}' ...")
|
50
|
+
run_command(cmd, exit_on_error)
|
51
|
+
end
|
52
|
+
|
53
|
+
def rubocop(exit_on_error = true)
|
54
|
+
cmd = 'chef exec rubocop'
|
55
|
+
banner("Running '#{cmd}' ...")
|
56
|
+
run_command(cmd, exit_on_error)
|
57
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cookbook_sdk/ext/string'
|
2
|
+
require 'cookbook_sdk/rake_tasks/test_tasks'
|
3
|
+
require 'cookbook_sdk/rake_tasks/helper_tasks'
|
4
|
+
require 'cookbook_sdk/rake_tasks/provisioning_tasks'
|
5
|
+
require 'English'
|
6
|
+
|
7
|
+
# Runs a shell command.
|
8
|
+
# If all good, return false.
|
9
|
+
# If error, return true.
|
10
|
+
# If error and exit_on_error, exit with the error code.
|
11
|
+
def run_command(cmd, exit_on_error = false)
|
12
|
+
Bundler.with_clean_env do
|
13
|
+
system(cmd)
|
14
|
+
status = $CHILD_STATUS.exitstatus
|
15
|
+
|
16
|
+
return false unless status != 0
|
17
|
+
return true unless exit_on_error
|
18
|
+
exit status
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def banner(text)
|
23
|
+
puts
|
24
|
+
puts text.cyan
|
25
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Etsy foodcritic rules
|
2
|
+
# Source: https://github.com/etsy/foodcritic-rules
|
3
|
+
|
4
|
+
@coreservicepackages = ["httpd", "node", "java", "nginx"]
|
5
|
+
@corecommands = ["yum -y", "yum install", "yum reinstall", "yum remove", "mkdir", "useradd", "usermod", "touch"]
|
6
|
+
|
7
|
+
rule "ETSY001", "Package or yum_package resource used with :upgrade action" do
|
8
|
+
tags %w{correctness recipe etsy}
|
9
|
+
recipe do | ast|
|
10
|
+
pres = find_resources(ast, :type => 'package').find_all do |cmd|
|
11
|
+
cmd_str = (resource_attribute(cmd, 'action') || resource_name(cmd)).to_s
|
12
|
+
cmd_str.include?('upgrade')
|
13
|
+
end
|
14
|
+
ypres = find_resources(ast, :type => 'yum_package').find_all do |cmd|
|
15
|
+
cmd_str = (resource_attribute(cmd, 'action') || resource_name(cmd)).to_s
|
16
|
+
cmd_str.include?('upgrade')
|
17
|
+
end
|
18
|
+
pres.concat(ypres).map{|cmd| match(cmd)}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
rule "ETSY006", "Execute resource used to run chef-provided command" do
|
23
|
+
tags %w{style recipe etsy}
|
24
|
+
recipe do |ast|
|
25
|
+
find_resources(ast, :type => 'execute').find_all do |cmd|
|
26
|
+
cmd_str = (resource_attribute(cmd, 'command') || resource_name(cmd)).to_s
|
27
|
+
@corecommands.any? { |corecommand| cmd_str.include? corecommand }
|
28
|
+
end.map{|c| match(c)}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
rule "ETSY007", "Package or yum_package resource used to install core package without specific version number" do
|
33
|
+
tags %w{style recipe etsy}
|
34
|
+
recipe do |ast,filename|
|
35
|
+
pres = find_resources(ast, :type => 'package').find_all do |cmd|
|
36
|
+
cmd_str = (resource_attribute(cmd, 'version') || resource_name(cmd)).to_s
|
37
|
+
cmd_action = (resource_attribute(cmd, 'action') || resource_name(cmd)).to_s
|
38
|
+
cmd_str == resource_name(cmd) && @coreservicepackages.any? { |svc| resource_name(cmd) == svc } && cmd_action.include?('install')
|
39
|
+
end
|
40
|
+
ypres = find_resources(ast, :type => 'yum_package').find_all do |cmd|
|
41
|
+
cmd_str = (resource_attribute(cmd, 'version') || resource_name(cmd)).to_s
|
42
|
+
cmd_action = (resource_attribute(cmd, 'action') || resource_name(cmd)).to_s
|
43
|
+
cmd_str == resource_name(cmd) && @coreservicepackages.any? { |svc| resource_name(cmd) == svc } && cmd_action.include?('install')
|
44
|
+
end
|
45
|
+
pres.concat(ypres).map { |cmd| match(cmd) }
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cookbook_sdk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mindera
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.4'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: highline
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 1.6.9
|
51
|
+
type: :runtime
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1.6'
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.6.9
|
61
|
+
description: |
|
62
|
+
# cookbook_sdk
|
63
|
+
|
64
|
+
[](https://travis-ci.org/Mindera/cookbook_sdk)
|
65
|
+
|
66
|
+
Helpers for chef cookbook development and provisioning.
|
67
|
+
email:
|
68
|
+
- social@mindera.com
|
69
|
+
executables: []
|
70
|
+
extensions: []
|
71
|
+
extra_rdoc_files: []
|
72
|
+
files:
|
73
|
+
- ".gitignore"
|
74
|
+
- ".rubocop.yml"
|
75
|
+
- ".travis.yml"
|
76
|
+
- Gemfile
|
77
|
+
- LICENSE.txt
|
78
|
+
- README.md
|
79
|
+
- Rakefile
|
80
|
+
- cookbook_sdk.gemspec
|
81
|
+
- lib/cookbook_sdk/ext/string.rb
|
82
|
+
- lib/cookbook_sdk/handlers/slack.rb
|
83
|
+
- lib/cookbook_sdk/rake_tasks.rb
|
84
|
+
- lib/cookbook_sdk/rake_tasks/helper_tasks.rb
|
85
|
+
- lib/cookbook_sdk/rake_tasks/provisioning_tasks.rb
|
86
|
+
- lib/cookbook_sdk/rake_tasks/test_tasks.rb
|
87
|
+
- lib/cookbook_sdk/version.rb
|
88
|
+
- lib/foodcritic/rules/etsy.rb
|
89
|
+
homepage: https://github.com/mindera/cookbook_sdk
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.4.8
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: cookbook sdk
|
113
|
+
test_files: []
|
114
|
+
has_rdoc:
|