chef-api 0.2.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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +14 -0
- data/Gemfile +12 -0
- data/LICENSE +201 -0
- data/README.md +264 -0
- data/Rakefile +1 -0
- data/chef-api.gemspec +25 -0
- data/lib/chef-api/boolean.rb +6 -0
- data/lib/chef-api/configurable.rb +78 -0
- data/lib/chef-api/connection.rb +466 -0
- data/lib/chef-api/defaults.rb +130 -0
- data/lib/chef-api/error_collection.rb +44 -0
- data/lib/chef-api/errors.rb +35 -0
- data/lib/chef-api/logger.rb +160 -0
- data/lib/chef-api/proxy.rb +72 -0
- data/lib/chef-api/resource.rb +16 -0
- data/lib/chef-api/resources/base.rb +951 -0
- data/lib/chef-api/resources/client.rb +85 -0
- data/lib/chef-api/resources/collection_proxy.rb +217 -0
- data/lib/chef-api/resources/cookbook.rb +24 -0
- data/lib/chef-api/resources/cookbook_version.rb +23 -0
- data/lib/chef-api/resources/data_bag.rb +136 -0
- data/lib/chef-api/resources/data_bag_item.rb +35 -0
- data/lib/chef-api/resources/environment.rb +16 -0
- data/lib/chef-api/resources/node.rb +17 -0
- data/lib/chef-api/resources/principal.rb +11 -0
- data/lib/chef-api/resources/role.rb +16 -0
- data/lib/chef-api/resources/user.rb +11 -0
- data/lib/chef-api/schema.rb +112 -0
- data/lib/chef-api/util.rb +119 -0
- data/lib/chef-api/validator.rb +16 -0
- data/lib/chef-api/validators/base.rb +82 -0
- data/lib/chef-api/validators/required.rb +11 -0
- data/lib/chef-api/validators/type.rb +23 -0
- data/lib/chef-api/version.rb +3 -0
- data/lib/chef-api.rb +76 -0
- data/locales/en.yml +89 -0
- data/spec/integration/resources/client_spec.rb +8 -0
- data/spec/integration/resources/environment_spec.rb +8 -0
- data/spec/integration/resources/node_spec.rb +8 -0
- data/spec/integration/resources/role_spec.rb +8 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/chef_server.rb +115 -0
- data/spec/support/shared/chef_api_resource.rb +91 -0
- data/spec/unit/resources/base_spec.rb +47 -0
- data/spec/unit/resources/client_spec.rb +69 -0
- metadata +128 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
module ChefAPI
|
2
|
+
#
|
3
|
+
# A wrapper class that describes a remote schema (such as the Chef Server
|
4
|
+
# API layer), with validation and other magic spinkled on top.
|
5
|
+
#
|
6
|
+
class Schema
|
7
|
+
|
8
|
+
#
|
9
|
+
# The full list of attributes defined on this schema.
|
10
|
+
#
|
11
|
+
# @return [Hash]
|
12
|
+
#
|
13
|
+
attr_reader :attributes
|
14
|
+
|
15
|
+
attr_reader :ignored_attributes
|
16
|
+
attr_reader :transformations
|
17
|
+
|
18
|
+
#
|
19
|
+
# The list of defined validators for this schema.
|
20
|
+
#
|
21
|
+
# @return [Array]
|
22
|
+
#
|
23
|
+
attr_reader :validators
|
24
|
+
|
25
|
+
#
|
26
|
+
# Create a new schema and evaulte the block contents in a clean room.
|
27
|
+
#
|
28
|
+
def initialize(&block)
|
29
|
+
@attributes = {}
|
30
|
+
@ignored_attributes = {}
|
31
|
+
@transformations = {}
|
32
|
+
@validators = []
|
33
|
+
|
34
|
+
instance_eval(&block) if block
|
35
|
+
|
36
|
+
@attributes.freeze
|
37
|
+
@ignored_attributes.freeze
|
38
|
+
@transformations.freeze
|
39
|
+
@validators.freeze
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# The defined primary key for this schema. If no primary key is given, it
|
44
|
+
# is assumed to be the first item in the list.
|
45
|
+
#
|
46
|
+
# @return [Symbol]
|
47
|
+
#
|
48
|
+
def primary_key
|
49
|
+
@primary_key ||= @attributes.first[0]
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# DSL method for defining an attribute.
|
54
|
+
#
|
55
|
+
# @param [Symbol] key
|
56
|
+
# the key to use
|
57
|
+
# @param [Hash] options
|
58
|
+
# a list of options to create the attribute with
|
59
|
+
#
|
60
|
+
# @return [Symbol]
|
61
|
+
# the attribute
|
62
|
+
#
|
63
|
+
def attribute(key, options = {})
|
64
|
+
if primary_key = options.delete(:primary)
|
65
|
+
@primary_key = key.to_sym
|
66
|
+
end
|
67
|
+
|
68
|
+
@attributes[key] = options.delete(:default)
|
69
|
+
|
70
|
+
# All remaining options are assumed to be validations
|
71
|
+
options.each do |validation, options|
|
72
|
+
if options
|
73
|
+
@validators << Validator.find(validation).new(key, options)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
key
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Ignore an attribute. This is handy if you know there's an attribute that
|
82
|
+
# the remote server will return, but you don't want that information
|
83
|
+
# exposed to the user (or the data is sensitive).
|
84
|
+
#
|
85
|
+
# @param [Array<Symbol>] keys
|
86
|
+
# the list of attributes to ignore
|
87
|
+
#
|
88
|
+
def ignore(*keys)
|
89
|
+
keys.each do |key|
|
90
|
+
@ignored_attributes[key.to_sym] = true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Transform an attribute onto another.
|
96
|
+
#
|
97
|
+
# @example Transform the +:bacon+ attribute onto the +:ham+ attribute
|
98
|
+
# transform :bacon, ham: true
|
99
|
+
#
|
100
|
+
# @example Transform an attribute with a complex transformation
|
101
|
+
# transform :bacon, ham: ->(value) { value.split('__', 2).last }
|
102
|
+
#
|
103
|
+
# @param [Symbol] key
|
104
|
+
# the attribute to transform
|
105
|
+
# @param [Hash] options
|
106
|
+
# the key-value pair of the transformations to make
|
107
|
+
#
|
108
|
+
def transform(key, options = {})
|
109
|
+
@transformations[key.to_sym] = options
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module ChefAPI
|
2
|
+
module Util
|
3
|
+
extend self
|
4
|
+
|
5
|
+
#
|
6
|
+
# Covert the given CaMelCaSeD string to under_score. Graciously borrowed
|
7
|
+
# from http://stackoverflow.com/questions/1509915.
|
8
|
+
#
|
9
|
+
# @param [String] string
|
10
|
+
# the string to use for transformation
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
def underscore(string)
|
15
|
+
string
|
16
|
+
.to_s
|
17
|
+
.gsub(/::/, '/')
|
18
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
19
|
+
.gsub(/([a-z\d])([A-Z])/,'\1_\2')
|
20
|
+
.tr('-', '_')
|
21
|
+
.downcase
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Convert an underscored string to it's camelcase equivalent constant.
|
26
|
+
#
|
27
|
+
# @param [String] string
|
28
|
+
# the string to convert
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
#
|
32
|
+
def camelize(string)
|
33
|
+
string
|
34
|
+
.to_s
|
35
|
+
.split('_')
|
36
|
+
.map { |e| e.capitalize }
|
37
|
+
.join
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Truncate the given string to a certain number of characters.
|
42
|
+
#
|
43
|
+
# @param [String] string
|
44
|
+
# the string to truncate
|
45
|
+
# @param [Hash] options
|
46
|
+
# the list of options (such as +length+)
|
47
|
+
#
|
48
|
+
def truncate(string, options = {})
|
49
|
+
length = options[:length] || 30
|
50
|
+
|
51
|
+
if string.length > length
|
52
|
+
string[0..length-3] + '...'
|
53
|
+
else
|
54
|
+
string
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# "Safely" read the contents of a file on disk, catching any permission
|
60
|
+
# errors or not found errors and raising a nicer exception.
|
61
|
+
#
|
62
|
+
# @example Reading a file that does not exist
|
63
|
+
# safe_read('/non-existent/file') #=> Error::FileNotFound
|
64
|
+
#
|
65
|
+
# @example Reading a file with improper permissions
|
66
|
+
# safe_read('/bad-permissions') #=> Error::InsufficientFilePermissions
|
67
|
+
#
|
68
|
+
# @example Reading a regular file
|
69
|
+
# safe_read('my-file.txt') #=> ["my-file", "..."]
|
70
|
+
#
|
71
|
+
# @param [String] path
|
72
|
+
# the path to the file on disk
|
73
|
+
#
|
74
|
+
# @return [Array<String>]
|
75
|
+
# A array where the first value is the basename of the file and the
|
76
|
+
# second value is the literal contents from +File.read+.
|
77
|
+
#
|
78
|
+
def safe_read(path)
|
79
|
+
path = File.expand_path(path)
|
80
|
+
name = File.basename(path, '.*')
|
81
|
+
contents = File.read(path)
|
82
|
+
|
83
|
+
[name, contents]
|
84
|
+
rescue Errno::EACCES
|
85
|
+
raise Error::InsufficientFilePermissions.new(path: path)
|
86
|
+
rescue Errno::ENOENT
|
87
|
+
raise Error::FileNotFound.new(path: path)
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Quickly iterate over a collection using native Ruby threads, preserving
|
92
|
+
# the original order of elements and being all thread-safe and stuff.
|
93
|
+
#
|
94
|
+
# @example Parse a collection of JSON files
|
95
|
+
#
|
96
|
+
# fast_collect(Dir['**/*.json']) do |item|
|
97
|
+
# JSON.parse(File.read(item))
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# @param [#each] collection
|
101
|
+
# the collection to iterate
|
102
|
+
# @param [Proc] block
|
103
|
+
# the block to evaluate (typically an expensive operation)
|
104
|
+
#
|
105
|
+
# @return [Array]
|
106
|
+
# the result of the iteration
|
107
|
+
#
|
108
|
+
def fast_collect(collection, &block)
|
109
|
+
collection.map do |item|
|
110
|
+
Thread.new do
|
111
|
+
Thread.current[:result] = block.call(item)
|
112
|
+
end
|
113
|
+
end.collect do |thread|
|
114
|
+
thread.join
|
115
|
+
thread[:result]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ChefAPI
|
2
|
+
module Validator
|
3
|
+
autoload :Base, 'chef-api/validators/base'
|
4
|
+
autoload :Required, 'chef-api/validators/required'
|
5
|
+
autoload :Type, 'chef-api/validators/type'
|
6
|
+
|
7
|
+
#
|
8
|
+
# Find a validator by the given key.
|
9
|
+
#
|
10
|
+
def self.find(key)
|
11
|
+
const_get(Util.camelize(key))
|
12
|
+
rescue NameError
|
13
|
+
raise Error::InvalidValidator.new(key: key)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module ChefAPI
|
2
|
+
class Validator::Base
|
3
|
+
#
|
4
|
+
# @return [Symbol]
|
5
|
+
# the attribute to apply this validation on
|
6
|
+
#
|
7
|
+
attr_reader :attribute
|
8
|
+
|
9
|
+
#
|
10
|
+
# @return [Hash]
|
11
|
+
# the hash of additional arguments passed in
|
12
|
+
#
|
13
|
+
attr_reader :options
|
14
|
+
|
15
|
+
#
|
16
|
+
# Create anew validator.
|
17
|
+
#
|
18
|
+
# @param [Symbol] attribute
|
19
|
+
# the attribute to apply this validation on
|
20
|
+
# @param [Hash] options
|
21
|
+
# the list of options passed in
|
22
|
+
#
|
23
|
+
def initialize(attribute, options = {})
|
24
|
+
@attribute = attribute
|
25
|
+
@options = options.is_a?(Hash) ? options : {}
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Just in case someone forgets to define a key, this will return the
|
30
|
+
# class's underscored name without "validator" as a symbol.
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# FooValidator.new.key #=> :foo
|
34
|
+
#
|
35
|
+
# @return [Symbol]
|
36
|
+
#
|
37
|
+
def key
|
38
|
+
name = self.class.name.split('::').last
|
39
|
+
Util.underscore(name).to_sym
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Execute the validations. This is an abstract class and must be
|
44
|
+
# overridden in custom validators.
|
45
|
+
#
|
46
|
+
# @param [Resource::Base::Base] resource
|
47
|
+
# the parent resource to validate against
|
48
|
+
#
|
49
|
+
def validate(resource)
|
50
|
+
raise Error::AbstractMethod.new(method: 'Validators::Base#validate')
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# The string representation of this validation.
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
#
|
58
|
+
def to_s
|
59
|
+
"#<#{classname}>"
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# The string representation of this validation.
|
64
|
+
#
|
65
|
+
# @return [String]
|
66
|
+
#
|
67
|
+
def inspect
|
68
|
+
"#<#{classname} :#{attribute}>"
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
#
|
74
|
+
# The class name for this validator.
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
#
|
78
|
+
def classname
|
79
|
+
@classname ||= self.class.name.split('::')[1..-1].join('::')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ChefAPI
|
2
|
+
class Validator::Type < Validator::Base
|
3
|
+
attr_reader :types
|
4
|
+
|
5
|
+
#
|
6
|
+
# Overload the super method to capture the type attribute in the options
|
7
|
+
# hash.
|
8
|
+
#
|
9
|
+
def initialize(attribute, type)
|
10
|
+
super
|
11
|
+
@types = Array(type)
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate(resource)
|
15
|
+
value = resource._attributes[attribute]
|
16
|
+
|
17
|
+
if value && !types.any? { |type| value.is_a?(type) }
|
18
|
+
short_name = type.to_s.split('::').last
|
19
|
+
resource.errors.add(attribute, "must be a kind of #{short_name}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/chef-api.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'pathname'
|
3
|
+
require 'chef-api/version'
|
4
|
+
|
5
|
+
module ChefAPI
|
6
|
+
autoload :Boolean, 'chef-api/boolean'
|
7
|
+
autoload :Configurable, 'chef-api/configurable'
|
8
|
+
autoload :Connection, 'chef-api/connection'
|
9
|
+
autoload :Defaults, 'chef-api/defaults'
|
10
|
+
autoload :Error, 'chef-api/errors'
|
11
|
+
autoload :ErrorCollection, 'chef-api/error_collection'
|
12
|
+
autoload :Logger, 'chef-api/logger'
|
13
|
+
autoload :Resource, 'chef-api/resource'
|
14
|
+
autoload :Schema, 'chef-api/schema'
|
15
|
+
autoload :Util, 'chef-api/util'
|
16
|
+
autoload :Validator, 'chef-api/validator'
|
17
|
+
|
18
|
+
#
|
19
|
+
# @todo Document this and why it's important
|
20
|
+
#
|
21
|
+
UNSET = Object.new
|
22
|
+
|
23
|
+
class << self
|
24
|
+
include ChefAPI::Configurable
|
25
|
+
|
26
|
+
#
|
27
|
+
# The source root of the ChefAPI gem. This is useful when requiring files
|
28
|
+
# that are relative to the root of the project.
|
29
|
+
#
|
30
|
+
# @return [Pathname]
|
31
|
+
#
|
32
|
+
def root
|
33
|
+
@root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# API connection object based off the configured options in {Configurable}.
|
38
|
+
#
|
39
|
+
# @return [ChefAPI::Connection]
|
40
|
+
#
|
41
|
+
def connection
|
42
|
+
unless @connection && @connection.same_options?(options)
|
43
|
+
@connection = ChefAPI::Connection.new(options)
|
44
|
+
end
|
45
|
+
|
46
|
+
@connection
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Delegate all methods to the connection object, essentially making the
|
51
|
+
# module object behave like a {Connection}.
|
52
|
+
#
|
53
|
+
def method_missing(m, *args, &block)
|
54
|
+
if connection.respond_to?(m)
|
55
|
+
connection.send(m, *args, &block)
|
56
|
+
else
|
57
|
+
super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Delegating +respond_to+ to the {Connection}.
|
63
|
+
#
|
64
|
+
def respond_to_missing?(m, include_private = false)
|
65
|
+
connection.respond_to?(m) || super
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
require 'i18n'
|
71
|
+
I18n.enforce_available_locales = false
|
72
|
+
I18n.load_path << Dir[ChefAPI.root.join('locales', '*.yml').to_s]
|
73
|
+
|
74
|
+
# Load the initial default values
|
75
|
+
ChefAPI.setup
|
76
|
+
|
data/locales/en.yml
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
en:
|
2
|
+
chef_api:
|
3
|
+
errors:
|
4
|
+
abstract_method: >
|
5
|
+
`%{method}` is an abstract method. You must override this method in
|
6
|
+
your subclass with the proper implementation and logic. For more
|
7
|
+
information, please see the inline documentation for %{method}. If you
|
8
|
+
are not a developer, this is most likely a bug in the ChefAPI gem.
|
9
|
+
Please file a bug report at
|
10
|
+
https://github.com/sethvargo/chef-api/issues/new and include the
|
11
|
+
command(s) you ran to arrive at this error.
|
12
|
+
cannot_regenerate_key: >
|
13
|
+
You called `regenerate_key` on a client that does not exist on the
|
14
|
+
remote Chef Server. You can only regenerate a private key for a client
|
15
|
+
that is persisted. Try saving this record this client before
|
16
|
+
regenerating the private key.
|
17
|
+
file_not_found: >
|
18
|
+
I could not find a file at `%{path}`. Please make sure you have typed
|
19
|
+
the path correctly and that the resource at `%{path}` does actually
|
20
|
+
exist.
|
21
|
+
http_bad_request: >
|
22
|
+
The Chef Server did not understand the request because it was malformed.
|
23
|
+
The Chef Server returned this message:
|
24
|
+
|
25
|
+
%{message}
|
26
|
+
http_forbidden_request: >
|
27
|
+
The Chef Server actively refused to fulfill the request. The Chef Server
|
28
|
+
returned this message:
|
29
|
+
|
30
|
+
%{message}
|
31
|
+
http_method_not_allowed: >
|
32
|
+
That HTTP method is not allowed on this URL. The Chef Server returned
|
33
|
+
this message:
|
34
|
+
|
35
|
+
%{message}
|
36
|
+
http_not_acceptable: >
|
37
|
+
The Chef Server identified this request as unacceptable. This usually
|
38
|
+
means you have not specified the correct Accept or Content-Type headers
|
39
|
+
on the request object. The Chef Server returned this message:
|
40
|
+
|
41
|
+
%{message}
|
42
|
+
http_not_found: >
|
43
|
+
The requested URL does not exist on the Chef Server. The Chef Server
|
44
|
+
returned this message:
|
45
|
+
|
46
|
+
%{message}
|
47
|
+
http_server_unavailable: >
|
48
|
+
The Chef Server is currently unavailable or is not currently accepting
|
49
|
+
client connections. Please ensure the server is accessible via ping
|
50
|
+
or telnet on your local network. If this error persists, please contact
|
51
|
+
your network administrator.
|
52
|
+
http_unauthorized_request: >
|
53
|
+
The Chef Server requires authorization. Please ensure you have specified
|
54
|
+
the correct client name and private key. If this error continues, please
|
55
|
+
verify the given client has the proper permissions on the Chef Server.
|
56
|
+
The Chef Server returned this message:
|
57
|
+
|
58
|
+
%{message}
|
59
|
+
insufficient_file_permissions: >
|
60
|
+
I cannot read the file at `%{path}` because the permissions on the file
|
61
|
+
do not permit it. Please ensure the file has the correct permissions and
|
62
|
+
that this Ruby process is running as a user with access to `%{path}`.
|
63
|
+
invalid_resource: >
|
64
|
+
There were errors saving your resource: %{errors}
|
65
|
+
invalid_validator: >
|
66
|
+
`%{key}` is not a valid validator. Please make sure it is spelled
|
67
|
+
correctly and that the constant is properly defined. If you are using
|
68
|
+
a custom validator, please ensure the validator extends
|
69
|
+
ChefAPI::Validator::Base and is a subclass of ChefAPI::Validator.
|
70
|
+
missing_url_parameter: >
|
71
|
+
The required URL parameter `%{param}' was not present. Please specify
|
72
|
+
`%{param}' as an option, like Resource.new(id, %{param}: 'value').
|
73
|
+
not_a_directory: >
|
74
|
+
The given path `%{path}' is not a directory. Please make sure you have
|
75
|
+
passed the path to a directory on disk.
|
76
|
+
resource_already_exists: >
|
77
|
+
The %{type} `%{id}` already exists on the Chef Server. Each
|
78
|
+
%{type} must have a unique identifier and the Chef Server indicated
|
79
|
+
this %{type} already exists. If you are trying to update the %{type},
|
80
|
+
consider using the `update` method instead.
|
81
|
+
resource_not_found: >
|
82
|
+
There is no %{type} with an id of `%{id}` on the Chef Server. If you
|
83
|
+
are updating the %{type}, please make sure the %{type} exists and has
|
84
|
+
the correct Chef identifier (primary key).
|
85
|
+
resource_not_mutable: >
|
86
|
+
The %{type} `%{id}` is not mutable. It may be locked by the remote
|
87
|
+
Chef Server, or the Chef Server may not permit modifying the resource.
|
88
|
+
unknown_attribute: >
|
89
|
+
`%{attribute}` is not a valid attribute
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'chef-api'
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
# Chef Server
|
5
|
+
require 'support/chef_server'
|
6
|
+
config.include(RSpec::ChefServer::DSL)
|
7
|
+
|
8
|
+
# Shared Examples
|
9
|
+
Dir[ChefAPI.root.join('spec/support/shared/**/*.rb')].each { |file| require file }
|
10
|
+
|
11
|
+
# Basic configuraiton
|
12
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
13
|
+
config.run_all_when_everything_filtered = true
|
14
|
+
config.filter_run(:focus)
|
15
|
+
|
16
|
+
#
|
17
|
+
config.before(:each) do
|
18
|
+
ChefAPI::Logger.level = :fatal
|
19
|
+
end
|
20
|
+
|
21
|
+
# Run specs in random order to surface order dependencies. If you find an
|
22
|
+
# order dependency and want to debug it, you can fix the order by providing
|
23
|
+
# the seed, which is printed after each run.
|
24
|
+
# --seed 1234
|
25
|
+
config.order = 'random'
|
26
|
+
end
|