brightbox-cli 5.0.0.alpha → 5.0.0.rc1

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -1
  3. data/CHANGELOG.md +60 -0
  4. data/Gemfile.lock +1 -1
  5. data/lib/brightbox-cli/accounts.rb +5 -1
  6. data/lib/brightbox-cli/api.rb +34 -1
  7. data/lib/brightbox-cli/cloud_ips.rb +6 -6
  8. data/lib/brightbox-cli/collaboration.rb +3 -7
  9. data/lib/brightbox-cli/commands/lbs/create.rb +0 -2
  10. data/lib/brightbox-cli/commands/lbs/show.rb +4 -0
  11. data/lib/brightbox-cli/config.rb +10 -4
  12. data/lib/brightbox-cli/database_server.rb +20 -20
  13. data/lib/brightbox-cli/database_snapshot.rb +5 -5
  14. data/lib/brightbox-cli/database_type.rb +4 -8
  15. data/lib/brightbox-cli/detailed_server.rb +26 -28
  16. data/lib/brightbox-cli/detailed_server_group.rb +2 -2
  17. data/lib/brightbox-cli/firewall_policy.rb +5 -9
  18. data/lib/brightbox-cli/firewall_rule.rb +14 -15
  19. data/lib/brightbox-cli/images.rb +22 -21
  20. data/lib/brightbox-cli/indifferent_access_hash.rb +50 -0
  21. data/lib/brightbox-cli/load_balancers.rb +27 -11
  22. data/lib/brightbox-cli/server_groups.rb +4 -8
  23. data/lib/brightbox-cli/servers.rb +22 -16
  24. data/lib/brightbox-cli/types.rb +4 -8
  25. data/lib/brightbox-cli/user_collaboration.rb +1 -1
  26. data/lib/brightbox-cli/users.rb +3 -5
  27. data/lib/brightbox-cli/version.rb +1 -1
  28. data/lib/brightbox-cli/volume.rb +9 -13
  29. data/lib/brightbox-cli/zones.rb +0 -4
  30. data/lib/brightbox_cli.rb +1 -0
  31. data/spec/commands/cloudips/update_spec.rb +7 -5
  32. data/spec/commands/configmaps/create_spec.rb +6 -6
  33. data/spec/commands/configmaps/destroy_spec.rb +1 -1
  34. data/spec/commands/configmaps/list_spec.rb +1 -1
  35. data/spec/commands/configmaps/show_spec.rb +3 -3
  36. data/spec/commands/configmaps/update_spec.rb +9 -9
  37. data/spec/commands/lbs/create_spec.rb +12 -26
  38. data/spec/commands/lbs/show_spec.rb +15 -3
  39. data/spec/commands/lbs/update_spec.rb +4 -4
  40. data/spec/commands/servers/update_spec.rb +7 -7
  41. data/spec/commands/sql/instances/create_spec.rb +8 -8
  42. data/spec/commands/sql/instances/reset_spec.rb +3 -3
  43. data/spec/commands/sql/instances/resize_spec.rb +4 -4
  44. data/spec/commands/sql/instances/show_spec.rb +2 -1
  45. data/spec/commands/sql/instances/update_spec.rb +3 -3
  46. data/spec/commands/sql/snapshots/list_spec.rb +1 -1
  47. data/spec/commands/sql/snapshots/show_spec.rb +50 -7
  48. data/spec/commands/volumes/attach_spec.rb +4 -4
  49. data/spec/commands/volumes/copy_spec.rb +2 -2
  50. data/spec/commands/volumes/destroy_spec.rb +1 -1
  51. data/spec/commands/volumes/detach_spec.rb +1 -1
  52. data/spec/commands/volumes/list_spec.rb +1 -1
  53. data/spec/commands/volumes/resize_spec.rb +3 -3
  54. data/spec/commands/volumes/show_spec.rb +1 -1
  55. data/spec/commands/volumes/update_spec.rb +4 -4
  56. data/spec/spec_helper.rb +14 -10
  57. data/spec/support/shared/api_resource_examples.rb +25 -0
  58. data/spec/unit/brightbox/account/attributes_spec.rb +13 -0
  59. data/spec/unit/brightbox/api/attributes_spec.rb +65 -0
  60. data/spec/unit/brightbox/api/fog_attributes_spec.rb +65 -0
  61. data/spec/unit/brightbox/cloud_ip/attributes_spec.rb +19 -0
  62. data/spec/unit/brightbox/collaborating_account/attributes_spec.rb +13 -0
  63. data/spec/unit/brightbox/database_server/attributes_spec.rb +13 -0
  64. data/spec/unit/brightbox/database_snapshot/attributes_spec.rb +13 -0
  65. data/spec/unit/brightbox/database_type/attributes_spec.rb +20 -0
  66. data/spec/unit/brightbox/detailed_server/attributes_spec.rb +29 -0
  67. data/spec/unit/brightbox/detailed_server_group/attributes_spec.rb +13 -0
  68. data/spec/unit/brightbox/firewall_policy/attributes_spec.rb +21 -0
  69. data/spec/unit/brightbox/firewall_rule/attributes_spec.rb +18 -0
  70. data/spec/unit/brightbox/image/attributes_spec.rb +13 -0
  71. data/spec/unit/brightbox/image/status_spec.rb +67 -0
  72. data/spec/unit/brightbox/load_balancer/acme_cert_spec.rb +75 -0
  73. data/spec/unit/brightbox/load_balancer/attributes_spec.rb +13 -0
  74. data/spec/unit/brightbox/load_balancer/formatted_acme_domains_spec.rb +78 -0
  75. data/spec/unit/brightbox/server/attributes_spec.rb +29 -0
  76. data/spec/unit/brightbox/server_group/attributes_spec.rb +13 -0
  77. data/spec/unit/brightbox/type/attributes_spec.rb +20 -0
  78. data/spec/unit/brightbox/user/attributes_spec.rb +13 -0
  79. data/spec/unit/brightbox/user_collaboration/attributes_spec.rb +13 -0
  80. metadata +47 -4
  81. data/spec/cassettes/brightbox_sql_snapshots/show/when_resource_exists/does_not_output_to_stderr.yml +0 -93
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4acdda82f537081ebb5cb73f47463dcb76aa4d13903ef59df37e9c7159e6bcef
4
- data.tar.gz: 653ee68c860f906a56daa9c859fcd62b625bcaa32f2c7610fdd62ea57513544e
3
+ metadata.gz: 1c8cd88f1d668182fcc07ad7ac31d8a3935bcf079321908ec56a364e59e0fe43
4
+ data.tar.gz: 4b5ae117508d213f075adebf4c70996e95001abe39a6e9de0769232d29f5d3c5
5
5
  SHA512:
6
- metadata.gz: 64289163116f1e986cad76c3794870c7fe28ac5d2a96ad7cf433ad3bf4fb4f8cb4445930dbddd13d7e9a803df1497940df47877689a3cee5fac5f50561b3f99d
7
- data.tar.gz: 793e0f20d1b18450a7024272a6eebb1b61e470c250e3dee740c7251c963b63914fd38ee48af2ae113a27d4046f251320267fece5b8cdd4d298222524aeb46d64
6
+ metadata.gz: 8b50ffa28cbb39bd012b39de3233ad1e6e29190723e2ed83f1239525c04bdbaa1927b7b26d528246fdbd5d9f6185ed08d88807ab58e7fd970b6dcadf65139b28
7
+ data.tar.gz: 022e0c725cc12e5d2db5178100f7434a9c52de94eb8330a88688238c9183944b1199016f75d9a868568498a37258bf13d3032b5e9fb3a357198b1605e117503e
@@ -22,7 +22,8 @@ jobs:
22
22
  fail-fast: false
23
23
  matrix:
24
24
  ruby: ["2.7", "3.0", "3.1", "3.2", "3.3"]
25
-
25
+ env:
26
+ DEBUG: "true"
26
27
  steps:
27
28
  - uses: actions/checkout@v3
28
29
  - name: Set up Ruby ${{ matrix.ruby }}
data/CHANGELOG.md CHANGED
@@ -1,3 +1,63 @@
1
+ ### v5.0.0.rc1 / 2024-12-20
2
+
3
+ [Full Changelog](https://github.com/brightbox/brightbox-cli/compare/v4.8.0...v5.0.0.rc1)
4
+
5
+ Backwards incompatible changes:
6
+
7
+ * Drop support for Ruby versions older than 2.7
8
+ * Update `Gemfile.lock` to use Bundler 2.4.22
9
+ * When ENV `HOME` is not set, the working directory is used for configs
10
+ rather than `/.brightbox` to fix issues with containers
11
+
12
+ Enhancements:
13
+
14
+ * Added support for ACME certificates
15
+ * `brightbox lbs create` and `update` accepts `--acme-domains` with CSV
16
+ domains to request them to be setup on the load balancer
17
+ * `brightbox lbs show` outputs ACME related fields
18
+ * `acme_domains` - domains requested to be present
19
+ * `acme_cert_expires` - when the ACME certificate in no longer valid
20
+ * `acme_cert_fingerprint` - the fingerprint of the ACME certificate
21
+ * `acme_cert_issued_at` - when the ACME certificate was issued
22
+ * `acme_cert_subjects` - domain present on ACME certificate
23
+ * `brightbox firewall-policy` is now an alias for `firewall-policies`
24
+
25
+ Changes:
26
+
27
+ * `brightbox images` will now report an deprecated and private image as
28
+ "private" rather than "deprecated"
29
+ * Update `fog-brightbox` to `v1.12.0`
30
+ * Numerous dependency gems updated
31
+ * Expanded debugging output
32
+ * `Brightbox::Api#attributes` attempts to transform and make attributes
33
+ indifferent to String or Symbol keys as that has introduced numerous
34
+ issues over the years. Fog only converts the top level of keys from
35
+ Strings to Symbols resulting in mismatched keys throughout
36
+ * Refactored all models `#attributes` and `#to_row` methods to use the
37
+ above with more involved testing
38
+
39
+ Bug fixes:
40
+
41
+ * `brightbox lbs create` no longer requires at least one node to balance
42
+ which was outdated client side validation long removed from the API
43
+ * `brightbox lbs create` should now recognise the `--buffer-size` option
44
+ * `brightbox lbs update` converts `buffer-size` to integer before sending
45
+ * `brightbox cloudips unmap` incorrectly used the "map" description in
46
+ the help output. This is now fixed
47
+
48
+ Testing:
49
+
50
+ * Update CI testing matrix from Ruby 2.7 up to 3.3
51
+ * Ensure bundler version declared in `Gemfile.lock` is used by CI tests
52
+ * CI setting completes all builds rather than cancelling on one fail
53
+ * CI testing includes `DEBUG` ENV settings
54
+ * Tests updated to not "fail" when `DEBUG` output is included upsetting
55
+ matches to expected output in numerous cases
56
+ * Simplecov has been introduced and configured to prevent a drop in
57
+ test coverage.
58
+ * Temporary testing config directories are removed explicitly to prevent
59
+ config bleeding in some test scenarios
60
+
1
61
  ### v4.8.0 / 2024-10-23
2
62
 
3
63
  [Full Changelog](https://github.com/brightbox/brightbox-cli/compare/v4.7.0...v4.8.0)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- brightbox-cli (5.0.0.alpha)
4
+ brightbox-cli (5.0.0.rc1)
5
5
  fog-brightbox (>= 1.12.0)
6
6
  fog-core (< 2.0)
7
7
  gli (~> 2.21)
@@ -13,7 +13,11 @@ module Brightbox
13
13
  end
14
14
 
15
15
  def to_row
16
- attributes.merge(:ram_free => ram_free, :cloud_ip_limit => cloud_ip_limit, :lb_limit => lb_limit)
16
+ attributes.to_h.merge(
17
+ :ram_free => ram_free,
18
+ :cloud_ip_limit => cloud_ip_limit,
19
+ :lb_limit => lb_limit
20
+ )
17
21
  end
18
22
 
19
23
  def self.all
@@ -52,6 +52,16 @@ module Brightbox
52
52
  Brightbox.config.cache_id(@id) if Brightbox.config.respond_to?(:cache_id)
53
53
  end
54
54
 
55
+ def attributes
56
+ fog_attributes
57
+ end
58
+
59
+ # Returns the transformed attributes from the fog model with a
60
+ # wrapper to allow access using either String or Symbol keys.
61
+ def fog_attributes
62
+ IndifferentAccessHash.new(deep_symbolize(fog_model.attributes))
63
+ end
64
+
55
65
  def fog_model
56
66
  @fog_model ||= self.class.find(@id)
57
67
  end
@@ -62,6 +72,10 @@ module Brightbox
62
72
  false
63
73
  end
64
74
 
75
+ def to_row
76
+ attributes.to_h
77
+ end
78
+
65
79
  def to_s
66
80
  @id
67
81
  end
@@ -165,7 +179,7 @@ module Brightbox
165
179
  if value
166
180
  value
167
181
  else
168
- Brightbox.config.cache_id id
182
+ Brightbox.config.cache_id id if Brightbox.config.respond_to?(:cache_id)
169
183
  @cache[id] = get(id)
170
184
  end
171
185
  end
@@ -192,5 +206,24 @@ module Brightbox
192
206
 
193
207
  fog_model.created_at.strftime("%Y-%m-%d")
194
208
  end
209
+
210
+ private
211
+
212
+ # Recursively converts all keys in a hash to symbols to ensure
213
+ # consistent access.
214
+ def deep_symbolize(hash)
215
+ return hash unless hash.respond_to?(:each_with_object)
216
+
217
+ hash.each_with_object({}) do |(k, v), result|
218
+ result[k.to_sym] = case v
219
+ when Hash
220
+ deep_symbolize(v)
221
+ when Array
222
+ v.map { |i| i.is_a?(Hash) ? deep_symbolize(i) : i }
223
+ else
224
+ v
225
+ end
226
+ end
227
+ end
195
228
  end
196
229
  end
@@ -33,15 +33,15 @@ module Brightbox
33
33
  end
34
34
 
35
35
  def attributes
36
- a = fog_model.attributes
37
- a[:destination] = destination_id
38
- a
36
+ fog_attributes.tap do |attrs|
37
+ attrs[:destination] = destination_id
38
+ end
39
39
  end
40
40
 
41
41
  def to_row
42
- o = attributes
43
- o[:port_translators] = translators(o)
44
- o
42
+ attributes.merge(
43
+ port_translators: translators(attributes),
44
+ ).to_h
45
45
  end
46
46
 
47
47
  def mapped?
@@ -31,14 +31,10 @@ module Brightbox
31
31
 
32
32
  attr_reader :id
33
33
 
34
- def attributes
35
- fog_model.attributes
36
- end
37
-
38
34
  def to_row
39
- row_attributes = attributes
40
- row_attributes[:name] = invitee_name
41
- row_attributes
35
+ attributes.merge(
36
+ name: invitee_name
37
+ ).to_h
42
38
  end
43
39
 
44
40
  def invitee_name
@@ -61,8 +61,6 @@ module Brightbox
61
61
  c.switch ["sslv3"]
62
62
 
63
63
  c.action do |global_options, options, args|
64
- raise "You must specify which servers to balance connections to" if args.empty?
65
-
66
64
  listeners = options[:l].split(",").map do |l|
67
65
  inport, outport, protocol, timeout = l.split ":"
68
66
  raise "listener '#{l}' is invalid" if inport.nil? || outport.nil? || protocol.nil?
@@ -17,6 +17,10 @@ module Brightbox
17
17
  deleted_at
18
18
  policy
19
19
  acme_domains
20
+ acme_cert_subjects
21
+ acme_cert_fingerprint
22
+ acme_cert_expires_at
23
+ acme_cert_issued_at
20
24
  ssl_minimum_version
21
25
  ssl_issuer
22
26
  ssl_subject
@@ -91,11 +91,17 @@ module Brightbox
91
91
  def debug_tokens
92
92
  return unless ENV["DEBUG"]
93
93
 
94
- debug "Access token: #{access_token} (#{cached_access_token})"
95
- if using_application?
96
- debug "Refresh token: #{refresh_token} (#{cached_refresh_token}))"
94
+ if client_name
95
+ debug "Client: #{client_name}"
96
+
97
+ debug "Access token: #{access_token} (#{cached_access_token})"
98
+ if using_application?
99
+ debug "Refresh token: #{refresh_token} (#{cached_refresh_token}))"
100
+ else
101
+ debug "Refresh token: <NOT EXPECTED FOR CLIENT>"
102
+ end
97
103
  else
98
- debug "Refresh token: <NOT EXPECTED FOR CLIENT>"
104
+ debug "No client selected"
99
105
  end
100
106
  end
101
107
 
@@ -70,34 +70,34 @@ module Brightbox
70
70
  end
71
71
 
72
72
  def type_identifier
73
- return unless fog_model.attributes.key?("database_server_type")
73
+ return unless fog_attributes.key?("database_server_type")
74
74
 
75
- fog_model.attributes["database_server_type"]["id"]
75
+ fog_attributes["database_server_type"]["id"]
76
76
  end
77
77
 
78
78
  def zone_handle
79
- return unless fog_model.attributes.key?("zone")
79
+ return unless fog_attributes.key?("zone")
80
80
 
81
- fog_model.attributes["zone"]["handle"]
81
+ fog_attributes["zone"]["handle"]
82
82
  end
83
83
 
84
84
  def to_row
85
- a = fog_model.attributes
86
- a[:status] = fog_model.state
87
- a[:locked] = locked?
88
- a[:type] = type_identifier
89
- a[:db_engine] = engine_version
90
- a[:engine] = database_engine
91
- a[:version] = database_version
92
- a[:maintenance_weekday] = maintenance_weekday
93
- a[:maintenance_hour] = maintenance_hour
94
- a[:maintenance_window] = maintenance_window
95
- a[:zone] = zone_handle
96
- a[:created_on] = created_on
97
- a[:allow_access] = allow_access
98
- a[:cloud_ip_ids] = cloud_ip_ids
99
- a[:cloud_ips] = cloud_ip_addresses
100
- a
85
+ attributes.merge(
86
+ status: fog_model.state,
87
+ locked: locked?,
88
+ type: type_identifier,
89
+ db_engine: engine_version,
90
+ engine: database_engine,
91
+ version: database_version,
92
+ maintenance_weekday: maintenance_weekday,
93
+ maintenance_hour: maintenance_hour,
94
+ maintenance_window: maintenance_window,
95
+ zone: zone_handle,
96
+ created_on: created_on,
97
+ allow_access: allow_access,
98
+ cloud_ip_ids: cloud_ip_ids,
99
+ cloud_ips: cloud_ip_addresses
100
+ )
101
101
  end
102
102
 
103
103
  def engine_version
@@ -27,11 +27,11 @@ module Brightbox
27
27
  end
28
28
 
29
29
  def to_row
30
- a = fog_model.attributes
31
- a[:status] = fog_model.state
32
- a[:locked] = locked?
33
- a[:created_on] = fog_model.created_at.strftime("%Y-%m-%d")
34
- a
30
+ fog_attributes.merge(
31
+ status: fog_model.state,
32
+ locked: locked?,
33
+ created_on: fog_model.created_at.strftime("%Y-%m-%d")
34
+ )
35
35
  end
36
36
  end
37
37
  end
@@ -3,10 +3,10 @@ module Brightbox
3
3
  def self.require_account?; true; end
4
4
 
5
5
  def attributes
6
- o = fog_model.attributes
7
- o[:ram] = ram
8
- o[:disk] = disk
9
- o
6
+ fog_attributes.tap do |attrs|
7
+ attrs[:ram] = ram
8
+ attrs[:disk] = disk
9
+ end
10
10
  end
11
11
 
12
12
  def ram
@@ -17,10 +17,6 @@ module Brightbox
17
17
  fog_model.disk.to_i
18
18
  end
19
19
 
20
- def to_row
21
- attributes
22
- end
23
-
24
20
  def self.all
25
21
  conn.database_types
26
22
  end
@@ -1,40 +1,38 @@
1
1
  module Brightbox
2
2
  class DetailedServer < Server
3
3
  def to_row
4
- row_attributes = attributes
4
+ attributes.tap do |attrs|
5
+ attrs[:compatibility_mode] = attrs["compatibility_mode"]
5
6
 
6
- row_attributes[:compatibility_mode] = row_attributes["compatibility_mode"]
7
-
8
- if server_type
9
- row_attributes[:type] = server_type["id"]
10
- row_attributes[:type_handle] = server_type["handle"]
11
- row_attributes[:type_name] = server_type["name"]
12
- row_attributes[:ram] = server_type["ram"]
13
- row_attributes[:cores] = server_type["cores"]
14
- row_attributes[:disk] = server_type["disk_size"].to_i
15
- end
16
-
17
- if image
18
- row_attributes[:image_name] = image.name
19
- row_attributes[:arch] = image.arch
20
- row_attributes[:image_username] = image.username
21
- end
7
+ if server_type
8
+ attrs[:type] = server_type["id"]
9
+ attrs[:type_handle] = server_type["handle"]
10
+ attrs[:type_name] = server_type["name"]
11
+ attrs[:ram] = server_type["ram"]
12
+ attrs[:cores] = server_type["cores"]
13
+ attrs[:disk] = server_type["disk_size"].to_i
14
+ end
22
15
 
23
- row_attributes[:private_ips] = interfaces.map { |i| i["ipv4_address"] }.join(", ")
24
- row_attributes[:ipv6_address] = interfaces.map { |i| i["ipv6_address"] }.join(", ")
16
+ if image
17
+ attrs[:image_name] = image.name
18
+ attrs[:arch] = image.arch
19
+ attrs[:image_username] = image.username
20
+ end
25
21
 
26
- row_attributes[:cloud_ip_ids] = cloud_ips.map { |i| i["id"] }.join(", ")
27
- row_attributes[:cloud_ipv4s] = cloud_ips.map { |i| i["public_ipv4"] }.join(", ")
28
- row_attributes[:cloud_ipv6s] = cloud_ips.map { |i| i["public_ipv6"] }.join(", ")
29
- row_attributes[:snapshots] = snapshots.map { |i| i["id"] }.join(", ")
22
+ attrs[:private_ips] = interfaces.map { |i| i["ipv4_address"] }.join(", ")
23
+ attrs[:ipv6_address] = interfaces.map { |i| i["ipv6_address"] }.join(", ")
30
24
 
31
- if server_groups
32
- row_attributes[:server_groups] = server_groups.map { |sg| sg["id"] }.join(", ")
33
- end
25
+ attrs[:cloud_ip_ids] = cloud_ips.map { |i| i["id"] }.join(", ")
26
+ attrs[:cloud_ipv4s] = cloud_ips.map { |i| i["public_ipv4"] }.join(", ")
27
+ attrs[:cloud_ipv6s] = cloud_ips.map { |i| i["public_ipv6"] }.join(", ")
28
+ attrs[:snapshots] = snapshots.map { |i| i["id"] }.join(", ")
34
29
 
35
- row_attributes[:volumes] = volume_ids if volumes
30
+ if server_groups
31
+ attrs[:server_groups] = server_groups.map { |sg| sg["id"] }.join(", ")
32
+ end
36
33
 
37
- row_attributes
34
+ attrs[:volumes] = volume_ids if volumes
35
+ end.to_h
38
36
  end
39
37
 
40
38
  def volume_ids
@@ -1,9 +1,9 @@
1
1
  module Brightbox
2
2
  class DetailedServerGroup < ServerGroup
3
3
  def to_row
4
- row_attributes = super
4
+ row_attributes = attributes
5
5
  row_attributes[:firewall_policy] = firewall_policy && firewall_policy.id
6
- row_attributes
6
+ row_attributes.to_h
7
7
  end
8
8
 
9
9
  def self.default_field_order
@@ -15,15 +15,11 @@ module Brightbox
15
15
  end
16
16
 
17
17
  def attributes
18
- t = fog_model.attributes
19
- t[:name] = name
20
- t[:description] = description
21
- t[:server_group] = server_group_id
22
- t
23
- end
24
-
25
- def to_row
26
- attributes
18
+ fog_attributes.tap do |attrs|
19
+ attrs[:name] = name
20
+ attrs[:description] = description
21
+ attrs[:server_group] = server_group_id
22
+ end
27
23
  end
28
24
 
29
25
  def self.default_field_order
@@ -19,24 +19,23 @@ module Brightbox
19
19
  end
20
20
 
21
21
  def attributes
22
- t = @attributes || fog_model.attributes
23
- t[:sport] = t[:source_port]
24
- t[:dport] = t[:destination_port]
25
- t[:firewall_policy] = t[:firewall_policy_id]
26
- t[:icmp_type] = t[:icmp_type_name]
27
- t
28
- end
29
-
30
- def to_row
31
- attrs = attributes.dup
32
- %i[protocol source sport destination dport icmp_type].each do |key|
33
- attrs[key] = attributes[key] || "-"
22
+ (@attributes || fog_attributes).tap do |attrs|
23
+ attrs[:sport] = attrs[:source_port]
24
+ attrs[:dport] = attrs[:destination_port]
25
+ attrs[:firewall_policy] = attrs[:firewall_policy_id]
26
+ attrs[:icmp_type] = attrs[:icmp_type_name]
34
27
  end
35
- attrs
36
28
  end
37
29
 
38
- def ret_val(attributes, key)
39
- attributes[key] || "-"
30
+ def to_row
31
+ attributes.merge(
32
+ protocol: attributes[:protocol] || "-",
33
+ source: attributes[:source] || "-",
34
+ sport: attributes[:sport] || "-",
35
+ destination: attributes[:destination] || "-",
36
+ dport: attributes[:dport] || "-",
37
+ icmp_type: attributes[:icmp_type] || "-"
38
+ )
40
39
  end
41
40
 
42
41
  def self.default_field_order
@@ -16,7 +16,7 @@ module Brightbox
16
16
  end
17
17
 
18
18
  def self.default_field_order
19
- %i[id owner type created_on status size arch name]
19
+ %i[id owner type created_on status size name]
20
20
  end
21
21
 
22
22
  # Filter out images that are not of the right type, account or status if the option is passed
@@ -68,31 +68,32 @@ module Brightbox
68
68
  end
69
69
 
70
70
  def status
71
- if fog_model.attributes[:status] == "available"
71
+ if fog_attributes[:status] == "available"
72
72
  public? ? "public" : "private"
73
+ elsif fog_attributes[:status] == "deprecated"
74
+ public? ? "deprecated" : "private"
73
75
  else
74
- fog_model.attributes[:status]
76
+ fog_attributes[:status]
75
77
  end
76
78
  end
77
79
 
78
80
  def to_row
79
- o = fog_model.attributes
80
- o[:id] = fog_model.id
81
- o[:status] = status
82
- o[:locked] = locked?
83
- o[:username] = username
84
- o[:arch] = arch
85
- o[:name] = name.to_s
86
- o[:owner] = owner_id
87
- o[:owner] = "brightbox" if official
88
- o[:type] = type
89
- o[:created_at] = created_at
90
- o[:created_on] = created_on
91
- o[:description] = description if description
92
- o[:licence_name] = licence_name
93
- o[:size] = virtual_size
94
- o[:min_ram] = min_ram
95
- o
81
+ fog_attributes.merge(
82
+ id: fog_model.id,
83
+ status: status,
84
+ locked: locked?,
85
+ username: username,
86
+ arch: arch,
87
+ name: name.to_s + " (#{arch})",
88
+ owner: official ? "brightbox" : owner_id,
89
+ type: type,
90
+ created_at: created_at,
91
+ created_on: created_on,
92
+ description: description,
93
+ licence_name: licence_name,
94
+ size: virtual_size,
95
+ min_ram: min_ram
96
+ )
96
97
  end
97
98
 
98
99
  def public?
@@ -100,7 +101,7 @@ module Brightbox
100
101
  end
101
102
 
102
103
  def status_sort_code
103
- case fog_model.attributes[:status]
104
+ case fog_attributes[:status]
104
105
  when "available"
105
106
  (public? ? 1 : 2)
106
107
  when "deprecated"
@@ -0,0 +1,50 @@
1
+ # A simpler wrapper to allows either String or Symbol keys to be used
2
+ # when accessing attributes since fog applies a change on the top
3
+ # level resulting in a mix of both which has introduced issues.
4
+ class IndifferentAccessHash
5
+ def initialize(hash)
6
+ @hash = hash
7
+ end
8
+
9
+ # @param key [String, Symbol] the key to look up
10
+ # @return [Object] the value of the key
11
+ def [](key)
12
+ value = @hash[key.to_s] || @hash[key.to_sym]
13
+ wrap(value)
14
+ end
15
+
16
+ # @param key [String, Symbol] the key to set
17
+ # @param value [Object] the value to set
18
+ # @return [Object] the value of the key
19
+ def []=(key, value)
20
+ @hash[key.to_sym] = value
21
+ end
22
+
23
+ # @param other [Object] the object to compare
24
+ # @return [Object] the result of the comparison
25
+ def ==(other)
26
+ @hash == (other.is_a?(IndifferentAccessHash) ? other.to_h : other)
27
+ end
28
+
29
+ def method_missing(method, *args, &block)
30
+ @hash.send(method, *args, &block)
31
+ end
32
+
33
+ def to_h
34
+ @hash
35
+ end
36
+
37
+ private
38
+
39
+ # This is to handle nested hashes to avoid the original issue again
40
+ def wrap(value)
41
+ case value
42
+ when Hash
43
+ IndifferentAccessHash.new(value)
44
+ when Array
45
+ value.map { |v| wrap(v) }
46
+ else
47
+ value
48
+ end
49
+ end
50
+ end