lorj 0.1.0
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 +7 -0
- data/.gitignore +14 -0
- data/.gitreview +4 -0
- data/Gemfile +25 -0
- data/Gemfile.lock +34 -0
- data/LICENSE.txt +14 -0
- data/README.md +652 -0
- data/Rakefile +24 -0
- data/bin/cloud_test.rb +81 -0
- data/example/students_1/process/Students.rb +20 -0
- data/example/students_1/students.rb +16 -0
- data/example/students_2/process/Students.rb +27 -0
- data/example/students_2/students.rb +36 -0
- data/example/students_3/controller/yaml_students.rb +94 -0
- data/example/students_3/controller/yaml_students_controller.rb +123 -0
- data/example/students_3/process/students.rb +118 -0
- data/example/students_3/students.rb +93 -0
- data/example/students_4/controller/yaml_students.rb +82 -0
- data/example/students_4/controller/yaml_students_controller.rb +141 -0
- data/example/students_4/process/students.rb +112 -0
- data/example/students_4/students.rb +103 -0
- data/example/yaml_students/students.rb +78 -0
- data/example/yaml_students/yaml_students.rb +115 -0
- data/lib/concept.md +111 -0
- data/lib/core/core.rb +723 -0
- data/lib/core/definition.rb +505 -0
- data/lib/core/definition_internal.rb +338 -0
- data/lib/core/lorj-basecontroller.rb +90 -0
- data/lib/core/lorj-basedefinition.rb +1079 -0
- data/lib/core/lorj-baseprocess.rb +231 -0
- data/lib/core/lorj-data.rb +567 -0
- data/lib/core/lorj-keypath.rb +115 -0
- data/lib/core_process/CloudProcess.rb +334 -0
- data/lib/core_process/global_process.rb +406 -0
- data/lib/core_process/network_process.rb +603 -0
- data/lib/img/.directory +4 -0
- data/lib/img/account_data_access.png +0 -0
- data/lib/img/config_data_access.png +0 -0
- data/lib/img/forj-lib-concept.png +0 -0
- data/lib/lorj/version.rb +3 -0
- data/lib/lorj.rb +51 -0
- data/lib/prc-account.rb +339 -0
- data/lib/prc-config.rb +1023 -0
- data/lib/prc-logging.rb +183 -0
- data/lib/prc.rb +108 -0
- data/lib/providers/hpcloud/Hpcloud.rb +419 -0
- data/lib/providers/hpcloud/compute.rb +108 -0
- data/lib/providers/hpcloud/network.rb +117 -0
- data/lib/providers/hpcloud/security_groups.rb +67 -0
- data/lib/providers/mock/Mock.rb +141 -0
- data/lib/providers/openstack/Openstack.rb +47 -0
- data/lib/providers/templates/compute.rb +42 -0
- data/lib/providers/templates/core.rb +61 -0
- data/lib/providers/templates/network.rb +33 -0
- data/lorj-spec/defaults.yaml +26 -0
- data/lorj.gemspec +39 -0
- data/spec/forj-account_spec.rb +75 -0
- data/spec/forj-config_spec.rb +196 -0
- metadata +164 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
# This class describes how to process some actions, and will do everything prior
|
19
|
+
# this task to make it to work.
|
20
|
+
|
21
|
+
# This Mock controller keep the data in memory in hash/Array data.
|
22
|
+
|
23
|
+
# declare yaml student API to the controller
|
24
|
+
cur_path = File.dirname(__FILE__)
|
25
|
+
api_file = File.expand_path(File.join(cur_path, "..", "..", "yaml_students", 'yaml_students.rb'))
|
26
|
+
require api_file
|
27
|
+
|
28
|
+
# The controller is a combination of 2 elements:
|
29
|
+
# - Controller class
|
30
|
+
# Code which will interfere with the external API.
|
31
|
+
#
|
32
|
+
# The file name must respect the name of the class. 1st letter already capitalized and letter after _ is capitalized.
|
33
|
+
# file: my_code.rb => needs to create MyCodeController class
|
34
|
+
#
|
35
|
+
# - Definition class
|
36
|
+
# This class declare any kind of mapping or additional fields to consider.
|
37
|
+
# Additionnal fields are unknow by the process. So, those fields will needs to be setup before.
|
38
|
+
#
|
39
|
+
# file name convention is identical than controller class.
|
40
|
+
# file: my_code.rb => needs to create MyCode class
|
41
|
+
|
42
|
+
controller_file = File.expand_path(File.join(cur_path,'yaml_students_controller.rb'))
|
43
|
+
require controller_file # Load controller mapping
|
44
|
+
|
45
|
+
# Declare
|
46
|
+
# - additional objects and their specific process (:connection using basic predefined :controller_create process)
|
47
|
+
# - data_mapping :
|
48
|
+
# :connection_string => :file_name
|
49
|
+
# :course => :training
|
50
|
+
#
|
51
|
+
# If some data has been added by the controller, the main and process, won't take care and the framework will fails.
|
52
|
+
# To eliminate this errors, there is 2 cases:
|
53
|
+
# - detect this change in the process or the main.
|
54
|
+
# - set it up, using lorj setup function, if the data is declared askable by the controller.
|
55
|
+
# The controller can define how the setup have to ask values, and even can get data
|
56
|
+
# from itself.
|
57
|
+
|
58
|
+
class YamlStudents
|
59
|
+
|
60
|
+
define_obj(:connection,{
|
61
|
+
:create_e => :controller_create # Nothing complex to do. So, simply call the controller create.
|
62
|
+
})
|
63
|
+
|
64
|
+
obj_needs :data, :connection_string, :mapping => :file_name
|
65
|
+
undefine_attribute :id # Do not return any predefined ID
|
66
|
+
undefine_attribute :name # Do not return any predefined NAME
|
67
|
+
|
68
|
+
# The student model has been expanded. The object name will be built from first and last name
|
69
|
+
define_obj(:student)
|
70
|
+
obj_needs :CloudObject, :connection
|
71
|
+
|
72
|
+
set_hdata :first_name
|
73
|
+
set_hdata :last_name
|
74
|
+
set_hdata :course, :mapping => :training
|
75
|
+
|
76
|
+
get_attr_mapping :course, :training
|
77
|
+
|
78
|
+
# This controller will know how to manage a student file with those data.
|
79
|
+
# But note that the file can have a lot of more data than what the process
|
80
|
+
# usually manage. It is up to you to increase your process to manage more data.
|
81
|
+
# Then each controller may need to define mapping fields.
|
82
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
# This class describes how to process some actions, and will do everything prior
|
19
|
+
# this task to make it to work.
|
20
|
+
|
21
|
+
# This Mock controller keep the data in memory in hash/Array data.
|
22
|
+
|
23
|
+
# declare yaml student API to the controller
|
24
|
+
cur_file = File.expand_path(File.join(File.dirname(File.dirname(__FILE__)), "..", "yaml_students", 'yaml_students.rb'))
|
25
|
+
require cur_file
|
26
|
+
|
27
|
+
# The controller is a combination of 2 elements:
|
28
|
+
# - Controller class
|
29
|
+
# Code which will interfere with the external API.
|
30
|
+
#
|
31
|
+
# The file name must respect the name of the class. 1st letter already capitalized and letter after _ is capitalized.
|
32
|
+
# file: my_code.rb => needs to create MyCodeController class
|
33
|
+
#
|
34
|
+
# - Definition class
|
35
|
+
# This class declare any kind of mapping or additional fields to consider.
|
36
|
+
# Additionnal fields are unknow by the process. So, those fields will needs to be setup before.
|
37
|
+
#
|
38
|
+
# file name convention is identical than controller class.
|
39
|
+
# file: my_code.rb => needs to create MyCode class
|
40
|
+
|
41
|
+
class YamlStudentsController
|
42
|
+
def initialize()
|
43
|
+
@@valid_attributes = [:name, :first_name, :last_name, :id, :status, :training]
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def create(sObjectType, hParams)
|
48
|
+
case sObjectType
|
49
|
+
when :connection
|
50
|
+
required?(hParams, :hdata, :file_name)
|
51
|
+
YamlSchool.new(hParams[:hdata, :file_name])
|
52
|
+
when :student
|
53
|
+
required?(hParams, :connection)
|
54
|
+
required?(hParams, :student_name)
|
55
|
+
|
56
|
+
hParams[:connection].create_student(hParams[:student_name], hParams[:hdata])
|
57
|
+
else
|
58
|
+
Error "'%s' is not a valid object for 'create'" % sObjectType
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# This function return a collection which have to provide:
|
63
|
+
# functions: [], length, each
|
64
|
+
# Used by network process.
|
65
|
+
def query(sObjectType, sQuery, hParams)
|
66
|
+
case sObjectType
|
67
|
+
when :student
|
68
|
+
required?(hParams, :connection)
|
69
|
+
|
70
|
+
hParams[:connection].query_student(sQuery)
|
71
|
+
else
|
72
|
+
Error "'%s' is not a valid object for 'create'" % sObjectType
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
def delete(sObjectType, hParams)
|
78
|
+
case sObjectType
|
79
|
+
when :student
|
80
|
+
required?(hParams, :connection)
|
81
|
+
|
82
|
+
hParams[:connection].delete_student(hParams[sObjectType][:id])
|
83
|
+
else
|
84
|
+
Error "'%s' is not a valid object for 'create'" % sObjectType
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def get(sObjectType, sUniqId, hParams)
|
89
|
+
case sObjectType
|
90
|
+
when :student
|
91
|
+
required?(hParams, :connection)
|
92
|
+
|
93
|
+
list = hParams[:connection].query_student({:id => sUniqId})
|
94
|
+
if list.length == 0
|
95
|
+
nil
|
96
|
+
else
|
97
|
+
list[0]
|
98
|
+
end
|
99
|
+
else
|
100
|
+
Error "'%s' is not a valid object for 'create'" % sObjectType
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def get_attr(oControlerObject, key)
|
105
|
+
# This controller function read the data and
|
106
|
+
# extract the information requested by the framework.
|
107
|
+
# Those data will be mapped to the process data model.
|
108
|
+
# The key is an array, to get data from a level tree.
|
109
|
+
# [data_l1, data_l2, data_l3] => should retrieve data from structure like data[ data_l2[ data_l3 ] ]
|
110
|
+
begin
|
111
|
+
attributes = oControlerObject
|
112
|
+
raise "get_attr: attribute '%s' is unknown in '%s'. Valid one are : '%s'" % [key[0], oControlerObject.class, @@valid_attributes ] unless @@valid_attributes.include?(key[0])
|
113
|
+
Lorj::rhGet(attributes, key)
|
114
|
+
rescue => e
|
115
|
+
Error "get_attr: Unable to map '%s'. %s" % [key, e.message]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def set_attr(oControlerObject, key, value)
|
120
|
+
begin
|
121
|
+
attributes = oControlerObject
|
122
|
+
raise "set_attr: attribute '%s' is unknown in '%s'. Valid one are : '%s'" % [key[0], oControlerObject.class, @@valid_attributes ] unless @@valid_attributes.include?(key[0])
|
123
|
+
Lorj::rhSet(attributes, value, key)
|
124
|
+
rescue => e
|
125
|
+
Error "set_attr: Unable to map '%s' on '%s'" % [key, sObjectType]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def update(sObjectType, oObject, hParams)
|
131
|
+
case sObjectType
|
132
|
+
when :student
|
133
|
+
required?(hParams, :connection)
|
134
|
+
|
135
|
+
hParams[:connection].update_student(oObject)
|
136
|
+
else
|
137
|
+
Error "'%s' is not a valid object for 'create'" % sObjectType
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Students process
|
2
|
+
class StudentsProcess
|
3
|
+
def create_student(sObjectType, hParams)
|
4
|
+
PrcLib::state ("Running creation process for object '%s' = '%s'" % [sObjectType, hParams[:student_name] ])
|
5
|
+
|
6
|
+
aStudentName = hParams[:student_name].split(" ")
|
7
|
+
# config object is a reference to runtime/config data.
|
8
|
+
config[:first_name] = aStudentName[0]
|
9
|
+
config[:last_name] = aStudentName[1]
|
10
|
+
|
11
|
+
oList = Query(sObjectType, {:name => hParams[:student_name]})
|
12
|
+
case oList.length
|
13
|
+
when 0
|
14
|
+
oObject = controller_create(sObjectType)
|
15
|
+
raise "Student '%s' not created." % hParams[:student_name] if oObject.nil?
|
16
|
+
PrcLib::info ("'%s': '%s' created with id %s" % [sObjectType, hParams[:student_name], oObject[:id]])
|
17
|
+
when 1
|
18
|
+
oObject = oList[0]
|
19
|
+
PrcLib::info ("'%s': '%s' loaded with id %s" % [sObjectType, hParams[:student_name], oObject[:id]])
|
20
|
+
else
|
21
|
+
oObject = oList[0]
|
22
|
+
PrcLib::warning("More than one student named '%s' is found: %s records. Selecting the first one and removing duplicates." % [hParams[:student_name], oList.length])
|
23
|
+
iCount = 0
|
24
|
+
oList[1..-1].each { | elem |
|
25
|
+
register(elem)
|
26
|
+
iCount += controller_delete(sObjectType)
|
27
|
+
}
|
28
|
+
PrcLib::info ("'%s': %s duplicated '%s' removed. First loaded with id %s" % [sObjectType, iCount, hParams[:student_name], oObject[:id]])
|
29
|
+
end
|
30
|
+
oObject
|
31
|
+
end
|
32
|
+
|
33
|
+
def query_student(sObjectType, sQuery, hParams)
|
34
|
+
PrcLib::state ("Running query process for object '%s' with query '%s'" % [sObjectType, sQuery])
|
35
|
+
|
36
|
+
oObjects = controller_query(sObjectType, sQuery)
|
37
|
+
raise "Query error." if oObjects.nil?
|
38
|
+
|
39
|
+
PrcLib::info ("'%s': Queried. %s records found." % [sObjectType, oObjects.length])
|
40
|
+
oObjects
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_student(sObjectType, sId, hParams)
|
44
|
+
PrcLib::state ("Running get process for object '%s' with ID %s" % [sObjectType, sId ])
|
45
|
+
|
46
|
+
oObject = controller_get(sObjectType, sId)
|
47
|
+
PrcLib::debug("No ID %s found." % sId) if oObject.nil?
|
48
|
+
|
49
|
+
oObject
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete_student(sObjectType, hParams)
|
53
|
+
Error "Unable to delete students, if at least one student is not loaded, or query not defined." if not hParams.exist?(:student) and not hParams.exist?(:query)
|
54
|
+
|
55
|
+
# This student deletion process supports 2 modes:
|
56
|
+
# - Delete from a query field (:query hParams)
|
57
|
+
# - Delete the latest loaded student.
|
58
|
+
|
59
|
+
if hParams.exist?(:query)
|
60
|
+
result = Query(sObjectType, hParams[:query])
|
61
|
+
if result.length > 0
|
62
|
+
result.each { | student |
|
63
|
+
puts "Student to remove: %s = %s" % [student[:id], student[:name]]
|
64
|
+
register(student)
|
65
|
+
controller_delete(:student)
|
66
|
+
PrcLib::info ("'%s:%s' student removed" % [student[:id], student[:name]])
|
67
|
+
}
|
68
|
+
end
|
69
|
+
else
|
70
|
+
controller_delete(:student)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Declaring your data model and handlers.
|
76
|
+
class Lorj::BaseDefinition
|
77
|
+
|
78
|
+
# We need to define the student object and the handler to use while we need to create it.
|
79
|
+
define_obj(:student,
|
80
|
+
{
|
81
|
+
:create_e => :create_student, # The function to call in the class Students
|
82
|
+
:query_e => :query_student,
|
83
|
+
:delete_e => :delete_student,
|
84
|
+
:get_e => :get_student
|
85
|
+
})
|
86
|
+
|
87
|
+
# All obj_needs will be collected and passed to the process handler as hParams.
|
88
|
+
# Data required to create a student
|
89
|
+
obj_needs :data, :student_name, { :for => [:create_e] }
|
90
|
+
|
91
|
+
# Data optional for any kind of event
|
92
|
+
obj_needs_optional
|
93
|
+
obj_needs :data, :query, { :for => [:delete_e] }
|
94
|
+
obj_needs :data, :first_name
|
95
|
+
obj_needs :data, :last_name
|
96
|
+
obj_needs :data, :course
|
97
|
+
|
98
|
+
# Define Data a student object needs to take care.
|
99
|
+
# The controller should map it if needed (if the value exists)
|
100
|
+
# But it can also add some extra attributes not predefined by the process.
|
101
|
+
# Usually, the process should ignore it.
|
102
|
+
# But if it detect it, the process should be careful with this data
|
103
|
+
# which are really specific to only one controller and may break the controller agnostic capability.
|
104
|
+
def_attribute :course
|
105
|
+
def_attribute :first_name
|
106
|
+
def_attribute :last_name
|
107
|
+
def_attribute :name
|
108
|
+
def_attribute :status
|
109
|
+
end
|
110
|
+
|
111
|
+
class Lorj::BaseDefinition
|
112
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$APP_PATH = File.dirname(__FILE__)
|
4
|
+
require 'lorj'
|
5
|
+
require 'ansi'
|
6
|
+
|
7
|
+
# If you want to see what is happening in the framework, uncomment debug settings.
|
8
|
+
#PrcLib.level = Logger::DEBUG # Printed out to your console.
|
9
|
+
#PrcLib.core_level = 3 # framework debug levels. (0 to 5)
|
10
|
+
|
11
|
+
# Load global Config
|
12
|
+
|
13
|
+
# This object is used to provide configuration data to lorj
|
14
|
+
|
15
|
+
# The config search is:
|
16
|
+
# 1- Application defaults (defaults.yaml) - Not defined by default. update the following line and create defaults.yaml
|
17
|
+
# PrcLib.app_defaults = $APP_PATH
|
18
|
+
# 2- Local defaults (~/.<Application Name>/config.yaml) - <Application Name> is 'Lorj' by default. Can be updated with following line.
|
19
|
+
# PrcLib.app_name = 'myapp'
|
20
|
+
# 3 - runtime. Those variables are set, with oConfig[key] = value
|
21
|
+
|
22
|
+
oConfig = Lorj::Config.new() # Use Simple Config Object
|
23
|
+
|
24
|
+
# You can use an account object, which add an extra account level
|
25
|
+
# between runtime and config.yaml/app default
|
26
|
+
# oConfig = Lorj::Account.new('MyAccount')
|
27
|
+
|
28
|
+
|
29
|
+
# Initialize the framework
|
30
|
+
# Use students process
|
31
|
+
hProcesses = [ File.join($APP_PATH, 'process', 'students.rb')]
|
32
|
+
# Use yaml_students controller
|
33
|
+
sController = File.join($APP_PATH, 'controller', 'yaml_students.rb')
|
34
|
+
oStudentCore = Lorj::Core.new( oConfig, hProcesses, sController )
|
35
|
+
|
36
|
+
# This kind of connection_string should be part of an Account Data.
|
37
|
+
# So, we won't need to set this config.
|
38
|
+
# But you can imagine to set at runtime this config as well.
|
39
|
+
oConfig[:connection_string] = "/tmp/students.yaml"
|
40
|
+
|
41
|
+
# Note that we have commented the next line.
|
42
|
+
# oStudentCore.Create(:connection, :connection_string => "/tmp/students.yaml")
|
43
|
+
# This call is not required, as the framework has all the information to create
|
44
|
+
# the connection, at the first time this connection is required.
|
45
|
+
# ie, while starting to create a student.
|
46
|
+
|
47
|
+
|
48
|
+
# Set the student name to use
|
49
|
+
oConfig[:student_name] = "Robert Redford"
|
50
|
+
|
51
|
+
# Ask the framework to create the object student 'Robert Redford'
|
52
|
+
puts ANSI.bold("Create 1st student:")
|
53
|
+
oStudentCore.Create(:student)
|
54
|
+
# The connection is made because creating a student requires
|
55
|
+
# the object :connection. (See example/students_4/controller/yaml_students.rb, around line 70)
|
56
|
+
|
57
|
+
puts ANSI.bold("Create 2nd student:")
|
58
|
+
# Want to create a duplicated student 'Robert Redford'?
|
59
|
+
oStudentCore.Create(:student)
|
60
|
+
# Because the process ensure that there is no duplicate, this won't create duplicates
|
61
|
+
|
62
|
+
# We can set runtime configuration instantly from the Create call
|
63
|
+
# The following line :
|
64
|
+
puts ANSI.bold("Create 3rd student:")
|
65
|
+
oStudentCore.Create(:student, {:student_name => "Anthony Hopkins"})
|
66
|
+
# replaced the following :
|
67
|
+
# oConfig[:student_name] = "Anthony Hopkins"
|
68
|
+
# oStudentCore.Create(:student)
|
69
|
+
|
70
|
+
# Let's query students named "Robert Redford"
|
71
|
+
puts ANSI.bold("Querying students as 'Robert Redford':")
|
72
|
+
oStudents = oStudentCore.Query(:student, { :name => "Robert Redford" } )
|
73
|
+
|
74
|
+
puts "%s students found for '%s':" % [oStudents.length, "Robert Redford"]
|
75
|
+
|
76
|
+
oStudents.each { | oStudent |
|
77
|
+
puts "%s: %s" % [oStudent[:id], oStudent[:name]]
|
78
|
+
}
|
79
|
+
|
80
|
+
# let's check the get function, who is the ID 2?
|
81
|
+
puts ANSI.bold("Who is student ID 2?")
|
82
|
+
oStudent = oStudentCore.Get(:student, 2)
|
83
|
+
|
84
|
+
puts "\nThe student ID 2 is %s" % oStudent[:name] unless oStudent.nil?
|
85
|
+
puts "\nThe student ID 2 doesn't exist." if oStudent.nil?
|
86
|
+
|
87
|
+
puts ANSI.bold("Create mistake")
|
88
|
+
oStudentCore.Create(:student, {
|
89
|
+
:student_name => "Anthony Mistake",
|
90
|
+
:course => 'what ever you want!!!'
|
91
|
+
})
|
92
|
+
|
93
|
+
# The query logic has been implemented directly in the process,
|
94
|
+
# so now, any kind of controller Delete will have the same behavior...
|
95
|
+
puts ANSI.bold("Remove mistake")
|
96
|
+
hQuery = { :name => "Anthony Mistake"}
|
97
|
+
oStudentCore.Delete(:student, :query => hQuery)
|
98
|
+
|
99
|
+
puts ANSI.bold("List of students for 'Art Drama':")
|
100
|
+
puts oStudentCore.Query(:student, { :course => "Art Drama"}).to_a
|
101
|
+
|
102
|
+
puts ANSI.bold("Deleted students:")
|
103
|
+
puts oStudentCore.Query(:student,{ :status => :removed}).to_a
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# encoding: UTF-8
|
4
|
+
|
5
|
+
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'ansi'
|
21
|
+
|
22
|
+
$APP_PATH = File.dirname(__FILE__)
|
23
|
+
|
24
|
+
require File.join($APP_PATH, 'yaml_students.rb')
|
25
|
+
|
26
|
+
school = YamlSchool.new('/tmp/students.yaml')
|
27
|
+
|
28
|
+
puts ANSI.bold("Create 1st student:")
|
29
|
+
if school.query_student({:name => "Robert Redford"}).length == 0
|
30
|
+
school.create_student("Robert Redford", {
|
31
|
+
first_name: 'Robert',
|
32
|
+
last_name: 'Redford',
|
33
|
+
training: 'Art Comedy'
|
34
|
+
})
|
35
|
+
end
|
36
|
+
|
37
|
+
puts ANSI.bold("Create 2nd student:")
|
38
|
+
if school.query_student({:name => "Anthony Hopkins"}).length == 0
|
39
|
+
school.create_student("Anthony Hopkins", {
|
40
|
+
first_name: 'Anthony',
|
41
|
+
last_name: 'Hopkins',
|
42
|
+
training: 'Art Drama'
|
43
|
+
})
|
44
|
+
end
|
45
|
+
|
46
|
+
puts ANSI.bold("Create 3rd student:")
|
47
|
+
if school.query_student({:name => "Marilyn Monroe"}).length == 0
|
48
|
+
school.create_student("Marilyn Monroe", {
|
49
|
+
first_name: 'Marilyn',
|
50
|
+
last_name: 'Mistake',
|
51
|
+
training: 'Art Drama'
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
puts ANSI.bold("Create mistake")
|
56
|
+
oStudent = school.create_student("Anthony Mistake", {
|
57
|
+
first_name: 'Anthony',
|
58
|
+
last_name: 'Mistake',
|
59
|
+
training: 'what ever you want!!!'
|
60
|
+
})
|
61
|
+
|
62
|
+
puts "Student created: '%s'" % oStudent
|
63
|
+
|
64
|
+
puts ANSI.bold("Remove mistake")
|
65
|
+
result = school.query_student({:name => "Anthony Mistake"})
|
66
|
+
if result.length > 0
|
67
|
+
result.each { | student |
|
68
|
+
puts "Wrong student to remove: %s = %s" % [student[:id], student[:name]]
|
69
|
+
school.delete_student(student[:id])
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
puts ANSI.bold("List of students for 'Art Drama':")
|
75
|
+
puts school.query_student({ :training => "Art Drama"})
|
76
|
+
|
77
|
+
puts ANSI.bold("Deleted students:")
|
78
|
+
puts school.query_student({ :status => :removed})
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
# This class describes how to process some actions, and will do everything prior
|
19
|
+
# this task to make it to work.
|
20
|
+
|
21
|
+
require 'yaml'
|
22
|
+
|
23
|
+
class YamlSchool
|
24
|
+
attr_accessor :sFile
|
25
|
+
attr_accessor :hData
|
26
|
+
|
27
|
+
def initialize(sFile)
|
28
|
+
@hData = { :students => []}
|
29
|
+
@sFile = sFile
|
30
|
+
load_data()
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_data()
|
34
|
+
if File.exists?(@sFile)
|
35
|
+
@hData = YAML.load_file(@sFile)
|
36
|
+
@hData = { :students => []} if not @hData
|
37
|
+
@hData[:students] = [] unless @hData.key?(:students)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def save_data()
|
42
|
+
begin
|
43
|
+
File.open(@sFile, 'w') do |out|
|
44
|
+
YAML.dump(@hData, out)
|
45
|
+
end
|
46
|
+
rescue => e
|
47
|
+
Lorj.error("%s\n%s" % [e.message, e.backtrace.join("\n")])
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_student(name, fields)
|
54
|
+
|
55
|
+
if fields[ :first_name].nil? or fields[ :last_name].nil?
|
56
|
+
puts "YAML API: Unable to create a student. :first_name and :last_name required."
|
57
|
+
return nil
|
58
|
+
end
|
59
|
+
|
60
|
+
result = fields.clone
|
61
|
+
result[:name] = name
|
62
|
+
result[:name] = "%s %s" % [result[:first_name], result[:first_name]] if name.nil?
|
63
|
+
result[:status] = :active
|
64
|
+
|
65
|
+
@hData[:students] << result
|
66
|
+
|
67
|
+
result[:id] = @hData[:students].length()-1
|
68
|
+
|
69
|
+
save_data()
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
def delete_student(sId)
|
74
|
+
return false unless File.exists?(sFile)
|
75
|
+
|
76
|
+
@hData[:students].each { | value |
|
77
|
+
hElem = value
|
78
|
+
if value[:id] == sId
|
79
|
+
@hData[:students][sId][:status] = :removed
|
80
|
+
save_data()
|
81
|
+
return 1
|
82
|
+
end
|
83
|
+
}
|
84
|
+
0
|
85
|
+
end
|
86
|
+
|
87
|
+
def query_student(sQuery)
|
88
|
+
|
89
|
+
result = []
|
90
|
+
|
91
|
+
@hData[:students].each { | value |
|
92
|
+
hElem = value
|
93
|
+
sQuery.each { | query_key, query_value |
|
94
|
+
hElem = nil if (
|
95
|
+
value.key?(:status) and
|
96
|
+
value[:status] != :active and
|
97
|
+
not sQuery.key?(:status)) or
|
98
|
+
not value.key?(query_key) or
|
99
|
+
value[query_key] != query_value
|
100
|
+
}
|
101
|
+
result << hElem if hElem
|
102
|
+
}
|
103
|
+
result
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
def update_student(sId, fields)
|
108
|
+
aList = query_student({ :id => Id})
|
109
|
+
if aList.length == 1
|
110
|
+
aList[0].merge(fields)
|
111
|
+
end
|
112
|
+
save_data()
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|