cheffish 0.7.1 → 0.8
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.
- 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
|