puppet 2.6.8 → 2.6.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +41 -0
- data/{README.rst → README.md} +17 -10
- data/conf/redhat/puppet.spec +93 -22
- data/ext/vim/README +2 -1
- data/ext/vim/ftplugin/puppet.vim +94 -0
- data/ext/vim/indent/puppet.vim +76 -0
- data/lib/puppet.rb +2 -3
- data/lib/puppet/application/agent.rb +3 -3
- data/lib/puppet/application/apply.rb +16 -5
- data/lib/puppet/configurer.rb +60 -56
- data/lib/puppet/configurer/fact_handler.rb +6 -1
- data/lib/puppet/defaults.rb +19 -0
- data/lib/puppet/file_serving/fileset.rb +1 -1
- data/lib/puppet/indirector/exec.rb +3 -3
- data/lib/puppet/indirector/queue.rb +1 -1
- data/lib/puppet/metatype/manager.rb +7 -20
- data/lib/puppet/parser/compiler.rb +17 -16
- data/lib/puppet/parser/resource.rb +18 -1
- data/lib/puppet/parser/scope.rb +2 -2
- data/lib/puppet/provider/mount/parsed.rb +1 -1
- data/lib/puppet/provider/naginator.rb +9 -1
- data/lib/puppet/provider/nameservice/directoryservice.rb +11 -8
- data/lib/puppet/provider/package/aptitude.rb +1 -0
- data/lib/puppet/rails/host.rb +7 -0
- data/lib/puppet/resource/catalog.rb +9 -3
- data/lib/puppet/transaction.rb +15 -26
- data/lib/puppet/transaction/report.rb +3 -3
- data/lib/puppet/type.rb +13 -24
- data/lib/puppet/util/queue.rb +1 -1
- data/lib/puppet/util/queue/stomp.rb +2 -2
- data/lib/puppet/util/settings/file_setting.rb +1 -0
- data/spec/integration/defaults_spec.rb +22 -0
- data/spec/integration/indirector/catalog/queue_spec.rb +2 -2
- data/spec/integration/type_spec.rb +11 -0
- data/spec/unit/application/agent_spec.rb +2 -2
- data/spec/unit/application/apply_spec.rb +62 -50
- data/spec/unit/configurer/fact_handler_spec.rb +43 -37
- data/spec/unit/configurer_spec.rb +404 -327
- data/spec/unit/file_serving/fileset_spec.rb +7 -0
- data/spec/unit/indirector/exec_spec.rb +4 -4
- data/spec/unit/indirector/node/exec_spec.rb +1 -1
- data/spec/unit/indirector/queue_spec.rb +4 -4
- data/spec/unit/node_spec.rb +1 -0
- data/spec/unit/parser/compiler_spec.rb +8 -46
- data/spec/unit/parser/resource_spec.rb +61 -3
- data/spec/unit/parser/scope_spec.rb +9 -3
- data/spec/unit/provider/nameservice/directoryservice_spec.rb +60 -0
- data/spec/unit/rails/host_spec.rb +8 -0
- data/spec/unit/resource/catalog_spec.rb +1 -1
- data/spec/unit/transaction/report_spec.rb +3 -3
- data/spec/unit/transaction_spec.rb +8 -2
- data/spec/unit/type_spec.rb +66 -0
- data/spec/unit/util/queue/stomp_spec.rb +10 -10
- data/spec/unit/util/settings/file_setting_spec.rb +4 -0
- metadata +1229 -1232
- data/README +0 -31
- data/lib/puppet/provider/nameservice/#directoryservice.rb# +0 -519
- data/lib/puppet/reference/#providers.rb# +0 -123
- data/spec/unit/indirector/certificate_status/#file_spec.rb# +0 -188
- data/spec/unit/resource/#type_collection_spec.rb# +0 -463
data/lib/puppet.rb
CHANGED
@@ -24,7 +24,7 @@ require 'puppet/util/run_mode'
|
|
24
24
|
# it's also a place to find top-level commands like 'debug'
|
25
25
|
|
26
26
|
module Puppet
|
27
|
-
PUPPETVERSION = '2.6.
|
27
|
+
PUPPETVERSION = '2.6.9'
|
28
28
|
|
29
29
|
def Puppet.version
|
30
30
|
PUPPETVERSION
|
@@ -59,8 +59,7 @@ module Puppet
|
|
59
59
|
|
60
60
|
# configuration parameter access and stuff
|
61
61
|
def self.[](param)
|
62
|
-
|
63
|
-
when :debug
|
62
|
+
if param == :debug
|
64
63
|
return Puppet::Util::Log.level == :debug
|
65
64
|
else
|
66
65
|
return @@settings[param]
|
@@ -98,7 +98,7 @@ class Puppet::Application::Agent < Puppet::Application
|
|
98
98
|
unless fingerprint = cert.fingerprint(options[:digest])
|
99
99
|
raise ArgumentError, "Could not get fingerprint for digest '#{options[:digest]}'"
|
100
100
|
end
|
101
|
-
|
101
|
+
puts fingerprint
|
102
102
|
end
|
103
103
|
|
104
104
|
def onetime
|
@@ -168,8 +168,8 @@ class Puppet::Application::Agent < Puppet::Application
|
|
168
168
|
end
|
169
169
|
|
170
170
|
def setup_listen
|
171
|
-
unless FileTest.exists?(Puppet[:
|
172
|
-
Puppet.err "Will not start without authorization file #{Puppet[:
|
171
|
+
unless FileTest.exists?(Puppet[:rest_authconfig])
|
172
|
+
Puppet.err "Will not start without authorization file #{Puppet[:rest_authconfig]}"
|
173
173
|
exit(14)
|
174
174
|
end
|
175
175
|
|
@@ -85,13 +85,18 @@ class Puppet::Application::Apply < Puppet::Application
|
|
85
85
|
end
|
86
86
|
|
87
87
|
# Collect our facts.
|
88
|
-
unless facts = Puppet::Node::Facts.find(Puppet[:
|
89
|
-
raise "Could not find facts for #{Puppet[:
|
88
|
+
unless facts = Puppet::Node::Facts.find(Puppet[:node_name_value])
|
89
|
+
raise "Could not find facts for #{Puppet[:node_name_value]}"
|
90
|
+
end
|
91
|
+
|
92
|
+
unless Puppet[:node_name_fact].empty?
|
93
|
+
Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
|
94
|
+
facts.name = Puppet[:node_name_value]
|
90
95
|
end
|
91
96
|
|
92
97
|
# Find our Node
|
93
|
-
unless node = Puppet::Node.find(Puppet[:
|
94
|
-
raise "Could not find node #{Puppet[:
|
98
|
+
unless node = Puppet::Node.find(Puppet[:node_name_value])
|
99
|
+
raise "Could not find node #{Puppet[:node_name_value]}"
|
95
100
|
end
|
96
101
|
|
97
102
|
# Merge in the facts.
|
@@ -125,7 +130,13 @@ class Puppet::Application::Apply < Puppet::Application
|
|
125
130
|
configurer = Puppet::Configurer.new
|
126
131
|
report = configurer.run(:skip_plugin_download => true, :catalog => catalog)
|
127
132
|
|
128
|
-
|
133
|
+
if not report
|
134
|
+
exit(1)
|
135
|
+
elsif options[:detailed_exitcodes] then
|
136
|
+
exit(report.exit_status)
|
137
|
+
else
|
138
|
+
exit(0)
|
139
|
+
end
|
129
140
|
rescue => detail
|
130
141
|
puts detail.backtrace if Puppet[:trace]
|
131
142
|
$stderr.puts detail.message
|
data/lib/puppet/configurer.rb
CHANGED
@@ -5,8 +5,6 @@ require 'puppet/network/http_pool'
|
|
5
5
|
require 'puppet/util'
|
6
6
|
|
7
7
|
class Puppet::Configurer
|
8
|
-
class CommandHookError < RuntimeError; end
|
9
|
-
|
10
8
|
require 'puppet/configurer/fact_handler'
|
11
9
|
require 'puppet/configurer/plugin_handler'
|
12
10
|
|
@@ -79,21 +77,11 @@ class Puppet::Configurer
|
|
79
77
|
download_plugins unless options[:skip_plugin_download]
|
80
78
|
|
81
79
|
download_fact_plugins unless options[:skip_plugin_download]
|
82
|
-
|
83
|
-
execute_prerun_command
|
84
80
|
end
|
85
81
|
|
86
82
|
# Get the remote catalog, yo. Returns nil if no catalog can be found.
|
87
|
-
def retrieve_catalog
|
88
|
-
|
89
|
-
# This is a bit complicated. We need the serialized and escaped facts,
|
90
|
-
# and we need to know which format they're encoded in. Thus, we
|
91
|
-
# get a hash with both of these pieces of information.
|
92
|
-
fact_options = facts_for_uploading
|
93
|
-
else
|
94
|
-
fact_options = {}
|
95
|
-
end
|
96
|
-
|
83
|
+
def retrieve_catalog(fact_options)
|
84
|
+
fact_options ||= {}
|
97
85
|
# First try it with no cache, then with the cache.
|
98
86
|
unless (Puppet[:use_cached_catalog] and result = retrieve_catalog_from_cache(fact_options)) or result = retrieve_new_catalog(fact_options)
|
99
87
|
if ! Puppet[:usecacheonfailure]
|
@@ -117,60 +105,73 @@ class Puppet::Configurer
|
|
117
105
|
catalog
|
118
106
|
end
|
119
107
|
|
108
|
+
# Retrieve (optionally) and apply a catalog. If a catalog is passed in
|
109
|
+
# the options, then apply that one, otherwise retrieve it.
|
110
|
+
def retrieve_and_apply_catalog(options, fact_options)
|
111
|
+
unless catalog = (options.delete(:catalog) || retrieve_catalog(fact_options))
|
112
|
+
Puppet.err "Could not retrieve catalog; skipping run"
|
113
|
+
return
|
114
|
+
end
|
115
|
+
|
116
|
+
report = options[:report]
|
117
|
+
report.configuration_version = catalog.version
|
118
|
+
|
119
|
+
benchmark(:notice, "Finished catalog run") do
|
120
|
+
catalog.apply(options)
|
121
|
+
end
|
122
|
+
|
123
|
+
report.finalize_report
|
124
|
+
report
|
125
|
+
end
|
126
|
+
|
120
127
|
# The code that actually runs the catalog.
|
121
128
|
# This just passes any options on to the catalog,
|
122
129
|
# which accepts :tags and :ignoreschedules.
|
123
130
|
def run(options = {})
|
124
|
-
begin
|
125
|
-
prepare(options)
|
126
|
-
rescue SystemExit,NoMemoryError
|
127
|
-
raise
|
128
|
-
rescue Exception => detail
|
129
|
-
puts detail.backtrace if Puppet[:trace]
|
130
|
-
Puppet.err "Failed to prepare catalog: #{detail}"
|
131
|
-
end
|
132
|
-
|
133
131
|
options[:report] ||= Puppet::Transaction::Report.new("apply")
|
134
132
|
report = options[:report]
|
135
|
-
Puppet::Util::Log.newdestination(report)
|
136
133
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
Puppet.err "Could not retrieve catalog; skipping run"
|
141
|
-
return
|
142
|
-
end
|
134
|
+
Puppet::Util::Log.newdestination(report)
|
135
|
+
begin
|
136
|
+
prepare(options)
|
143
137
|
|
144
|
-
|
138
|
+
if Puppet::Resource::Catalog.indirection.terminus_class == :rest
|
139
|
+
# This is a bit complicated. We need the serialized and escaped facts,
|
140
|
+
# and we need to know which format they're encoded in. Thus, we
|
141
|
+
# get a hash with both of these pieces of information.
|
142
|
+
fact_options = facts_for_uploading
|
143
|
+
end
|
145
144
|
|
146
|
-
|
145
|
+
# set report host name now that we have the fact
|
146
|
+
report.host = Puppet[:node_name_value]
|
147
147
|
|
148
|
-
|
149
|
-
|
150
|
-
|
148
|
+
begin
|
149
|
+
execute_prerun_command or return nil
|
150
|
+
retrieve_and_apply_catalog(options, fact_options)
|
151
|
+
rescue SystemExit,NoMemoryError
|
152
|
+
raise
|
153
|
+
rescue => detail
|
154
|
+
puts detail.backtrace if Puppet[:trace]
|
155
|
+
Puppet.err "Failed to apply catalog: #{detail}"
|
156
|
+
return nil
|
157
|
+
ensure
|
158
|
+
execute_postrun_command or return nil
|
151
159
|
end
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
160
|
+
ensure
|
161
|
+
# Make sure we forget the retained module_directories of any autoload
|
162
|
+
# we might have used.
|
163
|
+
Thread.current[:env_module_directories] = nil
|
164
|
+
|
165
|
+
# Now close all of our existing http connections, since there's no
|
166
|
+
# reason to leave them lying open.
|
167
|
+
Puppet::Network::HttpPool.clear_http_instances
|
157
168
|
end
|
158
169
|
ensure
|
159
|
-
# Make sure we forget the retained module_directories of any autoload
|
160
|
-
# we might have used.
|
161
|
-
Thread.current[:env_module_directories] = nil
|
162
|
-
|
163
|
-
# Now close all of our existing http connections, since there's no
|
164
|
-
# reason to leave them lying open.
|
165
|
-
Puppet::Network::HttpPool.clear_http_instances
|
166
|
-
execute_postrun_command
|
167
|
-
|
168
170
|
Puppet::Util::Log.close(report)
|
169
|
-
send_report(report
|
171
|
+
send_report(report)
|
170
172
|
end
|
171
173
|
|
172
|
-
def send_report(report
|
173
|
-
report.finalize_report if trans
|
174
|
+
def send_report(report)
|
174
175
|
puts report.summary if Puppet[:summarize]
|
175
176
|
save_last_run_summary(report)
|
176
177
|
report.save if Puppet[:report]
|
@@ -208,19 +209,22 @@ class Puppet::Configurer
|
|
208
209
|
end
|
209
210
|
|
210
211
|
def execute_from_setting(setting)
|
211
|
-
return if (command = Puppet[setting]) == ""
|
212
|
+
return true if (command = Puppet[setting]) == ""
|
212
213
|
|
213
214
|
begin
|
214
215
|
Puppet::Util.execute([command])
|
216
|
+
true
|
215
217
|
rescue => detail
|
216
|
-
|
218
|
+
puts detail.backtrace if Puppet[:trace]
|
219
|
+
Puppet.err "Could not run command from #{setting}: #{detail}"
|
220
|
+
false
|
217
221
|
end
|
218
222
|
end
|
219
223
|
|
220
224
|
def retrieve_catalog_from_cache(fact_options)
|
221
225
|
result = nil
|
222
226
|
@duration = thinmark do
|
223
|
-
result = Puppet::Resource::Catalog.find(Puppet[:
|
227
|
+
result = Puppet::Resource::Catalog.find(Puppet[:node_name_value], fact_options.merge(:ignore_terminus => true))
|
224
228
|
end
|
225
229
|
Puppet.notice "Using cached catalog"
|
226
230
|
result
|
@@ -233,7 +237,7 @@ class Puppet::Configurer
|
|
233
237
|
def retrieve_new_catalog(fact_options)
|
234
238
|
result = nil
|
235
239
|
@duration = thinmark do
|
236
|
-
result = Puppet::Resource::Catalog.find(Puppet[:
|
240
|
+
result = Puppet::Resource::Catalog.find(Puppet[:node_name_value], fact_options.merge(:ignore_cache => true))
|
237
241
|
end
|
238
242
|
result
|
239
243
|
rescue SystemExit,NoMemoryError
|
@@ -16,7 +16,12 @@ module Puppet::Configurer::FactHandler
|
|
16
16
|
# compile them and then "cache" them on the server.
|
17
17
|
begin
|
18
18
|
reload_facter
|
19
|
-
Puppet::Node::Facts.find(Puppet[:
|
19
|
+
facts = Puppet::Node::Facts.find(Puppet[:node_name_value])
|
20
|
+
unless Puppet[:node_name_fact].empty?
|
21
|
+
Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
|
22
|
+
facts.name = Puppet[:node_name_value]
|
23
|
+
end
|
24
|
+
facts
|
20
25
|
rescue SystemExit,NoMemoryError
|
21
26
|
raise
|
22
27
|
rescue Exception => detail
|
data/lib/puppet/defaults.rb
CHANGED
@@ -486,6 +486,25 @@ module Puppet
|
|
486
486
|
)
|
487
487
|
|
488
488
|
setdefaults(:agent,
|
489
|
+
:node_name_value => { :default => "$certname",
|
490
|
+
:desc => "The explicit value used for the node name for all requests the agent
|
491
|
+
makes to the master. WARNING: This setting is mutually exclusive with
|
492
|
+
node_name_fact. Changing this setting also requires changes to the default
|
493
|
+
auth.conf configuration on the Puppet Master. Please see
|
494
|
+
http://links.puppetlabs.com/node_name_value for more information."
|
495
|
+
},
|
496
|
+
:node_name_fact => { :default => "",
|
497
|
+
:desc => "The fact name used to determine the node name used for all requests the agent
|
498
|
+
makes to the master. WARNING: This setting is mutually exclusive with
|
499
|
+
node_name_value. Changing this setting also requires changes to the default
|
500
|
+
auth.conf configuration on the Puppet Master. Please see
|
501
|
+
http://links.puppetlabs.com/node_name_fact for more information.",
|
502
|
+
:hook => proc do |value|
|
503
|
+
if !value.empty? and Puppet[:node_name_value] != Puppet[:certname]
|
504
|
+
raise "Cannot specify both the node_name_value and node_name_fact settings"
|
505
|
+
end
|
506
|
+
end
|
507
|
+
},
|
489
508
|
:localconfig => { :default => "$statedir/localconfig",
|
490
509
|
:owner => "root",
|
491
510
|
:mode => 0660,
|
@@ -59,7 +59,7 @@ class Puppet::FileServing::Fileset
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def initialize(path, options = {})
|
62
|
-
path = path.chomp(File::SEPARATOR)
|
62
|
+
path = path.chomp(File::SEPARATOR) unless path == File::SEPARATOR
|
63
63
|
raise ArgumentError.new("Fileset paths must be fully qualified") unless File.expand_path(path) == path
|
64
64
|
|
65
65
|
@path = path
|
@@ -16,8 +16,8 @@ class Puppet::Indirector::Exec < Puppet::Indirector::Terminus
|
|
16
16
|
private
|
17
17
|
|
18
18
|
# Proxy the execution, so it's easier to test.
|
19
|
-
def execute(command)
|
20
|
-
Puppet::Util.execute(command)
|
19
|
+
def execute(command, arguments)
|
20
|
+
Puppet::Util.execute(command,arguments)
|
21
21
|
end
|
22
22
|
|
23
23
|
# Call the external command and see if it returns our output.
|
@@ -33,7 +33,7 @@ class Puppet::Indirector::Exec < Puppet::Indirector::Terminus
|
|
33
33
|
# Add our name to it.
|
34
34
|
external_command << name
|
35
35
|
begin
|
36
|
-
output = execute(external_command)
|
36
|
+
output = execute(external_command, :combine => false)
|
37
37
|
rescue Puppet::ExecutionFailure => detail
|
38
38
|
raise Puppet::Error, "Failed to find #{name} via exec: #{detail}"
|
39
39
|
end
|
@@ -36,7 +36,7 @@ class Puppet::Indirector::Queue < Puppet::Indirector::Terminus
|
|
36
36
|
def save(request)
|
37
37
|
result = nil
|
38
38
|
benchmark :info, "Queued #{indirection.name} for #{request.key}" do
|
39
|
-
result = client.
|
39
|
+
result = client.publish_message(queue, request.instance.render(:pson))
|
40
40
|
end
|
41
41
|
result
|
42
42
|
rescue => detail
|
@@ -61,10 +61,9 @@ module Manager
|
|
61
61
|
|
62
62
|
# Then create the class.
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
klass = genclass(
|
65
|
+
name,
|
66
66
|
:parent => (parent || Puppet::Type),
|
67
|
-
|
68
67
|
:overwrite => true,
|
69
68
|
:hash => @types,
|
70
69
|
:attributes => options,
|
@@ -87,14 +86,11 @@ module Manager
|
|
87
86
|
|
88
87
|
# Now set up autoload any providers that might exist for this type.
|
89
88
|
|
90
|
-
|
91
|
-
klass,
|
92
|
-
|
93
|
-
"puppet/provider/#{klass.name.to_s}"
|
94
|
-
)
|
89
|
+
klass.providerloader = Puppet::Util::Autoload.new(klass, "puppet/provider/#{klass.name.to_s}")
|
95
90
|
|
96
|
-
# We have to load everything so that we can figure out the default
|
91
|
+
# We have to load everything so that we can figure out the default provider.
|
97
92
|
klass.providerloader.loadall
|
93
|
+
klass.providify unless klass.providers.empty?
|
98
94
|
|
99
95
|
klass
|
100
96
|
end
|
@@ -103,11 +99,7 @@ module Manager
|
|
103
99
|
def rmtype(name)
|
104
100
|
# Then create the class.
|
105
101
|
|
106
|
-
|
107
|
-
name,
|
108
|
-
|
109
|
-
:hash => @types
|
110
|
-
)
|
102
|
+
klass = rmclass(name, :hash => @types)
|
111
103
|
|
112
104
|
singleton_class.send(:remove_method, "new#{name}") if respond_to?("new#{name}")
|
113
105
|
end
|
@@ -132,12 +124,7 @@ module Manager
|
|
132
124
|
# Create a loader for Puppet types.
|
133
125
|
def typeloader
|
134
126
|
unless defined?(@typeloader)
|
135
|
-
|
136
|
-
@typeloader = Puppet::Util::Autoload.new(
|
137
|
-
self,
|
138
|
-
|
139
|
-
"puppet/type", :wrap => false
|
140
|
-
)
|
127
|
+
@typeloader = Puppet::Util::Autoload.new(self, "puppet/type", :wrap => false)
|
141
128
|
end
|
142
129
|
|
143
130
|
@typeloader
|
@@ -15,15 +15,19 @@ class Puppet::Parser::Compiler
|
|
15
15
|
include Puppet::Resource::TypeCollectionHelper
|
16
16
|
|
17
17
|
def self.compile(node)
|
18
|
+
# We get these from the environment and only cache them in a thread
|
19
|
+
# variable for the duration of the compilation. If nothing else is using
|
20
|
+
# the thread, though, we can leave 'em hanging round with no ill effects,
|
21
|
+
# and this is safer than cleaning them at the end and assuming that will
|
22
|
+
# stick until the next entry to this function.
|
23
|
+
Thread.current[:known_resource_types] = nil
|
24
|
+
Thread.current[:env_module_directories] = nil
|
25
|
+
|
26
|
+
# ...and we actually do the compile now we have caching ready.
|
18
27
|
new(node).compile.to_resource
|
19
28
|
rescue => detail
|
20
29
|
puts detail.backtrace if Puppet[:trace]
|
21
30
|
raise Puppet::Error, "#{detail} on node #{node.name}"
|
22
|
-
ensure
|
23
|
-
# We get these from the environment and only cache them in a thread
|
24
|
-
# variable for the duration of the compilation.
|
25
|
-
Thread.current[:known_resource_types] = nil
|
26
|
-
Thread.current[:env_module_directories] = nil
|
27
31
|
end
|
28
32
|
|
29
33
|
attr_reader :node, :facts, :collections, :catalog, :node_scope, :resources, :relationships
|
@@ -56,23 +60,20 @@ class Puppet::Parser::Compiler
|
|
56
60
|
# Note that this will fail if the resource is not unique.
|
57
61
|
@catalog.add_resource(resource)
|
58
62
|
|
63
|
+
if resource.type.to_s.downcase != "class" && resource[:stage]
|
64
|
+
raise ArgumentError, "Only classes can set 'stage'; normal resources like #{resource} cannot change run stage"
|
65
|
+
end
|
59
66
|
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
67
|
+
# Stages should not be inside of classes. They are always a
|
68
|
+
# top-level container, regardless of where they appear in the
|
69
|
+
# manifest.
|
63
70
|
return if resource.type.to_s.downcase == "stage"
|
64
71
|
|
72
|
+
# This adds a resource to the class it lexically appears in in the
|
73
|
+
# manifest.
|
65
74
|
if resource.type.to_s.downcase != "class"
|
66
|
-
raise ArgumentError, "Only classes can set 'stage'; normal resources like #{resource} cannot change run stage" if resource[:stage]
|
67
75
|
return @catalog.add_edge(scope.resource, resource)
|
68
76
|
end
|
69
|
-
|
70
|
-
unless stage = @catalog.resource(:stage, resource[:stage] || (scope && scope.resource && scope.resource[:stage]) || :main)
|
71
|
-
raise ArgumentError, "Could not find stage #{resource[:stage] || :main} specified by #{resource}"
|
72
|
-
end
|
73
|
-
|
74
|
-
resource[:stage] ||= stage.title unless stage.title == :main
|
75
|
-
@catalog.add_edge(stage, resource)
|
76
77
|
end
|
77
78
|
|
78
79
|
# Do we use nodes found in the code, vs. the external node sources?
|