chef-gen-flavors 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/.rubocop.yml +23 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +242 -0
- data/Guardfile +15 -0
- data/History.md +10 -0
- data/LICENSE +15 -0
- data/Manifest.txt +46 -0
- data/README.md +311 -0
- data/Rakefile +85 -0
- data/chef-gen-flavors.gemspec +75 -0
- data/lib/chef_gen/flavor.rb +5 -0
- data/lib/chef_gen/flavor_base.rb +230 -0
- data/lib/chef_gen/flavors.rb +173 -0
- data/lib/chef_gen/snippet/attributes.rb +22 -0
- data/lib/chef_gen/snippet/chef_spec.rb +41 -0
- data/lib/chef_gen/snippet/cookbook_base.rb +64 -0
- data/lib/chef_gen/snippet/example_file.rb +23 -0
- data/lib/chef_gen/snippet/example_template.rb +25 -0
- data/lib/chef_gen/snippet/recipes.rb +22 -0
- data/lib/chef_gen/snippet/resource_provider.rb +24 -0
- data/lib/chef_gen/snippet/standard_ignore.rb +97 -0
- data/lib/chef_gen/snippet/style_rubocop.rb +14 -0
- data/lib/chef_gen/snippet/test_kitchen.rb +51 -0
- data/lib/chef_gen/snippets.rb +15 -0
- data/spec/lib/chef_gen/flavor_base_spec.rb +164 -0
- data/spec/lib/chef_gen/flavors_spec.rb +114 -0
- data/spec/lib/chef_gen/snippet/attributes_spec.rb +45 -0
- data/spec/lib/chef_gen/snippet/chef_spec_spec.rb +45 -0
- data/spec/lib/chef_gen/snippet/cookbook_base_spec.rb +37 -0
- data/spec/lib/chef_gen/snippet/example_file_spec.rb +45 -0
- data/spec/lib/chef_gen/snippet/example_template_spec.rb +45 -0
- data/spec/lib/chef_gen/snippet/recipes_spec.rb +45 -0
- data/spec/lib/chef_gen/snippet/resource_provider_spec.rb +45 -0
- data/spec/lib/chef_gen/snippet/standard_ignore_spec.rb +40 -0
- data/spec/lib/chef_gen/snippet/style_rubocop_spec.rb +36 -0
- data/spec/lib/chef_gen/snippet/test_kitchen_spec.rb +49 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/fixtures/code_generator/metadata.rb +2 -0
- data/spec/support/fixtures/code_generator/recipes/cookbook.rb +1 -0
- data/spec/support/fixtures/code_generator_2/metadata.rb +2 -0
- data/spec/support/fixtures/code_generator_2/recipes/cookbook.rb +1 -0
- data/spec/support/fixtures/lib/chef_gen/flavor/bar.rb +21 -0
- data/spec/support/fixtures/lib/chef_gen/flavor/baz.rb +6 -0
- data/spec/support/fixtures/lib/chef_gen/flavor/foo.rb +9 -0
- metadata +317 -0
data/Rakefile
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'chef_gen/flavors'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'hoe'
|
5
|
+
Hoe.plugin :gemspec
|
6
|
+
Hoe.plugins.delete :test
|
7
|
+
Hoe.spec 'chef-gen-flavors' do |s|
|
8
|
+
s.version = ChefGen::Flavors::VERSION
|
9
|
+
developer 'James FitzGibbon', 'james.i.fitzgibbon@nordstrom.com'
|
10
|
+
license 'apache2'
|
11
|
+
extra_deps << ['little-plugger', '~> 1.1']
|
12
|
+
extra_deps << ['bogo-ui', '~> 0.1']
|
13
|
+
extra_dev_deps << ['chef-dk', '~> 0.5']
|
14
|
+
extra_dev_deps << ['hoe', '~> 3.13']
|
15
|
+
extra_dev_deps << ['hoe-gemspec', '~> 1.0']
|
16
|
+
extra_dev_deps << ['rake', '~> 10.3']
|
17
|
+
extra_dev_deps << ['rspec', '~> 3.1']
|
18
|
+
extra_dev_deps << ['guard', '~> 2.12']
|
19
|
+
extra_dev_deps << ['guard-rspec', '~> 4.2']
|
20
|
+
extra_dev_deps << ['guard-rake', '~> 0.0']
|
21
|
+
extra_dev_deps << ['guard-rubocop', '~> 1.2']
|
22
|
+
extra_dev_deps << ['simplecov', '~> 0.9']
|
23
|
+
extra_dev_deps << ['simplecov-console', '~> 0.2']
|
24
|
+
extra_dev_deps << ['yard', '~> 0.8']
|
25
|
+
end
|
26
|
+
# re-generate our gemspec before packaging
|
27
|
+
task package: 'gem:spec'
|
28
|
+
rescue LoadError
|
29
|
+
puts 'hoe not available; disabling tasks'
|
30
|
+
end
|
31
|
+
|
32
|
+
# Style Tests
|
33
|
+
begin
|
34
|
+
require 'rubocop/rake_task'
|
35
|
+
RuboCop::RakeTask.new do |t|
|
36
|
+
t.formatters = ['progress']
|
37
|
+
t.options = ['-D']
|
38
|
+
t.patterns = %w(
|
39
|
+
lib/**/*.rb
|
40
|
+
spec/**/*.rb
|
41
|
+
./Rakefile
|
42
|
+
)
|
43
|
+
end
|
44
|
+
desc 'Run Style Tests'
|
45
|
+
task style: [:rubocop]
|
46
|
+
rescue LoadError
|
47
|
+
puts 'rubocop not available; disabling tasks'
|
48
|
+
end
|
49
|
+
|
50
|
+
# Unit Tests
|
51
|
+
begin
|
52
|
+
require 'rspec/core/rake_task'
|
53
|
+
RSpec::Core::RakeTask.new
|
54
|
+
|
55
|
+
# Coverage
|
56
|
+
desc 'Generate unit test coverage report'
|
57
|
+
task :coverage do
|
58
|
+
ENV['COVERAGE'] = 'true'
|
59
|
+
Rake::Task[:test].invoke
|
60
|
+
end
|
61
|
+
rescue LoadError
|
62
|
+
puts 'rspec not available; disabling tasks'
|
63
|
+
# create a no-op task so that :default works
|
64
|
+
task :test
|
65
|
+
end
|
66
|
+
|
67
|
+
# Documentation
|
68
|
+
begin
|
69
|
+
require 'yard'
|
70
|
+
require 'yard/rake/yardoc_task'
|
71
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
72
|
+
t.options = ['-m', 'markdown', '--private']
|
73
|
+
t.stats_options = ['--list-undoc']
|
74
|
+
end
|
75
|
+
rescue LoadError
|
76
|
+
puts 'yard not available; disabling tasks'
|
77
|
+
end
|
78
|
+
|
79
|
+
# test is an alias for spec
|
80
|
+
desc 'runs unit tests'
|
81
|
+
task test: [:spec]
|
82
|
+
|
83
|
+
# default is to test everything
|
84
|
+
desc 'runs all tests'
|
85
|
+
task default: :test
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# stub: chef-gen-flavors 0.3.0.20150514061941 ruby lib
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "chef-gen-flavors"
|
6
|
+
s.version = "0.3.0.20150514061941"
|
7
|
+
|
8
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
|
+
s.require_paths = ["lib"]
|
10
|
+
s.authors = ["James FitzGibbon"]
|
11
|
+
s.date = "2015-05-14"
|
12
|
+
s.description = "chef-gen-flavors is a framework for creating custom templates for the\n'chef generate' command provided by ChefDK.\n\nThis gem simply provides a framework; templates are provided by separate\ngems, which you can host privately for use within your organization or\npublicly for the Chef community to use.\n\nAt present this is focused primarily on providing templates for generation of\ncookbooks, as this is where most organization-specific customization takes place.\nSupport for the other artifacts that ChefDK can generate may work, but is not\nthe focus of early releases."
|
13
|
+
s.email = ["james.i.fitzgibbon@nordstrom.com"]
|
14
|
+
s.extra_rdoc_files = ["History.md", "Manifest.txt", "README.md"]
|
15
|
+
s.files = [".rspec", ".rubocop.yml", ".travis.yml", "Gemfile", "Gemfile.lock", "Guardfile", "History.md", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "chef-gen-flavors.gemspec", "lib/chef_gen/flavor.rb", "lib/chef_gen/flavor_base.rb", "lib/chef_gen/flavors.rb", "lib/chef_gen/snippet/attributes.rb", "lib/chef_gen/snippet/chef_spec.rb", "lib/chef_gen/snippet/cookbook_base.rb", "lib/chef_gen/snippet/example_file.rb", "lib/chef_gen/snippet/example_template.rb", "lib/chef_gen/snippet/recipes.rb", "lib/chef_gen/snippet/resource_provider.rb", "lib/chef_gen/snippet/standard_ignore.rb", "lib/chef_gen/snippet/style_rubocop.rb", "lib/chef_gen/snippet/test_kitchen.rb", "lib/chef_gen/snippets.rb", "spec/lib/chef_gen/flavor_base_spec.rb", "spec/lib/chef_gen/flavors_spec.rb", "spec/lib/chef_gen/snippet/attributes_spec.rb", "spec/lib/chef_gen/snippet/chef_spec_spec.rb", "spec/lib/chef_gen/snippet/cookbook_base_spec.rb", "spec/lib/chef_gen/snippet/example_file_spec.rb", "spec/lib/chef_gen/snippet/example_template_spec.rb", "spec/lib/chef_gen/snippet/recipes_spec.rb", "spec/lib/chef_gen/snippet/resource_provider_spec.rb", "spec/lib/chef_gen/snippet/standard_ignore_spec.rb", "spec/lib/chef_gen/snippet/style_rubocop_spec.rb", "spec/lib/chef_gen/snippet/test_kitchen_spec.rb", "spec/spec_helper.rb", "spec/support/fixtures/code_generator/metadata.rb", "spec/support/fixtures/code_generator/recipes/cookbook.rb", "spec/support/fixtures/code_generator_2/metadata.rb", "spec/support/fixtures/code_generator_2/recipes/cookbook.rb", "spec/support/fixtures/lib/chef_gen/flavor/bar.rb", "spec/support/fixtures/lib/chef_gen/flavor/baz.rb", "spec/support/fixtures/lib/chef_gen/flavor/foo.rb"]
|
16
|
+
s.homepage = "https://github.com/Nordstrom/chef-gen-flavors"
|
17
|
+
s.licenses = ["apache2"]
|
18
|
+
s.rdoc_options = ["--main", "README.md"]
|
19
|
+
s.rubygems_version = "2.4.4"
|
20
|
+
s.summary = "chef-gen-flavors is a framework for creating custom templates for the 'chef generate' command provided by ChefDK"
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
s.specification_version = 4
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_runtime_dependency(%q<little-plugger>, ["~> 1.1"])
|
27
|
+
s.add_runtime_dependency(%q<bogo-ui>, ["~> 0.1"])
|
28
|
+
s.add_development_dependency(%q<rdoc>, ["~> 4.0"])
|
29
|
+
s.add_development_dependency(%q<chef-dk>, ["~> 0.5"])
|
30
|
+
s.add_development_dependency(%q<hoe>, ["~> 3.13"])
|
31
|
+
s.add_development_dependency(%q<hoe-gemspec>, ["~> 1.0"])
|
32
|
+
s.add_development_dependency(%q<rake>, ["~> 10.3"])
|
33
|
+
s.add_development_dependency(%q<rspec>, ["~> 3.1"])
|
34
|
+
s.add_development_dependency(%q<guard>, ["~> 2.12"])
|
35
|
+
s.add_development_dependency(%q<guard-rspec>, ["~> 4.2"])
|
36
|
+
s.add_development_dependency(%q<guard-rake>, ["~> 0.0"])
|
37
|
+
s.add_development_dependency(%q<guard-rubocop>, ["~> 1.2"])
|
38
|
+
s.add_development_dependency(%q<simplecov>, ["~> 0.9"])
|
39
|
+
s.add_development_dependency(%q<simplecov-console>, ["~> 0.2"])
|
40
|
+
s.add_development_dependency(%q<yard>, ["~> 0.8"])
|
41
|
+
else
|
42
|
+
s.add_dependency(%q<little-plugger>, ["~> 1.1"])
|
43
|
+
s.add_dependency(%q<bogo-ui>, ["~> 0.1"])
|
44
|
+
s.add_dependency(%q<rdoc>, ["~> 4.0"])
|
45
|
+
s.add_dependency(%q<chef-dk>, ["~> 0.5"])
|
46
|
+
s.add_dependency(%q<hoe>, ["~> 3.13"])
|
47
|
+
s.add_dependency(%q<hoe-gemspec>, ["~> 1.0"])
|
48
|
+
s.add_dependency(%q<rake>, ["~> 10.3"])
|
49
|
+
s.add_dependency(%q<rspec>, ["~> 3.1"])
|
50
|
+
s.add_dependency(%q<guard>, ["~> 2.12"])
|
51
|
+
s.add_dependency(%q<guard-rspec>, ["~> 4.2"])
|
52
|
+
s.add_dependency(%q<guard-rake>, ["~> 0.0"])
|
53
|
+
s.add_dependency(%q<guard-rubocop>, ["~> 1.2"])
|
54
|
+
s.add_dependency(%q<simplecov>, ["~> 0.9"])
|
55
|
+
s.add_dependency(%q<simplecov-console>, ["~> 0.2"])
|
56
|
+
s.add_dependency(%q<yard>, ["~> 0.8"])
|
57
|
+
end
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<little-plugger>, ["~> 1.1"])
|
60
|
+
s.add_dependency(%q<bogo-ui>, ["~> 0.1"])
|
61
|
+
s.add_dependency(%q<rdoc>, ["~> 4.0"])
|
62
|
+
s.add_dependency(%q<chef-dk>, ["~> 0.5"])
|
63
|
+
s.add_dependency(%q<hoe>, ["~> 3.13"])
|
64
|
+
s.add_dependency(%q<hoe-gemspec>, ["~> 1.0"])
|
65
|
+
s.add_dependency(%q<rake>, ["~> 10.3"])
|
66
|
+
s.add_dependency(%q<rspec>, ["~> 3.1"])
|
67
|
+
s.add_dependency(%q<guard>, ["~> 2.12"])
|
68
|
+
s.add_dependency(%q<guard-rspec>, ["~> 4.2"])
|
69
|
+
s.add_dependency(%q<guard-rake>, ["~> 0.0"])
|
70
|
+
s.add_dependency(%q<guard-rubocop>, ["~> 1.2"])
|
71
|
+
s.add_dependency(%q<simplecov>, ["~> 0.9"])
|
72
|
+
s.add_dependency(%q<simplecov-console>, ["~> 0.2"])
|
73
|
+
s.add_dependency(%q<yard>, ["~> 0.8"])
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'chef-dk/generator'
|
2
|
+
|
3
|
+
module ChefGen
|
4
|
+
# a base for ChefDK Template Flavors
|
5
|
+
class FlavorBase
|
6
|
+
# the target path of 'chef generate'
|
7
|
+
# @return [String] path
|
8
|
+
attr_reader :target_path
|
9
|
+
|
10
|
+
# directories to create
|
11
|
+
# @return [Array] list of directories
|
12
|
+
attr_reader :directories
|
13
|
+
|
14
|
+
# the file patterns to write to the chefignore files
|
15
|
+
# @return [Array] list of file patterns
|
16
|
+
attr_reader :chefignore_files
|
17
|
+
|
18
|
+
# the file patterns to add to .gitignore
|
19
|
+
# @return [Array] list of file patterns
|
20
|
+
attr_reader :gitignore_files
|
21
|
+
|
22
|
+
# files to create unconditionally
|
23
|
+
# @return [Array] list of destination filenames
|
24
|
+
attr_reader :files
|
25
|
+
|
26
|
+
# files to create only if they do not exist
|
27
|
+
# @return [Array] list of destination filenames
|
28
|
+
attr_reader :files_if_missing
|
29
|
+
|
30
|
+
# templates to render unconditionally
|
31
|
+
# @return [Array] list of destination filenames
|
32
|
+
attr_reader :templates
|
33
|
+
|
34
|
+
# templates to render only if they do not exist
|
35
|
+
# @return [Array] list of destination filenames
|
36
|
+
attr_reader :templates_if_missing
|
37
|
+
|
38
|
+
# an informational block about how the user should proceed
|
39
|
+
# @return [String] instructions
|
40
|
+
attr_accessor :next_steps
|
41
|
+
|
42
|
+
# whether to fail if files would be overwritten
|
43
|
+
# @return [Boolean] true to fail on attempted overwrite
|
44
|
+
attr_accessor :fail_on_clobber
|
45
|
+
|
46
|
+
# whether to report the actions that were taken
|
47
|
+
# @return [Boolean] true to report actions
|
48
|
+
attr_accessor :report_actions
|
49
|
+
|
50
|
+
# creates a new flavor object
|
51
|
+
# @param recipe [Chef::Recipe] the recipe into which
|
52
|
+
# resources will be injected
|
53
|
+
# @return [self]
|
54
|
+
def initialize(recipe)
|
55
|
+
# store the recipe we'll be injecting resources into
|
56
|
+
@recipe = recipe
|
57
|
+
|
58
|
+
# derive our target path
|
59
|
+
ctx = ChefDK::Generator.context
|
60
|
+
@target_path = File.expand_path(
|
61
|
+
File.join(ctx.cookbook_root, ctx.cookbook_name)
|
62
|
+
)
|
63
|
+
|
64
|
+
# set defaults
|
65
|
+
@report_actions = true
|
66
|
+
@fail_on_clobber = !ctx.respond_to?(:clobber)
|
67
|
+
@directories = [''] # root directory
|
68
|
+
%w(files files_if_missing templates templates_if_missing
|
69
|
+
chefignore_files gitignore_files actions_taken failures)
|
70
|
+
.each do |varname|
|
71
|
+
instance_variable_set("@#{varname}".to_sym, [])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# generates the Chef resources that the plugin has declared
|
76
|
+
# @return [void]
|
77
|
+
def generate
|
78
|
+
run_mixins
|
79
|
+
add_directories
|
80
|
+
add_files
|
81
|
+
add_templates
|
82
|
+
unless @failures.empty?
|
83
|
+
@failures.each { |f| $stderr.puts f }
|
84
|
+
fail 'errors during generation'
|
85
|
+
end
|
86
|
+
build_ignore('.gitignore', @gitignore_files)
|
87
|
+
build_ignore('chefignore', @chefignore_files)
|
88
|
+
report_actions_taken(@actions_taken) \
|
89
|
+
if @report_actions && @actions_taken
|
90
|
+
display_next_steps(@next_steps) if @next_steps
|
91
|
+
end
|
92
|
+
|
93
|
+
# given a destination file, returns a flattened source
|
94
|
+
# filename by replacing / and . with _
|
95
|
+
# @param path [String] the destination file
|
96
|
+
# @return [String] the flattened source file
|
97
|
+
# @example convert a destination file
|
98
|
+
# source_path('spec/spec_helper.rb') #=> 'spec_spec_helper_rb'
|
99
|
+
def source_path(path)
|
100
|
+
path.tr('/.', '_')
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
# find all public methods of the plugin starting with snippet_
|
106
|
+
# and calls them
|
107
|
+
# @return [void]
|
108
|
+
# @yield [Chef::Recipe] the recipe into which the mixin can inject
|
109
|
+
# resources
|
110
|
+
# @api private
|
111
|
+
def run_mixins
|
112
|
+
snippets = public_methods.select do |m|
|
113
|
+
m.to_s =~ /^snippet_/
|
114
|
+
end
|
115
|
+
snippets.each do |m|
|
116
|
+
send(m, @recipe)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# declares a directory resource for each element of @directories
|
121
|
+
# @return [void]
|
122
|
+
# @api private
|
123
|
+
def add_directories
|
124
|
+
@directories.flatten.each do |dirname|
|
125
|
+
path = File.join(@target_path, dirname)
|
126
|
+
@recipe.send(:directory, path)
|
127
|
+
@actions_taken << "create directory #{path}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# declares a cookbook_file resource for each element of '#files' and
|
132
|
+
# '#files_if_missing', respecting the value of '#fail_on_clobber'
|
133
|
+
# @return [void]
|
134
|
+
# @api private
|
135
|
+
def add_files
|
136
|
+
_add_files(
|
137
|
+
@files, nil, @fail_on_clobber, :cookbook_file, :create
|
138
|
+
)
|
139
|
+
_add_files(
|
140
|
+
@files_if_missing, nil, false, :cookbook_file, :create_if_missing
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
# declares a template resource for each element of '#templates' and
|
145
|
+
# '#templates_if_missing', respecting the value of '#fail_on_clobber'
|
146
|
+
# @return [void]
|
147
|
+
# @api private
|
148
|
+
def add_templates
|
149
|
+
_add_files(
|
150
|
+
@templates, '.erb', @fail_on_clobber, :template, :create
|
151
|
+
)
|
152
|
+
_add_files(
|
153
|
+
@templates_if_missing, '.erb', false, :template, :create_if_missing
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
# does the heavy lifting for add_files and add_templates
|
158
|
+
# @param files [Array] the list of things to declare
|
159
|
+
# @param suffix [String] a suffix to add to the source file
|
160
|
+
# @param clobberfail [Boolean] whether to protect against
|
161
|
+
# overwriting files
|
162
|
+
# @param resource [Symbol] the symbolized Chef resource to declare
|
163
|
+
# @param resource_action [Symbol] the action to give the resource
|
164
|
+
# @return [void]
|
165
|
+
# @api private
|
166
|
+
def _add_files(files, suffix, clobberfail, resource, resource_action)
|
167
|
+
files.flatten.each do |filename|
|
168
|
+
src = "#{source_path(filename)}#{suffix}"
|
169
|
+
dst = File.join(@target_path, filename)
|
170
|
+
if clobberfail && File.exist?(dst)
|
171
|
+
@failures << "tried to overwrite file #{dst}"
|
172
|
+
else
|
173
|
+
@recipe.send(resource, dst) do
|
174
|
+
# :nocov:
|
175
|
+
source src
|
176
|
+
action resource_action
|
177
|
+
helpers(ChefDK::Generator::TemplateHelper) \
|
178
|
+
if :template == resource
|
179
|
+
# :nocov:
|
180
|
+
end
|
181
|
+
@actions_taken << "create file #{dst}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# creates a .gitignore or chefignore file
|
187
|
+
# @param dstfile [String] the destination file
|
188
|
+
# @param files [Array] an array of lines to write to the file
|
189
|
+
# @return [void]
|
190
|
+
# @api private
|
191
|
+
def build_ignore(dstfile, files)
|
192
|
+
return if files.empty?
|
193
|
+
dst = File.join(@target_path, dstfile)
|
194
|
+
@recipe.send(:file, dst) do
|
195
|
+
# :nocov:
|
196
|
+
content files.flatten.join("\n")
|
197
|
+
# :nocov:
|
198
|
+
end
|
199
|
+
@actions_taken << "create ignore file #{dst}"
|
200
|
+
end
|
201
|
+
|
202
|
+
# reports on the actions taken by the plugin
|
203
|
+
# @param actions [Array] the list of actions taken
|
204
|
+
# @return [void]
|
205
|
+
# @api private
|
206
|
+
def report_actions_taken(actions)
|
207
|
+
@recipe.send(:ruby_block, 'report_actions_taken') do
|
208
|
+
# :nocov:
|
209
|
+
block do
|
210
|
+
$stdout.puts "\n\nactions taken:"
|
211
|
+
actions.each { |a| $stdout.puts " #{a}" }
|
212
|
+
end
|
213
|
+
# :nocov:
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# displays the next steps for the user to take
|
218
|
+
# @return [void]
|
219
|
+
# @api private
|
220
|
+
def display_next_steps(next_steps)
|
221
|
+
@recipe.send(:ruby_block, 'display_next_steps') do
|
222
|
+
# :nocov:
|
223
|
+
block do
|
224
|
+
$stdout.puts next_steps
|
225
|
+
end
|
226
|
+
# :nocov:
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'little-plugger'
|
2
|
+
|
3
|
+
require 'chef_gen/flavor'
|
4
|
+
|
5
|
+
# chef generators
|
6
|
+
module ChefGen
|
7
|
+
# a plugin framework for creating ChefDK generator flavors
|
8
|
+
class Flavors
|
9
|
+
# the version of the gem
|
10
|
+
VERSION = '0.3.0'
|
11
|
+
|
12
|
+
extend LittlePlugger path: 'chef_gen/flavor',
|
13
|
+
module: ChefGen::Flavor
|
14
|
+
|
15
|
+
class << self
|
16
|
+
# return the path to to the code_generator cookbook for
|
17
|
+
# the selected ChefGen Flavor
|
18
|
+
# @return [String] the path to the code_generator cookbook
|
19
|
+
def path
|
20
|
+
# validate what LittlePlugger found
|
21
|
+
validate_plugins
|
22
|
+
# then take a copy so we can augment it
|
23
|
+
@plugins = plugins.dup
|
24
|
+
add_builtin_template
|
25
|
+
selected = plugin_from_env ||
|
26
|
+
only_plugin ||
|
27
|
+
prompt_for_plugin ||
|
28
|
+
fail('no ChefGen flavors found!')
|
29
|
+
path = generator_path(selected)
|
30
|
+
$stdout.puts "using ChefGen flavor '#{selected}' in #{path}"
|
31
|
+
path
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# validates all plugins found by LittlePlugger
|
37
|
+
# @raise RuntimeError if any plugin is invalid
|
38
|
+
# @return [void]
|
39
|
+
# @api private
|
40
|
+
def validate_plugins
|
41
|
+
plugins.each do |name, klass|
|
42
|
+
fail "no description for plugin #{name}" \
|
43
|
+
unless klass.respond_to?(:description)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# checks if the plugin to use has been specified in the environment
|
48
|
+
# variable CHEFGEN_FLAVOR
|
49
|
+
# @return [Symbol,nil] the plugin if specified and found, nil otherwise
|
50
|
+
# @api private
|
51
|
+
def plugin_from_env
|
52
|
+
if ENV.key?('CHEFGEN_FLAVOR')
|
53
|
+
candidate = ENV['CHEFGEN_FLAVOR'].downcase.to_sym
|
54
|
+
return candidate if plugins.key?(candidate)
|
55
|
+
end
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
# if the environment variable CHEFDK_FLAVOR is defined, adds
|
60
|
+
# the built-in template that comes with ChefDK to the list of available
|
61
|
+
# plugins
|
62
|
+
# @return [void]
|
63
|
+
# @api private
|
64
|
+
def add_builtin_template
|
65
|
+
@plugins[:builtin] = true if ENV.key?('CHEFDK_FLAVOR')
|
66
|
+
end
|
67
|
+
|
68
|
+
# returns the sole installed plugin if only one is found
|
69
|
+
# @return [Symbol,nil] the plugin if only one is installed,
|
70
|
+
# nil otherwise
|
71
|
+
# @api private
|
72
|
+
def only_plugin
|
73
|
+
@plugins.keys.size == 1 ? @plugins.keys.first : nil
|
74
|
+
end
|
75
|
+
|
76
|
+
# :nocov:
|
77
|
+
|
78
|
+
# prompts the user for a plugin to use if more than one is available
|
79
|
+
# @return [Symbol] the selected plugin
|
80
|
+
# @raise RuntimeError if an invalid plugin is chosen
|
81
|
+
# @api private
|
82
|
+
def prompt_for_plugin
|
83
|
+
return nil unless @plugins.keys.size >= 1
|
84
|
+
require 'bogo-ui'
|
85
|
+
ui = Bogo::Ui.new(app_name: 'ChefGen Flavor Selector')
|
86
|
+
valid = plugin_selection(ui)
|
87
|
+
response = ui.ask_question('Enter selection').to_i
|
88
|
+
return valid[response.to_i] if valid[response]
|
89
|
+
ui.fatal 'Invalid flavor chosen'
|
90
|
+
fail 'Invalid ChefGen Flavor'
|
91
|
+
end
|
92
|
+
|
93
|
+
# builds a list of plugins and displays them with as
|
94
|
+
# a number selection list
|
95
|
+
# @param ui [Bogo::Ui] the ui object to use for display
|
96
|
+
# @return [Hash] a hash of valid options
|
97
|
+
# @api private
|
98
|
+
def plugin_selection(ui)
|
99
|
+
output = [ui.color('Flavors on the menu', :bold)]
|
100
|
+
idx = 1
|
101
|
+
valid = {}
|
102
|
+
@plugins.each do |name, klass|
|
103
|
+
valid[idx] = name
|
104
|
+
if true == klass
|
105
|
+
output << "#{idx}. ChefDK built-in template"
|
106
|
+
else
|
107
|
+
output << "#{idx}. #{name}: #{klass.description}"
|
108
|
+
end
|
109
|
+
idx += 1
|
110
|
+
end
|
111
|
+
ui.info "#{output.join("\n")}\n"
|
112
|
+
valid
|
113
|
+
end
|
114
|
+
# :nocov:
|
115
|
+
|
116
|
+
# returns the path to the code_generator cookbook for the
|
117
|
+
# selected plugin. Handles the built-in template path,
|
118
|
+
# a plugin that overrides the path and a plugin that uses
|
119
|
+
# the default path
|
120
|
+
# @param plugin [Symbol] the selected plugin
|
121
|
+
# @return [String] the path to the code_generator cookbook
|
122
|
+
# @api private
|
123
|
+
def generator_path(plugin)
|
124
|
+
return builtin_code_generator_path if :builtin == plugin
|
125
|
+
klass = @plugins[plugin]
|
126
|
+
classfile = path_to_plugin(klass)
|
127
|
+
if klass.respond_to?(:code_generator_path)
|
128
|
+
klass.code_generator_path(classfile)
|
129
|
+
else
|
130
|
+
default_code_generator_path(classfile)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# returns the path of the file where the description method
|
135
|
+
# is defined for a given class
|
136
|
+
# @param klass [Class] the class to look up the method in
|
137
|
+
# @return [String] the path to the source file for the class
|
138
|
+
# @api private
|
139
|
+
def path_to_plugin(klass)
|
140
|
+
klass.method(:description).source_location[0]
|
141
|
+
end
|
142
|
+
|
143
|
+
# returns the default path to the code generator cookbook for
|
144
|
+
# a plugin, which is a directory named 'code_generator' four
|
145
|
+
# levels above the file which defines the plugin class
|
146
|
+
# @param classfile [String] the path to the class source, as
|
147
|
+
# returned from ::path_to_plugin
|
148
|
+
# @return [String] the path to the code_generator cookbook
|
149
|
+
# @api private
|
150
|
+
def default_code_generator_path(classfile)
|
151
|
+
File.expand_path(
|
152
|
+
File.join(
|
153
|
+
classfile,
|
154
|
+
'..', '..', '..', '..',
|
155
|
+
'code_generator'
|
156
|
+
)
|
157
|
+
)
|
158
|
+
end
|
159
|
+
|
160
|
+
# return the path to the code_generator cookbook that comes
|
161
|
+
# with ChefDK
|
162
|
+
# @return [String] the path to the code_generator cookbook
|
163
|
+
# @api private
|
164
|
+
def builtin_code_generator_path
|
165
|
+
require 'rubygems'
|
166
|
+
spec = Gem::Specification.find_by_name('chef-dk')
|
167
|
+
File.join(
|
168
|
+
spec.gem_dir, 'lib', 'chef-dk', 'skeletons', 'code_generator'
|
169
|
+
)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|