bourdain 1.2.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/Gemfile +11 -0
- data/Rakefile +19 -0
- data/Readme.md +1 -0
- data/TODO.md +41 -0
- data/VERSION +1 -0
- data/bin/tony +54 -0
- data/bin/tony-bump +3 -0
- data/bin/tony-check +3 -0
- data/bin/tony-generate +3 -0
- data/bourdain.gemspec +25 -0
- data/install-or-upgrade.sh +4 -0
- data/lib/bourdain/helpers/config.rb +12 -0
- data/lib/bourdain/helpers/locals.rb +17 -0
- data/lib/bourdain/helpers/logger.rb +41 -0
- data/lib/bourdain/helpers/parser.rb +76 -0
- data/lib/bourdain/helpers/registry.rb +53 -0
- data/lib/bourdain/helpers.rb +32 -0
- data/lib/bourdain/metadata.rb +19 -0
- data/lib/bourdain/resources/checks/bourdain.rb +71 -0
- data/lib/bourdain/resources/checks/chef.rb +35 -0
- data/lib/bourdain/resources/checks/cookbooks.rb +97 -0
- data/lib/bourdain/resources/checks/hooks.rb +67 -0
- data/lib/bourdain/resources/checks/ssh_config.rb +61 -0
- data/lib/bourdain/resources/checks.rb +36 -0
- data/lib/bourdain/resources/commands/bump.rb +74 -0
- data/lib/bourdain/resources/commands/check.rb +103 -0
- data/lib/bourdain/resources/commands/generate.rb +33 -0
- data/lib/bourdain/resources/commands.rb +10 -0
- data/lib/bourdain/resources/generators/attribute.rb +43 -0
- data/lib/bourdain/resources/generators/cookbook.rb +125 -0
- data/lib/bourdain/resources/generators/recipe.rb +54 -0
- data/lib/bourdain/resources/generators.rb +22 -0
- data/lib/bourdain/resources.rb +104 -0
- data/lib/bourdain.rb +3 -0
- data/templates/chef/environment.json +8 -0
- data/templates/chef/role.json +9 -0
- data/templates/cookbook/Berksfile +3 -0
- data/templates/cookbook/Readme.md +1 -0
- data/templates/cookbook/VERSION +1 -0
- data/templates/cookbook/Vagrantfile +19 -0
- data/templates/cookbook/attributes/example.rb +24 -0
- data/templates/cookbook/busser_minitest.rb +7 -0
- data/templates/cookbook/gitignore +26 -0
- data/templates/cookbook/kitchen.yml +23 -0
- data/templates/cookbook/metadata.rb +10 -0
- data/templates/cookbook/pre-commit +80 -0
- data/templates/cookbook/recipes/example.rb +38 -0
- data/test.sh +12 -0
- metadata +165 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e3811bdc20aa707f202ca15513ada539a93c825d
|
4
|
+
data.tar.gz: 8b158824deaecb5e201fa0e46d2e2cab40e8d9b2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 941638c93c4154d2911b1d4418d65ad65e7727abedc31fb4b4b469e85628e1bf0b900b9e6d69bb64112f21f8be5dedab58bee869cbb8d7a293366b1756b23089
|
7
|
+
data.tar.gz: b29f2437342970e19bd8f9b7ed53333663fef62096159d9a90474e12971476a2662e7697b5245d7b1928aa2077331b539d0b2a911d13a4718c111d129cf93db5
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'rake'
|
4
|
+
|
5
|
+
require 'yard'
|
6
|
+
YARD::Rake::YardocTask.new do |t|
|
7
|
+
t.files = %w[ --readme Readme.md lib/**/*.rb - VERSION ]
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rake/version_task'
|
11
|
+
Rake::VersionTask.new
|
12
|
+
|
13
|
+
require 'rubygems/tasks'
|
14
|
+
Gem::Tasks.new({
|
15
|
+
sign: {}
|
16
|
+
}) do |tasks|
|
17
|
+
tasks.console.command = 'pry'
|
18
|
+
end
|
19
|
+
Gem::Tasks::Sign::Checksum.new sha2: true
|
data/Readme.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Bourdain
|
data/TODO.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
~/.bourdain.json
|
2
|
+
|
3
|
+
Getting Smarter
|
4
|
+
Considers branch you're on
|
5
|
+
Considers version of branch on origin
|
6
|
+
Excludes changes in **/*.md
|
7
|
+
|
8
|
+
Default <options> are...
|
9
|
+
--help :: Show this message
|
10
|
+
--debug :: Enable debug logging
|
11
|
+
--jk :: Just explain what would happen
|
12
|
+
|
13
|
+
update [<options>]
|
14
|
+
Update the underlying Chef repo, cookbooks, and utilities
|
15
|
+
--pull :: Perform a git pull on resources (default: false)
|
16
|
+
|
17
|
+
generate user [<options>] <name>
|
18
|
+
Generate a new user data bag in the current repo
|
19
|
+
--shell <s> :: Choose a default shell (default: zsh)
|
20
|
+
--password <s> :: Provide a password for authentication
|
21
|
+
--ssh-key <s> :: Provide an SSH key for authentication %(default: intelligent)
|
22
|
+
--groups <s> :: Provide a comma-separated list of groups
|
23
|
+
--comment <s> :: Provide a comment (usually a full name)
|
24
|
+
--phone <s> :: Provide a phone or pager number
|
25
|
+
--email <s> :: Provide an email address
|
26
|
+
|
27
|
+
generate node [<options>] <name>
|
28
|
+
Generate a new node resource in the current repo
|
29
|
+
--environment <s> :: Provide an environment name
|
30
|
+
--run-list <s> :: Provide a run list string
|
31
|
+
|
32
|
+
generate file [<options>] <name> [<source>]
|
33
|
+
Generate a new file in the current cookbook
|
34
|
+
--namespace <s> :: Provide a namespace (default: default)
|
35
|
+
|
36
|
+
generate template [<options>] <name> [<source>]
|
37
|
+
Generate a new template in the current cookbook
|
38
|
+
--namespace <s> :: Provide a namespace (default: default)
|
39
|
+
|
40
|
+
generate data.?bag [<options>] [<namepace>] <name>
|
41
|
+
Generate a new data bag in the current cookbook
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.2.13
|
data/bin/tony
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'trollop'
|
3
|
+
require 'bourdain'
|
4
|
+
|
5
|
+
argv = ARGV.empty? ? [ '--help' ] : ARGV
|
6
|
+
|
7
|
+
commands = Bourdain::Registry.specs('command')
|
8
|
+
command_position = commands.map { |c| argv.index c[:name].to_s }.compact.shift
|
9
|
+
command_position = argv.length if command_position.nil?
|
10
|
+
argv_before_command = argv.slice(0, command_position)
|
11
|
+
|
12
|
+
Trollop::options(argv_before_command) do
|
13
|
+
version Bourdain::VERSION
|
14
|
+
banner Bourdain::ART + "\n\n" + <<-EOS.gsub(/^ /, '')
|
15
|
+
#{Bourdain::SUMMARY}
|
16
|
+
|
17
|
+
Usage: tony [<options>] <command>
|
18
|
+
|
19
|
+
Commands:
|
20
|
+
#{Bourdain::Registry.details('command') * "\n "}
|
21
|
+
|
22
|
+
Options:
|
23
|
+
EOS
|
24
|
+
end
|
25
|
+
|
26
|
+
command = argv.shift
|
27
|
+
Trollop::die 'No <command> provided' if command.nil?
|
28
|
+
Trollop::die 'Invalid <command> provided' if command_position.nil?
|
29
|
+
|
30
|
+
bin_dir = File.dirname(File.expand_path(__FILE__))
|
31
|
+
executable = File.join bin_dir, "tony-#{command}"
|
32
|
+
Trollop::die 'Invalid <command> provided' unless File.exists? executable
|
33
|
+
|
34
|
+
log = Bourdain::Logger.new
|
35
|
+
|
36
|
+
exec(executable, *argv) if File.exists? Bourdain::CONFIG
|
37
|
+
|
38
|
+
log.info <<-EOLOG.gsub(/^ /, '').strip
|
39
|
+
Hey, looks like you've never run Bourdain before.
|
40
|
+
|
41
|
+
Before I we can get started, you'll need to create a config file for Bourdain
|
42
|
+
at #{Bourdain::CONFIG}. It should look something like this:
|
43
|
+
EOLOG
|
44
|
+
puts
|
45
|
+
log.warn <<-EOLOG.gsub(/^ /, '').strip
|
46
|
+
{
|
47
|
+
"gitlab": {
|
48
|
+
"token": "your_gitlab_token"
|
49
|
+
}
|
50
|
+
}
|
51
|
+
EOLOG
|
52
|
+
puts
|
53
|
+
log.info 'You can find your GitLab token here: http://git.bluejeansnet.com/profile/account'
|
54
|
+
exit 1
|
data/bin/tony-bump
ADDED
data/bin/tony-check
ADDED
data/bin/tony-generate
ADDED
data/bourdain.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path(File.join('..', 'lib'), __FILE__)
|
3
|
+
require 'bourdain/metadata'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'bourdain'
|
7
|
+
s.version = Bourdain::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.author = Bourdain::AUTHOR
|
10
|
+
s.email = Bourdain::EMAIL
|
11
|
+
s.homepage = Bourdain::HOMEPAGE
|
12
|
+
s.summary = Bourdain::SUMMARY
|
13
|
+
s.description = Bourdain::SUMMARY + '.'
|
14
|
+
|
15
|
+
s.add_runtime_dependency 'pmap'
|
16
|
+
s.add_runtime_dependency 'gitlab'
|
17
|
+
s.add_runtime_dependency 'trollop'
|
18
|
+
s.add_runtime_dependency 'colorize'
|
19
|
+
s.add_runtime_dependency 'activesupport'
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File::basename(f) }
|
24
|
+
s.require_paths = %w[ lib ]
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Helpers
|
3
|
+
class Locals
|
4
|
+
def initialize locals
|
5
|
+
locals.each do |name, value|
|
6
|
+
instance_variable_set "@#{name}", value
|
7
|
+
metaclass = class << self ; self ; end
|
8
|
+
metaclass.send(:define_method, name) do
|
9
|
+
instance_variable_get("@#{name}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def bind ; binding end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
require 'colorize'
|
5
|
+
|
6
|
+
|
7
|
+
module Bourdain
|
8
|
+
module Logger
|
9
|
+
SEVERITY_COLORS = {
|
10
|
+
'DEBUG' => [ :blue, :default ],
|
11
|
+
'INFO' => [ :green, :default ],
|
12
|
+
'WARN' => [ :yellow, :default ],
|
13
|
+
'ERROR' => [ :red, :default ],
|
14
|
+
'FATAL' => [ :red, :black ]
|
15
|
+
}
|
16
|
+
|
17
|
+
def self.new level=::Logger::INFO, file=STDOUT
|
18
|
+
logger = ::Logger.new file
|
19
|
+
logger.level = level
|
20
|
+
logger.formatter = proc do |severity, datetime, _, msg|
|
21
|
+
if level == 1
|
22
|
+
msg.to_s.colorize(
|
23
|
+
color: SEVERITY_COLORS[severity.to_s][0],
|
24
|
+
background: SEVERITY_COLORS[severity.to_s][1]
|
25
|
+
) + "\n"
|
26
|
+
else
|
27
|
+
"%s [%s] %s -- %s\n".colorize(
|
28
|
+
color: SEVERITY_COLORS[severity.to_s][0],
|
29
|
+
background: SEVERITY_COLORS[severity.to_s][1]
|
30
|
+
) % [
|
31
|
+
severity,
|
32
|
+
datetime.iso8601(6),
|
33
|
+
File::basename(caller[4]),
|
34
|
+
msg
|
35
|
+
]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
return logger
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Bourdain
|
4
|
+
module Helpers
|
5
|
+
class UsageParser
|
6
|
+
def self.parse spec
|
7
|
+
lines = spec.lines.map(&:strip)
|
8
|
+
desc = lines.shift
|
9
|
+
usage = lines.shift
|
10
|
+
name = usage.split(' ').first
|
11
|
+
args = lines.select { |l| l =~ /^--/ }
|
12
|
+
resources = lines.select { |l| l =~ /^</ }
|
13
|
+
resources = resources.map { |r| r.gsub(/\W/, '') }
|
14
|
+
{
|
15
|
+
name: name,
|
16
|
+
usage: usage,
|
17
|
+
desc: desc,
|
18
|
+
resources: resources,
|
19
|
+
opts: args.map { |a| parse_arg a }
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def self.parse_arg arg_spec
|
25
|
+
matches = arg_spec.match(/^--(.*?)( \(.*?\))?( <.*?>)? :: (.*?)$/)
|
26
|
+
|
27
|
+
long = matches[1]
|
28
|
+
short = matches[2]
|
29
|
+
type = matches[3]
|
30
|
+
desc = matches[4]
|
31
|
+
|
32
|
+
short.gsub!(/[^a-z]/, '') unless short.nil?
|
33
|
+
|
34
|
+
type.gsub!(/[^a-z]/, '') unless type.nil?
|
35
|
+
|
36
|
+
type = case type
|
37
|
+
when 'i' ; :integer
|
38
|
+
when 'd' ; :double
|
39
|
+
when 'f' ; :float
|
40
|
+
when 's' ; :string
|
41
|
+
when 'o' ; :io
|
42
|
+
when nil ; nil
|
43
|
+
else raise "unkown type '#{type}'"
|
44
|
+
end
|
45
|
+
|
46
|
+
matches = desc.match(/(.*?)( \((default|required): .*?\))?$/)
|
47
|
+
unless matches.nil?
|
48
|
+
desc = matches[1]
|
49
|
+
opts = matches[2]
|
50
|
+
end
|
51
|
+
|
52
|
+
unless opts.nil?
|
53
|
+
if matches = opts.match(/default: (.*?)(,|\))/)
|
54
|
+
default = matches[1]
|
55
|
+
default = !!(default =~ /true/) unless default.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
if matches = opts.match(/required: (true|false)(,|\))/)
|
59
|
+
required = matches[1]
|
60
|
+
required = !!(required =~ /true/) unless required.nil?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
long = long.gsub('-', '_').to_sym
|
65
|
+
|
66
|
+
token = { long: long, desc: desc, opts: {} }
|
67
|
+
token[:opts][:type] = type unless type.nil?
|
68
|
+
token[:opts][:short] = short unless short.nil?
|
69
|
+
token[:opts][:default] = default unless default.nil?
|
70
|
+
token[:opts][:required] = required unless required.nil?
|
71
|
+
|
72
|
+
return token
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
|
4
|
+
module Bourdain
|
5
|
+
module Helpers
|
6
|
+
class Registry
|
7
|
+
attr_reader :name, :config
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@config = Hash.new { |default, key| default[key] = Set.new }
|
11
|
+
end
|
12
|
+
|
13
|
+
def register namespace, klass
|
14
|
+
@config[namespace].add(klass)
|
15
|
+
end
|
16
|
+
|
17
|
+
def namespace namespace
|
18
|
+
@config[namespace].to_a
|
19
|
+
end
|
20
|
+
|
21
|
+
def map namespace, &block
|
22
|
+
@config[namespace].map(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def specs namespace
|
26
|
+
@config[namespace].map do |klass|
|
27
|
+
Bourdain::Helpers::UsageParser.parse klass.raw_usage
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def klass namespace, name
|
32
|
+
@config[namespace].select do |klass|
|
33
|
+
Bourdain::Helpers::UsageParser.parse(klass.raw_usage)[:name] == name
|
34
|
+
end.shift
|
35
|
+
end
|
36
|
+
|
37
|
+
def spec namespace, name
|
38
|
+
specs(namespace).select do |spec|
|
39
|
+
spec[:name] == name
|
40
|
+
end.shift
|
41
|
+
end
|
42
|
+
|
43
|
+
def details namespace
|
44
|
+
specs = specs(namespace)
|
45
|
+
max_name_width = specs.sort_by { |s| s[:name].to_s.length }.last[:name].length
|
46
|
+
max_name_width += 2
|
47
|
+
specs.map do |spec|
|
48
|
+
"#{spec[:name].rjust(max_name_width)}: #{spec[:desc]}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
CWD = Dir.pwd
|
4
|
+
PATH = File.expand_path(__FILE__)
|
5
|
+
DIR = File.dirname(PATH)
|
6
|
+
ROOT = File.expand_path(File.join(DIR, '..', '..'))
|
7
|
+
BASE = Pathname.new(ROOT).relative_path_from(Pathname.new(CWD)).to_s
|
8
|
+
|
9
|
+
def gem_path *dir
|
10
|
+
Pathname.new(File.join(BASE, *dir)).cleanpath.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def apply_template file, opts
|
14
|
+
template_name, locals = opts[:template], opts[:locals]
|
15
|
+
locals = Bourdain::Helpers::Locals.new(locals).bind unless locals.nil?
|
16
|
+
template_path = gem_path('templates', *template_name)
|
17
|
+
template = ERB.new File.read(template_path)
|
18
|
+
contents = template.result(locals)
|
19
|
+
File.open(file, 'w') { |f| f.puts contents }
|
20
|
+
end
|
21
|
+
|
22
|
+
require_relative 'helpers/config'
|
23
|
+
require_relative 'helpers/locals'
|
24
|
+
require_relative 'helpers/logger'
|
25
|
+
require_relative 'helpers/parser'
|
26
|
+
require_relative 'helpers/registry'
|
27
|
+
|
28
|
+
module Bourdain
|
29
|
+
Config = Bourdain::Helpers::Config.new(CONFIG)
|
30
|
+
Registry = Bourdain::Helpers::Registry.new
|
31
|
+
GITLAB_HOST = 'git.bluejeansnet.com'
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Bourdain
|
2
|
+
CONFIG = File.join(ENV['HOME'], '.bourdain.json')
|
3
|
+
VERSION = File.read(File.join(File.dirname(__FILE__), '..', '..', 'VERSION')).strip
|
4
|
+
SUMMARY = 'Tools for badass chefs'
|
5
|
+
AUTHOR = 'Sean Clemmer'
|
6
|
+
EMAIL = 'sclemmer@bluejeans.com'
|
7
|
+
HOMEPAGE = 'http://wiki.bluejeansnet.com/operations/bourdain'
|
8
|
+
ART = <<-'EOART' % VERSION
|
9
|
+
|
10
|
+
__ __
|
11
|
+
/\ \ /\ \ __
|
12
|
+
\ \ \____ ___ __ __ _ __ \_\ \ __ /\_\ ___
|
13
|
+
\ \ '__`\ / __`\/\ \/\ \/\`'__\/'_` \ /'__`\ \/\ \ /' _ `\
|
14
|
+
\ \ \L\ \/\ \L\ \ \ \_\ \ \ \//\ \L\ \/\ \L\.\_\ \ \/\ \/\ \
|
15
|
+
\ \_,__/\ \____/\ \____/\ \_\\ \___,_\ \__/.\_\\ \_\ \_\ \_\
|
16
|
+
\/___/ \/___/ \/___/ \/_/ \/__,_ /\/__/\/_/ \/_/\/_/\/_/
|
17
|
+
v%s
|
18
|
+
EOART
|
19
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Checks
|
3
|
+
|
4
|
+
class BourdainCheck < Check
|
5
|
+
usage :check, <<-END
|
6
|
+
Check the local copy of Bourdain
|
7
|
+
bourdain
|
8
|
+
END
|
9
|
+
|
10
|
+
|
11
|
+
def initialize cookbook_config
|
12
|
+
super []
|
13
|
+
return unless require_chef!
|
14
|
+
check_bourdain!
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
private
|
20
|
+
def check_bourdain!
|
21
|
+
# Ensure we have an up-to-date copy of Bourdain
|
22
|
+
bourdain = File.join('utils', 'bourdain')
|
23
|
+
|
24
|
+
ahead_of_remote = false
|
25
|
+
unless Dir.exists? bourdain
|
26
|
+
log.warn "Hm, I don't see a copy of Bourdain. I'll fix that for you..."
|
27
|
+
%x| git clone git@git.bluejeansnet.com:chef/bourdain.git #{bourdain} |
|
28
|
+
log.info "Your copy of Bourdain is now up-to-date."
|
29
|
+
|
30
|
+
else
|
31
|
+
if youre_dirty? bourdain
|
32
|
+
log.warn "Your copy of Bourdain is dirty."
|
33
|
+
elsif youre_ahead? bourdain
|
34
|
+
log.warn "Your copy of Bourdain is ahead of the remote."
|
35
|
+
ahead_of_remote = true
|
36
|
+
elsif youre_behind? bourdain
|
37
|
+
log.warn "Hey, looks like your copy of Bourdain is out-of-date. I'll fix that for you..."
|
38
|
+
Dir.chdir(bourdain) { %x| git pull | }
|
39
|
+
log.info "Your copy of Bourdain is now up-to-date."
|
40
|
+
else
|
41
|
+
log.info "Your copy of Bourdain looks up-to-date."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
matches = File.read('Gemfile.lock').match(/bourdain \((.*?)\)$/)
|
46
|
+
|
47
|
+
if matches.nil?
|
48
|
+
log.warn "Couldn't find Kitchen hooks in your Gemfile lock. Something is amiss..."
|
49
|
+
error!
|
50
|
+
|
51
|
+
else
|
52
|
+
repo_version = matches[1].strip
|
53
|
+
local_version = File.read(File.join(bourdain, 'VERSION')).strip
|
54
|
+
|
55
|
+
if repo_version == local_version
|
56
|
+
log.info "Your Chef repo is bundled with the latest Bourdain."
|
57
|
+
elsif ahead_of_remote
|
58
|
+
# Don't worry about it, we've already warned them
|
59
|
+
elsif local_version < repo_version
|
60
|
+
log.error 'Your Chef repo is bundled with an older Bourdain. Try "bundle update".'
|
61
|
+
error!
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Remove pre-commit hook if installed
|
66
|
+
pre_commit_hook = File.join(*bourdain, '.git', 'hooks', 'pre-commit')
|
67
|
+
FileUtils.rm_rf pre_commit_hook
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Checks
|
3
|
+
|
4
|
+
class ChefCheck < Check
|
5
|
+
usage :check, <<-END
|
6
|
+
Check the underlying Kitchen
|
7
|
+
chef
|
8
|
+
END
|
9
|
+
|
10
|
+
|
11
|
+
def initialize cookbook_config
|
12
|
+
super []
|
13
|
+
return unless require_chef!
|
14
|
+
check_chef_repo!
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
private
|
20
|
+
def check_chef_repo!
|
21
|
+
# Check if we have an up-to-date copy of the Kitchen
|
22
|
+
if youre_dirty? '.'
|
23
|
+
log.warn "Your Kitchen is dirty."
|
24
|
+
elsif youre_ahead? '.'
|
25
|
+
log.warn "Your Kitchen is ahead of the remote."
|
26
|
+
elsif youre_behind? '.'
|
27
|
+
log.error "Looks like your Kitchen is behind the remote."
|
28
|
+
error!
|
29
|
+
else
|
30
|
+
log.info "Your Kitchen looks up-to-date."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Checks
|
3
|
+
|
4
|
+
class CookbooksCheck < Check
|
5
|
+
usage :check, <<-END
|
6
|
+
Check all the underlying cookbooks
|
7
|
+
cookbooks
|
8
|
+
END
|
9
|
+
|
10
|
+
|
11
|
+
def initialize cookbook_config
|
12
|
+
super []
|
13
|
+
return unless require_chef!
|
14
|
+
check_gitlab_cookbooks! cookbook_config
|
15
|
+
check_local_cookbooks! cookbook_config
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
private
|
21
|
+
def check_cookbook_freshness cookbook
|
22
|
+
notifications = []
|
23
|
+
path = cookbook[:path]
|
24
|
+
|
25
|
+
if Dir.exists? path
|
26
|
+
if youre_dirty? path
|
27
|
+
notifications.push [ path, :warn, "Your cookbook %{path} is dirty." % cookbook ]
|
28
|
+
elsif youre_ahead? path
|
29
|
+
notifications.push [ path, :warn, "Your cookbook %{path} is ahead of %{repo}." % cookbook ]
|
30
|
+
elsif youre_behind? path
|
31
|
+
notifications.push [ path, :error, "Hey, looks like your cookbook %{path} is behind %{repo}. Try pulling." % cookbook ]
|
32
|
+
error!
|
33
|
+
else
|
34
|
+
notifications.push [ path, :info, "Your cookbook %{path} looks up-to-date." % cookbook ]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
notifications
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_cookbook_exists cookbook
|
42
|
+
unless Dir.exists? cookbook[:path]
|
43
|
+
log.warn "Populating cookbook %{path} with %{repo}" % cookbook
|
44
|
+
%x| git clone git@#{GITLAB_HOST}:#{cookbook[:repo]} #{cookbook[:path]} |
|
45
|
+
log.info "Your cookbook %{path} is now up-to-date." % cookbook
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def log_notifications notifications
|
50
|
+
ns = notifications.map { |n| n.first rescue nil }.compact.select { |n| !n.empty? }
|
51
|
+
ns.sort_by(&:first).each do |n|
|
52
|
+
next if n.empty?
|
53
|
+
_, severity, message = n
|
54
|
+
log.send severity, message
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def ensure_pre_commit_installed cookbook
|
59
|
+
pre_commit_hook = File.join(cookbook[:path], '.git', 'hooks', 'pre-commit')
|
60
|
+
apply_template pre_commit_hook, template: %w[ cookbook pre-commit ]
|
61
|
+
FileUtils.chmod 0755, pre_commit_hook
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
def check_gitlab_cookbooks! cookbook_configs
|
67
|
+
notifications = cookbook_configs.pmap do |cookbook|
|
68
|
+
check_cookbook_freshness cookbook
|
69
|
+
end
|
70
|
+
unless notifications.first.empty?
|
71
|
+
log_notifications notifications
|
72
|
+
end
|
73
|
+
|
74
|
+
cookbook_configs.sort_by { |cc| cc[:path] }.each do |cookbook|
|
75
|
+
check_cookbook_exists cookbook
|
76
|
+
end
|
77
|
+
|
78
|
+
cookbook_configs.each do |cookbook|
|
79
|
+
ensure_pre_commit_installed cookbook
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def check_local_cookbooks! cookbook_configs
|
85
|
+
known_cookbook_paths = cookbook_configs.map { |cc| cc[:path].sub('forks/bjn_', 'forks/') }
|
86
|
+
local_cookbook_paths = Dir[File.join('{apps,bases,forks,libs,realms}', '*')]
|
87
|
+
unknown_cookbook_paths = local_cookbook_paths - known_cookbook_paths
|
88
|
+
unless unknown_cookbook_paths.empty?
|
89
|
+
log.warn "Head's up, I see some cookbooks aren't on GitLab:"
|
90
|
+
unknown_cookbook_paths.each do |cookbook_path|
|
91
|
+
log.warn " #{cookbook_path}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|