bourdain 1.2.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/Gemfile +11 -0
  4. data/Rakefile +19 -0
  5. data/Readme.md +1 -0
  6. data/TODO.md +41 -0
  7. data/VERSION +1 -0
  8. data/bin/tony +54 -0
  9. data/bin/tony-bump +3 -0
  10. data/bin/tony-check +3 -0
  11. data/bin/tony-generate +3 -0
  12. data/bourdain.gemspec +25 -0
  13. data/install-or-upgrade.sh +4 -0
  14. data/lib/bourdain/helpers/config.rb +12 -0
  15. data/lib/bourdain/helpers/locals.rb +17 -0
  16. data/lib/bourdain/helpers/logger.rb +41 -0
  17. data/lib/bourdain/helpers/parser.rb +76 -0
  18. data/lib/bourdain/helpers/registry.rb +53 -0
  19. data/lib/bourdain/helpers.rb +32 -0
  20. data/lib/bourdain/metadata.rb +19 -0
  21. data/lib/bourdain/resources/checks/bourdain.rb +71 -0
  22. data/lib/bourdain/resources/checks/chef.rb +35 -0
  23. data/lib/bourdain/resources/checks/cookbooks.rb +97 -0
  24. data/lib/bourdain/resources/checks/hooks.rb +67 -0
  25. data/lib/bourdain/resources/checks/ssh_config.rb +61 -0
  26. data/lib/bourdain/resources/checks.rb +36 -0
  27. data/lib/bourdain/resources/commands/bump.rb +74 -0
  28. data/lib/bourdain/resources/commands/check.rb +103 -0
  29. data/lib/bourdain/resources/commands/generate.rb +33 -0
  30. data/lib/bourdain/resources/commands.rb +10 -0
  31. data/lib/bourdain/resources/generators/attribute.rb +43 -0
  32. data/lib/bourdain/resources/generators/cookbook.rb +125 -0
  33. data/lib/bourdain/resources/generators/recipe.rb +54 -0
  34. data/lib/bourdain/resources/generators.rb +22 -0
  35. data/lib/bourdain/resources.rb +104 -0
  36. data/lib/bourdain.rb +3 -0
  37. data/templates/chef/environment.json +8 -0
  38. data/templates/chef/role.json +9 -0
  39. data/templates/cookbook/Berksfile +3 -0
  40. data/templates/cookbook/Readme.md +1 -0
  41. data/templates/cookbook/VERSION +1 -0
  42. data/templates/cookbook/Vagrantfile +19 -0
  43. data/templates/cookbook/attributes/example.rb +24 -0
  44. data/templates/cookbook/busser_minitest.rb +7 -0
  45. data/templates/cookbook/gitignore +26 -0
  46. data/templates/cookbook/kitchen.yml +23 -0
  47. data/templates/cookbook/metadata.rb +10 -0
  48. data/templates/cookbook/pre-commit +80 -0
  49. data/templates/cookbook/recipes/example.rb +38 -0
  50. data/test.sh +12 -0
  51. 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
@@ -0,0 +1,12 @@
1
+ *~
2
+ *.log
3
+ *.out
4
+ *.pid
5
+ *.swp
6
+ *.gem
7
+ .DS_Store
8
+ Gemfile.lock
9
+ tmp
10
+ log
11
+ doc
12
+ .yarddoc
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'pry'
7
+ gem 'rake'
8
+ gem 'yard'
9
+ gem 'version'
10
+ gem 'rubygems-tasks'
11
+ end
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
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bourdain'
3
+ exit Bourdain::Commands::BumpCommand.new(ARGV).status
data/bin/tony-check ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bourdain'
3
+ exit Bourdain::Commands::CheckCommand.new(ARGV).status
data/bin/tony-generate ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bourdain'
3
+ exit Bourdain::Commands::GenerateCommand.new(ARGV).status
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,4 @@
1
+ #!/usr/bin/env sh
2
+ rm -f *.gem
3
+ gem build *.gemspec
4
+ gem install *.gem
@@ -0,0 +1,12 @@
1
+ require 'json'
2
+
3
+ module Bourdain
4
+ module Helpers
5
+ class Config
6
+ attr_reader :items
7
+ def initialize path
8
+ @items = JSON::parse File.read(path), symbolize_names: true rescue {}
9
+ end
10
+ end
11
+ end
12
+ 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