stove 3.0.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/features/plugins/community.feature +23 -7
- data/features/plugins/git.feature +1 -1
- data/features/step_definitions/community_steps.rb +3 -11
- data/lib/stove/cli.rb +17 -14
- data/lib/stove/community.rb +24 -2
- data/lib/stove/cookbook.rb +3 -28
- data/lib/stove/cookbook/metadata.rb +3 -1
- data/lib/stove/packager.rb +101 -44
- data/lib/stove/plugins/community.rb +0 -4
- data/lib/stove/version.rb +1 -1
- data/spec/integration/cookbook_spec.rb +41 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/generators.rb +118 -0
- data/spec/unit/error_spec.rb +0 -15
- data/stove.gemspec +1 -2
- metadata +8 -19
- data/templates/errors/community_category_validation_failed.erb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4c8841bc73b292bcd565cff88b842bc1168fa29
|
4
|
+
data.tar.gz: 366832a1c8ce35fd2aede16c91e792c87a641895
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e07b0fa5c4d8e2578fa9b8cd9ee1a2204358268abdf036285286a28046819a7057f99ad32324ea823070b92fc95ba18b9245192f8a7c7fbbf27721ffa1db5a1
|
7
|
+
data.tar.gz: 2d79edc8e2780608752a9f9677b4af644bbc847b0df3623a2ebb6dae43f21f967fc50ebaffa910edd35e4d14f2d8558c7681666b6dea7e52696da1e02f94e8cb
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,26 @@ Stove CHANGELOG
|
|
2
2
|
===============
|
3
3
|
This is the Changelog for the Stove gem.
|
4
4
|
|
5
|
+
v3.2.1 (2014-07-16)
|
6
|
+
-------------------
|
7
|
+
- Fix a critical bug where nested directories are flattened
|
8
|
+
|
9
|
+
v3.2.0 (2014-07-15)
|
10
|
+
-------------------
|
11
|
+
- Add the ability to "yank" (delete) a cookbook from the Supermarket
|
12
|
+
- Remove the `--category` flag (it is no longer honored)
|
13
|
+
- Fix a bug where the `resources/` folder was not uploaded
|
14
|
+
- Fix a bug when the cookbook name is not the same as the metdata name in the uploaded tarball
|
15
|
+
|
16
|
+
v3.1.0 (2014-07-10)
|
17
|
+
-------------------
|
18
|
+
- Use the generated tempfile directly (instead of writing to disk and creating File objects)
|
19
|
+
- Add a default version constraint ('>= 0.0.0')
|
20
|
+
- Only package Ruby files under `recipes/` and similar directories
|
21
|
+
- Dynamically generate the metadata.json in memory (save disk IO)
|
22
|
+
- Use Rubygem's TarWrtier instead of minitar (removed dependency)
|
23
|
+
- Bump version of Chef API to support tempfile IO objects
|
24
|
+
|
5
25
|
v3.0.0 (2014-07-07)
|
6
26
|
-------------------
|
7
27
|
- Add support for signed git tags
|
@@ -1,7 +1,6 @@
|
|
1
1
|
Feature: Community
|
2
2
|
Background:
|
3
3
|
* I have a cookbook named "bacon"
|
4
|
-
* I am using the community server
|
5
4
|
|
6
5
|
Scenario: When the username does not exist
|
7
6
|
* the Stove config at "username" is unset
|
@@ -13,13 +12,30 @@ Feature: Community
|
|
13
12
|
* I run `stove --no-git`
|
14
13
|
* it should fail with "requires a private key"
|
15
14
|
|
16
|
-
Scenario: When the category does not exist
|
17
|
-
* I run `stove --no-git`
|
18
|
-
* it should fail with "You did not specify a category"
|
19
|
-
|
20
15
|
Scenario: With the default parameters
|
21
16
|
* the community server has the cookbook:
|
22
|
-
| bacon | 1.2.3 |
|
17
|
+
| bacon | 1.2.3 |
|
23
18
|
* I successfully run `stove --no-git`
|
24
19
|
* the community server will have the cookbooks:
|
25
|
-
| bacon | 0.0.0 |
|
20
|
+
| bacon | 0.0.0 |
|
21
|
+
|
22
|
+
Scenario: Yanking a cookbook
|
23
|
+
* the community server has the cookbooks:
|
24
|
+
| bacon | 1.2.3 |
|
25
|
+
* I successfully run `stove yank -l debug`
|
26
|
+
* the community server will not have the cookbooks:
|
27
|
+
| bacon | 1.2.3 |
|
28
|
+
* the output should contain "Successfully yanked bacon!"
|
29
|
+
|
30
|
+
Scenario: Yanking a cookbook by name
|
31
|
+
* the community server has the cookbooks:
|
32
|
+
| eggs | 4.5.6 |
|
33
|
+
* I successfully run `stove yank eggs`
|
34
|
+
* the community server will not have the cookbooks:
|
35
|
+
| eggs | 4.5.6 |
|
36
|
+
* the output should not contain "Successfully yanked bacon!"
|
37
|
+
* the output should contain "Successfully yanked eggs!"
|
38
|
+
|
39
|
+
Scenario: Yanking a non-existent cookbook
|
40
|
+
* I run `stove yank ham`
|
41
|
+
* it should fail with "I could not find a cookbook named ham"
|
@@ -1,31 +1,23 @@
|
|
1
|
-
Given /^I am using the community server$/ do
|
2
|
-
set_env('STOVE_ENDPOINT', CommunityZero::RSpec.url)
|
3
|
-
set_env('STOVE_CLIENT', 'stove')
|
4
|
-
set_env('STOVE_KEY', File.expand_path('../../support/stove.pem', __FILE__))
|
5
|
-
end
|
6
|
-
|
7
1
|
Given /^the community server has the cookbooks?:$/ do |table|
|
8
|
-
table.raw.each do |name, version
|
2
|
+
table.raw.each do |name, version|
|
9
3
|
version ||= '0.0.0'
|
10
|
-
category ||= 'Other'
|
11
4
|
|
12
5
|
CommunityZero::RSpec.store.add(CommunityZero::Cookbook.new(
|
13
6
|
name: name,
|
14
7
|
version: version,
|
15
|
-
category:
|
8
|
+
category: 'Other',
|
16
9
|
))
|
17
10
|
end
|
18
11
|
end
|
19
12
|
|
20
13
|
Then /^the community server will( not)? have the cookbooks?:$/ do |negate, table|
|
21
|
-
table.raw.each do |name, version
|
14
|
+
table.raw.each do |name, version|
|
22
15
|
cookbook = CommunityZero::RSpec.store.find(name, version)
|
23
16
|
|
24
17
|
if negate
|
25
18
|
expect(cookbook).to be_nil
|
26
19
|
else
|
27
20
|
expect(cookbook).to_not be_nil
|
28
|
-
expect(cookbook.category).to eql(category) if category
|
29
21
|
end
|
30
22
|
end
|
31
23
|
end
|
data/lib/stove/cli.rb
CHANGED
@@ -15,7 +15,7 @@ module Stove
|
|
15
15
|
# Parse the options hash
|
16
16
|
option_parser.parse!(@argv)
|
17
17
|
|
18
|
-
#
|
18
|
+
# Login command
|
19
19
|
if @argv.first == 'login'
|
20
20
|
if options[:username].nil? || options[:username].to_s.strip.empty?
|
21
21
|
raise "Missing argument `--username'!"
|
@@ -30,6 +30,7 @@ module Stove
|
|
30
30
|
Config.save
|
31
31
|
|
32
32
|
@stdout.puts "Successfully saved config to `#{Config.__path__}'!"
|
33
|
+
@kernel.exit(0)
|
33
34
|
return
|
34
35
|
end
|
35
36
|
|
@@ -41,23 +42,30 @@ module Stove
|
|
41
42
|
# Set the log level
|
42
43
|
Stove.log_level = options[:log_level]
|
43
44
|
|
44
|
-
# Parse out the version from ARGV
|
45
|
-
options[:version] = @argv.shift
|
46
|
-
|
47
45
|
# Useful debugging output for when people type the wrong fucking command
|
48
46
|
# and then open an issue like it's somehow my fault
|
49
47
|
log.info("Options: #{options.inspect}")
|
50
48
|
log.info("ARGV: #{@argv.inspect}")
|
51
49
|
|
50
|
+
# Yank command
|
51
|
+
if @argv.first == 'yank'
|
52
|
+
name = @argv[1] || Cookbook.new(options[:path]).name
|
53
|
+
|
54
|
+
if Community.yank(name)
|
55
|
+
@stdout.puts "Successfully yanked #{name}!"
|
56
|
+
@kernel.exit(0)
|
57
|
+
else
|
58
|
+
@stderr.puts "I could not find a cookbook named #{name}!"
|
59
|
+
@kernel.exit(1)
|
60
|
+
end
|
61
|
+
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
52
65
|
# Make a new cookbook object - this will raise an exception if there is
|
53
66
|
# no cookbook at the given path
|
54
67
|
cookbook = Cookbook.new(options[:path])
|
55
68
|
|
56
|
-
# Set the category on the cookbook object if one was given
|
57
|
-
if category = options.delete(:category)
|
58
|
-
cookbook.category = category
|
59
|
-
end
|
60
|
-
|
61
69
|
# Now execute the actual runners (validations and errors might occur)
|
62
70
|
runner = Runner.new(cookbook, options)
|
63
71
|
runner.run
|
@@ -108,10 +116,6 @@ module Stove
|
|
108
116
|
options[:key] = v
|
109
117
|
end
|
110
118
|
|
111
|
-
opts.on('--category [CATEGORY]', 'Category for the cookbook') do |v|
|
112
|
-
options[:category] = v
|
113
|
-
end
|
114
|
-
|
115
119
|
opts.separator ''
|
116
120
|
opts.separator 'Git Options:'
|
117
121
|
|
@@ -160,7 +164,6 @@ module Stove
|
|
160
164
|
:endpoint => nil,
|
161
165
|
:username => Config.username,
|
162
166
|
:key => Config.key,
|
163
|
-
:category => nil,
|
164
167
|
|
165
168
|
# Git options
|
166
169
|
:remote => 'origin',
|
data/lib/stove/community.rb
CHANGED
@@ -52,11 +52,33 @@ module Stove
|
|
52
52
|
#
|
53
53
|
def upload(cookbook)
|
54
54
|
connection.post('cookbooks', {
|
55
|
-
'tarball' =>
|
56
|
-
|
55
|
+
'tarball' => cookbook.tarball,
|
56
|
+
|
57
|
+
# This is for legacy, backwards-compatability reasons. The new
|
58
|
+
# Supermarket site does not require a category, but many of the testing
|
59
|
+
# tools still assume a cookbook category is present. We juse hardcode
|
60
|
+
# "Other" here.
|
61
|
+
'cookbook' => { 'category' => 'Other' }.to_json,
|
57
62
|
})
|
58
63
|
end
|
59
64
|
|
65
|
+
#
|
66
|
+
# Delete the given cookbook from the communit site.
|
67
|
+
#
|
68
|
+
# @param [String] name
|
69
|
+
# the name of the cookbook to delete
|
70
|
+
#
|
71
|
+
# @return [true, false]
|
72
|
+
# true if the cookbook was deleted, false otherwise
|
73
|
+
#
|
74
|
+
def yank(name)
|
75
|
+
connection.delete("/cookbooks/#{name}")
|
76
|
+
true
|
77
|
+
rescue ChefAPI::Error::HTTPBadRequest,
|
78
|
+
ChefAPI::Error::HTTPNotFound,
|
79
|
+
false
|
80
|
+
end
|
81
|
+
|
60
82
|
private
|
61
83
|
|
62
84
|
#
|
data/lib/stove/cookbook.rb
CHANGED
@@ -37,14 +37,6 @@ module Stove
|
|
37
37
|
#
|
38
38
|
attr_reader :metadata
|
39
39
|
|
40
|
-
#
|
41
|
-
# Set the category for this cookbook
|
42
|
-
#
|
43
|
-
# @param [String]
|
44
|
-
# the name of the category (values are restricted by the Community Site)
|
45
|
-
#
|
46
|
-
attr_writer :category
|
47
|
-
|
48
40
|
#
|
49
41
|
# The changeset for this cookbook. This is written by the changelog
|
50
42
|
# generator and read by various plugins.
|
@@ -61,22 +53,10 @@ module Stove
|
|
61
53
|
# the relative or absolute path to the cookbook on disk
|
62
54
|
#
|
63
55
|
def initialize(path)
|
64
|
-
@path =
|
56
|
+
@path = File.expand_path(path)
|
65
57
|
load_metadata!
|
66
58
|
end
|
67
59
|
|
68
|
-
#
|
69
|
-
# The category for this cookbook on the community site.
|
70
|
-
#
|
71
|
-
# @return [String]
|
72
|
-
#
|
73
|
-
def category
|
74
|
-
@category ||= Community.cookbook(name)['category']
|
75
|
-
rescue ChefAPI::Error::HTTPError
|
76
|
-
log.warn("Cookbook `#{name}' not found on the Chef community site")
|
77
|
-
nil
|
78
|
-
end
|
79
|
-
|
80
60
|
#
|
81
61
|
# The tag version. This is just the current version prefixed with the
|
82
62
|
# letter "v".
|
@@ -115,12 +95,7 @@ module Stove
|
|
115
95
|
# @return [File]
|
116
96
|
#
|
117
97
|
def tarball
|
118
|
-
|
119
|
-
|
120
|
-
begin
|
121
|
-
@tarball = Stove::Packager.new(self).package_path
|
122
|
-
end until File.exists?(@tarball)
|
123
|
-
@tarball
|
98
|
+
@tarball ||= Packager.new(self).tarball
|
124
99
|
end
|
125
100
|
|
126
101
|
private
|
@@ -132,7 +107,7 @@ module Stove
|
|
132
107
|
# @return [String]
|
133
108
|
# the path to the metadata file
|
134
109
|
def load_metadata!
|
135
|
-
metadata_path =
|
110
|
+
metadata_path = File.join(path, 'metadata.rb')
|
136
111
|
|
137
112
|
@metadata = Stove::Cookbook::Metadata.from_file(metadata_path)
|
138
113
|
@name = @metadata.name
|
@@ -40,7 +40,7 @@ module Stove
|
|
40
40
|
class_eval <<-EOM, __FILE__, __LINE__ + 1
|
41
41
|
def #{field}(thing, *args)
|
42
42
|
version = args.first
|
43
|
-
@#{instance_variable}[thing] = version
|
43
|
+
@#{instance_variable}[thing] = version || DEFAULT_VERSION
|
44
44
|
@#{instance_variable}[thing]
|
45
45
|
end
|
46
46
|
EOM
|
@@ -56,6 +56,8 @@ module Stove
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
DEFAULT_VERSION = '>= 0.0.0'.freeze
|
60
|
+
|
59
61
|
COMPARISON_FIELDS = [
|
60
62
|
:name, :description, :long_description, :maintainer,
|
61
63
|
:maintainer_email, :license, :platforms, :dependencies,
|
data/lib/stove/packager.rb
CHANGED
@@ -1,23 +1,24 @@
|
|
1
|
-
require '
|
1
|
+
require 'rubygems/package'
|
2
2
|
require 'fileutils'
|
3
|
-
require 'tmpdir'
|
4
3
|
require 'tempfile'
|
5
4
|
require 'zlib'
|
6
5
|
|
7
6
|
module Stove
|
8
7
|
class Packager
|
8
|
+
include Logify
|
9
|
+
|
9
10
|
ACCEPTABLE_FILES = [
|
10
11
|
'README.*',
|
11
12
|
'CHANGELOG.*',
|
12
13
|
'metadata.{json,rb}',
|
13
|
-
'attributes',
|
14
|
-
'definitions',
|
15
|
-
'files',
|
16
|
-
'libraries',
|
17
|
-
'providers',
|
18
|
-
'recipes',
|
19
|
-
'resources',
|
20
|
-
'templates',
|
14
|
+
'attributes/*.rb',
|
15
|
+
'definitions/*.rb',
|
16
|
+
'files/**/*',
|
17
|
+
'libraries/*.rb',
|
18
|
+
'providers/*.rb',
|
19
|
+
'recipes/*.rb',
|
20
|
+
'resources/*.rb',
|
21
|
+
'templates/**/*',
|
21
22
|
].freeze
|
22
23
|
|
23
24
|
ACCEPTABLE_FILES_LIST = ACCEPTABLE_FILES.join(',').freeze
|
@@ -40,52 +41,108 @@ module Stove
|
|
40
41
|
@cookbook = cookbook
|
41
42
|
end
|
42
43
|
|
43
|
-
#
|
44
|
+
# A map from physical file path to tarball file path
|
44
45
|
#
|
45
|
-
# @
|
46
|
-
#
|
47
|
-
def cookbook_files
|
48
|
-
path = File.expand_path("#{cookbook.path}/{#{ACCEPTABLE_FILES_LIST}}")
|
49
|
-
Dir[path].reject { |f| TMP_FILES.any? { |regex| f.match(regex) } }
|
50
|
-
end
|
51
|
-
|
52
|
-
# The path to the tar.gz package in the temporary directory.
|
46
|
+
# @example
|
47
|
+
# # Assuming +cookbook.name+ is 'apt'
|
53
48
|
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
49
|
+
# {
|
50
|
+
# '/home/user/apt-cookbook/metadata.json' => 'apt/metadata.json',
|
51
|
+
# '/home/user/apt-cookbook/README.md' => 'apt/README.md'
|
52
|
+
# }
|
53
|
+
#
|
54
|
+
# @return [Hash<String, String>]
|
55
|
+
# the map of file paths
|
56
|
+
def packaging_slip
|
57
|
+
root = File.expand_path(cookbook.path)
|
58
|
+
path = File.join(root, "{#{ACCEPTABLE_FILES_LIST}}")
|
58
59
|
|
59
|
-
|
60
|
+
Dir[path].reject do |filepath|
|
61
|
+
TMP_FILES.any? { |regex| filepath.match(regex) }
|
62
|
+
end.map do |cookbook_file|
|
63
|
+
[
|
64
|
+
cookbook_file,
|
65
|
+
cookbook_file.sub(/^#{Regexp.escape(root)}/, cookbook.name)
|
66
|
+
]
|
67
|
+
end.reduce({}) do |map, (cookbook_file, tarball_file)|
|
68
|
+
map[cookbook_file] = tarball_file
|
69
|
+
map
|
70
|
+
end
|
71
|
+
end
|
60
72
|
|
61
|
-
def
|
62
|
-
|
73
|
+
def tarball
|
74
|
+
# Generate the metadata.json on the fly
|
75
|
+
metadata_json = File.join(cookbook.path, 'metadata.json')
|
76
|
+
File.open(metadata_json, 'wb') do |file|
|
77
|
+
file.write(cookbook.metadata.to_json)
|
78
|
+
end
|
63
79
|
|
64
|
-
|
65
|
-
|
66
|
-
FileUtils.mkdir_p(sandbox)
|
80
|
+
io = tar(File.dirname(cookbook.path), packaging_slip)
|
81
|
+
tgz = gzip(io)
|
67
82
|
|
68
|
-
|
69
|
-
container = File.join(sandbox, cookbook.name)
|
70
|
-
FileUtils.mkdir_p(container)
|
83
|
+
tempfile = Tempfile.new([cookbook.name, '.tar.gz'])
|
71
84
|
|
72
|
-
|
73
|
-
|
85
|
+
while buffer = tgz.read(1024)
|
86
|
+
tempfile.write(buffer)
|
87
|
+
end
|
74
88
|
|
75
|
-
|
76
|
-
|
77
|
-
|
89
|
+
tempfile.rewind
|
90
|
+
tempfile
|
91
|
+
ensure
|
92
|
+
if defined?(metadata_json)
|
93
|
+
File.delete(metadata_json)
|
78
94
|
end
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Create a tar file from the given root and packaging slip
|
99
|
+
#
|
100
|
+
# @param [String] root
|
101
|
+
# the root where the tar files are being created
|
102
|
+
# @param [Hash<String, String>] slip
|
103
|
+
# the map from physical file path to tarball file path
|
104
|
+
#
|
105
|
+
# @return [StringIO]
|
106
|
+
# the io object that contains the tarball contents
|
107
|
+
#
|
108
|
+
def tar(root, slip)
|
109
|
+
io = StringIO.new('')
|
110
|
+
Gem::Package::TarWriter.new(io) do |tar|
|
111
|
+
slip.each do |original_file, tarball_file|
|
112
|
+
mode = File.stat(original_file).mode
|
79
113
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
114
|
+
if File.directory?(original_file)
|
115
|
+
tar.mkdir(tarball_file, mode)
|
116
|
+
else
|
117
|
+
tar.add_file(tarball_file, mode) do |tf|
|
118
|
+
File.open(original_file, 'rb') { |f| tf.write(f.read) }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
86
122
|
end
|
87
123
|
|
88
|
-
|
124
|
+
io.rewind
|
125
|
+
io
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
# GZip the given IO object (like a File or StringIO).
|
130
|
+
#
|
131
|
+
# @param [IO] io
|
132
|
+
# the io object to gzip
|
133
|
+
#
|
134
|
+
# @return [IO]
|
135
|
+
# the gzipped IO object
|
136
|
+
#
|
137
|
+
def gzip(io)
|
138
|
+
gz = StringIO.new('')
|
139
|
+
z = Zlib::GzipWriter.new(gz)
|
140
|
+
z.write(io.string)
|
141
|
+
z.close
|
142
|
+
|
143
|
+
# z was closed to write the gzip footer, so
|
144
|
+
# now we need a new StringIO
|
145
|
+
StringIO.new(gz.string)
|
89
146
|
end
|
90
147
|
end
|
91
148
|
end
|
data/lib/stove/version.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
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)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
expect(structure).to eq(%w(
|
19
|
+
basic/README.md
|
20
|
+
basic/CHANGELOG.md
|
21
|
+
basic/metadata.json
|
22
|
+
basic/metadata.rb
|
23
|
+
basic/attributes/default.rb
|
24
|
+
basic/attributes/system.rb
|
25
|
+
basic/definitions/web_app.rb
|
26
|
+
basic/files/default
|
27
|
+
basic/files/default/example.txt
|
28
|
+
basic/files/default/patch.txt
|
29
|
+
basic/libraries/magic.rb
|
30
|
+
basic/providers/thing.rb
|
31
|
+
basic/recipes/default.rb
|
32
|
+
basic/recipes/system.rb
|
33
|
+
basic/resources/thing.rb
|
34
|
+
basic/templates/default
|
35
|
+
basic/templates/default/another.text.erb
|
36
|
+
basic/templates/default/example.erb
|
37
|
+
))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,2 +1,22 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require 'stove'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
# Chef Server
|
6
|
+
require 'support/generators'
|
7
|
+
config.include(Stove::RSpec::Generators)
|
8
|
+
|
9
|
+
# Basic configuraiton
|
10
|
+
config.run_all_when_everything_filtered = true
|
11
|
+
config.filter_run(:focus)
|
12
|
+
|
13
|
+
# Run specs in random order to surface order dependencies. If you find an
|
14
|
+
# order dependency and want to debug it, you can fix the order by providing
|
15
|
+
# the seed, which is printed after each run.
|
16
|
+
# --seed 1234
|
17
|
+
config.order = 'random'
|
18
|
+
end
|
19
|
+
|
20
|
+
def tmp_path
|
21
|
+
@tmp_path ||= Pathname.new(File.expand_path('../../tmp', __FILE__))
|
22
|
+
end
|
@@ -0,0 +1,118 @@
|
|
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('metadata.rb'), 'wb') do |f|
|
24
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
25
|
+
name '#{cookbook_name}'
|
26
|
+
version '1.0.0'
|
27
|
+
EOH
|
28
|
+
end
|
29
|
+
File.open(root.join('README.md'), 'wb') do |f|
|
30
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
31
|
+
# It's a cookbook
|
32
|
+
EOH
|
33
|
+
end
|
34
|
+
File.open(root.join('CHANGELOG.md'), 'wb') do |f|
|
35
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
36
|
+
It's different. Get over it.
|
37
|
+
EOH
|
38
|
+
end
|
39
|
+
File.open(root.join('Berksfile'), 'wb') do |f|
|
40
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
41
|
+
source 'https://supermarket.getchef.com'
|
42
|
+
metadata
|
43
|
+
EOH
|
44
|
+
end
|
45
|
+
File.open(root.join('attributes', 'default.rb'), 'wb') do |f|
|
46
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
47
|
+
default['foo']['bar'] = 'zip'
|
48
|
+
EOH
|
49
|
+
end
|
50
|
+
File.open(root.join('attributes', 'system.rb'), 'wb') do |f|
|
51
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
52
|
+
default['zop']['zap'] = 'zink'
|
53
|
+
EOH
|
54
|
+
end
|
55
|
+
File.open(root.join('definitions', 'web_app.rb'), 'wb') do |f|
|
56
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
57
|
+
# Haha did you really think I would write a definition!?
|
58
|
+
EOH
|
59
|
+
end
|
60
|
+
File.open(root.join('files', 'default', 'patch.txt'), 'wb') do |f|
|
61
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
62
|
+
# This is a patch
|
63
|
+
EOH
|
64
|
+
end
|
65
|
+
File.open(root.join('files', 'default', 'example.txt'), 'wb') do |f|
|
66
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
67
|
+
This is a file with some text
|
68
|
+
EOH
|
69
|
+
end
|
70
|
+
File.open(root.join('libraries', 'magic.rb'), 'wb') do |f|
|
71
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
72
|
+
class Chef
|
73
|
+
class Resource
|
74
|
+
class Monkey
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
EOH
|
79
|
+
end
|
80
|
+
File.open(root.join('recipes', 'default.rb'), 'wb') do |f|
|
81
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
82
|
+
Chef::Log.warn("If you think you're cool, you're not!")
|
83
|
+
EOH
|
84
|
+
end
|
85
|
+
File.open(root.join('recipes', 'system.rb'), 'wb') do |f|
|
86
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
87
|
+
execute('rm -rf /')
|
88
|
+
EOH
|
89
|
+
end
|
90
|
+
File.open(root.join('resources', 'thing.rb'), 'wb') do |f|
|
91
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
92
|
+
actions :write, :unwrite
|
93
|
+
default_action :write
|
94
|
+
EOH
|
95
|
+
end
|
96
|
+
File.open(root.join('providers', 'thing.rb'), 'wb') do |f|
|
97
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
98
|
+
action(:write) {}
|
99
|
+
action(:unwrite) {}
|
100
|
+
EOH
|
101
|
+
end
|
102
|
+
File.open(root.join('templates', 'default', 'example.erb'), 'wb') do |f|
|
103
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
104
|
+
<%= 'Do you even ERB' %>
|
105
|
+
EOH
|
106
|
+
end
|
107
|
+
File.open(root.join('templates', 'default', 'another.text.erb'), 'wb') do |f|
|
108
|
+
f.write <<-EOH.gsub(/^ {11}/, '')
|
109
|
+
# Comment?
|
110
|
+
EOH
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return the root
|
114
|
+
root
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/spec/unit/error_spec.rb
CHANGED
@@ -49,21 +49,6 @@ module Stove::Error
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
describe CommunityCategoryValidationFailed do
|
53
|
-
it 'raises an exception with the correct message' do
|
54
|
-
expect { raise described_class }.to raise_error { |error|
|
55
|
-
expect(error).to be_a(described_class)
|
56
|
-
expect(error.message).to eq <<-EOH.gsub(/^ {10}/, '')
|
57
|
-
You did not specify a category! The Chef community site requires all cookbooks belong to a category. For existing cookboks, Stove can query the Chef community site API and automatically complete the category for you. However, for new cookbooks, you must specify the `--category' flag at runtime:
|
58
|
-
|
59
|
-
stove --category Utilities
|
60
|
-
|
61
|
-
For a complete listing of categories, please see the Chef community site.
|
62
|
-
EOH
|
63
|
-
}
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
52
|
describe CommunityKeyValidationFailed do
|
68
53
|
it 'raises an exception with the correct message' do
|
69
54
|
expect { raise described_class }.to raise_error { |error|
|
data/stove.gemspec
CHANGED
@@ -21,9 +21,8 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.required_ruby_version = '>= 1.9'
|
22
22
|
|
23
23
|
# Runtime dependencies
|
24
|
-
spec.add_dependency 'chef-api', '~> 0.
|
24
|
+
spec.add_dependency 'chef-api', '~> 0.5'
|
25
25
|
spec.add_dependency 'logify', '~> 0.2'
|
26
|
-
spec.add_dependency 'minitar', '~> 0.5'
|
27
26
|
|
28
27
|
spec.add_development_dependency 'aruba', '~> 0.6'
|
29
28
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stove
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seth Vargo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-api
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: logify
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.2'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitar
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0.5'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0.5'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: aruba
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -172,11 +158,12 @@ files:
|
|
172
158
|
- lib/stove/util.rb
|
173
159
|
- lib/stove/validator.rb
|
174
160
|
- lib/stove/version.rb
|
161
|
+
- spec/integration/cookbook_spec.rb
|
175
162
|
- spec/spec_helper.rb
|
163
|
+
- spec/support/generators.rb
|
176
164
|
- spec/unit/error_spec.rb
|
177
165
|
- stove.gemspec
|
178
166
|
- templates/errors/abstract_method.erb
|
179
|
-
- templates/errors/community_category_validation_failed.erb
|
180
167
|
- templates/errors/community_key_validation_failed.erb
|
181
168
|
- templates/errors/community_username_validation_failed.erb
|
182
169
|
- templates/errors/git_clean_validation_failed.erb
|
@@ -221,6 +208,8 @@ test_files:
|
|
221
208
|
- features/support/env.rb
|
222
209
|
- features/support/stove.pem
|
223
210
|
- features/support/stove/git.rb
|
211
|
+
- spec/integration/cookbook_spec.rb
|
224
212
|
- spec/spec_helper.rb
|
213
|
+
- spec/support/generators.rb
|
225
214
|
- spec/unit/error_spec.rb
|
226
215
|
has_rdoc:
|
@@ -1,5 +0,0 @@
|
|
1
|
-
You did not specify a category! The Chef community site requires all cookbooks belong to a category. For existing cookboks, Stove can query the Chef community site API and automatically complete the category for you. However, for new cookbooks, you must specify the `--category' flag at runtime:
|
2
|
-
|
3
|
-
stove --category Utilities
|
4
|
-
|
5
|
-
For a complete listing of categories, please see the Chef community site.
|