coral_core 0.2.26 → 0.2.30
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.
- data/Gemfile +7 -2
- data/Gemfile.lock +84 -15
- data/VERSION +1 -1
- data/coral_core.gemspec +51 -16
- data/lib/{coral_core/command.rb → coral/command/shell.rb} +12 -116
- data/lib/coral/machine/fog.rb +215 -0
- data/lib/coral/network/default.rb +26 -0
- data/lib/coral/node/rackspace.rb +23 -0
- data/lib/coral_core.rb +249 -134
- data/lib/coral_core/config.rb +233 -275
- data/lib/coral_core/config/collection.rb +57 -0
- data/lib/coral_core/config/options.rb +70 -0
- data/lib/coral_core/config/project.rb +225 -0
- data/lib/coral_core/core.rb +19 -173
- data/lib/coral_core/event/puppet_event.rb +98 -0
- data/lib/coral_core/mixin/config_collection.rb +52 -0
- data/lib/coral_core/mixin/config_ops.rb +51 -0
- data/lib/coral_core/mixin/config_options.rb +38 -0
- data/lib/coral_core/mixin/lookup.rb +211 -0
- data/lib/coral_core/mixin/macro/object_interface.rb +292 -0
- data/lib/coral_core/mixin/macro/plugin_interface.rb +277 -0
- data/lib/coral_core/mixin/settings.rb +46 -0
- data/lib/coral_core/mixin/sub_config.rb +208 -0
- data/lib/coral_core/mod/hash.rb +29 -0
- data/lib/{hiera_backend.rb → coral_core/mod/hiera_backend.rb} +0 -0
- data/lib/coral_core/plugin.rb +261 -0
- data/lib/coral_core/plugin/command.rb +95 -0
- data/lib/coral_core/plugin/machine.rb +152 -0
- data/lib/coral_core/plugin/network.rb +24 -0
- data/lib/coral_core/plugin/node.rb +184 -0
- data/lib/coral_core/plugin_base.rb +147 -0
- data/lib/coral_core/repository.rb +471 -82
- data/lib/coral_core/util/cli.rb +293 -0
- data/lib/coral_core/util/data.rb +178 -8
- data/lib/coral_core/util/disk.rb +13 -0
- data/lib/coral_core/util/git.rb +35 -10
- data/lib/coral_core/{interface.rb → util/interface.rb} +31 -21
- data/lib/coral_core/util/process.rb +43 -0
- data/locales/en.yml +8 -0
- data/spec/coral_core/interface_spec.rb +45 -45
- metadata +109 -34
- data/.gitmodules +0 -12
- data/lib/coral_core/memory.rb +0 -226
- data/lib/coral_core/util/git/base.rb +0 -65
- data/lib/coral_core/util/git/lib.rb +0 -89
- data/lib/coral_core/util/git/remote.rb +0 -12
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
module Coral
|
|
3
|
+
module Network
|
|
4
|
+
class Default < Plugin::Network
|
|
5
|
+
|
|
6
|
+
#-----------------------------------------------------------------------------
|
|
7
|
+
# Cloud plugin interface
|
|
8
|
+
|
|
9
|
+
def normalize
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
#-----------------------------------------------------------------------------
|
|
14
|
+
# Checks
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
#-----------------------------------------------------------------------------
|
|
18
|
+
# Property accessors / modifiers
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#-----------------------------------------------------------------------------
|
|
22
|
+
# Coral cloud operations
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
module Coral
|
|
3
|
+
module Node
|
|
4
|
+
class Rackspace < Plugin::Node
|
|
5
|
+
|
|
6
|
+
#-----------------------------------------------------------------------------
|
|
7
|
+
# Node plugin interface
|
|
8
|
+
|
|
9
|
+
def normalize
|
|
10
|
+
#super
|
|
11
|
+
dbg('hello from rackspace node')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
#-----------------------------------------------------------------------------
|
|
15
|
+
# Checks
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
#-----------------------------------------------------------------------------
|
|
19
|
+
# Property accessors / modifiers
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/coral_core.rb
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
module Kernel
|
|
14
14
|
|
|
15
15
|
def dbg(data, label = '')
|
|
16
|
+
# Invocations of this function should NOT be committed to the project
|
|
16
17
|
require 'pp'
|
|
17
18
|
|
|
18
19
|
puts '>>----------------------'
|
|
@@ -26,8 +27,9 @@ module Kernel
|
|
|
26
27
|
|
|
27
28
|
#---
|
|
28
29
|
|
|
29
|
-
def
|
|
30
|
-
|
|
30
|
+
def coral_locate(command)
|
|
31
|
+
command = command.to_s
|
|
32
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
|
31
33
|
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
|
32
34
|
exts.each do |ext|
|
|
33
35
|
exe = File.join(path, "#{command}#{ext}")
|
|
@@ -36,129 +38,103 @@ module Kernel
|
|
|
36
38
|
end
|
|
37
39
|
return nil
|
|
38
40
|
end
|
|
41
|
+
|
|
42
|
+
#---
|
|
43
|
+
|
|
44
|
+
def coral_require(base_dir, name)
|
|
45
|
+
name = name.to_s
|
|
46
|
+
|
|
47
|
+
require File.join(base_dir, "#{name}.rb")
|
|
48
|
+
directory = File.join(base_dir, name)
|
|
49
|
+
|
|
50
|
+
if File.directory?(directory)
|
|
51
|
+
Dir.glob(File.join(directory, '**', '*.rb')).each do |sub_file|
|
|
52
|
+
require sub_file
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
39
56
|
end
|
|
40
57
|
|
|
41
58
|
#-------------------------------------------------------------------------------
|
|
42
|
-
#
|
|
59
|
+
# Top level properties
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
lib_dir = File.dirname(__FILE__)
|
|
62
|
+
core_dir = File.join(lib_dir, 'coral_core')
|
|
63
|
+
mixin_dir = File.join(core_dir, 'mixin')
|
|
64
|
+
macro_dir = File.join(mixin_dir, 'macro')
|
|
65
|
+
event_dir = File.join(core_dir, 'event')
|
|
66
|
+
template_dir = File.join(core_dir, 'template')
|
|
67
|
+
util_dir = File.join(core_dir, 'util')
|
|
68
|
+
mod_dir = File.join(core_dir, 'mod')
|
|
48
69
|
|
|
49
70
|
#-------------------------------------------------------------------------------
|
|
71
|
+
# Coral requirements
|
|
72
|
+
|
|
73
|
+
git_location = coral_locate('git')
|
|
50
74
|
|
|
51
|
-
$:.unshift(
|
|
52
|
-
$:.include?(home) || $:.include?(File.expand_path(home))
|
|
75
|
+
$:.unshift(lib_dir) unless $:.include?(lib_dir) || $:.include?(File.expand_path(lib_dir))
|
|
53
76
|
|
|
54
77
|
#---
|
|
55
78
|
|
|
56
79
|
require 'rubygems'
|
|
57
80
|
|
|
58
|
-
|
|
81
|
+
require 'i18n'
|
|
82
|
+
require 'log4r'
|
|
83
|
+
require 'deep_merge'
|
|
84
|
+
require 'yaml'
|
|
85
|
+
require 'multi_json'
|
|
86
|
+
require 'digest/sha1'
|
|
59
87
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
rescue LoadError
|
|
64
|
-
log4r_lib = File.join(dependencies, 'log4r', 'lib')
|
|
65
|
-
|
|
66
|
-
$:.push(log4r_lib)
|
|
67
|
-
require File.join(log4r_lib, 'log4r.rb')
|
|
68
|
-
end
|
|
88
|
+
require 'puppet'
|
|
89
|
+
require 'fog'
|
|
69
90
|
|
|
70
91
|
#---
|
|
71
92
|
|
|
72
|
-
|
|
73
|
-
require 'deep_merge'
|
|
74
|
-
|
|
75
|
-
rescue LoadError
|
|
76
|
-
deep_merge_lib = File.join(dependencies, 'deep_merge', 'lib')
|
|
77
|
-
|
|
78
|
-
$:.push(deep_merge_lib)
|
|
79
|
-
require File.join(deep_merge_lib, 'deep_merge.rb')
|
|
80
|
-
end
|
|
93
|
+
# TODO: Make this dynamically settable
|
|
81
94
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
begin
|
|
85
|
-
require 'json'
|
|
86
|
-
|
|
87
|
-
rescue LoadError
|
|
88
|
-
json_lib = File.join(dependencies, 'json', 'lib')
|
|
89
|
-
|
|
90
|
-
$:.push(json_lib)
|
|
91
|
-
require File.join(json_lib, 'json.rb')
|
|
92
|
-
end
|
|
95
|
+
I18n.load_path << File.expand_path(File.join('..', 'locales', 'en.yml'), lib_dir)
|
|
93
96
|
|
|
94
97
|
#---
|
|
95
98
|
|
|
96
99
|
if git_location
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
rescue LoadError
|
|
101
|
-
git_lib = File.join(dependencies, 'git', 'lib')
|
|
102
|
-
|
|
103
|
-
$:.push(git_lib)
|
|
104
|
-
require File.join(git_lib, 'git.rb')
|
|
105
|
-
end
|
|
100
|
+
require 'grit'
|
|
101
|
+
coral_require(util_dir, :git)
|
|
106
102
|
end
|
|
107
103
|
|
|
108
104
|
#---
|
|
109
105
|
|
|
110
|
-
#
|
|
111
|
-
|
|
112
|
-
require
|
|
106
|
+
# Object modifications (100% pure monkey patches)
|
|
107
|
+
Dir.glob(File.join(mod_dir, '*.rb')).each do |file|
|
|
108
|
+
require file
|
|
113
109
|
end
|
|
114
110
|
|
|
115
|
-
|
|
116
|
-
require File.join('coral_core', 'util', 'git.rb')
|
|
111
|
+
#---
|
|
117
112
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
end
|
|
113
|
+
# Mixins for classes
|
|
114
|
+
Dir.glob(File.join(mixin_dir, '*.rb')).each do |file|
|
|
115
|
+
require file
|
|
122
116
|
end
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
[ :config, :interface, :core, :resource, :template ].each do |name|
|
|
126
|
-
require File.join('coral_core', name.to_s + ".rb")
|
|
117
|
+
Dir.glob(File.join(macro_dir, '*.rb')).each do |file|
|
|
118
|
+
require file
|
|
127
119
|
end
|
|
128
120
|
|
|
129
|
-
|
|
130
|
-
# ( normally inherit from core and have no reverse dependencies with
|
|
131
|
-
# core classes )
|
|
132
|
-
#
|
|
133
|
-
[ :shell ].each do |name|
|
|
134
|
-
require File.join('coral_core', 'util', name.to_s + ".rb")
|
|
135
|
-
end
|
|
121
|
+
#---
|
|
136
122
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
123
|
+
coral_require(util_dir, :data)
|
|
124
|
+
coral_require(core_dir, :config)
|
|
125
|
+
coral_require(util_dir, :interface)
|
|
126
|
+
coral_require(core_dir, :core)
|
|
141
127
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
end
|
|
128
|
+
# Include core utilities
|
|
129
|
+
[ :cli, :disk, :process, :shell ].each do |name|
|
|
130
|
+
coral_require(util_dir, name)
|
|
146
131
|
end
|
|
147
132
|
|
|
148
|
-
# Include
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
# Include bundled templates
|
|
154
|
-
Dir.glob(File.join(home, 'coral_core', 'template', '*.rb')).each do |file|
|
|
155
|
-
require file
|
|
133
|
+
# Include core systems
|
|
134
|
+
[ :event, :template, :repository, :resource, :plugin_base, :plugin ].each do |name|
|
|
135
|
+
coral_require(core_dir, name)
|
|
156
136
|
end
|
|
157
137
|
|
|
158
|
-
#---
|
|
159
|
-
|
|
160
|
-
require 'hiera_backend.rb'
|
|
161
|
-
|
|
162
138
|
#*******************************************************************************
|
|
163
139
|
# Coral Core Library
|
|
164
140
|
#
|
|
@@ -172,48 +148,167 @@ module Coral
|
|
|
172
148
|
|
|
173
149
|
#---
|
|
174
150
|
|
|
175
|
-
@@
|
|
151
|
+
@@config_file = 'coral.json'
|
|
176
152
|
|
|
177
|
-
|
|
153
|
+
#-----------------------------------------------------------------------------
|
|
178
154
|
|
|
179
155
|
def self.ui
|
|
180
|
-
return
|
|
156
|
+
return Core.ui
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
#---
|
|
160
|
+
|
|
161
|
+
def self.logger
|
|
162
|
+
return Core.logger
|
|
181
163
|
end
|
|
182
164
|
|
|
183
165
|
#-----------------------------------------------------------------------------
|
|
184
|
-
# Initialization
|
|
185
166
|
|
|
186
|
-
def self.
|
|
187
|
-
|
|
188
|
-
Dir.glob(File.join(base_path, '*.rb')).each do |file|
|
|
189
|
-
require file
|
|
190
|
-
end
|
|
191
|
-
Dir.glob(File.join(base_path, 'event', '*.rb')).each do |file|
|
|
192
|
-
require file
|
|
193
|
-
end
|
|
194
|
-
Dir.glob(File.join(base_path, 'template', '*.rb')).each do |file|
|
|
195
|
-
require file
|
|
196
|
-
end
|
|
197
|
-
end
|
|
167
|
+
def self.config_file=file_name
|
|
168
|
+
@@config_file = file_name
|
|
198
169
|
end
|
|
199
170
|
|
|
200
171
|
#---
|
|
201
172
|
|
|
173
|
+
def self.config_file
|
|
174
|
+
return @@config_file
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
#-----------------------------------------------------------------------------
|
|
178
|
+
# Initialization
|
|
179
|
+
|
|
202
180
|
@@initialized = false
|
|
203
181
|
|
|
204
182
|
def self.initialize
|
|
205
183
|
unless @@initialized
|
|
206
184
|
Config.set_property('time', Time.now.to_i)
|
|
207
185
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
186
|
+
begin
|
|
187
|
+
# Include Coral plugins
|
|
188
|
+
Puppet::Node::Environment.new.modules.each do |mod|
|
|
189
|
+
lib_path = File.join(mod.path, 'lib', 'coral')
|
|
190
|
+
Plugin.register(lib_path)
|
|
191
|
+
end
|
|
192
|
+
rescue
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
Plugin.initialize
|
|
212
196
|
|
|
213
197
|
@@initialized = true
|
|
214
198
|
end
|
|
215
199
|
end
|
|
216
200
|
|
|
201
|
+
#---
|
|
202
|
+
|
|
203
|
+
def self.initialized?
|
|
204
|
+
return @@initialized
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
#-----------------------------------------------------------------------------
|
|
208
|
+
# Plugins
|
|
209
|
+
|
|
210
|
+
def self.plugin(type, provider, options = {})
|
|
211
|
+
default_provider = Plugin.type_default(type)
|
|
212
|
+
|
|
213
|
+
if options.is_a?(Hash) || options.is_a?(Coral::Config)
|
|
214
|
+
config = Config.ensure(options)
|
|
215
|
+
provider = config.get(:provider, provider)
|
|
216
|
+
name = config.get(:name, ( provider ? provider : default_provider ))
|
|
217
|
+
options = config.export
|
|
218
|
+
end
|
|
219
|
+
provider = default_provider unless provider # Sanity checking (see plugins)
|
|
220
|
+
existing_instance = Plugin.get_instance(type, name) if name
|
|
221
|
+
|
|
222
|
+
return existing_instance if existing_instance
|
|
223
|
+
return Plugin.create_instance(type, provider, options)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
#---
|
|
227
|
+
|
|
228
|
+
def self.plugins(type, data, build_hash = false, keep_array = false)
|
|
229
|
+
group = ( build_hash ? {} : [] )
|
|
230
|
+
klass = class_const([ :coral, :plugin, type ])
|
|
231
|
+
data = klass.build_info(type, data) if klass.respond_to?(:build_info)
|
|
232
|
+
|
|
233
|
+
data.each do |options|
|
|
234
|
+
if plugin = plugin(type, options[:provider], options)
|
|
235
|
+
if build_hash
|
|
236
|
+
group[plugin.name] = plugin
|
|
237
|
+
else
|
|
238
|
+
group << plugin
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
return group.shift if ! build_hash && group.length == 1 && ! keep_array
|
|
243
|
+
return group
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
#---
|
|
247
|
+
|
|
248
|
+
def self.get_plugin(type, name)
|
|
249
|
+
return Plugin.get_instance(type, name)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
#---
|
|
253
|
+
|
|
254
|
+
def self.remove_plugin(plugin)
|
|
255
|
+
return Plugin.remove_instance(plugin)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
#-----------------------------------------------------------------------------
|
|
259
|
+
# Core plugin type facade
|
|
260
|
+
|
|
261
|
+
def self.network(name, options = {}, provider = nil)
|
|
262
|
+
plugin = plugin(:network, provider, options)
|
|
263
|
+
plugin.name = name
|
|
264
|
+
return plugin
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
#---
|
|
268
|
+
|
|
269
|
+
def self.networks(data, build_hash = false, keep_array = false)
|
|
270
|
+
return plugins(:network, data, build_hash, keep_array)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
#---
|
|
274
|
+
|
|
275
|
+
def self.node(name, options = {}, provider = nil)
|
|
276
|
+
plugin = plugin(:node, provider, options)
|
|
277
|
+
plugin.name = name
|
|
278
|
+
return plugin
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
#---
|
|
282
|
+
|
|
283
|
+
def self.nodes(data, build_hash = false, keep_array = false)
|
|
284
|
+
return plugins(:node, data, build_hash, keep_array)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
#---
|
|
288
|
+
|
|
289
|
+
def self.machine(options = {}, provider = nil)
|
|
290
|
+
plugin = plugin(:machine, provider, options)
|
|
291
|
+
return plugin
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
#---
|
|
295
|
+
|
|
296
|
+
def self.machines(data, build_hash = false, keep_array = false)
|
|
297
|
+
return plugins(:machine, data, build_hash, keep_array)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
#---
|
|
301
|
+
|
|
302
|
+
def self.command(options, provider = nil)
|
|
303
|
+
return plugin(:command, provider, options)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
#---
|
|
307
|
+
|
|
308
|
+
def self.commands(data, build_hash = false, keep_array = false)
|
|
309
|
+
return plugins(:command, data, build_hash, keep_array)
|
|
310
|
+
end
|
|
311
|
+
|
|
217
312
|
#-----------------------------------------------------------------------------
|
|
218
313
|
# External execution
|
|
219
314
|
|
|
@@ -228,33 +323,53 @@ module Coral
|
|
|
228
323
|
raise
|
|
229
324
|
end
|
|
230
325
|
end
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
#-------------------------------------------------------------------------------
|
|
234
|
-
# Data type alterations
|
|
235
|
-
|
|
236
|
-
class Hash
|
|
237
|
-
def search(search_key, options = {})
|
|
238
|
-
config = Coral::Config.ensure(options)
|
|
239
|
-
value = nil
|
|
240
326
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
value = value.search(search_key,
|
|
253
|
-
Coral::Config.new(config).set(:recurse_level, recurse_level)
|
|
254
|
-
)
|
|
255
|
-
end
|
|
256
|
-
break unless value.nil?
|
|
327
|
+
#-----------------------------------------------------------------------------
|
|
328
|
+
# Utilities
|
|
329
|
+
|
|
330
|
+
def self.class_name(name, separator = '::', want_array = FALSE)
|
|
331
|
+
components = []
|
|
332
|
+
|
|
333
|
+
case name
|
|
334
|
+
when String, Symbol
|
|
335
|
+
components = name.to_s.split(separator)
|
|
336
|
+
when Array
|
|
337
|
+
components = name
|
|
257
338
|
end
|
|
258
|
-
|
|
339
|
+
|
|
340
|
+
components.collect! do |value|
|
|
341
|
+
value.to_s.strip.capitalize
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
if want_array
|
|
345
|
+
return components
|
|
346
|
+
end
|
|
347
|
+
return components.join(separator)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
#---
|
|
351
|
+
|
|
352
|
+
def self.class_const(name, separator = '::')
|
|
353
|
+
components = class_name(name, separator, TRUE)
|
|
354
|
+
constant = Object
|
|
355
|
+
|
|
356
|
+
components.each do |component|
|
|
357
|
+
constant = constant.const_defined?(component) ?
|
|
358
|
+
constant.const_get(component) :
|
|
359
|
+
constant.const_missing(component)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
return constant
|
|
259
363
|
end
|
|
364
|
+
|
|
365
|
+
#---
|
|
366
|
+
|
|
367
|
+
def self.sha1(data)
|
|
368
|
+
return Digest::SHA1.hexdigest(Util::Data.to_json(data, false))
|
|
369
|
+
end
|
|
260
370
|
end
|
|
371
|
+
|
|
372
|
+
#-------------------------------------------------------------------------------
|
|
373
|
+
# Coral initialization
|
|
374
|
+
|
|
375
|
+
Coral.initialize
|