chef-metal 0.5 → 0.6
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/CHANGELOG.md +29 -0
- data/lib/chef_metal/convergence_strategy/precreate_chef_objects.rb +14 -0
- data/lib/chef_metal/version.rb +1 -1
- metadata +31 -13
- data/lib/chef/provider/fog_key_pair.rb +0 -169
- data/lib/chef/provider/vagrant_box.rb +0 -44
- data/lib/chef/provider/vagrant_cluster.rb +0 -42
- data/lib/chef/resource/fog_key_pair.rb +0 -34
- data/lib/chef/resource/vagrant_box.rb +0 -18
- data/lib/chef/resource/vagrant_cluster.rb +0 -16
- data/lib/chef_metal/fog.rb +0 -20
- data/lib/chef_metal/provisioner/fog_provisioner.rb +0 -550
- data/lib/chef_metal/provisioner/vagrant_provisioner.rb +0 -348
- data/lib/chef_metal/provisioner_init/fog_init.rb +0 -4
- data/lib/chef_metal/provisioner_init/vagrant_cluster_init.rb +0 -4
- data/lib/chef_metal/vagrant.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f75d0eea4f0ab10f62670396310edd0576e866f
|
4
|
+
data.tar.gz: 6dd9f7a2319e535163b35772f1efa62b6d32bd7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdb8c0681270de564b0adc840e73a382c8bef6a1aa358692e81b80b480f670d6be31c1128f87e0ce8b6774168a74d0731d3975264d7a2e7ed0b97ac13455d924
|
7
|
+
data.tar.gz: a58484ee3eafe1c46914fe624587c2476e16f42c9b935f7bdcae29b6e409354745a7e57884ed97fc86031174bf6344caf95096b7de0c745410bdf4fc50e7dadb
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Chef Metal Changelog
|
2
|
+
|
3
|
+
## 0.6 (4/4/2014)
|
4
|
+
|
5
|
+
- Vagrant and Fog provisioners moved to their own gems (chef-metal-vagrant and chef-metal-fog)
|
6
|
+
- Support for Hosted and Enterprise Chef (https://github.com/dafyddcrosby)
|
7
|
+
|
8
|
+
## 0.5 (4/3/2014)
|
9
|
+
|
10
|
+
* Provisioner interface changes designed to allow provisioners to be used outside of Chef (doubt@getchef.com)
|
11
|
+
* All Provisioner and Machine methods now take "action_handler" instead of "provider." It uses the ActionHandler interface described in action_handler.rb. In short:
|
12
|
+
- provider.run_context -> action_handler.recipe_context
|
13
|
+
- provider.updated_by_last_action(true) -> action_handler.updated!
|
14
|
+
- provider.converge_by -> action_handler.perform_action
|
15
|
+
- provider.cookbook_name -> provider.debug_name
|
16
|
+
* Convergence strategy: delete_chef_objects() -> cleanup_convergence()
|
17
|
+
* Ability to get back to a machine from a node (another Provisioner interface change) (doubt@getchef.com):
|
18
|
+
* Provisioners must create a file named `chef_metal/provisioner_init/<scheme>_init.rb`. It will be required when a node is encountered with that scheme. It should call ChefMetal.add_registered_provisioner_class(<scheme>, <provisioner class name>). For the provisioner_url `fog:AWS:21348723432`, the scheme is "fog" and the file is `chef_metalprovisioner_init/fog_init.rb`. It should call `ChefMetal.add_registered_provisioner_class('fog', ChefMetal::Provisioner::FogProvisioner)`.
|
19
|
+
* Provisioner classes must implement the class method `inflate(node)`, which should create a Provisioner instance appropriate to the given `node` (generally by looking at `node['normal']['provisioner_output']`)
|
20
|
+
* New `NoConverge` convergence strategy that creates a node but does not install Chef or converge.
|
21
|
+
* Support for machine_file `group`, `owner` and `mode` attributes (@irvingpop)
|
22
|
+
* SSH transport (ryan@segv.net): try to enable pty when possible (increases chance of successful connection). Set options[:ssh_pty_enable] to `false` to turn this off. Set `true` to force it (and fail if we can't get it)
|
23
|
+
|
24
|
+
## 0.4 (3/29/2014)
|
25
|
+
|
26
|
+
* EC2: Make it possible for multiple IAM users to converge chef-metal on the same account
|
27
|
+
* Openstack: Openstack support via the Fog driver! (@cstewart87)
|
28
|
+
* EC2: Add :use_private_ip_for_ssh option, and use private ip by default if public IP does not exist. (@xorl, @dafyddcrosby)
|
29
|
+
* RHEL/Centos: fix platform detection and installation
|
@@ -126,8 +126,22 @@ module ChefMetal
|
|
126
126
|
chef_server machine_resource.chef_server
|
127
127
|
raw_json machine.node
|
128
128
|
end
|
129
|
+
end
|
129
130
|
|
131
|
+
# If using enterprise/hosted chef, fix acls
|
132
|
+
if machine_resource.chef_server[:chef_server_url] =~ /\/+organizations\/.+/
|
133
|
+
grant_client_node_permissions(machine_resource.chef_server, machine.node['name'], ["read", "update"])
|
134
|
+
end
|
135
|
+
end
|
130
136
|
|
137
|
+
# Grant the client permissions to the node
|
138
|
+
# This procedure assumes that the client name and node name are the same
|
139
|
+
def grant_client_node_permissions(chef_server, node_name, perms)
|
140
|
+
rest = Chef::REST.new(chef_server[:chef_server_url])
|
141
|
+
node_perms = rest.get("/nodes/#{node_name}/_acl")
|
142
|
+
perms.each do |p|
|
143
|
+
node_perms[p]['actors'] << node_name unless node_perms[p]['actors'].include?(node_name)
|
144
|
+
rest.put("/nodes/#{node_name}/_acl/#{p}", p => node_perms[p])
|
131
145
|
end
|
132
146
|
end
|
133
147
|
|
data/lib/chef_metal/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-metal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.6'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Keiser
|
@@ -80,6 +80,34 @@ dependencies:
|
|
80
80
|
- - ~>
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '2.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: chef-metal-fog
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: chef-metal-vagrant
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: rspec
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,21 +142,17 @@ executables: []
|
|
114
142
|
extensions: []
|
115
143
|
extra_rdoc_files:
|
116
144
|
- README.md
|
145
|
+
- CHANGELOG.md
|
117
146
|
- LICENSE
|
118
147
|
files:
|
119
148
|
- Rakefile
|
120
149
|
- LICENSE
|
121
150
|
- README.md
|
122
|
-
-
|
151
|
+
- CHANGELOG.md
|
123
152
|
- lib/chef/provider/machine.rb
|
124
153
|
- lib/chef/provider/machine_file.rb
|
125
|
-
- lib/chef/provider/vagrant_box.rb
|
126
|
-
- lib/chef/provider/vagrant_cluster.rb
|
127
|
-
- lib/chef/resource/fog_key_pair.rb
|
128
154
|
- lib/chef/resource/machine.rb
|
129
155
|
- lib/chef/resource/machine_file.rb
|
130
|
-
- lib/chef/resource/vagrant_box.rb
|
131
|
-
- lib/chef/resource/vagrant_cluster.rb
|
132
156
|
- lib/chef_metal/action_handler.rb
|
133
157
|
- lib/chef_metal/aws_credentials.rb
|
134
158
|
- lib/chef_metal/convergence_strategy/install_cached.rb
|
@@ -137,7 +161,6 @@ files:
|
|
137
161
|
- lib/chef_metal/convergence_strategy/no_converge.rb
|
138
162
|
- lib/chef_metal/convergence_strategy/precreate_chef_objects.rb
|
139
163
|
- lib/chef_metal/convergence_strategy.rb
|
140
|
-
- lib/chef_metal/fog.rb
|
141
164
|
- lib/chef_metal/inline_resource.rb
|
142
165
|
- lib/chef_metal/machine/basic_machine.rb
|
143
166
|
- lib/chef_metal/machine/unix_machine.rb
|
@@ -145,16 +168,11 @@ files:
|
|
145
168
|
- lib/chef_metal/machine.rb
|
146
169
|
- lib/chef_metal/openstack_credentials.rb
|
147
170
|
- lib/chef_metal/provider_action_handler.rb
|
148
|
-
- lib/chef_metal/provisioner/fog_provisioner.rb
|
149
|
-
- lib/chef_metal/provisioner/vagrant_provisioner.rb
|
150
171
|
- lib/chef_metal/provisioner.rb
|
151
|
-
- lib/chef_metal/provisioner_init/fog_init.rb
|
152
|
-
- lib/chef_metal/provisioner_init/vagrant_cluster_init.rb
|
153
172
|
- lib/chef_metal/recipe_dsl.rb
|
154
173
|
- lib/chef_metal/transport/ssh.rb
|
155
174
|
- lib/chef_metal/transport/winrm.rb
|
156
175
|
- lib/chef_metal/transport.rb
|
157
|
-
- lib/chef_metal/vagrant.rb
|
158
176
|
- lib/chef_metal/version.rb
|
159
177
|
- lib/chef_metal.rb
|
160
178
|
homepage: http://wiki.opscode.com/display/chef
|
@@ -1,169 +0,0 @@
|
|
1
|
-
require 'chef/provider/lwrp_base'
|
2
|
-
require 'chef_metal/provider_action_handler'
|
3
|
-
|
4
|
-
class Chef::Provider::FogKeyPair < Chef::Provider::LWRPBase
|
5
|
-
|
6
|
-
include ChefMetal::ProviderActionHandler
|
7
|
-
|
8
|
-
use_inline_resources
|
9
|
-
|
10
|
-
def whyrun_supported?
|
11
|
-
true
|
12
|
-
end
|
13
|
-
|
14
|
-
action :create do
|
15
|
-
create_key
|
16
|
-
end
|
17
|
-
|
18
|
-
action :delete do
|
19
|
-
if current_resource_exists?
|
20
|
-
converge_by "delete #{key_description}" do
|
21
|
-
case new_resource.provisioner.compute_options[:provider]
|
22
|
-
when 'DigitalOcean'
|
23
|
-
compute.destroy_key_pair(@current_id)
|
24
|
-
when 'OpenStack'
|
25
|
-
compute.key_pairs.destroy(@current_id)
|
26
|
-
else
|
27
|
-
compute.key_pairs.delete(new_resource.name)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def key_description
|
34
|
-
"#{new_resource.name} on #{new_resource.provisioner.provisioner_url}"
|
35
|
-
end
|
36
|
-
|
37
|
-
def create_key
|
38
|
-
if current_resource_exists?
|
39
|
-
# If the public keys are different, update the server public key
|
40
|
-
if !current_resource.private_key_path
|
41
|
-
if new_resource.allow_overwrite
|
42
|
-
ensure_keys
|
43
|
-
else
|
44
|
-
raise "#{key_description} already exists on the server, but the private key #{new_resource.private_key_path} does not exist!"
|
45
|
-
end
|
46
|
-
else
|
47
|
-
ensure_keys
|
48
|
-
end
|
49
|
-
|
50
|
-
new_fingerprint = case new_resource.provisioner.compute_options[:provider]
|
51
|
-
when 'DigitalOcean'
|
52
|
-
Cheffish::KeyFormatter.encode(desired_key, :format => :openssh)
|
53
|
-
when 'OpenStack'
|
54
|
-
Cheffish::KeyFormatter.encode(desired_key, :format => :openssh)
|
55
|
-
else
|
56
|
-
Cheffish::KeyFormatter.encode(desired_key, :format => :fingerprint)
|
57
|
-
end
|
58
|
-
|
59
|
-
if new_fingerprint != @current_fingerprint
|
60
|
-
if new_resource.allow_overwrite
|
61
|
-
converge_by "update #{key_description} to match local key at #{new_resource.private_key_path}" do
|
62
|
-
case new_resource.provisioner.compute_options[:provider]
|
63
|
-
when 'DigitalOcean'
|
64
|
-
compute.create_ssh_key(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
|
65
|
-
when 'OpenStack'
|
66
|
-
compute.create_key_pair(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
|
67
|
-
else
|
68
|
-
compute.import_key_pair(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
|
69
|
-
end
|
70
|
-
end
|
71
|
-
else
|
72
|
-
raise "#{key_description} does not match local private key, and allow_overwrite is false!"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
else
|
76
|
-
# Generate the private and/or public keys if they do not exist
|
77
|
-
ensure_keys
|
78
|
-
|
79
|
-
# Create key
|
80
|
-
converge_by "create #{key_description} from local key at #{new_resource.private_key_path}" do
|
81
|
-
case new_resource.provisioner.compute_options[:provider]
|
82
|
-
when 'DigitalOcean'
|
83
|
-
compute.create_ssh_key(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
|
84
|
-
when 'OpenStack'
|
85
|
-
compute.create_key_pair(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
|
86
|
-
else
|
87
|
-
compute.import_key_pair(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def ensure_keys
|
94
|
-
resource = new_resource
|
95
|
-
Cheffish.inline_resource(self) do
|
96
|
-
private_key resource.private_key_path do
|
97
|
-
public_key_path resource.public_key_path
|
98
|
-
if resource.private_key_options
|
99
|
-
resource.private_key_options.each_pair do |key,value|
|
100
|
-
send(key, value)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def desired_key
|
108
|
-
@desired_key ||= begin
|
109
|
-
if new_resource.public_key_path
|
110
|
-
public_key, format = Cheffish::KeyFormatter.decode(IO.read(new_resource.public_key_path))
|
111
|
-
public_key
|
112
|
-
else
|
113
|
-
private_key, format = Cheffish::KeyFormatter.decode(IO.read(new_resource.private_key_path))
|
114
|
-
private_key.public_key
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def current_resource_exists?
|
120
|
-
@current_resource.action != [ :delete ]
|
121
|
-
end
|
122
|
-
|
123
|
-
def compute
|
124
|
-
new_resource.provisioner.compute
|
125
|
-
end
|
126
|
-
|
127
|
-
def current_public_key
|
128
|
-
current_resource.source_key
|
129
|
-
end
|
130
|
-
|
131
|
-
def load_current_resource
|
132
|
-
if !new_resource.provisioner.kind_of?(ChefMetal::Provisioner::FogProvisioner)
|
133
|
-
raise 'ec2_key_pair only works with fog_provisioner'
|
134
|
-
end
|
135
|
-
@current_resource = Chef::Resource::FogKeyPair.new(new_resource.name)
|
136
|
-
case new_resource.provisioner.compute_options[:provider]
|
137
|
-
when 'DigitalOcean'
|
138
|
-
current_key_pair = compute.ssh_keys.select { |key| key.name == new_resource.name }.first
|
139
|
-
if current_key_pair
|
140
|
-
@current_id = current_key_pair.id
|
141
|
-
@current_fingerprint = current_key_pair ? compute.ssh_keys.get(@current_id).ssh_pub_key : nil
|
142
|
-
else
|
143
|
-
current_resource.action :delete
|
144
|
-
end
|
145
|
-
when 'OpenStack'
|
146
|
-
current_key_pair = compute.key_pairs.get(new_resource.name)
|
147
|
-
if current_key_pair
|
148
|
-
@current_id = current_key_pair.name
|
149
|
-
@current_fingerprint = current_key_pair ? compute.key_pairs.get(@current_id).public_key : nil
|
150
|
-
else
|
151
|
-
current_resource.action :delete
|
152
|
-
end
|
153
|
-
else
|
154
|
-
current_key_pair = compute.key_pairs.get(new_resource.name)
|
155
|
-
if current_key_pair
|
156
|
-
@current_fingerprint = current_key_pair ? current_key_pair.fingerprint : nil
|
157
|
-
else
|
158
|
-
current_resource.action :delete
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
if new_resource.private_key_path && ::File.exist?(new_resource.private_key_path)
|
163
|
-
current_resource.private_key_path new_resource.private_key_path
|
164
|
-
end
|
165
|
-
if new_resource.public_key_path && ::File.exist?(new_resource.public_key_path)
|
166
|
-
current_resource.public_key_path new_resource.public_key_path
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'chef/provider/lwrp_base'
|
2
|
-
require 'chef/mixin/shell_out'
|
3
|
-
|
4
|
-
class Chef::Provider::VagrantBox < Chef::Provider::LWRPBase
|
5
|
-
|
6
|
-
use_inline_resources
|
7
|
-
|
8
|
-
include Chef::Mixin::ShellOut
|
9
|
-
|
10
|
-
def whyrun_supported?
|
11
|
-
true
|
12
|
-
end
|
13
|
-
|
14
|
-
action :create do
|
15
|
-
if !list_boxes.has_key?(new_resource.name)
|
16
|
-
if new_resource.url
|
17
|
-
converge_by "run 'vagrant box add #{new_resource.name} #{new_resource.url}'" do
|
18
|
-
shell_out("vagrant box add #{new_resource.name} #{new_resource.url}").error!
|
19
|
-
end
|
20
|
-
else
|
21
|
-
raise "Box #{new_resource.name} does not exist"
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
action :delete do
|
27
|
-
if list_boxes.has_key?(new_resource.name)
|
28
|
-
converge_by "run 'vagrant box remove #{new_resource.name} #{list_boxes[new_resource.name]}'" do
|
29
|
-
shell_out("vagrant box remove #{new_resource.name} #{list_boxes[new_resource.name]}").error!
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def list_boxes
|
35
|
-
@list_boxes ||= shell_out("vagrant box list").stdout.lines.inject({}) do |result, line|
|
36
|
-
line =~ /^(\S+)\s+\((.+)\)\s*$/
|
37
|
-
result[$1] = $2
|
38
|
-
result
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def load_current_resource
|
43
|
-
end
|
44
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'chef/provider/lwrp_base'
|
2
|
-
require 'chef_metal/provider_action_handler'
|
3
|
-
|
4
|
-
class Chef::Provider::VagrantCluster < Chef::Provider::LWRPBase
|
5
|
-
|
6
|
-
include ChefMetal::ProviderActionHandler
|
7
|
-
|
8
|
-
use_inline_resources
|
9
|
-
|
10
|
-
def whyrun_supported?
|
11
|
-
true
|
12
|
-
end
|
13
|
-
|
14
|
-
action :create do
|
15
|
-
the_base_path = new_resource.path
|
16
|
-
ChefMetal.inline_resource(self) do
|
17
|
-
directory the_base_path
|
18
|
-
file ::File.join(the_base_path, 'Vagrantfile') do
|
19
|
-
content <<EOM
|
20
|
-
Dir.glob('#{::File.join(the_base_path, '*.vm')}') do |vm_file|
|
21
|
-
eval(IO.read(vm_file), nil, vm_file)
|
22
|
-
end
|
23
|
-
EOM
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
action :delete do
|
29
|
-
the_base_path = new_resource.path
|
30
|
-
ChefMetal.inline_resource(self) do
|
31
|
-
file ::File.join(the_base_path, 'Vagrantfile') do
|
32
|
-
action :delete
|
33
|
-
end
|
34
|
-
directory the_base_path do
|
35
|
-
action :delete
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def load_current_resource
|
41
|
-
end
|
42
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'chef_metal'
|
2
|
-
|
3
|
-
class Chef::Resource::FogKeyPair < Chef::Resource::LWRPBase
|
4
|
-
self.resource_name = 'fog_key_pair'
|
5
|
-
|
6
|
-
def initialize(*args)
|
7
|
-
super
|
8
|
-
@provisioner = ChefMetal.enclosing_provisioner
|
9
|
-
end
|
10
|
-
|
11
|
-
def after_created
|
12
|
-
# Make the credentials usable
|
13
|
-
provisioner.key_pairs[name] = self
|
14
|
-
end
|
15
|
-
|
16
|
-
actions :create, :delete, :nothing
|
17
|
-
default_action :create
|
18
|
-
|
19
|
-
attribute :provisioner
|
20
|
-
# Private key to use as input (will be generated if it does not exist)
|
21
|
-
attribute :private_key_path, :kind_of => String
|
22
|
-
# Public key to use as input (will be generated if it does not exist)
|
23
|
-
attribute :public_key_path, :kind_of => String
|
24
|
-
# List of parameters to the private_key resource used for generation of the key
|
25
|
-
attribute :private_key_options, :kind_of => Hash
|
26
|
-
|
27
|
-
# TODO what is the right default for this?
|
28
|
-
attribute :allow_overwrite, :kind_of => [TrueClass, FalseClass], :default => false
|
29
|
-
|
30
|
-
# Proc that runs after the resource completes. Called with (resource, private_key, public_key)
|
31
|
-
def after(&block)
|
32
|
-
block ? @after = block : @after
|
33
|
-
end
|
34
|
-
end
|