lorj 1.0.9 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/example/students_1/process/students.rb +1 -1
  4. data/example/students_1/student_v1.md +2 -0
  5. data/example/students_1/students.rb +2 -1
  6. data/example/students_2/process/students.rb +1 -1
  7. data/example/students_2/students.rb +4 -2
  8. data/example/students_3/controller/yaml_students_def.rb +1 -1
  9. data/example/students_3/process/students.rb +1 -1
  10. data/example/students_3/student_v3.md +5 -3
  11. data/example/students_3/students.rb +5 -3
  12. data/example/students_4/controller/yaml_students_def.rb +1 -1
  13. data/example/students_4/process/students/definition/students.rb +1 -1
  14. data/example/students_4/students.rb +5 -3
  15. data/example/students_5/controller/yaml_students.rb +1 -1
  16. data/example/students_5/process/students.rb +1 -1
  17. data/example/students_5/student_v5.md +4 -4
  18. data/example/students_5/students.rb +8 -7
  19. data/example/yaml_students/students.rb +4 -4
  20. data/lib/core/core.rb +110 -64
  21. data/lib/core/core_internal.rb +110 -15
  22. data/lib/core/core_object_data.rb +4 -4
  23. data/lib/core/core_process_setup.rb +3 -30
  24. data/lib/core/lorj_data.rb +1 -1
  25. data/lib/core/lorj_keypath.rb +3 -1
  26. data/lib/core/process.rb +67 -0
  27. data/lib/lorj/version.rb +2 -1
  28. data/lib/lorj.rb +3 -4
  29. data/lib/lorj_account.rb +6 -5
  30. data/lib/lorj_config.rb +3 -2
  31. data/lib/providers/templates/compute.rb +1 -1
  32. data/lorj-spec/controllers/mock/mock.rb +144 -0
  33. data/lorj-spec/data.yaml +0 -0
  34. data/lorj-spec/process/mock2_process.rb +48 -0
  35. data/lorj-spec/process/mock_process.rb +48 -0
  36. data/lorj-spec/providers/mock2/mock2.rb +0 -0
  37. data/lorj.gemspec +2 -4
  38. data/spec/05_lorj_keypath_spec.rb +78 -0
  39. data/spec/20_lorj_meta_spec.rb +1 -1
  40. data/spec/21_lorj_processes_spec.rb +115 -0
  41. metadata +27 -42
  42. data/lib/core_process/cloud/process/common.rb +0 -60
  43. data/lib/core_process/cloud/process/connection.rb +0 -92
  44. data/lib/core_process/cloud/process/external_network.rb +0 -90
  45. data/lib/core_process/cloud/process/flavor.rb +0 -97
  46. data/lib/core_process/cloud/process/images.rb +0 -99
  47. data/lib/core_process/cloud/process/internet_network.rb +0 -33
  48. data/lib/core_process/cloud/process/internet_server.rb +0 -29
  49. data/lib/core_process/cloud/process/keypairs.rb +0 -332
  50. data/lib/core_process/cloud/process/network.rb +0 -107
  51. data/lib/core_process/cloud/process/public_ip.rb +0 -102
  52. data/lib/core_process/cloud/process/router.rb +0 -267
  53. data/lib/core_process/cloud/process/rules.rb +0 -120
  54. data/lib/core_process/cloud/process/security_groups.rb +0 -120
  55. data/lib/core_process/cloud/process/server.rb +0 -126
  56. data/lib/core_process/cloud/process/server_log.rb +0 -34
  57. data/lib/core_process/cloud/process/subnetwork.rb +0 -96
  58. data/lib/core_process/cloud_process.rb +0 -30
  59. data/lib/prc_base_config.rb +0 -300
  60. data/lib/prc_core_config.rb +0 -1258
  61. data/lib/prc_section_config.rb +0 -90
  62. data/lib/providers/hpcloud/compute.rb +0 -105
  63. data/lib/providers/hpcloud/hpcloud.rb +0 -462
  64. data/lib/providers/hpcloud/network.rb +0 -115
  65. data/lib/providers/hpcloud/security_groups.rb +0 -68
  66. data/lib/providers/openstack/openstack.rb +0 -410
  67. data/lib/providers/openstack/openstack_create.rb +0 -205
  68. data/lib/providers/openstack/openstack_delete.rb +0 -28
  69. data/lib/providers/openstack/openstack_get.rb +0 -39
  70. data/lib/providers/openstack/openstack_process.rb +0 -26
  71. data/lib/providers/openstack/openstack_query.rb +0 -96
  72. data/lib/providers/openstack/openstack_update.rb +0 -35
  73. data/lib/rh.rb +0 -426
  74. data/spec/01_hash_rh_spec.rb +0 -282
  75. data/spec/02_prc_base_config_spec.rb +0 -227
  76. data/spec/03_prc_section_config_spec.rb +0 -196
  77. data/spec/04_prc_core_config_spec.rb +0 -325
@@ -1,126 +0,0 @@
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
- # It requires Core objects to be defined + default ForjProcess functions.
18
-
19
- # rubocop: disable Style/ClassAndModuleChildren
20
-
21
- # ---------------------------------------------------------------------------
22
- # Server management
23
- # ---------------------------------------------------------------------------
24
- class CloudProcess
25
- # Process Handler functions
26
- def forj_get_or_create_server(sCloudObj, hParams)
27
- server_name = hParams[:server_name]
28
- PrcLib.state("Searching for server '%s'", server_name)
29
- servers = forj_query_server(sCloudObj, { :name => server_name }, hParams)
30
- if servers.length > 0
31
- # Get server details
32
- forj_get_server(sCloudObj, servers[0][:attrs][:id], hParams)
33
- else
34
- create_server(sCloudObj, hParams)
35
- end
36
- end
37
-
38
- def forj_delete_server(sCloudObj, hParams)
39
- ssl_error_obj = SSLErrorMgt.new
40
- begin
41
- controller_delete(sCloudObj)
42
- PrcLib.info('Server %s was destroyed ', hParams[:server][:name])
43
- rescue => e
44
- retry unless ssl_error_obj.error_detected(e.message, e.backtrace, e)
45
- end
46
- end
47
-
48
- def forj_query_server(sCloudObj, sQuery, _hParams)
49
- ssl_error_obj = SSLErrorMgt.new
50
- begin
51
- controller_query(sCloudObj, sQuery)
52
- rescue => e
53
- retry unless ssl_error_obj.error_detected(e.message, e.backtrace, e)
54
- end
55
- end
56
-
57
- def forj_get_server(sCloudObj, sId, _hParams)
58
- ssl_error_obj = SSLErrorMgt.new
59
- begin
60
- controller_get(sCloudObj, sId)
61
- rescue => e
62
- retry unless ssl_error_obj.error_detected(e.message, e.backtrace, e)
63
- end
64
- end
65
- end
66
-
67
- # SERVER Object
68
- # Identify the server to use/build on the network/...
69
- class Lorj::BaseDefinition
70
- define_obj(:server,
71
-
72
- :create_e => :forj_get_or_create_server,
73
- :query_e => :forj_query_server,
74
- :get_e => :forj_get_server,
75
- # :update_e => :forj_update_server,
76
- :delete_e => :forj_delete_server
77
- )
78
-
79
- obj_needs :CloudObject, :compute_connection
80
- obj_needs :CloudObject, :flavor, :for => [:create_e]
81
- obj_needs :CloudObject, :network, :for => [:create_e]
82
- obj_needs :CloudObject, :security_groups, :for => [:create_e]
83
- obj_needs :CloudObject, :keypairs, :for => [:create_e]
84
- obj_needs :CloudObject, :image, :for => [:create_e]
85
- obj_needs :data, :server_name, :for => [:create_e]
86
-
87
- obj_needs_optional
88
- obj_needs :data, :user_data, :for => [:create_e]
89
- obj_needs :data, :meta_data, :for => [:create_e]
90
-
91
- def_attribute :status
92
- predefine_data_value :create, :desc => 'Server is creating.'
93
- predefine_data_value :boot, :desc => 'Server is booting.'
94
- predefine_data_value :active, :desc => 'Server is started.'
95
- def_attribute :private_ip_address
96
- def_attribute :public_ip_address
97
-
98
- def_attribute :image_id
99
- def_attribute :key_name
100
- end
101
-
102
- # Internal Process function
103
- class CloudProcess
104
- def create_server(sCloudObj, hParams)
105
- name = hParams[:server_name]
106
- begin
107
- PrcLib.info('boot: meta-data provided.') if hParams[:meta_data]
108
- PrcLib.info('boot: user-data provided.') if hParams[:user_data]
109
- PrcLib.state('creating server %s', name)
110
- server = controller_create(sCloudObj)
111
- PrcLib.info("%s '%s' created.", sCloudObj, name)
112
- rescue => e
113
- PrcLib.fatal(1, "Unable to create server '%s'", name, e)
114
- end
115
- server
116
- end
117
-
118
- def forj_get_server_log(sCloudObj, sId, _hParams)
119
- ssl_error_obj = SSLErrorMgt.new
120
- begin
121
- controller_get(sCloudObj, sId)
122
- rescue => e
123
- retry unless ssl_error_obj.error_detected(e.message, e.backtrace, e)
124
- end
125
- end
126
- end
@@ -1,34 +0,0 @@
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
- # It requires Core objects to be defined + default ForjProcess functions.
18
-
19
- # rubocop: disable Style/ClassAndModuleChildren
20
-
21
- # SERVER Console Object
22
- # Object representing the console log attached to a server
23
- class Lorj::BaseDefinition
24
- define_obj(:server_log,
25
-
26
- :get_e => :forj_get_server_log
27
- )
28
-
29
- obj_needs :CloudObject, :server
30
- obj_needs :data, :log_lines
31
- undefine_attribute :name
32
- undefine_attribute :id
33
- def_attribute :output
34
- end
@@ -1,96 +0,0 @@
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
- # It requires Core objects to be defined + default ForjProcess functions.
18
-
19
- # rubocop: disable Style/ClassAndModuleChildren
20
-
21
- # Subnetwork Management
22
- class CloudProcess
23
- def forj_get_or_create_subnetwork(sCloudObj, hParams)
24
- subnets = query_subnet(sCloudObj, hParams)
25
- unless subnets.length == 0
26
- register(subnets[0])
27
- return subnets[0]
28
- end
29
-
30
- # Create the subnet
31
- subnet = create_subnet(sCloudObj, hParams)
32
-
33
- return nil if subnet.nil?
34
- register(subnet)
35
- subnet
36
- end
37
- end
38
-
39
- # Define framework object on BaseDefinition
40
- # Identify subnetwork as part of network.
41
- class Lorj::BaseDefinition
42
- define_obj(:subnetwork,
43
- :create_e => :forj_get_or_create_subnetwork
44
- )
45
-
46
- obj_needs :CloudObject, :network_connection
47
- obj_needs :CloudObject, :network
48
- obj_needs :data, :subnetwork_name
49
-
50
- def_attribute :network_id
51
- end
52
-
53
- # Subnetwork Management - internal functions
54
- class CloudProcess
55
- def create_subnet(sCloudObj, hParams)
56
- name = hParams[:subnetwork_name]
57
- PrcLib.state("Creating subnet '%s'", name)
58
- begin
59
- subnet = controller_create(sCloudObj, hParams)
60
- PrcLib.info("Subnet '%s' created.", subnet[:name])
61
- rescue => e
62
- PrcLib.fatal(1, "Unable to create '%s' subnet.", name, e)
63
- end
64
- subnet
65
- end
66
-
67
- def delete_subnet
68
- net_conn_obj = get_cloudObj(:network_connection)
69
- sub_net_obj = get_cloudObj(:subnetwork)
70
-
71
- PrcLib.state("Deleting subnet '%s'", sub_net_obj.name)
72
- begin
73
- provider_delete_subnetwork(net_conn_obj, sub_net_obj)
74
- net_conn_obj.subnets.get(sub_net_obj.id).destroy
75
- rescue => e
76
- PrcLib.error("%s\n%s", e.message, e.backtrace.join("\n"))
77
- end
78
- end
79
-
80
- def query_subnet(sCloudObj, hParams)
81
- PrcLib.state('Searching for sub-network attached to '\
82
- "network '%s'", hParams[:network, :name])
83
- #######################
84
- begin
85
- query = { :network_id => hParams[:network, :id] }
86
- info = {
87
- :notfound => "No %s found from '%s' network",
88
- :checkmatch => "Found 1 %s. checking exact match for network '%s'.",
89
- :nomatch => "No %s for network '%s' match"
90
- }
91
- query_single(sCloudObj, query, hParams[:network, :name], info)
92
- rescue => e
93
- PrcLib.error("%s\n%s", e.message, e.backtrace.join("\n"))
94
- end
95
- end
96
- end
@@ -1,30 +0,0 @@
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
- # It requires Core objects to be defined + default ForjProcess functions.
18
-
19
- cloud_path = File.dirname(__FILE__)
20
-
21
- # Define model
22
-
23
- lorj_objects = %w(common connection network subnetwork router
24
- external_network security_groups rules
25
- keypairs images flavor internet_network server public_ip
26
- server_log internet_server)
27
-
28
- lorj_objects.each do |name|
29
- load File.join(cloud_path, 'cloud', 'process', name + '.rb')
30
- end
@@ -1,300 +0,0 @@
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
- require 'yaml'
18
-
19
- module PRC
20
- # This class is Base config system of lorj.
21
- #
22
- # It implements basic config features:
23
- # * #erase - To cleanup all data in self config
24
- # * #[] - To get a value for a key or tree of keys
25
- # * #[]= - To set a value for a key in the tree.
26
- # * #exist? - To check the existence of a value from a key
27
- # * #del - To delete a key tree.
28
- # * #save - To save all data in a yaml file
29
- # * #load - To load data from a yaml file
30
- # * #data_options - To influence on how exist?, [], []=, load and save will
31
- # behave
32
- #
33
- # Config Data are managed as Hash of Hashes.
34
- # It uses actively Hash.rh_* functions. See rh.rb.
35
- class BaseConfig
36
- # internal Hash data of this config.
37
- # Do not use it except if you know what you are doing.
38
- attr_reader :data
39
-
40
- # * *set*: set the config file name. It accepts relative or absolute path to
41
- # the file.
42
- # * *get*: get the config file name used by #load and #save.
43
- attr_accessor :filename
44
-
45
- # config layer version
46
- attr_accessor :version
47
-
48
- # initialize BaseConfig
49
- #
50
- # * *Args*
51
- # - +keys+ : Array of key path to found
52
- #
53
- # * *Returns*
54
- # - boolean : true if the key path was found
55
- #
56
- # ex:
57
- # value = CoreConfig.New({ :test => {:titi => 'found'}})
58
- # # => creates a CoreConfig with this Hash of Hash
59
- def initialize(value = nil)
60
- @data = {}
61
- @data = value if value.is_a?(Hash)
62
- @data_options = {} # Options for exist?/set/get/load/save
63
- end
64
-
65
- # data_options set data options used by exist?, get, set, load and save
66
- # functions.
67
- #
68
- # CoreConfig class type, call data_options to set options, before calling
69
- # functions: exist?, get, set, load and save.
70
- #
71
- # Currently, data_options implements:
72
- # - :data_readonly : The data cannot be updated. set will not update
73
- # the value.
74
- # - :file_readonly : The file used to load data cannot be updated.
75
- # save will not update the file.
76
- #
77
- # The child class can superseed or replace data options with their own
78
- # options.
79
- # Ex: If your child class want to introduce notion of sections,
80
- # you can define the following with get:
81
- #
82
- # class MySection < PRC::BaseConfig
83
- # # by default, section name to use by get/set is :default
84
- # def data_options(options = {:section => :default})
85
- # p_data_options(options)
86
- # end
87
- #
88
- # def [](*keys)
89
- # p_get(@data_options[:section], *keys)
90
- # end
91
- #
92
- # def []=(*keys, value)
93
- # p_set(@data_options[:section], *keys, value)
94
- # end
95
- # end
96
- #
97
- # * *Args*
98
- # - +keys+ : Array of key path to found
99
- #
100
- # * *Returns*
101
- # - boolean : true if the key path was found
102
- def data_options(options = nil)
103
- p_data_options options
104
- end
105
-
106
- # exist?
107
- #
108
- # * *Args*
109
- # - +keys+ : Array of key path to found
110
- #
111
- # * *Returns*
112
- # - boolean : true if the key path was found
113
- #
114
- # ex:
115
- # { :test => {:titi => 'found'}}
116
- def exist?(*keys)
117
- p_exist?(*keys)
118
- end
119
-
120
- # Erase the data in the object. internal version is cleared as well.
121
- #
122
- # * *Returns*
123
- # - Hash : {}.
124
- #
125
- def erase
126
- @version = nil
127
- @data = {}
128
- end
129
-
130
- # Get function
131
- #
132
- # * *Args*
133
- # - +keys+ : Array of key path to found
134
- #
135
- # * *Returns*
136
- # -
137
- #
138
- def [](*keys)
139
- p_get(*keys)
140
- end
141
-
142
- # Set function
143
- #
144
- # * *Args*
145
- # - +keys+ : set a value in the Array of key path.
146
- #
147
- # * *Returns*
148
- # - The value set or nil
149
- #
150
- # ex:
151
- # value = CoreConfig.New
152
- #
153
- # value[:level1, :level2] = 'value'
154
- # # => {:level1 => {:level2 => 'value'}}
155
-
156
- def del(*keys)
157
- p_del(*keys)
158
- end
159
-
160
- # Set function
161
- #
162
- # * *Args*
163
- # - +keys+ : set a value in the Array of key path.
164
- #
165
- # * *Returns*
166
- # - The value set or nil
167
- #
168
- # ex:
169
- # value = CoreConfig.New
170
- #
171
- # value[:level1, :level2] = 'value'
172
- # # => {:level1 => {:level2 => 'value'}}
173
- def []=(*keys, value)
174
- p_set(*keys, value)
175
- end
176
-
177
- # Load from a file
178
- #
179
- # * *Args* :
180
- # - +filename+ : file name to load. This file name will become the default
181
- # file name to use next time.
182
- # * *Returns* :
183
- # - true if loaded.
184
- # * *Raises* :
185
- # - ++ ->
186
- def load(filename = nil)
187
- p_load(filename)
188
- end
189
-
190
- # Save to a file
191
- #
192
- # * *Args* :
193
- # - +filename+ : file name to save. This file name will become the default
194
- # file name to use next time.
195
- # * *Returns* :
196
- # - boolean if saved or not. true = saved.
197
- def save(filename = nil)
198
- p_save(filename)
199
- end
200
-
201
- # transform keys from string to symbol until deep level. Default is 1.
202
- #
203
- # * *Args* :
204
- # - +level+ : Default 1. level to transform
205
- #
206
- # * *Returns* :
207
- # - it self, with config updated.
208
- def rh_key_to_symbol(level = 1)
209
- data.rh_key_to_symbol level
210
- end
211
-
212
- # Check the need to transform keys from string to symbol until deep level.
213
- # Default is 1.
214
- #
215
- # * *Args* :
216
- # - +level+ : Default 1: levels to verify
217
- #
218
- # * *Returns* :
219
- # - true if need to be updated.
220
- #
221
- def rh_key_to_symbol?(level = 1)
222
- data.rh_key_to_symbol? level
223
- end
224
-
225
- # Redefine the file name attribute set.
226
- #
227
- # * *Args* :
228
- # - +filename+ : default file name to use.
229
- # * *Returns* :
230
- # - filename
231
- def filename=(filename) #:nodoc:
232
- @filename = File.expand_path(filename) unless filename.nil?
233
- end
234
-
235
- # Print a representation of the Layer data
236
- def to_s
237
- msg = format("File : %s\n", @filename)
238
- msg += data.to_yaml
239
- msg
240
- end
241
-
242
- private
243
-
244
- def p_data_options(options = nil)
245
- @data_options = options unless options.nil?
246
- @data_options
247
- end
248
-
249
- def p_exist?(*keys)
250
- return nil if keys.length == 0
251
-
252
- (@data.rh_exist?(*keys))
253
- end
254
-
255
- def p_get(*keys)
256
- return nil if keys.length == 0
257
-
258
- @data.rh_get(*keys)
259
- end
260
-
261
- def p_del(*keys)
262
- return nil if keys.length == 0
263
-
264
- @data.rh_del(*keys)
265
- end
266
-
267
- def p_set(*keys, value)
268
- return nil if keys.length == 0
269
- return p_get(*keys) if @data_options[:data_readonly]
270
-
271
- @data.rh_set(value, keys)
272
- end
273
-
274
- def p_load(file = nil)
275
- self.filename = file unless file.nil?
276
-
277
- fail 'Config filename not set.' if @filename.nil?
278
-
279
- @data = YAML.load_file(File.expand_path(@filename))
280
- if @data.key?(:file_version)
281
- @version = @data[:file_version]
282
- @data.delete(:file_version)
283
- end
284
- true
285
- end
286
-
287
- def p_save(file = nil)
288
- return false if @data_options[:file_readonly]
289
- self.filename = file unless file.nil?
290
-
291
- fail 'Config filename not set.' if @filename.nil?
292
-
293
- @data.delete(:file_version)
294
- @data[:file_version] = @version unless @version.nil?
295
-
296
- File.open(@filename, 'w+') { |out| YAML.dump(@data, out) }
297
- true
298
- end
299
- end
300
- end