chef-sugar 1.1.0 → 1.2.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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