ionoscloud-dbaas-mongo 1.0.0 → 1.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +3 -3
  3. data/README.md +6 -2
  4. data/docs/README.md +56 -0
  5. data/docs/api/ClustersApi.md +78 -0
  6. data/docs/api/UsersApi.md +82 -0
  7. data/docs/models/ClusterProperties.md +1 -1
  8. data/docs/models/Connection.md +1 -1
  9. data/docs/models/CreateClusterProperties.md +1 -1
  10. data/docs/models/PatchClusterProperties.md +26 -0
  11. data/docs/models/PatchClusterRequest.md +20 -0
  12. data/docs/models/PatchUserProperties.md +20 -0
  13. data/docs/models/PatchUserRequest.md +20 -0
  14. data/docs/models/TemplateList.md +11 -1
  15. data/docs/models/TemplateListAllOf.md +4 -0
  16. data/docs/models/TemplateResponse.md +4 -0
  17. data/docs/models/UserProperties.md +0 -2
  18. data/lib/ionoscloud-dbaas-mongo/api/clusters_api.rb +71 -0
  19. data/lib/ionoscloud-dbaas-mongo/api/users_api.rb +83 -0
  20. data/lib/ionoscloud-dbaas-mongo/api_client.rb +1 -1
  21. data/lib/ionoscloud-dbaas-mongo/models/cluster_properties.rb +1 -1
  22. data/lib/ionoscloud-dbaas-mongo/models/connection.rb +1 -1
  23. data/lib/ionoscloud-dbaas-mongo/models/create_cluster_properties.rb +1 -1
  24. data/lib/ionoscloud-dbaas-mongo/models/patch_cluster_properties.rb +322 -0
  25. data/lib/ionoscloud-dbaas-mongo/models/patch_cluster_request.rb +244 -0
  26. data/lib/ionoscloud-dbaas-mongo/models/patch_user_properties.rb +259 -0
  27. data/lib/ionoscloud-dbaas-mongo/models/patch_user_request.rb +244 -0
  28. data/lib/ionoscloud-dbaas-mongo/models/resource_type.rb +1 -0
  29. data/lib/ionoscloud-dbaas-mongo/models/template_list.rb +123 -4
  30. data/lib/ionoscloud-dbaas-mongo/models/template_list_all_of.rb +36 -1
  31. data/lib/ionoscloud-dbaas-mongo/models/template_response.rb +37 -1
  32. data/lib/ionoscloud-dbaas-mongo/models/user_properties.rb +19 -23
  33. data/lib/ionoscloud-dbaas-mongo/version.rb +1 -1
  34. data/lib/ionoscloud-dbaas-mongo.rb +4 -0
  35. data/sonar-project.properties +12 -0
  36. metadata +12 -2
@@ -38,7 +38,7 @@ module IonoscloudDbaasMongo
38
38
  # @option config [Configuration] Configuration for initializing the object, default to Configuration.default
39
39
  def initialize(config = Configuration.default)
40
40
  @config = config
41
- @user_agent = "sdk-ruby-dbaas-mongo/v1.0.0"
41
+ @user_agent = "sdk-ruby-dbaas-mongo/v1.1.0"
42
42
  @default_headers = {
43
43
  'Content-Type' => 'application/json',
44
44
  'User-Agent' => @user_agent
@@ -39,7 +39,7 @@ module IonoscloudDbaasMongo
39
39
  attr_accessor :maintenance_window
40
40
 
41
41
 
42
- # The unique ID of the template, which specifies the number of cores, storage size, and memory.
42
+ # The unique ID of the template, which specifies the number of cores, storage size, and memory. You cannot downgrade to a smaller template or minor edition (e.g. from business to playground). To get a list of all templates to confirm the changes use the /templates endpoint.
43
43
  attr_accessor :template_id
44
44
 
45
45
 
@@ -25,7 +25,7 @@ module IonoscloudDbaasMongo
25
25
  attr_accessor :lan_id
26
26
 
27
27
 
28
- # The list of IPs and subnet for your cluster. Note the following unavailable IP ranges: 10.233.64.0/18 10.233.0.0/18 10.233.114.0/24
28
+ # The list of IPs for your cluster. All IPs must be in a /24 network. Note the following unavailable IP ranges: 10.233.114.0/24
29
29
  attr_accessor :cidr_list
30
30
 
31
31
  # Attribute mapping from ruby-style variable name to JSON key.
@@ -17,7 +17,7 @@ module IonoscloudDbaasMongo
17
17
  # The properties with all data needed to create a new MongoDB cluster.
18
18
  class CreateClusterProperties
19
19
 
20
- # The unique ID of the template, which specifies the number of cores, storage size, and memory.
20
+ # The unique ID of the template, which specifies the number of cores, storage size, and memory. You cannot downgrade to a smaller template or minor edition (e.g. from business to playground). To get a list of all templates to confirm the changes use the /templates endpoint.
21
21
  attr_accessor :template_id
22
22
 
23
23
 
@@ -0,0 +1,322 @@
1
+ =begin
2
+ #IONOS DBaaS MongoDB REST API
3
+
4
+ #With IONOS Cloud Database as a Service, you have the ability to quickly set up and manage a MongoDB database. You can also delete clusters, manage backups and users via the API. MongoDB is an open source, cross-platform, document-oriented database program. Classified as a NoSQL database program, it uses JSON-like documents with optional schemas. The MongoDB API allows you to create additional database clusters or modify existing ones. Both tools, the Data Center Designer (DCD) and the API use the same concepts consistently and are well suited for smooth and intuitive use.
5
+
6
+ The version of the OpenAPI document: 0.1.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ OpenAPI Generator version: 5.2.1-SNAPSHOT
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module IonoscloudDbaasMongo
17
+ # Properties of the payload to change a cluster.
18
+ class PatchClusterProperties
19
+
20
+ # The name of your cluster.
21
+ attr_accessor :display_name
22
+
23
+
24
+ attr_accessor :maintenance_window
25
+
26
+
27
+ # The total number of instances in the cluster (one primary and n-1 secondaries).
28
+ attr_accessor :instances
29
+
30
+
31
+ attr_accessor :connections
32
+
33
+
34
+ # The unique ID of the template, which specifies the number of cores, storage size, and memory. You cannot downgrade to a smaller template or minor edition (e.g. from business to playground). To get a list of all templates to confirm the changes use the /templates endpoint.
35
+ attr_accessor :template_id
36
+
37
+ # Attribute mapping from ruby-style variable name to JSON key.
38
+ def self.attribute_map
39
+ {
40
+
41
+ :'display_name' => :'displayName',
42
+
43
+ :'maintenance_window' => :'maintenanceWindow',
44
+
45
+ :'instances' => :'instances',
46
+
47
+ :'connections' => :'connections',
48
+
49
+ :'template_id' => :'templateID'
50
+ }
51
+ end
52
+
53
+ # Returns all the JSON keys this model knows about
54
+ def self.acceptable_attributes
55
+ attribute_map.values
56
+ end
57
+
58
+ # Attribute type mapping.
59
+ def self.openapi_types
60
+ {
61
+
62
+ :'display_name' => :'String',
63
+
64
+ :'maintenance_window' => :'MaintenanceWindow',
65
+
66
+ :'instances' => :'Integer',
67
+
68
+ :'connections' => :'Array<Connection>',
69
+
70
+ :'template_id' => :'String'
71
+ }
72
+ end
73
+
74
+ # List of attributes with nullable: true
75
+ def self.openapi_nullable
76
+ Set.new([
77
+
78
+
79
+
80
+
81
+
82
+ ])
83
+ end
84
+
85
+ # Initializes the object
86
+ # @param [Hash] attributes Model attributes in the form of hash
87
+ def initialize(attributes = {})
88
+ if (!attributes.is_a?(Hash))
89
+ fail ArgumentError, "The input argument (attributes) must be a hash in `IonoscloudDbaasMongo::PatchClusterProperties` initialize method"
90
+ end
91
+
92
+ # check to see if the attribute exists and convert string to symbol for hash key
93
+ attributes = attributes.each_with_object({}) { |(k, v), h|
94
+ if (!self.class.attribute_map.key?(k.to_sym))
95
+ fail ArgumentError, "`#{k}` is not a valid attribute in `IonoscloudDbaasMongo::PatchClusterProperties`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
96
+ end
97
+ h[k.to_sym] = v
98
+ }
99
+
100
+
101
+ if attributes.key?(:'display_name')
102
+ self.display_name = attributes[:'display_name']
103
+ end
104
+
105
+
106
+ if attributes.key?(:'maintenance_window')
107
+ self.maintenance_window = attributes[:'maintenance_window']
108
+ end
109
+
110
+
111
+ if attributes.key?(:'instances')
112
+ self.instances = attributes[:'instances']
113
+ end
114
+
115
+
116
+ if attributes.key?(:'connections') && (value = attributes[:'connections']).is_a?(Array)
117
+ self.connections = value
118
+ end
119
+
120
+
121
+ if attributes.key?(:'template_id')
122
+ self.template_id = attributes[:'template_id']
123
+ end
124
+ end
125
+
126
+ # Show invalid properties with the reasons. Usually used together with valid?
127
+ # @return Array for valid properties with the reasons
128
+ def list_invalid_properties
129
+ invalid_properties = Array.new
130
+
131
+
132
+
133
+
134
+ if !@connections.nil? && @connections.length > 1
135
+ invalid_properties.push('invalid value for "connections", number of items must be less than or equal to 1.')
136
+ end
137
+
138
+ if !@connections.nil? && @connections.length < 0
139
+ invalid_properties.push('invalid value for "connections", number of items must be greater than or equal to 0.')
140
+ end
141
+
142
+
143
+ invalid_properties
144
+ end
145
+
146
+ # Check to see if the all the properties in the model are valid
147
+ # @return true if the model is valid
148
+ def valid?
149
+
150
+
151
+
152
+
153
+ return false if !@connections.nil? && @connections.length > 1
154
+ return false if !@connections.nil? && @connections.length < 0
155
+
156
+ true
157
+ end
158
+
159
+
160
+
161
+
162
+
163
+ # Custom attribute writer method with validation
164
+ # @param [Object] connections Value to be assigned
165
+ def connections=(connections)
166
+ if !connections.nil? && connections.length > 1
167
+ fail ArgumentError, 'invalid value for "connections", number of items must be less than or equal to 1.'
168
+ end
169
+
170
+ if !connections.nil? && connections.length < 0
171
+ fail ArgumentError, 'invalid value for "connections", number of items must be greater than or equal to 0.'
172
+ end
173
+
174
+ @connections = connections
175
+ end
176
+
177
+
178
+ # Checks equality by comparing each attribute.
179
+ # @param [Object] Object to be compared
180
+ def ==(o)
181
+ return true if self.equal?(o)
182
+ self.class == o.class &&
183
+ display_name == o.display_name &&
184
+ maintenance_window == o.maintenance_window &&
185
+ instances == o.instances &&
186
+ connections == o.connections &&
187
+ template_id == o.template_id
188
+ end
189
+
190
+ # @see the `==` method
191
+ # @param [Object] Object to be compared
192
+ def eql?(o)
193
+ self == o
194
+ end
195
+
196
+ # Calculates hash code according to all attributes.
197
+ # @return [Integer] Hash code
198
+ def hash
199
+ [display_name, maintenance_window, instances, connections, template_id].hash
200
+ end
201
+
202
+ # Builds the object from hash
203
+ # @param [Hash] attributes Model attributes in the form of hash
204
+ # @return [Object] Returns the model itself
205
+ def self.build_from_hash(attributes)
206
+ new.build_from_hash(attributes)
207
+ end
208
+
209
+ # Builds the object from hash
210
+ # @param [Hash] attributes Model attributes in the form of hash
211
+ # @return [Object] Returns the model itself
212
+ def build_from_hash(attributes)
213
+ return nil unless attributes.is_a?(Hash)
214
+ self.class.openapi_types.each_pair do |key, type|
215
+ if attributes[self.class.attribute_map[key]].nil? && self.class.openapi_nullable.include?(key)
216
+ self.send("#{key}=", nil)
217
+ elsif type =~ /\AArray<(.*)>/i
218
+ # check to ensure the input is an array given that the attribute
219
+ # is documented as an array but the input is not
220
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
221
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map { |v| _deserialize($1, v) })
222
+ end
223
+ elsif !attributes[self.class.attribute_map[key]].nil?
224
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
225
+ end
226
+ end
227
+
228
+ self
229
+ end
230
+
231
+ # Deserializes the data based on type
232
+ # @param string type Data type
233
+ # @param string value Value to be deserialized
234
+ # @return [Object] Deserialized data
235
+ def _deserialize(type, value)
236
+ case type.to_sym
237
+ when :Time
238
+ Time.parse(value)
239
+ when :Date
240
+ Date.parse(value)
241
+ when :String
242
+ value.to_s
243
+ when :Integer
244
+ value.to_i
245
+ when :Float
246
+ value.to_f
247
+ when :Boolean
248
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
249
+ true
250
+ else
251
+ false
252
+ end
253
+ when :Object
254
+ # generic object (usually a Hash), return directly
255
+ value
256
+ when /\AArray<(?<inner_type>.+)>\z/
257
+ inner_type = Regexp.last_match[:inner_type]
258
+ value.map { |v| _deserialize(inner_type, v) }
259
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
260
+ k_type = Regexp.last_match[:k_type]
261
+ v_type = Regexp.last_match[:v_type]
262
+ {}.tap do |hash|
263
+ value.each do |k, v|
264
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
265
+ end
266
+ end
267
+ else # model
268
+ # models (e.g. Pet) or oneOf
269
+ klass = IonoscloudDbaasMongo.const_get(type)
270
+ klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
271
+ end
272
+ end
273
+
274
+ # Returns the string representation of the object
275
+ # @return [String] String presentation of the object
276
+ def to_s
277
+ to_hash.to_s
278
+ end
279
+
280
+ # to_body is an alias to to_hash (backward compatibility)
281
+ # @return [Hash] Returns the object in the form of hash
282
+ def to_body
283
+ to_hash
284
+ end
285
+
286
+ # Returns the object in the form of hash
287
+ # @return [Hash] Returns the object in the form of hash
288
+ def to_hash
289
+ hash = {}
290
+ self.class.attribute_map.each_pair do |attr, param|
291
+ value = self.send(attr)
292
+ if value.nil?
293
+ is_nullable = self.class.openapi_nullable.include?(attr)
294
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
295
+ end
296
+
297
+ hash[param] = _to_hash(value)
298
+ end
299
+ hash
300
+ end
301
+
302
+ # Outputs non-array value in the form of hash
303
+ # For object, use to_hash. Otherwise, just return the value
304
+ # @param [Object] value Any valid value
305
+ # @return [Hash] Returns the value in the form of hash
306
+ def _to_hash(value)
307
+ if value.is_a?(Array)
308
+ value.compact.map { |v| _to_hash(v) }
309
+ elsif value.is_a?(Hash)
310
+ {}.tap do |hash|
311
+ value.each { |k, v| hash[k] = _to_hash(v) }
312
+ end
313
+ elsif value.respond_to? :to_hash
314
+ value.to_hash
315
+ else
316
+ value
317
+ end
318
+ end
319
+
320
+ end
321
+
322
+ end
@@ -0,0 +1,244 @@
1
+ =begin
2
+ #IONOS DBaaS MongoDB REST API
3
+
4
+ #With IONOS Cloud Database as a Service, you have the ability to quickly set up and manage a MongoDB database. You can also delete clusters, manage backups and users via the API. MongoDB is an open source, cross-platform, document-oriented database program. Classified as a NoSQL database program, it uses JSON-like documents with optional schemas. The MongoDB API allows you to create additional database clusters or modify existing ones. Both tools, the Data Center Designer (DCD) and the API use the same concepts consistently and are well suited for smooth and intuitive use.
5
+
6
+ The version of the OpenAPI document: 0.1.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ OpenAPI Generator version: 5.2.1-SNAPSHOT
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module IonoscloudDbaasMongo
17
+ # Request payload to change a cluster.
18
+ class PatchClusterRequest
19
+
20
+ attr_accessor :metadata
21
+
22
+
23
+ attr_accessor :properties
24
+
25
+ # Attribute mapping from ruby-style variable name to JSON key.
26
+ def self.attribute_map
27
+ {
28
+
29
+ :'metadata' => :'metadata',
30
+
31
+ :'properties' => :'properties'
32
+ }
33
+ end
34
+
35
+ # Returns all the JSON keys this model knows about
36
+ def self.acceptable_attributes
37
+ attribute_map.values
38
+ end
39
+
40
+ # Attribute type mapping.
41
+ def self.openapi_types
42
+ {
43
+
44
+ :'metadata' => :'Metadata',
45
+
46
+ :'properties' => :'PatchClusterProperties'
47
+ }
48
+ end
49
+
50
+ # List of attributes with nullable: true
51
+ def self.openapi_nullable
52
+ Set.new([
53
+
54
+
55
+ ])
56
+ end
57
+
58
+ # Initializes the object
59
+ # @param [Hash] attributes Model attributes in the form of hash
60
+ def initialize(attributes = {})
61
+ if (!attributes.is_a?(Hash))
62
+ fail ArgumentError, "The input argument (attributes) must be a hash in `IonoscloudDbaasMongo::PatchClusterRequest` initialize method"
63
+ end
64
+
65
+ # check to see if the attribute exists and convert string to symbol for hash key
66
+ attributes = attributes.each_with_object({}) { |(k, v), h|
67
+ if (!self.class.attribute_map.key?(k.to_sym))
68
+ fail ArgumentError, "`#{k}` is not a valid attribute in `IonoscloudDbaasMongo::PatchClusterRequest`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
69
+ end
70
+ h[k.to_sym] = v
71
+ }
72
+
73
+
74
+ if attributes.key?(:'metadata')
75
+ self.metadata = attributes[:'metadata']
76
+ end
77
+
78
+
79
+ if attributes.key?(:'properties')
80
+ self.properties = attributes[:'properties']
81
+ end
82
+ end
83
+
84
+ # Show invalid properties with the reasons. Usually used together with valid?
85
+ # @return Array for valid properties with the reasons
86
+ def list_invalid_properties
87
+ invalid_properties = Array.new
88
+
89
+
90
+ invalid_properties
91
+ end
92
+
93
+ # Check to see if the all the properties in the model are valid
94
+ # @return true if the model is valid
95
+ def valid?
96
+
97
+
98
+ true
99
+ end
100
+
101
+
102
+
103
+ # Checks equality by comparing each attribute.
104
+ # @param [Object] Object to be compared
105
+ def ==(o)
106
+ return true if self.equal?(o)
107
+ self.class == o.class &&
108
+ metadata == o.metadata &&
109
+ properties == o.properties
110
+ end
111
+
112
+ # @see the `==` method
113
+ # @param [Object] Object to be compared
114
+ def eql?(o)
115
+ self == o
116
+ end
117
+
118
+ # Calculates hash code according to all attributes.
119
+ # @return [Integer] Hash code
120
+ def hash
121
+ [metadata, properties].hash
122
+ end
123
+
124
+ # Builds the object from hash
125
+ # @param [Hash] attributes Model attributes in the form of hash
126
+ # @return [Object] Returns the model itself
127
+ def self.build_from_hash(attributes)
128
+ new.build_from_hash(attributes)
129
+ end
130
+
131
+ # Builds the object from hash
132
+ # @param [Hash] attributes Model attributes in the form of hash
133
+ # @return [Object] Returns the model itself
134
+ def build_from_hash(attributes)
135
+ return nil unless attributes.is_a?(Hash)
136
+ self.class.openapi_types.each_pair do |key, type|
137
+ if attributes[self.class.attribute_map[key]].nil? && self.class.openapi_nullable.include?(key)
138
+ self.send("#{key}=", nil)
139
+ elsif type =~ /\AArray<(.*)>/i
140
+ # check to ensure the input is an array given that the attribute
141
+ # is documented as an array but the input is not
142
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
143
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map { |v| _deserialize($1, v) })
144
+ end
145
+ elsif !attributes[self.class.attribute_map[key]].nil?
146
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
147
+ end
148
+ end
149
+
150
+ self
151
+ end
152
+
153
+ # Deserializes the data based on type
154
+ # @param string type Data type
155
+ # @param string value Value to be deserialized
156
+ # @return [Object] Deserialized data
157
+ def _deserialize(type, value)
158
+ case type.to_sym
159
+ when :Time
160
+ Time.parse(value)
161
+ when :Date
162
+ Date.parse(value)
163
+ when :String
164
+ value.to_s
165
+ when :Integer
166
+ value.to_i
167
+ when :Float
168
+ value.to_f
169
+ when :Boolean
170
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
171
+ true
172
+ else
173
+ false
174
+ end
175
+ when :Object
176
+ # generic object (usually a Hash), return directly
177
+ value
178
+ when /\AArray<(?<inner_type>.+)>\z/
179
+ inner_type = Regexp.last_match[:inner_type]
180
+ value.map { |v| _deserialize(inner_type, v) }
181
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
182
+ k_type = Regexp.last_match[:k_type]
183
+ v_type = Regexp.last_match[:v_type]
184
+ {}.tap do |hash|
185
+ value.each do |k, v|
186
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
187
+ end
188
+ end
189
+ else # model
190
+ # models (e.g. Pet) or oneOf
191
+ klass = IonoscloudDbaasMongo.const_get(type)
192
+ klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
193
+ end
194
+ end
195
+
196
+ # Returns the string representation of the object
197
+ # @return [String] String presentation of the object
198
+ def to_s
199
+ to_hash.to_s
200
+ end
201
+
202
+ # to_body is an alias to to_hash (backward compatibility)
203
+ # @return [Hash] Returns the object in the form of hash
204
+ def to_body
205
+ to_hash
206
+ end
207
+
208
+ # Returns the object in the form of hash
209
+ # @return [Hash] Returns the object in the form of hash
210
+ def to_hash
211
+ hash = {}
212
+ self.class.attribute_map.each_pair do |attr, param|
213
+ value = self.send(attr)
214
+ if value.nil?
215
+ is_nullable = self.class.openapi_nullable.include?(attr)
216
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
217
+ end
218
+
219
+ hash[param] = _to_hash(value)
220
+ end
221
+ hash
222
+ end
223
+
224
+ # Outputs non-array value in the form of hash
225
+ # For object, use to_hash. Otherwise, just return the value
226
+ # @param [Object] value Any valid value
227
+ # @return [Hash] Returns the value in the form of hash
228
+ def _to_hash(value)
229
+ if value.is_a?(Array)
230
+ value.compact.map { |v| _to_hash(v) }
231
+ elsif value.is_a?(Hash)
232
+ {}.tap do |hash|
233
+ value.each { |k, v| hash[k] = _to_hash(v) }
234
+ end
235
+ elsif value.respond_to? :to_hash
236
+ value.to_hash
237
+ else
238
+ value
239
+ end
240
+ end
241
+
242
+ end
243
+
244
+ end