ibm-cloud-sdk 0.1.4 → 0.1.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 181a2894e2d8045bea0d2a33cf81570480eee1f668017b8ade96b1801d0465b2
4
- data.tar.gz: 5399f7e3e4f4b483a72e673d351605cb1f8bb09f216e5fd1a9439742f736aedf
3
+ metadata.gz: dc39c6125bcaf6730a73477c76e7e40d2eb131cf6ca34466537d65f615ed8e6a
4
+ data.tar.gz: ac29b18c76bff0ed290878e12007f1bf639654ed239ce7c27e99431acde25a17
5
5
  SHA512:
6
- metadata.gz: 237fd30c5dd4efa622de5be57a2df9e2285dcabc3d15f415d6efb6bec31b36254cbaf6c3cb32a6d8b7113b7e8709e4eddee64736515030e5e3227694dc464b4e
7
- data.tar.gz: ed36bdf032519bc35c1563f62fe279f6744b3f25b97fef4358ebd689958a48a17a5a1eafbf85f72a3c62e372dfb764b35463cc292eede788b3ad127170664ced
6
+ metadata.gz: 845d945f1e0722745858a2256decc3fd73628fd172ba88a8e49a51a7edbf06418965cc609566288e31c2965ff88f2eff33f7691628bd33ef26da0309827c5058
7
+ data.tar.gz: ee6c2c63c3472db99d9d773d77e045180594958b0ee4627b964f64365e1ea6a07c7a3159706ef326d9b87702a97218d7648c057737b14e4afc02bf4f40ae6c5f
@@ -1,6 +1,29 @@
1
1
  # Changelog
2
2
  All notable changes to the gem ibm-cloud-sdk-ruby will be documented here.
3
3
 
4
+ ## v0.1.9 - 2020-10-02
5
+ - Fix PowerVS Volume attach/detach calls
6
+
7
+ ## v0.1.8 - 2020-10-01
8
+ - Add second level instances
9
+
10
+ ## v0.1.7 - 2020-09-28
11
+ - Added Logging in IBM Cloud
12
+ - Add VCR to vpc spec
13
+ - Add exception when status of response is not in 200 range or 404
14
+ - Power IaaS Update docstrings, VM actions volumes
15
+
16
+ ## v0.1.6 - 2020-09-23
17
+ - Add PowerIaaS method to get instance info
18
+ - Return region specific PowerVS storage types
19
+ - Move VPC instance into instances and add initialization method.
20
+
21
+ ## v0.1.5 - 2020-09-21
22
+ - Added Enumerable based pagination support
23
+ - Move instance profiles
24
+ - Improve resource lookup by GUID
25
+ - Add support to create a PowerIaas volume
26
+
4
27
  ## v0.1.4 - 2020-09-17
5
28
  - Added support for the IBM Virtual Private Cloud (VPC) service
6
29
 
data/Gemfile CHANGED
@@ -5,3 +5,5 @@ gemspec
5
5
 
6
6
  gem "rake", "~> 12.0"
7
7
  gem "rspec", "~> 3.0"
8
+ gem 'vcr'
9
+ gem 'webmock'
@@ -8,6 +8,7 @@ require "ibm/cloud/sdk/power_iaas"
8
8
  require "ibm/cloud/sdk/resource_controller"
9
9
  require "ibm/cloud/sdk/version"
10
10
  require "ibm/cloud/sdk/vpc/cloud_sdk"
11
+ require "ibm/cloud/sdk/logging"
11
12
 
12
13
  module IBM
13
14
  module Cloud
@@ -0,0 +1,21 @@
1
+ require_relative 'null_logger'
2
+
3
+ module IBM
4
+ module Cloud
5
+ module SDK
6
+ class << self
7
+ attr_writer :logger
8
+ end
9
+
10
+ def self.logger
11
+ @logger ||= NullLogger.new
12
+ end
13
+
14
+ module Logging
15
+ def logger
16
+ IBM::Cloud::SDK.logger
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ require "logger"
2
+
3
+ module IBM
4
+ module Cloud
5
+ module SDK
6
+ class NullLogger < Logger
7
+ def initialize(*_args)
8
+ end
9
+
10
+ def add(*_args, &_block)
11
+ end
12
+
13
+ def debug?
14
+ false
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,7 +1,11 @@
1
+ require_relative 'logging'
2
+
1
3
  module IBM
2
4
  module Cloud
3
5
  module SDK
4
6
  class PowerIaas < BaseService
7
+ include Logging
8
+
5
9
  # Create an API Client object for the Power IaaS service
6
10
  #
7
11
  # @param region [String] the IBM Power Cloud instance region
@@ -15,12 +19,23 @@ module IBM
15
19
  @region = region
16
20
  @token = token
17
21
  @tenant = tenant
22
+ RestClient.log = logger
18
23
  end
19
24
 
25
+ # Get the API service Endpoint URL
26
+ #
27
+ # @return [String] Endpoint URL
20
28
  def endpoint
21
29
  "https://#{region.sub(/-\d$/, '')}.power-iaas.cloud.ibm.com/pcloud/v1"
22
30
  end
23
31
 
32
+ # Get Power Cloud Instance information
33
+ #
34
+ # @return [Hash] CloudInstance
35
+ def get_pcloud_instance
36
+ get("cloud-instances/#{guid}")
37
+ end
38
+
24
39
  # Get all PVM instances in an IBM Power Cloud instance
25
40
  #
26
41
  # @return [Array<Hash>] all PVM Instances for this instance
@@ -34,12 +49,15 @@ module IBM
34
49
 
35
50
  # Get an IBM Power Cloud PVM instance
36
51
  #
37
- # @param pvm_instance_id [String] the PVM instance ID
52
+ # @param pvm_instance_id [String] PVM instance ID
38
53
  # @return [Hash] PVM Instances
39
54
  def get_pvm_instance(instance_id)
40
55
  get("cloud-instances/#{guid}/pvm-instances/#{instance_id}")
41
56
  end
42
57
 
58
+ # Perform 'start' action on a PVMInstance
59
+ #
60
+ # @param pvm_instance_id [String] PVM instance ID
43
61
  def start_pvm_instance(instance_id)
44
62
  post(
45
63
  "cloud-instances/#{guid}/pvm-instances/#{instance_id}/action",
@@ -47,6 +65,9 @@ module IBM
47
65
  )
48
66
  end
49
67
 
68
+ # Perform 'stop' action on a PVMInstance
69
+ #
70
+ # @param pvm_instance_id [String] PVM instance ID
50
71
  def stop_pvm_instance(instance_id)
51
72
  post(
52
73
  "cloud-instances/#{guid}/pvm-instances/#{instance_id}/action",
@@ -54,6 +75,22 @@ module IBM
54
75
  )
55
76
  end
56
77
 
78
+ # Perform 'immediate-shutdown' action on a PVMInstance
79
+ #
80
+ # @param pvm_instance_id [String] PVM instance ID
81
+ def immediate_shutdown_pvm_instance(instance_id)
82
+ post(
83
+ "cloud-instances/#{guid}/pvm-instances/#{instance_id}/action",
84
+ {"action" => "immediate-shutdown"}.to_json
85
+ )
86
+ end
87
+
88
+ # Perform 'reboot' action on a PVMInstance
89
+ #
90
+ # This action has been deprecated and replaced by 'soft-reboot'
91
+ # and 'hard-reboot'
92
+ #
93
+ # @param pvm_instance_id [String] PVM instance ID
57
94
  def reboot_pvm_instance(instance_id)
58
95
  post(
59
96
  "cloud-instances/#{guid}/pvm-instances/#{instance_id}/action",
@@ -61,10 +98,47 @@ module IBM
61
98
  )
62
99
  end
63
100
 
101
+ # Perform 'soft-reboot' action on a PVMInstance
102
+ #
103
+ # @param pvm_instance_id [String] PVM instance ID
104
+ def soft_reboot_pvm_instance(instance_id)
105
+ post(
106
+ "cloud-instances/#{guid}/pvm-instances/#{instance_id}/action",
107
+ {"action" => "soft-reboot"}.to_json
108
+ )
109
+ end
110
+
111
+ # Perform 'hard-reboot' action on a PVMInstance
112
+ #
113
+ # @param pvm_instance_id [String] PVM instance ID
114
+ def hard_reboot_pvm_instance(instance_id)
115
+ post(
116
+ "cloud-instances/#{guid}/pvm-instances/#{instance_id}/action",
117
+ {"action" => "hard-reboot"}.to_json
118
+ )
119
+ end
120
+
121
+ # Perform 'reset-state' action on a PVMInstance
122
+ #
123
+ # @param pvm_instance_id [String] PVM instance ID
124
+ def reset_state_pvm_instance(instance_id)
125
+ post(
126
+ "cloud-instances/#{guid}/pvm-instances/#{instance_id}/action",
127
+ {"action" => "reset-state"}.to_json
128
+ )
129
+ end
130
+
131
+ # Create a new PVM instance
132
+ #
133
+ # @param instance_hash [Hash] New instance attributes
134
+ # @return [Hash] PVMInstance
64
135
  def create_pvm_instance(instance_hash)
65
136
  post("cloud-instances/#{guid}/pvm-instances", instance_hash.to_json)
66
137
  end
67
138
 
139
+ # Delete a PVM instance
140
+ #
141
+ # @param pvm_instance_id [String] PVM instance ID
68
142
  def delete_pvm_instance(instance_id)
69
143
  delete("cloud-instances/#{guid}/pvm-instances/#{instance_id}")
70
144
  end
@@ -82,7 +156,7 @@ module IBM
82
156
 
83
157
  # Get an IBM Power Cloud image
84
158
  #
85
- # @param image_id [String] The ID of an Image
159
+ # @param image_id [String] Image ID
86
160
  # @return [Hash] Image
87
161
  def get_image(image_id)
88
162
  get("cloud-instances/#{guid}/images/#{image_id}")
@@ -90,6 +164,9 @@ module IBM
90
164
  nil
91
165
  end
92
166
 
167
+ # Delete an image from a cloud instance
168
+ #
169
+ # @param image_id [String] Image ID
93
170
  def delete_image(image_id)
94
171
  delete("cloud-instances/#{guid}/images/#{image_id}")
95
172
  end
@@ -107,7 +184,7 @@ module IBM
107
184
 
108
185
  # Get a specific volume
109
186
  #
110
- # @param volume_id [String] The ID of a volume
187
+ # @param volume_id [String] Image ID
111
188
  # @return [Hash] Volume
112
189
  def get_volume(volume_id)
113
190
  get("cloud-instances/#{guid}/volumes/#{volume_id}")
@@ -115,11 +192,35 @@ module IBM
115
192
 
116
193
  # Delete a volume
117
194
  #
118
- # @param volume_id [String] The ID of a volume
195
+ # @param volume_id [String] Volume ID
119
196
  def delete_volume(volume_id)
120
197
  delete("cloud-instances/#{guid}/volumes/#{volume_id}")
121
198
  end
122
199
 
200
+ # Create a volume
201
+ #
202
+ # @param volume_hash [Hash] New volume attributes
203
+ # @return [Hash] Volume
204
+ def create_volume(volume_hash)
205
+ post("cloud-instances/#{guid}/volumes", volume_hash.to_json)
206
+ end
207
+
208
+ # Attach a volume
209
+ #
210
+ # @param pvm_instance_id [String] PVM Instance ID
211
+ # @param volume_id [String] Volume ID
212
+ def attach_volume(pvm_instance_id, volume_id)
213
+ post("cloud-instances/#{guid}/pvm-instances/#{pvm_instance_id}/volumes/#{volume_id}", {})
214
+ end
215
+
216
+ # Detach a volume
217
+ #
218
+ # @param pvm_instance_id [String] PVM Instance ID
219
+ # @param volume_id [String] Volume ID
220
+ def detach_volume(pvm_instance_id, volume_id)
221
+ delete("cloud-instances/#{guid}/pvm-instances/#{pvm_instance_id}/volumes/#{volume_id}")
222
+ end
223
+
123
224
  # Get all networks in an IBM Power Cloud instance
124
225
  #
125
226
  # @return [Array<Hash>] all networks for this IBM Power Cloud instance
@@ -132,7 +233,7 @@ module IBM
132
233
 
133
234
  # Get an IBM Power Cloud network
134
235
  #
135
- # @param network_id [String] the network ID
236
+ # @param network_id [String] Network ID
136
237
  # @return [Hash] Network
137
238
  def get_network(network_id)
138
239
  get("cloud-instances/#{guid}/networks/#{network_id}")
@@ -146,42 +247,64 @@ module IBM
146
247
  end
147
248
 
148
249
  # Get a storage types list in IBM Power Cloud.
149
- # note: this mehod to be refactored under the common
250
+ # note: this method to be refactored under the common
150
251
  # IBM::Cloud::SDK::PowerIaas.endpoint when the rest api become available.
151
252
  #
152
- # @return [Hash] StorageType
253
+ # @return [Array<Hash>] StorageType
153
254
  def get_storage_types
154
- JSON.parse(RestClient.get("https://#{region.sub(/-\d$/, '')}.power-iaas.cloud.ibm.com/broker/v1/storage-types", headers))
255
+ JSON.parse(RestClient.get("https://#{region.sub(/-\d$/, '')}.power-iaas.cloud.ibm.com/broker/v1/storage-types", headers))[region]
155
256
  end
156
257
 
258
+ # Create a new network
259
+ #
260
+ # @param network_hash [Hash] New network attributes
261
+ # @return [Hash] Network
157
262
  def create_network(network_hash)
158
263
  post("cloud-instances/#{guid}/networks", network_hash.to_json)
159
264
  end
160
265
 
266
+ # Delete a network
267
+ #
268
+ # @param network_id [String] Network ID
161
269
  def delete_network(network_id)
162
270
  delete("cloud-instances/#{guid}/networks/#{network_id}")
163
271
  end
164
272
 
273
+ # Get all ports for a network
274
+ #
275
+ # @param network_id [String] Network ID
276
+ # @return [Array<Hash>] NetworkPort
165
277
  def get_network_ports(network_id)
166
278
  get("cloud-instances/#{guid}/networks/#{network_id}/ports")["ports"]
167
279
  end
168
280
 
281
+ # List the tenant's SSH Keys
282
+ #
283
+ # @return [Array<Hash>] SSHKey
169
284
  def get_ssh_keys
170
285
  get("tenants/#{tenant}")["sshKeys"]
171
286
  end
172
287
 
288
+ # Add a new SSH key to the tenant
289
+ #
290
+ # @param name [String] User defined name for the SSH key
291
+ # @param sshkey [String] SSH RSA key
292
+ # @return [Hash] SSHKey
173
293
  def create_key_pair(name, sshkey)
174
294
  payload = {"name" => name, "sshkey" => sshkey}
175
295
  post("tenants/#{tenant}/sshkeys", payload.to_json)
176
296
  end
177
297
 
298
+ # Delete SSH key from the tenant
299
+ #
300
+ # @param sshkey_name [String] SSH Key name
178
301
  def delete_key_pair(name)
179
302
  delete("tenants/#{tenant}/sshkeys/#{name}")
180
303
  end
181
304
 
182
305
  # Get an SAP profile
183
306
  #
184
- # @param sap_profile_id [String] The ID of an SAP profile
307
+ # @param sap_profile_id [String] SAP Profile ID
185
308
  # @return [Hash] SAP profile
186
309
  def get_sap_profile(sap_profile_id)
187
310
  get("cloud-instances/#{guid}/sap/#{sap_profile_id}")
@@ -204,7 +327,7 @@ module IBM
204
327
  # instance is the standard 'PVMInstance' type and can be accessed via
205
328
  # the existing *_pvm_instance methods.
206
329
  #
207
- # @param sap_profile_id [String] The ID of an SAP profile
330
+ # @param sap_profile_id [String] SAP Profile ID
208
331
  # @return [Hash] SAP profile
209
332
  def create_sap_pvm_instance(instance_hash)
210
333
  post("cloud-instances/#{guid}/sap", instance_hash.to_json)
@@ -2,6 +2,7 @@ module IBM
2
2
  module Cloud
3
3
  module SDK
4
4
  class ResourceController < BaseService
5
+ require "ibm/cloud/sdk/resource_controller/resource"
5
6
  def endpoint
6
7
  "https://resource-controller.cloud.ibm.com/v2"
7
8
  end
@@ -10,15 +11,8 @@ module IBM
10
11
  @token = token
11
12
  end
12
13
 
13
- def get_resources
14
- resources = get("resource_instances")["resources"] || []
15
-
16
- require "ibm/cloud/sdk/resource_controller/resource"
17
- resources.map { |instance| Resource.new(instance) }
18
- end
19
-
20
14
  def get_resource(guid)
21
- get_resources.detect { |resource| resource.guid == guid }
15
+ Resource.new(get("resource_instances/#{guid}"))
22
16
  end
23
17
 
24
18
  private
@@ -1,7 +1,7 @@
1
1
  module IBM
2
2
  module Cloud
3
3
  module SDK
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.9"
5
5
  end
6
6
  end
7
7
  end
@@ -4,11 +4,13 @@
4
4
  require_relative 'vpc/base_vpc'
5
5
  require_relative 'vpc/base_collection'
6
6
  require_relative 'vpc/base_instance'
7
+ require_relative 'vpc/exceptions'
7
8
 
8
9
  require_relative 'vpc/floatingips'
9
10
  require_relative 'vpc/flowlogcollectors'
10
11
  require_relative 'vpc/ike_policies'
11
12
  require_relative 'vpc/images'
13
+ require_relative 'vpc/instance_profiles'
12
14
  require_relative 'vpc/instances'
13
15
  require_relative 'vpc/ipsec_policies'
14
16
  require_relative 'vpc/keys'
@@ -32,17 +34,16 @@ module IBM
32
34
  # Create an API Client object for the VPC IaaS service
33
35
  #
34
36
  # @param region [String] the IBM Power Cloud instance region
35
- # @param token [IAMtoken] the IBM Cloud IAM Token object
36
- # @param logger [Logger] an instance of an instanciated logger.
37
- def initialize(region, api_key, logger: nil)
37
+ # @param connection [IBM::Cloud::SDK::VPC::Connection] A connection object.
38
+ # @param logger [Logger] An instance of an instanciated logger.
39
+ def initialize(region, connection, logger: nil)
38
40
  @region = region
39
- @api_key = api_key
40
- @token = api_key
41
+ @connection = connection
41
42
 
42
- @logger = logger || Logger.new($stdout)
43
+ @logger = logger || Logger.new($stdout, level: :warn)
43
44
  end
44
45
 
45
- attr_reader :token, :logger
46
+ attr_reader :connection, :logger
46
47
  attr_accessor :region
47
48
 
48
49
  # The Region API endpoint.
@@ -67,6 +68,10 @@ module IBM
67
68
  VPC::Images.new(self)
68
69
  end
69
70
 
71
+ def instance_profiles
72
+ VPC::InstanceProfiles.new(self)
73
+ end
74
+
70
75
  def instances
71
76
  VPC::Instances.new(self)
72
77
  end
@@ -1,14 +1,20 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
+ require_relative('base_mixins/has_child')
5
+
4
6
  module IBM
5
7
  module Cloud
6
8
  module SDK
7
9
  # Container that encapsulates the VPC API.
8
10
  class BaseCollection < BaseVPC
11
+ # This class is used as a base for collection APIs.
12
+ # @param parent [Object] The parent instance in the API chain.
13
+ # @param endpoint [string] A path from the parent to the desired endpoint. In most cases is should be 1 word.
14
+ # @param array_key [string] The key that the API response holds the endpoint data. When nil the endpoint will be used.
15
+ # @param child_class [Object] The Object to be used when instanciating the single instance for this class.
9
16
  def initialize(parent, endpoint, array_key: nil, child_class: nil)
10
17
  # Setup empty base instance variables.
11
- @data = nil
12
18
  @params = nil
13
19
 
14
20
  array_key ||= endpoint
@@ -17,50 +23,83 @@ module IBM
17
23
  @array_key ||= array_key
18
24
  @instance ||= child_class
19
25
 
26
+ (class << self; include ChildMixin; end) if child_class
27
+
20
28
  super(parent, endpoint)
21
29
  end
22
30
 
31
+ # A chainable method to set query filters on the collection.
32
+ # @example vpc.images.params(limit: 1).all
33
+ #
34
+ # @param start [String] A server-supplied token determining what resource to start the page on.
35
+ # @param limit [Integer] The number of resources to return on a page allowed values are between 1 and 100
36
+ # @param resource_group [String] Filters the collection to resources within one of the resource groups identified in a comma-separated list of resource group identifiers
37
+ # @return [BaseCollection] This class with the param instance variable set.
38
+ def params(start: nil, limit: nil, resource_group: nil)
39
+ @params = {}
40
+ @params[:start] = start if start
41
+ @params[:limit] = limit if limit
42
+ @params[:resource_group] = resource_group if resource_group
43
+ self
44
+ end
45
+
23
46
  # Retrieve the collection from the cloud.
47
+ # @return [IBM::Cloud::SDK::VPC::Response] The http response object.
24
48
  def fetch
25
49
  @data ||= get(params: @params)
26
- @data
27
50
  end
28
51
 
52
+ # Get an iterable for the resource collection.
53
+ # @return [Enumerator] Use standard each, next idioms.
29
54
  def all
30
- response = fetch.subkey(@array_key)
31
- return response if response.is_a?(Array)
55
+ each_resource(url)
56
+ end
32
57
 
33
- raise "#{self.class}.#{__method__} Expecting response to be an Array not a #{response.class}"
58
+ # Fetch all data and return in an array.
59
+ # @return [Array] Hashes of the returned data.
60
+ def data
61
+ all.to_a
34
62
  end
35
63
 
36
- def params(start: nil, limit: nil, resource_group: nil)
37
- @params = {}
38
- @params['start'] = start if start
39
- @params['limit'] = limit if limit
40
- @params['resource_group'] = resource_group if resource_group
41
- self
64
+ # Determine if the collection has a total_count key in its response.
65
+ # @return [Boolean]
66
+ def has_count?
67
+ fetch.json&.key?(:total_count)
42
68
  end
43
69
 
70
+ # Get the total count if it exists in the response. Returns nil otherwise.
71
+ # @return [Integer] The total count reuturned by the server.
44
72
  def count
45
- fetch.subkey('total_count')
73
+ fetch.json&.fetch(:total_count, nil)
46
74
  end
47
75
 
48
- def limit
49
- fetch.subkey('limit')
76
+ # A generic post method to create a resource on the collection.
77
+ # @param payload [Hash] A hash of parameters to send to the server.
78
+ # @param payload_type [String] One of the following options json, form, or body.
79
+ # @return [IBM::Cloud::SDK::VPC::Response] The http response object.
80
+ def create(payload, payload_type = 'json')
81
+ adhoc(method: 'post', payload_type: payload_type, payload: payload)
50
82
  end
51
83
 
52
- def instance(id)
53
- @instance.new(self, id)
54
- end
84
+ private
55
85
 
56
- def next
57
- fetch.subkey('next')
58
- rescue RuntimeError
59
- nil
60
- end
86
+ # Create a generator that removes the need for pagination.
87
+ def each_resource(url, &block)
88
+ return enum_for(:each_resource, url) unless block_given?
89
+ return unless url
90
+
91
+ response = @connection.adhoc('get', url, metadata(@params)).json
92
+ resources = response.fetch(@array_key.to_sym)
93
+
94
+ resources&.each do |value|
95
+ yield value
96
+ end
97
+ return unless response.key?(:next)
98
+
99
+ next_url = response.dig(:next, :href)
100
+ return unless next_url
61
101
 
62
- def create(payload)
63
- post(payload)
102
+ each_resource(next_url, &block)
64
103
  end
65
104
  end
66
105
  end
@@ -7,7 +7,7 @@ module IBM
7
7
  # Container that encapsulates the VPC API.
8
8
  class BaseInstance < BaseVPC
9
9
  def details
10
- get.hash
10
+ get.hash_response
11
11
  end
12
12
 
13
13
  def update(payload)
@@ -0,0 +1,27 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module IBM
5
+ module Cloud
6
+ module SDK
7
+ # Access a specific instance by either id or name depending on API.
8
+ module ChildMixin
9
+ # Get an instance of the collection object.
10
+ # @param id [String] ID of Name to search on depending on API.
11
+ # @return [] The instance object.
12
+ def instance(id)
13
+ @instance.new(self, id)
14
+ end
15
+
16
+ # Return the first_instance returned from a collection get.
17
+ def first_instance
18
+ result = params(limit: 1).all.first
19
+ return nil unless result
20
+ return nil unless result.key?(:id)
21
+
22
+ instance(result.fetch(:id))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -8,14 +8,14 @@ module IBM
8
8
  class BaseVPC
9
9
  def initialize(parent, endpoint = nil)
10
10
  @endpoint = parent.url(endpoint)
11
- @token = parent.token
11
+ @connection = parent.connection
12
12
  @logger = parent.logger
13
13
  end
14
14
 
15
- attr_reader :endpoint, :token, :logger
15
+ attr_reader :endpoint, :connection, :logger
16
16
 
17
17
  def adhoc(method: 'get', path: nil, params: {}, payload_type: 'json', payload: {})
18
- @token.adhoc(method.to_sym, url(path), metadata(params, payload_type, payload))
18
+ @connection.adhoc(method.to_sym, url(path), metadata(params, payload_type, payload))
19
19
  end
20
20
 
21
21
  def get(path: nil, params: {})
@@ -23,7 +23,7 @@ module IBM
23
23
  end
24
24
 
25
25
  def post(payload = {}, path: nil, params: {}, type: 'json')
26
- adhoc(method: 'post', path: path, params: params, payload: payload)
26
+ adhoc(method: 'post', path: path, params: params, payload: payload, payload_type: type)
27
27
  end
28
28
 
29
29
  def put(payload = {}, path: nil, params: {})
@@ -12,7 +12,7 @@ module IBM
12
12
  @logger ||= Logger.new($stdout, level: :warn)
13
13
 
14
14
  @client = HTTP.use(http_options(options))
15
- @token = IBM::Cloud::SDK::VPC::Connection.new(api_key, logger: @logger, client: @client)
15
+ @connection = IBM::Cloud::SDK::VPC::Connection.new(api_key, logger: @logger, client: @client)
16
16
  end
17
17
 
18
18
  def http_options(options = {})
@@ -24,10 +24,10 @@ module IBM
24
24
  )
25
25
  end
26
26
 
27
- attr_reader :logger, :token
27
+ attr_reader :logger, :connection
28
28
 
29
29
  def vpc(region = 'us-east')
30
- IBM::Cloud::SDK::Vpc.new(region, @token, logger: @logger)
30
+ IBM::Cloud::SDK::Vpc.new(region, @connection, logger: @logger)
31
31
  end
32
32
  end
33
- end
33
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IBM
4
+ module Cloud
5
+ module SDK
6
+ module VPC
7
+ # Module to contain all custom exception classes.
8
+ module Exceptions
9
+ # An exception for http with a response attribute.
10
+ # @param response [IBM::Cloud::SDK::VPC::Response] The original response object.
11
+ # @param msg [String] A human readable message.
12
+ class ExceptionWithResponse < RuntimeError
13
+ def initialize(response, msg)
14
+ @response = response
15
+ super(msg)
16
+ end
17
+ # @return [IBM::Cloud::SDK::VPC::Response] The response
18
+ attr_reader :response
19
+ end
20
+
21
+ # An exception for http status errors with a response attribute.
22
+ # @param response [IBM::Cloud::SDK::VPC::Response] The original response object.
23
+ class HttpStatusError < ExceptionWithResponse
24
+ def initialize(response)
25
+ msg = "Invalid status #{response.code} for url \"#{response.url}\", #{response.reason}. #{response.body}"
26
+ super(response, msg)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -8,8 +8,10 @@ module IBM
8
8
  module Cloud
9
9
  module SDK
10
10
  module VPC
11
-
12
- # Contols tokens.
11
+ # The Connection object to be used for all HTTP requests.
12
+ # @param api_key [String] The API Key to be used for this account.
13
+ # @param logger [Logger] An instantiated logger instance.
14
+ # @param client [HTTP::Client] An instantiated HTTP client.
13
15
  class Connection
14
16
  def initialize(api_key, logger: nil, client: nil)
15
17
  @api_key = api_key
@@ -20,17 +22,36 @@ module IBM
20
22
 
21
23
  attr_reader :client
22
24
 
25
+ # Send a HTTP request. Checks the validity of the response.
26
+ # @param verb [String] THe HTTP verb to use for this request.
27
+ # @param uri [String] The Full URL to send.
28
+ # @option opts [Hash] :params Parameters for URL encoding parameters.
29
+ # @option opts [Hash] :json Used when sending a hash as application/json content type.
30
+ # @option opts [Hash] :form Used when sending a hash as a form.
31
+ # @option opts [Hash] :headers Used to modify headers for request.
32
+ # @return [IBM::Cloud::SDK::VPC::Response] Wrapped response to query.
33
+ # @raise [IBM::Cloud::SDK::VPC::Exceptions::HttpStatusError] Response code is not either in 200-series or 404.
23
34
  def adhoc(verb, uri, opts = {})
24
- response = @client.auth(@token.authorization_header).request(verb.to_sym, uri, opts)
35
+ unverified_request(verb, uri, opts).raise_for_status?
36
+ end
37
+
38
+ # Send a HTTP request. Don't do any validation checks.
39
+ # @see :adhoc for options.
40
+ def unverified_request(verb, uri, opts = {})
41
+ response = @client.auth(@token.authorization_header).request(verb.to_s.downcase.to_sym, uri, opts)
25
42
  Response.new(response)
26
43
  end
27
44
 
45
+ # Get bearer token string for clients not using the adhoc method.
28
46
  def authorization_header
29
47
  @token.authorization_header
30
48
  end
31
49
  end
32
50
 
33
- # Get a token.
51
+ # The IAM token manager.
52
+ # @param api_key [String] The API Key to be used for this account.
53
+ # @param logger [Logger] An instantiated logger instance.
54
+ # @param client [HTTP::Client] An instantiated HTTP client.
34
55
  class Token
35
56
  def initialize(api_key, logger: nil, client: nil)
36
57
  @api_key = api_key
@@ -39,6 +60,9 @@ module IBM
39
60
  @data = fetch
40
61
  end
41
62
 
63
+ # Retrieve a new access_token from IAM.
64
+ # @return [IBM::Cloud::SDK::VPC::Response] Wrapped response to query.
65
+ # @raise [IBM::Cloud::SDK::VPC::Exceptions::HttpStatusError] Response code is not either in 200-series or 404.
42
66
  def fetch
43
67
  payload = {
44
68
  form: {
@@ -47,14 +71,20 @@ module IBM
47
71
  }
48
72
  }
49
73
  response = HTTP.post('https://iam.cloud.ibm.com/identity/token', payload)
50
- @data = Response.new(response).json
74
+ @data = Response.new(response).raise_for_status?.json
51
75
  end
52
76
 
77
+ # Check to see if the access_token is expired. Fetch a new token if none exists.
78
+ # @return [IBM::Cloud::SDK::VPC::Response] Wrapped response to query.
79
+ # @raise [IBM::Cloud::SDK::VPC::Exceptions::HttpStatusError] Response code is not either in 200-series or 404.
53
80
  def expired?
54
81
  fetch unless @data
55
82
  @data.fetch(:expiration).to_i <= Time.now.to_i + 600
56
83
  end
57
84
 
85
+ # Get a Bearer token string. Before returning check to see if token is expired.
86
+ # @return [String] The Bearer token header used in subsequent requests.
87
+ # @raise [IBM::Cloud::SDK::VPC::Exceptions::HttpStatusError] Response code is not either in 200-series or 404.
58
88
  def authorization_header
59
89
  fetch if expired?
60
90
  "#{@data.fetch(:token_type)} #{@data.fetch(:access_token)}"
@@ -8,80 +8,124 @@ module IBM
8
8
  module SDK
9
9
  module VPC
10
10
  # Encapsulate the HTTP response.
11
+ # @param response [HTTP::Response] The HTTP response object.
11
12
  class Response
12
13
  def initialize(response)
13
14
  @response = response
14
15
  end
15
16
 
17
+ # The raw HTTP response.
18
+ # @return [HTTP::Response]
16
19
  attr_reader :response
17
20
 
18
21
  # Return the response in a hash or array.
22
+ # @return [Hash] When response is a hash.
23
+ # @return [Array] When response is an array.
24
+ # @raise [Exceptions::ExceptionWithResponse] Contents of body is not properly formatted json.
19
25
  def json
20
26
  JSON.parse(body, symbolize_names: true)
21
27
  rescue StandardError
22
- raise "Error while parsing response body. #{response.body}"
28
+ raise Exceptions::ExceptionWithResponse.new(self, "#{url} Error while parsing response body. #{response.body}")
23
29
  end
24
30
 
25
31
  # Return the raw response string.
32
+ # @return [String]
33
+ # @return [nil] Response does not have body method.
26
34
  def body
27
- response.body.to_s
35
+ response&.body.to_s
28
36
  end
29
37
 
30
38
  # Return the response code.
39
+ # @return [Integer] Response has code method.
40
+ # @return [nil] Response does not have code method.
31
41
  def code
32
- response.code
42
+ response&.code
33
43
  end
34
44
 
45
+ alias status code
46
+
35
47
  # Return the raw connection object.
48
+ # @return [HTTP::Connection]
49
+ # @return [nil] Response does not have a connection method.
36
50
  def connection
37
- response.connection
51
+ response&.connection
52
+ end
53
+
54
+ # Chainable method to verify the status code. Raise an exception for non 200-series or 404 status codes.
55
+ # @return [Response] Allows for method to be chainable.
56
+ # @raise [Exceptions::HttpStatusError] Raise if status checks failed.
57
+ def raise_for_status?
58
+ return self if (200..299).include?(code)
59
+ return self if code == 404
60
+
61
+ raise Exceptions::HttpStatusError.new(self)
38
62
  end
39
63
 
40
64
  # Return the content type of the response.
65
+ # @return [String] The mimetype of the response.
66
+ # @return [nil] Response does not have response method that responds to mime_type.
41
67
  def content_type
42
- response.response.mime_type
68
+ response&.response&.mime_type
43
69
  end
44
70
 
45
71
  # Return the textual reason.
72
+ # @return [String] HTTP Reason
73
+ # @return [nil] Response does not have reaspn method that responds.
46
74
  def reason
47
- response.reason
75
+ response&.reason
48
76
  end
49
77
 
50
78
  # Return the sent url as a string.
79
+ # @return [String] Full URL sent
80
+ # @return [nil] Response does not have response method that responds to mime_type.
51
81
  def url
52
- response.uri.to_s
82
+ response&.uri.to_s
53
83
  end
54
84
 
55
85
  # Return the sent url as a URI class.
86
+ # @see https://github.com/httprb/http/blob/master/lib/http/uri.rb URI Class doc.
87
+ # @return [HTTP::URI]
88
+ # @return [nil] Response does not have response method that responds to mime_type.
56
89
  def uri
57
- response.uri
90
+ response&.uri
58
91
  end
59
92
 
60
93
  # Verify that the json response is a hash.
94
+ # @return [Hash] Response from JSON
95
+ # @raise [RuntimeError] JSON object is not a Hash.
61
96
  def hash_response
62
97
  check_object(Hash)
63
98
  end
64
99
 
65
100
  # Verify that the json response is an array.
101
+ # @return [Array] Response from JSON
102
+ # @raise [RuntimeError] JSON object is not a Array.
66
103
  def array_response
67
104
  check_object(Array)
68
105
  end
69
106
 
70
107
  # Find a subkey within the returned response.
108
+ # @param key [String] Name of a first level key.
109
+ # @return [Any] Response from JSON
110
+ # @raise [RuntimeError] JSON object is not a Array.
71
111
  def subkey(key)
72
112
  ret = hash_response
73
113
  sym_key = key.to_sym
74
114
  return ret.fetch(sym_key) if ret.key?(sym_key)
75
115
 
76
- raise "Key not found in #{ret}."
116
+ msg = "Key #{key} not found in #{ret}."
117
+ raise Exceptions::ExceptionWithResponse.new(self, msg)
77
118
  end
78
119
 
79
120
  # Check to see if the returned object is the expected object.
121
+ # @param obj [Object] The object to test the response against.
122
+ # @raise [Exceptions::ExceptionWithResponse] Parsed JSON is not the expecte class.
80
123
  def check_object(obj)
81
124
  ret = json
82
125
  return ret if ret.instance_of?(obj)
83
126
 
84
- raise "Expected #{obj} in response for #{url}. The returned object is a #{ret.class}."
127
+ msg = "Expected #{obj} in response for #{url}. The returned object is a #{ret.class}."
128
+ raise Exceptions::ExceptionWithResponse.new(self, msg)
85
129
  end
86
130
  end
87
131
  end
@@ -5,7 +5,7 @@ module IBM
5
5
  module Cloud
6
6
  module SDK
7
7
  module VPC
8
- module INSTANCES
8
+ module INSTANCE
9
9
  # Actions for an instance.
10
10
  class Actions < BaseCollection
11
11
  def initialize(parent)
@@ -5,7 +5,7 @@ module IBM
5
5
  module Cloud
6
6
  module SDK
7
7
  module VPC
8
- module INSTANCES
8
+ module INSTANCE
9
9
  # Get a Floating IP.
10
10
  class FloatingIps < BaseCollection
11
11
  def initialize(parent)
@@ -7,41 +7,16 @@ module IBM
7
7
  module Cloud
8
8
  module SDK
9
9
  module VPC
10
- module INSTANCES
10
+ module INSTANCE
11
11
  # All netowrk interfaces.
12
- class NetworkInterfaces < BaseVPC
12
+ class NetworkInterfaces < BaseCollection
13
13
  def initialize(parent)
14
- super(parent, 'network_interfaces')
15
- end
16
-
17
- def all
18
- get.subkey('network_interfaces')
19
- # get
20
- end
21
-
22
- def update(payload)
23
- post(payload)
24
- end
25
-
26
- def instance(id)
27
- NetworkInterface.new(self, id)
14
+ super(parent, 'network_interfaces', child_class: NetworkInterface)
28
15
  end
29
16
  end
30
17
 
31
18
  # A single network insterface.
32
- class NetworkInterface < BaseVPC
33
- def remove
34
- delete
35
- end
36
-
37
- def details
38
- get
39
- end
40
-
41
- def update(payload)
42
- patch(payload)
43
- end
44
-
19
+ class NetworkInterface < BaseInstance
45
20
  def floating_ips
46
21
  FloatingIps.new(self)
47
22
  end
@@ -5,39 +5,16 @@ module IBM
5
5
  module Cloud
6
6
  module SDK
7
7
  module VPC
8
- module INSTANCES
8
+ module INSTANCE
9
9
  # Get all attached volumes.
10
- class VolumeAttachments < BaseVPC
10
+ class VolumeAttachments < BaseCollection
11
11
  def initialize(parent)
12
- super(parent, 'volume_attachments')
13
- end
14
-
15
- def all
16
- get
17
- end
18
-
19
- def create(payload)
20
- post(payload)
21
- end
22
-
23
- def instance(id)
24
- VolumeAttachment.new(self, id)
12
+ super(parent, 'volume_attachments', child_class: VolumeAttachment)
25
13
  end
26
14
  end
27
15
 
28
16
  # A single attached volume.
29
- class VolumeAttachment < BaseVPC
30
- def details
31
- get
32
- end
33
-
34
- def update(payload)
35
- patch(payload)
36
- end
37
-
38
- def remove
39
- delete
40
- end
17
+ class VolumeAttachment < BaseInstance
41
18
  end
42
19
  end
43
20
  end
@@ -0,0 +1,21 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module IBM
5
+ module Cloud
6
+ module SDK
7
+ module VPC
8
+ # Work with multiple profiles.
9
+ class InstanceProfiles < BaseCollection
10
+ def initialize(parent)
11
+ super(parent, 'instance/profiles', child_class: Profile, array_key: 'profiles')
12
+ end
13
+ end
14
+
15
+ # Get a single profile.
16
+ class Profile < BaseInstance
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,7 +1,9 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative('instance')
4
+ require_relative 'instance/actions'
5
+ require_relative 'instance/network_interfaces'
6
+ require_relative 'instance/volume_attachments'
5
7
 
6
8
  module IBM
7
9
  module Cloud
@@ -11,7 +13,45 @@ module IBM
11
13
  # Work with multiple VM instances.
12
14
  class Instances < BaseCollection
13
15
  def initialize(parent)
14
- super(parent, 'instances', child_class: INSTANCES::Instance)
16
+ super(parent, 'instances', child_class: Instance)
17
+ end
18
+
19
+ # A chainable method to set query filters on the collection.
20
+ # @example vpc.images.params(limit: 1).all
21
+ #
22
+ # @param start [String] A server-supplied token determining what resource to start the page on.
23
+ # @param limit [Integer] The number of resources to return on a page allowed values are between 1 and 100
24
+ # @param name [String] Filters the collection to resources with the exact specified name
25
+ # @param vpc_id [String] Filters the collection to resources in the VPC with the specified identifier
26
+ # @param vpc_crn [String] Filters the collection to resources in the VPC with the specified CRN
27
+ # @param vpc_name [String] Filters the collection to resources in the VPC with the exact specified name
28
+ # @return [BaseCollection] This class with the param instance variable set.
29
+ def params(start: nil, limit: nil, name: nil, vpc_id: nil, vpc_crn: nil, vpc_name: nil)
30
+ super(start: start, limit: limit)
31
+ @params['name'] = name if name
32
+ @params['vpc.id'] = vpc_id if vpc_id
33
+ @params['vpc.crn'] = vpc_crn if vpc_crn
34
+ @params['vpc.name'] = vpc_name if vpc_name
35
+ self
36
+ end
37
+ end
38
+
39
+ # Work with a single instance.
40
+ class Instance < BaseInstance
41
+ def actions
42
+ INSTANCE::Actions.new(self)
43
+ end
44
+
45
+ def network_interfaces
46
+ INSTANCE::NetworkInterfaces.new(self)
47
+ end
48
+
49
+ def volume_attachments
50
+ INSTANCE::VolumeAttachments.new(self)
51
+ end
52
+
53
+ def initialization
54
+ adhoc(method: 'get', path: 'initialization').json
15
55
  end
16
56
  end
17
57
  end
@@ -27,7 +27,7 @@ module IBM
27
27
  end
28
28
 
29
29
  # A single zone.
30
- class Zone < BaseVPC
30
+ class Zone < BaseInstance
31
31
  end
32
32
  end
33
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ibm-cloud-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - IBM Cloud Developers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-17 00:00:00.000000000 Z
11
+ date: 2020-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -60,6 +60,8 @@ files:
60
60
  - lib/ibm/cloud/sdk/base_service.rb
61
61
  - lib/ibm/cloud/sdk/iam.rb
62
62
  - lib/ibm/cloud/sdk/iam/token.rb
63
+ - lib/ibm/cloud/sdk/logging.rb
64
+ - lib/ibm/cloud/sdk/null_logger.rb
63
65
  - lib/ibm/cloud/sdk/power_iaas.rb
64
66
  - lib/ibm/cloud/sdk/resource_controller.rb
65
67
  - lib/ibm/cloud/sdk/resource_controller/resource.rb
@@ -67,20 +69,21 @@ files:
67
69
  - lib/ibm/cloud/sdk/vpc.rb
68
70
  - lib/ibm/cloud/sdk/vpc/base_collection.rb
69
71
  - lib/ibm/cloud/sdk/vpc/base_instance.rb
72
+ - lib/ibm/cloud/sdk/vpc/base_mixins/has_child.rb
70
73
  - lib/ibm/cloud/sdk/vpc/base_vpc.rb
71
74
  - lib/ibm/cloud/sdk/vpc/cloud_sdk.rb
75
+ - lib/ibm/cloud/sdk/vpc/exceptions.rb
72
76
  - lib/ibm/cloud/sdk/vpc/floatingips.rb
73
77
  - lib/ibm/cloud/sdk/vpc/flowlogcollectors.rb
74
78
  - lib/ibm/cloud/sdk/vpc/helpers/connection.rb
75
79
  - lib/ibm/cloud/sdk/vpc/helpers/response.rb
76
80
  - lib/ibm/cloud/sdk/vpc/ike_policies.rb
77
81
  - lib/ibm/cloud/sdk/vpc/images.rb
78
- - lib/ibm/cloud/sdk/vpc/instance.rb
79
82
  - lib/ibm/cloud/sdk/vpc/instance/actions.rb
80
83
  - lib/ibm/cloud/sdk/vpc/instance/floating_ips.rb
81
84
  - lib/ibm/cloud/sdk/vpc/instance/network_interfaces.rb
82
- - lib/ibm/cloud/sdk/vpc/instance/profiles.rb
83
85
  - lib/ibm/cloud/sdk/vpc/instance/volume_attachments.rb
86
+ - lib/ibm/cloud/sdk/vpc/instance_profiles.rb
84
87
  - lib/ibm/cloud/sdk/vpc/instances.rb
85
88
  - lib/ibm/cloud/sdk/vpc/ipsec_policies.rb
86
89
  - lib/ibm/cloud/sdk/vpc/keys.rb
@@ -109,7 +112,7 @@ licenses:
109
112
  - '"Apache-2.0"'
110
113
  metadata:
111
114
  homepage_uri: https://github.com/IBM-Cloud/ibm-cloud-sdk-ruby
112
- changelog_uri: https://github.com/IBM-Cloud/ibm-cloud-sdk-ruby/blob/v0.1.4/CHANGELOG.md
115
+ changelog_uri: https://github.com/IBM-Cloud/ibm-cloud-sdk-ruby/blob/v0.1.9/CHANGELOG.md
113
116
  post_install_message:
114
117
  rdoc_options: []
115
118
  require_paths:
@@ -1,36 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require_relative 'instance/actions'
5
- require_relative 'instance/network_interfaces'
6
- require_relative 'instance/volume_attachments'
7
- require_relative 'instance/profiles'
8
-
9
- module IBM
10
- module Cloud
11
- module SDK
12
- module VPC
13
- module INSTANCES
14
- # Work with a single instance.
15
- class Instance < BaseInstance
16
- def actions
17
- Actions.new(self)
18
- end
19
-
20
- def network_interfaces
21
- NetworkInterfaces.new(self)
22
- end
23
-
24
- def volume_attachments
25
- VolumeAttachments.new(self)
26
- end
27
-
28
- def profiles
29
- Profiles.new(self)
30
- end
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,34 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- module IBM
5
- module Cloud
6
- module SDK
7
- module VPC
8
- module INSTANCES
9
- # Work with multiple profiles.
10
- class Profiles < BaseVPC
11
- def initialize(parent)
12
- super(parent, 'instance/profiles')
13
- end
14
-
15
- def all
16
- get
17
- end
18
-
19
- def instance(name)
20
- Profile.new(self, name)
21
- end
22
- end
23
-
24
- # Get a single profile.
25
- class Profile < BaseVPC
26
- def details
27
- get
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end