garcun 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +17 -0
  3. data/.gitignore +197 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +22 -0
  6. data/LICENSE +201 -0
  7. data/README.md +521 -0
  8. data/Rakefile +47 -0
  9. data/garcun.gemspec +83 -0
  10. data/lib/garcon.rb +290 -0
  11. data/lib/garcon/chef/chef_helpers.rb +343 -0
  12. data/lib/garcon/chef/coerce/coercer.rb +134 -0
  13. data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
  14. data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
  15. data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
  16. data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
  17. data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
  18. data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
  19. data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
  20. data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
  21. data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
  22. data/lib/garcon/chef/handler/devreporter.rb +127 -0
  23. data/lib/garcon/chef/log.rb +64 -0
  24. data/lib/garcon/chef/node.rb +100 -0
  25. data/lib/garcon/chef/provider/civilize.rb +209 -0
  26. data/lib/garcon/chef/provider/development.rb +159 -0
  27. data/lib/garcon/chef/provider/download.rb +420 -0
  28. data/lib/garcon/chef/provider/house_keeping.rb +265 -0
  29. data/lib/garcon/chef/provider/node_cache.rb +31 -0
  30. data/lib/garcon/chef/provider/partial.rb +183 -0
  31. data/lib/garcon/chef/provider/recovery.rb +80 -0
  32. data/lib/garcon/chef/provider/zip_file.rb +271 -0
  33. data/lib/garcon/chef/resource/attribute.rb +52 -0
  34. data/lib/garcon/chef/resource/base_dsl.rb +174 -0
  35. data/lib/garcon/chef/resource/blender.rb +140 -0
  36. data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
  37. data/lib/garcon/chef/resource/resource_name.rb +109 -0
  38. data/lib/garcon/chef/secret_bag.rb +204 -0
  39. data/lib/garcon/chef/validations.rb +76 -0
  40. data/lib/garcon/chef_inclusions.rb +151 -0
  41. data/lib/garcon/configuration.rb +138 -0
  42. data/lib/garcon/core_ext.rb +39 -0
  43. data/lib/garcon/core_ext/array.rb +27 -0
  44. data/lib/garcon/core_ext/binding.rb +64 -0
  45. data/lib/garcon/core_ext/boolean.rb +66 -0
  46. data/lib/garcon/core_ext/duration.rb +271 -0
  47. data/lib/garcon/core_ext/enumerable.rb +34 -0
  48. data/lib/garcon/core_ext/file.rb +127 -0
  49. data/lib/garcon/core_ext/filetest.rb +62 -0
  50. data/lib/garcon/core_ext/hash.rb +279 -0
  51. data/lib/garcon/core_ext/kernel.rb +159 -0
  52. data/lib/garcon/core_ext/lazy.rb +222 -0
  53. data/lib/garcon/core_ext/method_access.rb +243 -0
  54. data/lib/garcon/core_ext/module.rb +92 -0
  55. data/lib/garcon/core_ext/nil.rb +53 -0
  56. data/lib/garcon/core_ext/numeric.rb +44 -0
  57. data/lib/garcon/core_ext/object.rb +342 -0
  58. data/lib/garcon/core_ext/pathname.rb +152 -0
  59. data/lib/garcon/core_ext/process.rb +41 -0
  60. data/lib/garcon/core_ext/random.rb +497 -0
  61. data/lib/garcon/core_ext/string.rb +312 -0
  62. data/lib/garcon/core_ext/struct.rb +49 -0
  63. data/lib/garcon/core_ext/symbol.rb +170 -0
  64. data/lib/garcon/core_ext/time.rb +234 -0
  65. data/lib/garcon/exceptions.rb +101 -0
  66. data/lib/garcon/inflections.rb +237 -0
  67. data/lib/garcon/inflections/defaults.rb +79 -0
  68. data/lib/garcon/inflections/inflections.rb +182 -0
  69. data/lib/garcon/inflections/rules_collection.rb +37 -0
  70. data/lib/garcon/secret.rb +271 -0
  71. data/lib/garcon/stash/format.rb +114 -0
  72. data/lib/garcon/stash/journal.rb +226 -0
  73. data/lib/garcon/stash/queue.rb +83 -0
  74. data/lib/garcon/stash/serializer.rb +86 -0
  75. data/lib/garcon/stash/store.rb +435 -0
  76. data/lib/garcon/task.rb +31 -0
  77. data/lib/garcon/task/atomic.rb +151 -0
  78. data/lib/garcon/task/atomic_boolean.rb +127 -0
  79. data/lib/garcon/task/condition.rb +99 -0
  80. data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
  81. data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
  82. data/lib/garcon/task/count_down_latch.rb +92 -0
  83. data/lib/garcon/task/delay.rb +196 -0
  84. data/lib/garcon/task/dereferenceable.rb +144 -0
  85. data/lib/garcon/task/event.rb +119 -0
  86. data/lib/garcon/task/executor.rb +275 -0
  87. data/lib/garcon/task/executor_options.rb +59 -0
  88. data/lib/garcon/task/future.rb +107 -0
  89. data/lib/garcon/task/immediate_executor.rb +84 -0
  90. data/lib/garcon/task/ivar.rb +171 -0
  91. data/lib/garcon/task/lazy_reference.rb +74 -0
  92. data/lib/garcon/task/monotonic_time.rb +69 -0
  93. data/lib/garcon/task/obligation.rb +256 -0
  94. data/lib/garcon/task/observable.rb +101 -0
  95. data/lib/garcon/task/priority_queue.rb +234 -0
  96. data/lib/garcon/task/processor_count.rb +128 -0
  97. data/lib/garcon/task/read_write_lock.rb +304 -0
  98. data/lib/garcon/task/safe_task_executor.rb +58 -0
  99. data/lib/garcon/task/single_thread_executor.rb +97 -0
  100. data/lib/garcon/task/thread_pool/cached.rb +71 -0
  101. data/lib/garcon/task/thread_pool/executor.rb +294 -0
  102. data/lib/garcon/task/thread_pool/fixed.rb +61 -0
  103. data/lib/garcon/task/thread_pool/worker.rb +90 -0
  104. data/lib/garcon/task/timer.rb +44 -0
  105. data/lib/garcon/task/timer_set.rb +194 -0
  106. data/lib/garcon/task/timer_task.rb +377 -0
  107. data/lib/garcon/task/waitable_list.rb +58 -0
  108. data/lib/garcon/utility/ansi.rb +199 -0
  109. data/lib/garcon/utility/at_random.rb +77 -0
  110. data/lib/garcon/utility/crypto.rb +292 -0
  111. data/lib/garcon/utility/equalizer.rb +146 -0
  112. data/lib/garcon/utility/faker/extensions/array.rb +22 -0
  113. data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
  114. data/lib/garcon/utility/faker/faker.rb +164 -0
  115. data/lib/garcon/utility/faker/faker/company.rb +17 -0
  116. data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
  117. data/lib/garcon/utility/faker/faker/version.rb +3 -0
  118. data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
  119. data/lib/garcon/utility/faker/locales/en.yml +21 -0
  120. data/lib/garcon/utility/file_helper.rb +170 -0
  121. data/lib/garcon/utility/hookers.rb +178 -0
  122. data/lib/garcon/utility/interpolation.rb +90 -0
  123. data/lib/garcon/utility/memstash.rb +364 -0
  124. data/lib/garcon/utility/misc.rb +54 -0
  125. data/lib/garcon/utility/msg_from_god.rb +62 -0
  126. data/lib/garcon/utility/retry.rb +238 -0
  127. data/lib/garcon/utility/timeout.rb +58 -0
  128. data/lib/garcon/utility/uber/builder.rb +91 -0
  129. data/lib/garcon/utility/uber/callable.rb +7 -0
  130. data/lib/garcon/utility/uber/delegates.rb +13 -0
  131. data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
  132. data/lib/garcon/utility/uber/options.rb +101 -0
  133. data/lib/garcon/utility/uber/uber_version.rb +3 -0
  134. data/lib/garcon/utility/uber/version.rb +33 -0
  135. data/lib/garcon/utility/url_helper.rb +100 -0
  136. data/lib/garcon/utils.rb +29 -0
  137. data/lib/garcon/version.rb +62 -0
  138. data/lib/garcun.rb +24 -0
  139. 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