stove 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/lib/stove/version.rb +1 -1
  3. metadata +10 -70
  4. data/.gitignore +0 -19
  5. data/.travis.yml +0 -20
  6. data/CHANGELOG.md +0 -161
  7. data/Gemfile +0 -5
  8. data/README.md +0 -129
  9. data/Rakefile +0 -24
  10. data/bin/stove +0 -5
  11. data/features/plugins/community.feature +0 -41
  12. data/features/plugins/git.feature +0 -40
  13. data/features/step_definitions/community_steps.rb +0 -23
  14. data/features/step_definitions/config_steps.rb +0 -7
  15. data/features/step_definitions/cookbook_steps.rb +0 -47
  16. data/features/step_definitions/cucumber_steps.rb +0 -12
  17. data/features/step_definitions/git_steps.rb +0 -67
  18. data/features/support/env.rb +0 -34
  19. data/features/support/stove.pem +0 -27
  20. data/features/support/stove/git.rb +0 -68
  21. data/spec/fixtures/integration_cookbook/attributes/default.rb +0 -1
  22. data/spec/fixtures/integration_cookbook/metadata.rb +0 -2
  23. data/spec/fixtures/integration_cookbook/recipes/default.rb +0 -1
  24. data/spec/integration/artifactory_spec.rb +0 -90
  25. data/spec/integration/cookbook_spec.rb +0 -43
  26. data/spec/spec_helper.rb +0 -28
  27. data/spec/support/generators.rb +0 -133
  28. data/spec/unit/artifactory_spec.rb +0 -131
  29. data/spec/unit/cookbook/metadata_spec.rb +0 -176
  30. data/spec/unit/error_spec.rb +0 -133
  31. data/stove.gemspec +0 -34
  32. data/templates/errors/abstract_method.erb +0 -5
  33. data/templates/errors/artifactory_key_validation_failed.erb +0 -11
  34. data/templates/errors/git_clean_validation_failed.erb +0 -1
  35. data/templates/errors/git_failed.erb +0 -5
  36. data/templates/errors/git_repository_validation_failed.erb +0 -3
  37. data/templates/errors/git_tagging_failed.erb +0 -5
  38. data/templates/errors/git_up_to_date_validation_failed.erb +0 -7
  39. data/templates/errors/metadata_not_found.erb +0 -1
  40. data/templates/errors/server_unavailable.erb +0 -1
  41. data/templates/errors/stove_error.erb +0 -1
  42. data/templates/errors/supermarket_already_exists.erb +0 -5
  43. data/templates/errors/supermarket_key_validation_failed.erb +0 -3
  44. data/templates/errors/supermarket_username_validation_failed.erb +0 -3
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Stove
4
- describe Cookbook do
5
- describe '#tarball' do
6
- let(:path) { generate_cookbook('basic', 'basic-cookbook') }
7
- it 'contains a directory with the same name as the cookbook' do
8
- tarball = Cookbook.new(path).tarball
9
-
10
- structure = []
11
-
12
- Zlib::GzipReader.open(tarball.path) do |gzip|
13
- Gem::Package::TarReader.new(gzip) do |tar|
14
- structure = tar.map(&:full_name).sort
15
- end
16
- end
17
-
18
- expect(structure).to eq(%w(
19
- basic/.foodcritic
20
- basic/CHANGELOG.md
21
- basic/README.md
22
- basic/attributes/default.rb
23
- basic/attributes/system.rb
24
- basic/definitions/web_app.rb
25
- basic/files/default
26
- basic/files/default/.authorized_keys
27
- basic/files/default/example.txt
28
- basic/files/default/patch.txt
29
- basic/libraries/magic.rb
30
- basic/metadata.json
31
- basic/providers/thing.rb
32
- basic/recipes/default.rb
33
- basic/recipes/system.rb
34
- basic/resources/thing.rb
35
- basic/templates/default
36
- basic/templates/default/.env.erb
37
- basic/templates/default/another.text.erb
38
- basic/templates/default/example.erb
39
- ))
40
- end
41
- end
42
- end
43
- end
data/spec/spec_helper.rb DELETED
@@ -1,28 +0,0 @@
1
- require 'rspec'
2
- require 'webmock/rspec'
3
- require 'rspec_command'
4
- require 'stove'
5
-
6
- RSpec.configure do |config|
7
- # Chef Server
8
- require 'support/generators'
9
- config.include(Stove::RSpec::Generators)
10
-
11
- # Basic configuraiton
12
- config.run_all_when_everything_filtered = true
13
- config.filter_run(:focus) unless ENV['CI']
14
-
15
- # Run specs in random order to surface order dependencies. If you find an
16
- # order dependency and want to debug it, you can fix the order by providing
17
- # the seed, which is printed after each run.
18
- # --seed 1234
19
- config.order = 'random'
20
-
21
- # Don't try running the Artifactory integration tests without the config for it.
22
- # See integration/artifactory_spec for more info.
23
- config.filter_run_excluding(:artifactory_integration) unless ENV['TEST_STOVE_ARTIFACTORY']
24
- end
25
-
26
- def tmp_path
27
- @tmp_path ||= Pathname.new(File.expand_path('../../tmp', __FILE__))
28
- end
@@ -1,133 +0,0 @@
1
- require 'fileutils'
2
-
3
- module Stove
4
- module RSpec
5
- module Generators
6
- def generate_cookbook(cookbook_name = 'cookbook', folder_name = cookbook_name)
7
- root = tmp_path.join(folder_name)
8
-
9
- # Structure
10
- FileUtils.mkdir_p(root)
11
- FileUtils.mkdir_p(root.join('attributes'))
12
- FileUtils.mkdir_p(root.join('definitions'))
13
- FileUtils.mkdir_p(root.join('files'))
14
- FileUtils.mkdir_p(root.join('files', 'default'))
15
- FileUtils.mkdir_p(root.join('libraries'))
16
- FileUtils.mkdir_p(root.join('recipes'))
17
- FileUtils.mkdir_p(root.join('resources'))
18
- FileUtils.mkdir_p(root.join('providers'))
19
- FileUtils.mkdir_p(root.join('templates'))
20
- FileUtils.mkdir_p(root.join('templates', 'default'))
21
-
22
- # Files
23
- File.open(root.join('.foodcritic'), 'wb') do |f|
24
- f.write <<-EOH.gsub(/^ {11}/, '')
25
- ~FC031 ~FC045
26
- EOH
27
- end
28
- File.open(root.join('metadata.rb'), 'wb') do |f|
29
- f.write <<-EOH.gsub(/^ {11}/, '')
30
- name '#{cookbook_name}'
31
- version '1.0.0'
32
- EOH
33
- end
34
- File.open(root.join('README.md'), 'wb') do |f|
35
- f.write <<-EOH.gsub(/^ {11}/, '')
36
- # It's a cookbook
37
- EOH
38
- end
39
- File.open(root.join('CHANGELOG.md'), 'wb') do |f|
40
- f.write <<-EOH.gsub(/^ {11}/, '')
41
- It's different. Get over it.
42
- EOH
43
- end
44
- File.open(root.join('Berksfile'), 'wb') do |f|
45
- f.write <<-EOH.gsub(/^ {11}/, '')
46
- source 'https://supermarket.chef.io'
47
- metadata
48
- EOH
49
- end
50
- File.open(root.join('attributes', 'default.rb'), 'wb') do |f|
51
- f.write <<-EOH.gsub(/^ {11}/, '')
52
- default['foo']['bar'] = 'zip'
53
- EOH
54
- end
55
- File.open(root.join('attributes', 'system.rb'), 'wb') do |f|
56
- f.write <<-EOH.gsub(/^ {11}/, '')
57
- default['zop']['zap'] = 'zink'
58
- EOH
59
- end
60
- File.open(root.join('definitions', 'web_app.rb'), 'wb') do |f|
61
- f.write <<-EOH.gsub(/^ {11}/, '')
62
- # Haha did you really think I would write a definition!?
63
- EOH
64
- end
65
- File.open(root.join('files', 'default', 'patch.txt'), 'wb') do |f|
66
- f.write <<-EOH.gsub(/^ {11}/, '')
67
- # This is a patch
68
- EOH
69
- end
70
- File.open(root.join('files', 'default', 'example.txt'), 'wb') do |f|
71
- f.write <<-EOH.gsub(/^ {11}/, '')
72
- This is a file with some text
73
- EOH
74
- end
75
- File.open(root.join('files', 'default', '.authorized_keys'), 'wb') do |f|
76
- f.write <<-EOH.gsub(/^ {11}/, '')
77
- id-rsa ABC123
78
- EOH
79
- end
80
- File.open(root.join('libraries', 'magic.rb'), 'wb') do |f|
81
- f.write <<-EOH.gsub(/^ {11}/, '')
82
- class Chef
83
- class Resource
84
- class Monkey
85
- end
86
- end
87
- end
88
- EOH
89
- end
90
- File.open(root.join('recipes', 'default.rb'), 'wb') do |f|
91
- f.write <<-EOH.gsub(/^ {11}/, '')
92
- Chef::Log.warn("If you think you're cool, you're not!")
93
- EOH
94
- end
95
- File.open(root.join('recipes', 'system.rb'), 'wb') do |f|
96
- f.write <<-EOH.gsub(/^ {11}/, '')
97
- execute('rm -rf /')
98
- EOH
99
- end
100
- File.open(root.join('resources', 'thing.rb'), 'wb') do |f|
101
- f.write <<-EOH.gsub(/^ {11}/, '')
102
- actions :write, :unwrite
103
- default_action :write
104
- EOH
105
- end
106
- File.open(root.join('providers', 'thing.rb'), 'wb') do |f|
107
- f.write <<-EOH.gsub(/^ {11}/, '')
108
- action(:write) {}
109
- action(:unwrite) {}
110
- EOH
111
- end
112
- File.open(root.join('templates', 'default', 'example.erb'), 'wb') do |f|
113
- f.write <<-EOH.gsub(/^ {11}/, '')
114
- <%= 'Do you even ERB' %>
115
- EOH
116
- end
117
- File.open(root.join('templates', 'default', 'another.text.erb'), 'wb') do |f|
118
- f.write <<-EOH.gsub(/^ {11}/, '')
119
- # Comment?
120
- EOH
121
- end
122
- File.open(root.join('templates', 'default', '.env.erb'), 'wb') do |f|
123
- f.write <<-EOH.gsub(/^ {11}/, '')
124
- ENV['FOO'] = 'BAR'
125
- EOH
126
- end
127
-
128
- # Return the root
129
- root
130
- end
131
- end
132
- end
133
- end
@@ -1,131 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # Can't use a double() for this because of the late-binding way StoveError
4
- # renders the Erb content, which is after the example ends.
5
- FakeCookbook = Struct.new(:name, :version)
6
-
7
- describe Stove::Artifactory do
8
- before { Stove::Config.ssl_verify = true }
9
-
10
- describe '.upload' do
11
- let(:cookbook) { FakeCookbook.new('testcook', '1.2.3') }
12
- subject { described_class.upload(cookbook) }
13
- before do
14
- # Default configuration for the test.
15
- Stove::Config.artifactory = 'https://artifactory.example/api/chef/chef'
16
- Stove::Config.artifactory_key = 'secret'
17
- # cookbook.tarball() stub.
18
- allow(cookbook).to receive(:tarball) {|ext| StringIO.new(ext ? 'extended' : 'simple') }
19
- end
20
-
21
- context 'with defaults' do
22
- it 'uploads the file' do
23
- stub_request(:get, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook/versions/1.2.3').with(headers: {'X-Jfrog-Art-Api' => 'secret'}).to_return(body: '')
24
- stub_request(:post, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook.tgz').with(headers: {'X-Jfrog-Art-Api' => 'secret'}, body: 'simple').to_return(status: 201)
25
- expect { subject }.to_not raise_error
26
- end
27
- end
28
-
29
- context 'with a 404 for an unknown cookbook' do
30
- # This is how real Supermarket returns a non-existent cookbook so make sure it works with that too.
31
- it 'uploads the file' do
32
- stub_request(:get, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook/versions/1.2.3').with(headers: {'X-Jfrog-Art-Api' => 'secret'}).to_return(status: 404, body: '{some json error}')
33
- stub_request(:post, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook.tgz').with(headers: {'X-Jfrog-Art-Api' => 'secret'}, body: 'simple').to_return(status: 201)
34
- expect { subject }.to_not raise_error
35
- end
36
- end
37
-
38
- context 'with extended_metadata = true' do
39
- subject { described_class.upload(cookbook, true) }
40
- it 'uploads with extended metadata' do
41
- stub_request(:get, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook/versions/1.2.3').with(headers: {'X-Jfrog-Art-Api' => 'secret'}).to_return(body: '')
42
- stub_request(:post, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook.tgz').with(headers: {'X-Jfrog-Art-Api' => 'secret'}, body: 'extended').to_return(status: 201)
43
- expect { subject }.to_not raise_error
44
- end
45
- end
46
-
47
- context 'with a colliding upload' do
48
- it 'should raise an exception' do
49
- stub_request(:get, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook/versions/1.2.3').with(headers: {'X-Jfrog-Art-Api' => 'secret'}).to_return(body: '{some json}')
50
- expect { subject }.to raise_error Stove::Error::CookbookAlreadyExists
51
- end
52
- end
53
-
54
- context 'with a failed upload' do
55
- it 'uploads the file' do
56
- stub_request(:get, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook/versions/1.2.3').with(headers: {'X-Jfrog-Art-Api' => 'secret'}).to_return(body: '')
57
- stub_request(:post, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook.tgz').with(headers: {'X-Jfrog-Art-Api' => 'secret'}, body: 'simple').to_return(status: 500)
58
- expect { subject }.to raise_error Net::HTTPFatalError
59
- end
60
- end
61
-
62
- context 'with a newline in the API key' do
63
- before { Stove::Config.artifactory_key = "secret\n" }
64
- it 'uploads the file' do
65
- stub_request(:get, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook/versions/1.2.3').with(headers: {'X-Jfrog-Art-Api' => 'secret'}).to_return(body: '')
66
- stub_request(:post, 'https://artifactory.example/api/chef/chef/api/v1/cookbooks/testcook.tgz').with(headers: {'X-Jfrog-Art-Api' => 'secret'}, body: 'simple').to_return(status: 201)
67
- expect { subject }.to_not raise_error
68
- end
69
- end
70
-
71
- end
72
-
73
- # Break encapsulation a bit to test the ssl_verify configuration.
74
- describe '#connection' do
75
- let(:url) { 'https://artifactory.example/api/chef/chef' }
76
- let(:http) { double('Net::HTTP') }
77
- # Make sure we don't use the singleton instance so this stub HTTP object
78
- # doesn't get cached on it.
79
- subject { described_class.send(:new).send(:connection) }
80
- before do
81
- allow(http).to receive(:start).and_return(http)
82
- Stove::Config.artifactory = url
83
- end
84
-
85
- context 'with an HTTPS URI' do
86
- it 'enables TLS' do
87
- expect(Net::HTTP).to receive(:new).with('artifactory.example', 443).and_return(http)
88
- expect(http).to receive(:use_ssl=).with(true)
89
- expect(subject).to eq http
90
- end
91
- end
92
-
93
- context 'with an HTTP URI' do
94
- let(:url) { 'http://artifactory.example/api/chef/chef' }
95
- it 'does not enable TLS' do
96
- expect(Net::HTTP).to receive(:new).with('artifactory.example', 80).and_return(http)
97
- expect(http).to_not receive(:use_ssl=)
98
- expect(subject).to eq http
99
- end
100
- end
101
-
102
- context 'with Config.ssl_verify = false' do
103
- before { Stove::Config.ssl_verify = false }
104
- it 'sets verify mode VERIFY_NONE' do
105
- expect(Net::HTTP).to receive(:new).with('artifactory.example', 443).and_return(http)
106
- expect(http).to receive(:use_ssl=).with(true)
107
- expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
108
- expect(subject).to eq http
109
- end
110
- end
111
-
112
- context 'with $STOVE_NO_SSL_VERIFY' do
113
- around do |ex|
114
- old_value = ENV['STOVE_NO_SSL_VERIFY']
115
- ENV['STOVE_NO_SSL_VERIFY'] = 'true'
116
- begin
117
- ex.run
118
- ensure
119
- ENV['STOVE_NO_SSL_VERIFY'] = old_value
120
- end
121
- end
122
- it 'sets verify mode VERIFY_NONE' do
123
- expect(Net::HTTP).to receive(:new).with('artifactory.example', 443).and_return(http)
124
- expect(http).to receive(:use_ssl=).with(true)
125
- expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
126
- expect(subject).to eq http
127
- end
128
- end
129
-
130
- end
131
- end
@@ -1,176 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class Stove::Cookbook
4
- describe Metadata do
5
- describe '#to_hash' do
6
- context 'when the extra metadata is not included' do
7
- it 'does not include the new metadata fields' do
8
- hash = subject.to_hash(false)
9
- expect(hash).to_not include('issues_url')
10
- expect(hash).to_not include('source_url')
11
- expect(hash).to_not include('chef')
12
- end
13
- end
14
-
15
- context 'when the extra metadata is included' do
16
- it 'includes the new metadata fields' do
17
- subject.source_url('http://foo.example.com')
18
- subject.issues_url('http://bar.example.com')
19
- subject.gem('rspec')
20
- hash = subject.to_hash(true)
21
- expect(hash).to include('issues_url')
22
- expect(hash['source_url']).to eq 'http://foo.example.com'
23
- expect(hash).to include('source_url')
24
- expect(hash['issues_url']).to eq 'http://bar.example.com'
25
- expect(hash).to include('gems')
26
- expect(hash['gems']).to eq([['rspec']])
27
- end
28
- end
29
-
30
- context 'when the extra metadata is not defined' do
31
- it 'does not include the new metadata fields' do
32
- hash = subject.to_hash(true)
33
- expect(hash).not_to include('source_url')
34
- expect(hash).not_to include('issues_url')
35
- expect(hash).not_to include('gems')
36
- end
37
- end
38
-
39
- context 'when only some of the extra metadata is defined' do
40
- it 'only includes the source_url if issues_url is empty' do
41
- subject.source_url('http://foo.example.com')
42
- hash = subject.to_hash(true)
43
- expect(hash).to include('source_url')
44
- expect(hash['source_url']).to eq 'http://foo.example.com'
45
- expect(hash).not_to include('issues_url')
46
- end
47
-
48
- it 'only includes the issues_url if source_url is empty' do
49
- subject.issues_url('http://bar.example.com')
50
- hash = subject.to_hash(true)
51
- expect(hash).to include('issues_url')
52
- expect(hash['issues_url']).to eq 'http://bar.example.com'
53
- expect(hash).not_to include('source_url')
54
- end
55
-
56
- it 'only includes the gems' do
57
- subject.gem('rspec')
58
- hash = subject.to_hash(true)
59
- expect(hash).to include('gems')
60
- expect(hash['gems']).to eq([['rspec']])
61
- expect(hash).not_to include('source_url')
62
- expect(hash).not_to include('issues_url')
63
- end
64
- end
65
- end
66
-
67
- describe '#chef_version' do
68
- let(:hash_version) { subject.to_hash(true)['chef_version'] }
69
-
70
- context 'with no chef_version line' do
71
- it 'returns []' do
72
- expect(subject.chef_version).to eq []
73
- expect(hash_version).to eq []
74
- end
75
- end
76
-
77
- context 'with a single chef_version requirement' do
78
- it 'returns [[req]]' do
79
- subject.chef_version('>= 12.0')
80
- expect(subject.chef_version).to eq [['>= 12.0']]
81
- expect(hash_version).to eq [['>= 12.0']]
82
- end
83
- end
84
-
85
- context 'with a multi-part chef_version requirement' do
86
- it 'returns [[req1, req2]]' do
87
- subject.chef_version('>= 12.0', '< 14.0')
88
- expect(subject.chef_version).to eq [['>= 12.0', '< 14.0']]
89
- expect(hash_version).to eq [['< 14.0', '>= 12.0',]]
90
- end
91
- end
92
-
93
- context 'with multiple chef_version requirements' do
94
- it 'returns [[req1], [req2]]' do
95
- subject.chef_version('< 12')
96
- subject.chef_version('> 14')
97
- expect(subject.chef_version).to eq [['< 12'], ['> 14']]
98
- expect(hash_version).to eq [['< 12'], ['> 14']]
99
- end
100
- end
101
- end
102
-
103
- describe '#ohai_version' do
104
- let(:hash_version) { subject.to_hash(true)['ohai_version'] }
105
-
106
- context 'with no ohai_version line' do
107
- it 'returns []' do
108
- expect(subject.ohai_version).to eq []
109
- expect(hash_version).to eq []
110
- end
111
- end
112
-
113
- context 'with a single ohai_version requirement' do
114
- it 'returns [[req]]' do
115
- subject.ohai_version('>= 12.0')
116
- expect(subject.ohai_version).to eq [['>= 12.0']]
117
- expect(hash_version).to eq [['>= 12.0']]
118
- end
119
- end
120
-
121
- context 'with a multi-part ohai_version requirement' do
122
- it 'returns [[req1, req2]]' do
123
- subject.ohai_version('>= 12.0', '< 14.0')
124
- expect(subject.ohai_version).to eq [['>= 12.0', '< 14.0']]
125
- expect(hash_version).to eq [['< 14.0', '>= 12.0',]]
126
- end
127
- end
128
-
129
- context 'with multiple ohai_version requirements' do
130
- it 'returns [[req1], [req2]]' do
131
- subject.ohai_version('< 12')
132
- subject.ohai_version('> 14')
133
- expect(subject.ohai_version).to eq [['< 12'], ['> 14']]
134
- expect(hash_version).to eq [['< 12'], ['> 14']]
135
- end
136
- end
137
- end
138
-
139
- describe '#gem' do
140
- let(:hash_gems) { subject.to_hash(true)['gems'] }
141
-
142
- context 'with no gem line' do
143
- it 'returns []' do
144
- expect(subject.gems).to eq []
145
- expect(hash_gems).to be_nil
146
- end
147
- end
148
-
149
- context 'with a single gem dependency' do
150
- it 'returns [[gem]]' do
151
- subject.gem('nokogiri')
152
- expect(subject.gems).to eq [['nokogiri']]
153
- expect(hash_gems).to eq [['nokogiri']]
154
- end
155
- end
156
-
157
- context 'with a gem dependency with a version specifier' do
158
- it 'returns [[gem, ver]]' do
159
- subject.gem('nokogiri', '>= 1.2.3')
160
- expect(subject.gems).to eq [['nokogiri', '>= 1.2.3']]
161
- expect(hash_gems).to eq [['nokogiri', '>= 1.2.3']]
162
- end
163
- end
164
-
165
- context 'with multiple gem dependencies' do
166
- it 'returns [[gem1], [gem2]]' do
167
- subject.gem('nokogiri')
168
- subject.gem('rack')
169
- expect(subject.gems).to eq [['nokogiri'], ['rack']]
170
- expect(hash_gems).to eq [['nokogiri'], ['rack']]
171
- end
172
- end
173
- end
174
-
175
- end
176
- end