garcun 0.0.2
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/.gitattributes +17 -0
- data/.gitignore +197 -0
- data/.rspec +2 -0
- data/Gemfile +22 -0
- data/LICENSE +201 -0
- data/README.md +521 -0
- data/Rakefile +47 -0
- data/garcun.gemspec +83 -0
- data/lib/garcon.rb +290 -0
- data/lib/garcon/chef/chef_helpers.rb +343 -0
- data/lib/garcon/chef/coerce/coercer.rb +134 -0
- data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
- data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
- data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
- data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
- data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
- data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
- data/lib/garcon/chef/handler/devreporter.rb +127 -0
- data/lib/garcon/chef/log.rb +64 -0
- data/lib/garcon/chef/node.rb +100 -0
- data/lib/garcon/chef/provider/civilize.rb +209 -0
- data/lib/garcon/chef/provider/development.rb +159 -0
- data/lib/garcon/chef/provider/download.rb +420 -0
- data/lib/garcon/chef/provider/house_keeping.rb +265 -0
- data/lib/garcon/chef/provider/node_cache.rb +31 -0
- data/lib/garcon/chef/provider/partial.rb +183 -0
- data/lib/garcon/chef/provider/recovery.rb +80 -0
- data/lib/garcon/chef/provider/zip_file.rb +271 -0
- data/lib/garcon/chef/resource/attribute.rb +52 -0
- data/lib/garcon/chef/resource/base_dsl.rb +174 -0
- data/lib/garcon/chef/resource/blender.rb +140 -0
- data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
- data/lib/garcon/chef/resource/resource_name.rb +109 -0
- data/lib/garcon/chef/secret_bag.rb +204 -0
- data/lib/garcon/chef/validations.rb +76 -0
- data/lib/garcon/chef_inclusions.rb +151 -0
- data/lib/garcon/configuration.rb +138 -0
- data/lib/garcon/core_ext.rb +39 -0
- data/lib/garcon/core_ext/array.rb +27 -0
- data/lib/garcon/core_ext/binding.rb +64 -0
- data/lib/garcon/core_ext/boolean.rb +66 -0
- data/lib/garcon/core_ext/duration.rb +271 -0
- data/lib/garcon/core_ext/enumerable.rb +34 -0
- data/lib/garcon/core_ext/file.rb +127 -0
- data/lib/garcon/core_ext/filetest.rb +62 -0
- data/lib/garcon/core_ext/hash.rb +279 -0
- data/lib/garcon/core_ext/kernel.rb +159 -0
- data/lib/garcon/core_ext/lazy.rb +222 -0
- data/lib/garcon/core_ext/method_access.rb +243 -0
- data/lib/garcon/core_ext/module.rb +92 -0
- data/lib/garcon/core_ext/nil.rb +53 -0
- data/lib/garcon/core_ext/numeric.rb +44 -0
- data/lib/garcon/core_ext/object.rb +342 -0
- data/lib/garcon/core_ext/pathname.rb +152 -0
- data/lib/garcon/core_ext/process.rb +41 -0
- data/lib/garcon/core_ext/random.rb +497 -0
- data/lib/garcon/core_ext/string.rb +312 -0
- data/lib/garcon/core_ext/struct.rb +49 -0
- data/lib/garcon/core_ext/symbol.rb +170 -0
- data/lib/garcon/core_ext/time.rb +234 -0
- data/lib/garcon/exceptions.rb +101 -0
- data/lib/garcon/inflections.rb +237 -0
- data/lib/garcon/inflections/defaults.rb +79 -0
- data/lib/garcon/inflections/inflections.rb +182 -0
- data/lib/garcon/inflections/rules_collection.rb +37 -0
- data/lib/garcon/secret.rb +271 -0
- data/lib/garcon/stash/format.rb +114 -0
- data/lib/garcon/stash/journal.rb +226 -0
- data/lib/garcon/stash/queue.rb +83 -0
- data/lib/garcon/stash/serializer.rb +86 -0
- data/lib/garcon/stash/store.rb +435 -0
- data/lib/garcon/task.rb +31 -0
- data/lib/garcon/task/atomic.rb +151 -0
- data/lib/garcon/task/atomic_boolean.rb +127 -0
- data/lib/garcon/task/condition.rb +99 -0
- data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
- data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
- data/lib/garcon/task/count_down_latch.rb +92 -0
- data/lib/garcon/task/delay.rb +196 -0
- data/lib/garcon/task/dereferenceable.rb +144 -0
- data/lib/garcon/task/event.rb +119 -0
- data/lib/garcon/task/executor.rb +275 -0
- data/lib/garcon/task/executor_options.rb +59 -0
- data/lib/garcon/task/future.rb +107 -0
- data/lib/garcon/task/immediate_executor.rb +84 -0
- data/lib/garcon/task/ivar.rb +171 -0
- data/lib/garcon/task/lazy_reference.rb +74 -0
- data/lib/garcon/task/monotonic_time.rb +69 -0
- data/lib/garcon/task/obligation.rb +256 -0
- data/lib/garcon/task/observable.rb +101 -0
- data/lib/garcon/task/priority_queue.rb +234 -0
- data/lib/garcon/task/processor_count.rb +128 -0
- data/lib/garcon/task/read_write_lock.rb +304 -0
- data/lib/garcon/task/safe_task_executor.rb +58 -0
- data/lib/garcon/task/single_thread_executor.rb +97 -0
- data/lib/garcon/task/thread_pool/cached.rb +71 -0
- data/lib/garcon/task/thread_pool/executor.rb +294 -0
- data/lib/garcon/task/thread_pool/fixed.rb +61 -0
- data/lib/garcon/task/thread_pool/worker.rb +90 -0
- data/lib/garcon/task/timer.rb +44 -0
- data/lib/garcon/task/timer_set.rb +194 -0
- data/lib/garcon/task/timer_task.rb +377 -0
- data/lib/garcon/task/waitable_list.rb +58 -0
- data/lib/garcon/utility/ansi.rb +199 -0
- data/lib/garcon/utility/at_random.rb +77 -0
- data/lib/garcon/utility/crypto.rb +292 -0
- data/lib/garcon/utility/equalizer.rb +146 -0
- data/lib/garcon/utility/faker/extensions/array.rb +22 -0
- data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
- data/lib/garcon/utility/faker/faker.rb +164 -0
- data/lib/garcon/utility/faker/faker/company.rb +17 -0
- data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
- data/lib/garcon/utility/faker/faker/version.rb +3 -0
- data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
- data/lib/garcon/utility/faker/locales/en.yml +21 -0
- data/lib/garcon/utility/file_helper.rb +170 -0
- data/lib/garcon/utility/hookers.rb +178 -0
- data/lib/garcon/utility/interpolation.rb +90 -0
- data/lib/garcon/utility/memstash.rb +364 -0
- data/lib/garcon/utility/misc.rb +54 -0
- data/lib/garcon/utility/msg_from_god.rb +62 -0
- data/lib/garcon/utility/retry.rb +238 -0
- data/lib/garcon/utility/timeout.rb +58 -0
- data/lib/garcon/utility/uber/builder.rb +91 -0
- data/lib/garcon/utility/uber/callable.rb +7 -0
- data/lib/garcon/utility/uber/delegates.rb +13 -0
- data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
- data/lib/garcon/utility/uber/options.rb +101 -0
- data/lib/garcon/utility/uber/uber_version.rb +3 -0
- data/lib/garcon/utility/uber/version.rb +33 -0
- data/lib/garcon/utility/url_helper.rb +100 -0
- data/lib/garcon/utils.rb +29 -0
- data/lib/garcon/version.rb +62 -0
- data/lib/garcun.rb +24 -0
- metadata +680 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
require 'chef/provider'
|
|
21
|
+
|
|
22
|
+
module Garcon
|
|
23
|
+
module Resource
|
|
24
|
+
# Combine a resource and provider class for quick and easy oven baked
|
|
25
|
+
# goodness. Never has cooking been this fun since the invention of the
|
|
26
|
+
# grocery store!
|
|
27
|
+
#
|
|
28
|
+
# @example
|
|
29
|
+
# class Chef::Resource::HouseKeeping < Chef::Resource
|
|
30
|
+
# include Garcon(blender: true)
|
|
31
|
+
#
|
|
32
|
+
# attribute :path,
|
|
33
|
+
# kind_of: String,
|
|
34
|
+
# name_attribute: true
|
|
35
|
+
# attribute :message,
|
|
36
|
+
# kind_of: String,
|
|
37
|
+
# default: 'Clean the kitchen'
|
|
38
|
+
#
|
|
39
|
+
# action :run do
|
|
40
|
+
# file new_resource.path do
|
|
41
|
+
# content new_resource.message
|
|
42
|
+
# end
|
|
43
|
+
# end
|
|
44
|
+
# end
|
|
45
|
+
#
|
|
46
|
+
module Blender
|
|
47
|
+
# Coerce is_a? so that the DSL will consider this a Provider for the
|
|
48
|
+
# purposes of attaching enclosing_provider.
|
|
49
|
+
#
|
|
50
|
+
# @param klass [Class]
|
|
51
|
+
#
|
|
52
|
+
# @return [Boolean]
|
|
53
|
+
#
|
|
54
|
+
# @api private
|
|
55
|
+
def is_a?(klass)
|
|
56
|
+
klass == Chef::Provider ? true : super
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Coerce provider_for_action so that the resource is also the provider.
|
|
60
|
+
#
|
|
61
|
+
# @param action [Symbol]
|
|
62
|
+
#
|
|
63
|
+
# @return [Chef::Provider]
|
|
64
|
+
#
|
|
65
|
+
# @api private
|
|
66
|
+
def provider_for_action(action)
|
|
67
|
+
provider(self.class.blender_provider_class) unless provider
|
|
68
|
+
super
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
module ClassMethods
|
|
72
|
+
# Define a provider action. The block should contain the usual provider
|
|
73
|
+
# code.
|
|
74
|
+
#
|
|
75
|
+
# @param name [Symbol]
|
|
76
|
+
# Name of the action.
|
|
77
|
+
#
|
|
78
|
+
# @param block [Proc]
|
|
79
|
+
# Action implementation.
|
|
80
|
+
#
|
|
81
|
+
def action(name, &block)
|
|
82
|
+
blender_actions[name.to_sym] = block
|
|
83
|
+
actions(name.to_sym) if respond_to?(:actions)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Storage accessor for blended action blocks. Maps action name to proc.
|
|
87
|
+
#
|
|
88
|
+
# @return [Hash<Symbol, Proc>]
|
|
89
|
+
#
|
|
90
|
+
# @api private
|
|
91
|
+
def blender_actions
|
|
92
|
+
(@blender_actions ||= {})
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Create a provider class for the blender actions in this resource.
|
|
96
|
+
# Inherits from the blender provider class of the resource's
|
|
97
|
+
# superclass if present.
|
|
98
|
+
#
|
|
99
|
+
# @return [Class]
|
|
100
|
+
#
|
|
101
|
+
# @api private
|
|
102
|
+
def blender_provider_class
|
|
103
|
+
@blender_provider_class ||= begin
|
|
104
|
+
provider_superclass = begin
|
|
105
|
+
self.superclass.blender_provider_class
|
|
106
|
+
rescue NoMethodError
|
|
107
|
+
Chef::Provider
|
|
108
|
+
end
|
|
109
|
+
actions = blender_actions
|
|
110
|
+
class_name = self.name
|
|
111
|
+
Class.new(provider_superclass) do
|
|
112
|
+
include Garcon
|
|
113
|
+
define_singleton_method(:name) { class_name + ' (blender)' }
|
|
114
|
+
actions.each do |action, block|
|
|
115
|
+
define_method(:"action_#{action}", &block)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Hook called when module is included, extends a descendant with class
|
|
122
|
+
# and instance methods.
|
|
123
|
+
#
|
|
124
|
+
# @param [Module] descendant
|
|
125
|
+
# The module or class including Garcon::Resource::Blender
|
|
126
|
+
#
|
|
127
|
+
# @return [self]
|
|
128
|
+
#
|
|
129
|
+
# @api private
|
|
130
|
+
def included(descendant)
|
|
131
|
+
super
|
|
132
|
+
descendant.extend ClassMethods
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
extend ClassMethods
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module Garcon
|
|
21
|
+
module Resource
|
|
22
|
+
# Resource mixin to allow lazyily-evaluated defaults in resource attributes.
|
|
23
|
+
#
|
|
24
|
+
module LazyEval
|
|
25
|
+
module ClassMethods
|
|
26
|
+
# Create a lazyily-evaluated block.
|
|
27
|
+
#
|
|
28
|
+
# @param [Proc] block
|
|
29
|
+
# Callable to return the default value.
|
|
30
|
+
#
|
|
31
|
+
# @return [Chef::DelayedEvaluator]
|
|
32
|
+
#
|
|
33
|
+
def lazy(&block)
|
|
34
|
+
Chef::DelayedEvaluator.new(&block)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Hook called when module is included, extends a descendant with class
|
|
38
|
+
# and instance methods.
|
|
39
|
+
#
|
|
40
|
+
# @param [Module] descendant
|
|
41
|
+
# the module or class including Garcon::Resource::LazyEval
|
|
42
|
+
#
|
|
43
|
+
# @return [self]
|
|
44
|
+
#
|
|
45
|
+
def included(descendant)
|
|
46
|
+
super
|
|
47
|
+
descendant.extend ClassMethods
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
extend ClassMethods
|
|
52
|
+
|
|
53
|
+
# Override the default set_or_return to support lazy evaluation of the
|
|
54
|
+
# default value. This only actually matters when it is called from a class
|
|
55
|
+
# level context via #attributes.
|
|
56
|
+
#
|
|
57
|
+
def set_or_return(symbol, arg, validation)
|
|
58
|
+
if validation && validation[:default].is_a?(Chef::DelayedEvaluator)
|
|
59
|
+
validation = validation.dup
|
|
60
|
+
validation[:default] = instance_eval(&validation[:default])
|
|
61
|
+
end
|
|
62
|
+
super(symbol, arg, validation)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module Garcon
|
|
21
|
+
module Resource
|
|
22
|
+
# Helper module to automatically set @resource_name.
|
|
23
|
+
#
|
|
24
|
+
# @example
|
|
25
|
+
# class MyResource < Chef::Resource
|
|
26
|
+
# include Garcon
|
|
27
|
+
#
|
|
28
|
+
# provides :my_resource
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
module ResourceName
|
|
32
|
+
# Constructor for Chef::Resource::MyResource.
|
|
33
|
+
#
|
|
34
|
+
def initialize(*args)
|
|
35
|
+
super
|
|
36
|
+
if self.class.resource_name(false)
|
|
37
|
+
@resource_name = self.class.resource_name
|
|
38
|
+
else
|
|
39
|
+
@resource_name ||= self.class.resource_name
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module ClassMethods
|
|
44
|
+
# Maps a resource/provider (and optionally a platform and version) to a
|
|
45
|
+
# Chef resource/provider. This allows finer grained per platform
|
|
46
|
+
# resource attributes and the end of overloaded resource definitions.
|
|
47
|
+
#
|
|
48
|
+
# @note
|
|
49
|
+
# The provides method must be defined in both the custom resource and
|
|
50
|
+
# custom provider files and both files must have identical provides
|
|
51
|
+
# statement(s).
|
|
52
|
+
#
|
|
53
|
+
# @param [Symbol] name
|
|
54
|
+
# Name of a Chef resource/provider to map to.
|
|
55
|
+
#
|
|
56
|
+
# @return [undefined]
|
|
57
|
+
#
|
|
58
|
+
def provides(name)
|
|
59
|
+
if self.name && respond_to?(:constantize)
|
|
60
|
+
old_constantize = instance_method(:constantize)
|
|
61
|
+
define_singleton_method(:constantize) do |name|
|
|
62
|
+
name == self.name ? self : old_constantize.bind(self).call(name)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
@provides_name = name
|
|
66
|
+
super if defined?(super)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Return the Snake case name of the current resource class. If not set
|
|
70
|
+
# explicitly it will be introspected based on the class name.
|
|
71
|
+
#
|
|
72
|
+
# @param [Boolean] auto
|
|
73
|
+
# Try to auto-detect based on class name.
|
|
74
|
+
#
|
|
75
|
+
# @return [Symbol]
|
|
76
|
+
#
|
|
77
|
+
def resource_name(auto = true)
|
|
78
|
+
return @provides_name if @provides_name
|
|
79
|
+
@provides_name || if name && name.start_with?('Chef::Resource')
|
|
80
|
+
Garcon::Inflections.snakeify(name, 'Chef::Resource').to_sym
|
|
81
|
+
elsif name
|
|
82
|
+
Garcon::Inflections.snakeify(name.split('::').last).to_sym
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Used by Resource#to_text to find the human name for the resource.
|
|
87
|
+
#
|
|
88
|
+
def dsl_name
|
|
89
|
+
resource_name.to_s
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Hook called when module is included, extends a descendant with class
|
|
93
|
+
# and instance methods.
|
|
94
|
+
#
|
|
95
|
+
# @param [Module] descendant
|
|
96
|
+
# the module or class including Garcon::Resource::ResourceName
|
|
97
|
+
#
|
|
98
|
+
# @return [self]
|
|
99
|
+
#
|
|
100
|
+
def included(descendant)
|
|
101
|
+
super
|
|
102
|
+
descendant.extend ClassMethods
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
extend ClassMethods
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module Garcon
|
|
21
|
+
# Library routine that returns an encrypted data bag value for a supplied
|
|
22
|
+
# string. The key used in decrypting the encrypted value should be located
|
|
23
|
+
# at node[:garcon][:secret][:key_path].
|
|
24
|
+
#
|
|
25
|
+
# Note that if node[:garcon][:devmode] is true, then the value of the index
|
|
26
|
+
# parameter is just returned as-is. This means that in developer mode, if a
|
|
27
|
+
# cookbook does this:
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# class Chef
|
|
31
|
+
# class Recipe
|
|
32
|
+
# include Garcon::SecretBag
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# admin = secret('bag_name', 'RoG+3xqKE23uc')
|
|
37
|
+
#
|
|
38
|
+
# That means admin will be 'RoG+3xqKE23uc'
|
|
39
|
+
#
|
|
40
|
+
# You also can provide a default password value in developer mode, like:
|
|
41
|
+
#
|
|
42
|
+
# node.set[:garcon][:secret][:passwd] = 'mysql_passwd'
|
|
43
|
+
# mysql_passwd = secret('passwords', 'eazypass')
|
|
44
|
+
#
|
|
45
|
+
# The mysql_passwd will == 'eazypass'
|
|
46
|
+
#
|
|
47
|
+
module SecretBag
|
|
48
|
+
include Garcon::Exceptions
|
|
49
|
+
|
|
50
|
+
def secret(bag_name, index)
|
|
51
|
+
if node[:garcon][:devmode]
|
|
52
|
+
dev_secret(index)
|
|
53
|
+
else
|
|
54
|
+
case node[:garcon][:databag_type]
|
|
55
|
+
when :encrypted
|
|
56
|
+
encrypted_secret(bag_name, index)
|
|
57
|
+
when :standard
|
|
58
|
+
standard_secret(bag_name, index)
|
|
59
|
+
when :vault
|
|
60
|
+
vault_secret('vault_' + bag_name, index)
|
|
61
|
+
else
|
|
62
|
+
raise InvalidDataBagType
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def encrypted_secret(bag_name, index)
|
|
68
|
+
key_path = node[:garcon][:secret][:key_path]
|
|
69
|
+
Chef::Log.info "Loading encrypted databag #{bag_name}.#{index} " \
|
|
70
|
+
"using key at #{key_path}"
|
|
71
|
+
secret = Chef::EncryptedDataBagItem.load_secret key_path
|
|
72
|
+
Chef::EncryptedDataBagItem.load(bag_name, index, secret)[index]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def standard_secret(bag_name, index)
|
|
76
|
+
Chef::Log.info "Loading databag #{bag_name}.#{index}"
|
|
77
|
+
Chef::DataBagItem.load(bag_name, index)[index]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def vault_secret(bag_name, index)
|
|
81
|
+
begin
|
|
82
|
+
require 'chef-vault'
|
|
83
|
+
rescue LoadError
|
|
84
|
+
Chef::Log.warn "Missing gem 'chef-vault'"
|
|
85
|
+
end
|
|
86
|
+
Chef::Log.info "Loading vault secret #{index} from #{bag_name}"
|
|
87
|
+
ChefVault::Item.load(bag_name, index)[index]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Return a password using either data bags or attributes for storage.
|
|
91
|
+
# The storage mechanism used is determined by the
|
|
92
|
+
# `node[:garcon][:use_databags]` attribute.
|
|
93
|
+
#
|
|
94
|
+
# @param [String] type
|
|
95
|
+
# password type, can be `:user`, `:service`, `:db` or `:token`
|
|
96
|
+
#
|
|
97
|
+
# @param [String] keys
|
|
98
|
+
# the identifier of the password
|
|
99
|
+
#
|
|
100
|
+
def get_password(type, key)
|
|
101
|
+
unless [:db, :user, :service, :token].include?(type)
|
|
102
|
+
Chef::Log.error "Unsupported type for get_password: #{type}"
|
|
103
|
+
return
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
if node[:garcon][:use_databags]
|
|
107
|
+
if type == :token
|
|
108
|
+
secret node[:garcon][:secret][:secrets_data_bag], key
|
|
109
|
+
else
|
|
110
|
+
secret node[:garcon][:secret]["#{type}_passwords_data_bag"], key
|
|
111
|
+
end
|
|
112
|
+
else
|
|
113
|
+
node[:garcon][:secret][key][type]
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Loads the encrypted data bag item and returns credentials for the
|
|
118
|
+
# environment or for a default key.
|
|
119
|
+
#
|
|
120
|
+
# @param [String] environment
|
|
121
|
+
# The environment
|
|
122
|
+
#
|
|
123
|
+
# @param [String] source
|
|
124
|
+
# The deployment source to load configuration for
|
|
125
|
+
#
|
|
126
|
+
# @return [Chef::DataBagItem]
|
|
127
|
+
# The data bag item
|
|
128
|
+
#
|
|
129
|
+
def data_bag_config_for(environment, source)
|
|
130
|
+
data_bag_item = encrypted_data_bag_for(environment, DATA_BAG)
|
|
131
|
+
|
|
132
|
+
if data_bag_item.has_key?(source)
|
|
133
|
+
data_bag_item[source]
|
|
134
|
+
elsif DATA_BAG == source
|
|
135
|
+
data_bag_item
|
|
136
|
+
else
|
|
137
|
+
{}
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Looks for the given data bag in the cache and if not found, will load a
|
|
142
|
+
# data bag item named for the chef_environment, or '_wildcard' value.
|
|
143
|
+
#
|
|
144
|
+
# @param [String] environment
|
|
145
|
+
# The environment.
|
|
146
|
+
#
|
|
147
|
+
# @param [String] data_bag
|
|
148
|
+
# The data bag to load.
|
|
149
|
+
#
|
|
150
|
+
# @return [Chef::Mash]
|
|
151
|
+
# The data bag item in Mash form.
|
|
152
|
+
#
|
|
153
|
+
def encrypted_data_bag_for(environment, data_bag)
|
|
154
|
+
@encrypted_data_bags = {} unless @encrypted_data_bags
|
|
155
|
+
|
|
156
|
+
if encrypted_data_bags[data_bag]
|
|
157
|
+
return get_from_data_bags_cache(data_bag)
|
|
158
|
+
else
|
|
159
|
+
data_bag_item = encrypted_data_bag_item(data_bag, environment)
|
|
160
|
+
data_bag_item ||= encrypted_data_bag_item(data_bag, WILDCARD)
|
|
161
|
+
data_bag_item ||= {}
|
|
162
|
+
@encrypted_data_bags[data_bag] = data_bag_item
|
|
163
|
+
return data_bag_item
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# @return [Hash]
|
|
168
|
+
def encrypted_data_bags
|
|
169
|
+
@encrypted_data_bags
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Loads an entry from the encrypted_data_bags class variable.
|
|
173
|
+
#
|
|
174
|
+
# @param [String] dbag
|
|
175
|
+
# The data bag to find.
|
|
176
|
+
#
|
|
177
|
+
# @return [type] [description]
|
|
178
|
+
#
|
|
179
|
+
def get_from_data_bags_cache(data_bag)
|
|
180
|
+
encrypted_data_bags[data_bag]
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Loads an EncryptedDataBagItem from the Chef server and
|
|
184
|
+
# turns it into a Chef::Mash, giving it indifferent access. Returns
|
|
185
|
+
# nil when a data bag item is not found.
|
|
186
|
+
#
|
|
187
|
+
# @param [String] dbag
|
|
188
|
+
# @param [String] dbag_item
|
|
189
|
+
#
|
|
190
|
+
# @raise [Chef::Garcon::DataBagEncryptionError]
|
|
191
|
+
# When the data bag cannot be decrypted or transformed into a Mash for
|
|
192
|
+
# some reason.
|
|
193
|
+
#
|
|
194
|
+
# @return [Chef::Mash]
|
|
195
|
+
#
|
|
196
|
+
def encrypted_data_bag_item(dbag, dbag_item)
|
|
197
|
+
Mash.from_hash(Chef::EncryptedDataBagItem.load(dbag, dbag_item).to_hash)
|
|
198
|
+
rescue Net::HTTPServerException
|
|
199
|
+
nil
|
|
200
|
+
rescue NoMethodError
|
|
201
|
+
raise DataBagEncryptionError.new
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|