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
@@ -0,0 +1,67 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Checks
|
3
|
+
|
4
|
+
class HooksCheck < Check
|
5
|
+
usage :check, <<-END
|
6
|
+
Check the local copy of Kitchen hooks
|
7
|
+
hooks
|
8
|
+
END
|
9
|
+
|
10
|
+
|
11
|
+
def initialize _
|
12
|
+
super []
|
13
|
+
return unless require_chef!
|
14
|
+
check_hooks!
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
private
|
20
|
+
def check_hooks!
|
21
|
+
# Ensure we have an up-to-date copy of Kitchen hooks
|
22
|
+
hooks = File.join('utils', 'hooks')
|
23
|
+
|
24
|
+
ahead_of_remote = false
|
25
|
+
unless Dir.exists? hooks
|
26
|
+
log.warn "Hm, I don't see a copy of Kitchen hooks. I'll fix that for you..."
|
27
|
+
%x| git clone git@git.bluejeansnet.com:kitchen-hooks.git #{hooks} |
|
28
|
+
log.info "Your copy of Kitchen hooks is now up-to-date."
|
29
|
+
|
30
|
+
else
|
31
|
+
if youre_dirty? hooks
|
32
|
+
log.warn "Your copy of Kitchen hooks is dirty."
|
33
|
+
elsif youre_ahead? hooks
|
34
|
+
log.warn "Your copy of Kitchen hooks is ahead of the remote."
|
35
|
+
ahead_of_remote = true
|
36
|
+
elsif youre_behind? hooks
|
37
|
+
log.warn "Hey, looks like your copy of Kitchen hooks is out-of-date. I'll fix that for you..."
|
38
|
+
Dir.chdir(bourdain) { %x| git pull | }
|
39
|
+
log.info "Your copy of Kitchen hooks is now up-to-date."
|
40
|
+
else
|
41
|
+
log.info "Your copy of Kitchen hooks looks up-to-date."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
matches = File.read('Gemfile.lock').match(/kitchen_hooks \((.*?)\)$/)
|
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(hooks, 'VERSION')).strip
|
54
|
+
|
55
|
+
if repo_version == local_version
|
56
|
+
log.info "Your Chef repo is bundled with the latest Kitchen hooks."
|
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 Kitchen hooks. Try "bundle update".'
|
61
|
+
error!
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Bourdain
|
4
|
+
module Checks
|
5
|
+
|
6
|
+
class SSHConfigCheck < Check
|
7
|
+
usage :check, <<-END
|
8
|
+
Ensure all nodes are enterened into the local SSH config
|
9
|
+
ssh_config
|
10
|
+
END
|
11
|
+
|
12
|
+
|
13
|
+
def initialize cookbook_config
|
14
|
+
super []
|
15
|
+
return unless require_chef!
|
16
|
+
check_ssh_config!
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
private
|
22
|
+
def check_ssh_config! ssh_config=File.join(ENV['HOME'], '.ssh', 'config')
|
23
|
+
unless File::exist?(ssh_config)
|
24
|
+
log.warn 'Skipping SSH config check. File does not exist: %s' % ssh_config.inspect
|
25
|
+
return
|
26
|
+
end
|
27
|
+
|
28
|
+
nodes = Dir[File.join('nodes', '*.json')]
|
29
|
+
nodes = nodes.map do |path|
|
30
|
+
JSON::parse File.read(path)
|
31
|
+
end
|
32
|
+
|
33
|
+
config = File.read(ssh_config)
|
34
|
+
|
35
|
+
hosts = []
|
36
|
+
config.lines.select do |l|
|
37
|
+
l =~ /Host (\S+)/
|
38
|
+
hosts << $1 if $1
|
39
|
+
end
|
40
|
+
|
41
|
+
unconfigured_nodes = nodes.select do |n|
|
42
|
+
!hosts.include? n['name']
|
43
|
+
end
|
44
|
+
|
45
|
+
File.open(ssh_config, 'a') do |f|
|
46
|
+
f.puts unless unconfigured_nodes.empty?
|
47
|
+
unconfigured_nodes.each do |n|
|
48
|
+
log.info 'Adding %s to %s' % [ n['name'].inspect, ssh_config ]
|
49
|
+
f.puts "Host %s" % n['name']
|
50
|
+
f.puts "\tHostName\t%s" % n['name']
|
51
|
+
f.puts "\tPort\t22"
|
52
|
+
f.puts "\tUser\tvagrant"
|
53
|
+
f.puts "\tStrictHostKeyChecking\tno"
|
54
|
+
f.puts "\tIdentityFile\t~/.vagrant.d/insecure_private_key"
|
55
|
+
f.puts
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
|
5
|
+
module Bourdain
|
6
|
+
module Checks
|
7
|
+
class Check < Bourdain::Resource
|
8
|
+
protected
|
9
|
+
def work_tree repo
|
10
|
+
"--work-tree=#{File.join(Dir.pwd, repo)}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def git_dir repo
|
14
|
+
"--git-dir=#{File.join(Dir.pwd, repo, '.git')}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def youre_behind? repo
|
18
|
+
`git #{git_dir repo} log ..origin/master --oneline`.split("\n").length > 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def youre_ahead? repo
|
22
|
+
`git #{git_dir repo} log origin/master.. --oneline`.split("\n").length > 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def youre_dirty? repo
|
26
|
+
`git #{git_dir repo} #{work_tree repo} diff HEAD --numstat`.split("\n").length > 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
require_relative 'checks/chef'
|
33
|
+
require_relative 'checks/hooks'
|
34
|
+
require_relative 'checks/bourdain'
|
35
|
+
require_relative 'checks/cookbooks'
|
36
|
+
require_relative 'checks/ssh_config'
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Commands
|
3
|
+
|
4
|
+
class BumpCommand < Command
|
5
|
+
usage :command, <<-END
|
6
|
+
Bump a VERSION file (patch by default)
|
7
|
+
bump [<options>] [<version-spec=major|minor|patch|x.y.z>]
|
8
|
+
END
|
9
|
+
|
10
|
+
def initialize argv
|
11
|
+
super
|
12
|
+
version_spec = argv.shift
|
13
|
+
version_spec = 'patch' if version_spec.nil?
|
14
|
+
verify! version_spec
|
15
|
+
return unless require_versionfile!
|
16
|
+
current_version = get_cookbook_version
|
17
|
+
new_version = bump_version version_spec, current_version
|
18
|
+
set_cookbook_version new_version
|
19
|
+
log.info "Bumped to #{new_version}."
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
def set_cookbook_version version
|
25
|
+
File.open('VERSION', 'w') { |f| f.write version }
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_cookbook_version
|
29
|
+
File.open('VERSION').read.strip
|
30
|
+
end
|
31
|
+
|
32
|
+
def verify! version_spec
|
33
|
+
case version_spec
|
34
|
+
when /major/
|
35
|
+
:major
|
36
|
+
when /minor/
|
37
|
+
:minor
|
38
|
+
when /patch/
|
39
|
+
:patch
|
40
|
+
when /\d+\.\d+\.\d+/
|
41
|
+
:manual
|
42
|
+
else
|
43
|
+
Trollop::die 'Invalid <version-spec> provided'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def bump_version version_spec, version
|
48
|
+
type = verify! version_spec
|
49
|
+
|
50
|
+
# I'm not really that thinky, so I stole this from knife-spork:
|
51
|
+
#
|
52
|
+
# https://github.com/jonlives/knife-spork/blob/master/lib/chef/knife/spork-bump.rb
|
53
|
+
#
|
54
|
+
if type == :manual
|
55
|
+
version_array = version_spec.split('.')
|
56
|
+
|
57
|
+
else
|
58
|
+
field = case type
|
59
|
+
when :patch ; 2
|
60
|
+
when :minor ; 1
|
61
|
+
when :major ; 0
|
62
|
+
end
|
63
|
+
|
64
|
+
version_array = version.split('.').map(&:to_i)
|
65
|
+
version_array[field] += 1
|
66
|
+
((field + 1)..2).each { |i| version_array[i] = 0 }
|
67
|
+
end
|
68
|
+
|
69
|
+
version_array.join('.')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
require 'pmap'
|
5
|
+
require 'gitlab'
|
6
|
+
|
7
|
+
|
8
|
+
module Bourdain
|
9
|
+
module Commands
|
10
|
+
|
11
|
+
class CheckCommand < Command
|
12
|
+
usage :command, <<-END
|
13
|
+
Check the state of the Kitchen, Bourdain and other things
|
14
|
+
check [<options>] [<check>]
|
15
|
+
<check>
|
16
|
+
END
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
def initialize argv
|
21
|
+
super
|
22
|
+
checks = Bourdain::Registry.specs('check')
|
23
|
+
maybe_check_position = checks.map { |c| argv.index c[:name].to_s }.compact.shift
|
24
|
+
check_position = maybe_check_position.nil? ? argv.length : maybe_check_position
|
25
|
+
|
26
|
+
options = argv.slice(0, check_position)
|
27
|
+
argv = argv.slice(check_position, argv.length)
|
28
|
+
|
29
|
+
super options
|
30
|
+
|
31
|
+
begin
|
32
|
+
gitlab_token = Bourdain::Config.items[:gitlab][:token]
|
33
|
+
rescue
|
34
|
+
log.fatal "Couldn't find your GitLab token in your config, bailing!"
|
35
|
+
error!
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
Gitlab.configure do |gitlab|
|
40
|
+
gitlab.endpoint = "http://#{Bourdain::GITLAB_HOST}/api/v3"
|
41
|
+
gitlab.private_token = gitlab_token
|
42
|
+
end
|
43
|
+
|
44
|
+
check = argv.shift
|
45
|
+
|
46
|
+
unless check.nil?
|
47
|
+
check = Bourdain::Registry.klass('check', check)
|
48
|
+
Trollop::die 'Invalid <check> provided' if check.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
return unless require_chef!
|
52
|
+
|
53
|
+
if check.nil?
|
54
|
+
@status = Bourdain::Registry.map('check') do |c|
|
55
|
+
c.new(cookbook_config_from_gitlab).status
|
56
|
+
end.sort.last
|
57
|
+
else
|
58
|
+
@status = check.new(cookbook_config_from_gitlab).status
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
private
|
65
|
+
def cookbook_config_from_gitlab
|
66
|
+
cookbook_configs = []
|
67
|
+
|
68
|
+
# Have to page results as GitLab absolutely will not return more than
|
69
|
+
# 100 results per page (even if we ask for more)
|
70
|
+
1.upto(25) do |page|
|
71
|
+
Gitlab.projects(per_page: 50, page: page).each do |project|
|
72
|
+
namespace, name = project.name_with_namespace.split(' / ', 2)
|
73
|
+
namespace = nil if name.nil?
|
74
|
+
next unless namespace == 'chef'
|
75
|
+
next if %w[ chef kitchen bourdain ].include? name
|
76
|
+
|
77
|
+
cookbook_name = name.sub(/^\w+?_/, '')
|
78
|
+
cookbook_path = name.sub(/^(\w+?)_/, '\1s/bjn_')
|
79
|
+
|
80
|
+
# Fork names shouldn't have the bjn_ prefix
|
81
|
+
if name =~ /^fork_/
|
82
|
+
cookbook_name.sub!(/(bjn|fork)_/, '')
|
83
|
+
cookbook_path.sub!(/(bjn|fork)_/, '')
|
84
|
+
end
|
85
|
+
|
86
|
+
name =~ /^(\w+?)_/
|
87
|
+
cookbook_type = $1.to_sym
|
88
|
+
|
89
|
+
cookbook_configs << {
|
90
|
+
name: cookbook_name,
|
91
|
+
type: cookbook_type,
|
92
|
+
path: cookbook_path,
|
93
|
+
repo: "#{namespace}/#{name}.git",
|
94
|
+
project: project
|
95
|
+
}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
cookbook_configs
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Commands
|
3
|
+
|
4
|
+
class GenerateCommand < Command
|
5
|
+
usage :command, <<-END
|
6
|
+
Generate various things. Take that, Chef DK!
|
7
|
+
generate [<options>] <generator>
|
8
|
+
<generator>
|
9
|
+
END
|
10
|
+
|
11
|
+
def initialize argv
|
12
|
+
generators = Bourdain::Registry.specs('generator')
|
13
|
+
maybe_generator_position = generators.map { |c| argv.index c[:name].to_s }.compact.shift
|
14
|
+
generator_position = maybe_generator_position.nil? ? argv.length : maybe_generator_position
|
15
|
+
generator_name = argv[generator_position]
|
16
|
+
|
17
|
+
options = argv.slice(0, generator_position)
|
18
|
+
argv = argv.slice(generator_position, argv.length)
|
19
|
+
|
20
|
+
super options
|
21
|
+
|
22
|
+
generator = nil
|
23
|
+
generator = argv.shift unless maybe_generator_position.nil?
|
24
|
+
Trollop::die 'Invalid <generator> provided' if generator.nil?
|
25
|
+
generator = Bourdain::Registry.klass('generator', generator_name)
|
26
|
+
Trollop::die 'Invalid <generator> provided' if generator.nil?
|
27
|
+
|
28
|
+
@status = generator.new(argv).status
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Generators
|
3
|
+
|
4
|
+
class AttributeGenerator < Generator
|
5
|
+
usage :generator, <<-END
|
6
|
+
Generate a new attribute file in the current cookbook
|
7
|
+
attribute [<options>] <name>
|
8
|
+
END
|
9
|
+
|
10
|
+
|
11
|
+
def initialize argv
|
12
|
+
super
|
13
|
+
|
14
|
+
name = argv.shift
|
15
|
+
Trollop::die 'No <name> provided' if name.nil?
|
16
|
+
Trollop::die 'Invalid <name> provided' unless valid? name
|
17
|
+
name = normalized(name)
|
18
|
+
|
19
|
+
return unless require_cookbook!
|
20
|
+
|
21
|
+
FileUtils.mkdir_p 'attributes'
|
22
|
+
path = File.join('attributes', name + '.rb')
|
23
|
+
|
24
|
+
if File::exists? path
|
25
|
+
log.warn "Attribute file already exists. Doing nothing."
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
cookbook_name = File.basename Dir.pwd
|
30
|
+
|
31
|
+
apply_template path, \
|
32
|
+
template: %w[ cookbook attributes example.rb ],
|
33
|
+
locals: {
|
34
|
+
cookbook_name: cookbook_name,
|
35
|
+
name: name
|
36
|
+
}
|
37
|
+
|
38
|
+
log.info "Generated attribute file at #{path}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'trollop'
|
2
|
+
|
3
|
+
|
4
|
+
module Bourdain
|
5
|
+
module Generators
|
6
|
+
|
7
|
+
class CookbookGenerator < Generator
|
8
|
+
usage :generator, <<-END
|
9
|
+
Generate a new cookbook in the current repo
|
10
|
+
cookbook [<options>] <path>
|
11
|
+
--dot-chef (-c) :: Generate a .chef directory (default: false)
|
12
|
+
--git-init :: Initialize a git repository (default: true)
|
13
|
+
--attributes :: Generate a default attribute file (default: true)
|
14
|
+
--recipe :: Generate a default recipe (default: true)
|
15
|
+
--berksfile :: Generate a Berksfile (default: true)
|
16
|
+
--gitignore (-i) :: Generate a .gitignore (default: true)
|
17
|
+
--metadata :: Generate cookbook metadata (default: true)
|
18
|
+
--readme (-m) :: Generate a Readme (default: true)
|
19
|
+
--kitchenfile :: Generate a Test Kitchen file (default: true)
|
20
|
+
--vagrantfile :: Generate a Vagrantfile (default: true)
|
21
|
+
--versionfile (-z) :: Generate a VERSION file (default: true)
|
22
|
+
--pre-commit :: Generate a pre-commit hook (default: true)
|
23
|
+
--description (-p) <s> :: Description for resources
|
24
|
+
END
|
25
|
+
|
26
|
+
def initialize argv
|
27
|
+
super
|
28
|
+
|
29
|
+
path = argv.shift
|
30
|
+
Trollop::die 'No <path> provided' if path.nil?
|
31
|
+
Trollop::die 'Invalid <path> provided' unless valid? path
|
32
|
+
|
33
|
+
return unless require_chef!
|
34
|
+
|
35
|
+
if Dir::exists? path
|
36
|
+
log.warn "Cookbook already exists. Doing nothing."
|
37
|
+
return
|
38
|
+
end
|
39
|
+
|
40
|
+
name = File.basename(normalized(path))
|
41
|
+
|
42
|
+
FileUtils.mkdir_p path
|
43
|
+
|
44
|
+
if opts[:dot_chef]
|
45
|
+
FileUtils.mkdir_p File.join(path, '.chef/data_bags')
|
46
|
+
FileUtils.mkdir_p File.join(path, '.chef/nodes')
|
47
|
+
end
|
48
|
+
|
49
|
+
if opts[:attributes]
|
50
|
+
FileUtils.mkdir_p File.join(path, 'attributes')
|
51
|
+
apply_template File.join(path, 'attributes', 'default.rb'), \
|
52
|
+
template: %w[ cookbook attributes example.rb ], locals: {
|
53
|
+
name: 'default', cookbook_name: name
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
if opts[:recipe]
|
58
|
+
FileUtils.mkdir_p File.join(path, 'recipes')
|
59
|
+
apply_template File.join(path, 'recipes', 'default.rb'), \
|
60
|
+
template: %w[ cookbook recipes example.rb ], locals: {
|
61
|
+
name: 'default', cookbook_name: name
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
if opts[:berksfile]
|
66
|
+
apply_template File.join(path, 'Berksfile'), \
|
67
|
+
template: %w[ cookbook Berksfile ]
|
68
|
+
end
|
69
|
+
|
70
|
+
if opts[:gitignore]
|
71
|
+
apply_template File.join(path, '.gitignore'), \
|
72
|
+
template: %w[ cookbook gitignore ]
|
73
|
+
end
|
74
|
+
|
75
|
+
if opts[:metadata]
|
76
|
+
apply_template File.join(path, 'metadata.rb'), \
|
77
|
+
template: %w[ cookbook metadata.rb ], locals: { name: name }
|
78
|
+
end
|
79
|
+
|
80
|
+
if opts[:readme]
|
81
|
+
apply_template File.join(path, 'Readme.md'), \
|
82
|
+
template: %w[ cookbook Readme.md ], locals: { name: name }
|
83
|
+
end
|
84
|
+
|
85
|
+
if opts[:kitchenfile]
|
86
|
+
minitest_path = File.join(path, 'test', 'integration', 'default', 'minitest')
|
87
|
+
FileUtils.mkdir_p minitest_path
|
88
|
+
apply_template File.join(minitest_path, 'test_default.rb'), \
|
89
|
+
template: %w[ cookbook busser_minitest.rb ], locals: {
|
90
|
+
cookbook_name: name, recipe_name: 'default'
|
91
|
+
}
|
92
|
+
apply_template File.join(path, '.kitchen.yml'), \
|
93
|
+
template: %w[ cookbook kitchen.yml ], locals: { name: name }
|
94
|
+
end
|
95
|
+
|
96
|
+
if opts[:vagrantfile]
|
97
|
+
apply_template File.join(path, 'Vagrantfile'), \
|
98
|
+
template: %w[ cookbook Vagrantfile ], locals: { name: name }
|
99
|
+
end
|
100
|
+
|
101
|
+
if opts[:versionfile]
|
102
|
+
apply_template File.join(path, 'VERSION'), \
|
103
|
+
template: %w[ cookbook VERSION ]
|
104
|
+
end
|
105
|
+
|
106
|
+
if opts[:pre_commit]
|
107
|
+
hooks = File.join(path, '.git', 'hooks')
|
108
|
+
FileUtils.mkdir_p hooks
|
109
|
+
pre_commit_hook = File.join(hooks, 'pre-commit')
|
110
|
+
apply_template pre_commit_hook, template: %w[ cookbook pre-commit ]
|
111
|
+
FileUtils.chmod 0755, pre_commit_hook
|
112
|
+
end
|
113
|
+
|
114
|
+
if opts[:git_init]
|
115
|
+
Dir.chdir(path) do
|
116
|
+
`git init .`
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
log.info "Generated cookbook at #{path}."
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Bourdain
|
2
|
+
module Generators
|
3
|
+
|
4
|
+
class RecipeGenerator < Generator
|
5
|
+
usage :generator, <<-END
|
6
|
+
Generate a new recipe in the current cookbook
|
7
|
+
recipe [<options>] <name>
|
8
|
+
--minitest :: Generate a minitest file (default: true)
|
9
|
+
END
|
10
|
+
|
11
|
+
|
12
|
+
def initialize argv
|
13
|
+
super
|
14
|
+
|
15
|
+
name = argv.shift
|
16
|
+
Trollop::die 'No <name> provided' if name.nil?
|
17
|
+
Trollop::die 'Invalid <name> provided' unless valid? name
|
18
|
+
name = normalized(name)
|
19
|
+
|
20
|
+
return unless require_cookbook!
|
21
|
+
|
22
|
+
FileUtils.mkdir_p 'recipes'
|
23
|
+
path = File.join('recipes', name + '.rb')
|
24
|
+
|
25
|
+
if File::exists? path
|
26
|
+
log.warn 'Recipe already exists. Doing nothing.'
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
cookbook_name = File.basename Dir.pwd
|
31
|
+
|
32
|
+
apply_template path, \
|
33
|
+
template: %w[ cookbook recipes example.rb ],
|
34
|
+
locals: {
|
35
|
+
cookbook_name: cookbook_name,
|
36
|
+
name: name
|
37
|
+
}
|
38
|
+
|
39
|
+
if opts[:minitest]
|
40
|
+
minitest_path = File.join('test', 'integration', 'default', 'minitest', "test_#{name}.rb")
|
41
|
+
FileUtils.mkdir_p File.dirname(minitest_path)
|
42
|
+
apply_template minitest_path, \
|
43
|
+
template: %w[ cookbook busser_minitest.rb ], locals: {
|
44
|
+
cookbook_name: cookbook_name, recipe_name: name
|
45
|
+
}
|
46
|
+
log.info "Generated test for recipe at #{minitest_path}."
|
47
|
+
end
|
48
|
+
|
49
|
+
log.info "Generated recipe at #{path}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
|
5
|
+
module Bourdain
|
6
|
+
module Generators
|
7
|
+
class Generator < Bourdain::Resource
|
8
|
+
protected
|
9
|
+
def valid? name
|
10
|
+
name =~ /[_a-z]+/
|
11
|
+
end
|
12
|
+
|
13
|
+
def normalized name
|
14
|
+
File::basename(name, '.rb')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require_relative 'generators/attribute'
|
21
|
+
require_relative 'generators/cookbook'
|
22
|
+
require_relative 'generators/recipe'
|