chef-gen-flavors 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/.rubocop.yml +23 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +242 -0
  7. data/Guardfile +15 -0
  8. data/History.md +10 -0
  9. data/LICENSE +15 -0
  10. data/Manifest.txt +46 -0
  11. data/README.md +311 -0
  12. data/Rakefile +85 -0
  13. data/chef-gen-flavors.gemspec +75 -0
  14. data/lib/chef_gen/flavor.rb +5 -0
  15. data/lib/chef_gen/flavor_base.rb +230 -0
  16. data/lib/chef_gen/flavors.rb +173 -0
  17. data/lib/chef_gen/snippet/attributes.rb +22 -0
  18. data/lib/chef_gen/snippet/chef_spec.rb +41 -0
  19. data/lib/chef_gen/snippet/cookbook_base.rb +64 -0
  20. data/lib/chef_gen/snippet/example_file.rb +23 -0
  21. data/lib/chef_gen/snippet/example_template.rb +25 -0
  22. data/lib/chef_gen/snippet/recipes.rb +22 -0
  23. data/lib/chef_gen/snippet/resource_provider.rb +24 -0
  24. data/lib/chef_gen/snippet/standard_ignore.rb +97 -0
  25. data/lib/chef_gen/snippet/style_rubocop.rb +14 -0
  26. data/lib/chef_gen/snippet/test_kitchen.rb +51 -0
  27. data/lib/chef_gen/snippets.rb +15 -0
  28. data/spec/lib/chef_gen/flavor_base_spec.rb +164 -0
  29. data/spec/lib/chef_gen/flavors_spec.rb +114 -0
  30. data/spec/lib/chef_gen/snippet/attributes_spec.rb +45 -0
  31. data/spec/lib/chef_gen/snippet/chef_spec_spec.rb +45 -0
  32. data/spec/lib/chef_gen/snippet/cookbook_base_spec.rb +37 -0
  33. data/spec/lib/chef_gen/snippet/example_file_spec.rb +45 -0
  34. data/spec/lib/chef_gen/snippet/example_template_spec.rb +45 -0
  35. data/spec/lib/chef_gen/snippet/recipes_spec.rb +45 -0
  36. data/spec/lib/chef_gen/snippet/resource_provider_spec.rb +45 -0
  37. data/spec/lib/chef_gen/snippet/standard_ignore_spec.rb +40 -0
  38. data/spec/lib/chef_gen/snippet/style_rubocop_spec.rb +36 -0
  39. data/spec/lib/chef_gen/snippet/test_kitchen_spec.rb +49 -0
  40. data/spec/spec_helper.rb +38 -0
  41. data/spec/support/fixtures/code_generator/metadata.rb +2 -0
  42. data/spec/support/fixtures/code_generator/recipes/cookbook.rb +1 -0
  43. data/spec/support/fixtures/code_generator_2/metadata.rb +2 -0
  44. data/spec/support/fixtures/code_generator_2/recipes/cookbook.rb +1 -0
  45. data/spec/support/fixtures/lib/chef_gen/flavor/bar.rb +21 -0
  46. data/spec/support/fixtures/lib/chef_gen/flavor/baz.rb +6 -0
  47. data/spec/support/fixtures/lib/chef_gen/flavor/foo.rb +9 -0
  48. metadata +317 -0
@@ -0,0 +1,22 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # a cookbook that has attributes
4
+ module Attributes
5
+ # declares directories
6
+ # @param recipe [Chef::Recipe] the recipe into which resources
7
+ # will be injected
8
+ # @return [void]
9
+ def snippet_attributes_dirs(recipe)
10
+ @directories << 'attributes'
11
+ end
12
+
13
+ # declares files
14
+ # @param recipe [Chef::Recipe] the recipe into which resources
15
+ # will be injected
16
+ # @return [void]
17
+ def snippet_attributes_files(recipe)
18
+ @templates_if_missing << File.join('attributes', 'default.rb')
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,41 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # creates a framework for ChefSpec unit testing
4
+ module ChefSpec
5
+ # declares the .rspec file
6
+ # @param recipe [Chef::Recipe] the recipe into which resources
7
+ # will be injected
8
+ # @return [void]
9
+ def snippet_chefspec_dotrspec(recipe)
10
+ @templates << '.rspec'
11
+ end
12
+
13
+ # declares the ChefSpec directories
14
+ # @param recipe [Chef::Recipe] the recipe into which resources
15
+ # will be injected
16
+ # @return [void]
17
+ def snippet_chefspec_dirs(recipe)
18
+ @directories << 'spec'
19
+ @directories << File.join('spec', 'recipes')
20
+ end
21
+
22
+ # declares the ChefSpec spec_helper
23
+ # @param recipe [Chef::Recipe] the recipe into which resources
24
+ # will be injected
25
+ # @return [void]
26
+ def snippet_chefspec_spechelper(recipe)
27
+ @templates_if_missing << File.join('spec', 'spec_helper.rb')
28
+ end
29
+
30
+ # declares the default recipe spec
31
+ # @param recipe [Chef::Recipe] the recipe into which resources
32
+ # will be injected
33
+ # @return [void]
34
+ def snippet_chefspec_defaultrecipespec(recipe)
35
+ @templates_if_missing << File.join(
36
+ 'spec', 'recipes', 'default_spec.rb'
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,64 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # creates the basic files that every cookbook should have
4
+ # each file is managed through a separate method to allow for
5
+ # people to mix this in but turn off just one file
6
+ module CookbookBase
7
+ # declares the Gemfile
8
+ # @param recipe [Chef::Recipe] the recipe into which resources
9
+ # will be injected
10
+ # @return [void]
11
+ def snippet_cookbookbase_gemfile(recipe)
12
+ @templates << 'Gemfile'
13
+ end
14
+
15
+ # declares the Berksfile
16
+ # @param recipe [Chef::Recipe] the recipe into which resources
17
+ # will be injected
18
+ # @return [void]
19
+ def snippet_cookbookbase_berksfile(recipe)
20
+ @templates << 'Berksfile'
21
+ end
22
+
23
+ # declares the Rakefile
24
+ # @param recipe [Chef::Recipe] the recipe into which resources
25
+ # will be injected
26
+ # @return [void]
27
+ def snippet_cookbookbase_rakefile(recipe)
28
+ @templates << 'Rakefile'
29
+ end
30
+
31
+ # declares the Guardfile
32
+ # @param recipe [Chef::Recipe] the recipe into which resources
33
+ # will be injected
34
+ # @return [void]
35
+ def snippet_cookbookbase_guardfile(recipe)
36
+ @templates << 'Guardfile'
37
+ end
38
+
39
+ # declares the metadata.rb file
40
+ # @param recipe [Chef::Recipe] the recipe into which resources
41
+ # will be injected
42
+ # @return [void]
43
+ def snippet_cookbookbase_metadata(recipe)
44
+ @templates_if_missing << 'metadata.rb'
45
+ end
46
+
47
+ # declares the README file
48
+ # @param recipe [Chef::Recipe] the recipe into which resources
49
+ # will be injected
50
+ # @return [void]
51
+ def snippet_cookbookbase_readme(recipe)
52
+ @templates_if_missing << 'README.md'
53
+ end
54
+
55
+ # declares the CHANGELOG
56
+ # @param recipe [Chef::Recipe] the recipe into which resources
57
+ # will be injected
58
+ # @return [void]
59
+ def snippet_cookbookbase_changelog(recipe)
60
+ @templates_if_missing << 'CHANGELOG.md'
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,23 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # a sample cookbook_file source
4
+ module ExampleFile
5
+ # declares directories
6
+ # @param recipe [Chef::Recipe] the recipe into which resources
7
+ # will be injected
8
+ # @return [void]
9
+ def snippet_examplefile_dirs(recipe)
10
+ @directories << 'files'
11
+ @directories << File.join('files', 'default')
12
+ end
13
+
14
+ # declares files
15
+ # @param recipe [Chef::Recipe] the recipe into which resources
16
+ # will be injected
17
+ # @return [void]
18
+ def snippet_examplefile_files(recipe)
19
+ @files_if_missing << File.join('files', 'default', 'example.conf')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # a sample template source
4
+ module ExampleTemplate
5
+ # declares directories
6
+ # @param recipe [Chef::Recipe] the recipe into which resources
7
+ # will be injected
8
+ # @return [void]
9
+ def snippet_exampletemplate_dirs(recipe)
10
+ @directories << 'templates'
11
+ @directories << File.join('templates', 'default')
12
+ end
13
+
14
+ # declares files
15
+ # @param recipe [Chef::Recipe] the recipe into which resources
16
+ # will be injected
17
+ # @return [void]
18
+ def snippet_exampletemplate_files(recipe)
19
+ @files_if_missing << File.join(
20
+ 'templates', 'default', 'example.conf.erb'
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # a cookbook that has recipes
4
+ module Recipes
5
+ # declares directories
6
+ # @param recipe [Chef::Recipe] the recipe into which resources
7
+ # will be injected
8
+ # @return [void]
9
+ def snippet_recipes_dirs(recipe)
10
+ @directories << 'recipes'
11
+ end
12
+
13
+ # declares files
14
+ # @param recipe [Chef::Recipe] the recipe into which resources
15
+ # will be injected
16
+ # @return [void]
17
+ def snippet_recipes_files(recipe)
18
+ @templates_if_missing << File.join('recipes', 'default.rb')
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # a cookbook that has provides resources and providers
4
+ module ResourceProvider
5
+ # declares directories
6
+ # @param recipe [Chef::Recipe] the recipe into which resources
7
+ # will be injected
8
+ # @return [void]
9
+ def snippet_resourceprovider_dirs(recipe)
10
+ @directories << 'resources'
11
+ @directories << 'providers'
12
+ end
13
+
14
+ # declares files
15
+ # @param recipe [Chef::Recipe] the recipe into which resources
16
+ # will be injected
17
+ # @return [void]
18
+ def snippet_resourceprovider_files(recipe)
19
+ @templates_if_missing << File.join('resources', 'default.rb')
20
+ @templates_if_missing << File.join('providers', 'default.rb')
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,97 @@
1
+ # rubocop:disable Metrics/MethodLength
2
+ module ChefGen
3
+ module Snippet
4
+ # populates the list of ignore patterns for chefignore and .gitignore
5
+ module StandardIgnore
6
+ # adds ignore patterns for chefignore
7
+ # @param recipe [Chef::Recipe] the recipe into which resources
8
+ # will be injected
9
+ # @return [void]
10
+ def snippet_standardignore_chefignore(recipe)
11
+ @chefignore_files << <<END.split("\n")
12
+ .DS_Store
13
+ Icon?
14
+ nohup.out
15
+ ehthumbs.db
16
+ Thumbs.db
17
+ .sass-cache
18
+ \#*
19
+ .#*
20
+ *~
21
+ *.sw[a-z]
22
+ *.bak
23
+ REVISION
24
+ TAGS*
25
+ tmtags
26
+ *_flymake.*
27
+ *_flymake
28
+ *.tmproj
29
+ .project
30
+ .settings
31
+ mkmf.log
32
+ a.out
33
+ *.o
34
+ *.pyc
35
+ *.so
36
+ *.com
37
+ *.class
38
+ *.dll
39
+ *.exe
40
+ */rdoc/
41
+ .watchr
42
+ .rspec
43
+ spec/*
44
+ spec/fixtures/*
45
+ test/*
46
+ features/*
47
+ Guardfile
48
+ Procfile
49
+ .git
50
+ */.git
51
+ .gitignore
52
+ .gitmodules
53
+ .gitconfig
54
+ .gitattributes
55
+ .svn
56
+ */.bzr/*
57
+ */.hg/*
58
+ */.svn/*
59
+ Berksfile
60
+ Berksfile.lock
61
+ cookbooks/*
62
+ tmp
63
+ CONTRIBUTING
64
+ Colanderfile
65
+ Strainerfile
66
+ .colander
67
+ .strainer
68
+ .vagrant
69
+ Vagrantfile
70
+ .travis.yml
71
+ END
72
+ end
73
+
74
+ # adds ignore patterns for .gitignore
75
+ # @param recipe [Chef::Recipe] the recipe into which resources
76
+ # will be injected
77
+ # @return [void]
78
+ def snippet_standardignore_gitignore(recipe)
79
+ @gitignore_files << <<END.split("\n")
80
+ .vagrant
81
+ Berksfile.lock
82
+ *~
83
+ *#
84
+ .#*
85
+ \#*#
86
+ .*.sw[a-z]
87
+ *.un~
88
+ Gemfile.lock
89
+ bin/*
90
+ .bundle/*
91
+ .kitchen/
92
+ .kitchen.local.yml
93
+ END
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,14 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # sets up style testing using Rubocop
4
+ module StyleRubocop
5
+ # declares the rubocop config file
6
+ # @param recipe [Chef::Recipe] the recipe into which resources
7
+ # will be injected
8
+ # @return [void]
9
+ def snippet_stylerubocop_config(recipe)
10
+ @templates_if_missing << '.rubocop.yml'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,51 @@
1
+ module ChefGen
2
+ module Snippet
3
+ # creates a framework for Test Kitchen integration testing
4
+ module TestKitchen
5
+ # declares the Test Kitchen config
6
+ # @param recipe [Chef::Recipe] the recipe into which resources
7
+ # will be injected
8
+ # @return [void]
9
+ def snippet_testkitchen_config(recipe)
10
+ @templates_if_missing << '.kitchen.yml'
11
+ end
12
+
13
+ # declares directories
14
+ # @param recipe [Chef::Recipe] the recipe into which resources
15
+ # will be injected
16
+ # @return [void]
17
+ def snippet_testkitchen_dirs(recipe)
18
+ @directories << 'test'
19
+ @directories << File.join('test', 'integration')
20
+ @directories << File.join('test', 'integration', 'default')
21
+ @directories << File.join(
22
+ 'test', 'integration', 'default', 'serverspec'
23
+ )
24
+ @directories << File.join(
25
+ 'test', 'integration', 'default', 'serverspec', 'recipes'
26
+ )
27
+ end
28
+
29
+ # declares the Test Kitchen spec helper
30
+ # @param recipe [Chef::Recipe] the recipe into which resources
31
+ # will be injected
32
+ # @return [void]
33
+ def snippet_testkitchen_spechelper(recipe)
34
+ @templates_if_missing << File.join(
35
+ 'test', 'integration', 'default', 'serverspec', 'spec_helper.rb'
36
+ )
37
+ end
38
+
39
+ # declares the Test Kitchen default recipe spec
40
+ # @param recipe [Chef::Recipe] the recipe into which resources
41
+ # will be injected
42
+ # @return [void]
43
+ def snippet_testkitchen_defaultrecipespec(recipe)
44
+ @templates_if_missing << File.join(
45
+ 'test', 'integration', 'default', 'serverspec',
46
+ 'recipes', 'default_spec.rb'
47
+ )
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,15 @@
1
+ module ChefGen
2
+ # template snippets that flavors can compose to do common things
3
+ module Snippet
4
+ autoload :Attributes, 'chef_gen/snippet/attributes'
5
+ autoload :ChefSpec, 'chef_gen/snippet/chef_spec'
6
+ autoload :CookbookBase, 'chef_gen/snippet/cookbook_base'
7
+ autoload :ExampleFile, 'chef_gen/snippet/example_file'
8
+ autoload :ExampleTemplate, 'chef_gen/snippet/example_template'
9
+ autoload :Recipes, 'chef_gen/snippet/recipes'
10
+ autoload :ResourceProvider, 'chef_gen/snippet/resource_provider'
11
+ autoload :StandardIgnore, 'chef_gen/snippet/standard_ignore'
12
+ autoload :StyleRubocop, 'chef_gen/snippet/style_rubocop'
13
+ autoload :TestKitchen, 'chef_gen/snippet/test_kitchen'
14
+ end
15
+ end
@@ -0,0 +1,164 @@
1
+ require 'chef_gen/flavor_base'
2
+
3
+ # :nocov:
4
+ module ChefGen
5
+ module Flavor
6
+ class Amazing < FlavorBase
7
+ class << self
8
+ def description
9
+ 'an amazing cookbook template'
10
+ end
11
+ end
12
+ end
13
+ end
14
+ module Snippet
15
+ module Bar
16
+ def snippet_bar(_)
17
+ @directories << 'bar'
18
+ end
19
+ end
20
+ end
21
+ end
22
+ # :nocov:
23
+
24
+ RSpec.describe ChefGen::FlavorBase do
25
+ before do
26
+ @ctx = double('ChefDK generator context')
27
+ allow(@ctx).to receive(:cookbook_root).and_return('/nonexistent')
28
+ allow(@ctx).to receive(:cookbook_name).and_return('foo')
29
+ allow(ChefDK::Generator).to receive(:context).and_return(@ctx)
30
+ @recipe = double('Chef recipe').as_null_object
31
+ @orig_stdout = $stdout
32
+ $stdout = File.open(File::NULL, 'w')
33
+ end
34
+
35
+ after do
36
+ $stdout = @orig_stdout
37
+ end
38
+
39
+ it 'can be constructed' do
40
+ template = ChefGen::Flavor::Amazing.new(@recipe)
41
+ expect(template).to be_a ChefGen::FlavorBase
42
+ end
43
+
44
+ it 'creates files unconditionally' do
45
+ expect(@recipe).to receive(:directory).once
46
+ expect(@recipe).to receive(:cookbook_file).once
47
+ template = ChefGen::Flavor::Amazing.new(@recipe)
48
+ template.files << 'README.md'
49
+ template.generate
50
+ end
51
+
52
+ it 'creates files conditionally with the clobber check enabled' do
53
+ expect(@recipe).to receive(:directory).once
54
+ expect(@recipe).not_to receive(:cookbook_file)
55
+ expect(File).to receive(:exist?)
56
+ .with('/nonexistent/foo/README.md')
57
+ .and_return(true)
58
+ template = ChefGen::Flavor::Amazing.new(@recipe)
59
+ template.fail_on_clobber = true
60
+ template.files << 'README.md'
61
+ expect { template.generate }
62
+ .to output(/tried to overwrite file.+README\.md/).to_stderr
63
+ .and raise_error
64
+ end
65
+
66
+ it 'creates files conditionally with the clobber check disabled' do
67
+ expect(@recipe).to receive(:directory).once
68
+ expect(@recipe).to receive(:cookbook_file).once
69
+ expect(@ctx).to receive(:respond_to?).with(:clobber).and_return(true)
70
+ template = ChefGen::Flavor::Amazing.new(@recipe)
71
+ template.files << 'README.md'
72
+ template.generate
73
+ end
74
+
75
+ it 'creates templates unconditionally' do
76
+ expect(@recipe).to receive(:directory).once
77
+ expect(@recipe).to receive(:template).once
78
+ template = ChefGen::Flavor::Amazing.new(@recipe)
79
+ template.templates << 'README.md'
80
+ template.generate
81
+ end
82
+
83
+ it 'creates templates conditionally with the clobber check enabled' do
84
+ expect(@recipe).to receive(:directory).once
85
+ expect(@recipe).not_to receive(:template)
86
+ expect(File).to receive(:exist?)
87
+ .with('/nonexistent/foo/README.md')
88
+ .and_return(true)
89
+ template = ChefGen::Flavor::Amazing.new(@recipe)
90
+ template.fail_on_clobber = true
91
+ template.templates << 'README.md'
92
+ expect { template.generate }
93
+ .to output(/tried to overwrite file.+README\.md/).to_stderr
94
+ .and raise_error
95
+ end
96
+
97
+ it 'creates templates conditionally with the clobber check disabled' do
98
+ expect(@recipe).to receive(:directory).once
99
+ expect(@recipe).to receive(:template).once
100
+ expect(@ctx).to receive(:respond_to?).with(:clobber).and_return(true)
101
+ template = ChefGen::Flavor::Amazing.new(@recipe)
102
+ template.templates << 'README.md'
103
+ template.generate
104
+ end
105
+
106
+ it 'accumulates .gitignore entries' do
107
+ expect(@recipe).to receive(:file).with(/.gitignore$/)
108
+ template = ChefGen::Flavor::Amazing.new(@recipe)
109
+ template.gitignore_files << 'foo'
110
+ template.gitignore_files << 'bar'
111
+ template.generate
112
+ end
113
+
114
+ it 'does not write a .gitignore if there are no entries' do
115
+ expect(@recipe).not_to receive(:cookbook_file).with(/.gitignore$/)
116
+ template = ChefGen::Flavor::Amazing.new(@recipe)
117
+ template.generate
118
+ end
119
+
120
+ it 'accumulates chefignore entries' do
121
+ expect(@recipe).to receive(:file).with(/chefignore$/)
122
+ template = ChefGen::Flavor::Amazing.new(@recipe)
123
+ template.chefignore_files << 'foo'
124
+ template.chefignore_files << 'bar'
125
+ template.generate
126
+ end
127
+
128
+ it 'does not write a chefignore if there are no entries' do
129
+ expect(@recipe).not_to receive(:cookbook_file).with(/chefignore$/)
130
+ template = ChefGen::Flavor::Amazing.new(@recipe)
131
+ template.generate
132
+ end
133
+
134
+ it 'calls mixin methods' do
135
+ expect(@recipe).to receive(:directory).with(%r{foo/$})
136
+ expect(@recipe).to receive(:directory).with(%r{foo/bar$})
137
+ template = ChefGen::Flavor::Amazing.new(@recipe)
138
+ template.extend ChefGen::Snippet::Bar
139
+ template.generate
140
+ end
141
+
142
+ it 'reports on actions by default' do
143
+ expect(@recipe).to receive(:ruby_block).with('report_actions_taken')
144
+ template = ChefGen::Flavor::Amazing.new(@recipe)
145
+ template.files << 'README.md'
146
+ template.generate
147
+ end
148
+
149
+ it 'does not report actions if disabled' do
150
+ expect(@recipe).not_to receive(:ruby_block)
151
+ template = ChefGen::Flavor::Amazing.new(@recipe)
152
+ template.report_actions = false
153
+ template.files << 'README.md'
154
+ template.generate
155
+ end
156
+
157
+ it 'displays the next steps if populated' do
158
+ expect(@recipe).to receive(:ruby_block).with('display_next_steps')
159
+ template = ChefGen::Flavor::Amazing.new(@recipe)
160
+ template.report_actions = false
161
+ template.next_steps = 'do something amazing'
162
+ template.generate
163
+ end
164
+ end