Skip to content

Commit bf75e9f

Browse files
authored
Implemnt util for Argus grafana configuration commands (#224)
1 parent 36e1c33 commit bf75e9f

File tree

2 files changed

+343
-6
lines changed

2 files changed

+343
-6
lines changed

internal/pkg/services/argus/utils/utils.go

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ const (
1414
service = "argus"
1515
)
1616

17+
type ArgusClient interface {
18+
GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error)
19+
GetGrafanaConfigsExecute(ctx context.Context, instanceId, projectId string) (*argus.GrafanaConfigs, error)
20+
}
21+
1722
func ValidatePlanId(planId string, resp *argus.PlansResponse) error {
1823
if resp == nil {
1924
return fmt.Errorf("no Argus plans provided")
@@ -56,14 +61,74 @@ func LoadPlanId(planName string, resp *argus.PlansResponse) (*string, error) {
5661
}
5762
}
5863

59-
type ArgusClient interface {
60-
GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error)
61-
}
62-
6364
func GetInstanceName(ctx context.Context, apiClient ArgusClient, instanceId, projectId string) (string, error) {
6465
resp, err := apiClient.GetInstanceExecute(ctx, instanceId, projectId)
6566
if err != nil {
6667
return "", fmt.Errorf("get Argus instance: %w", err)
6768
}
6869
return *resp.Name, nil
6970
}
71+
72+
func toPayloadGenericOAuth(response *argus.GrafanaOauth) *argus.UpdateGrafanaConfigsPayloadGenericOauth {
73+
if response == nil {
74+
return nil
75+
}
76+
return &argus.UpdateGrafanaConfigsPayloadGenericOauth{
77+
ApiUrl: response.ApiUrl,
78+
AuthUrl: response.AuthUrl,
79+
Enabled: response.Enabled,
80+
Name: response.Name,
81+
OauthClientId: response.OauthClientId,
82+
OauthClientSecret: response.OauthClientSecret,
83+
RoleAttributePath: response.RoleAttributePath,
84+
RoleAttributeStrict: response.RoleAttributeStrict,
85+
Scopes: response.Scopes,
86+
TokenUrl: response.TokenUrl,
87+
UsePkce: response.UsePkce,
88+
}
89+
}
90+
91+
func toRespGenericOAuth(payloadModel *argus.UpdateGrafanaConfigsPayloadGenericOauth) *argus.GrafanaOauth {
92+
if payloadModel == nil {
93+
return nil
94+
}
95+
return &argus.GrafanaOauth{
96+
ApiUrl: payloadModel.ApiUrl,
97+
AuthUrl: payloadModel.AuthUrl,
98+
Enabled: payloadModel.Enabled,
99+
Name: payloadModel.Name,
100+
OauthClientId: payloadModel.OauthClientId,
101+
OauthClientSecret: payloadModel.OauthClientSecret,
102+
RoleAttributePath: payloadModel.RoleAttributePath,
103+
RoleAttributeStrict: payloadModel.RoleAttributeStrict,
104+
Scopes: payloadModel.Scopes,
105+
TokenUrl: payloadModel.TokenUrl,
106+
UsePkce: payloadModel.UsePkce,
107+
}
108+
}
109+
110+
func GetPartialUpdateGrafanaConfigsPayload(ctx context.Context, apiClient ArgusClient, instanceId, projectId string, singleSignOn, publicReadAccess *bool) (*argus.UpdateGrafanaConfigsPayload, error) {
111+
currentConfigs, err := apiClient.GetGrafanaConfigsExecute(ctx, instanceId, projectId)
112+
if err != nil {
113+
return nil, fmt.Errorf("get current Grafana configs: %w", err)
114+
}
115+
116+
if currentConfigs == nil || currentConfigs.GenericOauth == nil {
117+
return nil, fmt.Errorf("no Grafana configs found for instance %q", instanceId)
118+
}
119+
120+
payload := &argus.UpdateGrafanaConfigsPayload{
121+
GenericOauth: toPayloadGenericOAuth(currentConfigs.GenericOauth),
122+
PublicReadAccess: currentConfigs.PublicReadAccess,
123+
UseStackitSso: currentConfigs.UseStackitSso,
124+
}
125+
126+
if singleSignOn != nil {
127+
payload.UseStackitSso = singleSignOn
128+
}
129+
if publicReadAccess != nil {
130+
payload.PublicReadAccess = publicReadAccess
131+
}
132+
133+
return payload, nil
134+
}

internal/pkg/services/argus/utils/utils_test.go

Lines changed: 274 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
1010

11+
"github.com/google/go-cmp/cmp"
1112
"github.com/google/uuid"
1213
"github.com/stackitcloud/stackit-sdk-go/services/argus"
1314
)
@@ -33,8 +34,10 @@ var testPlansResponse = argus.PlansResponse{
3334
}
3435

3536
type argusClientMocked struct {
36-
getInstanceFails bool
37-
getInstanceResp *argus.GetInstanceResponse
37+
getInstanceFails bool
38+
getInstanceResp *argus.GetInstanceResponse
39+
getGrafanaConfigsFails bool
40+
getGrafanaConfigsResp *argus.GrafanaConfigs
3841
}
3942

4043
func (m *argusClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*argus.GetInstanceResponse, error) {
@@ -43,6 +46,38 @@ func (m *argusClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (
4346
}
4447
return m.getInstanceResp, nil
4548
}
49+
50+
func (m *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*argus.GrafanaConfigs, error) {
51+
if m.getGrafanaConfigsFails {
52+
return nil, fmt.Errorf("could not get grafana configs")
53+
}
54+
return m.getGrafanaConfigsResp, nil
55+
}
56+
57+
func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.GrafanaConfigs {
58+
gc := argus.GrafanaConfigs{
59+
GenericOauth: &argus.GrafanaOauth{
60+
ApiUrl: utils.Ptr("apiUrl"),
61+
AuthUrl: utils.Ptr("authUrl"),
62+
Enabled: utils.Ptr(true),
63+
Name: utils.Ptr("name"),
64+
OauthClientId: utils.Ptr("oauthClientId"),
65+
OauthClientSecret: utils.Ptr("oauthClientSecret"),
66+
RoleAttributePath: utils.Ptr("roleAttributePath"),
67+
RoleAttributeStrict: utils.Ptr(true),
68+
Scopes: utils.Ptr("scopes"),
69+
TokenUrl: utils.Ptr("tokenUrl"),
70+
UsePkce: utils.Ptr(true),
71+
},
72+
PublicReadAccess: utils.Ptr(false),
73+
UseStackitSso: utils.Ptr(false),
74+
}
75+
for _, mod := range mods {
76+
mod(&gc)
77+
}
78+
return &gc
79+
}
80+
4681
func TestGetInstanceName(t *testing.T) {
4782
tests := []struct {
4883
description string
@@ -220,3 +255,240 @@ func TestValidatePlanId(t *testing.T) {
220255
})
221256
}
222257
}
258+
259+
func TestToPayloadGenericOAuth(t *testing.T) {
260+
tests := []struct {
261+
description string
262+
response *argus.GrafanaOauth
263+
expected *argus.UpdateGrafanaConfigsPayloadGenericOauth
264+
}{
265+
{
266+
description: "base",
267+
response: &argus.GrafanaOauth{
268+
ApiUrl: utils.Ptr("apiUrl"),
269+
AuthUrl: utils.Ptr("authUrl"),
270+
Enabled: utils.Ptr(true),
271+
Name: utils.Ptr("name"),
272+
OauthClientId: utils.Ptr("oauthClientId"),
273+
OauthClientSecret: utils.Ptr("oauthClientSecret"),
274+
RoleAttributePath: utils.Ptr("roleAttributePath"),
275+
RoleAttributeStrict: utils.Ptr(true),
276+
Scopes: utils.Ptr("scopes"),
277+
TokenUrl: utils.Ptr("tokenUrl"),
278+
UsePkce: utils.Ptr(true),
279+
},
280+
expected: &argus.UpdateGrafanaConfigsPayloadGenericOauth{
281+
ApiUrl: utils.Ptr("apiUrl"),
282+
AuthUrl: utils.Ptr("authUrl"),
283+
Enabled: utils.Ptr(true),
284+
Name: utils.Ptr("name"),
285+
OauthClientId: utils.Ptr("oauthClientId"),
286+
OauthClientSecret: utils.Ptr("oauthClientSecret"),
287+
RoleAttributePath: utils.Ptr("roleAttributePath"),
288+
RoleAttributeStrict: utils.Ptr(true),
289+
Scopes: utils.Ptr("scopes"),
290+
TokenUrl: utils.Ptr("tokenUrl"),
291+
UsePkce: utils.Ptr(true),
292+
},
293+
},
294+
{
295+
description: "nil response",
296+
response: nil,
297+
expected: nil,
298+
},
299+
}
300+
301+
for _, tt := range tests {
302+
t.Run(tt.description, func(t *testing.T) {
303+
output := toPayloadGenericOAuth(tt.response)
304+
305+
diff := cmp.Diff(output, tt.expected)
306+
if diff != "" {
307+
t.Errorf("expected output to be %+v, got %+v", tt.expected, output)
308+
}
309+
})
310+
}
311+
}
312+
313+
func TestToRespGenericOAuth(t *testing.T) {
314+
tests := []struct {
315+
description string
316+
payload *argus.UpdateGrafanaConfigsPayloadGenericOauth
317+
expected *argus.GrafanaOauth
318+
}{
319+
{
320+
description: "base",
321+
payload: &argus.UpdateGrafanaConfigsPayloadGenericOauth{
322+
ApiUrl: utils.Ptr("apiUrl"),
323+
AuthUrl: utils.Ptr("authUrl"),
324+
Enabled: utils.Ptr(true),
325+
Name: utils.Ptr("name"),
326+
OauthClientId: utils.Ptr("oauthClientId"),
327+
OauthClientSecret: utils.Ptr("oauthClientSecret"),
328+
RoleAttributePath: utils.Ptr("roleAttributePath"),
329+
RoleAttributeStrict: utils.Ptr(true),
330+
Scopes: utils.Ptr("scopes"),
331+
TokenUrl: utils.Ptr("tokenUrl"),
332+
UsePkce: utils.Ptr(true),
333+
},
334+
expected: &argus.GrafanaOauth{
335+
ApiUrl: utils.Ptr("apiUrl"),
336+
AuthUrl: utils.Ptr("authUrl"),
337+
Enabled: utils.Ptr(true),
338+
Name: utils.Ptr("name"),
339+
OauthClientId: utils.Ptr("oauthClientId"),
340+
OauthClientSecret: utils.Ptr("oauthClientSecret"),
341+
RoleAttributePath: utils.Ptr("roleAttributePath"),
342+
RoleAttributeStrict: utils.Ptr(true),
343+
Scopes: utils.Ptr("scopes"),
344+
TokenUrl: utils.Ptr("tokenUrl"),
345+
UsePkce: utils.Ptr(true),
346+
},
347+
},
348+
{
349+
description: "nil payload",
350+
payload: nil,
351+
expected: nil,
352+
},
353+
}
354+
355+
for _, tt := range tests {
356+
t.Run(tt.description, func(t *testing.T) {
357+
output := toRespGenericOAuth(tt.payload)
358+
359+
diff := cmp.Diff(output, tt.expected)
360+
if diff != "" {
361+
t.Errorf("expected output to be %+v, got %+v", tt.expected, output)
362+
}
363+
})
364+
}
365+
}
366+
367+
func TestGetPartialUpdateGrafanaConfigsPayload(t *testing.T) {
368+
tests := []struct {
369+
description string
370+
singleSignOn *bool
371+
publicReadAccess *bool
372+
getGrafanaConfigsFails bool
373+
getGrafanaConfigsResp *argus.GrafanaConfigs
374+
isValid bool
375+
expectedPayload *argus.UpdateGrafanaConfigsPayload
376+
}{
377+
{
378+
description: "enable both",
379+
singleSignOn: utils.Ptr(true),
380+
publicReadAccess: utils.Ptr(true),
381+
getGrafanaConfigsResp: fixtureGrafanaConfigs(),
382+
isValid: true,
383+
expectedPayload: &argus.UpdateGrafanaConfigsPayload{
384+
GenericOauth: toPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth),
385+
UseStackitSso: utils.Ptr(true),
386+
PublicReadAccess: utils.Ptr(true),
387+
},
388+
},
389+
{
390+
description: "disable both",
391+
singleSignOn: utils.Ptr(false),
392+
publicReadAccess: utils.Ptr(false),
393+
getGrafanaConfigsResp: fixtureGrafanaConfigs(),
394+
isValid: true,
395+
expectedPayload: &argus.UpdateGrafanaConfigsPayload{
396+
GenericOauth: toPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth),
397+
UseStackitSso: utils.Ptr(false),
398+
PublicReadAccess: utils.Ptr(false),
399+
},
400+
},
401+
{
402+
description: "enable single sign on",
403+
singleSignOn: utils.Ptr(true),
404+
publicReadAccess: nil,
405+
getGrafanaConfigsResp: fixtureGrafanaConfigs(),
406+
isValid: true,
407+
expectedPayload: &argus.UpdateGrafanaConfigsPayload{
408+
GenericOauth: toPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth),
409+
UseStackitSso: utils.Ptr(true),
410+
PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess,
411+
},
412+
},
413+
{
414+
description: "enable public read access",
415+
singleSignOn: nil,
416+
publicReadAccess: utils.Ptr(true),
417+
getGrafanaConfigsResp: fixtureGrafanaConfigs(),
418+
isValid: true,
419+
expectedPayload: &argus.UpdateGrafanaConfigsPayload{
420+
GenericOauth: toPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth),
421+
UseStackitSso: fixtureGrafanaConfigs().UseStackitSso,
422+
PublicReadAccess: utils.Ptr(true),
423+
},
424+
},
425+
{
426+
description: "disable single sign on",
427+
singleSignOn: utils.Ptr(false),
428+
publicReadAccess: nil,
429+
getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) {
430+
gc.UseStackitSso = utils.Ptr(true)
431+
}),
432+
isValid: true,
433+
expectedPayload: &argus.UpdateGrafanaConfigsPayload{
434+
GenericOauth: toPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth),
435+
UseStackitSso: utils.Ptr(false),
436+
PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess,
437+
},
438+
},
439+
{
440+
description: "disable public read access",
441+
singleSignOn: nil,
442+
publicReadAccess: utils.Ptr(false),
443+
getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) {
444+
gc.PublicReadAccess = utils.Ptr(true)
445+
}),
446+
isValid: true,
447+
expectedPayload: &argus.UpdateGrafanaConfigsPayload{
448+
GenericOauth: toPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth),
449+
UseStackitSso: fixtureGrafanaConfigs().UseStackitSso,
450+
PublicReadAccess: utils.Ptr(false),
451+
},
452+
},
453+
{
454+
description: "get grafana configs fails",
455+
singleSignOn: utils.Ptr(true),
456+
publicReadAccess: utils.Ptr(true),
457+
getGrafanaConfigsFails: true,
458+
isValid: false,
459+
},
460+
{
461+
description: "no grafana configs",
462+
singleSignOn: utils.Ptr(true),
463+
publicReadAccess: utils.Ptr(true),
464+
getGrafanaConfigsResp: &argus.GrafanaConfigs{},
465+
isValid: false,
466+
},
467+
}
468+
469+
for _, tt := range tests {
470+
t.Run(tt.description, func(t *testing.T) {
471+
client := &argusClientMocked{
472+
getGrafanaConfigsFails: tt.getGrafanaConfigsFails,
473+
getGrafanaConfigsResp: tt.getGrafanaConfigsResp,
474+
}
475+
476+
payload, err := GetPartialUpdateGrafanaConfigsPayload(context.Background(), client, testInstanceId, testProjectId, tt.singleSignOn, tt.publicReadAccess)
477+
478+
if tt.isValid && err != nil {
479+
t.Errorf("failed on valid input")
480+
}
481+
if !tt.isValid && err == nil {
482+
t.Errorf("did not fail on invalid input")
483+
}
484+
if !tt.isValid {
485+
return
486+
}
487+
488+
diff := cmp.Diff(payload, tt.expectedPayload)
489+
if diff != "" {
490+
t.Errorf("expected output payload to be %+v, got %+v", tt.expectedPayload, payload)
491+
}
492+
})
493+
}
494+
}

0 commit comments

Comments
 (0)