1 package loaddata
2
3 import (
4 "cmp"
5 "context"
6 "encoding/json"
7 "io"
8 "net/http"
9 "net/url"
10 "os"
11 "path/filepath"
12 "slices"
13 "strings"
14 "testing"
15 "time"
16
17 "github.com/99designs/gqlgen/graphql"
18 graphqlTypes "github.com/shurcooL/graphql"
19 "github.com/stretchr/testify/require"
20
21 "edge-infra.dev/pkg/edge/api/graph/model"
22 "edge-infra.dev/pkg/edge/api/utils"
23 "edge-infra.dev/pkg/edge/edgecli"
24 "edge-infra.dev/pkg/edge/edgecli/flagutil"
25 )
26
27 var defaultConfig = `
28 {
29 "ROLE_MAPPING": {
30 "EDGE_BANNER_ADMIN": [
31 "ea-read",
32 "ea-banner-admin"
33 ]
34 },
35 "RULES": {
36 "ea-write": [
37 "ls",
38 "cat"
39 ],
40 "ea-banner-admin": [
41 "kubectl"
42 ]
43 }
44 }
45 `
46
47
48 type helper interface {
49 Helper()
50 }
51
52 func ErrorEqualMsg(msg string) require.ErrorAssertionFunc {
53 return func(tt require.TestingT, err error, _ ...interface{}) {
54 if help, ok := tt.(helper); ok {
55 help.Helper()
56 }
57
58 require.EqualError(tt, err, msg)
59 }
60 }
61
62
63
64 func ErrorEqualMsgElements(msg string) require.ErrorAssertionFunc {
65 return func(tt require.TestingT, err error, _ ...interface{}) {
66 if help, ok := tt.(helper); ok {
67 help.Helper()
68 }
69
70 expected := strings.Split(msg, "\n")
71 actual := strings.Split(err.Error(), "\n")
72 for _, errMsg := range expected {
73 require.Contains(tt, actual, errMsg)
74 }
75 }
76 }
77
78 func TestValidate(t *testing.T) {
79 t.Parallel()
80
81 tests := map[string]struct {
82 cfg config
83 expErr require.ErrorAssertionFunc
84 }{
85 "Valid Full Config": {
86 cfg: config{
87 RoleMappings: map[string][]string{
88 "role1": {
89 "priv1",
90 "priv2",
91 },
92 "role2": {
93 "priv3",
94 },
95 },
96 Rules: map[string][]string{
97 "priv1": {
98 "command1",
99 "command2",
100 },
101 "priv2": {
102 "command3",
103 },
104 },
105 },
106 expErr: require.NoError,
107 },
108 "Valid Half Config": {
109 cfg: config{
110 RoleMappings: map[string][]string{
111 "role1": {
112 "priv1",
113 },
114 },
115 },
116 expErr: require.NoError,
117 },
118 "Invalid Uninitialized Maps": {
119 cfg: config{
120 RoleMappings: map[string][]string{},
121 Rules: map[string][]string{},
122 },
123 expErr: ErrorEqualMsg("empty config"),
124 },
125 "Invalid No Config": {
126 cfg: config{},
127 expErr: ErrorEqualMsg("empty config"),
128 },
129 "Invalid Full Config": {
130 cfg: config{
131 RoleMappings: map[string][]string{
132 "role1": {
133
134 "",
135 },
136
137 "role2": {},
138 },
139 Rules: map[string][]string{
140 "priv1": {
141
142 "",
143 },
144
145 "priv2": {},
146 },
147 },
148 expErr: ErrorEqualMsgElements("role \"role1\" has empty privilege\nrole \"role2\" has no privileges\nprivilege \"priv1\" has empty command\nprivilege \"priv2\" has no commands"),
149 },
150 }
151
152 for name, tc := range tests {
153 tc := tc
154 t.Run(name, func(t *testing.T) {
155 t.Parallel()
156
157 tc.expErr(t, tc.cfg.Validate())
158 })
159 }
160 }
161
162 func TestLoadConfig(t *testing.T) {
163 t.Parallel()
164 tests := map[string]struct {
165 testData string
166 wantConfig config
167 requireError require.ErrorAssertionFunc
168 }{
169 "ValidConfig": {
170 testData: `{
171 "ROLE_MAPPING": {
172 "EDGE_BANNER_ADMIN": [
173 "ea-read",
174 "ea-banner-admin"
175 ]
176 },
177 "RULES": {
178 "ea-write": [
179 "ls",
180 "cat"
181 ],
182 "ea-banner-admin": [
183 "kubectl"
184 ]
185 }
186 }`,
187 wantConfig: config{
188 RoleMappings: map[string][]string{
189 "EDGE_BANNER_ADMIN": {
190 "ea-read",
191 "ea-banner-admin",
192 },
193 },
194 Rules: map[string][]string{
195 "ea-write": {
196 "ls",
197 "cat",
198 },
199 "ea-banner-admin": {
200 "kubectl",
201 },
202 },
203 },
204 requireError: require.NoError,
205 },
206 "Duplicate Keys": {
207
208
209 testData: `{
210 "ROLE_MAPPING": {
211 "EDGE_BANNER_ADMIN": [
212 "ea-admin"
213 ],
214 "EDGE_ORG_ADMIN": [
215 "ea-admin"
216 ],
217 "EDGE_BANNER_ADMIN": [
218 "ea-write"
219 ]
220 }
221 }`,
222 wantConfig: config{
223 RoleMappings: map[string][]string{
224 "EDGE_BANNER_ADMIN": {
225 "ea-write",
226 },
227 "EDGE_ORG_ADMIN": {
228 "ea-admin",
229 },
230 },
231 },
232 requireError: require.NoError,
233 },
234 "InvalidConfig": {
235 testData: `invalid json`,
236 wantConfig: config{},
237 requireError: ErrorEqualMsg("invalid character 'i' looking for beginning of value"),
238 },
239 "Invalid After Valid JSON": {
240 testData: `{
241 "ROLE_MAPPING": {
242 "EDGE_BANNER_ADMIN": [
243 "ea-banner-admin"
244 ]
245 },
246 "RULES": {
247 "ea-banner-admin": [
248 "kubectl"
249 ]
250 }
251 }INVALIDINPUTOVERHERE`,
252 wantConfig: config{},
253 requireError: ErrorEqualMsg("error multiple objects in config file"),
254 },
255 "Invalid Multiple Valid JSON Objects": {
256 testData: `{
257 "ROLE_MAPPING": {
258 "EDGE_BANNER_ADMIN": [
259 "ea-banner-admin"
260 ]
261 }
262 },
263 {
264 "RULES": {
265 "ea-banner-admin": [
266 "kubectl"
267 ]
268 }
269 }`,
270 wantConfig: config{},
271 requireError: ErrorEqualMsg("error multiple objects in config file"),
272 },
273 "Unknown Fields": {
274 testData: `{
275 "ROLE_MAPPING": {
276 "EDGE_BANNER_ADMIN": [
277 "ea-read"
278 ]
279 },
280 "RULES": {
281 "ea-write": [
282 "ls"
283 ]
284 },
285 "somethingelse": {
286 "somethingelse": [
287 "somethingelse"
288 ]
289 }
290 }`,
291 requireError: ErrorEqualMsg("json: unknown field \"somethingelse\""),
292 },
293 "EmptyConfig": {
294 testData: `{}`,
295 requireError: ErrorEqualMsg("error invalid config: empty config"),
296 },
297 "Empty Fields": {
298 testData: `{
299 "ROLE_MAPPING": {},
300 "RULES": {}
301 }`,
302 requireError: ErrorEqualMsg("error invalid config: empty config"),
303 },
304 }
305
306 for name, tt := range tests {
307 tt := tt
308 t.Run(name, func(t *testing.T) {
309 t.Parallel()
310
311 tempDir := t.TempDir()
312
313
314 filePath := filepath.Join(tempDir, "config.json")
315
316
317 err := os.WriteFile(filePath, []byte(tt.testData), 0644)
318 if err != nil {
319 t.Fatal(err)
320 }
321
322
323 conf, err := loadConfig(filePath)
324
325
326 tt.requireError(t, err)
327
328
329 require.EqualValues(t, tt.wantConfig, conf)
330 })
331 }
332 }
333
334 func TestVariables(t *testing.T) {
335 t.Parallel()
336
337 tests := map[string]struct {
338 conf config
339 expVariables map[string]interface{}
340 }{
341 "No Config": {
342 conf: config{
343 Rules: nil,
344 RoleMappings: nil,
345 },
346 expVariables: map[string]interface{}{
347
348
349 "commands": []model.OperatorInterventionCommandInput{},
350 "privileges": []model.OperatorInterventionPrivilegeInput{},
351 "rules": []model.UpdateOperatorInterventionRuleInput{},
352 "roleMappings": []*model.UpdateOperatorInterventionRoleMappingInput{},
353
354
355 "skipCommands": graphqlTypes.Boolean(true),
356 "skipPrivileges": graphqlTypes.Boolean(true),
357 "skipRules": graphqlTypes.Boolean(true),
358 "skipRoleMappings": graphqlTypes.Boolean(true),
359 },
360 },
361 "Only Role Mappings": {
362 conf: config{
363 Rules: nil,
364 RoleMappings: map[string][]string{
365 "EDGE_ORG_ADMIN": {
366 "ea-read", "ea-write",
367 },
368 },
369 },
370 expVariables: map[string]interface{}{
371
372
373
374 "commands": []model.OperatorInterventionCommandInput{},
375 "rules": []model.UpdateOperatorInterventionRuleInput{},
376
377
378 "privileges": []model.OperatorInterventionPrivilegeInput{
379 {Name: "ea-read"}, {Name: "ea-write"},
380 },
381
382 "roleMappings": []*model.UpdateOperatorInterventionRoleMappingInput{
383 {
384 Role: "EDGE_ORG_ADMIN",
385 Privileges: []*model.OperatorInterventionPrivilegeInput{
386 {Name: "ea-read"},
387 {Name: "ea-write"},
388 },
389 },
390 },
391
392
393 "skipCommands": graphqlTypes.Boolean(true),
394 "skipRules": graphqlTypes.Boolean(true),
395
396 "skipPrivileges": graphqlTypes.Boolean(false),
397 "skipRoleMappings": graphqlTypes.Boolean(false),
398 },
399 },
400 "Only Rules": {
401 conf: config{
402 Rules: map[string][]string{
403 "ea-admin": {"ls", "systemctl"},
404 "ea-read": {"ls", "cat"},
405 },
406 RoleMappings: nil,
407 },
408 expVariables: map[string]interface{}{
409
410
411
412 "roleMappings": []*model.UpdateOperatorInterventionRoleMappingInput{},
413
414
415 "privileges": []model.OperatorInterventionPrivilegeInput{
416 {Name: "ea-admin"}, {Name: "ea-read"},
417 },
418 "commands": []model.OperatorInterventionCommandInput{
419
420 {Name: "cat"}, {Name: "ls"}, {Name: "systemctl"},
421 },
422
423 "rules": []model.UpdateOperatorInterventionRuleInput{
424 {
425 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "ea-admin"},
426 Commands: []*model.OperatorInterventionCommandInput{{Name: "ls"}, {Name: "systemctl"}},
427 },
428 {
429 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "ea-read"},
430 Commands: []*model.OperatorInterventionCommandInput{{Name: "ls"}, {Name: "cat"}},
431 },
432 },
433
434
435 "skipRoleMappings": graphqlTypes.Boolean(true),
436
437 "skipCommands": graphqlTypes.Boolean(false),
438 "skipPrivileges": graphqlTypes.Boolean(false),
439 "skipRules": graphqlTypes.Boolean(false),
440 },
441 },
442 "Both Rules and Mappings": {
443 conf: config{
444 Rules: map[string][]string{
445 "ea-admin": {"ls", "systemctl"},
446 "ea-read": {"ls", "cat"},
447 },
448 RoleMappings: map[string][]string{
449 "EDGE_ORG_ADMIN": {
450 "ea-read", "ea-write",
451 },
452 },
453 },
454 expVariables: map[string]interface{}{
455 "commands": []model.OperatorInterventionCommandInput{
456
457 {Name: "cat"}, {Name: "ls"}, {Name: "systemctl"},
458 },
459
460
461 "privileges": []model.OperatorInterventionPrivilegeInput{
462
463 {Name: "ea-admin"},
464 {Name: "ea-read"},
465 {Name: "ea-write"},
466 },
467
468 "rules": []model.UpdateOperatorInterventionRuleInput{
469 {
470 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "ea-admin"},
471 Commands: []*model.OperatorInterventionCommandInput{{Name: "ls"}, {Name: "systemctl"}},
472 },
473 {
474 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "ea-read"},
475 Commands: []*model.OperatorInterventionCommandInput{{Name: "ls"}, {Name: "cat"}},
476 },
477 },
478 "roleMappings": []*model.UpdateOperatorInterventionRoleMappingInput{
479 {
480 Role: "EDGE_ORG_ADMIN",
481 Privileges: []*model.OperatorInterventionPrivilegeInput{{Name: "ea-read"}, {Name: "ea-write"}},
482 },
483 },
484
485
486 "skipCommands": graphqlTypes.Boolean(false),
487 "skipPrivileges": graphqlTypes.Boolean(false),
488 "skipRules": graphqlTypes.Boolean(false),
489 "skipRoleMappings": graphqlTypes.Boolean(false),
490 },
491 },
492 "Duplicate Rules": {
493
494
495
496 conf: config{
497 Rules: map[string][]string{
498 "ea-admin": {"ls", "ls"},
499 },
500 RoleMappings: nil,
501 },
502 expVariables: map[string]interface{}{
503
504
505
506 "roleMappings": []*model.UpdateOperatorInterventionRoleMappingInput{},
507
508
509 "privileges": []model.OperatorInterventionPrivilegeInput{
510 {Name: "ea-admin"},
511 },
512 "commands": []model.OperatorInterventionCommandInput{
513
514 {Name: "ls"},
515 },
516
517 "rules": []model.UpdateOperatorInterventionRuleInput{
518 {
519 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "ea-admin"},
520
521 Commands: []*model.OperatorInterventionCommandInput{{Name: "ls"}, {Name: "ls"}},
522 },
523 },
524
525
526 "skipRoleMappings": graphqlTypes.Boolean(true),
527
528 "skipCommands": graphqlTypes.Boolean(false),
529 "skipPrivileges": graphqlTypes.Boolean(false),
530 "skipRules": graphqlTypes.Boolean(false),
531 },
532 },
533 "No privileges in role mapping": {
534 conf: config{
535 RoleMappings: map[string][]string{
536 "EDGE_ORG_ADMIN": {},
537 },
538 },
539 expVariables: map[string]interface{}{
540 "commands": []model.OperatorInterventionCommandInput{},
541 "rules": []model.UpdateOperatorInterventionRuleInput{},
542
543 "privileges": []model.OperatorInterventionPrivilegeInput{},
544 "roleMappings": []*model.UpdateOperatorInterventionRoleMappingInput{
545 {
546 Role: "EDGE_ORG_ADMIN",
547 Privileges: []*model.OperatorInterventionPrivilegeInput{},
548 },
549 },
550
551 "skipCommands": graphqlTypes.Boolean(true),
552 "skipRules": graphqlTypes.Boolean(true),
553 "skipPrivileges": graphqlTypes.Boolean(true),
554
555 "skipRoleMappings": graphqlTypes.Boolean(false),
556 },
557 },
558 "No commands in rule": {
559 conf: config{
560 Rules: map[string][]string{
561 "ea-admin": {},
562 },
563 },
564 expVariables: map[string]interface{}{
565 "roleMappings": []*model.UpdateOperatorInterventionRoleMappingInput{},
566
567 "commands": []model.OperatorInterventionCommandInput{},
568
569 "privileges": []model.OperatorInterventionPrivilegeInput{
570 {Name: "ea-admin"},
571 },
572 "rules": []model.UpdateOperatorInterventionRuleInput{
573 {
574 Privilege: &model.OperatorInterventionPrivilegeInput{Name: "ea-admin"},
575 Commands: []*model.OperatorInterventionCommandInput{},
576 },
577 },
578
579 "skipRoleMappings": graphqlTypes.Boolean(true),
580 "skipCommands": graphqlTypes.Boolean(true),
581
582 "skipRules": graphqlTypes.Boolean(false),
583 "skipPrivileges": graphqlTypes.Boolean(false),
584 },
585 },
586 }
587
588 for name, tc := range tests {
589 tc := tc
590 t.Run(name, func(t *testing.T) {
591 t.Parallel()
592
593 vars := createVariables(tc.conf)
594
595
596 slices.SortFunc(vars["rules"].([]model.UpdateOperatorInterventionRuleInput), func(a, b model.UpdateOperatorInterventionRuleInput) int {
597 return cmp.Compare(a.Privilege.Name, b.Privilege.Name)
598 })
599
600 require.Equal(t, tc.expVariables, vars)
601 })
602 }
603 }
604
605 func TestMissingFlagFile(t *testing.T) {
606 testConfig := edgecli.Config{}
607 cmd := NewCmd(&testConfig)
608
609 require.ErrorContains(t, cmd.Command().Exec(context.Background(), []string{}), "Flag 'file' is required")
610
611 require.NoError(t, flagutil.SetFlag(cmd.Rags, flagutil.LoadData, "test-cluster-0"))
612 }
613
614 func TestLoadData(t *testing.T) {
615 t.Parallel()
616
617 server := utils.NewMockHTTPTestServer().AddAllowedContentType("application/json").DefaultNotFound()
618 t.Cleanup(server.Server.Close)
619
620 tests := map[string]struct {
621 data map[string]interface{}
622
623 expError require.ErrorAssertionFunc
624 }{
625 "Error Response": {
626 data: map[string]interface{}{
627 "updateOperatorInterventionRoleMappings": model.UpdateOperatorInterventionRoleMappingResponse{
628 Errors: []*model.OperatorInterventionErrorResponse{
629 {Type: model.OperatorInterventionErrorTypeUnknownRole},
630 },
631 },
632 "createOperatorInterventionPrivileges": model.CreateOperatorInterventionPrivilegeResponse{
633 Errors: []*model.OperatorInterventionErrorResponse{
634 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
635 },
636 },
637 },
638 expError: ErrorEqualMsg("error during mutation"),
639 },
640 "No Error Response": {
641 data: map[string]interface{}{
642 "updateOperatorInterventionRoleMappings": model.UpdateOperatorInterventionRoleMappingResponse{},
643 "createOperatorInterventionPrivileges": model.CreateOperatorInterventionPrivilegeResponse{},
644 },
645 expError: require.NoError,
646 },
647 }
648
649 for name, tc := range tests {
650 name := name
651 tc := tc
652 t.Run(name, func(t *testing.T) {
653 t.Parallel()
654
655
656 dir := t.TempDir()
657 filePath := filepath.Join(dir, "config.json")
658 require.NoError(t, os.WriteFile(
659 filePath,
660 []byte(defaultConfig),
661 0644,
662 ))
663
664 server.Any(name, apiRequestCallback(tc.data), func(_ http.ResponseWriter, r *http.Request) bool {
665 return strings.HasPrefix(r.URL.String(), "/"+url.PathEscape(name))
666 })
667
668
669
670
671
672 future := time.Now().Add(time.Hour * 24)
673 testConfig := edgecli.Config{
674 CurrentBannerContext: "fakeBanner",
675 BannerContexts: map[string]*edgecli.BannerContext{
676 "fakeBanner": {
677 TokenTime: future.Format(time.RFC3339),
678 Token: "fakeToken",
679 Endpoint: server.Server.URL + "/" + url.PathEscape(name),
680 },
681 },
682 }
683
684 cmd := NewCmd(&testConfig)
685 cmd.Command()
686
687 require.NoError(t, flagutil.SetFlag(cmd.Rags, flagutil.LoadData, filePath))
688
689
690 err := cmd.Command().Exec(context.Background(), []string{})
691 tc.expError(t, err)
692 })
693 }
694 }
695
696 func apiRequestCallback(data interface{}) func(w http.ResponseWriter, r *http.Request) {
697 return func(w http.ResponseWriter, r *http.Request) {
698 body, err := io.ReadAll(r.Body)
699 if err != nil {
700 utils.WriteBadResponse(w, nil)
701 return
702 }
703
704 mutationCorrect := assertMutationOrder(body)
705 if !mutationCorrect {
706 utils.WriteBadResponse(w, nil)
707 return
708 }
709
710 data, err := wrapAsGraphqlResponse(data)
711 if err != nil {
712 utils.WriteBadResponse(w, nil)
713 return
714 }
715 utils.WriteOkResponse(w, data)
716 }
717 }
718
719
720
721
722
723 func assertMutationOrder(body []byte) bool {
724 return all(
725 assertOnce(string(body), "createOperatorInterventionCommands"),
726 assertOnce(string(body), "createOperatorInterventionPrivileges"),
727 assertOnce(string(body), "updateOperatorInterventionRules"),
728 assertOnce(string(body), "updateOperatorInterventionRoleMappings"),
729
730 assertInOrder(string(body), "createOperatorInterventionPrivileges", "updateOperatorInterventionRoleMappings"),
731 assertInOrder(string(body), "createOperatorInterventionPrivileges", "updateOperatorInterventionRules"),
732 assertInOrder(string(body), "createOperatorInterventionCommands", "updateOperatorInterventionRules"),
733 )
734 }
735
736
737 func all(vals ...bool) bool {
738 for _, val := range vals {
739 if !val {
740 return false
741 }
742 }
743 return true
744 }
745
746
747 func assertOnce(body string, value string) bool {
748 return strings.Count(body, value) == 1
749 }
750
751
752 func assertInOrder(data string, first string, second string) bool {
753 firstIdx := strings.Index(data, first)
754 if firstIdx == -1 {
755 return false
756 }
757 secondIdx := strings.Index(data, second)
758 if secondIdx == -1 {
759 return false
760 }
761
762 return second > first
763 }
764
765 func wrapAsGraphqlResponse(v interface{}) ([]byte, error) {
766 res, err := json.Marshal(v)
767 if err != nil {
768 return nil, err
769 }
770 resp := graphql.Response{Data: res}
771 return json.Marshal(resp)
772 }
773
774 func TestGenerateAllOutput(t *testing.T) {
775 t.Parallel()
776
777 var invalidCommand = "invalidCommand"
778 var invalidRole = "invalidRole"
779 var invalidPriv = "invalidPriv"
780
781 tests := map[string]struct {
782 variables map[string]interface{}
783 mutation oiLoadDataMutation
784
785 exp string
786 errorAssertion require.ErrorAssertionFunc
787 }{
788 "No Mutations, No Errors": {
789 variables: map[string]interface{}{
790 "skipCommands": graphqlTypes.Boolean(true),
791 "skipPrivileges": graphqlTypes.Boolean(true),
792 "skipRules": graphqlTypes.Boolean(true),
793 "skipRoleMappings": graphqlTypes.Boolean(true),
794 },
795 mutation: oiLoadDataMutation{
796 CreateOperatorInterventionCommands: struct {
797 model.CreateOperatorInterventionCommandResponse
798 }{
799 CreateOperatorInterventionCommandResponse: model.CreateOperatorInterventionCommandResponse{
800 Errors: nil,
801 },
802 },
803 CreateOperatorInterventionPrivileges: struct {
804 model.CreateOperatorInterventionPrivilegeResponse
805 }{
806 CreateOperatorInterventionPrivilegeResponse: model.CreateOperatorInterventionPrivilegeResponse{
807 Errors: nil,
808 },
809 },
810 UpdateOperatorInterventionRules: struct {
811 model.UpdateOperatorInterventionRuleResponse
812 }{
813 UpdateOperatorInterventionRuleResponse: model.UpdateOperatorInterventionRuleResponse{
814 Errors: nil,
815 },
816 },
817 UpdateOperatorInterventionRoleMappings: struct {
818 model.UpdateOperatorInterventionRoleMappingResponse
819 }{
820 UpdateOperatorInterventionRoleMappingResponse: model.UpdateOperatorInterventionRoleMappingResponse{
821 Errors: nil,
822 },
823 },
824 },
825 exp: "",
826 errorAssertion: require.NoError,
827 },
828 "No Mutations, All Errors": {
829 variables: map[string]interface{}{
830 "skipCommands": graphqlTypes.Boolean(true),
831 "skipPrivileges": graphqlTypes.Boolean(true),
832 "skipRules": graphqlTypes.Boolean(true),
833 "skipRoleMappings": graphqlTypes.Boolean(true),
834 },
835 mutation: oiLoadDataMutation{
836 CreateOperatorInterventionCommands: struct {
837 model.CreateOperatorInterventionCommandResponse
838 }{
839 CreateOperatorInterventionCommandResponse: model.CreateOperatorInterventionCommandResponse{
840 Errors: []*model.OperatorInterventionErrorResponse{
841 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
842 },
843 },
844 },
845 CreateOperatorInterventionPrivileges: struct {
846 model.CreateOperatorInterventionPrivilegeResponse
847 }{
848 CreateOperatorInterventionPrivilegeResponse: model.CreateOperatorInterventionPrivilegeResponse{
849 Errors: []*model.OperatorInterventionErrorResponse{
850 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
851 },
852 },
853 },
854 UpdateOperatorInterventionRules: struct {
855 model.UpdateOperatorInterventionRuleResponse
856 }{
857 UpdateOperatorInterventionRuleResponse: model.UpdateOperatorInterventionRuleResponse{
858 Errors: []*model.OperatorInterventionErrorResponse{
859 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
860 },
861 },
862 },
863 UpdateOperatorInterventionRoleMappings: struct {
864 model.UpdateOperatorInterventionRoleMappingResponse
865 }{
866 UpdateOperatorInterventionRoleMappingResponse: model.UpdateOperatorInterventionRoleMappingResponse{
867 Errors: []*model.OperatorInterventionErrorResponse{
868 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
869 },
870 },
871 },
872 },
873 exp: "",
874 errorAssertion: require.NoError,
875 },
876 "All Mutations, No Errors": {
877 variables: map[string]interface{}{
878 "skipCommands": graphqlTypes.Boolean(false),
879 "skipPrivileges": graphqlTypes.Boolean(false),
880 "skipRules": graphqlTypes.Boolean(false),
881 "skipRoleMappings": graphqlTypes.Boolean(false),
882 },
883 mutation: oiLoadDataMutation{
884 CreateOperatorInterventionCommands: struct {
885 model.CreateOperatorInterventionCommandResponse
886 }{
887 CreateOperatorInterventionCommandResponse: model.CreateOperatorInterventionCommandResponse{
888 Errors: nil,
889 },
890 },
891 CreateOperatorInterventionPrivileges: struct {
892 model.CreateOperatorInterventionPrivilegeResponse
893 }{
894 CreateOperatorInterventionPrivilegeResponse: model.CreateOperatorInterventionPrivilegeResponse{
895 Errors: nil,
896 },
897 },
898 UpdateOperatorInterventionRules: struct {
899 model.UpdateOperatorInterventionRuleResponse
900 }{
901 UpdateOperatorInterventionRuleResponse: model.UpdateOperatorInterventionRuleResponse{
902 Errors: nil,
903 },
904 },
905 UpdateOperatorInterventionRoleMappings: struct {
906 model.UpdateOperatorInterventionRoleMappingResponse
907 }{
908 UpdateOperatorInterventionRoleMappingResponse: model.UpdateOperatorInterventionRoleMappingResponse{
909 Errors: nil,
910 },
911 },
912 },
913 exp: "\nOI Commands applied\n\n\nOI Privileges applied\n\n\nOI Rules applied\n\n\nOI Role Mappings applied\n",
914 errorAssertion: require.NoError,
915 },
916 "All Mutations, All Errors": {
917 variables: map[string]interface{}{
918 "skipCommands": graphqlTypes.Boolean(false),
919 "skipPrivileges": graphqlTypes.Boolean(false),
920 "skipRules": graphqlTypes.Boolean(false),
921 "skipRoleMappings": graphqlTypes.Boolean(false),
922 },
923 mutation: oiLoadDataMutation{
924 CreateOperatorInterventionCommands: struct {
925 model.CreateOperatorInterventionCommandResponse
926 }{
927 CreateOperatorInterventionCommandResponse: model.CreateOperatorInterventionCommandResponse{
928 Errors: []*model.OperatorInterventionErrorResponse{
929 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
930 },
931 },
932 },
933 CreateOperatorInterventionPrivileges: struct {
934 model.CreateOperatorInterventionPrivilegeResponse
935 }{
936 CreateOperatorInterventionPrivilegeResponse: model.CreateOperatorInterventionPrivilegeResponse{
937 Errors: []*model.OperatorInterventionErrorResponse{
938 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
939 },
940 },
941 },
942 UpdateOperatorInterventionRules: struct {
943 model.UpdateOperatorInterventionRuleResponse
944 }{
945 UpdateOperatorInterventionRuleResponse: model.UpdateOperatorInterventionRuleResponse{
946 Errors: []*model.OperatorInterventionErrorResponse{
947 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege, Privilege: &invalidPriv},
948 },
949 },
950 },
951 UpdateOperatorInterventionRoleMappings: struct {
952 model.UpdateOperatorInterventionRoleMappingResponse
953 }{
954 UpdateOperatorInterventionRoleMappingResponse: model.UpdateOperatorInterventionRoleMappingResponse{
955 Errors: []*model.OperatorInterventionErrorResponse{
956 {Type: model.OperatorInterventionErrorTypeUnknownRole, Role: &invalidRole},
957 },
958 },
959 },
960 },
961 exp: "\nErrors occurred when applying OI Commands: \n\tError: UNKNOWN_PRIVILEGE\n\nOI Commands not applied.\n\n\nErrors occurred when applying OI Privileges: \n\tError: UNKNOWN_PRIVILEGE\n\nOI Privileges not applied.\n\n\nErrors occurred when applying OI Rules: \n\tError: UNKNOWN_PRIVILEGE. Details: Privilege: \"invalidPriv\"\n\nOI Rules not applied.\n\n\nErrors occurred when applying OI Role Mappings: \n\tError: UNKNOWN_ROLE. Details: Role: \"invalidRole\"\n\nOI Role Mappings not applied.\n",
962 errorAssertion: ErrorEqualMsg("error during mutation"),
963 },
964 "All Mutations, Some Errors": {
965 variables: map[string]interface{}{
966 "skipCommands": graphqlTypes.Boolean(false),
967 "skipPrivileges": graphqlTypes.Boolean(false),
968 "skipRules": graphqlTypes.Boolean(false),
969 "skipRoleMappings": graphqlTypes.Boolean(false),
970 },
971 mutation: oiLoadDataMutation{
972 CreateOperatorInterventionCommands: struct {
973 model.CreateOperatorInterventionCommandResponse
974 }{
975 CreateOperatorInterventionCommandResponse: model.CreateOperatorInterventionCommandResponse{
976 Errors: nil,
977 },
978 },
979 CreateOperatorInterventionPrivileges: struct {
980 model.CreateOperatorInterventionPrivilegeResponse
981 }{
982 CreateOperatorInterventionPrivilegeResponse: model.CreateOperatorInterventionPrivilegeResponse{
983 Errors: []*model.OperatorInterventionErrorResponse{
984 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
985 },
986 },
987 },
988 UpdateOperatorInterventionRules: struct {
989 model.UpdateOperatorInterventionRuleResponse
990 }{
991 UpdateOperatorInterventionRuleResponse: model.UpdateOperatorInterventionRuleResponse{
992 Errors: nil,
993 },
994 },
995 UpdateOperatorInterventionRoleMappings: struct {
996 model.UpdateOperatorInterventionRoleMappingResponse
997 }{
998 UpdateOperatorInterventionRoleMappingResponse: model.UpdateOperatorInterventionRoleMappingResponse{
999 Errors: []*model.OperatorInterventionErrorResponse{
1000 {Type: model.OperatorInterventionErrorTypeUnknownRole, Role: &invalidRole},
1001 },
1002 },
1003 },
1004 },
1005
1006 exp: "\nOI Commands applied\n\n\nErrors occurred when applying OI Privileges: \n\tError: UNKNOWN_PRIVILEGE\n\nOI Privileges not applied.\n\n\nOI Rules applied\n\n\nErrors occurred when applying OI Role Mappings: \n\tError: UNKNOWN_ROLE. Details: Role: \"invalidRole\"\n\nOI Role Mappings not applied.\n",
1007 errorAssertion: ErrorEqualMsg("error during mutation"),
1008 },
1009 "Some Mutations, No Errors": {
1010 variables: map[string]interface{}{
1011 "skipCommands": graphqlTypes.Boolean(false),
1012 "skipPrivileges": graphqlTypes.Boolean(true),
1013 "skipRules": graphqlTypes.Boolean(false),
1014 "skipRoleMappings": graphqlTypes.Boolean(true),
1015 },
1016 mutation: oiLoadDataMutation{
1017 CreateOperatorInterventionCommands: struct {
1018 model.CreateOperatorInterventionCommandResponse
1019 }{
1020 CreateOperatorInterventionCommandResponse: model.CreateOperatorInterventionCommandResponse{
1021 Errors: nil,
1022 },
1023 },
1024 CreateOperatorInterventionPrivileges: struct {
1025 model.CreateOperatorInterventionPrivilegeResponse
1026 }{
1027 CreateOperatorInterventionPrivilegeResponse: model.CreateOperatorInterventionPrivilegeResponse{
1028 Errors: nil,
1029 },
1030 },
1031 UpdateOperatorInterventionRules: struct {
1032 model.UpdateOperatorInterventionRuleResponse
1033 }{
1034 UpdateOperatorInterventionRuleResponse: model.UpdateOperatorInterventionRuleResponse{
1035 Errors: nil,
1036 },
1037 },
1038 UpdateOperatorInterventionRoleMappings: struct {
1039 model.UpdateOperatorInterventionRoleMappingResponse
1040 }{
1041 UpdateOperatorInterventionRoleMappingResponse: model.UpdateOperatorInterventionRoleMappingResponse{
1042 Errors: nil,
1043 },
1044 },
1045 },
1046
1047 exp: "\nOI Commands applied\n\n\nOI Rules applied\n",
1048 errorAssertion: require.NoError,
1049 },
1050 "Some Mutations, All Errors": {
1051 variables: map[string]interface{}{
1052 "skipCommands": graphqlTypes.Boolean(true),
1053 "skipPrivileges": graphqlTypes.Boolean(false),
1054 "skipRules": graphqlTypes.Boolean(false),
1055 "skipRoleMappings": graphqlTypes.Boolean(true),
1056 },
1057 mutation: oiLoadDataMutation{
1058 CreateOperatorInterventionCommands: struct {
1059 model.CreateOperatorInterventionCommandResponse
1060 }{
1061 CreateOperatorInterventionCommandResponse: model.CreateOperatorInterventionCommandResponse{
1062 Errors: []*model.OperatorInterventionErrorResponse{
1063 {Type: model.OperatorInterventionErrorTypeUnknownCommand},
1064 },
1065 },
1066 },
1067 CreateOperatorInterventionPrivileges: struct {
1068 model.CreateOperatorInterventionPrivilegeResponse
1069 }{
1070 CreateOperatorInterventionPrivilegeResponse: model.CreateOperatorInterventionPrivilegeResponse{
1071 Errors: []*model.OperatorInterventionErrorResponse{
1072 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
1073 },
1074 },
1075 },
1076 UpdateOperatorInterventionRules: struct {
1077 model.UpdateOperatorInterventionRuleResponse
1078 }{
1079 UpdateOperatorInterventionRuleResponse: model.UpdateOperatorInterventionRuleResponse{
1080 Errors: []*model.OperatorInterventionErrorResponse{
1081 {Type: model.OperatorInterventionErrorTypeUnknownRule, Privilege: &invalidPriv, Command: &invalidCommand},
1082 },
1083 },
1084 },
1085 UpdateOperatorInterventionRoleMappings: struct {
1086 model.UpdateOperatorInterventionRoleMappingResponse
1087 }{
1088 UpdateOperatorInterventionRoleMappingResponse: model.UpdateOperatorInterventionRoleMappingResponse{
1089 Errors: []*model.OperatorInterventionErrorResponse{
1090 {Type: model.OperatorInterventionErrorTypeUnknownRole, Role: &invalidRole},
1091 },
1092 },
1093 },
1094 },
1095
1096 exp: "\nErrors occurred when applying OI Privileges: \n\tError: UNKNOWN_PRIVILEGE\n\nOI Privileges not applied.\n\n\nErrors occurred when applying OI Rules: \n\tError: UNKNOWN_RULE. Details: Privilege: \"invalidPriv\", Command: \"invalidCommand\"\n\nOI Rules not applied.\n",
1097 errorAssertion: ErrorEqualMsg("error during mutation"),
1098 },
1099 "Some Mutations, Some Errors": {
1100 variables: map[string]interface{}{
1101 "skipCommands": graphqlTypes.Boolean(false),
1102 "skipPrivileges": graphqlTypes.Boolean(false),
1103 "skipRules": graphqlTypes.Boolean(true),
1104 "skipRoleMappings": graphqlTypes.Boolean(false),
1105 },
1106 mutation: oiLoadDataMutation{
1107 CreateOperatorInterventionCommands: struct {
1108 model.CreateOperatorInterventionCommandResponse
1109 }{
1110 CreateOperatorInterventionCommandResponse: model.CreateOperatorInterventionCommandResponse{
1111 Errors: []*model.OperatorInterventionErrorResponse{
1112 {Type: model.OperatorInterventionErrorTypeUnknownPrivilege},
1113 },
1114 },
1115 },
1116 CreateOperatorInterventionPrivileges: struct {
1117 model.CreateOperatorInterventionPrivilegeResponse
1118 }{
1119 CreateOperatorInterventionPrivilegeResponse: model.CreateOperatorInterventionPrivilegeResponse{
1120 Errors: nil,
1121 },
1122 },
1123 UpdateOperatorInterventionRules: struct {
1124 model.UpdateOperatorInterventionRuleResponse
1125 }{
1126 UpdateOperatorInterventionRuleResponse: model.UpdateOperatorInterventionRuleResponse{
1127 Errors: nil,
1128 },
1129 },
1130 UpdateOperatorInterventionRoleMappings: struct {
1131 model.UpdateOperatorInterventionRoleMappingResponse
1132 }{
1133 UpdateOperatorInterventionRoleMappingResponse: model.UpdateOperatorInterventionRoleMappingResponse{
1134 Errors: []*model.OperatorInterventionErrorResponse{
1135 {Type: model.OperatorInterventionErrorTypeUnknownRole, Role: &invalidRole},
1136 },
1137 },
1138 },
1139 },
1140
1141 exp: "\nErrors occurred when applying OI Commands: \n\tError: UNKNOWN_PRIVILEGE\n\nOI Commands not applied.\n\n\nOI Privileges applied\n\n\nErrors occurred when applying OI Role Mappings: \n\tError: UNKNOWN_ROLE. Details: Role: \"invalidRole\"\n\nOI Role Mappings not applied.\n",
1142 errorAssertion: ErrorEqualMsg("error during mutation"),
1143 },
1144 }
1145
1146 for name, tc := range tests {
1147 tc := tc
1148 t.Run(name, func(t *testing.T) {
1149 t.Parallel()
1150
1151 out, err := generateAllOutput(tc.variables, tc.mutation)
1152 tc.errorAssertion(t, err)
1153
1154 require.Equal(t, tc.exp, out)
1155 })
1156 }
1157 }
1158
View as plain text