lorj 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 +1 -0
- data/README.md +39 -579
- data/Rakefile +7 -0
- data/example/students_1/student_v1.md +115 -0
- data/example/students_1/students.rb +8 -2
- data/example/students_2/process/students.rb +5 -5
- data/example/students_2/student_v2.md +90 -0
- data/example/students_2/students.rb +6 -6
- data/example/students_3/controller/yaml_students.rb +23 -73
- data/example/students_3/controller/yaml_students_code.rb +106 -0
- data/example/students_3/controller/yaml_students_def.rb +69 -0
- data/example/students_3/process/students.rb +23 -157
- data/example/students_3/student_v3.md +283 -0
- data/example/students_3/students.rb +26 -83
- data/example/students_4/controller/yaml_students.rb +51 -0
- data/example/students_4/controller/yaml_students_code.rb +109 -0
- data/example/students_4/controller/yaml_students_def.rb +72 -0
- data/example/students_4/process/students/code/students.rb +103 -0
- data/example/students_4/process/students/definition/students.rb +60 -0
- data/example/students_4/process/students.rb +29 -0
- data/example/students_4/student_v4.md +191 -0
- data/example/students_4/students.rb +65 -0
- data/example/students_5/controller/yaml_students.rb +106 -0
- data/example/{students_3 → students_5}/controller/yaml_students_controller.rb +5 -3
- data/example/students_5/process/students.rb +182 -0
- data/example/students_5/student_v5.md +382 -0
- data/example/students_5/students.rb +119 -0
- data/example/yaml_students/students.rb +1 -1
- data/example/yaml_students/yaml_students.rb +102 -23
- data/lib/concept.md +3 -3
- data/lib/core/core.rb +15 -15
- data/lib/core/core_controller.rb +49 -24
- data/lib/core/core_internal.rb +2 -2
- data/lib/core/core_model.rb +13 -7
- data/lib/core/core_object_data.rb +18 -18
- data/lib/core/core_object_params.rb +75 -34
- data/lib/core/core_process.rb +104 -59
- data/lib/core/core_process_setup.rb +11 -11
- data/lib/core/core_setup_ask.rb +24 -14
- data/lib/core/core_setup_encrypt.rb +17 -15
- data/lib/core/core_setup_init.rb +19 -15
- data/lib/core/core_setup_list.rb +12 -12
- data/lib/core/definition.rb +20 -20
- data/lib/core/definition_internal.rb +20 -10
- data/lib/core/lorj_basecontroller.rb +8 -8
- data/lib/core/lorj_basedefinition.rb +47 -126
- data/lib/core/lorj_baseprocess.rb +81 -57
- data/lib/core/lorj_data.rb +28 -27
- data/lib/core/lorj_keypath.rb +1 -1
- data/lib/core_process/cloud/process/flavor.rb +3 -2
- data/lib/core_process/cloud/process/keypairs.rb +5 -4
- data/lib/core_process/cloud/process/network.rb +4 -3
- data/lib/core_process/cloud/process/public_ip.rb +3 -2
- data/lib/core_process/cloud/process/rules.rb +7 -6
- data/lib/core_process/cloud/process/security_groups.rb +1 -1
- data/lib/core_process/cloud/process/server.rb +1 -1
- data/lib/core_process/cloud/process/server_log.rb +1 -1
- data/lib/core_process/cloud/process/subnetwork.rb +4 -1
- data/lib/core_process/cloud_process.rb +1 -1
- data/lib/logging.rb +41 -48
- data/lib/lorj/version.rb +1 -1
- data/lib/lorj.rb +7 -0
- data/lib/lorj_account.rb +3 -3
- data/lib/lorj_config.rb +1 -1
- data/lib/lorj_defaults.rb +222 -26
- data/lib/overview.md +120 -0
- data/lib/prc.rb +97 -24
- data/lib/prc_core_config.rb +134 -52
- data/lib/providers/hpcloud/compute.rb +3 -3
- data/lib/providers/hpcloud/hpcloud.rb +14 -14
- data/lib/providers/hpcloud/network.rb +4 -4
- data/lib/providers/hpcloud/security_groups.rb +1 -1
- data/lib/providers/mock/mock.rb +3 -3
- data/lib/providers/openstack/openstack.rb +12 -12
- data/lib/providers/templates/compute.rb +6 -6
- data/lib/rh.rb +7 -5
- data/spec/04_prc_core_config_spec.rb +52 -0
- data/spec/11_lorj_config_spec.rb +1 -1
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 186c6ba434808e7cc8e6d5ac0e7e703118698cbd
|
4
|
+
data.tar.gz: f53774dadcf6ed48fdcee6f3519d13461109bbf6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60b75966452c090d07aec57ff3bdf67e5100ce575be45fe038ffe256c863c8415edfad2ce23343af60ac52b93fa67818b1cac2e653be2de2844e3b34b0ad2e1d
|
7
|
+
data.tar.gz: 8e1b1c7ade0845986befba7a2bb0a34a34b519b0a5d7922fe9b3195692b205438770c2f7d261a2a4ae28ce3fb578905cfe96b0af9a7ebc67e7d8edd252287f4f
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -13,16 +13,25 @@ This framework helps to design any kind of solution which needs to maintain a ge
|
|
13
13
|
This case was implemented by forj cli to implement services on any kind of cloud solution.
|
14
14
|
|
15
15
|
forj cli needs to build a forge (collection of servers) on a cloud.
|
16
|
-
It requires to ensure that everything is in place (network properly configured
|
16
|
+
It requires to ensure that everything is in place (network properly configured
|
17
|
+
if not create it, router exists, flavors available, etc.) to create the first server.
|
17
18
|
|
18
|
-
For **Lorj**, how to create the forge and ensure that everything is in place is
|
19
|
-
|
19
|
+
For **Lorj**, how to create the forge and ensure that everything is in place is
|
20
|
+
the **GENERIC process**.<br>
|
21
|
+
And then how to manipulate the cloud (get the network, create the network,
|
22
|
+
create the server, etc...) is the **controller**. <br>
|
20
23
|
Usually, the controller is a wrapper to an API, which do actions, like 'create server'.
|
24
|
+
But depending on what you defined in your GENERIC process, a controller can define
|
25
|
+
a controller process, which will deal with the complexity of the controller to execute the
|
26
|
+
GENERIC process task requested.
|
21
27
|
|
22
|
-
Then, at runtime, while changing the controller to aws, hpcloud, openstack, or
|
23
|
-
|
28
|
+
Then, at runtime, while changing the controller to aws, hpcloud, openstack, or
|
29
|
+
even docker or decker, forj cli GENERIC process will be still the same.
|
30
|
+
It simplifies forj cli extension, by just adding new controller to support more
|
31
|
+
clouds providers.
|
24
32
|
|
25
|
-
Currently, forj cli has implemented *hpcloud* and *openstack* providers, using
|
33
|
+
Currently, forj cli has implemented *hpcloud* and *openstack* providers, using
|
34
|
+
*fog*. Docker controller is under development.
|
26
35
|
|
27
36
|
## Getting started
|
28
37
|
|
@@ -54,595 +63,46 @@ We have written a small class to illustrate this API. (See examples/yaml_student
|
|
54
63
|
|
55
64
|
This api has everything to create, query, edit and delete a student in a yaml file.
|
56
65
|
|
57
|
-
Using Lorj, you want to propose multiple storage system (not only using the yaml
|
66
|
+
Using Lorj, you want to propose multiple storage system (not only using the yaml
|
67
|
+
format) to your application, by supporting several storage systems, like mysql DB.
|
58
68
|
|
59
69
|
next, we will write 3 versions, which will introduce how to deal with process and controllers:
|
60
70
|
|
61
71
|
* version 1:
|
62
|
-
|
72
|
+
Writing your first 'do nothing' process, with no controller.
|
63
73
|
|
64
|
-
|
65
|
-
Complete the process to have create/query/get and delete capability, with mock controller.
|
66
|
-
The mock controller is basically a controller keeping data in memory.
|
67
|
-
|
68
|
-
* version 3:
|
69
|
-
Update the version 2 to fully implement the example of an yaml_student API.
|
70
|
-
|
71
|
-
The main is `examples/yaml_students/students.rb`<BR>
|
72
|
-
The API is `examples/yaml_students/yaml_students.rb`
|
73
|
-
|
74
|
-
We have created a full example version 4 which implements some interesting way to improve your code available in `examples/students_4/`
|
75
|
-
|
76
|
-
---
|
77
|
-
#### Writing student version 1
|
78
|
-
|
79
|
-
**NOTE**: following example is available in `examples/students_1/`
|
80
|
-
|
81
|
-
First of all, write your first main. Create a file `example.rb` with following content:
|
82
|
-
|
83
|
-
##### File `students.rb`
|
84
|
-
|
85
|
-
``` ruby
|
86
|
-
#!/usr/bin/env ruby
|
87
|
-
|
88
|
-
$APP_PATH = File.dirname(__FILE__)
|
89
|
-
require 'lorj'
|
90
|
-
|
91
|
-
# If you want to see what is happening in the framework, uncomment debug settings.
|
92
|
-
# PrcLib.level = Logger::DEBUG # Printed out to your console.
|
93
|
-
# PrcLib.core_level = 3 # framework debug levels.
|
94
|
-
|
95
|
-
# Initialize the framework
|
96
|
-
hProcesses = [ File.join($APP_PATH, 'process', 'students.rb')]
|
97
|
-
oStudentCore = Lorj::Core.new( nil, hProcesses)
|
98
|
-
|
99
|
-
# Ask the framework to create the object student 'Robert Redford'
|
100
|
-
oStudentCore.Create(:student, {:student_name => "Robert Redford"})
|
101
|
-
```
|
102
|
-
|
103
|
-
##### File `process/Students.rb`
|
104
|
-
|
105
|
-
Now, let's write our first process. We are going to create a file Students.rb under a sub-directory 'process'.
|
106
|
-
|
107
|
-
``` ruby
|
108
|
-
# Students process
|
109
|
-
class StudentsProcess
|
110
|
-
def create_student(sObjectType, hParams)
|
111
|
-
puts "Running creation process for object '%s' = '%s'" % [sObjectType, hParams[:student_name] ]
|
112
|
-
|
113
|
-
# If you prefer to print out to the log system instead:
|
114
|
-
# PrcLib::debug("Running creation process for object '%s' = '%s'" % [sObjectType, hParams[:student_name] ])
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# Declaring your data model and handlers.
|
119
|
-
class Lorj::BaseDefinition
|
120
|
-
|
121
|
-
# We need to define the student object and the handler to use while we need to create it.
|
122
|
-
define_obj(:student,
|
123
|
-
{
|
124
|
-
:create_e => :create_student # The function to call in the class Students
|
125
|
-
})
|
126
|
-
|
127
|
-
obj_needs :data, :student_name, { :for => [:create_e] }
|
128
|
-
|
129
|
-
end
|
130
|
-
```
|
131
|
-
|
132
|
-
What did we wrote?
|
133
|
-
|
134
|
-
* We defined a *StudentsProcess* class
|
135
|
-
|
136
|
-
This is the core of your process. It describes how to handle the object requested. The data to use is available in `hParams`.
|
137
|
-
|
138
|
-
**IMPORTANT !!** There is no reference to any files or Database connection.
|
139
|
-
|
140
|
-
**NOTE**: The framework requires you to define a class name composed by the name of the process and 'Process'.
|
141
|
-
Here, it is 'Students' + **'Process'**
|
142
|
-
|
143
|
-
|
144
|
-
* We declared the data model and the process handlers with declaration in *Lorj::BaseDefinition* class.
|
145
|
-
|
146
|
-
In short, we declared `:student` object, which needs `:student_name` at creation step.
|
147
|
-
|
148
|
-
**NOTE** Implicitly, the framework consider that the object contains at least 2 data fields, :id (should be unique) and :name (string)
|
149
|
-
|
150
|
-
|
151
|
-
Currently, this model do nothing except printing out.
|
152
|
-
|
153
|
-
#####typical output
|
154
|
-
|
155
|
-
$ example/students_1/students.rb
|
156
|
-
WARNING: PrcLib.app_defaults is not set. Application defaults won't be loaded.
|
157
|
-
Running creation process for object 'student' = 'Robert Redford'
|
158
|
-
WARNING: 'create_student' has returned no data for object Lorj::Data 'student'!
|
159
|
-
|
160
|
-
There is 2 warnings.
|
161
|
-
|
162
|
-
* **PrcLib.app_defaults** represents the application name. It is used to keep your application configuration data in ~/.{PrcLib.app_defaults}/ directory. Defining this data in your main, will eliminate this warning.
|
163
|
-
* **create_student** function in your process has returned nothing. while lorj is called to create an object, it assumes to get the object data created. Lorj keep those data in a cache. In this example, **create_student** returned nil, and lorj raise a warning about that.
|
164
|
-
|
165
|
-
---
|
166
|
-
#### Writing student version 2
|
167
|
-
|
168
|
-
**NOTE**: following example is available in `examples/students_2/`
|
169
|
-
|
170
|
-
lorj comes with a `:mock` controller. This one is really basic. It keep data in an Hash in MockController class.<br>
|
171
|
-
In this example, we add create/get/query/delete capability in the process and use the `:mock` controller to store the data.
|
172
|
-
|
173
|
-
##### File `process/Students.rb`
|
174
|
-
|
175
|
-
Add 3 handlers query_e, get_e and delete_e like this. Add the :mapping case as well.
|
176
|
-
|
177
|
-
``` ruby
|
178
|
-
class Lorj::BaseDefinition
|
179
|
-
define_obj(:student,
|
180
|
-
{
|
181
|
-
:create_e => :create_student, # The function to call in the class Students
|
182
|
-
:query_e => :controller_query, # We use predefined call to the controller query
|
183
|
-
:get_e => :controller_get, # We use predefined call to the controller get
|
184
|
-
:delete_e => :controller_delete # We use predefined call to the controller delete
|
185
|
-
})
|
186
|
-
|
187
|
-
# Note about mapping. This is usually done by the controller. We will see this later.
|
188
|
-
obj_needs :data, :student_name, { :for => [:create_e], :mapping => :name }
|
189
|
-
|
190
|
-
end
|
191
|
-
```
|
192
|
-
|
193
|
-
Update the handler `create_student`:
|
194
|
-
|
195
|
-
``` ruby
|
196
|
-
def create_student(sObjectType, hParams)
|
197
|
-
PrcLib::state ("Running creation process for object '%s' = '%s'" % [sObjectType, hParams[:student_name] ])
|
74
|
+
[Details is explained here](example/students_1/student_v1_md.html)
|
198
75
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
oObject
|
203
|
-
end
|
204
|
-
```
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
##### File `students.rb`
|
209
|
-
The update your main and add those lines. In the following, we create 3 students, while 2 are duplicated.
|
210
|
-
|
211
|
-
``` ruby
|
212
|
-
|
213
|
-
# Want to create a duplicated student 'Robert Redford'?
|
214
|
-
oStudentCore.Create(:student)
|
215
|
-
# no problem. The key is the key in the Mock controller array.
|
216
|
-
|
217
|
-
oStudentCore.Create(:student, :student_name => "Anthony Hopkins")
|
218
|
-
|
219
|
-
# Let's create a third different student.
|
220
|
-
oStudents = oStudentCore.Query(:student, { :name => "Robert Redford" } )
|
221
|
-
|
222
|
-
puts "%s students found" % oStudents.length
|
223
|
-
|
224
|
-
oStudents.each { | oStudent |
|
225
|
-
puts "%s: %s" % [oStudent[:id], oStudent[:name]]
|
226
|
-
}
|
227
|
-
|
228
|
-
# let's check the get function, who is the ID 2?
|
229
|
-
oStudent = oStudentCore.Get(:student, 2)
|
230
|
-
|
231
|
-
puts "The student ID 2 is %s" % oStudent[:name]
|
232
|
-
|
233
|
-
```
|
234
|
-
|
235
|
-
#####typical output:
|
236
|
-
|
237
|
-
$ example/students_2/students.rb
|
238
|
-
WARNING: PrcLib.app_defaults is not set. Application defaults won't be loaded.
|
239
|
-
2 students found
|
240
|
-
0: Robert Redford
|
241
|
-
1: Robert Redford
|
242
|
-
The student ID 2 is Anthony Hopkins
|
243
|
-
|
244
|
-
|
245
|
-
Cool! But everything is in memory! We would like to write this in a file.
|
246
|
-
Writing our controller, means that the process should not be updated anymore!
|
247
|
-
|
248
|
-
Let's move to the most interesting version. Translate an API example to use lorj!
|
249
|
-
|
250
|
-
#### Writing student version 3
|
251
|
-
|
252
|
-
**NOTE**: following example is available in `examples/students_3/`
|
253
|
-
|
254
|
-
A controller is like a wrapper to an API which offer what we would like to use to save our yaml file.<br>
|
255
|
-
We already have a running API that we can use to manage students in yaml format.
|
256
|
-
|
257
|
-
This API is written in `examples/yaml_students/yaml_students.rb`. <br>
|
258
|
-
`examples/yaml_students/students.rb` is the main program calling the api and create a basic yaml file example in `/tmp/students.yaml`
|
259
|
-
|
260
|
-
You can review the main 'students.rb' to see the simple code.
|
261
|
-
|
262
|
-
In short, this code do:
|
263
|
-
|
264
|
-
* create 3 students, only if they do not exists
|
265
|
-
* remove a wrong one
|
266
|
-
* Identify list of students on a specific training
|
267
|
-
* Identify students removed.
|
268
|
-
|
269
|
-
We will do the same thing with lorj.
|
270
|
-
|
271
|
-
Using lorj means you are going to split your code in different pieces. You will need to integrate a layer between your main and the API. This layer is composed by :
|
272
|
-
|
273
|
-
* 1 generic data model
|
274
|
-
* 1 generic process handlers
|
275
|
-
* 1 controller definition - expanding the data model for our Student yaml API
|
276
|
-
* 1 controller code - wrapper to the student yaml API.
|
277
|
-
|
278
|
-
So, we are going to update following files:
|
279
|
-
|
280
|
-
* students.rb - Adapt the main to do the same as original students script using the student yaml API.
|
281
|
-
* process/students.rb - Student data model - Update the process data model.
|
282
|
-
* process/students.rb - Student process handler - Update student process handlers.
|
283
|
-
* controller/yaml_students.rb - controller definition - Extend the student data model with controller definition.
|
284
|
-
* controller/yaml_students_controller.rb - controller code - Write the student yaml API wrapper.
|
285
|
-
|
286
|
-
First of all, let me re-visit the :student data model, then the student process handlers.
|
287
|
-
|
288
|
-
We need to define more parameters for handlers, and define the data model.
|
289
|
-
|
290
|
-
##### File `process/students.rb`
|
291
|
-
Update the class Lorj::BaseDefinition, and the data model and handlers parameters.
|
292
|
-
|
293
|
-
*The generic data model:*
|
294
|
-
|
295
|
-
``` ruby
|
296
|
-
class Lorj::BaseDefinition
|
297
|
-
define_obj(:student,
|
298
|
-
{
|
299
|
-
:create_e => :create_student, # The function to call in the class Students
|
300
|
-
:query_e => :controller_query, # We use predefined call to the controller query
|
301
|
-
:delete_e => :controller_delete # We use predefined call to the controller delete
|
302
|
-
})
|
303
|
-
|
304
|
-
# obj_needs is used to declare parameters to pass to handlers.
|
305
|
-
# :for indicates those parameters to be passed to create_e handler only.
|
306
|
-
# Those data (or objects) will be collected and passed to the process handler as hParams.
|
307
|
-
|
308
|
-
obj_needs :data, :student_name, { :for => [:create_e] }
|
309
|
-
|
310
|
-
# By default, all data are required.
|
311
|
-
# You can set it as optional. Your process will need to deal with this optional data.
|
312
|
-
obj_needs_optional
|
313
|
-
obj_needs :data, :first_name, { :for => [:create_e] }
|
314
|
-
obj_needs :data, :last_name, { :for => [:create_e] }
|
315
|
-
obj_needs :data, :course # Note that in this model, the training is renamed as course.
|
316
|
-
# the controller will need to map it to 'training'.
|
317
|
-
|
318
|
-
# def_attribute defines the data model.
|
319
|
-
# The process will be able to access those data
|
320
|
-
# if the controller has mapped them.
|
321
|
-
# For the exercice, I have changed the name of the training field to become :course instead.
|
322
|
-
def_attribute :course
|
323
|
-
# Same thing for the student name. instead of 'name', we defined :student_name
|
324
|
-
def_attribute :student_name
|
325
|
-
def_attribute :first_name
|
326
|
-
def_attribute :last_name
|
327
|
-
def_attribute :status
|
328
|
-
|
329
|
-
undefine_attribute :name
|
330
|
-
end
|
331
|
-
```
|
332
|
-
|
333
|
-
Then, update the process to manage student duplicates. Update function `create_student`
|
334
|
-
|
335
|
-
*The generic process handlers:*
|
336
|
-
|
337
|
-
``` ruby
|
338
|
-
class StudentsProcess
|
339
|
-
def create_student(sObjectType, hParams)
|
340
|
-
PrcLib::state ("Running creation process for object '%s' = '%s'" % [sObjectType, hParams[:student_name] ])
|
341
|
-
|
342
|
-
# config object is a reference to runtime/config data.
|
343
|
-
oList = Query(sObjectType, {:name => hParams[:student_name]})
|
344
|
-
case oList.length
|
345
|
-
when 0
|
346
|
-
oObject = controller_create(sObjectType)
|
347
|
-
raise "Student '%s' not created." % hParams[:student_name] if oObject.nil?
|
348
|
-
PrcLib::info ("'%s': '%s' created with id %s" % [sObjectType, hParams[:student_name], oObject[:id]])
|
349
|
-
when 1
|
350
|
-
oObject = oList[0]
|
351
|
-
PrcLib::info ("'%s': '%s' loaded with id %s" % [sObjectType, hParams[:student_name], oObject[:id]])
|
352
|
-
else
|
353
|
-
oObject = oList[0]
|
354
|
-
PrcLib::warning("More than one student named '%s' is found: %s records. Selecting the first one and removing duplicates." % [hParams[:student_name], oList.length])
|
355
|
-
iCount = 0
|
356
|
-
oList[1..-1].each { | elem |
|
357
|
-
register(elem)
|
358
|
-
iCount += controller_delete(sObjectType)
|
359
|
-
}
|
360
|
-
PrcLib::info ("'%s': %s duplicated '%s' removed. First loaded with id %s" % [sObjectType, iCount, hParams[:student_name], oObject[:id]])
|
361
|
-
end
|
362
|
-
oObject
|
363
|
-
end
|
364
|
-
end
|
365
|
-
```
|
366
|
-
|
367
|
-
Here you see that we query, check list, create if missing, or delete if duplicates found.
|
368
|
-
You can run it now, as we still uses mock controller. It should work.
|
369
|
-
|
370
|
-
##### File `students.rb`
|
371
|
-
|
372
|
-
Now, let's update the main to be close to what we have on `examples/yaml_students/students.rb`
|
373
|
-
|
374
|
-
This is a simple basic translation of `examples/yaml_students/students.rb`
|
375
|
-
|
376
|
-
``` ruby
|
377
|
-
#!/usr/bin/env ruby
|
378
|
-
|
379
|
-
$APP_PATH = File.dirname(__FILE__)
|
380
|
-
require 'lorj'
|
381
|
-
require 'ansi'
|
382
|
-
|
383
|
-
# If you want to see what is happening in the framework, uncomment debug settings.
|
384
|
-
# PrcLib.level = Logger::DEBUG # Printed out to your console.
|
385
|
-
# PrcLib.core_level = 3 # framework debug levels. Values between 0 to 5.
|
386
|
-
|
387
|
-
# Initialize the framework
|
388
|
-
hProcesses = [ File.join($APP_PATH, 'process', 'students.rb')]
|
389
|
-
|
390
|
-
# You can try with mock instead. uncomment the next line and comment 2 next lines.
|
391
|
-
#~ oStudentCore = Lorj::Core.new( nil, hProcesses, :mock)
|
392
|
-
oStudentCore = Lorj::Core.new( nil, hProcesses, File.join($APP_PATH, 'controller', 'yaml_students.rb'))
|
393
|
-
oStudentCore.Create(:connection, :connection_string => "/tmp/students.yaml")
|
394
|
-
|
395
|
-
puts ANSI.bold("Create 1st student:")
|
396
|
-
|
397
|
-
oStudentCore.Create(:student, {
|
398
|
-
student_name: 'Robert Redford',
|
399
|
-
first_name: 'Robert',
|
400
|
-
last_name: 'Redford',
|
401
|
-
course: 'Art Comedy'
|
402
|
-
})
|
403
|
-
|
404
|
-
puts ANSI.bold("Create 2nd student:")
|
405
|
-
oStudentCore.Create(:student, {
|
406
|
-
student_name: 'Anthony Hopkins',
|
407
|
-
first_name: 'Anthony',
|
408
|
-
last_name: 'Hopkins',
|
409
|
-
course: 'Art Drama'
|
410
|
-
})
|
411
|
-
|
412
|
-
puts ANSI.bold("Create 3rd student:")
|
413
|
-
oStudentCore.Create(:student, {
|
414
|
-
student_name: "Marilyn Monroe",
|
415
|
-
first_name: 'Marilyn',
|
416
|
-
last_name: 'Monroe',
|
417
|
-
course: 'Art Drama'
|
418
|
-
})
|
419
|
-
|
420
|
-
puts ANSI.bold("Create mistake")
|
421
|
-
oStudentCore.Create(:student, {
|
422
|
-
:student_name => "Anthony Mistake",
|
423
|
-
:first_name => 'Anthony',
|
424
|
-
:last_name => 'Mistake',
|
425
|
-
:course => 'what ever you want!!!'
|
426
|
-
})
|
427
|
-
|
428
|
-
# Because the last student was the mistake one, we can directly delete it.
|
429
|
-
# Usually, we use get instead.
|
430
|
-
puts ANSI.bold("Remove mistake")
|
431
|
-
oStudentCore.Delete(:student)
|
432
|
-
|
433
|
-
puts ANSI.bold("List of students for 'Art Drama':")
|
434
|
-
puts oStudentCore.Query(:student, { :course => "Art Drama"}).to_a
|
435
|
-
|
436
|
-
puts ANSI.bold("Deleted students:")
|
437
|
-
puts oStudentCore.Query(:student,{ :status => :removed}).to_a
|
438
|
-
```
|
76
|
+
* version 2:
|
77
|
+
Complete the process to have create/query/get and delete capability, with mock controller.
|
78
|
+
The mock controller is basically a controller keeping data in memory.
|
439
79
|
|
440
|
-
|
441
|
-
|
442
|
-
##### File `controller/yaml_students_controller.rb`
|
443
|
-
|
444
|
-
We need to write the controller part, now. As I said, it is like a wrapper. Let's have a look:
|
445
|
-
|
446
|
-
*The controller code:*
|
447
|
-
|
448
|
-
``` ruby
|
449
|
-
# declare yaml student API to the controller
|
450
|
-
cur_file = File.expand_path(File.join(File.dirname(File.dirname(__FILE__)), "..", "yaml_students", 'yaml_students.rb'))
|
451
|
-
require cur_file
|
452
|
-
|
453
|
-
# The controller is a combination of 2 elements:
|
454
|
-
# - Controller class
|
455
|
-
# Code which will interfere with the external API.
|
456
|
-
#
|
457
|
-
# The file name must respect the name of the class. 1st letter already capitalized and letter after _ is capitalized.
|
458
|
-
# file: my_code.rb => needs to create MyCodeController class
|
459
|
-
#
|
460
|
-
# - Definition class
|
461
|
-
# This class declare any kind of mapping or additional fields to consider.
|
462
|
-
# Additionnal fields are unknow by the process. So, those fields will needs to be setup before.
|
463
|
-
#
|
464
|
-
# file name convention is identical than controller class.
|
465
|
-
# file: my_code.rb => needs to create MyCode class
|
466
|
-
|
467
|
-
class YamlStudentsController
|
468
|
-
def initialize()
|
469
|
-
@@valid_attributes = [:name, :first_name, :last_name, :id, :status, :training]
|
470
|
-
end
|
471
|
-
|
472
|
-
def create(sObjectType, hParams)
|
473
|
-
case sObjectType
|
474
|
-
when :connection
|
475
|
-
required?(hParams, :hdata, :file_name)
|
476
|
-
YamlSchool.new(hParams[:hdata, :file_name])
|
477
|
-
when :student
|
478
|
-
required?(hParams, :connection)
|
479
|
-
required?(hParams, :student_name)
|
480
|
-
|
481
|
-
# We use the hdata built by the lorj. See set_hdata in the next file.
|
482
|
-
hParams[:connection].create_student(hParams[:student_name], hParams[:hdata])
|
483
|
-
else
|
484
|
-
Error "'%s' is not a valid object for 'create'" % sObjectType
|
485
|
-
end
|
486
|
-
end
|
487
|
-
|
488
|
-
# This function return a collection which have to provide:
|
489
|
-
# functions: [], length, each
|
490
|
-
def query(sObjectType, sQuery, hParams)
|
491
|
-
case sObjectType
|
492
|
-
when :student
|
493
|
-
required?(hParams, :connection)
|
494
|
-
|
495
|
-
hParams[:connection].query_student(sQuery)
|
496
|
-
else
|
497
|
-
Error "'%s' is not a valid object for 'create'" % sObjectType
|
498
|
-
end
|
499
|
-
|
500
|
-
end
|
501
|
-
|
502
|
-
def delete(sObjectType, hParams)
|
503
|
-
case sObjectType
|
504
|
-
when :student
|
505
|
-
required?(hParams, :connection)
|
506
|
-
|
507
|
-
hParams[:connection].delete_student(hParams[sObjectType][:id])
|
508
|
-
else
|
509
|
-
Error "'%s' is not a valid object for 'create'" % sObjectType
|
510
|
-
end
|
511
|
-
end
|
512
|
-
|
513
|
-
def get_attr(oControlerObject, key)
|
514
|
-
# This controller function read the data and
|
515
|
-
# extract the information requested by the framework.
|
516
|
-
# Those data will be mapped to the process data model.
|
517
|
-
# The key is an array, to get data from a level tree.
|
518
|
-
# [data_l1, data_l2, data_l3] => should retrieve data from structure
|
519
|
-
# like data[ data_l2 [ data_l3 ] ]
|
520
|
-
begin
|
521
|
-
attributes = oControlerObject
|
522
|
-
raise "get_attr: attribute '%s' is unknown in '%s'. Valid one are : '%s'",
|
523
|
-
key[0], oControlerObject.class,
|
524
|
-
@@valid_attributes unless @@valid_attributes.include?(key[0])
|
525
|
-
Lorj::rh_get(attributes, key)
|
526
|
-
rescue => e
|
527
|
-
Error "get_attr: Unable to map '%s'. %s" % [key, e.message]
|
528
|
-
end
|
529
|
-
end
|
530
|
-
|
531
|
-
def set_attr(oControlerObject, key, value)
|
532
|
-
begin
|
533
|
-
attributes = oControlerObject
|
534
|
-
raise "set_attr: attribute '%s' is unknown in '%s'. Valid one are : '%s'",
|
535
|
-
key[0], oControlerObject.class,
|
536
|
-
@@valid_attributes unless @@valid_attributes.include?(key[0])
|
537
|
-
Lorj::rh_set(attributes, value, key)
|
538
|
-
rescue => e
|
539
|
-
Error "set_attr: Unable to map '%s' on '%s'" % [key, sObjectType]
|
540
|
-
end
|
541
|
-
end
|
542
|
-
|
543
|
-
def update(sObjectType, oObject, hParams)
|
544
|
-
case sObjectType
|
545
|
-
when :student
|
546
|
-
required?(hParams, :connection)
|
547
|
-
|
548
|
-
hParams[:connection].update_student(oObject)
|
549
|
-
else
|
550
|
-
Error "'%s' is not a valid object for 'create'" % sObjectType
|
551
|
-
end
|
552
|
-
end
|
553
|
-
|
554
|
-
end
|
80
|
+
[Details is explained here](example/students_2/student_v2_md.html)
|
555
81
|
|
556
|
-
|
557
|
-
In
|
558
|
-
|
559
|
-
- create with YamlSchool.create_student
|
560
|
-
- delete with YamlSchool.delete_student
|
561
|
-
- query with YamlSchool.query_student
|
562
|
-
- update with YamlSchool.update_student
|
563
|
-
|
564
|
-
And we have defined 2 additional functions
|
565
|
-
|
566
|
-
- get_attr: to extract data from a YamlSchool Object
|
567
|
-
- set_attr: to set data to a YamlSchool Object
|
568
|
-
|
569
|
-
##### File `controller/yaml_students.rb`
|
570
|
-
|
571
|
-
And we need to write some mapping stuff to the controller. We have to add this
|
572
|
-
|
573
|
-
*The controller definition:*
|
574
|
-
|
575
|
-
``` ruby
|
576
|
-
class YamlStudents
|
577
|
-
# This is a new object which is known by the controller only.
|
578
|
-
# Used to open the yaml file. Generically, I named it :connection.
|
579
|
-
# But this can be any name you want. Only the controller will deal with it.
|
580
|
-
define_obj(:connection,{
|
581
|
-
:create_e => :controller_create # Nothing complex to do. So, simply call the controller create.
|
582
|
-
})
|
583
|
-
|
584
|
-
obj_needs :data, :connection_string, :mapping => :file_name
|
585
|
-
undefine_attribute :id # Do not return any predefined ID
|
586
|
-
undefine_attribute :name # Do not return any predefined NAME
|
587
|
-
|
588
|
-
# The student model have to be expanded.
|
589
|
-
define_obj(:student)
|
590
|
-
# It requires to create a connection to the data, ie opening the yaml file.
|
591
|
-
# So, before working with the :student object, the controller requires a connection
|
592
|
-
# This connection will be loaded in the memory and provided to the controller
|
593
|
-
# when needed.
|
594
|
-
obj_needs :CloudObject, :connection
|
595
|
-
|
596
|
-
# To simplify controller wrapper, we use hdata built by lorj, and passed to the API
|
597
|
-
# This hdata is a hash containing mapped data, thanks to set_hdata.
|
598
|
-
set_hdata :first_name
|
599
|
-
set_hdata :last_name
|
600
|
-
# Instead of 'course', the yaml API uses 'training'
|
601
|
-
set_hdata :course, :mapping => :training
|
602
|
-
|
603
|
-
get_attr_mapping :course, :training
|
604
|
-
# instead of 'student_name', the yaml API uses 'name'
|
605
|
-
get_attr_mapping :student_name, :name
|
606
|
-
|
607
|
-
# This controller will know how to manage a student file with those data.
|
608
|
-
# But note that the file can have a lot of more data than what the process
|
609
|
-
# usually manage. It is up to you to increase your process to manage more data.
|
610
|
-
# Then each controller may need to define mapping fields.
|
611
|
-
end
|
612
|
-
```
|
82
|
+
* version 3:
|
83
|
+
In this version, we will just create a controller, to replace mock.
|
613
84
|
|
614
|
-
|
85
|
+
[Details is explained here](example/students_3/student_v3_md.html)
|
615
86
|
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
Create 1st student:
|
620
|
-
Create 2nd student:
|
621
|
-
Create 3rd student:
|
622
|
-
Create mistake
|
623
|
-
Student created '{:id=>3, :course=>"what ever you want!!!", :student_name=>"Anthony Mistake", :first_name=>"Anthony", :last_name=>"Mistake", :status=>:active}'
|
624
|
-
Remove mistake
|
625
|
-
Wrong student to remove: 3 = Anthony Mistake
|
626
|
-
List of students for 'Art Drama':
|
627
|
-
{:id=>1, :course=>"Art Drama", :student_name=>"Anthony Hopkins", :first_name=>"Anthony", :last_name=>"Hopkins", :status=>:active}
|
628
|
-
{:id=>2, :course=>"Art Drama", :student_name=>"Marilyn Monroe", :first_name=>"Marilyn", :last_name=>"Monroe", :status=>:active}
|
629
|
-
Deleted students:
|
630
|
-
{:id=>3, :course=>"what ever you want!!!", :student_name=>"Anthony Mistake", :first_name=>"Anthony", :last_name=>"Mistake", :status=>:removed}
|
87
|
+
* version 4:
|
88
|
+
In this version, we are going to improve the process, to find way to simplify
|
89
|
+
the previous code.
|
631
90
|
|
632
|
-
|
91
|
+
[Details is explained here](example/students_4/student_v4_md.html)
|
633
92
|
|
634
|
-
|
93
|
+
* version 5:
|
94
|
+
Update the version 4 to fully implement the example of an yaml_student API.
|
95
|
+
ie :
|
96
|
+
Reproducind what the main `examples/yaml_students/students.rb` is doing.<BR>
|
97
|
+
The API is `examples/yaml_students/yaml_students.rb`
|
635
98
|
|
636
|
-
|
99
|
+
[Details is explained here](example/students_5/student_v5_md.html)
|
637
100
|
|
638
|
-
|
101
|
+
# What next?
|
639
102
|
|
640
|
-
|
103
|
+
If you want to understand the concept, check [here](lib/concept_md.html)
|
641
104
|
|
642
|
-
|
643
|
-
* Lorj::Account - Based on Lorj::Config, it introduces an **account** file, between **local config** and **runtime**.
|
644
|
-
* Logging system - Based on logger. A log file contains all data until debug. It prints to the console only data specified by PrcLib::.level
|
645
|
-
* lorj.setup - This function works with Lorj::Account. Thanks an application data definition (defaults.yaml), lorj ask the user information to build an account. Those data will be loaded and used by your process/controller flow.
|
105
|
+
If you want to get an overview of functionnalities per context, see [here](lib/overview_md.html)
|
646
106
|
|
647
107
|
For details, see API documentation.
|
648
108
|
|