chef-sugar 1.1.0 → 1.2.0.beta.1

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/LICENSE +1 -1
  4. data/README.md +91 -1
  5. data/Rakefile +6 -0
  6. data/chef-extensions.gemspec +3 -6
  7. data/lib/chef/sugar.rb +5 -1
  8. data/lib/chef/sugar/architecture.rb +1 -1
  9. data/lib/chef/sugar/cloud.rb +1 -1
  10. data/lib/chef/sugar/constraints.rb +161 -0
  11. data/lib/chef/sugar/core_extensions.rb +18 -0
  12. data/lib/chef/sugar/core_extensions/array.rb +34 -0
  13. data/lib/chef/sugar/core_extensions/string.rb +49 -0
  14. data/lib/chef/sugar/data_bag.rb +34 -9
  15. data/lib/chef/sugar/ip.rb +1 -1
  16. data/lib/chef/sugar/kernel.rb +49 -0
  17. data/lib/chef/sugar/node.rb +157 -1
  18. data/lib/chef/sugar/platform.rb +1 -1
  19. data/lib/chef/sugar/platform_family.rb +1 -1
  20. data/lib/chef/sugar/ruby.rb +1 -1
  21. data/lib/chef/sugar/shell.rb +1 -1
  22. data/lib/chef/sugar/vagrant.rb +1 -1
  23. data/lib/chef/sugar/version.rb +2 -2
  24. data/metadata.rb +1 -1
  25. data/recipes/default.rb +2 -2
  26. data/spec/spec_helper.rb +3 -0
  27. data/spec/support/shared_examples.rb +1 -1
  28. data/spec/unit/chef/{extensions → sugar}/architecture_spec.rb +0 -0
  29. data/spec/unit/chef/{extensions → sugar}/cloud_spec.rb +0 -0
  30. data/spec/unit/chef/sugar/constraints_spec.rb +43 -0
  31. data/spec/unit/chef/sugar/core_extensions/array_spec.rb +10 -0
  32. data/spec/unit/chef/sugar/core_extensions/string_spec.rb +16 -0
  33. data/spec/unit/chef/{extensions → sugar}/data_bag_spec.rb +23 -4
  34. data/spec/unit/chef/{extensions → sugar}/ip_spec.rb +0 -0
  35. data/spec/unit/chef/sugar/kernel_spec.rb +16 -0
  36. data/spec/unit/chef/sugar/node_spec.rb +117 -0
  37. data/spec/unit/chef/{extensions → sugar}/platform_family_spec.rb +0 -0
  38. data/spec/unit/chef/{extensions → sugar}/platform_spec.rb +0 -0
  39. data/spec/unit/chef/{extensions → sugar}/ruby_spec.rb +0 -0
  40. data/spec/unit/chef/{extensions → sugar}/shell_spec.rb +0 -0
  41. data/spec/unit/chef/{extensions → sugar}/vagrant_spec.rb +0 -0
  42. metadata +45 -61
  43. data/.kitchen.yml +0 -16
  44. data/recipes/development.rb +0 -65
  45. data/spec/unit/chef/extensions/node_spec.rb +0 -30
@@ -0,0 +1,49 @@
1
+ #
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ # require_relative '../constraints'
18
+
19
+ class String
20
+ #
21
+ # Treat strings as version objects.
22
+ #
23
+ # @see Chef::Sugar::Constraints::Version
24
+ #
25
+ # @example Using pure string objects like versions
26
+ # '1.2.3'.satisfies?('~> 1.2.0')
27
+ #
28
+ # @param [String, Array<String>] constraints
29
+ # the list of constraints to satisfy
30
+ #
31
+ def satisfies?(*constraints)
32
+ Chef::Sugar::Constraints::Version.new(dup).satisfies?(*constraints)
33
+ end
34
+
35
+ #
36
+ # Treat strings as version constraints.
37
+ #
38
+ # @see Chef::Sugar::Constraints::Constraint
39
+ #
40
+ # @example Using pure string objects like constraints
41
+ # '~> 1.2.0'.satisfied_by?('1.2.3')
42
+ #
43
+ # @param [String] version
44
+ # the version to check if it is satisfied
45
+ #
46
+ def satisfied_by?(version)
47
+ Chef::Sugar::Constraints::Constraint.new(dup).satisfied_by?(version)
48
+ end
49
+ end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -17,6 +17,20 @@
17
17
  class Chef
18
18
  module Sugar
19
19
  module DataBag
20
+ class EncryptedDataBagSecretNotGiven < StandardError
21
+ def initialize
22
+ super <<-EOH
23
+ You did not set your `encrypted_data_bag_secret'! In order to use the
24
+ `encrypted_data_bag_item' helper, you must load your encrypted data bag secret
25
+ into the `Chef::Config'.
26
+
27
+ Alternatively, you can pass the secret key as the last parameter to the method
28
+ call. For more information, please see
29
+ http://docs.opscode.com/chef/essentials_data_bags.html#access-from-recipe.
30
+ EOH
31
+ end
32
+ end
33
+
20
34
  extend self
21
35
 
22
36
  #
@@ -27,12 +41,21 @@ class Chef
27
41
  # the name of the encrypted data bag
28
42
  # @param [String] id
29
43
  # the id of the encrypted data bag
44
+ # @param [String] secret
45
+ # the encrypted data bag secret (default's to the +Chef::Config+ value)
30
46
  #
31
47
  # @return [Hash]
32
48
  #
33
- def encrypted_data_bag_item(bag, id)
49
+ def encrypted_data_bag_item(bag, id, secret = nil)
34
50
  Chef::Log.debug "Loading encrypted data bag item #{bag}/#{id}"
35
- Chef::EncryptedDataBagItem.load(bag, id)
51
+
52
+ secret ||= Chef::Config[:encrypted_data_bag_secret]
53
+
54
+ if secret
55
+ Chef::EncryptedDataBagItem.load(bag, id, secret)
56
+ else
57
+ raise EncryptedDataBagSecretNotGiven.new
58
+ end
36
59
  end
37
60
 
38
61
  #
@@ -53,11 +76,13 @@ class Chef
53
76
  # the name of the encrypted data bag
54
77
  # @param [String] id
55
78
  # the id of the encrypted data bag
79
+ # @param [String] secret
80
+ # the encrypted data bag secret (default's to the +Chef::Config+ value)
56
81
  #
57
82
  # @return [Hash]
58
83
  #
59
- def encrypted_data_bag_item_for_environment(node, bag, id)
60
- data = encrypted_data_bag_item(bag, id)
84
+ def encrypted_data_bag_item_for_environment(node, bag, id, secret = nil)
85
+ data = encrypted_data_bag_item(bag, id, secret)
61
86
 
62
87
  if data[node.chef_environment]
63
88
  Chef::Log.debug "Using #{node.chef_environment} as the key"
@@ -71,13 +96,13 @@ class Chef
71
96
 
72
97
  module DSL
73
98
  # @see Chef::Sugar::DataBag#encrypted_data_bag_item?
74
- def encrypted_data_bag_item(bag, id)
75
- Chef::Sugar::DataBag.encrypted_data_bag_item(bag, id)
99
+ def encrypted_data_bag_item(bag, id, secret = nil)
100
+ Chef::Sugar::DataBag.encrypted_data_bag_item(bag, id, secret)
76
101
  end
77
102
 
78
103
  # @see Chef::Sugar::DataBag#encrypted_data_bag_item_for_environment?
79
- def encrypted_data_bag_item_for_environment(bag, id)
80
- Chef::Sugar::DataBag.encrypted_data_bag_item_for_environment(node, bag, id)
104
+ def encrypted_data_bag_item_for_environment(bag, id, secret = nil)
105
+ Chef::Sugar::DataBag.encrypted_data_bag_item_for_environment(node, bag, id, secret)
81
106
  end
82
107
  end
83
108
  end
data/lib/chef/sugar/ip.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,49 @@
1
+ #
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ class Chef
18
+ module Sugar
19
+ module Kernel
20
+ class ChefGemLoadError < StandardError
21
+ def initialize(name)
22
+ super <<-EOH
23
+ Chef could not load the gem `#{name}'! You may need to install the gem manually
24
+ with `gem install #{name}', or include a recipe before you can use this
25
+ resource. Please consult the documentation for this cookbook for proper usage.
26
+ EOH
27
+ end
28
+ end
29
+
30
+ #
31
+ # Require a gem that should have been installed by Chef, such as in a
32
+ # recipes as a +chef_gem+. This method will gracefully degrade if the
33
+ # gem cannot be loaded.
34
+ #
35
+ # @param [String] name
36
+ # the name of the gem to install
37
+ #
38
+ # @return [Boolean]
39
+ # true if the require is successful and false if the gem is already
40
+ # loaded
41
+ #
42
+ def require_chef_gem(name)
43
+ require(name)
44
+ rescue LoadError
45
+ raise ChefGemLoadError.new(name)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -16,6 +16,16 @@
16
16
 
17
17
  class Chef
18
18
  class Node
19
+ class AttributeDoesNotExistError < StandardError
20
+ def initialize(keys)
21
+ hash = keys.map { |key| "['#{key}']" }
22
+
23
+ super <<-EOH
24
+ No attribute `node#{hash.join}' exists on
25
+ the current node. Please make sure you have spelled everything correctly.
26
+ EOH
27
+ end
28
+ end
19
29
  #
20
30
  # Determine if the current node is in the given Chef environment
21
31
  # (or matches the given regular expression).
@@ -37,5 +47,151 @@ class Chef
37
47
  run_list.include?(recipe_name)
38
48
  end
39
49
  alias_method :include_recipe?, :includes_recipe?
50
+
51
+ #
52
+ # Safely fetch a deeply nested attribute by specifying a list of keys,
53
+ # bypassing Ruby's Hash notation. This method swallows +NoMethodError+
54
+ # exceptions, avoiding the most common error in Chef-land.
55
+ #
56
+ # This method will return +nil+ if any deeply nested key does not exist.
57
+ #
58
+ # @see [Node#deep_fetch!]
59
+ #
60
+ def deep_fetch(*keys)
61
+ deep_fetch!(*keys)
62
+ rescue NoMethodError, AttributeDoesNotExistError
63
+ nil
64
+ end
65
+
66
+ #
67
+ # Deeply fetch a node attribute by specifying a list of keys, bypassing
68
+ # Ruby's Hash notation.
69
+ #
70
+ # This method will raise any exceptions, such as
71
+ # +undefined method `[]' for nil:NilClass+, just as if you used the native
72
+ # attribute notation. If you want a safely vivified hash, see {deep_fetch}.
73
+ #
74
+ # @example Fetch a deeply nested key
75
+ # node.deep_fetch(:foo, :bar, :zip) #=> node['foo']['bar']['zip']
76
+ #
77
+ # @param [Array<String, Symbol>] keys
78
+ # the list of keys to kdeep fetch
79
+ #
80
+ # @return [Object]
81
+ #
82
+ def deep_fetch!(*keys)
83
+ keys.map!(&:to_s)
84
+
85
+ keys.inject(attributes.to_hash) do |hash, key|
86
+ hash[key]
87
+ end
88
+ rescue NoMethodError
89
+ raise AttributeDoesNotExistError.new(keys)
90
+ end
91
+
92
+ #
93
+ # Dynamically define the current namespace. Multiple namespaces may be
94
+ # nested.
95
+ #
96
+ # @example Define a simple namespace
97
+ #
98
+ # namespace 'apache2' do
99
+ # # ...
100
+ # end
101
+ #
102
+ # @example Define a nested namespace
103
+ #
104
+ # namespace 'apache2', 'config' do
105
+ # # ...
106
+ # end
107
+ #
108
+ # @example Define a complex nested namespace
109
+ #
110
+ # namespace 'apache2' do
111
+ # namespace 'config' do
112
+ # # ...
113
+ # end
114
+ # end
115
+ #
116
+ # @example Define a namespace with a custom precedence level
117
+ #
118
+ # namespace 'apache2', precedence: normal do
119
+ # # Attributes here will use the "normal" level
120
+ # end
121
+ #
122
+ # @example Define different nested precedence levels
123
+ #
124
+ # namespace 'apache2', precedence: normal do
125
+ # # Attributes defined here will use the "normal" level
126
+ #
127
+ # namespace 'config', precedence: override do
128
+ # # Attributes defined here will use the "override" level
129
+ # end
130
+ # end
131
+ #
132
+ #
133
+ # @param [Array] args
134
+ # the list of arguments (such as the namespace and precedence levels)
135
+ # the user gave
136
+ # @param [Proc] block
137
+ # the nested evaluation context
138
+ #
139
+ # @return [nil]
140
+ # to prevent accidential method chaining if the block isn't closed
141
+ #
142
+ def namespace(*args, &block)
143
+ @namespace_options = {
144
+ precedence: default
145
+ }.merge(args.last.is_a?(Hash) ? args.pop : {})
146
+
147
+ keys = args.map(&:to_s)
148
+
149
+ @current_namespace = current_namespace + keys
150
+ instance_eval(&block)
151
+ @current_namespace = current_namespace - keys
152
+
153
+ nil
154
+ end
155
+
156
+ alias_method :old_method_missing, :method_missing
157
+ #
158
+ # Provide a nice DSL for defining attributes. +method_missing+ is called
159
+ # on all the attribute names. For more information on how to use the DSL,
160
+ # see the class-level documentation.
161
+ #
162
+ # @return [nil]
163
+ # to prevent accidential method chaining if the block isn't closed
164
+ #
165
+ def method_missing(m, *args, &block)
166
+ old_method_missing(m, *args, &block)
167
+ rescue NoMethodError
168
+ vivified[m.to_s] = args.size == 1 ? args.first : args
169
+ nil
170
+ end
171
+
172
+ private
173
+
174
+ #
175
+ # The current namespace. This is actually a reverse-ordered array that
176
+ # vivifies the correct hash.#
177
+ #
178
+ # @return [Array<String>]
179
+ #
180
+ def current_namespace
181
+ @current_namespace ||= []
182
+ end
183
+
184
+ #
185
+ # The vivified (fake-filled) hash. It is assumed that the default value
186
+ # for non-existent keys in the hash is a new, empty hash.
187
+ #
188
+ # @return [Hash<String, Hash>]
189
+ #
190
+ def vivified
191
+ current_namespace.inject(@namespace_options[:precedence]) do |hash, item|
192
+ hash[item] ||= {}
193
+ hash[item]
194
+ end
195
+ end
40
196
  end
41
197
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
2
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -16,6 +16,6 @@
16
16
 
17
17
  class Chef
18
18
  module Sugar
19
- VERSION = '1.1.0'
19
+ VERSION = '1.2.0.beta.1'
20
20
  end
21
21
  end
data/metadata.rb CHANGED
@@ -5,4 +5,4 @@ license 'Apache 2.0'
5
5
  description 'Installs chef-sugar. Please see the chef-sugar ' \
6
6
  'Ruby gem for more information.'
7
7
  long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
8
- version '1.0.1'
8
+ version '1.1.0'
data/recipes/default.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # Cookbook Name:: chef-sugar
3
3
  # Recipe:: default
4
4
  #
5
- # Copyright 2013, Seth Vargo <sethvargo@gmail.com>
5
+ # Copyright 2013-2014, Seth Vargo <sethvargo@gmail.com>
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
18
18
  #
19
19
 
20
20
  chef_gem('chef-sugar') do
21
- version '1.0.1'
21
+ version '1.2.0.beta.1'
22
22
  action :nothing
23
23
  end.run_action(:install)
24
24