forj 1.0.1 → 1.0.2
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/.gitignore +7 -0
- data/.gitreview +4 -0
- data/Gemfile +21 -19
- data/Gemfile.lock +71 -0
- data/bin/forj +126 -83
- data/forj.gemspec +64 -0
- data/{lib → forj}/defaults.yaml +23 -1
- data/lib/appinit.rb +5 -5
- data/lib/build_tmpl/build-env.py +293 -0
- data/lib/cloud_test.rb +121 -0
- data/lib/forj-settings.rb +52 -39
- data/lib/forj/ForjCli.rb +11 -10
- data/lib/forj/ForjCore.rb +8 -6
- data/lib/forj/process/ForjProcess.rb +345 -82
- data/lib/ssh.rb +81 -20
- metadata +110 -80
- data/lib/compute.rb +0 -36
- data/lib/connection.rb +0 -144
- data/lib/down.rb +0 -60
- data/lib/forj-account.rb +0 -294
- data/lib/forj-config.rb +0 -522
- data/lib/helpers.rb +0 -56
- data/lib/lib-forj/lib/core/core.rb +0 -1740
- data/lib/lib-forj/lib/core/definition.rb +0 -441
- data/lib/lib-forj/lib/core/definition_internal.rb +0 -306
- data/lib/lib-forj/lib/core_process/CloudProcess.rb +0 -334
- data/lib/lib-forj/lib/core_process/global_process.rb +0 -406
- data/lib/lib-forj/lib/core_process/network_process.rb +0 -603
- data/lib/lib-forj/lib/lib-forj.rb +0 -37
- data/lib/lib-forj/lib/providers/hpcloud/Hpcloud.rb +0 -419
- data/lib/lib-forj/lib/providers/hpcloud/compute.rb +0 -108
- data/lib/lib-forj/lib/providers/hpcloud/network.rb +0 -117
- data/lib/lib-forj/lib/providers/hpcloud/security_groups.rb +0 -67
- data/lib/lib-forj/lib/providers/templates/compute.rb +0 -42
- data/lib/lib-forj/lib/providers/templates/core.rb +0 -61
- data/lib/lib-forj/lib/providers/templates/network.rb +0 -33
- data/lib/log.rb +0 -162
- data/lib/network.rb +0 -365
- data/lib/repositories.rb +0 -222
- data/lib/security.rb +0 -207
- data/lib/ssh.sh +0 -185
- data/spec/connection_spec.rb +0 -52
- data/spec/forj-config_spec.rb +0 -237
- data/spec/repositories_spec.rb +0 -50
data/lib/helpers.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
|
18
|
-
require 'fileutils'
|
19
|
-
|
20
|
-
module Helpers
|
21
|
-
def get_home_path
|
22
|
-
File.expand_path('~')
|
23
|
-
end
|
24
|
-
|
25
|
-
def create_directory(path)
|
26
|
-
unless File.directory?(path)
|
27
|
-
Dir.mkdir path
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def dir_exists?(path)
|
32
|
-
if File.exists?(path)
|
33
|
-
if not File.directory?(path)
|
34
|
-
msg = "'%s' is not a directory. Please fix it." % path
|
35
|
-
if $FORJ_LOGGER
|
36
|
-
Logging.fatal(1, msg)
|
37
|
-
else
|
38
|
-
raise msg
|
39
|
-
end
|
40
|
-
end
|
41
|
-
if not File.readable?(path) or not File.writable?(path) or not File.executable?(path)
|
42
|
-
msg = "%s is not a valid directory. Check permissions and fix it." % path
|
43
|
-
if $FORJ_LOGGER
|
44
|
-
Logging.fatal(1, msg)
|
45
|
-
else
|
46
|
-
raise msg
|
47
|
-
end
|
48
|
-
end
|
49
|
-
return true
|
50
|
-
end
|
51
|
-
false
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
@@ -1,1740 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
|
18
|
-
|
19
|
-
# Those classes describes :
|
20
|
-
# - processes (BaseProcess) : How to create/delete/edit/query object.
|
21
|
-
# - controler (BaseControler) : If a provider is defined, define how will do object creation/etc...
|
22
|
-
# - definition(BaseDefinition): Functions to declare objects, query/data mapping and setup
|
23
|
-
# this task to make it to work.
|
24
|
-
|
25
|
-
module ForjLib
|
26
|
-
def ForjLib::debug(iLevel, sMsg)
|
27
|
-
if iLevel <= $LIB_FORJ_DEBUG
|
28
|
-
Logging.debug("-%s- %s" % [iLevel, sMsg])
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
module ForjLib
|
34
|
-
class ForjLib::Data
|
35
|
-
|
36
|
-
def initialize(oType = :object)
|
37
|
-
# Support :data for single object data
|
38
|
-
# :list for a list of object data
|
39
|
-
oType = :data if not [:list, :object, :data].include?(oType)
|
40
|
-
@oType = oType
|
41
|
-
case oType
|
42
|
-
when :data, :object
|
43
|
-
@data = new_object
|
44
|
-
when :list
|
45
|
-
@data = new_object_list
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def type?()
|
50
|
-
@oType
|
51
|
-
end
|
52
|
-
|
53
|
-
def object_type?()
|
54
|
-
@data[:object_type]
|
55
|
-
end
|
56
|
-
|
57
|
-
def set(oObj, sObjType = nil, hQuery = {})
|
58
|
-
if oObj.is_a?(ForjLib::Data)
|
59
|
-
oType = oObj.type?
|
60
|
-
case oType
|
61
|
-
when :data, :object
|
62
|
-
@data[:object_type] = ((sObjType.nil?)? (oObj.object_type?) : sObjType)
|
63
|
-
@data[:object] = oObj.get(:object)
|
64
|
-
@data[:attrs] = oObj.get(:attrs)
|
65
|
-
when :list
|
66
|
-
@data[:object_type] = ((sObjType.nil?)? (oObj.object_type?) : sObjType)
|
67
|
-
@data[:object] = oObj.get(:object)
|
68
|
-
@data[:list] = oObj.get(:list)
|
69
|
-
@data[:query] = oObj.get(:query)
|
70
|
-
end
|
71
|
-
return self
|
72
|
-
end
|
73
|
-
|
74
|
-
# while saving the object, a mapping work is done?
|
75
|
-
case @oType
|
76
|
-
when :data, :object
|
77
|
-
@data[:object_type] = sObjType
|
78
|
-
@data[:object] = oObj
|
79
|
-
@data[:attrs] = yield(sObjType, oObj)
|
80
|
-
when :list
|
81
|
-
@data[:object] = oObj
|
82
|
-
@data[:object_type] = sObjType
|
83
|
-
@data[:query] = hQuery
|
84
|
-
unless oObj.nil?
|
85
|
-
begin
|
86
|
-
oObj.each { | oObject |
|
87
|
-
next if oObject.nil?
|
88
|
-
begin
|
89
|
-
oDataObject = ForjLib::Data.new(:object)
|
90
|
-
|
91
|
-
oDataObject.set(oObject, sObjType) { |sObjectType, oObject|
|
92
|
-
yield(sObjectType, oObject)
|
93
|
-
}
|
94
|
-
@data[:list] << oDataObject
|
95
|
-
rescue => e
|
96
|
-
raise ForjError.new(), "'%s' Mapping attributes issue.\n%s" % [sObjType, e.message]
|
97
|
-
end
|
98
|
-
}
|
99
|
-
rescue => e
|
100
|
-
raise ForjError.new(), "each function is not supported by '%s'.\n%s" % [oObj.class, e.message]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
self
|
105
|
-
end
|
106
|
-
|
107
|
-
def type=(sObjType)
|
108
|
-
return self if self.empty?
|
109
|
-
@data[:object_type] = sObjType
|
110
|
-
self
|
111
|
-
end
|
112
|
-
|
113
|
-
def [](*key)
|
114
|
-
get(*key)
|
115
|
-
end
|
116
|
-
|
117
|
-
def []=(*key, value)
|
118
|
-
return false if @oType == :list
|
119
|
-
rhSet(@data, value, :attrs, key)
|
120
|
-
true
|
121
|
-
end
|
122
|
-
|
123
|
-
def get(*key)
|
124
|
-
return @data if key.length == 0
|
125
|
-
case @oType
|
126
|
-
when :data, :object # Return only attrs or the real object.
|
127
|
-
return @data[key[0]] if key[0] == :object
|
128
|
-
return rhGet(@data, key) if key[0] == :attrs
|
129
|
-
rhGet(@data, :attrs, key)
|
130
|
-
when :list
|
131
|
-
return @data[key[0]] if [:object, :query].include?(key[0])
|
132
|
-
return @data[:list][key[0]] if key.length == 1
|
133
|
-
@data[:list][key[0]][key[1..-1]] # can Return only attrs or the real object.
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def exist?(*key)
|
138
|
-
case @oType
|
139
|
-
when :data, :object
|
140
|
-
return true if key[0] == :object and @data.key?(key[0])
|
141
|
-
return true if key[0] == :attrs and rhExist?(@data, key)
|
142
|
-
(rhExist?(@data, :attrs, key) == key.length+1)
|
143
|
-
when :list
|
144
|
-
return true if key[0] == :object and @data.key?(key[0])
|
145
|
-
(rhExist?(@data[:list][key[0]], :attrs, key[1..-1]) == key.length)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def empty?()
|
150
|
-
@data[:object].nil?
|
151
|
-
end
|
152
|
-
|
153
|
-
def nil?()
|
154
|
-
# Obsolete Use empty? instead.
|
155
|
-
@data[:object].nil?
|
156
|
-
end
|
157
|
-
|
158
|
-
def length()
|
159
|
-
case @oType
|
160
|
-
when :data
|
161
|
-
return 0 if self.nil?
|
162
|
-
1
|
163
|
-
when :list
|
164
|
-
@data[:list].length
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def each(sData = :list)
|
169
|
-
to_remove = []
|
170
|
-
return nil if @oType != :list or not [:object, :list].include?(sData)
|
171
|
-
|
172
|
-
@data[:list].each { |elem|
|
173
|
-
sAction = yield (elem)
|
174
|
-
case sAction
|
175
|
-
when :remove
|
176
|
-
to_remove << elem
|
177
|
-
end
|
178
|
-
}
|
179
|
-
if to_remove.length > 0
|
180
|
-
to_remove.each { | elem |
|
181
|
-
@data[:list].delete(elem)
|
182
|
-
}
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
def each_index(sData = :list)
|
187
|
-
to_remove = []
|
188
|
-
return nil if @oType != :list or not [:object, :list].include?(sData)
|
189
|
-
|
190
|
-
@data[:list].each_index { |iIndex|
|
191
|
-
sAction = yield (iIndex)
|
192
|
-
case sAction
|
193
|
-
when :remove
|
194
|
-
to_remove << @data[:list][iIndex]
|
195
|
-
end
|
196
|
-
}
|
197
|
-
if to_remove.length > 0
|
198
|
-
to_remove.each { | elem |
|
199
|
-
@data[:list].delete(elem)
|
200
|
-
}
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def registered?()
|
205
|
-
@bRegister
|
206
|
-
end
|
207
|
-
|
208
|
-
def register()
|
209
|
-
@bRegister = true
|
210
|
-
self
|
211
|
-
end
|
212
|
-
|
213
|
-
def unregister()
|
214
|
-
@bRegister = false
|
215
|
-
self
|
216
|
-
end
|
217
|
-
private
|
218
|
-
|
219
|
-
def new_object_list
|
220
|
-
{
|
221
|
-
:object => nil,
|
222
|
-
:object_type => nil,
|
223
|
-
:list => [],
|
224
|
-
:query => nil
|
225
|
-
}
|
226
|
-
end
|
227
|
-
|
228
|
-
def new_object
|
229
|
-
oCoreObject = {
|
230
|
-
:object_type => nil,
|
231
|
-
:attrs => {},
|
232
|
-
:object => nil,
|
233
|
-
}
|
234
|
-
end
|
235
|
-
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
class ForjError < RuntimeError
|
240
|
-
attr_reader :ForjMsg
|
241
|
-
|
242
|
-
def initialize(message = nil)
|
243
|
-
@ForjMsg = message
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
# Class to handle key or keypath on needs
|
248
|
-
class KeyPath
|
249
|
-
|
250
|
-
def initialize(sKeyPath = nil)
|
251
|
-
|
252
|
-
@keypath = []
|
253
|
-
self.set sKeyPath
|
254
|
-
end
|
255
|
-
|
256
|
-
def key=(sKeyPath)
|
257
|
-
self.set(sKeyPath)
|
258
|
-
end
|
259
|
-
|
260
|
-
def set(sKeyPath)
|
261
|
-
|
262
|
-
if sKeyPath.is_a?(Symbol)
|
263
|
-
@keypath = [ sKeyPath]
|
264
|
-
elsif sKeyPath.is_a?(Array)
|
265
|
-
@keypath = sKeyPath
|
266
|
-
elsif sKeyPath.is_a?(String)
|
267
|
-
if /[^\\\/]?\/[^\/]/ =~ sKeyPath or /:[^:\/]/ =~ sKeyPath
|
268
|
-
# keypath to interpret
|
269
|
-
aResult = sKeyPath.split('/')
|
270
|
-
aResult.each_index { | iIndex |
|
271
|
-
next if not aResult[iIndex].is_a?(String)
|
272
|
-
aResult[iIndex] = aResult[iIndex][1..-1].to_sym if aResult[iIndex][0] == ":"
|
273
|
-
}
|
274
|
-
@keypath = aResult
|
275
|
-
else
|
276
|
-
@keypath = [sKeyPath]
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
def aTree()
|
282
|
-
@keypath
|
283
|
-
end
|
284
|
-
|
285
|
-
def sFullPath()
|
286
|
-
return nil if @keypath.length == 0
|
287
|
-
aKeyAccess = @keypath.clone
|
288
|
-
aKeyAccess.each_index { |iIndex|
|
289
|
-
next if not aKeyAccess[iIndex].is_a?(Symbol)
|
290
|
-
aKeyAccess[iIndex] = ":" + aKeyAccess[iIndex].to_s
|
291
|
-
}
|
292
|
-
aKeyAccess.join('/')
|
293
|
-
end
|
294
|
-
|
295
|
-
def to_s
|
296
|
-
return nil if @keypath.length == 0
|
297
|
-
aKeyAccess = @keypath.clone
|
298
|
-
aKeyAccess.each_index { |iIndex|
|
299
|
-
next if not aKeyAccess[iIndex].is_a?(Symbol)
|
300
|
-
aKeyAccess[iIndex] = aKeyAccess[iIndex].to_s
|
301
|
-
}
|
302
|
-
aKeyAccess.join('/')
|
303
|
-
end
|
304
|
-
|
305
|
-
def sKey(iIndex = -1)
|
306
|
-
return nil if @keypath.length == 0
|
307
|
-
@keypath[iIndex] if self.length >= 1
|
308
|
-
end
|
309
|
-
|
310
|
-
def length()
|
311
|
-
@keypath.length
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
# This is the main class definition.
|
316
|
-
# It drives creation of High level cloud class object, like servers
|
317
|
-
# Initialization requires a Configuration Object (ForjConfig) and the Account to load.
|
318
|
-
# Account is loaded with ForjAccount Object.
|
319
|
-
# During ForjCloud initialization, general options + account options are loaded.
|
320
|
-
|
321
|
-
# For example, to create a server
|
322
|
-
|
323
|
-
# oCloud = ForjCloud.new(oConfig, 'myhpcloud')
|
324
|
-
# oConfig.set(:server_name,'myservername')
|
325
|
-
# oCloud.Create(:server)
|
326
|
-
|
327
|
-
# Most of data are predefined from account or general config.
|
328
|
-
# If some required value are missing, an error is reported.
|
329
|
-
# A Process Object can be defined, in order to add some process features, like :maestro_server
|
330
|
-
|
331
|
-
# Based Forj Object to use, with a process and (or not) a controler.
|
332
|
-
class ForjObject
|
333
|
-
|
334
|
-
# ForjObject parameters are:
|
335
|
-
# oForjConfig : Required. an instance of a configuration system which HAVE to provide
|
336
|
-
# 2 kind of functions:
|
337
|
-
# - set (key, value) and []=(key, value)
|
338
|
-
# From processes, you can set a runtime data with:
|
339
|
-
# config.set(key, value)
|
340
|
-
# OR
|
341
|
-
# config[key] = value
|
342
|
-
#
|
343
|
-
# - get (key, default) and [](key, default)
|
344
|
-
# default is an optional value.
|
345
|
-
# From processes, you can get a data (runtime/account/config.yaml or defaults.yaml) with:
|
346
|
-
# config.get(key)
|
347
|
-
# OR
|
348
|
-
# config[key]
|
349
|
-
|
350
|
-
# sProcessClass: Required. string or symbol. Is the name of ProcessClass to use.
|
351
|
-
# This class is dynamically loaded and derived from BaseProcess class.
|
352
|
-
# It loads the Process class content from a file '$CORE_PROCESS_PATH/<sProcessClass>.rb'
|
353
|
-
# If sProcessClass is a file path, this file will be loaded as a ruby include.
|
354
|
-
|
355
|
-
# <sProcessClass>.rb file name is case sensible and respect RUBY Class name convention
|
356
|
-
|
357
|
-
# sControllerClass: Optional. string or symbol. Is the name of ControlerClass to use.
|
358
|
-
# This class is dynamically loaded and derived from BaseControler class.
|
359
|
-
# It loads the Controler class content from a file '$PROVIDER_PATH/<sControlerClass>.rb'
|
360
|
-
#
|
361
|
-
# The provider can redefine partially or totally some processes
|
362
|
-
# ForjObject will load those redefinition from file:
|
363
|
-
# '$PROVIDER_PATH/<sControlerClass>Process.rb'
|
364
|
-
|
365
|
-
# <sControllerClass>.rb or <sControllerClass>Process.rb file name is case sensible and respect RUBY Class name convention
|
366
|
-
|
367
|
-
attr_reader :config
|
368
|
-
|
369
|
-
|
370
|
-
def initialize(oForjConfig, processesClass = nil, sControllerClass = nil)
|
371
|
-
# Loading ProcessClass
|
372
|
-
# Create Process derived from respectively BaseProcess
|
373
|
-
@config = oForjConfig
|
374
|
-
|
375
|
-
if processesClass.nil?
|
376
|
-
aProcessesClass = []
|
377
|
-
elsif not processesClass.is_a?(Array)
|
378
|
-
aProcessesClass = [processesClass]
|
379
|
-
else
|
380
|
-
aProcessesClass = processesClass
|
381
|
-
end
|
382
|
-
|
383
|
-
cBaseProcess = BaseProcess
|
384
|
-
cProcessClass = nil
|
385
|
-
|
386
|
-
aProcessesClass.each { | sProcessClass |
|
387
|
-
ForjLib.debug(1, "Loading Process '%s'" % sProcessClass)
|
388
|
-
|
389
|
-
# And load the content from the <sProcessClass>.rb
|
390
|
-
if sProcessClass.is_a?(Symbol)
|
391
|
-
sFile = File.join($CORE_PROCESS_PATH, sProcessClass.to_s + '.rb')
|
392
|
-
else
|
393
|
-
if sProcessClass.include?('/')
|
394
|
-
# Consider a path to the process file. File name is the name of the class.
|
395
|
-
sPath = File.dirname(File.expand_path(sProcessClass))
|
396
|
-
file = File.basename(sProcessClass)
|
397
|
-
file['.rb'] = '' if file['.rb']
|
398
|
-
sProcessClass = file
|
399
|
-
sProcessClass = file.capitalize if (/[A-Z]/ =~ file) != 0
|
400
|
-
else
|
401
|
-
sPath = $CORE_PROCESS_PATH
|
402
|
-
end
|
403
|
-
sFile = File.join(sPath, sProcessClass + '.rb')
|
404
|
-
end
|
405
|
-
if File.exists?(sFile)
|
406
|
-
cNewClass = Class.new(cBaseProcess)
|
407
|
-
sProcessClass = "%sProcess" % sProcessClass if not /Process$/ =~ sProcessClass
|
408
|
-
ForjLib.debug(1, "Declaring Process '%s'" % sProcessClass)
|
409
|
-
cBaseProcess = Object.const_set(sProcessClass, cNewClass)
|
410
|
-
cProcessClass = sProcessClass
|
411
|
-
BaseDefinition.current_process(cBaseProcess)
|
412
|
-
load sFile
|
413
|
-
else
|
414
|
-
Logging.warning("Process file definition '%s' is missing. " % sFile)
|
415
|
-
end
|
416
|
-
}
|
417
|
-
|
418
|
-
if sControllerClass
|
419
|
-
ForjLib.debug(1, "Loading Controler/definition '%s'" % sControllerClass)
|
420
|
-
# Add Provider Object -------------
|
421
|
-
sProviderClass = sControllerClass.capitalize
|
422
|
-
|
423
|
-
# Initialize an empty class derived from BaseDefinition.
|
424
|
-
# This to ensure provider Class will be derived from this Base Class
|
425
|
-
# If this class is derived from a different Class, ruby will raise an error.
|
426
|
-
|
427
|
-
# Create Definition and Controler derived from respectively BaseDefinition and BaseControler
|
428
|
-
cBaseDefinition = Class.new(BaseDefinition)
|
429
|
-
# Finally, name that class!
|
430
|
-
Object.const_set sProviderClass, cBaseDefinition
|
431
|
-
|
432
|
-
cBaseControler = Class.new(BaseController)
|
433
|
-
Object.const_set sProviderClass + 'Controller', cBaseControler
|
434
|
-
|
435
|
-
# Loading Provider base file. This file should load a class
|
436
|
-
# which have the same name as the file.
|
437
|
-
if sControllerClass.include?('/')
|
438
|
-
# Consider a path to the process file. File name is the name of the class.
|
439
|
-
sPath = File.dirname(File.expand_path(sControllerClass))
|
440
|
-
file = File.basename(sControllerClass)
|
441
|
-
file['.rb'] = '' if file['.rb']
|
442
|
-
sControllerClass = file
|
443
|
-
else
|
444
|
-
sPath = File.join($PROVIDERS_PATH, sControllerClass)
|
445
|
-
end
|
446
|
-
sFile = File.join(sPath, sProviderClass + '.rb')
|
447
|
-
if File.exists?(sFile)
|
448
|
-
load sFile
|
449
|
-
else
|
450
|
-
raise ForjError.new(), "Provider file definition '%s' is missing. Cannot go on" % sFile
|
451
|
-
end
|
452
|
-
|
453
|
-
#cForjBaseCloud = Class.new(ForjBaseCloud)
|
454
|
-
# Finally, name that class!
|
455
|
-
#Object.const_set sProviderClass, cForjBaseCloud
|
456
|
-
|
457
|
-
# Identify Provider Classes. Search for
|
458
|
-
# - Definition Class (sProviderClass) - Contains ForjClass Object
|
459
|
-
# - Controller Class (sProviderClass + 'Controller') - Provider Cloud controler object
|
460
|
-
|
461
|
-
# Search for Definition Class
|
462
|
-
begin
|
463
|
-
# Get it from Objects
|
464
|
-
oDefClass = Object.const_get(sProviderClass)
|
465
|
-
rescue
|
466
|
-
raise ForjError.new(), 'ForjCloud: Unable to find class "%s"' % sProviderClass
|
467
|
-
end
|
468
|
-
|
469
|
-
# Search for Controler Class
|
470
|
-
# - Process Class (sProviderClass + 'Process') - Provider Process object if defined
|
471
|
-
begin
|
472
|
-
# Get the same one suffixed with 'Provider' from Objects
|
473
|
-
oCoreObjectControllerClass = Object.const_get(sProviderClass + 'Controller')
|
474
|
-
rescue
|
475
|
-
raise ForjError.new(), 'ForjCloud: Unable to find class "%s"' % sProviderClass + 'Controller'
|
476
|
-
end
|
477
|
-
|
478
|
-
# Then, we create an BaseCloud Object with 2 objects joined:
|
479
|
-
# ForjAccount and a BaseControler Object type
|
480
|
-
|
481
|
-
|
482
|
-
else
|
483
|
-
oCoreObjectControllerClass = nil
|
484
|
-
end
|
485
|
-
|
486
|
-
# Add Process management object ---------------
|
487
|
-
unless cProcessClass.nil?
|
488
|
-
begin
|
489
|
-
oBaseProcessDefClass = Object.const_get(cProcessClass)
|
490
|
-
rescue
|
491
|
-
raise ForjError.new(), 'ForjCloud: Unable to find class "%s"' % cProcessClass
|
492
|
-
end
|
493
|
-
else
|
494
|
-
raise ForjError.new(), 'ForjCloud: No valid process loaded. Aborting.'
|
495
|
-
end
|
496
|
-
# Ex: Hpcloud(ForjAccount, HpcloudProvider)
|
497
|
-
if oCoreObjectControllerClass
|
498
|
-
@oCoreObject = oDefClass.new(oForjConfig, oBaseProcessDefClass.new(), oCoreObjectControllerClass.new())
|
499
|
-
else
|
500
|
-
@oCoreObject = oDefClass.new(oForjConfig, oBaseProcessDefClass.new())
|
501
|
-
end
|
502
|
-
|
503
|
-
end
|
504
|
-
|
505
|
-
def Connect(oCloudObj)
|
506
|
-
return nil if not oCloudObj or not @oCoreObject
|
507
|
-
@oCoreObject.Connect(oCloudObj)
|
508
|
-
end
|
509
|
-
|
510
|
-
def Create(oCloudObj)
|
511
|
-
return nil if not oCloudObj or not @oCoreObject
|
512
|
-
@oCoreObject.Create(oCloudObj)
|
513
|
-
end
|
514
|
-
|
515
|
-
def Delete(oCloudObj)
|
516
|
-
return nil if not oCloudObj or not @oCoreObject
|
517
|
-
|
518
|
-
@oCoreObject.Delete(oCloudObj)
|
519
|
-
end
|
520
|
-
|
521
|
-
def Query(oCloudObj, sQuery)
|
522
|
-
return nil if not oCloudObj or not @oCoreObject
|
523
|
-
|
524
|
-
@oCoreObject.Query(oCloudObj, sQuery)
|
525
|
-
end
|
526
|
-
|
527
|
-
def Get(oCloudObj, sId)
|
528
|
-
return nil if not oCloudObj or not @oCoreObject or sId.nil?
|
529
|
-
|
530
|
-
@oCoreObject.Get(oCloudObj, sId)
|
531
|
-
end
|
532
|
-
|
533
|
-
def Update(oCloudObj)
|
534
|
-
return nil if not oCloudObj or not @oCoreObject
|
535
|
-
|
536
|
-
@oCoreObject.Update(oCloudObj)
|
537
|
-
end
|
538
|
-
|
539
|
-
# Function used to ask users about setting up his account.
|
540
|
-
def Setup(oCloudObj, sAccountName = nil)
|
541
|
-
return nil if not oCloudObj or not @oCoreObject
|
542
|
-
@oCoreObject.Setup(oCloudObj, sAccountName)
|
543
|
-
end
|
544
|
-
end
|
545
|
-
|
546
|
-
# This class based on generic ForjObject, defines a Cloud Process to use.
|
547
|
-
class ForjCloud < ForjObject
|
548
|
-
def initialize(oConfig, sAccount = nil, aProcesses = [])
|
549
|
-
|
550
|
-
unless oConfig.is_a?(ForjAccount)
|
551
|
-
oForjAccount = ForjAccount.new(oConfig)
|
552
|
-
unless sAccount.nil?
|
553
|
-
oForjAccount.ac_load(sAccount)
|
554
|
-
end
|
555
|
-
else
|
556
|
-
oForjAccount = oConfig
|
557
|
-
end
|
558
|
-
aProcessList = [:CloudProcess]
|
559
|
-
|
560
|
-
sControllerMod = oForjAccount.get(:provider_name)
|
561
|
-
raise ForjError.new(), "Provider_name not set. Unable to create instance ForjCloud." if sControllerMod.nil?
|
562
|
-
|
563
|
-
sControllerProcessMod = File.join($PROVIDERS_PATH, sControllerMod, sControllerMod.capitalize + "Process.rb")
|
564
|
-
if File.exist?(sControllerProcessMod)
|
565
|
-
aProcessList << sControllerProcessMod
|
566
|
-
else
|
567
|
-
ForjLib.debug(1, "No Provider process defined. File '%s' not found." % sControllerProcessMod)
|
568
|
-
end
|
569
|
-
|
570
|
-
super(oForjAccount, aProcessList.concat(aProcesses), sControllerMod)
|
571
|
-
end
|
572
|
-
end
|
573
|
-
|
574
|
-
|
575
|
-
# class describing generic Object Process
|
576
|
-
# Ex: How to get a Network Object (ie: get a network or create it if missing)
|
577
|
-
class BaseProcess
|
578
|
-
def initialize()
|
579
|
-
@oDefinition = nil
|
580
|
-
end
|
581
|
-
|
582
|
-
def set_BaseObject(oDefinition)
|
583
|
-
@oDefinition = oDefinition
|
584
|
-
end
|
585
|
-
private
|
586
|
-
|
587
|
-
def query_cache_cleanup(sObjectType)
|
588
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
589
|
-
@oDefinition.query_cleanup(sObjectType)
|
590
|
-
end
|
591
|
-
|
592
|
-
def object_cache_cleanup(sObjectType)
|
593
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
594
|
-
@oDefinition.object_cleanup(sObjectType)
|
595
|
-
end
|
596
|
-
|
597
|
-
def controler
|
598
|
-
raise ForjError.new(), "No Controler object loaded." if not @oDefinition
|
599
|
-
@oDefinition
|
600
|
-
end
|
601
|
-
|
602
|
-
def object
|
603
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
604
|
-
@oDefinition
|
605
|
-
end
|
606
|
-
|
607
|
-
def format_object(sObjectType, oMiscObj)
|
608
|
-
|
609
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
610
|
-
@oDefinition.format_object(sObjectType, oMiscObj)
|
611
|
-
end
|
612
|
-
|
613
|
-
def format_query(sObjectType, oMiscObj, hQuery)
|
614
|
-
|
615
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
616
|
-
@oDefinition.format_list(sObjectType, oMiscObj, hQuery)
|
617
|
-
end
|
618
|
-
|
619
|
-
def DataObjects(sObjectType, *key)
|
620
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
621
|
-
@oDefinition.DataObjects(sObjectType, *key)
|
622
|
-
end
|
623
|
-
|
624
|
-
def get_data(oObj, *key)
|
625
|
-
|
626
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
627
|
-
@oDefinition.get_data(oObj, :attrs, key)
|
628
|
-
end
|
629
|
-
|
630
|
-
def register(oObject, sObjectType = nil)
|
631
|
-
|
632
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
633
|
-
@oDefinition.register(oObject, sObjectType)
|
634
|
-
end
|
635
|
-
|
636
|
-
def config
|
637
|
-
raise ForjError.new(), "No Base object loaded." if not @oDefinition
|
638
|
-
@oDefinition.config
|
639
|
-
end
|
640
|
-
|
641
|
-
def query_single(sCloudObj, oList, sQuery, name, sInfoMsg = {})
|
642
|
-
oList = controler.query(sCloudObj, sQuery)
|
643
|
-
sInfo = {
|
644
|
-
:notfound => "No %s '%s' found",
|
645
|
-
:checkmatch => "Found 1 %s. checking exact match for '%s'.",
|
646
|
-
:nomatch => "No %s '%s' match",
|
647
|
-
:found => "Found %s '%s'.",
|
648
|
-
:more => "Found several %s. Searching for '%s'.",
|
649
|
-
:items_form => "%s",
|
650
|
-
:items => [:name]
|
651
|
-
}
|
652
|
-
sInfo[:notfound] = sInfoMsg[:notfound] if sInfoMsg.key?(:notfound)
|
653
|
-
sInfo[:checkmatch] = sInfoMsg[:checkmatch] if sInfoMsg.key?(:checkmatch)
|
654
|
-
sInfo[:nomatch] = sInfoMsg[:nomatch] if sInfoMsg.key?(:nomatch)
|
655
|
-
sInfo[:found] = sInfoMsg[:found] if sInfoMsg.key?(:found)
|
656
|
-
sInfo[:more] = sInfoMsg[:more] if sInfoMsg.key?(:more)
|
657
|
-
sInfo[:items] = sInfoMsg[:items] if sInfoMsg.key?(:items)
|
658
|
-
sInfo[:items_form] = sInfoMsg[:items_form] if sInfoMsg.key?(:items_form)
|
659
|
-
case oList.length()
|
660
|
-
when 0
|
661
|
-
Logging.info( sInfo[:notfound] % [sCloudObj, name] )
|
662
|
-
oList
|
663
|
-
when 1
|
664
|
-
ForjLib.debug(2, sInfo[:checkmatch] % [sCloudObj, name])
|
665
|
-
element = nil
|
666
|
-
oList.each { | oElem |
|
667
|
-
bFound = true
|
668
|
-
sQuery.each { | key, value |
|
669
|
-
if oElem[key] != value
|
670
|
-
bFound = false
|
671
|
-
break
|
672
|
-
end
|
673
|
-
}
|
674
|
-
:remove if not bFound
|
675
|
-
}
|
676
|
-
if oList.length == 0
|
677
|
-
Logging.info(sInfo[:nomatch] % [sCloudObj, name])
|
678
|
-
else
|
679
|
-
sItems = []
|
680
|
-
if sInfo[:items].is_a?(Array)
|
681
|
-
sInfo[:items].each { | key |
|
682
|
-
sItems << oList[0, key]
|
683
|
-
}
|
684
|
-
else
|
685
|
-
sItems << oList[0, sInfo[:items]]
|
686
|
-
end
|
687
|
-
sItem = sInfo[:items_form] % sItems
|
688
|
-
Logging.info(sInfo[:found] % [sCloudObj, sItem])
|
689
|
-
end
|
690
|
-
oList
|
691
|
-
else
|
692
|
-
ForjLib.debug(2, sInfo[:more] % [sCloudObj, name])
|
693
|
-
# Looping to find the one corresponding
|
694
|
-
element = nil
|
695
|
-
oList.each { | oElem |
|
696
|
-
bFound = true
|
697
|
-
sQuery.each { | key, value |
|
698
|
-
if oElem[key] != value
|
699
|
-
bFound = false
|
700
|
-
break
|
701
|
-
end
|
702
|
-
}
|
703
|
-
:remove if not bFound
|
704
|
-
}
|
705
|
-
if oList.length == 0
|
706
|
-
Logging.info(sInfo[:notfound] % [sCloudObj, name])
|
707
|
-
else
|
708
|
-
sItems = []
|
709
|
-
if sInfo[:items].is_a?(Array)
|
710
|
-
sInfo[:items].each { | key |
|
711
|
-
sItems << oList[0, key]
|
712
|
-
}
|
713
|
-
else
|
714
|
-
sItems << oList[0, sInfo[:items]]
|
715
|
-
end
|
716
|
-
sItem = sInfo[:items_form] % sItems
|
717
|
-
Logging.info(sInfo[:found] % [sCloudObj, sItem])
|
718
|
-
end
|
719
|
-
oList
|
720
|
-
end
|
721
|
-
end
|
722
|
-
end
|
723
|
-
|
724
|
-
|
725
|
-
class BaseController
|
726
|
-
# Default handlers which needs to be defined by the cloud controller,
|
727
|
-
# called by BaseDefinition Create, Delete, Get, Query and Update functions.
|
728
|
-
def connect(sObjectType, hParams)
|
729
|
-
raise ForjError.new(), "connect has not been redefined by the controller '%s'" % self.class
|
730
|
-
end
|
731
|
-
|
732
|
-
def create(sObjectType, hParams)
|
733
|
-
raise ForjError.new(), "create_object has not been redefined by the controller '%s'" % self.class
|
734
|
-
end
|
735
|
-
|
736
|
-
def delete(sObjectType, hParams)
|
737
|
-
raise ForjError.new(), "delete_object has not been redefined by the controller '%s'" % self.class
|
738
|
-
end
|
739
|
-
|
740
|
-
def get(sObjectType, sUniqId, hParams)
|
741
|
-
raise ForjError.new(), "get_object has not been redefined by the controller '%s'" % self.class
|
742
|
-
end
|
743
|
-
|
744
|
-
def query(sObjectType, sQuery, hParams)
|
745
|
-
raise ForjError.new(), "query_object has not been redefined by the controller '%s'" % self.class
|
746
|
-
end
|
747
|
-
|
748
|
-
def update(sObjectType, oObject, hParams)
|
749
|
-
raise ForjError.new(), "update_object has not been redefined by the controller '%s'" % self.class
|
750
|
-
end
|
751
|
-
|
752
|
-
def forjError(msg)
|
753
|
-
raise ForjError.new(), "%s: %s" % [self.class, msg]
|
754
|
-
end
|
755
|
-
|
756
|
-
def required?(oParams, key)
|
757
|
-
raise ForjError.new(), "%s: %s is not set." % [self.class, key] if not oParams.exist?(key)
|
758
|
-
end
|
759
|
-
end
|
760
|
-
|
761
|
-
# represent an object or a list of object
|
762
|
-
|
763
|
-
# Collection of DataObject
|
764
|
-
# This class represents Object Parameters
|
765
|
-
class ObjectData
|
766
|
-
def initialize(bInternal = false)
|
767
|
-
|
768
|
-
@hParams = {}
|
769
|
-
@hParams[:hdata] = {} unless bInternal
|
770
|
-
@bInternal = bInternal
|
771
|
-
end
|
772
|
-
|
773
|
-
def [] (*key)
|
774
|
-
|
775
|
-
key = key.flatten
|
776
|
-
# Return ObjectData Element if asked. Ignore additional keys.
|
777
|
-
return @hParams[key[0]] if key[1] == :ObjectData
|
778
|
-
|
779
|
-
return @hParams if key.length == 0
|
780
|
-
|
781
|
-
oObject = rhGet(@hParams, key[0])
|
782
|
-
return nil if oObject.nil?
|
783
|
-
|
784
|
-
# Return attributes if asked
|
785
|
-
return oObject[:attrs, key[2..-1]] if key[1] == :attrs
|
786
|
-
|
787
|
-
if oObject.is_a?(ForjLib::Data)
|
788
|
-
if @bInternal
|
789
|
-
# params are retrieved in process context
|
790
|
-
# By default, if key is detected as a framework object, return its data.
|
791
|
-
return oObject[:attrs, key[1..-1]]
|
792
|
-
else
|
793
|
-
# params are retrieved in controller context
|
794
|
-
# By default, if key is detected as a controller object, return its data.
|
795
|
-
return oObject[:object, key[1..-1]]
|
796
|
-
end
|
797
|
-
end
|
798
|
-
|
799
|
-
# otherwise, simply return what is found in keys hierarchy.
|
800
|
-
rhGet(@hParams, key)
|
801
|
-
end
|
802
|
-
|
803
|
-
# Functions used to set simple data/Object for controller/process function call.
|
804
|
-
# TODO: to revisit this function, as we may consider simple data, as ForjLib::Data object
|
805
|
-
def []= (*key, value)
|
806
|
-
return nil if [:object, :query].include?(key[0])
|
807
|
-
rhSet(@hParams, value, key)
|
808
|
-
end
|
809
|
-
|
810
|
-
def add(oDataObject)
|
811
|
-
# Requires to be a valid framework object.
|
812
|
-
raise ForjError.new, "Invalid Framework object type '%s'." % oDataObject.class unless oDataObject.is_a?(ForjLib::Data)
|
813
|
-
|
814
|
-
sObjectType = oDataObject.object_type?
|
815
|
-
|
816
|
-
if oDataObject.type? == :list
|
817
|
-
oOldDataObject = rhGet(@hParams, :query, sObjectType)
|
818
|
-
oOldDataObject.unregister if oOldDataObject
|
819
|
-
rhSet(@hParams, oDataObject, :query, sObjectType)
|
820
|
-
else
|
821
|
-
oOldDataObject = rhGet(@hParams, sObjectType)
|
822
|
-
oOldDataObject.unregister if oOldDataObject
|
823
|
-
@hParams[sObjectType] = oDataObject
|
824
|
-
end
|
825
|
-
oDataObject.register
|
826
|
-
end
|
827
|
-
|
828
|
-
def delete(oObj)
|
829
|
-
if oObj.is_a?(Symbol)
|
830
|
-
sObjectType = oObj
|
831
|
-
@hParams[sObjectType] = nil
|
832
|
-
else
|
833
|
-
raise ForjError.new(), "ObjectData: delete error. oObj is not a framework data Object." unless oObj.is_a?(ForjLib::Data)
|
834
|
-
if oObj[:object_type] == :object_list
|
835
|
-
rhSet(@hParams, nil, :query, sObjectType)
|
836
|
-
else
|
837
|
-
sObjectType = oObj[:object_type]
|
838
|
-
@hParams[sObjectType] = nil
|
839
|
-
end
|
840
|
-
end
|
841
|
-
oObj.unregister
|
842
|
-
end
|
843
|
-
|
844
|
-
def << (hHash)
|
845
|
-
@hParams.merge!(hHash)
|
846
|
-
end
|
847
|
-
|
848
|
-
def exist?(*key)
|
849
|
-
raise ForjError.new, "ObjectData: key is not list of values (string/symbol or array)" if not [Array, String, Symbol].include?(key.class)
|
850
|
-
|
851
|
-
key = [key] if key.is_a?(Symbol) or key.is_a?(String)
|
852
|
-
|
853
|
-
key = key.flatten
|
854
|
-
|
855
|
-
oObject = rhGet(@hParams, key[0])
|
856
|
-
return false if oObject.nil?
|
857
|
-
|
858
|
-
if oObject.is_a?(ForjLib::Data)
|
859
|
-
# Return true if ObjectData Element is found when asked.
|
860
|
-
return true if key[1] == :ObjectData and oObject.type?(key[0]) == :object
|
861
|
-
|
862
|
-
# Return true if attritutes or controller object attributes found when asked.
|
863
|
-
return oObject.exist?(key[2..-1]) if key[1] == :attrs
|
864
|
-
return oObject.exist?(key[1..-1]) if key.length > 1
|
865
|
-
true
|
866
|
-
else
|
867
|
-
# By default true if found key hierarchy
|
868
|
-
(rhExist?(@hParams, key) == key.length)
|
869
|
-
end
|
870
|
-
end
|
871
|
-
|
872
|
-
#~ def get(*key)
|
873
|
-
#~ rhGet(@hParams, key)
|
874
|
-
#~ end
|
875
|
-
|
876
|
-
def type?(key)
|
877
|
-
return nil if rhExist?(@hParams, key) != 1
|
878
|
-
:data
|
879
|
-
:DataObject if @hParams[key].type?() == :object
|
880
|
-
end
|
881
|
-
|
882
|
-
def cObj(*key)
|
883
|
-
rhGet(@hParams, key, :object) if rhExist?(@hParams, key, :object) == 2
|
884
|
-
end
|
885
|
-
|
886
|
-
end
|
887
|
-
|
888
|
-
# Following class defines class levels function to
|
889
|
-
# declare framework objects.
|
890
|
-
# As each process needs to define new object to deal with
|
891
|
-
# require that process to define it with definition functions
|
892
|
-
# See definition.rb for functions to use.
|
893
|
-
|
894
|
-
class BaseDefinition
|
895
|
-
# Capitalized function are called to start a process. It is done by ForjObject.
|
896
|
-
|
897
|
-
# BaseCloud Object available functions.
|
898
|
-
def Create(sCloudObj)
|
899
|
-
return nil if not sCloudObj
|
900
|
-
raise ForjError.new(), "%s.Create: '%s' is not a known object type." % [self.class, sCloudObj] if rhExist?(@@meta_obj, sCloudObj) != 1
|
901
|
-
|
902
|
-
pProc = rhGet(@@meta_obj, sCloudObj, :lambdas, :create_e)
|
903
|
-
|
904
|
-
# Check required parameters
|
905
|
-
oObjMissing = _check_required(sCloudObj, :create_e, pProc).reverse
|
906
|
-
|
907
|
-
while oObjMissing.length >0
|
908
|
-
sElem = oObjMissing.pop
|
909
|
-
|
910
|
-
raise ForjError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
|
911
|
-
oObjMissing = _check_required(sCloudObj, :create_e, pProc).reverse
|
912
|
-
|
913
|
-
raise ForjError.new(), "loop detection: '%s' is required but Create(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
|
914
|
-
end
|
915
|
-
@RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
|
916
|
-
|
917
|
-
if pProc.nil?
|
918
|
-
# This object is a meta object, without any data.
|
919
|
-
# Used to build other kind of objects.
|
920
|
-
oObject = ForjLib::Data.new
|
921
|
-
oObject.set({}, sCloudObj) {}
|
922
|
-
else
|
923
|
-
# build Function params to pass to the event handler.
|
924
|
-
aParams = _get_object_params(sCloudObj, :create_e, pProc,)
|
925
|
-
ForjLib.debug(2, "Create Object '%s' - Running '%s'" % [sCloudObj, pProc])
|
926
|
-
|
927
|
-
# Call the process function.
|
928
|
-
# At some point, the process will call the controller, via the framework.
|
929
|
-
# This controller call via the framework has the role to
|
930
|
-
# create an ObjectData well formatted, with _return_map function
|
931
|
-
# See Definition.connect/create/update/query/get functions (lowercase)
|
932
|
-
oObject = @oForjProcess.method(pProc).call(sCloudObj, aParams)
|
933
|
-
# return usually is the main object that the process called should provide.
|
934
|
-
# Save Object if the object has been created by the process, without controller
|
935
|
-
end
|
936
|
-
|
937
|
-
unless oObject.nil?
|
938
|
-
@ObjectData.add(oObject)
|
939
|
-
end
|
940
|
-
end
|
941
|
-
|
942
|
-
def Delete(sCloudObj)
|
943
|
-
return nil if not sCloudObj
|
944
|
-
|
945
|
-
raise ForjError.new(), "%s.Delete: '%s' is not a known object type." % [self.class, sCloudObj] if rhExist?(@@meta_obj, sCloudObj) != 1
|
946
|
-
|
947
|
-
pProc = rhGet(@@meta_obj, sCloudObj, :lambdas, :delete_e)
|
948
|
-
|
949
|
-
return nil if pProc.nil?
|
950
|
-
|
951
|
-
# Check required parameters
|
952
|
-
oObjMissing = _check_required(sCloudObj, :delete_e, pProc).reverse
|
953
|
-
|
954
|
-
while oObjMissing.length >0
|
955
|
-
sElem = oObjMissing.pop
|
956
|
-
raise ForjError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
|
957
|
-
oObjMissing = _check_required(sCloudObj, :delete_e, pProc).reverse
|
958
|
-
raise ForjError.new(), "loop detection: '%s' is required but Delete(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
|
959
|
-
end
|
960
|
-
@RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
|
961
|
-
|
962
|
-
# build Function params to pass to the event handler.
|
963
|
-
aParams = _get_object_params(sCloudObj, :delete_e, pProc)
|
964
|
-
|
965
|
-
bState = @oForjProcess.method(pProc).call(sCloudObj, aParams)
|
966
|
-
# return usually is the main object that the process called should provide.
|
967
|
-
if bState
|
968
|
-
@ObjectData.del(sCloudObj)
|
969
|
-
end
|
970
|
-
|
971
|
-
end
|
972
|
-
|
973
|
-
def query_cleanup(sCloudObj)
|
974
|
-
oList = @ObjectData[:query, sCloudObj]
|
975
|
-
unless oList.nil?
|
976
|
-
@ObjectData.delete(oList)
|
977
|
-
end
|
978
|
-
end
|
979
|
-
|
980
|
-
def object_cleanup(sCloudObj)
|
981
|
-
oObject = @ObjectData[sCloudObj, :ObjectData]
|
982
|
-
unless oObject.nil?
|
983
|
-
@ObjectData.delete(oObject)
|
984
|
-
end
|
985
|
-
end
|
986
|
-
|
987
|
-
|
988
|
-
# This function returns a list of objects
|
989
|
-
def Query(sCloudObj, hQuery)
|
990
|
-
|
991
|
-
return nil if not sCloudObj
|
992
|
-
|
993
|
-
raise ForjError.new(), "$s.Get: '%s' is not a known object type." % [self.class, sCloudObj] if rhExist?(@@meta_obj, sCloudObj) != 1
|
994
|
-
|
995
|
-
# Check if we can re-use a previous query
|
996
|
-
oList = @ObjectData[:query, sCloudObj]
|
997
|
-
unless oList.nil?
|
998
|
-
if oList[:query] == hQuery
|
999
|
-
ForjLib.debug(3, "Using Object '%s' query cache : %s" % [sCloudObj, hQuery])
|
1000
|
-
return oList
|
1001
|
-
end
|
1002
|
-
end
|
1003
|
-
|
1004
|
-
pProc = rhGet(@@meta_obj, sCloudObj, :lambdas, :query_e)
|
1005
|
-
|
1006
|
-
return nil if pProc.nil?
|
1007
|
-
|
1008
|
-
# Check required parameters
|
1009
|
-
oObjMissing = _check_required(sCloudObj, :query_e, pProc).reverse
|
1010
|
-
|
1011
|
-
while oObjMissing.length >0
|
1012
|
-
sElem = oObjMissing.pop
|
1013
|
-
raise ForjError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
|
1014
|
-
oObjMissing = _check_required(sCloudObj, :query_e, pProc).reverse
|
1015
|
-
raise ForjError.new(), "loop detection: '%s' is required but Query(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
|
1016
|
-
end
|
1017
|
-
@RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
|
1018
|
-
|
1019
|
-
# build Function params to pass to the Process Event handler.
|
1020
|
-
aParams = _get_object_params(sCloudObj, :query_e, pProc)
|
1021
|
-
|
1022
|
-
# Call the process function.
|
1023
|
-
# At some point, the process will call the controller, via the framework.
|
1024
|
-
# This controller call via the framework has the role to
|
1025
|
-
# create an ObjectData well formatted, with _return_map function
|
1026
|
-
# See Definition.connect/create/update/query/get functions (lowercase)
|
1027
|
-
oObject = @oForjProcess.method(pProc).call(sCloudObj, hQuery, aParams)
|
1028
|
-
# return usually is the main object that the process called should provide.
|
1029
|
-
unless oObject.nil?
|
1030
|
-
# Save Object if the object has been created by the process, without controller
|
1031
|
-
@ObjectData.add(oObject)
|
1032
|
-
end
|
1033
|
-
end
|
1034
|
-
|
1035
|
-
def Get(sCloudObj, sUniqId)
|
1036
|
-
|
1037
|
-
return nil if not sCloudObj
|
1038
|
-
|
1039
|
-
raise ForjError.new(), "$s.Get: '%s' is not a known object type." % [self.class, sCloudObj] if rhExist?(@@meta_obj, sCloudObj) != 1
|
1040
|
-
|
1041
|
-
pProc = rhGet(@@meta_obj, sCloudObj, :lambdas, :get_e)
|
1042
|
-
|
1043
|
-
return nil if pProc.nil?
|
1044
|
-
|
1045
|
-
# Check required parameters
|
1046
|
-
oObjMissing = _check_required(sCloudObj, :get_e, pProc).reverse
|
1047
|
-
|
1048
|
-
while oObjMissing.length >0
|
1049
|
-
sElem = oObjMissing.pop
|
1050
|
-
raise ForjError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
|
1051
|
-
oObjMissing = _check_required(sCloudObj, :get_e, pProc).reverse
|
1052
|
-
raise ForjError.new(), "loop detection: '%s' is required but Get(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
|
1053
|
-
end
|
1054
|
-
@RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
|
1055
|
-
|
1056
|
-
# build Function params to pass to the Process Event handler.
|
1057
|
-
aParams = _get_object_params(sCloudObj, :get_e, pProc)
|
1058
|
-
|
1059
|
-
# Call the process function.
|
1060
|
-
# At some point, the process will call the controller, via the framework.
|
1061
|
-
# This controller call via the framework has the role to
|
1062
|
-
# create an ObjectData well formatted, with _return_map function
|
1063
|
-
# See Definition.connect/create/update/query/get functions (lowercase)
|
1064
|
-
oObject = @oForjProcess.method(pProc).call(sCloudObj, sUniqId, aParams)
|
1065
|
-
# return usually is the main object that the process called should provide.
|
1066
|
-
unless oObject.nil?
|
1067
|
-
# Save Object if the object has been created by the process, without controller
|
1068
|
-
@ObjectData.add(oObject)
|
1069
|
-
end
|
1070
|
-
end
|
1071
|
-
|
1072
|
-
def Update(sCloudObj)
|
1073
|
-
|
1074
|
-
return nil if not sCloudObj
|
1075
|
-
|
1076
|
-
raise ForjError.new(), "$s.Update: '%s' is not a known object type." % [self.class, sCloudObj] if rhExist?(@@meta_obj, sCloudObj) != 1
|
1077
|
-
|
1078
|
-
pProc = rhGet(@@meta_obj, sCloudObj, :lambdas, :update_e)
|
1079
|
-
|
1080
|
-
return nil if pProc.nil?
|
1081
|
-
|
1082
|
-
# Check required parameters
|
1083
|
-
oObjMissing = _check_required(sCloudObj, :update_e, pProc).reverse
|
1084
|
-
|
1085
|
-
while oObjMissing.length >0
|
1086
|
-
sElem = oObjMissing.pop
|
1087
|
-
raise ForjError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
|
1088
|
-
oObjMissing = _check_required(sCloudObj, :update_e, pProc).reverse
|
1089
|
-
raise ForjError.new(), "loop detection: '%s' is required but Update(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
|
1090
|
-
end
|
1091
|
-
@RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
|
1092
|
-
|
1093
|
-
# build Function params to pass to the event handler.
|
1094
|
-
aParams = _get_object_params(sCloudObj, :update_e, pProc)
|
1095
|
-
|
1096
|
-
oObject = @oForjProcess.method(pProc).call(sCloudObj, aParams)
|
1097
|
-
# return usually is the main object that the process called should provide.
|
1098
|
-
unless oObject.nil?
|
1099
|
-
# Save Object if the object has been created by the process, without controller
|
1100
|
-
@ObjectData.add(oObject)
|
1101
|
-
end
|
1102
|
-
end
|
1103
|
-
|
1104
|
-
def Setup(sObjectType, sAccountName)
|
1105
|
-
# Loop in dependencies to get list of data object to setup
|
1106
|
-
raise ForjError,new(), "Setup: '%s' not a valid object type." if rhExist?(@@meta_obj, sObjectType) != 1
|
1107
|
-
|
1108
|
-
hAskStep = ForjDefault.get(:ask_step, :setup)
|
1109
|
-
aSetup = []
|
1110
|
-
hAskStep.each{ | value |
|
1111
|
-
aSetup << {
|
1112
|
-
:desc => value[:desc],
|
1113
|
-
:explanation => value[:explanation],
|
1114
|
-
:pre_step_handler => value[:pre_step_function],
|
1115
|
-
:order => [[]],
|
1116
|
-
:post_step_handler => value[:post_step_function]
|
1117
|
-
}
|
1118
|
-
|
1119
|
-
}
|
1120
|
-
oInspectedObjects = []
|
1121
|
-
oInspectObj = [sObjectType]
|
1122
|
-
|
1123
|
-
@oForjConfig.ac_load(sAccountName) if sAccountName
|
1124
|
-
|
1125
|
-
ForjLib.debug(2, "Setup is identifying account data to ask for '%s'" % sObjectType)
|
1126
|
-
while oInspectObj.length() >0
|
1127
|
-
# Identify data to ask
|
1128
|
-
# A data to ask is a data needs from an object type
|
1129
|
-
# which is declared in section of defaults.yaml
|
1130
|
-
# and is declared :account to true (in defaults.yaml or in process declaration - define_data)
|
1131
|
-
|
1132
|
-
sObjectType = oInspectObj.pop
|
1133
|
-
sAsk_step = 0
|
1134
|
-
ForjLib.debug(1, "Checking '%s'" % sObjectType)
|
1135
|
-
hTopParams = rhGet(@@meta_obj,sObjectType, :params)
|
1136
|
-
if hTopParams[:keys].nil?
|
1137
|
-
ForjLib.debug(1, "Warning! Object '%s' has no data/object needs. Check the process" % sObjectType)
|
1138
|
-
next
|
1139
|
-
end
|
1140
|
-
hTopParams[:keys].each { |sKeypath, hParams|
|
1141
|
-
oKeyPath = KeyPath.new(sKeypath)
|
1142
|
-
sKey = oKeyPath.sKey
|
1143
|
-
case hParams[:type]
|
1144
|
-
when :data
|
1145
|
-
hMeta = _get_meta_data(sKey)
|
1146
|
-
next if hMeta.nil?
|
1147
|
-
sAsk_step = hMeta[:ask_step] if rhExist?(hMeta, :ask_step) == 1 and hMeta[:ask_step].is_a?(Fixnum)
|
1148
|
-
ForjLib.debug(3, "#{sKey} is part of setup step #{sAsk_step}")
|
1149
|
-
aOrder = aSetup[sAsk_step][:order]
|
1150
|
-
|
1151
|
-
if oInspectedObjects.include?(sKey)
|
1152
|
-
ForjLib.debug(2, "#{sKey} is already asked. Ignored.")
|
1153
|
-
next
|
1154
|
-
end
|
1155
|
-
if hMeta[:account].is_a?(TrueClass)
|
1156
|
-
if not hMeta[:depends_on].is_a?(Array)
|
1157
|
-
Logging.warning("'%s' depends_on definition have to be an array." % oKeyPath.sFullPath) unless hMeta[:depends_on].nil?
|
1158
|
-
iLevel = 0
|
1159
|
-
bFound = true
|
1160
|
-
else
|
1161
|
-
# Searching highest level from dependencies.
|
1162
|
-
bFound = false
|
1163
|
-
iLevel = 0
|
1164
|
-
hMeta[:depends_on].each { |depend_key|
|
1165
|
-
aOrder.each_index { |iCurLevel|
|
1166
|
-
if aOrder[iCurLevel].include?(depend_key)
|
1167
|
-
bFound = true
|
1168
|
-
iLevel = [iLevel, iCurLevel + 1].max
|
1169
|
-
end
|
1170
|
-
}
|
1171
|
-
aOrder[iLevel] = [] if aOrder[iLevel].nil?
|
1172
|
-
}
|
1173
|
-
end
|
1174
|
-
if bFound
|
1175
|
-
if not aOrder[iLevel].include?(sKey)
|
1176
|
-
if hMeta[:ask_sort].is_a?(Fixnum)
|
1177
|
-
iOrder = hMeta[:ask_sort]
|
1178
|
-
if aOrder[iLevel][iOrder].nil?
|
1179
|
-
aOrder[iLevel][iOrder] = sKey
|
1180
|
-
else
|
1181
|
-
aOrder[iLevel].insert(iOrder, sKey)
|
1182
|
-
end
|
1183
|
-
ForjLib.debug(3, "S%s/L%s/O%s: '%s' added in setup list. " % [sAsk_step, iLevel, iOrder, sKey])
|
1184
|
-
else
|
1185
|
-
aOrder[iLevel] << sKey
|
1186
|
-
ForjLib.debug(3, "S%s/L%s/Last: '%s' added in setup list." % [sAsk_step, iLevel, sKey])
|
1187
|
-
end
|
1188
|
-
end
|
1189
|
-
end
|
1190
|
-
oInspectedObjects << sKey
|
1191
|
-
else
|
1192
|
-
ForjLib.debug(2, "#{sKey} used by #{sObjectType} won't be asked during setup. :account = true not set.")
|
1193
|
-
end
|
1194
|
-
when :CloudObject
|
1195
|
-
oInspectObj << sKey if not oInspectObj.include?(sKey) and not oInspectedObjects.include?(sKey)
|
1196
|
-
end
|
1197
|
-
}
|
1198
|
-
oInspectedObjects << sObjectType
|
1199
|
-
end
|
1200
|
-
ForjLib.debug(2, "Setup check if needs to add unrelated data in the process")
|
1201
|
-
hAskStep.each_index{ | iStep |
|
1202
|
-
value = hAskStep[iStep]
|
1203
|
-
if rhExist?(value, :add) == 1
|
1204
|
-
sKeysToAdd = rhGet(value, :add)
|
1205
|
-
sKeysToAdd.each { | sKeyToAdd |
|
1206
|
-
bFound = false
|
1207
|
-
aSetup[iStep][:order].each_index { | iOrder |
|
1208
|
-
sKeysToAsk = aSetup[iStep][:order][iOrder]
|
1209
|
-
unless sKeysToAsk.index(sKeyToAdd).nil?
|
1210
|
-
bFound = true
|
1211
|
-
break
|
1212
|
-
end
|
1213
|
-
}
|
1214
|
-
next if bFound
|
1215
|
-
iLevel = 0
|
1216
|
-
iOrder = aSetup[iStep][:order].length
|
1217
|
-
iAtStep = iStep
|
1218
|
-
hMeta = _get_meta_data(sKeyToAdd)
|
1219
|
-
if rhExist?(hMeta, :after) == 1
|
1220
|
-
sAfterKeys = hMeta[:after]
|
1221
|
-
sAfterKeys = [ sAfterKeys ] if not sAfterKeys.is_a?(Array)
|
1222
|
-
sAfterKeys.each{ |sAfterKey |
|
1223
|
-
bFound = false
|
1224
|
-
aSetup.each_index { |iStepToCheck|
|
1225
|
-
aSetup[iStepToCheck][:order].each_index { | iLevelToCheck |
|
1226
|
-
sKeysToAsk = aSetup[iStepToCheck][:order][iLevelToCheck]
|
1227
|
-
iOrderToCheck = sKeysToAsk.index(sAfterKey)
|
1228
|
-
unless iOrderToCheck.nil?
|
1229
|
-
iAtStep = iStepToCheck if iStepToCheck > iAtStep
|
1230
|
-
iLevel = iLevelToCheck if iLevelToCheck > iLevel
|
1231
|
-
iOrder = iOrderToCheck + 1 if iOrderToCheck + 1 > iOrder
|
1232
|
-
bFound = true
|
1233
|
-
break
|
1234
|
-
end
|
1235
|
-
}
|
1236
|
-
}
|
1237
|
-
}
|
1238
|
-
end
|
1239
|
-
aSetup[iAtStep][:order][iLevel].insert(iOrder, sKeyToAdd)
|
1240
|
-
ForjLib.debug(3, "S%s/L%s/O%s: '%s' added in setup list at position." % [iAtStep, iLevel, iOrder, sKeyToAdd])
|
1241
|
-
}
|
1242
|
-
end
|
1243
|
-
}
|
1244
|
-
|
1245
|
-
ForjLib.debug(2, "Setup will ask for :\n %s" % aSetup.to_yaml)
|
1246
|
-
|
1247
|
-
Logging.info("Configuring account : '#{config[:account_name]}', provider '#{config[:provider_name]}'")
|
1248
|
-
|
1249
|
-
# Ask for user input
|
1250
|
-
aSetup.each_index { | iStep |
|
1251
|
-
ForjLib.debug(2, "Ask step %s:" % iStep)
|
1252
|
-
puts "%s%s%s" % [ANSI.bold, aSetup[iStep][:desc], ANSI.clear] unless aSetup[iStep][:desc].nil?
|
1253
|
-
puts "%s\n\n" % ANSI.yellow(aSetup[iStep][:explanation]) unless aSetup[iStep][:explanation].nil?
|
1254
|
-
aOrder = aSetup[iStep][:order]
|
1255
|
-
aOrder.each_index { | iIndex |
|
1256
|
-
ForjLib.debug(2, "Ask order %s:" % iIndex)
|
1257
|
-
aOrder[iIndex].each { | sKey |
|
1258
|
-
hParam = _get_meta_data(sKey)
|
1259
|
-
hParam = {} if hParam.nil?
|
1260
|
-
|
1261
|
-
bOk = false
|
1262
|
-
|
1263
|
-
if hParam[:pre_step_function]
|
1264
|
-
pProc = hParam[:pre_step_function]
|
1265
|
-
bOk = not(@oForjProcess.method(pProc).call(sKey))
|
1266
|
-
end
|
1267
|
-
|
1268
|
-
|
1269
|
-
sDesc = "'%s' value" % sKey
|
1270
|
-
puts "#{sKey}: %s" % [hParam[:explanation]] unless rhGet(hParam, :explanation).nil?
|
1271
|
-
sDesc = hParam[:desc] unless hParam[:desc].nil?
|
1272
|
-
sDefault = @oForjConfig.get(sKey, hParam[:default_value])
|
1273
|
-
rValidate = nil
|
1274
|
-
|
1275
|
-
rValidate = hParam[:validate] unless hParam[:validate].nil?
|
1276
|
-
bRequired = (hParam[:required] == true)
|
1277
|
-
while not bOk
|
1278
|
-
bOk = true
|
1279
|
-
if not hParam[:list_values].nil?
|
1280
|
-
hValues = hParam[:list_values]
|
1281
|
-
sObjectToLoad = hValues[:object]
|
1282
|
-
|
1283
|
-
bListStrict = (hValues[:validate] == :list_strict)
|
1284
|
-
|
1285
|
-
case hValues[:query_type]
|
1286
|
-
when :controller_call
|
1287
|
-
oObject = @ObjectData[sObjectToLoad, :ObjectData]
|
1288
|
-
Logging.state("Loading #{sObjectToLoad}.")
|
1289
|
-
oObject = Create(sObjectToLoad) if oObject.nil?
|
1290
|
-
return nil if oObject.nil?
|
1291
|
-
oParams = ObjectData.new
|
1292
|
-
oParams.add(oObject)
|
1293
|
-
oParams << hValues[:query_params]
|
1294
|
-
raise ForjError.new(), "#{sKey}: query_type => :controller_call requires missing :query_call declaration (Controller function)" if hValues[:query_call].nil?
|
1295
|
-
pProc = hValues[:query_call]
|
1296
|
-
begin
|
1297
|
-
aList = @oProvider.method(pProc).call(sObjectToLoad, oParams)
|
1298
|
-
rescue => e
|
1299
|
-
raise ForjError.new(), "Error during call of '%s':\n%s" % [pProc, e.message]
|
1300
|
-
end
|
1301
|
-
when :query_call
|
1302
|
-
sQuery = {}
|
1303
|
-
sQuery = hValues[:query_params] unless hValues[:query_params].nil?
|
1304
|
-
Logging.state("Querying #{sObjectToLoad}.")
|
1305
|
-
oObjectList = Query(sObjectToLoad, sQuery)
|
1306
|
-
aList = []
|
1307
|
-
oObjectList.each { | oElem |
|
1308
|
-
aList << oElem[hValues[:value]]
|
1309
|
-
}
|
1310
|
-
aList.sort!
|
1311
|
-
when :process_call
|
1312
|
-
raise ForjError.new(), "#{sKey}: query_type => :process_call requires missing :query_call declaration (Provider function)" if hValues[:query_call].nil?
|
1313
|
-
pProc = hValues[:query_call]
|
1314
|
-
sObjectToLoad = hValues[:object]
|
1315
|
-
oParams = ObjectData.new
|
1316
|
-
oParams.add(oObject)
|
1317
|
-
oParams << hValues[:query_params]
|
1318
|
-
begin
|
1319
|
-
aList = @oForjProcess.method(pProc).call(sObjectToLoad, oParams)
|
1320
|
-
rescue => e
|
1321
|
-
raise ForjError.new(), "Error during call of '%s':\n%s" % [pProc, e.message]
|
1322
|
-
end
|
1323
|
-
else
|
1324
|
-
raise ForjError.new, "'%s' invalid. %s/list_values/values_type supports %s. " % [hValues[:values_type], sKey, [:provider_function]]
|
1325
|
-
end
|
1326
|
-
Logging.fatal(1, "%s requires a value from the '%s' query which is empty." % [sKey, sObjectToLoad])if aList.nil? and bListStrict
|
1327
|
-
aList = [] if aList.nil?
|
1328
|
-
if not bListStrict
|
1329
|
-
aList << "other"
|
1330
|
-
end
|
1331
|
-
say("Enter %s" % ((sDefault.nil?)? sDesc : sDesc + " |%s|" % sDefault))
|
1332
|
-
value = choose { | q |
|
1333
|
-
q.choices(*aList)
|
1334
|
-
q.default = sDefault if sDefault
|
1335
|
-
}
|
1336
|
-
if not bListStrict and value == "other"
|
1337
|
-
value = _ask(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
|
1338
|
-
end
|
1339
|
-
else
|
1340
|
-
pValidateProc = hParam[:validate_function]
|
1341
|
-
pAskProc = hParam[:ask_function]
|
1342
|
-
|
1343
|
-
if pAskProc.nil?
|
1344
|
-
unless pValidateProc.nil?
|
1345
|
-
value = _ask(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
|
1346
|
-
while not @oForjProcess.method(pValidateProc).call(value)
|
1347
|
-
value = _ask(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
|
1348
|
-
end
|
1349
|
-
else
|
1350
|
-
value = _ask(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
|
1351
|
-
end
|
1352
|
-
else
|
1353
|
-
unless pValidateProc.nil?
|
1354
|
-
value = @oForjProcess.method(pAskProc).call(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
|
1355
|
-
while not @oForjProcess.method(pValidateProc).call(value)
|
1356
|
-
value = @oForjProcess.method(pAskProc).call(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
|
1357
|
-
end
|
1358
|
-
else
|
1359
|
-
value = @oForjProcess.method(pAskProc).call(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
|
1360
|
-
end
|
1361
|
-
end
|
1362
|
-
end
|
1363
|
-
|
1364
|
-
@oForjConfig.set(sKey, value)
|
1365
|
-
if hParam[:post_step_function]
|
1366
|
-
pProc = hParam[:post_step_function]
|
1367
|
-
bOk = @oForjProcess.method(pProc).call()
|
1368
|
-
end
|
1369
|
-
end
|
1370
|
-
}
|
1371
|
-
}
|
1372
|
-
}
|
1373
|
-
end
|
1374
|
-
|
1375
|
-
# Initialize Cloud object Data
|
1376
|
-
|
1377
|
-
def initialize(oForjConfig, oForjProcess, oForjProvider = nil)
|
1378
|
-
# Object Data object. Contains all loaded object data.
|
1379
|
-
# This object is used to build hParams as well.
|
1380
|
-
@ObjectData = ObjectData.new(true)
|
1381
|
-
#
|
1382
|
-
@RuntimeContext = {
|
1383
|
-
:oCurrentObj => nil
|
1384
|
-
}
|
1385
|
-
|
1386
|
-
@oForjConfig = oForjConfig
|
1387
|
-
raise ForjError.new(), "'%s' is not a valid ForjAccount or ForjConfig Object." % [oForjConfig.class] if not oForjConfig.is_a?(ForjAccount) and not oForjConfig.is_a?(ForjConfig)
|
1388
|
-
|
1389
|
-
@oProvider = oForjProvider
|
1390
|
-
if oForjProvider
|
1391
|
-
raise ForjError.new(), "'%s' is not a valid ForjProvider Object type." % [oForjProvider.class] if not oForjProvider.is_a?(BaseController)
|
1392
|
-
end
|
1393
|
-
|
1394
|
-
@oForjProcess = oForjProcess
|
1395
|
-
raise ForjError.new(), "'%s' is not a valid BaseProcess Object type." % [oForjProcess.class] if not oForjProcess.is_a?(BaseProcess)
|
1396
|
-
|
1397
|
-
@oForjProcess.set_BaseObject(self)
|
1398
|
-
end
|
1399
|
-
|
1400
|
-
# ------------------------------------------------------
|
1401
|
-
# Functions used by processes functions
|
1402
|
-
# ------------------------------------------------------
|
1403
|
-
# Ex: object.set_data(...)
|
1404
|
-
# config
|
1405
|
-
|
1406
|
-
|
1407
|
-
# Function to manipulate the config object.
|
1408
|
-
# 2 kind of functions:
|
1409
|
-
# - set (key, value) and []=(key, value)
|
1410
|
-
# From processes, you can set a runtime data with:
|
1411
|
-
# config.set(key, value)
|
1412
|
-
# OR
|
1413
|
-
# config[key] = value
|
1414
|
-
#
|
1415
|
-
# - get (key, default) and [](key, default)
|
1416
|
-
# default is an optional value.
|
1417
|
-
# From processes, you can get a data (runtime/account/config.yaml or defaults.yaml) with:
|
1418
|
-
# config.get(key)
|
1419
|
-
# OR
|
1420
|
-
# config[key]
|
1421
|
-
|
1422
|
-
def config
|
1423
|
-
raise ForjError.new(), "No config object loaded." if not @oForjConfig
|
1424
|
-
@oForjConfig
|
1425
|
-
end
|
1426
|
-
|
1427
|
-
def format_query(sObjectType, oControlerObject, hQuery)
|
1428
|
-
{
|
1429
|
-
:object => oControlerObject,
|
1430
|
-
:object_type => :object_list,
|
1431
|
-
:list_type => sObjectType,
|
1432
|
-
:list => [],
|
1433
|
-
:query => hQuery
|
1434
|
-
}
|
1435
|
-
end
|
1436
|
-
|
1437
|
-
def format_object(sCloudObj, oMiscObject)
|
1438
|
-
return nil if not sCloudObj or not [String, Symbol].include?(sCloudObj.class)
|
1439
|
-
|
1440
|
-
sCloudObj = sCloudObj.to_sym if sCloudObj.class == String
|
1441
|
-
|
1442
|
-
oCoreObject = {
|
1443
|
-
:object_type => sCloudObj,
|
1444
|
-
:attrs => {},
|
1445
|
-
:object => oMiscObject,
|
1446
|
-
}
|
1447
|
-
end
|
1448
|
-
|
1449
|
-
def get_data_metadata(sKey)
|
1450
|
-
_get_meta_data(sKey)
|
1451
|
-
end
|
1452
|
-
|
1453
|
-
# Before doing a query, mapping fields
|
1454
|
-
# Transform Object query field to Provider query Fields
|
1455
|
-
def query_map(sCloudObj, hParams)
|
1456
|
-
return nil if not sCloudObj or not [String, Symbol].include?(sCloudObj.class)
|
1457
|
-
return {} if not hParams
|
1458
|
-
|
1459
|
-
sCloudObj = sCloudObj.to_sym if sCloudObj.class == String
|
1460
|
-
|
1461
|
-
hReturn = {}
|
1462
|
-
hMap = rhGet(@@meta_obj, sCloudObj, :query_mapping)
|
1463
|
-
hParams.each { |key, value|
|
1464
|
-
oKeyPath = KeyPath.new(key)
|
1465
|
-
sKeyPath = oKeyPath.sFullPath
|
1466
|
-
raise ForjError.new(), "Forj query field '%s.%s' not defined by class '%s'" % [sCloudObj, oKeyPath.sKey, self.class] if not hMap.key?(oKeyPath.sFullPath)
|
1467
|
-
oMapPath = KeyPath.new(hMap[oKeyPath.sFullPath])
|
1468
|
-
hValueMapping = rhGet(@@meta_obj, sCloudObj, :value_mapping, sKeyPath)
|
1469
|
-
if hValueMapping
|
1470
|
-
raise ForjError.new(), "'%s.%s': No value mapping for '%s'" % [sCloudObj, oKeyPath.sKey, value] if rhExist?(hValueMapping, value) != 1
|
1471
|
-
|
1472
|
-
rhSet(hReturn, hValueMapping[value], oMapPath.aTree)
|
1473
|
-
else
|
1474
|
-
rhSet(hReturn, value, oMapPath.aTree)
|
1475
|
-
end
|
1476
|
-
}
|
1477
|
-
hReturn
|
1478
|
-
end
|
1479
|
-
|
1480
|
-
# Used by the Process.
|
1481
|
-
# Ask controller get_attr to get a data
|
1482
|
-
# The result is the data of a defined data attribute.
|
1483
|
-
# If the value is normally mapped (value mapped), the value is
|
1484
|
-
# returned as a recognized data attribute value.
|
1485
|
-
def get_attr(oObject, key)
|
1486
|
-
|
1487
|
-
raise ForjError.new(), "'%s' is not a valid Object type. " % [oObject.class] if not oObject.is_a?(Hash) and rhExist?(oObject, :object_type) != 1
|
1488
|
-
sCloudObj = oObject[:object_type]
|
1489
|
-
oKeyPath = KeyPath.new(key)
|
1490
|
-
raise ForjError.new(), "'%s' key is not declared as data of '%s' CloudObject. You may need to add obj_needs..." % [oKeyPath.sKey, sCloudObj] if rhExist?(@@meta_obj, sCloudObj, :returns, oKeyPath.sFullPath) != 3
|
1491
|
-
begin
|
1492
|
-
oMapPath = KeyPath.new(rhGet(@@meta_obj, sCloudObj, :returns, oKeyPath.sFullPath))
|
1493
|
-
hMap = oMapPath.sFullPath
|
1494
|
-
value = @oProvider.get_attr(get_cObject(oObject), hMap)
|
1495
|
-
|
1496
|
-
hValueMapping = rhGet(@@meta_obj, sCloudObj, :value_mapping, oKeyPath.sFullPath)
|
1497
|
-
|
1498
|
-
if hValueMapping
|
1499
|
-
hValueMapping.each { | found_key, found_value |
|
1500
|
-
if found_value == value
|
1501
|
-
value = found_key
|
1502
|
-
break
|
1503
|
-
end
|
1504
|
-
}
|
1505
|
-
end
|
1506
|
-
rescue => e
|
1507
|
-
raise ForjError.new(), "'%s.get_attr' fails to provide value of '%s'" % [oProvider.class, key]
|
1508
|
-
end
|
1509
|
-
end
|
1510
|
-
|
1511
|
-
# Register the object to the internal @ObjectData instance
|
1512
|
-
def register(oObject, sObjectType = nil, sDataType = :object)
|
1513
|
-
if oObject.is_a?(ForjLib::Data)
|
1514
|
-
oDataObject = oObject
|
1515
|
-
else
|
1516
|
-
raise ForjError.new(), "Unable to register an object '%s' as ForjLib::Data object if ObjectType is not given." % [ oObject.class ] if not sObjectType
|
1517
|
-
oDataObject = ForjLib::Data.new(sDataType)
|
1518
|
-
oDataObject.set(oObject, sObjectType) { | sObjType, oControlerObject |
|
1519
|
-
_return_map(sObjType, oControlerObject)
|
1520
|
-
}
|
1521
|
-
end
|
1522
|
-
@ObjectData.add oDataObject
|
1523
|
-
end
|
1524
|
-
|
1525
|
-
def DataObjects(sObjectType, *key)
|
1526
|
-
@ObjectData[sObjectType, key]
|
1527
|
-
end
|
1528
|
-
|
1529
|
-
# get an attribute/object/... from an object.
|
1530
|
-
def get_data(oObj, *key)
|
1531
|
-
if oObj.is_a?(Hash) and oObj.key?(:object_type)
|
1532
|
-
oObjData = ObjectData.new
|
1533
|
-
oObjData << oObj
|
1534
|
-
else
|
1535
|
-
oObjData = @ObjectData
|
1536
|
-
end
|
1537
|
-
oObjData[oObj, *key]
|
1538
|
-
end
|
1539
|
-
|
1540
|
-
#~ def hParams(sCloudObj, hParams)
|
1541
|
-
#~ aParams = _get_object_params(sCloudObj, ":ObjectData.hParams")
|
1542
|
-
#~ end
|
1543
|
-
|
1544
|
-
def get_cObject(oObject)
|
1545
|
-
return nil if rhExist?(oObject, :object) != 1
|
1546
|
-
rhGet(oObject, :object)
|
1547
|
-
end
|
1548
|
-
|
1549
|
-
# a Process can execute any kind of predefined controler task.
|
1550
|
-
# Those function build hParams with Provider compliant data (mapped)
|
1551
|
-
# Results are formatted as usual framework Data object and stored.
|
1552
|
-
def connect(sObjectType)
|
1553
|
-
|
1554
|
-
hParams = _get_object_params(sObjectType, :create_e, :connect, true)
|
1555
|
-
oControlerObject = @oProvider.connect(sObjectType, hParams)
|
1556
|
-
oDataObject = ForjLib::Data.new
|
1557
|
-
oDataObject.set(oControlerObject, sObjectType) { | sObjType, oObject |
|
1558
|
-
begin
|
1559
|
-
_return_map(sObjType, oObject)
|
1560
|
-
rescue => e
|
1561
|
-
raise ForjError.new(), "connect %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
|
1562
|
-
end
|
1563
|
-
}
|
1564
|
-
@ObjectData.add oDataObject
|
1565
|
-
oDataObject
|
1566
|
-
end
|
1567
|
-
|
1568
|
-
def create(sObjectType)
|
1569
|
-
# The process ask the controller to create the object.
|
1570
|
-
# hParams have to be fully readable by the controller.
|
1571
|
-
hParams = _get_object_params(sObjectType, :create_e, :create, true)
|
1572
|
-
oControlerObject = @oProvider.create(sObjectType, hParams)
|
1573
|
-
oDataObject = ForjLib::Data.new
|
1574
|
-
oDataObject.set(oControlerObject, sObjectType) { | sObjType, oObject |
|
1575
|
-
begin
|
1576
|
-
_return_map(sObjType, oObject)
|
1577
|
-
rescue => e
|
1578
|
-
raise ForjError.new(), "create %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
|
1579
|
-
end
|
1580
|
-
}
|
1581
|
-
@ObjectData.add oDataObject
|
1582
|
-
|
1583
|
-
oDataObject
|
1584
|
-
end
|
1585
|
-
|
1586
|
-
# The controller must return true to inform about the real deletion
|
1587
|
-
def delete(sObjectType)
|
1588
|
-
hParams = _get_object_params(sObjectType, :delete_e, :delete, true)
|
1589
|
-
bState = @oProvider.delete(sObjectType, hParams)
|
1590
|
-
@ObjectData.delete(sCloudObj) if bState
|
1591
|
-
bState
|
1592
|
-
end
|
1593
|
-
|
1594
|
-
def get(sObjectType, sUniqId)
|
1595
|
-
|
1596
|
-
hParams = _get_object_params(sObjectType, :get_e, :get, true)
|
1597
|
-
|
1598
|
-
oControlerObject = @oProvider.get(sObjectType, sUniqId, hParams)
|
1599
|
-
oDataObject = ForjLib::Data.new
|
1600
|
-
oDataObject.set(oControlerObject, sObjectType) { | sObjType, oObject |
|
1601
|
-
begin
|
1602
|
-
_return_map(sObjType, oObject)
|
1603
|
-
rescue => e
|
1604
|
-
raise ForjError.new(), "get %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
|
1605
|
-
end
|
1606
|
-
}
|
1607
|
-
@ObjectData.add oDataObject
|
1608
|
-
|
1609
|
-
oDataObject
|
1610
|
-
end
|
1611
|
-
|
1612
|
-
def query(sObjectType, hQuery)
|
1613
|
-
|
1614
|
-
# Check if we can re-use a previous query
|
1615
|
-
oList = @ObjectData[:query, sObjectType]
|
1616
|
-
unless oList.nil?
|
1617
|
-
if oList[:query] == hQuery
|
1618
|
-
ForjLib.debug(3, "Using Object '%s' query cache : %s" % [sObjectType, hQuery])
|
1619
|
-
return oList
|
1620
|
-
end
|
1621
|
-
end
|
1622
|
-
|
1623
|
-
|
1624
|
-
hParams = _get_object_params(sObjectType, :query_e, :query, true)
|
1625
|
-
sProviderQuery = query_map(sObjectType, hQuery)
|
1626
|
-
|
1627
|
-
oControlerObject = @oProvider.query(sObjectType, sProviderQuery, hParams)
|
1628
|
-
|
1629
|
-
oDataObjects = ForjLib::Data.new :list
|
1630
|
-
oDataObjects.set(oControlerObject, sObjectType, hQuery) { | sObjType, key |
|
1631
|
-
begin
|
1632
|
-
_return_map(sObjType, key)
|
1633
|
-
rescue => e
|
1634
|
-
raise ForjError.new(), "query %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
|
1635
|
-
end
|
1636
|
-
}
|
1637
|
-
|
1638
|
-
ForjLib.debug(2, "Object %s - queried. Found %s object(s)." % [sObjectType, oDataObjects.length()])
|
1639
|
-
|
1640
|
-
@ObjectData.add oDataObjects
|
1641
|
-
oDataObjects
|
1642
|
-
end
|
1643
|
-
|
1644
|
-
def update(sObjectType)
|
1645
|
-
# Need to detect data updated and update the Controler object with the controler
|
1646
|
-
|
1647
|
-
hParams = _get_object_params(sObjectType, :update_e, :update, true)
|
1648
|
-
|
1649
|
-
oObject = @ObjectData[sObjectType, :ObjectData]
|
1650
|
-
oControlerObject = oObject[:object]
|
1651
|
-
|
1652
|
-
bUpdated = false
|
1653
|
-
oObject[:attrs].each { |key, value |
|
1654
|
-
oKeyPath = KeyPath.new(key)
|
1655
|
-
oMapPath = KeyPath.new(rhGet(@@meta_obj, sObjectType, :returns, oKeyPath.sFullPath))
|
1656
|
-
old_value = @oProvider.get_attr(oControlerObject, oMapPath.aTree)
|
1657
|
-
if value != old_value
|
1658
|
-
bUpdated = true
|
1659
|
-
@oProvider.set_attr(oControlerObject, oMapPath.aTree, value)
|
1660
|
-
ForjLib.debug(2, "%s.%s - Updating: %s = %s (old : %s)" % [@oForjProcess.class, sObjectType, key, value, old_value])
|
1661
|
-
end
|
1662
|
-
}
|
1663
|
-
|
1664
|
-
bDone = @oProvider.update(sObjectType, oObject, hParams) if bUpdated
|
1665
|
-
|
1666
|
-
raise ForjError.new, "Controller function 'update' must return True or False. Class returned: '%s'" % bDone.class if not [TrueClass, FalseClass].include?(bDone.class)
|
1667
|
-
|
1668
|
-
ForjLib.debug(1, "%s.%s - updated." % [@oForjProcess.class, sObjectType]) if bDone
|
1669
|
-
oObject.set(oControlerObject, sObjectType) { | sObjType, oObject |
|
1670
|
-
begin
|
1671
|
-
_return_map(sObjType, oObject)
|
1672
|
-
rescue => e
|
1673
|
-
raise ForjError.new(), "update %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
|
1674
|
-
end
|
1675
|
-
}
|
1676
|
-
bDone
|
1677
|
-
end
|
1678
|
-
|
1679
|
-
|
1680
|
-
private
|
1681
|
-
|
1682
|
-
# -------------------------------------------------------------------------
|
1683
|
-
# Functions available for Process to communicate with the controler Object
|
1684
|
-
# -------------------------------------------------------------------------
|
1685
|
-
def cloud_obj_requires(sCloudObj, res = {})
|
1686
|
-
aCaller = caller
|
1687
|
-
aCaller.pop
|
1688
|
-
|
1689
|
-
return res if @ObjectData.exist?(sCloudObj)
|
1690
|
-
#~ return res if rhExist?(@CloudData, sCloudObj) == 1
|
1691
|
-
|
1692
|
-
rhGet(@@meta_obj,sCloudObj, :params).each { |key, hParams|
|
1693
|
-
case hParams[:type]
|
1694
|
-
when :data
|
1695
|
-
if hParams.key?(:array)
|
1696
|
-
hParams[:array].each{ | aElem |
|
1697
|
-
aElem = aElem.clone
|
1698
|
-
aElem.pop # Do not go until last level, as used to loop next.
|
1699
|
-
rhGet(hParams, aElem).each { | subkey, hSubParam |
|
1700
|
-
next if aElem.length == 0 and [:array, :type].include?(subkey)
|
1701
|
-
if hSubParams[:required] and @oForjConfig.get(subkey).nil?
|
1702
|
-
res[subkey] = hSubParams
|
1703
|
-
end
|
1704
|
-
}
|
1705
|
-
}
|
1706
|
-
else
|
1707
|
-
if hParams[:required] and @oForjConfig.get(key).nil?
|
1708
|
-
res[key] = hParams
|
1709
|
-
end
|
1710
|
-
end
|
1711
|
-
when :CloudObject
|
1712
|
-
#~ if hParams[:required] and rhExist?(@CloudData, sCloudObj) != 1
|
1713
|
-
if hParams[:required] and not @ObjectData.exist?(sCloudObj)
|
1714
|
-
res[key] = hParams
|
1715
|
-
cloud_obj_requires(key, res)
|
1716
|
-
end
|
1717
|
-
end
|
1718
|
-
}
|
1719
|
-
res
|
1720
|
-
end
|
1721
|
-
|
1722
|
-
def get_object(sCloudObj)
|
1723
|
-
#~ return nil if rhExist?(@CloudData, sCloudObj) != 1
|
1724
|
-
return nil if not @ObjectData.exist?(sCloudObj)
|
1725
|
-
@ObjectData[sCloudObj, :ObjectData]
|
1726
|
-
#~ rhGet(@CloudData, sCloudObj)
|
1727
|
-
end
|
1728
|
-
|
1729
|
-
def objectExist?(sCloudObj)
|
1730
|
-
@ObjectData.exist?(sCloudObj)
|
1731
|
-
#~ (rhExist?(@CloudData, sCloudObj) != 1)
|
1732
|
-
end
|
1733
|
-
|
1734
|
-
def get_forjKey(oCloudData, key)
|
1735
|
-
return nil if not @ObjectData.exist?(sCloudObj)
|
1736
|
-
@ObjectData[sCloudObj, :attrs, key]
|
1737
|
-
#~ return nil if rhExist?(oCloudData, sCloudObj) != 1
|
1738
|
-
#~ rhGet(oCloudData, sCloudObj, :attrs, key)
|
1739
|
-
end
|
1740
|
-
end
|