Skip to content

Commit 8476c60

Browse files
authored
fix: address panic in response handling and better handling for ModelStatus api method (#1895)
* fix: address panic in secret backend results * fix: better error handling for ModelStatus api client method
1 parent ca834d3 commit 8476c60

File tree

4 files changed

+101
-4
lines changed

4 files changed

+101
-4
lines changed

internal/jujuapi/types.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ func toFullModelInfo(modelInfo jujuclient.ModelInfo) jujuparams.ModelInfo {
325325

326326
var secretBackendResults []jujuparams.SecretBackendResult
327327
for _, sb := range modelInfo.SecretBackends {
328-
secretBackendResults = append(secretBackendResults, jujuparams.SecretBackendResult{
328+
res := jujuparams.SecretBackendResult{
329329
Result: jujuparams.SecretBackend{
330330
Name: sb.Result.Name,
331331
BackendType: sb.Result.BackendType,
@@ -336,12 +336,15 @@ func toFullModelInfo(modelInfo jujuclient.ModelInfo) jujuparams.ModelInfo {
336336
NumSecrets: sb.NumSecrets,
337337
Status: sb.Status,
338338
Message: sb.Message,
339-
Error: &jujuparams.Error{
339+
}
340+
if sb.Error != nil {
341+
res.Error = &jujuparams.Error{
340342
Message: sb.Error.Error(),
341343
Code: string(errors.ErrorCode(sb.Error)),
342344
Info: errors.ErrorInfo(sb.Error),
343-
},
344-
})
345+
}
346+
}
347+
secretBackendResults = append(secretBackendResults, res)
345348
}
346349
modelInfoParams.SecretBackends = secretBackendResults
347350

internal/jujuapi/types_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,3 +363,69 @@ func TestToFullModelInfo(t *testing.T) {
363363
},
364364
}})
365365
}
366+
367+
func TestToFullModelInfoNilSecretBackendError(t *testing.T) {
368+
c := qt.New(t)
369+
370+
modelInfo := jujuclient.ModelInfo{
371+
ModelInfo: base.ModelInfo{
372+
Name: "test-model",
373+
Cloud: "aws",
374+
CloudCredential: "aws/alice@canonical.com/main-cred",
375+
Owner: "alice@canonical.com",
376+
},
377+
SecretBackends: []jujuclient.SecretBackendResult{{
378+
Result: jujuclient.SecretBackend{
379+
Name: "vault",
380+
BackendType: "vault",
381+
},
382+
ID: "backend-1",
383+
NumSecrets: 7,
384+
Status: "available",
385+
Message: "ready",
386+
Error: nil,
387+
}},
388+
}
389+
390+
got := toFullModelInfo(modelInfo)
391+
392+
c.Assert(got.SecretBackends, qt.DeepEquals, []jujuparams.SecretBackendResult{{
393+
Result: jujuparams.SecretBackend{
394+
Name: "vault",
395+
BackendType: "vault",
396+
},
397+
ID: "backend-1",
398+
NumSecrets: 7,
399+
Status: "available",
400+
Message: "ready",
401+
Error: nil,
402+
}})
403+
}
404+
405+
func TestToFullModelInfoNonNilSecretBackendError(t *testing.T) {
406+
c := qt.New(t)
407+
408+
modelInfo := jujuclient.ModelInfo{
409+
ModelInfo: base.ModelInfo{
410+
Name: "test-model",
411+
Cloud: "aws",
412+
CloudCredential: "aws/alice@canonical.com/main-cred",
413+
Owner: "alice@canonical.com",
414+
},
415+
SecretBackends: []jujuclient.SecretBackendResult{{
416+
Result: jujuclient.SecretBackend{
417+
Name: "vault",
418+
BackendType: "vault",
419+
},
420+
Error: errors.E("an error", errors.CodeNotFound, map[string]any{"detail": "not found"}),
421+
}},
422+
}
423+
424+
got := toFullModelInfo(modelInfo)
425+
426+
c.Assert(got.SecretBackends, qt.HasLen, 1)
427+
c.Assert(got.SecretBackends[0].Error, qt.IsNotNil)
428+
c.Assert(got.SecretBackends[0].Error.Error(), qt.Equals, "an error")
429+
c.Assert(got.SecretBackends[0].Error.Code, qt.Equals, string(errors.CodeNotFound))
430+
c.Assert(got.SecretBackends[0].Error.Info, qt.DeepEquals, map[string]any{"detail": "not found"})
431+
}

internal/jujuclient/modelmanager.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ func (c Connection) ModelStatus(ctx context.Context, modelTag names.ModelTag) (b
142142
if len(statuses) == 0 {
143143
return base.ModelStatus{}, errors.E("no status returned for model")
144144
}
145+
if statuses[0].Error != nil {
146+
return base.ModelStatus{}, statuses[0].Error
147+
}
145148
return statuses[0], nil
146149
}
147150

testing/dial_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import (
88
"testing"
99

1010
qt "github.com/frankban/quicktest"
11+
"github.com/google/uuid"
1112
"github.com/juju/names/v5"
1213
"github.com/juju/version/v2"
1314

1415
"github.com/canonical/jimm/v3/internal/dbmodel"
16+
"github.com/canonical/jimm/v3/internal/errors"
1517
"github.com/canonical/jimm/v3/internal/jujuclient"
1618
"github.com/canonical/jimm/v3/internal/testutils/jimmtest"
1719
)
@@ -82,6 +84,29 @@ func TestDialWithJWT(t *testing.T) {
8284
c.Check(addrs, qt.ContentEquals, config.Addrs)
8385
}
8486

87+
func TestDialModelStatusMissingModel(t *testing.T) {
88+
c := qt.New(t)
89+
s := jimmtest.SetupJimmWithControllers(c)
90+
91+
name, config := s.GetOneControllerConfig(c)
92+
ctl := dbmodel.Controller{
93+
UUID: config.UUID,
94+
Name: name,
95+
CACertificate: config.CACert,
96+
PublicAddress: config.Addrs[0],
97+
TLSHostname: "juju-apiserver",
98+
}
99+
100+
api, err := s.JIMM.Dialer.Dial(context.Background(), &ctl, names.ModelTag{}, nil, nil)
101+
c.Assert(err, qt.Equals, nil)
102+
defer api.Close()
103+
104+
_, err = api.ModelStatus(context.Background(), names.NewModelTag(uuid.NewString()))
105+
c.Assert(err, qt.Not(qt.IsNil))
106+
c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeNotFound)
107+
c.Check(err, qt.ErrorMatches, `model .* not found.*`)
108+
}
109+
85110
// TestConnectStreams tests the ConnectStream and ConnectControllerStream methods
86111
// of our Juju dialer. It verifies that we can connect to valid endpoints
87112
// on a Juju controller, and that invalid endpoints return errors.

0 commit comments

Comments
 (0)