cheffish 0.7.1 → 0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef/provider/chef_acl.rb +434 -0
- data/lib/chef/provider/chef_client.rb +5 -1
- data/lib/chef/provider/chef_container.rb +50 -0
- data/lib/chef/provider/chef_group.rb +78 -0
- data/lib/chef/provider/chef_mirror.rb +138 -0
- data/lib/chef/provider/chef_organization.rb +150 -0
- data/lib/chef/provider/chef_user.rb +6 -1
- data/lib/chef/provider/public_key.rb +0 -1
- data/lib/chef/resource/chef_acl.rb +38 -44
- data/lib/chef/resource/chef_container.rb +18 -0
- data/lib/chef/resource/chef_group.rb +49 -0
- data/lib/chef/resource/chef_mirror.rb +47 -0
- data/lib/chef/resource/chef_organization.rb +64 -0
- data/lib/chef/resource/private_key.rb +6 -1
- data/lib/chef/resource/public_key.rb +5 -0
- data/lib/cheffish/actor_provider_base.rb +14 -9
- data/lib/cheffish/basic_chef_client.rb +18 -2
- data/lib/cheffish/chef_provider_base.rb +7 -0
- data/lib/cheffish/merged_config.rb +10 -2
- data/lib/cheffish/recipe_dsl.rb +34 -8
- data/lib/cheffish/server_api.rb +12 -2
- data/lib/cheffish/version.rb +1 -1
- data/lib/cheffish.rb +2 -2
- data/spec/functional/merged_config_spec.rb +20 -0
- data/spec/integration/chef_acl_spec.rb +914 -0
- data/spec/integration/chef_client_spec.rb +78 -44
- data/spec/integration/chef_container_spec.rb +34 -0
- data/spec/integration/chef_group_spec.rb +324 -0
- data/spec/integration/chef_mirror_spec.rb +244 -0
- data/spec/integration/chef_node_spec.rb +115 -93
- data/spec/integration/chef_organization_spec.rb +244 -0
- data/spec/integration/chef_user_spec.rb +51 -9
- data/spec/support/repository_support.rb +103 -0
- data/spec/support/spec_support.rb +55 -2
- metadata +23 -9
- data/lib/chef/resource/in_parallel.rb +0 -6
@@ -14,9 +14,9 @@ class Cheffish::ActorProviderBase < Cheffish::ChefProviderBase
|
|
14
14
|
if current_resource_exists?
|
15
15
|
# Update the actor if it's different
|
16
16
|
if differences.size > 0
|
17
|
-
description = [ "update #{actor_type} #{new_resource.name} at #{
|
17
|
+
description = [ "update #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
|
18
18
|
converge_by description do
|
19
|
-
result = rest.put("#{
|
19
|
+
result = rest.put("#{actor_path}/#{new_resource.name}", normalize_for_put(new_json))
|
20
20
|
current_public_key, current_public_key_format = Cheffish::KeyFormatter.decode(result['public_key']) if result['public_key']
|
21
21
|
end
|
22
22
|
end
|
@@ -25,9 +25,9 @@ class Cheffish::ActorProviderBase < Cheffish::ChefProviderBase
|
|
25
25
|
if !new_public_key
|
26
26
|
raise "You must specify a public key to create a #{actor_type}! Use the private_key resource to create a key, and pass it in with source_key_path."
|
27
27
|
end
|
28
|
-
description = [ "create #{actor_type} #{new_resource.name} at #{
|
28
|
+
description = [ "create #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
|
29
29
|
converge_by description do
|
30
|
-
result = rest.post("#{
|
30
|
+
result = rest.post("#{actor_path}", normalize_for_post(new_json))
|
31
31
|
current_public_key, current_public_key_format = Cheffish::KeyFormatter.decode(result['public_key']) if result['public_key']
|
32
32
|
end
|
33
33
|
end
|
@@ -58,8 +58,8 @@ class Cheffish::ActorProviderBase < Cheffish::ChefProviderBase
|
|
58
58
|
|
59
59
|
def delete_actor
|
60
60
|
if current_resource_exists?
|
61
|
-
converge_by "delete #{actor_type} #{new_resource.name} at #{
|
62
|
-
rest.delete("#{
|
61
|
+
converge_by "delete #{actor_type} #{new_resource.name} at #{actor_path}" do
|
62
|
+
rest.delete("#{actor_path}/#{new_resource.name}")
|
63
63
|
Chef::Log.info("#{new_resource} deleted #{actor_type} #{new_resource.name} at #{rest.url}")
|
64
64
|
end
|
65
65
|
end
|
@@ -74,7 +74,13 @@ class Cheffish::ActorProviderBase < Cheffish::ChefProviderBase
|
|
74
74
|
@new_public_key ||= begin
|
75
75
|
if new_resource.source_key
|
76
76
|
if new_resource.source_key.is_a?(String)
|
77
|
-
Cheffish::KeyFormatter.decode(new_resource.source_key)
|
77
|
+
key, key_format = Cheffish::KeyFormatter.decode(new_resource.source_key)
|
78
|
+
|
79
|
+
if key.private?
|
80
|
+
key.public_key
|
81
|
+
else
|
82
|
+
key
|
83
|
+
end
|
78
84
|
elsif new_resource.source_key.private?
|
79
85
|
new_resource.source_key.public_key
|
80
86
|
else
|
@@ -108,7 +114,7 @@ class Cheffish::ActorProviderBase < Cheffish::ChefProviderBase
|
|
108
114
|
|
109
115
|
def load_current_resource
|
110
116
|
begin
|
111
|
-
json = rest.get("#{
|
117
|
+
json = rest.get("#{actor_path}/#{new_resource.name}")
|
112
118
|
@current_resource = json_to_resource(json)
|
113
119
|
rescue Net::HTTPServerException => e
|
114
120
|
if e.response.code == "404"
|
@@ -122,5 +128,4 @@ class Cheffish::ActorProviderBase < Cheffish::ChefProviderBase
|
|
122
128
|
current_resource.output_key_path = new_resource.output_key_path
|
123
129
|
end
|
124
130
|
end
|
125
|
-
|
126
131
|
end
|
@@ -37,6 +37,11 @@ module Cheffish
|
|
37
37
|
attr_accessor :recipe_name
|
38
38
|
def_delegators :@run_context, :resource_collection, :immediate_notifications, :delayed_notifications
|
39
39
|
|
40
|
+
def add_resource(resource)
|
41
|
+
resource.run_context = run_context
|
42
|
+
run_context.resource_collection.insert(resource)
|
43
|
+
end
|
44
|
+
|
40
45
|
def load_block(&block)
|
41
46
|
@recipe_name = 'block'
|
42
47
|
instance_eval(&block)
|
@@ -54,10 +59,21 @@ module Cheffish
|
|
54
59
|
@event_catcher.updates.size > 0
|
55
60
|
end
|
56
61
|
|
57
|
-
|
62
|
+
# Builds a resource sans context, which can be later used in a new client's
|
63
|
+
# add_resource() method.
|
64
|
+
def self.build_resource(type, name, created_at=nil, &resource_attrs_block)
|
65
|
+
created_at ||= caller[0]
|
66
|
+
result = BasicChefClient.new.build_resource(type, name, created_at, &resource_attrs_block)
|
67
|
+
result
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.inline_resource(provider, provider_action, *resources, &block)
|
58
71
|
events = ProviderEventForwarder.new(provider, provider_action)
|
59
72
|
client = BasicChefClient.new(provider.node, events)
|
60
|
-
|
73
|
+
resources.each do |resource|
|
74
|
+
client.add_resource(resource)
|
75
|
+
end
|
76
|
+
client.load_block(&block) if block
|
61
77
|
client.converge
|
62
78
|
client.updated?
|
63
79
|
end
|
@@ -215,10 +215,17 @@ module Cheffish
|
|
215
215
|
def initialize(name, parent = nil)
|
216
216
|
@name = name
|
217
217
|
@parent = parent
|
218
|
+
@org = nil
|
218
219
|
end
|
219
220
|
|
220
221
|
attr_reader :name
|
221
222
|
attr_reader :parent
|
223
|
+
attr_reader :org
|
222
224
|
end
|
223
225
|
end
|
226
|
+
|
227
|
+
# We are not interested in Chef's cloning behavior here.
|
228
|
+
def load_prior_resource
|
229
|
+
Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
|
230
|
+
end
|
224
231
|
end
|
@@ -45,8 +45,12 @@ module Cheffish
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
def method_missing(name)
|
49
|
-
|
48
|
+
def method_missing(name, *args)
|
49
|
+
if args.count > 0
|
50
|
+
raise NoMethodError, "Unexpected method #{name} for MergedConfig with arguments #{args}"
|
51
|
+
else
|
52
|
+
self[name]
|
53
|
+
end
|
50
54
|
end
|
51
55
|
|
52
56
|
def key?(name)
|
@@ -82,5 +86,9 @@ module Cheffish
|
|
82
86
|
end
|
83
87
|
result
|
84
88
|
end
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
to_hash.to_s
|
92
|
+
end
|
85
93
|
end
|
86
94
|
end
|
data/lib/cheffish/recipe_dsl.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'cheffish'
|
2
2
|
|
3
|
+
require 'chef/version'
|
3
4
|
require 'chef_zero/server'
|
4
5
|
require 'chef/chef_fs/chef_fs_data_store'
|
5
6
|
require 'chef/chef_fs/config'
|
@@ -7,26 +8,38 @@ require 'cheffish/chef_run_data'
|
|
7
8
|
require 'cheffish/chef_run_listener'
|
8
9
|
require 'chef/client'
|
9
10
|
require 'chef/config'
|
11
|
+
require 'chef_zero/version'
|
10
12
|
require 'cheffish/merged_config'
|
13
|
+
require 'chef/resource/chef_acl'
|
11
14
|
require 'chef/resource/chef_client'
|
15
|
+
require 'chef/resource/chef_container'
|
12
16
|
require 'chef/resource/chef_data_bag'
|
13
17
|
require 'chef/resource/chef_data_bag_item'
|
14
18
|
require 'chef/resource/chef_environment'
|
19
|
+
require 'chef/resource/chef_group'
|
20
|
+
require 'chef/resource/chef_mirror'
|
15
21
|
require 'chef/resource/chef_node'
|
22
|
+
require 'chef/resource/chef_organization'
|
16
23
|
require 'chef/resource/chef_role'
|
17
24
|
require 'chef/resource/chef_user'
|
18
25
|
require 'chef/resource/private_key'
|
19
26
|
require 'chef/resource/public_key'
|
27
|
+
require 'chef/provider/chef_acl'
|
20
28
|
require 'chef/provider/chef_client'
|
29
|
+
require 'chef/provider/chef_container'
|
21
30
|
require 'chef/provider/chef_data_bag'
|
22
31
|
require 'chef/provider/chef_data_bag_item'
|
23
32
|
require 'chef/provider/chef_environment'
|
33
|
+
require 'chef/provider/chef_group'
|
34
|
+
require 'chef/provider/chef_mirror'
|
24
35
|
require 'chef/provider/chef_node'
|
36
|
+
require 'chef/provider/chef_organization'
|
25
37
|
require 'chef/provider/chef_role'
|
26
38
|
require 'chef/provider/chef_user'
|
27
39
|
require 'chef/provider/private_key'
|
28
40
|
require 'chef/provider/public_key'
|
29
41
|
|
42
|
+
|
30
43
|
class Chef
|
31
44
|
module DSL
|
32
45
|
module Recipe
|
@@ -49,7 +62,7 @@ class Chef
|
|
49
62
|
def with_chef_local_server(options, &block)
|
50
63
|
options[:host] ||= '127.0.0.1'
|
51
64
|
options[:log_level] ||= Chef::Log.level
|
52
|
-
options[:port] ||= 8901.upto(9900)
|
65
|
+
options[:port] ||= ChefZero::VERSION.to_f >= 2.2 ? 8901.upto(9900) : 8901
|
53
66
|
|
54
67
|
# Create the data store chef-zero will use
|
55
68
|
options[:data_store] ||= begin
|
@@ -59,16 +72,13 @@ class Chef
|
|
59
72
|
|
60
73
|
# Ensure all paths are given
|
61
74
|
%w(acl client cookbook container data_bag environment group node role).each do |type|
|
62
|
-
options["#{type}_path"
|
75
|
+
options["#{type}_path"] ||= begin
|
63
76
|
if options[:chef_repo_path].kind_of?(String)
|
64
|
-
|
77
|
+
Chef::Util::PathHelper.join(options[:chef_repo_path], "#{type}s")
|
65
78
|
else
|
66
|
-
options[:chef_repo_path].map { |path|
|
79
|
+
options[:chef_repo_path].map { |path| Chef::Util::PathHelper.join(path, "#{type}s")}
|
67
80
|
end
|
68
81
|
end
|
69
|
-
# Work around issue in earlier versions of ChefFS where it expects strings for these
|
70
|
-
# instead of symbols
|
71
|
-
options["#{type}_path"] = options["#{type}_path".to_sym]
|
72
82
|
end
|
73
83
|
|
74
84
|
chef_fs = Chef::ChefFS::Config.new(options).local_fs
|
@@ -95,7 +105,7 @@ class Chef
|
|
95
105
|
class Config
|
96
106
|
default(:profile) { ENV['CHEF_PROFILE'] || 'default' }
|
97
107
|
configurable(:private_keys)
|
98
|
-
default(:private_key_paths) { [
|
108
|
+
default(:private_key_paths) { [ Chef::Util::PathHelper.join(config_dir, 'keys'), Chef::Util::PathHelper.join(user_home, '.ssh') ] }
|
99
109
|
default(:private_key_write_path) { private_key_paths.first }
|
100
110
|
end
|
101
111
|
|
@@ -119,3 +129,19 @@ class Chef
|
|
119
129
|
end
|
120
130
|
|
121
131
|
end
|
132
|
+
|
133
|
+
# Chef 12 moved Chef::Config.path_join to PathHelper.join
|
134
|
+
if Chef::VERSION.to_i >= 12
|
135
|
+
require 'chef/util/path_helper'
|
136
|
+
else
|
137
|
+
require 'chef/config'
|
138
|
+
class Chef
|
139
|
+
class Util
|
140
|
+
class PathHelper
|
141
|
+
def join(*args)
|
142
|
+
Chef::Config.path_join(*args)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
data/lib/cheffish/server_api.rb
CHANGED
@@ -16,13 +16,16 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
+
require 'chef/version'
|
19
20
|
require 'chef/http'
|
20
21
|
require 'chef/http/authenticator'
|
21
22
|
require 'chef/http/cookie_manager'
|
22
23
|
require 'chef/http/decompressor'
|
23
24
|
require 'chef/http/json_input'
|
24
25
|
require 'chef/http/json_output'
|
25
|
-
|
26
|
+
if Gem::Version.new(Chef::VERSION) >= Gem::Version.new('11.12')
|
27
|
+
require 'chef/http/remote_request_id'
|
28
|
+
end
|
26
29
|
|
27
30
|
module Cheffish
|
28
31
|
# Exactly like Chef::ServerAPI, but requires you to pass in what keys you want (no defaults)
|
@@ -30,13 +33,20 @@ module Cheffish
|
|
30
33
|
|
31
34
|
def initialize(url, options = {})
|
32
35
|
super(url, options)
|
36
|
+
root_url = URI.parse(url)
|
37
|
+
root_url.path = ''
|
38
|
+
@root_url = root_url.to_s
|
33
39
|
end
|
34
40
|
|
41
|
+
attr_reader :root_url
|
42
|
+
|
35
43
|
use Chef::HTTP::JSONInput
|
36
44
|
use Chef::HTTP::JSONOutput
|
37
45
|
use Chef::HTTP::CookieManager
|
38
46
|
use Chef::HTTP::Decompressor
|
39
47
|
use Chef::HTTP::Authenticator
|
40
|
-
|
48
|
+
if Gem::Version.new(Chef::VERSION) >= Gem::Version.new('11.12')
|
49
|
+
use Chef::HTTP::RemoteRequestID
|
50
|
+
end
|
41
51
|
end
|
42
52
|
end
|
data/lib/cheffish/version.rb
CHANGED
data/lib/cheffish.rb
CHANGED
@@ -9,8 +9,8 @@ require 'chef/application'
|
|
9
9
|
module Cheffish
|
10
10
|
NAME_REGEX = /^[.\-[:alnum:]_]+$/
|
11
11
|
|
12
|
-
def self.inline_resource(provider, provider_action, &block)
|
13
|
-
BasicChefClient.inline_resource(provider, provider_action, &block)
|
12
|
+
def self.inline_resource(provider, provider_action, *resources, &block)
|
13
|
+
BasicChefClient.inline_resource(provider, provider_action, *resources, &block)
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.default_chef_server(config = profiled_config)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'cheffish/merged_config'
|
2
|
+
|
3
|
+
describe "merged_config" do
|
4
|
+
|
5
|
+
let(:config) do
|
6
|
+
Cheffish::MergedConfig.new({:test=>'val'})
|
7
|
+
end
|
8
|
+
|
9
|
+
it "returns value in config" do
|
10
|
+
expect(config.test).to eq('val')
|
11
|
+
end
|
12
|
+
|
13
|
+
it "raises a NoMethodError if calling an unknown method with arguments" do
|
14
|
+
expect{config.merge({:some => 'hash'})}.to raise_error(NoMethodError)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "has an informative string representation" do
|
18
|
+
expect("#{config}").to eq("{:test=>\"val\"}")
|
19
|
+
end
|
20
|
+
end
|