ridley 0.10.2 → 0.11.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/README.md +147 -216
  2. data/lib/ridley.rb +2 -0
  3. data/lib/ridley/bootstrap_bindings/unix_template_binding.rb +21 -25
  4. data/lib/ridley/bootstrap_bindings/windows_template_binding.rb +29 -34
  5. data/lib/ridley/bootstrapper.rb +2 -2
  6. data/lib/ridley/bootstrapper/context.rb +5 -5
  7. data/lib/ridley/chef.rb +0 -1
  8. data/lib/ridley/chef/cookbook.rb +0 -9
  9. data/lib/ridley/chef_object.rb +128 -0
  10. data/lib/ridley/chef_objects.rb +3 -0
  11. data/lib/ridley/chef_objects/client_object.rb +55 -0
  12. data/lib/ridley/chef_objects/cookbook_object.rb +190 -0
  13. data/lib/ridley/chef_objects/data_bag_item_obect.rb +104 -0
  14. data/lib/ridley/chef_objects/data_bag_object.rb +31 -0
  15. data/lib/ridley/chef_objects/environment_object.rb +59 -0
  16. data/lib/ridley/chef_objects/node_object.rb +161 -0
  17. data/lib/ridley/chef_objects/role_object.rb +62 -0
  18. data/lib/ridley/chef_objects/sandbox_object.rb +58 -0
  19. data/lib/ridley/client.rb +76 -45
  20. data/lib/ridley/connection.rb +1 -1
  21. data/lib/ridley/errors.rb +8 -1
  22. data/lib/ridley/host_connector.rb +26 -6
  23. data/lib/ridley/host_connector/ssh.rb +3 -3
  24. data/lib/ridley/host_connector/ssh/worker.rb +7 -9
  25. data/lib/ridley/host_connector/winrm/worker.rb +4 -5
  26. data/lib/ridley/mixin/bootstrap_binding.rb +1 -12
  27. data/lib/ridley/resource.rb +51 -171
  28. data/lib/ridley/resources/client_resource.rb +18 -68
  29. data/lib/ridley/resources/cookbook_resource.rb +181 -381
  30. data/lib/ridley/resources/data_bag_item_resource.rb +55 -161
  31. data/lib/ridley/resources/data_bag_resource.rb +20 -61
  32. data/lib/ridley/resources/environment_resource.rb +9 -64
  33. data/lib/ridley/resources/node_resource.rb +135 -311
  34. data/lib/ridley/resources/role_resource.rb +1 -57
  35. data/lib/ridley/resources/sandbox_resource.rb +80 -65
  36. data/lib/ridley/resources/search_resource.rb +99 -0
  37. data/lib/ridley/sandbox_uploader.rb +12 -52
  38. data/lib/ridley/version.rb +1 -1
  39. data/spec/acceptance/bootstrapping_spec.rb +1 -1
  40. data/spec/acceptance/client_resource_spec.rb +15 -37
  41. data/spec/acceptance/data_bag_item_resource_spec.rb +8 -14
  42. data/spec/acceptance/data_bag_resource_spec.rb +1 -1
  43. data/spec/acceptance/environment_resource_spec.rb +13 -22
  44. data/spec/acceptance/node_resource_spec.rb +10 -29
  45. data/spec/acceptance/role_resource_spec.rb +14 -13
  46. data/spec/acceptance/sandbox_resource_spec.rb +2 -2
  47. data/spec/support/shared_examples/ridley_resource.rb +2 -23
  48. data/spec/unit/ridley/bootstrap_bindings/unix_template_binding_spec.rb +3 -4
  49. data/spec/unit/ridley/bootstrap_bindings/windows_template_binding_spec.rb +3 -5
  50. data/spec/unit/ridley/bootstrapper/context_spec.rb +2 -3
  51. data/spec/unit/ridley/bootstrapper_spec.rb +1 -1
  52. data/spec/unit/ridley/chef_object_spec.rb +240 -0
  53. data/spec/unit/ridley/chef_objects/client_object_spec.rb +11 -0
  54. data/spec/unit/ridley/chef_objects/cookbook_object_spec.rb +93 -0
  55. data/spec/unit/ridley/chef_objects/data_bag_item_object_spec.rb +74 -0
  56. data/spec/unit/ridley/chef_objects/data_bag_object_spec.rb +9 -0
  57. data/spec/unit/ridley/chef_objects/environment_object_spec.rb +57 -0
  58. data/spec/unit/ridley/chef_objects/node_object_spec.rb +252 -0
  59. data/spec/unit/ridley/chef_objects/role_object_spec.rb +57 -0
  60. data/spec/unit/ridley/chef_objects/sandbox_object_spec.rb +66 -0
  61. data/spec/unit/ridley/client_spec.rb +51 -51
  62. data/spec/unit/ridley/host_connector/ssh/worker_spec.rb +4 -4
  63. data/spec/unit/ridley/host_connector/ssh_spec.rb +26 -24
  64. data/spec/unit/ridley/host_connector/winrm/worker_spec.rb +3 -4
  65. data/spec/unit/ridley/host_connector/winrm_spec.rb +4 -4
  66. data/spec/unit/ridley/host_connector_spec.rb +40 -3
  67. data/spec/unit/ridley/mixin/bootstrap_binding_spec.rb +1 -1
  68. data/spec/unit/ridley/resource_spec.rb +81 -109
  69. data/spec/unit/ridley/resources/client_resource_spec.rb +18 -33
  70. data/spec/unit/ridley/resources/cookbook_resource_spec.rb +56 -230
  71. data/spec/unit/ridley/resources/data_bag_item_resource_spec.rb +2 -57
  72. data/spec/unit/ridley/resources/data_bag_resource_spec.rb +12 -7
  73. data/spec/unit/ridley/resources/environment_resource_spec.rb +10 -118
  74. data/spec/unit/ridley/resources/node_resource_spec.rb +83 -394
  75. data/spec/unit/ridley/resources/role_resource_spec.rb +2 -56
  76. data/spec/unit/ridley/resources/sandbox_resource_spec.rb +139 -136
  77. data/spec/unit/ridley/resources/search_resource_spec.rb +234 -0
  78. data/spec/unit/ridley/sandbox_uploader_spec.rb +13 -58
  79. metadata +36 -17
  80. data/lib/ridley/chef/chefignore.rb +0 -76
  81. data/lib/ridley/resources/encrypted_data_bag_item_resource.rb +0 -55
  82. data/lib/ridley/resources/search.rb +0 -101
  83. data/spec/fixtures/chefignore +0 -8
  84. data/spec/unit/ridley/chef/chefignore_spec.rb +0 -40
  85. data/spec/unit/ridley/resources/search_spec.rb +0 -221
@@ -1,63 +1,7 @@
1
1
  module Ridley
2
2
  # @author Jamie Winsor <reset@riotgames.com>
3
3
  class RoleResource < Ridley::Resource
4
- set_chef_id "name"
5
- set_chef_type "role"
6
- set_chef_json_class "Chef::Role"
7
4
  set_resource_path "roles"
8
-
9
- attribute :name,
10
- required: true
11
-
12
- attribute :description,
13
- default: String.new
14
-
15
- attribute :default_attributes,
16
- default: Hashie::Mash.new
17
-
18
- attribute :override_attributes,
19
- default: Hashie::Mash.new
20
-
21
- attribute :run_list,
22
- default: Array.new
23
-
24
- attribute :env_run_lists,
25
- default: Hash.new
26
-
27
- # Set a role level override attribute given the dotted path representation of the Chef
28
- # attribute and value
29
- #
30
- # @example setting and saving a node level override attribute
31
- #
32
- # obj = node.role("why_god_why")
33
- # obj.set_override_attribute("my_app.billing.enabled", false)
34
- # obj.save
35
- #
36
- # @param [String] key
37
- # @param [Object] value
38
- #
39
- # @return [HashWithIndifferentAccess]
40
- def set_override_attribute(key, value)
41
- attr_hash = HashWithIndifferentAccess.from_dotted_path(key, value)
42
- self.override_attributes = self.override_attributes.deep_merge(attr_hash)
43
- end
44
-
45
- # Set a role level default attribute given the dotted path representation of the Chef
46
- # attribute and value
47
- #
48
- # @example setting and saving a node level default attribute
49
- #
50
- # obj = node.role("why_god_why")
51
- # obj.set_default_attribute("my_app.billing.enabled", false)
52
- # obj.save
53
- #
54
- # @param [String] key
55
- # @param [Object] value
56
- #
57
- # @return [HashWithIndifferentAccess]
58
- def set_default_attribute(key, value)
59
- attr_hash = HashWithIndifferentAccess.from_dotted_path(key, value)
60
- self.default_attributes = self.default_attributes.deep_merge(attr_hash)
61
- end
5
+ represented_by Ridley::RoleObject
62
6
  end
63
7
  end
@@ -1,86 +1,101 @@
1
1
  module Ridley
2
2
  # @author Jamie Winsor <reset@riotgames.com>
3
- class SandboxResource
4
- class << self
5
- # Create a new Sandbox on the client's Chef Server. A Sandbox requires an
6
- # array of file checksums which lets the Chef Server know what the signature
7
- # of the contents to be uploaded will look like.
8
- #
9
- # @param [Ridley::Client] client
10
- # @param [Array] checksums
11
- # a hash of file checksums
12
- #
13
- # @example using the Ridley client to create a sandbox
14
- # client.sandbox.create([
15
- # "385ea5490c86570c7de71070bce9384a",
16
- # "f6f73175e979bd90af6184ec277f760c",
17
- # "2e03dd7e5b2e6c8eab1cf41ac61396d5"
18
- # ])
19
- #
20
- # @return [Array<Ridley::SandboxResource>]
21
- def create(client, checksums = [])
22
- sumhash = { checksums: Hash.new }.tap do |chks|
23
- Array(checksums).each { |chk| chks[:checksums][chk] = nil }
24
- end
3
+ class SandboxResource < Ridley::Resource
4
+ set_resource_path "sandboxes"
5
+ represented_by Ridley::SandboxObject
25
6
 
26
- new(client, client.connection.post("sandboxes", MultiJson.encode(sumhash)).body)
27
- end
7
+ finalizer do
8
+ uploader.terminate if uploader && uploader.alive?
28
9
  end
29
10
 
30
- include Chozo::VariaModel
31
-
32
- attribute :sandbox_id,
33
- type: String
34
-
35
- attribute :uri,
36
- type: String
37
-
38
- attribute :checksums,
39
- type: Hash
40
-
41
- attribute :is_completed,
42
- type: Boolean,
43
- default: false
44
-
45
- attr_reader :client
11
+ def initialize(connection_registry, client_name, client_key, options = {})
12
+ super(connection_registry)
13
+ options = options.reverse_merge(pool_size: 4)
14
+ @uploader = SandboxUploader.pool(size: options[:pool_size], args: [ client_name, client_key, options ])
15
+ end
46
16
 
17
+ # Create a new Sandbox on the client's Chef Server. A Sandbox requires an
18
+ # array of file checksums which lets the Chef Server know what the signature
19
+ # of the contents to be uploaded will look like.
20
+ #
47
21
  # @param [Ridley::Client] client
48
- # @param [Hash] new_attrs
49
- def initialize(client, new_attrs = {})
50
- @client = client
51
- mass_assign(new_attrs)
22
+ # @param [Array] checksums
23
+ # a hash of file checksums
24
+ #
25
+ # @example using the Ridley client to create a sandbox
26
+ # client.sandbox.create([
27
+ # "385ea5490c86570c7de71070bce9384a",
28
+ # "f6f73175e979bd90af6184ec277f760c",
29
+ # "2e03dd7e5b2e6c8eab1cf41ac61396d5"
30
+ # ])
31
+ #
32
+ # @return [Array<Ridley::SandboxResource>]
33
+ def create(checksums = [])
34
+ sumhash = { checksums: Hash.new }.tap do |chks|
35
+ Array(checksums).each { |chk| chks[:checksums][chk] = nil }
36
+ end
37
+ new(connection.post(self.class.resource_path, MultiJson.encode(sumhash)).body)
52
38
  end
53
39
 
54
- # Return information about the given checksum
55
- #
56
- # @example
57
- # sandbox.checksum("e5a0f6b48d0712382295ff30bec1f9cc") => {
58
- # needs_upload: true,
59
- # url: "https://s3.amazonaws.com/opscode-platform-production-data/organization"
60
- # }
40
+ # @param [#chef_id] object
61
41
  #
62
- # @param [#to_sym] chk_id
63
- # checksum to retrieve information about
42
+ # @raise [Ridley::Errors::SandboxCommitError]
43
+ # @raise [Ridley::Errors::ResourceNotFound]
44
+ # @raise [Ridley::Errors::PermissionDenied]
64
45
  #
65
46
  # @return [Hash]
66
- # a hash containing the checksum information
67
- def checksum(chk_id)
68
- checksums[chk_id.to_sym]
47
+ def commit(object)
48
+ chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
49
+ connection.put("#{self.class.resource_path}/#{chef_id}", MultiJson.encode(is_completed: true)).body
50
+ rescue Ridley::Errors::HTTPBadRequest => ex
51
+ abort Ridley::Errors::SandboxCommitError.new(ex.message)
52
+ rescue Ridley::Errors::HTTPNotFound => ex
53
+ abort Ridley::Errors::ResourceNotFound.new(ex.message)
54
+ rescue Ridley::Errors::HTTPUnauthorized, Ridley::Errors::HTTPForbidden => ex
55
+ abort Ridley::Errors::PermissionDenied.new(ex.message)
69
56
  end
70
57
 
71
- # Concurrently upload all of this sandboxes files into the checksum containers of the sandbox
72
- def upload(checksums)
73
- SandboxUploader.upload(self, checksums)
58
+ # Concurrently upload all of the files in the given sandbox
59
+ #
60
+ # @param [Ridley::SandboxObject] sandbox
61
+ # @param [Hash] checksums
62
+ # a hash of file checksums and file paths
63
+ #
64
+ # @example
65
+ # SandboxUploader.upload(sandbox,
66
+ # "e5a0f6b48d0712382295ff30bec1f9cc" => "/Users/reset/code/rbenv-cookbook/recipes/default.rb",
67
+ # "de6532a7fbe717d52020dc9f3ae47dbe" => "/Users/reset/code/rbenv-cookbook/recipes/ohai_plugin.rb"
68
+ # )
69
+ #
70
+ # @return [Array<Hash>]
71
+ def upload(object, checksums)
72
+ checksums.collect do |chk_id, path|
73
+ uploader.future(:upload, object, chk_id, path)
74
+ end.map(&:value)
75
+ end
76
+
77
+ def update(*args)
78
+ raise RuntimeError, "action not supported"
74
79
  end
75
80
 
76
- # Notify the Chef Server that uploading to this sandbox has completed
77
- def commit
78
- response = client.connection.put("sandboxes/#{sandbox_id}", MultiJson.encode(is_completed: true)).body
79
- set_attribute(:is_completed, response[:is_completed])
81
+ def all(*args)
82
+ raise RuntimeError, "action not supported"
80
83
  end
81
84
 
82
- def to_s
83
- "#{sandbox_id}: #{checksums}"
85
+ def find(*args)
86
+ raise RuntimeError, "action not supported"
84
87
  end
88
+
89
+ def delete(*args)
90
+ raise RuntimeError, "action not supported"
91
+ end
92
+
93
+ def delete_all(*args)
94
+ raise RuntimeError, "action not supported"
95
+ end
96
+
97
+ private
98
+
99
+ attr_reader :uploader
85
100
  end
86
101
  end
@@ -0,0 +1,99 @@
1
+ module Ridley
2
+ # @author Jamie Winsor <reset@riotgames.com>
3
+ class SearchResource < Ridley::Resource
4
+ class << self
5
+ # @param [String] query_string
6
+ #
7
+ # @option options [String] :sort
8
+ # a sort string such as 'name DESC'
9
+ # @option options [Integer] :rows
10
+ # how many rows to return
11
+ # @option options [Integer] :start
12
+ # the result number to start from
13
+ #
14
+ # @return [Hash]
15
+ def build_query(query_string, options = {})
16
+ {}.tap do |query_opts|
17
+ query_opts[:q] = query_string unless query_string.nil?
18
+ query_opts[:sort] = options[:sort] unless options[:sort].nil?
19
+ query_opts[:rows] = options[:rows] unless options[:rows].nil?
20
+ query_opts[:start] = options[:start] unless options[:start].nil?
21
+ end
22
+ end
23
+
24
+ # @param [#to_s] index
25
+ #
26
+ # @return [String]
27
+ def query_uri(index)
28
+ "#{resource_path}/#{index}"
29
+ end
30
+ end
31
+
32
+ set_resource_path "search"
33
+
34
+ # Returns an array of possible search indexes to be search on
35
+ #
36
+ # @param [Ridley::Client] client
37
+ #
38
+ # @example
39
+ #
40
+ # Search.indexes(client) => [ :client, :environment, :node, :role ]
41
+ #
42
+ # @return [Array<String, Symbol>]
43
+ def indexes
44
+ connection.get(self.class.resource_path).body.collect { |name, _| name }
45
+ end
46
+
47
+ # Executes the built up query on the search's client
48
+ #
49
+ # @param [#to_sym, #to_s] index
50
+ # @param [#to_s] query_string
51
+ #
52
+ # @option options [String] :sort
53
+ # a sort string such as 'name DESC'
54
+ # @option options [Integer] :rows
55
+ # how many rows to return
56
+ # @option options [Integer] :start
57
+ # the result number to start from
58
+ #
59
+ # @example
60
+ # Search.new(client, :role)
61
+ # search.run =>
62
+ # {
63
+ # total: 1,
64
+ # start: 0,
65
+ # rows: [
66
+ # {
67
+ # name: "ridley-test-role",
68
+ # default_attributes: {},
69
+ # json_class: "Chef::Role",
70
+ # env_run_lists: {},
71
+ # run_list: [],
72
+ # description: "a test role for Ridley!",
73
+ # chef_type: "role",
74
+ # override_attributes: {}
75
+ # }
76
+ # ]
77
+ # }
78
+ #
79
+ # @return [Array<ChefObject>, Hash]
80
+ def run(index, query_string, options = {})
81
+ query_uri = self.class.query_uri(index)
82
+ query = self.class.build_query(query_string, options)
83
+ response = connection.get(query_uri, query).body
84
+
85
+ case index.to_sym
86
+ when :node
87
+ response[:rows].collect { |row| Ridley::NodeObject.new(row) }
88
+ when :role
89
+ response[:rows].collect { |row| Ridley::RoleObject.new(row) }
90
+ when :client
91
+ response[:rows].collect { |row| Ridley::ClientObject.new(row) }
92
+ when :environment
93
+ response[:rows].collect { |row| Ridley::EnvironmentObject.new(row) }
94
+ else
95
+ response[:rows]
96
+ end
97
+ end
98
+ end
99
+ end
@@ -3,24 +3,6 @@ module Ridley
3
3
  # @api private
4
4
  class SandboxUploader
5
5
  class << self
6
- # Concurrently upload all of the files in the given sandbox and then clean up
7
- # after ourselves
8
- #
9
- # @param [Ridley::SandboxResource] sandbox
10
- # @param [Hash] checksums
11
- #
12
- # @option options [Integer] :pool_size (12)
13
- # the amount of concurrent uploads to perform
14
- def upload(sandbox, checksums, options = {})
15
- options = options.reverse_merge(
16
- pool_size: 12
17
- )
18
- uploader = pool(size: options[:pool_size], args: [sandbox])
19
- uploader.multi_upload(checksums)
20
- ensure
21
- uploader.terminate if uploader && uploader.alive?
22
- end
23
-
24
6
  # Return the checksum of the contents of the file at the given filepath
25
7
  #
26
8
  # @param [String] path
@@ -55,45 +37,29 @@ module Ridley
55
37
  end
56
38
  end
57
39
 
58
- extend Forwardable
59
40
  include Celluloid
60
41
 
61
- attr_reader :sandbox
62
-
63
- def_delegator :sandbox, :client
64
- def_delegator :sandbox, :checksum
65
-
66
- def initialize(sandbox)
67
- @sandbox = sandbox
68
- end
42
+ attr_reader :client_name
43
+ attr_reader :client_key
44
+ attr_reader :options
69
45
 
70
- # Concurrently upload multiple files into a sandbox
71
- #
72
- # @param [Hash] checksums
73
- # a hash of file checksums and file paths
74
- #
75
- # @example uploading multiple checksums
76
- #
77
- # sandbox.multi_upload(
78
- # "e5a0f6b48d0712382295ff30bec1f9cc" => "/Users/reset/code/rbenv-cookbook/recipes/default.rb",
79
- # "de6532a7fbe717d52020dc9f3ae47dbe" => "/Users/reset/code/rbenv-cookbook/recipes/ohai_plugin.rb"
80
- # )
81
- def multi_upload(checksums)
82
- checksums.collect do |chk_id, path|
83
- future.upload(chk_id, path)
84
- end.map(&:value)
46
+ def initialize(client_name, client_key, options = {})
47
+ @client_name = client_name
48
+ @client_key = client_key
49
+ @options = options
85
50
  end
86
51
 
87
52
  # Upload one file into the sandbox for the given checksum id
88
53
  #
54
+ # @param [Ridley::SandboxObject] sandbox
89
55
  # @param [String] chk_id
90
56
  # checksum of the file being uploaded
91
57
  # @param [String] path
92
58
  # path to the file to upload
93
59
  #
94
60
  # @return [Hash, nil]
95
- def upload(chk_id, path)
96
- checksum = self.checksum(chk_id)
61
+ def upload(sandbox, chk_id, path)
62
+ checksum = sandbox.checksum(chk_id)
97
63
 
98
64
  unless checksum[:needs_upload]
99
65
  return nil
@@ -109,17 +75,11 @@ module Ridley
109
75
  upload_path = url.path
110
76
  url.path = ""
111
77
 
112
- # versions prior to OSS Chef 11 will strip the port to upload the file to in the checksum
113
- # url returned. This will ensure we are uploading to the proper location.
114
- if client.connection.foss?
115
- url.port = URI(client.connection.server_url).port
116
- end
117
-
118
78
  begin
119
- Faraday.new(url, client.options.slice(*Connection::VALID_OPTIONS)) do |c|
79
+ Faraday.new(url, self.options) do |c|
120
80
  c.response :chef_response
121
81
  c.response :follow_redirects
122
- c.request :chef_auth, client.client_name, client.client_key
82
+ c.request :chef_auth, self.client_name, self.client_key
123
83
  c.adapter :net_http
124
84
  end.put(upload_path, contents, headers)
125
85
  rescue Ridley::Errors::HTTPError => ex
@@ -1,3 +1,3 @@
1
1
  module Ridley
2
- VERSION = "0.10.2"
2
+ VERSION = "0.11.0.rc1"
3
3
  end
@@ -23,7 +23,7 @@ describe "Bootstrapping a node", type: "acceptance" do
23
23
 
24
24
  it "returns an array of response objects" do
25
25
  pending
26
-
26
+
27
27
  connection.node.bootstrap("33.33.33.10").should_not have_errors
28
28
  end
29
29
  end