stove 6.0.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
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