brightbox-cli 5.0.0.rc1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c8cd88f1d668182fcc07ad7ac31d8a3935bcf079321908ec56a364e59e0fe43
4
- data.tar.gz: 4b5ae117508d213f075adebf4c70996e95001abe39a6e9de0769232d29f5d3c5
3
+ metadata.gz: 5e929ec8c3d8a07bace33e5bbe1d7abf05ab2bbea81478251dda30dfaf8092de
4
+ data.tar.gz: dba86d8b80857f383a4b9fa4a977c6ff34f02d837e1f1f959a10133eb893f9f3
5
5
  SHA512:
6
- metadata.gz: 8b50ffa28cbb39bd012b39de3233ad1e6e29190723e2ed83f1239525c04bdbaa1927b7b26d528246fdbd5d9f6185ed08d88807ab58e7fd970b6dcadf65139b28
7
- data.tar.gz: 022e0c725cc12e5d2db5178100f7434a9c52de94eb8330a88688238c9183944b1199016f75d9a868568498a37258bf13d3032b5e9fb3a357198b1605e117503e
6
+ metadata.gz: b805583af2e9a07fb8d1936e116ad6bf4df7e5d95c9e531400f2e1eb79db391ddb2b6f38362c402956e73d4e5495948bbfb341cd015b98d21f3e95d998138710
7
+ data.tar.gz: 19925cf75cbc66ac82b5e91a34a7fc76e18fc34086b91b7eb271659665664f6907d759cebf872b56b0cb6e5bace2ef053d0f501393e123d112a2bb6ad195096d
data/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
- ### v5.0.0.rc1 / 2024-12-20
1
+ ### v5.0.0 / 2025-01-20
2
2
 
3
- [Full Changelog](https://github.com/brightbox/brightbox-cli/compare/v4.8.0...v5.0.0.rc1)
3
+ [Full Changelog](https://github.com/brightbox/brightbox-cli/compare/v4.8.0...v5.0.0)
4
4
 
5
5
  Backwards incompatible changes:
6
6
 
@@ -8,6 +8,11 @@ Backwards incompatible changes:
8
8
  * Update `Gemfile.lock` to use Bundler 2.4.22
9
9
  * When ENV `HOME` is not set, the working directory is used for configs
10
10
  rather than `/.brightbox` to fix issues with containers
11
+ * `show` commands require at least one argument to
12
+ prevent an issue where the wrong, summary API was
13
+ used resulting in missing data in tables
14
+ * `images` architecture is now its own `arch` column and no longer
15
+ combined with the name field.
11
16
 
12
17
  Enhancements:
13
18
 
@@ -57,6 +62,8 @@ Testing:
57
62
  test coverage.
58
63
  * Temporary testing config directories are removed explicitly to prevent
59
64
  config bleeding in some test scenarios
65
+ * Tests for `server activate_console` confirm support for local time and
66
+ time zones.
60
67
 
61
68
  ### v4.8.0 / 2024-10-23
62
69
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- brightbox-cli (5.0.0.rc1)
4
+ brightbox-cli (5.0.0)
5
5
  fog-brightbox (>= 1.12.0)
6
6
  fog-core (< 2.0)
7
7
  gli (~> 2.21)
@@ -4,7 +4,11 @@ module Brightbox
4
4
  cmd.arg_name "image-id..."
5
5
  cmd.command [:show] do |c|
6
6
  c.action do |global_options, _options, args|
7
- images = Image.find_all_or_warn(args)
7
+ raise "You must specify image IDs to show" if args.empty?
8
+
9
+ images = Image.find_or_call(args) do |id|
10
+ raise "Couldn't find an image with ID #{id}"
11
+ end
8
12
 
9
13
  display_options = {
10
14
  :vertical => true,
@@ -4,7 +4,11 @@ module Brightbox
4
4
  cmd.arg_name "lbs-id..."
5
5
  cmd.command [:show] do |c|
6
6
  c.action do |global_options, _options, args|
7
- lbs = LoadBalancer.find_all_or_warn(args)
7
+ raise "You must specify load balancer IDs to show" if args.empty?
8
+
9
+ lbs = LoadBalancer.find_or_call(args) do |id|
10
+ raise "Couldn't find a load balancer with ID #{id}"
11
+ end
8
12
 
9
13
  table_opts = global_options.merge(
10
14
  :vertical => true,
@@ -23,7 +23,11 @@ module Brightbox
23
23
  uri.query = "password=#{r['console_token']}"
24
24
 
25
25
  expires = Time.parse(r["console_token_expires"])
26
- consoles << { :url => uri.to_s, :token => r["console_token"], :expires => expires.localtime.to_s }
26
+ consoles << {
27
+ url: uri.to_s,
28
+ token: r["console_token"],
29
+ expires: expires.localtime.to_s
30
+ }
27
31
  end
28
32
 
29
33
  render_table(consoles, global_options.merge(:fields => %i[url token expires], :resize => false))
@@ -4,7 +4,11 @@ module Brightbox
4
4
  cmd.arg_name "server-id..."
5
5
  cmd.command [:show] do |c|
6
6
  c.action do |global_options, _options, args|
7
- servers = DetailedServer.find_all_or_warn(args)
7
+ raise "You must specify server IDs to show" if args.empty?
8
+
9
+ servers = DetailedServer.find_or_call(args) do |id|
10
+ raise "Couldn't find a server with ID #{id}"
11
+ end
8
12
 
9
13
  table_opts = global_options.merge(:vertical => true)
10
14
  render_table(servers, table_opts)
@@ -4,7 +4,11 @@ module Brightbox
4
4
  cmd.arg_name "user-id..."
5
5
  cmd.command [:show] do |c|
6
6
  c.action do |global_options, _options, args|
7
- users = User.find_all_or_warn(args)
7
+ raise "You must specify user IDs to show" if args.empty?
8
+
9
+ users = User.find_or_call(args) do |id|
10
+ raise "Couldn't find a user with ID #{id}"
11
+ end
8
12
 
9
13
  table_opts = global_options.merge(
10
14
  :vertical => true,
@@ -5,7 +5,11 @@ module Brightbox
5
5
 
6
6
  cmd.command [:show] do |c|
7
7
  c.action do |global_options, _options, args|
8
- volumes = Volume.find_all_or_warn(args)
8
+ raise "You must specify volume IDs to show" if args.empty?
9
+
10
+ volumes = Volume.find_or_call(args) do |id|
11
+ raise "Couldn't find a volume with ID #{id}"
12
+ end
9
13
 
10
14
  table_opts = global_options.merge(
11
15
  :vertical => true,
@@ -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 name]
19
+ %i[id owner type created_on status size arch 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
@@ -84,7 +84,7 @@ module Brightbox
84
84
  locked: locked?,
85
85
  username: username,
86
86
  arch: arch,
87
- name: name.to_s + " (#{arch})",
87
+ name: name.to_s,
88
88
  owner: official ? "brightbox" : owner_id,
89
89
  type: type,
90
90
  created_at: created_at,
@@ -1,3 +1,3 @@
1
1
  module Brightbox
2
- VERSION = "5.0.0.rc1".freeze unless defined?(Brightbox::VERSION)
2
+ VERSION = "5.0.0".freeze unless defined?(Brightbox::VERSION)
3
3
  end
@@ -17,35 +17,51 @@ RSpec.describe "brightbox images" do
17
17
  context "without arguments" do
18
18
  let(:argv) { %w[images show] }
19
19
 
20
+ it "reports missing IDs" do
21
+ expect { output }.to_not raise_error
22
+
23
+ aggregate_failures do
24
+ expect(stderr).to match("ERROR: You must specify image IDs to show")
25
+ expect(stdout).to eq("")
26
+ end
27
+ end
28
+ end
29
+
30
+ context "with identifier argument" do
31
+ let(:argv) { %w[images show img-11111] }
32
+
20
33
  before do
21
- stub_request(:get, "#{api_url}/1.0/images?account_id=acc-12345")
34
+ expect(Brightbox::Image).to receive(:find)
35
+ .with("img-11111")
36
+ .and_call_original
37
+
38
+ stub_request(:get, "#{api_url}/1.0/images/img-11111?account_id=acc-12345")
22
39
  .to_return(
23
40
  status: 200,
24
- body: [
25
- {
26
- id: "img-12345"
27
- }
28
- ].to_json
41
+ body: {
42
+ id: "img-11111",
43
+ min_ram: 2_048
44
+ }.to_json
29
45
  )
30
46
  end
31
47
 
32
48
  it "does not error" do
33
49
  expect { output }.to_not raise_error
34
50
 
35
- expect(stderr).to match("")
36
- expect(stderr).not_to match("ERROR")
37
- expect(stdout).to match("img-12345")
51
+ aggregate_failures do
52
+ expect(stderr).to match("")
53
+ expect(stderr).not_to match("ERROR")
54
+ expect(stdout).to match("img-11111")
55
+
56
+ expect(stdout).to match("min_ram: 2048")
57
+ end
38
58
  end
39
59
  end
40
60
 
41
- context "with identifier" do
42
- let(:argv) { %w[images show img-11111] }
61
+ context "with multiple identifiers" do
62
+ let(:argv) { %w[images show img-11111 img-22222] }
43
63
 
44
64
  before do
45
- expect(Brightbox::Image).to receive(:find)
46
- .with("img-11111")
47
- .and_call_original
48
-
49
65
  stub_request(:get, "#{api_url}/1.0/images/img-11111?account_id=acc-12345")
50
66
  .to_return(
51
67
  status: 200,
@@ -54,16 +70,30 @@ RSpec.describe "brightbox images" do
54
70
  min_ram: 2_048
55
71
  }.to_json
56
72
  )
73
+
74
+ stub_request(:get, "#{api_url}/1.0/images/img-22222?account_id=acc-12345")
75
+ .to_return(
76
+ status: 200,
77
+ body: {
78
+ id: "img-22222",
79
+ min_ram: 4_096
80
+ }.to_json
81
+ )
57
82
  end
58
83
 
59
84
  it "does not error" do
60
85
  expect { output }.to_not raise_error
61
86
 
62
- expect(stderr).to match("")
63
- expect(stderr).not_to match("ERROR")
64
- expect(stdout).to match("img-11111")
87
+ aggregate_failures do
88
+ expect(stderr).to match("")
89
+ expect(stderr).not_to match("ERROR")
90
+
91
+ expect(stdout).to match("img-11111")
92
+ expect(stdout).to match("min_ram: 2048")
65
93
 
66
- expect(stdout).to match("min_ram: 2048")
94
+ expect(stdout).to match("img-22222")
95
+ expect(stdout).to match("min_ram: 4096")
96
+ end
67
97
  end
68
98
  end
69
99
  end
@@ -11,29 +11,60 @@ describe "brightbox lbs" do
11
11
  cache_access_token(config, "f83da712e6299cda953513ec07f7a754f747d727")
12
12
  end
13
13
 
14
- context "without identifier argument" do
14
+ context "without arguments" do
15
15
  let(:argv) { %w[lbs show] }
16
+
17
+ it "reports missing IDs" do
18
+ expect { output }.to_not raise_error
19
+
20
+ aggregate_failures do
21
+ expect(stderr).to include("ERROR: You must specify load balancer IDs to show")
22
+ expect(stdout).to be_empty
23
+ end
24
+ end
25
+ end
26
+
27
+ context "with identifier argument" do
28
+ let(:argv) { %w[lbs show lba-12345] }
16
29
  let(:json_response) do
17
30
  <<~EOS
18
- [
19
- {
20
- "id":"lba-12345",
21
- "name":"app-lb1",
22
- "status":"active",
23
- "created_at":"2012-03-05T12:00:00Z",
24
- "nodes":[
31
+ {
32
+ "id":"lba-12345",
33
+ "name":"app-lb1",
34
+ "status":"active",
35
+ "created_at":"2012-03-05T12:00:00Z",
36
+ "acme": {
37
+ "domains": [
25
38
  {
26
- "id":"srv-12345",
27
- "status":"active"
39
+ "identifier": "domain.test",
40
+ "status": "verified"
41
+ },
42
+ {
43
+ "identifier": "domain2.test",
44
+ "status": "verified"
28
45
  }
29
- ]
30
- }
31
- ]
46
+ ],
47
+ "certificate": {
48
+ "domains": [
49
+ "domain.test"
50
+ ],
51
+ "expires_at": "2025-12-31T23:59:59Z",
52
+ "fingerprint": "fingerprint",
53
+ "issued_at": "2025-01-01T00:00:00Z"
54
+ }
55
+ },
56
+ "nodes":[
57
+ {
58
+ "id":"srv-12345",
59
+ "status":"active"
60
+ }
61
+ ]
62
+ }
32
63
  EOS
33
64
  end
34
65
 
35
66
  before do
36
- stub_request(:get, "http://api.brightbox.localhost/1.0/load_balancers?account_id=acc-12345")
67
+ stub_request(:get, "http://api.brightbox.localhost/1.0/load_balancers/lba-12345?account_id=acc-12345")
37
68
  .to_return(:status => 200, :body => json_response)
38
69
  end
39
70
 
@@ -45,13 +76,18 @@ describe "brightbox lbs" do
45
76
  expect(stdout).to include("name: app-lb1")
46
77
  expect(stdout).to include("created_at: 2012-03-05T12:00Z")
47
78
  expect(stdout).to include("nodes: srv-12345")
79
+ expect(stdout).to include("acme_domains: domain.test:verified,domain2.test:verified")
80
+ expect(stdout).to include("acme_cert_subjects: domain.test")
81
+ expect(stdout).to include("acme_cert_expires_at: 2025-12-31T23:59:59Z")
82
+ expect(stdout).to include("acme_cert_fingerprint: fingerprint")
83
+ expect(stdout).to include("acme_cert_issued_at: 2025-01-01T00:00:00Z")
48
84
  end
49
85
  end
50
86
  end
51
87
 
52
- context "with identifier argument" do
53
- let(:argv) { %w[lbs show lba-12345] }
54
- let(:json_response) do
88
+ context "with multiple identifiers" do
89
+ let(:argv) { %w[lbs show lba-12345 lba-54321] }
90
+ let(:json_response_1) do
55
91
  <<~EOS
56
92
  {
57
93
  "id":"lba-12345",
@@ -87,13 +123,52 @@ describe "brightbox lbs" do
87
123
  }
88
124
  EOS
89
125
  end
126
+ let(:json_response_2) do
127
+ <<~EOS
128
+ {
129
+ "id":"lba-54321",
130
+ "name":"app-lb2",
131
+ "status":"active",
132
+ "created_at":"2012-03-05T12:00:00Z",
133
+ "acme": {
134
+ "domains": [
135
+ {
136
+ "identifier": "domain.test",
137
+ "status": "verified"
138
+ },
139
+ {
140
+ "identifier": "domain2.test",
141
+ "status": "verified"
142
+ }
143
+ ],
144
+ "certificate": {
145
+ "domains": [
146
+ "domain.test"
147
+ ],
148
+ "expires_at": "2025-12-31T23:59:59Z",
149
+ "fingerprint": "fingerprint",
150
+ "issued_at": "2025-01-01T00:00:00Z"
151
+ }
152
+ },
153
+ "nodes":[
154
+ {
155
+ "id":"srv-54321",
156
+ "status":"active"
157
+ }
158
+ ]
159
+ }
160
+ EOS
161
+ end
90
162
 
91
163
  before do
92
164
  stub_request(:get, "http://api.brightbox.localhost/1.0/load_balancers/lba-12345?account_id=acc-12345")
93
- .to_return(:status => 200, :body => json_response)
165
+ .to_return(:status => 200, :body => json_response_1)
166
+
167
+ stub_request(:get, "http://api.brightbox.localhost/1.0/load_balancers/lba-54321?account_id=acc-12345")
168
+ .to_return(:status => 200, :body => json_response_2)
94
169
  end
95
170
 
96
- it "shows load balancer details" do
171
+ it "shows multiple load balancer details" do
97
172
  aggregate_failures do
98
173
  expect(stderr).to be_empty unless ENV["DEBUG"]
99
174
  expect(stdout).to include("id: lba-12345")
@@ -106,6 +181,17 @@ describe "brightbox lbs" do
106
181
  expect(stdout).to include("acme_cert_expires_at: 2025-12-31T23:59:59Z")
107
182
  expect(stdout).to include("acme_cert_fingerprint: fingerprint")
108
183
  expect(stdout).to include("acme_cert_issued_at: 2025-01-01T00:00:00Z")
184
+
185
+ expect(stdout).to include("id: lba-54321")
186
+ expect(stdout).to include("status: active")
187
+ expect(stdout).to include("name: app-lb2")
188
+ expect(stdout).to include("created_at: 2012-03-05T12:00Z")
189
+ expect(stdout).to include("nodes: srv-54321")
190
+ expect(stdout).to include("acme_domains: domain.test:verified,domain2.test:verified")
191
+ expect(stdout).to include("acme_cert_subjects: domain.test")
192
+ expect(stdout).to include("acme_cert_expires_at: 2025-12-31T23:59:59Z")
193
+ expect(stdout).to include("acme_cert_fingerprint: fingerprint")
194
+ expect(stdout).to include("acme_cert_issued_at: 2025-01-01T00:00:00Z")
109
195
  end
110
196
  end
111
197
  end
@@ -6,11 +6,153 @@ describe "brightbox servers" do
6
6
  let(:stdout) { output.stdout }
7
7
  let(:stderr) { output.stderr }
8
8
 
9
- context "" do
9
+ before do
10
+ WebMock.reset!
11
+
12
+ config_from_contents(API_CLIENT_CONFIG_CONTENTS)
13
+ stub_client_token_request
14
+ Brightbox.config.reauthenticate
15
+ end
16
+
17
+ context "without arguments" do
10
18
  let(:argv) { %w[servers activate_console] }
11
19
 
12
20
  it "does not error" do
13
21
  expect { output }.to_not raise_error
22
+
23
+ aggregate_failures do
24
+ expect(stderr).to match("ERROR: You must specify servers to activate the console for")
25
+ expect(stdout).to be_empty
26
+ end
27
+ end
28
+ end
29
+
30
+ context "with identifier argument" do
31
+ let(:argv) { %w[servers activate_console srv-lv426] }
32
+ let(:token_expires) { "2025-01-01T01:01:01Z" }
33
+
34
+ before do
35
+ stub_request(:get, "#{api_url}/1.0/servers/srv-lv426")
36
+ .with(query: hash_including(account_id: "acc-12345"))
37
+ .to_return(
38
+ status: 200,
39
+ body: {
40
+ id: "srv-lv426",
41
+ console_token: nil,
42
+ console_token_expires: nil,
43
+ console_url: nil,
44
+ image: {
45
+ id: "img-12345"
46
+ }
47
+ }.to_json
48
+ )
49
+
50
+ stub_request(:get, "#{api_url}/1.0/images")
51
+ .with(query: hash_including(account_id: "acc-12345"))
52
+ .to_return(
53
+ status: 200,
54
+ body: [
55
+ {
56
+ id: "img-12345"
57
+ }
58
+ ].to_json
59
+ )
60
+
61
+ stub_request(:post, "#{api_url}/1.0/servers/srv-lv426/activate_console")
62
+ .with(query: hash_including(account_id: "acc-12345"))
63
+ .to_return(
64
+ status: 202,
65
+ body: {
66
+ id: "srv-lv426",
67
+ console_token: "<test-token-placeholder>",
68
+ console_token_expires: token_expires,
69
+ console_url: "https://console.test.test/srv-lv426",
70
+ image: {
71
+ id: "img-12345"
72
+ }
73
+ }.to_json
74
+ )
75
+ end
76
+
77
+ context "when in different time zone" do
78
+ around do |example|
79
+ original_tz = ENV["TZ"]
80
+ example.run
81
+ ENV["TZ"] = original_tz
82
+ end
83
+
84
+ context "when in UTC" do
85
+ before do
86
+ ENV["TZ"] = "Europe/London"
87
+ end
88
+
89
+ context "without daylight savings" do
90
+ it "does not error" do
91
+ expect { output }.to_not raise_error
92
+
93
+ aggregate_failures do
94
+ expect(stderr).to match("")
95
+ expect(stderr).not_to match("ERROR")
96
+
97
+ expect(stdout).to match("url")
98
+ expect(stdout).to match("https://console.test.test/srv-lv426")
99
+
100
+ expect(stdout).to match("token")
101
+ expect(stdout).to match("<test-token-placeholder>")
102
+
103
+ expect(stdout).to match("expires")
104
+ expect(stdout).to match("2025-01-01T01:01")
105
+ end
106
+ end
107
+ end
108
+
109
+ context "with daylight savings (BST)" do
110
+ let(:token_expires) { "2025-07-01T01:01:01Z" }
111
+
112
+ it "does not error" do
113
+ expect { output }.to_not raise_error
114
+
115
+ aggregate_failures do
116
+ expect(stderr).to match("")
117
+ expect(stderr).not_to match("ERROR")
118
+
119
+ expect(stdout).to match("url")
120
+ expect(stdout).to match("https://console.test.test/srv-lv426")
121
+
122
+ expect(stdout).to match("token")
123
+ expect(stdout).to match("<test-token-placeholder>")
124
+
125
+ expect(stdout).to match("expires")
126
+ expect(stdout).to match("2025-07-01T02:01")
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ context "when in EST" do
133
+ around do |example|
134
+ ENV["TZ"] = "America/New_York"
135
+ example.run
136
+ end
137
+
138
+ it "does not error" do
139
+ expect { output }.to_not raise_error
140
+
141
+ aggregate_failures do
142
+ expect(stderr).to match("")
143
+ expect(stderr).not_to match("ERROR")
144
+
145
+ expect(stdout).to match("url")
146
+ expect(stdout).to match("https://console.test.test/srv-lv426")
147
+
148
+ expect(stdout).to match("token")
149
+ expect(stdout).to match("<test-token-placeholder>")
150
+
151
+ expect(stdout).to match("expires")
152
+ expect(stdout).to match("2024-12-31T20:01")
153
+ end
154
+ end
155
+ end
14
156
  end
15
157
  end
16
158
  end
@@ -6,11 +6,93 @@ describe "brightbox servers" do
6
6
  let(:stdout) { output.stdout }
7
7
  let(:stderr) { output.stderr }
8
8
 
9
- context "" do
9
+ before do
10
+ WebMock.reset!
11
+
12
+ config_from_contents(API_CLIENT_CONFIG_CONTENTS)
13
+ stub_client_token_request
14
+ Brightbox.config.reauthenticate
15
+ end
16
+
17
+ context "without arguments" do
10
18
  let(:argv) { %w[servers show] }
11
19
 
20
+ it "reports missing IDs" do
21
+ expect { output }.to_not raise_error
22
+
23
+ aggregate_failures do
24
+ expect(stderr).to match("ERROR: You must specify server IDs to show")
25
+ expect(stdout).to be_empty
26
+ end
27
+ end
28
+ end
29
+
30
+ context "with identifier argument" do
31
+ let(:argv) { %w[servers show srv-55555] }
32
+
33
+ before do
34
+ stub_request(:get, "#{api_url}/1.0/images")
35
+ .with(query: hash_including(account_id: "acc-12345"))
36
+ .to_return(
37
+ status: 200,
38
+ body: {
39
+ images: [
40
+ {
41
+ id: "img-12345",
42
+ min_ram: 2_048
43
+ }
44
+ ]
45
+ }.to_json
46
+ )
47
+
48
+ stub_request(:get, "#{api_url}/1.0/images/img-12345")
49
+ .with(query: hash_including(account_id: "acc-12345"))
50
+ .to_return(
51
+ status: 200,
52
+ body: {
53
+ id: "img-12345"
54
+ }.to_json
55
+ )
56
+
57
+ stub_request(:get, "#{api_url}/1.0/servers/srv-55555")
58
+ .with(query: hash_including(account_id: "acc-12345"))
59
+ .to_return(
60
+ status: 200,
61
+ body: {
62
+ id: "srv-12345",
63
+ name: "app-server1",
64
+ status: "active",
65
+ image: {
66
+ id: "img-12345"
67
+ },
68
+ server_type: {
69
+ id: "typ-12345"
70
+ },
71
+ cloud_ips: [],
72
+ interfaces: [
73
+ {
74
+ id: "int-12345",
75
+ ipv4_address: "10.0.0.0",
76
+ ipv6_address: "2a02:1234:abcd:5678::1"
77
+ }
78
+ ],
79
+ server_groups: [],
80
+ snapshots: []
81
+ }.to_json
82
+ )
83
+ end
84
+
12
85
  it "does not error" do
86
+ require "pry"
87
+ # binding.pry
13
88
  expect { output }.to_not raise_error
89
+
90
+ aggregate_failures do
91
+ expect(stderr).not_to match("ERROR")
92
+ expect(stdout).to match("id: srv-12345")
93
+ expect(stdout).to match("status: active")
94
+ expect(stdout).to match("name: app-server1")
95
+ end
14
96
  end
15
97
  end
16
98
  end
@@ -6,11 +6,76 @@ describe "brightbox users" do
6
6
  let(:stdout) { output.stdout }
7
7
  let(:stderr) { output.stderr }
8
8
 
9
- context "" do
9
+ before do
10
+ WebMock.reset!
11
+
12
+ config_from_contents(API_CLIENT_CONFIG_CONTENTS)
13
+ stub_client_token_request
14
+ Brightbox.config.reauthenticate
15
+ end
16
+
17
+ context "without arguments" do
10
18
  let(:argv) { %w[users show] }
11
19
 
12
20
  it "does not error" do
13
21
  expect { output }.to_not raise_error
22
+
23
+ aggregate_failures do
24
+ expect(stderr).to match("ERROR: You must specify user IDs to show")
25
+ expect(stdout).to be_empty
26
+ end
27
+ end
28
+ end
29
+
30
+ context "with identifier argument" do
31
+ let(:argv) { %w[users show usr-90781] }
32
+
33
+ before do
34
+ # FIXME: Two requests, one with the parameter and one without
35
+ # One for ALL tests (with VCR breaking things)
36
+ # One for this test standalone
37
+ stub_request(:get, "#{api_url}/1.0/users/usr-90781")
38
+ .to_return(
39
+ status: 200,
40
+ body: {
41
+ id: "usr-90781",
42
+ email_address: "user@domain.test",
43
+ accounts: [
44
+ {
45
+ id: "acc-12345",
46
+ name: "Test account"
47
+ }
48
+ ]
49
+ }.to_json
50
+ )
51
+
52
+ # Same again but supporting the account_id parameter
53
+ stub_request(:get, "#{api_url}/1.0/users/usr-90781")
54
+ .with(query: hash_including(account_id: "acc-12345"))
55
+ .to_return(
56
+ status: 200,
57
+ body: {
58
+ id: "usr-90781",
59
+ email_address: "user@domain.test",
60
+ accounts: [
61
+ {
62
+ id: "acc-12345",
63
+ name: "Test account"
64
+ }
65
+ ]
66
+ }.to_json
67
+ )
68
+ end
69
+
70
+ it "does not error" do
71
+ expect { output }.to_not raise_error
72
+
73
+ aggregate_failures do
74
+ expect(stderr).to match("")
75
+ expect(stderr).not_to match("ERROR")
76
+ expect(stdout).to match("usr-90781")
77
+ expect(stdout).to match("email_address: user@domain.test")
78
+ end
14
79
  end
15
80
  end
16
81
  end
@@ -8,45 +8,27 @@ describe "brightbox volumes show" do
8
8
  let(:stderr) { output.stderr }
9
9
 
10
10
  before do
11
- config_from_contents(API_CLIENT_CONFIG_CONTENTS)
12
-
13
- stub_request(:post, "http://api.brightbox.localhost/token")
14
- .to_return(
15
- status: 200,
16
- body: JSON.dump(
17
- access_token: "ACCESS-TOKEN",
18
- refresh_token: "REFRESH_TOKEN"
19
- )
20
- )
11
+ WebMock.reset!
21
12
 
13
+ config_from_contents(API_CLIENT_CONFIG_CONTENTS)
14
+ stub_client_token_request
22
15
  Brightbox.config.reauthenticate
23
16
  end
24
17
 
25
18
  context "without arguments" do
26
19
  let(:argv) { %w[volumes show] }
27
20
 
28
- before do
29
- stub_request(:get, "http://api.brightbox.localhost/1.0/volumes")
30
- .with(query: hash_including(account_id: "acc-12345"))
31
- .to_return(
32
- status: 200,
33
- body: volumes_response
34
- )
35
- end
36
-
37
- it "does not error" do
21
+ it "reports missing IDs" do
38
22
  expect { output }.to_not raise_error
39
23
 
40
- expect(stderr).to be_empty unless ENV["DEBUG"]
41
-
42
24
  aggregate_failures do
43
- expect(stdout).to match("id: vol-12345")
44
- expect(stdout).to match("id: vol-abcde")
25
+ expect(stderr).to match("ERROR: You must specify volume IDs to show")
26
+ expect(stdout).to be_empty
45
27
  end
46
28
  end
47
29
  end
48
30
 
49
- context "with identifier" do
31
+ context "with identifier argument" do
50
32
  let(:argv) { %w[volumes show vol-88878] }
51
33
 
52
34
  before do
@@ -92,4 +74,51 @@ describe "brightbox volumes show" do
92
74
  end
93
75
  end
94
76
  end
77
+
78
+ context "with multiple identifiers" do
79
+ let(:argv) { %w[volumes show vol-88878 vol-99999] }
80
+
81
+ before do
82
+ stub_request(:get, "http://api.brightbox.localhost/1.0/volumes/vol-88878")
83
+ .with(query: hash_including(account_id: "acc-12345"))
84
+ .to_return(
85
+ status: 200,
86
+ body: volume_response(
87
+ id: "vol-88878",
88
+ description: "A volume for testing",
89
+ filesystem_type: "ext4",
90
+ storage_type: "network",
91
+ size: 10_240,
92
+ status: "attached",
93
+ server: nil
94
+ )
95
+ )
96
+
97
+ stub_request(:get, "http://api.brightbox.localhost/1.0/volumes/vol-99999")
98
+ .with(query: hash_including(account_id: "acc-12345"))
99
+ .to_return(
100
+ status: 200,
101
+ body: volume_response(
102
+ id: "vol-99999",
103
+ description: "Another volume for testing",
104
+ filesystem_type: "ext4",
105
+ storage_type: "network",
106
+ size: 10_240,
107
+ status: "attached",
108
+ server: nil
109
+ )
110
+ )
111
+ end
112
+
113
+ it "does not error" do
114
+ expect { output }.to_not raise_error
115
+
116
+ expect(stderr).not_to match("ERROR")
117
+
118
+ aggregate_failures do
119
+ expect(stdout).to match("id: vol-88878")
120
+ expect(stdout).to match("id: vol-99999")
121
+ end
122
+ end
123
+ end
95
124
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brightbox-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.rc1
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Leach
8
8
  - Paul Thornthwaite
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2024-12-20 00:00:00.000000000 Z
11
+ date: 2025-01-20 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: fog-brightbox
@@ -827,7 +826,6 @@ licenses:
827
826
  - MIT
828
827
  metadata:
829
828
  rubygems_mfa_required: 'true'
830
- post_install_message:
831
829
  rdoc_options: []
832
830
  require_paths:
833
831
  - lib
@@ -838,12 +836,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
838
836
  version: '2.7'
839
837
  required_rubygems_version: !ruby/object:Gem::Requirement
840
838
  requirements:
841
- - - ">"
839
+ - - ">="
842
840
  - !ruby/object:Gem::Version
843
- version: 1.3.1
841
+ version: '0'
844
842
  requirements: []
845
- rubygems_version: 3.4.19
846
- signing_key:
843
+ rubygems_version: 3.6.2
847
844
  specification_version: 4
848
845
  summary: The Brightbox cloud management system
849
846
  test_files: