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,160 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module ChefAPI
|
4
|
+
module Logger
|
5
|
+
class << self
|
6
|
+
# @private
|
7
|
+
def included(base)
|
8
|
+
base.send(:extend, ClassMethods)
|
9
|
+
base.send(:include, InstanceMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# Get the logger class for the given name. If a logger does not exist
|
14
|
+
# for the given name, a new one is created.
|
15
|
+
#
|
16
|
+
# @param [String] name
|
17
|
+
# the name of the logger to find
|
18
|
+
#
|
19
|
+
# @return [DefaultLogger]
|
20
|
+
# the logger for the given name
|
21
|
+
#
|
22
|
+
def logger_for(name)
|
23
|
+
loggers[name] ||= DefaultLogger.new(name, level)
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# The global log level.
|
28
|
+
#
|
29
|
+
# @return [Symbol]
|
30
|
+
#
|
31
|
+
def level
|
32
|
+
@level ||= :warn
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Set the global log level.
|
37
|
+
#
|
38
|
+
# @param [String, Symbol] level
|
39
|
+
# the log level
|
40
|
+
#
|
41
|
+
# @return [Symbol]
|
42
|
+
#
|
43
|
+
def level=(level)
|
44
|
+
@level = level.to_s.downcase.to_sym
|
45
|
+
|
46
|
+
loggers.each do |_, logger|
|
47
|
+
logger.level = @level
|
48
|
+
end
|
49
|
+
|
50
|
+
@level
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def loggers
|
56
|
+
@loggers ||= {}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module ClassMethods
|
61
|
+
#
|
62
|
+
# Write a message to the logger for this class.
|
63
|
+
#
|
64
|
+
# @return [DefaultLogger]
|
65
|
+
#
|
66
|
+
def log
|
67
|
+
@log ||= Logger.logger_for(name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module InstanceMethods
|
72
|
+
#
|
73
|
+
# Write a message to the logger for this instance's class.
|
74
|
+
#
|
75
|
+
# @return [DefaultLogger]
|
76
|
+
#
|
77
|
+
def log
|
78
|
+
@log ||= Logger.logger_for(self.class.name)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# The default logger for everything logged through the Chef API.
|
84
|
+
#
|
85
|
+
class DefaultLogger < ::Logger
|
86
|
+
class << self
|
87
|
+
private
|
88
|
+
|
89
|
+
#
|
90
|
+
# @macro attr_questioner
|
91
|
+
#
|
92
|
+
# @method $1?
|
93
|
+
# Determine if the current logger's level is +:$1+.
|
94
|
+
#
|
95
|
+
# @return [Boolean]
|
96
|
+
# true if the current log level is +:$1+ or lower, false otherwise
|
97
|
+
#
|
98
|
+
def attr_questioner(name)
|
99
|
+
class_eval <<-EOH, __FILE__, __LINE__ + 1
|
100
|
+
def #{name}?
|
101
|
+
level == ::Logger::Severity.const_get('#{name}'.upcase)
|
102
|
+
end
|
103
|
+
EOH
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
attr_questioner :fatal
|
108
|
+
attr_questioner :error
|
109
|
+
attr_questioner :warn
|
110
|
+
attr_questioner :info
|
111
|
+
attr_questioner :debug
|
112
|
+
|
113
|
+
#
|
114
|
+
# Create a new logger with the given name. In debug mode, the +name+ is
|
115
|
+
# used to identify the caller of the log message. In other modes, it is
|
116
|
+
# ignored entirely.
|
117
|
+
#
|
118
|
+
# @param [String] name
|
119
|
+
# the name of the class calling the logger
|
120
|
+
#
|
121
|
+
def initialize(name, level)
|
122
|
+
super($stdout)
|
123
|
+
|
124
|
+
@formatter = formatter
|
125
|
+
@progname = name
|
126
|
+
self.level = level
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# Set this logger's level to the given key.
|
131
|
+
#
|
132
|
+
# @example Set the log level to +info+
|
133
|
+
# logger.level = :info
|
134
|
+
#
|
135
|
+
# @param [String, Symbol] value
|
136
|
+
# the value to set for the logger
|
137
|
+
#
|
138
|
+
def level=(value)
|
139
|
+
@level = ::Logger::Severity.const_get(value.to_s.upcase)
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def formatter
|
145
|
+
Proc.new do |severity, timestamp, progname, message|
|
146
|
+
if debug?
|
147
|
+
"[#{progname}] #{message}\n"
|
148
|
+
else
|
149
|
+
message + "\n"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class NullLogger < DefaultLogger
|
156
|
+
def initialize(*args); end
|
157
|
+
def add(*args, &block); end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ChefAPI
|
2
|
+
#
|
3
|
+
# Create a proxy object, which delegates all methods to the class given in
|
4
|
+
# the initializer. This is used by the client object to filter the first
|
5
|
+
# parameter of any singleton methods to pass in the given client as the first
|
6
|
+
# argument. It's dirty, but it allows developers to write pretty code, which
|
7
|
+
# is more what I care about.
|
8
|
+
#
|
9
|
+
# @example Without a proxy object
|
10
|
+
# client = ChefAPI::Client.new('...')
|
11
|
+
# repo = ChefAPI::Resource::Repository.new(client, name: '...')
|
12
|
+
#
|
13
|
+
# @example With a proxy object
|
14
|
+
# client = ChefAPI::Client.new('...')
|
15
|
+
# repo = client.repositories.new(name: '...')
|
16
|
+
#
|
17
|
+
class Proxy < BasicObject
|
18
|
+
#
|
19
|
+
# This is quite possibly the worst thing I've ever done in my life.
|
20
|
+
# Dynamically remove all methods from this class, just we we can delegate
|
21
|
+
# *everything* to the instance class.
|
22
|
+
#
|
23
|
+
# It is presumed there is no hope...
|
24
|
+
#
|
25
|
+
instance_methods.each do |name|
|
26
|
+
unless name =~ /__|object_id|instance_eval/
|
27
|
+
undef_method name
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Create a new proxy object.
|
33
|
+
#
|
34
|
+
# @param [ChefAPI::Client] client
|
35
|
+
# the client object to use for the proxy
|
36
|
+
# @param [Class] klass
|
37
|
+
# the class to proxy to
|
38
|
+
#
|
39
|
+
def initialize(client, klass)
|
40
|
+
@client = client
|
41
|
+
@klass = klass
|
42
|
+
|
43
|
+
klass.singleton_methods.each do |name|
|
44
|
+
instance_eval <<-EOH, __FILE__, __LINE__ + 1
|
45
|
+
def #{name}(*args)
|
46
|
+
if args.last.is_a?(::Hash)
|
47
|
+
args.last[:client] = @client
|
48
|
+
else
|
49
|
+
args << { client: @client }
|
50
|
+
end
|
51
|
+
|
52
|
+
@klass.send(:#{name}, *args)
|
53
|
+
end
|
54
|
+
EOH
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @private
|
59
|
+
def method_missing(m, *args, &block)
|
60
|
+
if @klass.respond_to?(m)
|
61
|
+
@klass.send(m, *args, &block)
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @private
|
68
|
+
def respond_to_missing?(m, include_private = false)
|
69
|
+
@klass.respond_to?(m) || super
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ChefAPI
|
2
|
+
module Resource
|
3
|
+
autoload :Base, 'chef-api/resources/base'
|
4
|
+
autoload :Client, 'chef-api/resources/client'
|
5
|
+
autoload :CollectionProxy, 'chef-api/resources/collection_proxy'
|
6
|
+
autoload :Cookbook, 'chef-api/resources/cookbook'
|
7
|
+
autoload :CookbookVersion, 'chef-api/resources/cookbook_version'
|
8
|
+
autoload :DataBag, 'chef-api/resources/data_bag'
|
9
|
+
autoload :DataBagItem, 'chef-api/resources/data_bag_item'
|
10
|
+
autoload :Environment, 'chef-api/resources/environment'
|
11
|
+
autoload :Node, 'chef-api/resources/node'
|
12
|
+
autoload :Principal, 'chef-api/resources/principal'
|
13
|
+
autoload :Role, 'chef-api/resources/role'
|
14
|
+
autoload :User, 'chef-api/resources/user'
|
15
|
+
end
|
16
|
+
end
|