From 4764bdc5a8cf974a4d172d5417736a3d2a86326a Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Thu, 12 Jun 2025 12:16:46 -0500 Subject: [PATCH 01/15] Setup e2e tests for domain --- Taskfile.yml | 6 +++ src/e2e/domain_test.go | 59 ++++++++++++++++++++++++++ src/e2e/helpers.go | 95 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 src/e2e/domain_test.go create mode 100644 src/e2e/helpers.go diff --git a/Taskfile.yml b/Taskfile.yml index 7c1ac434..7ae9fa48 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -56,6 +56,12 @@ tasks: cmds: - go test -race -coverprofile=coverage.txt -covermode=atomic -v ./cmd/... {{ .CLI_ARGS }} + test-e2e: + desc: Run Integration tests + dir: "{{.SRC_DIR}}" + cmds: + - go test -race -v ./e2e/... {{ .CLI_ARGS }} + update-opslevel-go: desc: Update opslevel-go version to latest release dir: "{{.SRC_DIR}}" diff --git a/src/e2e/domain_test.go b/src/e2e/domain_test.go new file mode 100644 index 00000000..58902201 --- /dev/null +++ b/src/e2e/domain_test.go @@ -0,0 +1,59 @@ +package e2e + +import ( + "strings" + "testing" +) + +func TestDomainHappyPath(t *testing.T) { + createInput := ` +name: "Integration Test Domain" +description: "Created by integration test" +` + updateInput1 := ` +name: "Integration Test Domain Updated" +description: "Updated by integration test" +` + updateInput2 := ` +name: "Integration Test Domain Updated Again" +description: null +` + domainName := "Integration Test Domain" + updatedDomainName := "Integration Test Domain Updated" + updatedAgainDomainName := "Integration Test Domain Updated Again" + + test := CLITest{ + Create: Create("create domain -f -", createInput), + Get: Get("get domain"), + Delete: Delete("delete domain"), + Steps: []Step{ + func(u *Utility) { + out, err := u.Run("list domain") + if err != nil || !strings.Contains(out, domainName) { + u.Fatalf("list failed: %v\nout: %s", err, out) + } + }, + func(u *Utility) { + out, err := u.Run("update domain "+u.ID+" -f -", updateInput1) + if err != nil { + u.Fatalf("update1 failed: %v\nout: %s", err, out) + } + out, err = u.Run("get domain " + u.ID) + if err != nil || !strings.Contains(out, updatedDomainName) || !strings.Contains(out, "Updated by integration test") { + u.Fatalf("get after update1 failed: %v\nout: %s", err, out) + } + }, + func(u *Utility) { + out, err := u.Run("update domain "+u.ID+" -f -", updateInput2) + if err != nil { + u.Fatalf("update2 (unset) failed: %v\nout: %s", err, out) + } + out, err = u.Run("get domain " + u.ID) + if err != nil || !strings.Contains(out, updatedAgainDomainName) || strings.Contains(out, "Updated by integration test") { + u.Fatalf("get after update2 failed (description should be unset): %v\nout: %s", err, out) + } + }, + }, + } + test.Run(t) +} diff --git a/src/e2e/helpers.go b/src/e2e/helpers.go new file mode 100644 index 00000000..b858b2e1 --- /dev/null +++ b/src/e2e/helpers.go @@ -0,0 +1,95 @@ +package e2e + +import ( + "bytes" + "os" + "os/exec" + "strings" + "testing" +) + +type Utility struct { + *testing.T + ID string // The resource ID created by Create +} + +// Run executes the CLI using 'go run main.go' from the ./src directory with the given arguments and optional stdin, returning combined output and error. +func (u *Utility) Run(args string, stdin ...string) (string, error) { + cmd := exec.Command("go", append([]string{"run", "main.go"}, strings.Split(args, " ")...)...) + cmd.Dir = ".." + cmd.Env = os.Environ() + var out bytes.Buffer + var errBuf bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &errBuf + if len(stdin) > 0 { + cmd.Stdin = strings.NewReader(stdin[0]) + } + err := cmd.Run() + return out.String() + errBuf.String(), err +} + +type Step func(*Utility) + +type CLITest struct { + Create Step + Get [2]Step + Delete Step + Steps []Step +} + +func (ct *CLITest) Run(t *testing.T) { + util := &Utility{T: t} + + defer func() { + if util.ID != "" { + ct.Delete(util) + } + }() + + ct.Create(util) + ct.Get[0](util) // Should exist after create + for _, step := range ct.Steps { + step(util) + } + ct.Delete(util) + ct.Get[1](util) // Should not exist after delete + util.ID = "" // Mark as deleted so defer doesn't try again +} + +func Create(cmd string, input string) Step { + return func(u *Utility) { + out, err := u.Run(cmd, input) + if err != nil { + u.Fatalf("create failed: %v\nout: %s", err, out) + } + u.ID = strings.TrimSpace(out) + if u.ID == "" { + u.Fatalf("expected ID, got: %q", out) + } + } +} + +func Get(cmd string) [2]Step { + return [2]Step{func(u *Utility) { + out, err := u.Run(cmd + " " + u.ID) + if err != nil { + u.Fatalf("get failed: %v\nout: %s", err, out) + } + }, func(u *Utility) { + out, err := u.Run(cmd + " " + u.ID) + lower := strings.ToLower(out) + if err == nil || !(strings.Contains(lower, "not found") || strings.Contains(lower, "missing") || strings.Contains(lower, "gone")) { + u.Fatalf("expected get after delete to fail with not found, got: %v\nout: %s", err, out) + } + }} +} + +func Delete(cmd string) Step { + return func(u *Utility) { + out, err := u.Run(cmd + " " + u.ID) + if err != nil { + u.Fatalf("delete failed: %v\nout: %s", err, out) + } + } +} From 4f853cb5c2372d1fdcfb7775043cd43a7f4f0751 Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Wed, 18 Jun 2025 09:11:42 -0500 Subject: [PATCH 02/15] PR feedback --- src/e2e/domain_test.go | 33 ++++++++++++++------------------- src/e2e/helpers.go | 30 +++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/e2e/domain_test.go b/src/e2e/domain_test.go index 58902201..673dc7e5 100644 --- a/src/e2e/domain_test.go +++ b/src/e2e/domain_test.go @@ -6,50 +6,45 @@ import ( ) func TestDomainHappyPath(t *testing.T) { - createInput := ` + test := CLITest{ + Create: Create("create domain -f -", ` name: "Integration Test Domain" description: "Created by integration test" -` - updateInput1 := ` -name: "Integration Test Domain Updated" -description: "Updated by integration test" -` - updateInput2 := ` -name: "Integration Test Domain Updated Again" -description: null -` - domainName := "Integration Test Domain" - updatedDomainName := "Integration Test Domain Updated" - updatedAgainDomainName := "Integration Test Domain Updated Again" - - test := CLITest{ - Create: Create("create domain -f -", createInput), +`), Get: Get("get domain"), Delete: Delete("delete domain"), Steps: []Step{ func(u *Utility) { out, err := u.Run("list domain") - if err != nil || !strings.Contains(out, domainName) { + if err != nil || !strings.Contains(out, "Integration Test Domain") { u.Fatalf("list failed: %v\nout: %s", err, out) } }, func(u *Utility) { + updateInput1 := ` +name: "Integration Test Domain Updated" +description: "Updated by integration test" +` out, err := u.Run("update domain "+u.ID+" -f -", updateInput1) if err != nil { u.Fatalf("update1 failed: %v\nout: %s", err, out) } out, err = u.Run("get domain " + u.ID) - if err != nil || !strings.Contains(out, updatedDomainName) || !strings.Contains(out, "Updated by integration test") { + if err != nil || !strings.Contains(out, "Integration Test Domain Updated") || !strings.Contains(out, "Updated by integration test") { u.Fatalf("get after update1 failed: %v\nout: %s", err, out) } }, func(u *Utility) { + updateInput2 := ` +name: "Integration Test Domain Updated Again" +description: null +` out, err := u.Run("update domain "+u.ID+" -f -", updateInput2) if err != nil { u.Fatalf("update2 (unset) failed: %v\nout: %s", err, out) } out, err = u.Run("get domain " + u.ID) - if err != nil || !strings.Contains(out, updatedAgainDomainName) || strings.Contains(out, "Updated by integration test") { + if err != nil || !strings.Contains(out, "Integration Test Domain Updated Again") || strings.Contains(out, "Updated by integration test") { u.Fatalf("get after update2 failed (description should be unset): %v\nout: %s", err, out) } }, diff --git a/src/e2e/helpers.go b/src/e2e/helpers.go index b858b2e1..a867099e 100644 --- a/src/e2e/helpers.go +++ b/src/e2e/helpers.go @@ -4,6 +4,7 @@ import ( "bytes" "os" "os/exec" + "strconv" "strings" "testing" ) @@ -40,21 +41,32 @@ type CLITest struct { func (ct *CLITest) Run(t *testing.T) { util := &Utility{T: t} - defer func() { if util.ID != "" { ct.Delete(util) } }() - ct.Create(util) - ct.Get[0](util) // Should exist after create - for _, step := range ct.Steps { - step(util) + t.Run("Create", func(t *testing.T) { + util.T = t + ct.Create(util) + }) + t.Run("Get", func(t *testing.T) { + util.T = t + ct.Get[0](util) // Should exist after create + }) + for i, step := range ct.Steps { + t.Run("Step "+strconv.Itoa(i), func(t *testing.T) { + util.T = t + step(util) + }) } - ct.Delete(util) - ct.Get[1](util) // Should not exist after delete - util.ID = "" // Mark as deleted so defer doesn't try again + t.Run("Delete", func(t *testing.T) { + util.T = t + ct.Delete(util) + ct.Get[1](util) // Should not exist after delete + util.ID = "" // Mark as deleted so defer doesn't try again + }) } func Create(cmd string, input string) Step { @@ -79,7 +91,7 @@ func Get(cmd string) [2]Step { }, func(u *Utility) { out, err := u.Run(cmd + " " + u.ID) lower := strings.ToLower(out) - if err == nil || !(strings.Contains(lower, "not found") || strings.Contains(lower, "missing") || strings.Contains(lower, "gone")) { + if err == nil || !(strings.Contains(lower, "not found") || strings.Contains(lower, "missing") || strings.Contains(lower, "does not exist on this account")) { u.Fatalf("expected get after delete to fail with not found, got: %v\nout: %s", err, out) } }} From f933a9123da2de0e197d93ee3556a02c8499892b Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Wed, 18 Jun 2025 09:48:48 -0500 Subject: [PATCH 03/15] Checkpoint --- src/e2e/domain_test.go | 58 ++++++++-------- src/e2e/helpers.go | 152 ++++++++++++++++++++++++----------------- 2 files changed, 117 insertions(+), 93 deletions(-) diff --git a/src/e2e/domain_test.go b/src/e2e/domain_test.go index 673dc7e5..c82dd351 100644 --- a/src/e2e/domain_test.go +++ b/src/e2e/domain_test.go @@ -6,49 +6,45 @@ import ( ) func TestDomainHappyPath(t *testing.T) { - test := CLITest{ - Create: Create("create domain -f -", ` + tc := TestCase{ + Steps: []Step{ + Create("create domain -f -", ` name: "Integration Test Domain" description: "Created by integration test" `), - Get: Get("get domain"), - Delete: Delete("delete domain"), - Steps: []Step{ - func(u *Utility) { - out, err := u.Run("list domain") - if err != nil || !strings.Contains(out, "Integration Test Domain") { - u.Fatalf("list failed: %v\nout: %s", err, out) + List("list domain", func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test Domain") { + u.Fatalf("list missing domain: %s", out) } - }, - func(u *Utility) { - updateInput1 := ` + }), + Update("update domain", ` name: "Integration Test Domain Updated" description: "Updated by integration test" -` - out, err := u.Run("update domain "+u.ID+" -f -", updateInput1) - if err != nil { - u.Fatalf("update1 failed: %v\nout: %s", err, out) +`, func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test Domain Updated") || !strings.Contains(out, "Updated by integration test") { + u.Fatalf("get after update1 failed\nout: %s", out) } - out, err = u.Run("get domain " + u.ID) - if err != nil || !strings.Contains(out, "Integration Test Domain Updated") || !strings.Contains(out, "Updated by integration test") { - u.Fatalf("get after update1 failed: %v\nout: %s", err, out) + }), + Get("get domain", func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test Domain Updated") || !strings.Contains(out, "Updated by integration test") { + u.Fatalf("get after update1 failed: %s", out) } - }, - func(u *Utility) { - updateInput2 := ` + }), + Update("update domain", ` name: "Integration Test Domain Updated Again" description: null -` - out, err := u.Run("update domain "+u.ID+" -f -", updateInput2) - if err != nil { - u.Fatalf("update2 (unset) failed: %v\nout: %s", err, out) +`, func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test Domain Updated Again") || strings.Contains(out, "Updated by integration test") { + u.Fatalf("get after update2 failed (description should be unset)\nout: %s", out) } - out, err = u.Run("get domain " + u.ID) - if err != nil || !strings.Contains(out, "Integration Test Domain Updated Again") || strings.Contains(out, "Updated by integration test") { - u.Fatalf("get after update2 failed (description should be unset): %v\nout: %s", err, out) + }), + Get("get domain", func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test Domain Updated Again") || strings.Contains(out, "Updated by integration test") { + u.Fatalf("get after update2 failed (description should be unset): %s", out) } - }, + }), + Delete("delete domain"), }, } - test.Run(t) + tc.Run(t) } diff --git a/src/e2e/helpers.go b/src/e2e/helpers.go index a867099e..31193b93 100644 --- a/src/e2e/helpers.go +++ b/src/e2e/helpers.go @@ -4,14 +4,23 @@ import ( "bytes" "os" "os/exec" - "strconv" "strings" "testing" ) type Utility struct { *testing.T - ID string // The resource ID created by Create + ID string // The resource ID created by a step, if needed +} + +type Step struct { + Name string + Run func(*Utility) + Deferred bool // If true, run only at the end as cleanup +} + +type TestCase struct { + Steps []Step } // Run executes the CLI using 'go run main.go' from the ./src directory with the given arguments and optional stdin, returning combined output and error. @@ -30,78 +39,97 @@ func (u *Utility) Run(args string, stdin ...string) (string, error) { return out.String() + errBuf.String(), err } -type Step func(*Utility) - -type CLITest struct { - Create Step - Get [2]Step - Delete Step - Steps []Step -} - -func (ct *CLITest) Run(t *testing.T) { +func (tc *TestCase) Run(t *testing.T) { util := &Utility{T: t} - defer func() { - if util.ID != "" { - ct.Delete(util) + // Run non-deferred steps + for _, step := range tc.Steps { + if step.Deferred { + continue } - }() - - t.Run("Create", func(t *testing.T) { - util.T = t - ct.Create(util) - }) - t.Run("Get", func(t *testing.T) { - util.T = t - ct.Get[0](util) // Should exist after create - }) - for i, step := range ct.Steps { - t.Run("Step "+strconv.Itoa(i), func(t *testing.T) { + t.Run(step.Name, func(t *testing.T) { + util.T = t + step.Run(util) + }) + } + // Run deferred steps + for _, step := range tc.Steps { + if !step.Deferred { + continue + } + t.Run(step.Name, func(t *testing.T) { util.T = t - step(util) + step.Run(util) }) } - t.Run("Delete", func(t *testing.T) { - util.T = t - ct.Delete(util) - ct.Get[1](util) // Should not exist after delete - util.ID = "" // Mark as deleted so defer doesn't try again - }) } func Create(cmd string, input string) Step { - return func(u *Utility) { - out, err := u.Run(cmd, input) - if err != nil { - u.Fatalf("create failed: %v\nout: %s", err, out) - } - u.ID = strings.TrimSpace(out) - if u.ID == "" { - u.Fatalf("expected ID, got: %q", out) - } + return Step{ + Name: "Create", + Run: func(u *Utility) { + out, err := u.Run(cmd, input) + if err != nil { + u.Fatalf("create failed: %v\nout: %s", err, out) + } + u.ID = strings.TrimSpace(out) + if u.ID == "" { + u.Fatalf("expected ID, got: %q", out) + } + }, } } -func Get(cmd string) [2]Step { - return [2]Step{func(u *Utility) { - out, err := u.Run(cmd + " " + u.ID) - if err != nil { - u.Fatalf("get failed: %v\nout: %s", err, out) - } - }, func(u *Utility) { - out, err := u.Run(cmd + " " + u.ID) - lower := strings.ToLower(out) - if err == nil || !(strings.Contains(lower, "not found") || strings.Contains(lower, "missing") || strings.Contains(lower, "does not exist on this account")) { - u.Fatalf("expected get after delete to fail with not found, got: %v\nout: %s", err, out) - } - }} +func Delete(cmd string) Step { + return Step{ + Name: "Delete", + Deferred: true, + Run: func(u *Utility) { + out, err := u.Run(cmd + " " + u.ID) + if err != nil { + u.Fatalf("delete failed: %v\nout: %s", err, out) + } + }, + } } -func Delete(cmd string) Step { - return func(u *Utility) { - out, err := u.Run(cmd + " " + u.ID) - if err != nil { - u.Fatalf("delete failed: %v\nout: %s", err, out) - } +// Get returns a Step that runs the get command and validates the output using the provided function. +func Get(cmd string, validate func(u *Utility, stdout string)) Step { + return Step{ + Name: "Get", + Run: func(u *Utility) { + out, err := u.Run(cmd + " " + u.ID) + if err != nil { + u.Fatalf("get failed: %v\nout: %s", err, out) + } + validate(u, out) + }, + } +} + +// List returns a Step that runs the list command and validates the output using the provided function. +func List(cmd string, validate func(u *Utility, stdout string)) Step { + return Step{ + Name: "List", + Run: func(u *Utility) { + out, err := u.Run(cmd) + if err != nil { + u.Fatalf("list failed: %v\nout: %s", err, out) + } + validate(u, out) + }, + } +} + +// Update returns a Step that runs the update command with input and validates the output using the provided function. +func Update(cmd string, input string, validate func(u *Utility, stdout string)) Step { + return Step{ + Name: "Update", + Run: func(u *Utility) { + out, err := u.Run(cmd+" "+u.ID+" -f -", input) + if err != nil { + u.Fatalf("update failed: %v\nout: %s", err, out) + } + validate(u, out) + }, } } From 2fe7e0bb894f5aef25bb8307a8e4e654e67eeb20 Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Wed, 18 Jun 2025 12:11:32 -0500 Subject: [PATCH 04/15] Expand test coverage --- Taskfile.yml | 2 +- src/cmd/service.go | 8 ++ src/cmd/team.go | 6 +- src/e2e/domain_test.go | 90 +++++++++------ src/e2e/helpers.go | 201 ++++++++++++++++++++------------- src/e2e/infrastructure_test.go | 68 +++++++++++ src/e2e/service_test.go | 74 ++++++++++++ src/e2e/team_test.go | 74 ++++++++++++ 8 files changed, 405 insertions(+), 118 deletions(-) create mode 100644 src/e2e/infrastructure_test.go create mode 100644 src/e2e/service_test.go create mode 100644 src/e2e/team_test.go diff --git a/Taskfile.yml b/Taskfile.yml index 7ae9fa48..302f68a3 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -60,7 +60,7 @@ tasks: desc: Run Integration tests dir: "{{.SRC_DIR}}" cmds: - - go test -race -v ./e2e/... {{ .CLI_ARGS }} + - go test -v ./e2e/... {{ .CLI_ARGS }} update-opslevel-go: desc: Update opslevel-go version to latest release diff --git a/src/cmd/service.go b/src/cmd/service.go index d9e9f61b..bbee6c69 100644 --- a/src/cmd/service.go +++ b/src/cmd/service.go @@ -158,6 +158,14 @@ type: EOF`, Run: func(cmd *cobra.Command, args []string) { input, err := readResourceInput[opslevel.ServiceUpdateInput]() + if len(args) == 1 { + key := args[0] + if opslevel.IsID(key) { + input.Id = opslevel.RefOf(opslevel.ID(key)) + } else { + input.Alias = opslevel.RefOf(key) + } + } cobra.CheckErr(err) service, err := getClientGQL().UpdateService(*input) cobra.CheckErr(err) diff --git a/src/cmd/team.go b/src/cmd/team.go index f702e92a..fc53ecfb 100644 --- a/src/cmd/team.go +++ b/src/cmd/team.go @@ -31,12 +31,12 @@ parentTeam: alias: "parent-team" responsibilities: "all the things" EOF`, - Args: cobra.ExactArgs(1), ArgAliases: []string{"NAME"}, Run: func(cmd *cobra.Command, args []string) { - key := args[0] input, err := readResourceInput[opslevel.TeamCreateInput]() - input.Name = key + if len(args) == 1 { + input.Name = args[0] + } cobra.CheckErr(err) team, err := getClientGQL().CreateTeam(*input) cobra.CheckErr(err) diff --git a/src/e2e/domain_test.go b/src/e2e/domain_test.go index c82dd351..3f46e7cf 100644 --- a/src/e2e/domain_test.go +++ b/src/e2e/domain_test.go @@ -6,44 +6,68 @@ import ( ) func TestDomainHappyPath(t *testing.T) { - tc := TestCase{ + tc := CLITest{ Steps: []Step{ - Create("create domain -f -", ` + Create{ + Cmd: "create domain", + Input: ` name: "Integration Test Domain" description: "Created by integration test" -`), - List("list domain", func(u *Utility, out string) { - if !strings.Contains(out, "Integration Test Domain") { - u.Fatalf("list missing domain: %s", out) - } - }), - Update("update domain", ` +`, + }, + Get{ + Cmd: "get domain", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test Domain") { + u.Fatalf("get after create failed: %s", out) + } + }, + }, + List{ + Cmd: "list domain", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test Domain") { + u.Fatalf("list missing domain: %s", out) + } + }, + }, + Update{ + Cmd: "update domain", + Input: ` name: "Integration Test Domain Updated" description: "Updated by integration test" -`, func(u *Utility, out string) { - if !strings.Contains(out, "Integration Test Domain Updated") || !strings.Contains(out, "Updated by integration test") { - u.Fatalf("get after update1 failed\nout: %s", out) - } - }), - Get("get domain", func(u *Utility, out string) { - if !strings.Contains(out, "Integration Test Domain Updated") || !strings.Contains(out, "Updated by integration test") { - u.Fatalf("get after update1 failed: %s", out) - } - }), - Update("update domain", ` -name: "Integration Test Domain Updated Again" -description: null -`, func(u *Utility, out string) { - if !strings.Contains(out, "Integration Test Domain Updated Again") || strings.Contains(out, "Updated by integration test") { - u.Fatalf("get after update2 failed (description should be unset)\nout: %s", out) - } - }), - Get("get domain", func(u *Utility, out string) { - if !strings.Contains(out, "Integration Test Domain Updated Again") || strings.Contains(out, "Updated by integration test") { - u.Fatalf("get after update2 failed (description should be unset): %s", out) - } - }), - Delete("delete domain"), +`, + }, + Get{ + Cmd: "get domain", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test Domain Updated") || !strings.Contains(out, "Updated by integration test") { + u.Fatalf("update1 failed\nout: %s", out) + } + }, + }, + // TODO: description cannot be unset yest + // Update{ + // Cmd: "update domain", + // Input: ` + //name: "Integration Test Domain Updated Again" + //description: null + //`, + // }, + // Get{ + // Cmd: "get domain", + // Validate: func(u *Utility, out string) { + // if !strings.Contains(out, "Integration Test Domain Updated Again") || strings.Contains(out, "Updated by integration test") { + // u.Fatalf("update2 failed (description should be unset)\nout: %s", out) + // } + // }, + // }, + Delete{ + Cmd: "delete domain", + }, + Missing{ + Cmd: "get domain", + }, }, } tc.Run(t) diff --git a/src/e2e/helpers.go b/src/e2e/helpers.go index 31193b93..0a131dd5 100644 --- a/src/e2e/helpers.go +++ b/src/e2e/helpers.go @@ -4,6 +4,7 @@ import ( "bytes" "os" "os/exec" + "strconv" "strings" "testing" ) @@ -13,18 +14,46 @@ type Utility struct { ID string // The resource ID created by a step, if needed } -type Step struct { - Name string - Run func(*Utility) - Deferred bool // If true, run only at the end as cleanup +type Step interface { + Run(u *Utility) + Name() string + Deferred() bool } -type TestCase struct { +// CLITest uses []Step interface now +type CLITest struct { Steps []Step } +func (tc *CLITest) Run(t *testing.T) { + util := &Utility{T: t} + // Run non-deferred steps + for i, step := range tc.Steps { + if step.Deferred() { + continue + } + t.Run(step.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + util.T = t + step.Run(util) + }) + } + // Run deferred steps + for i, step := range tc.Steps { + if !step.Deferred() { + continue + } + t.Run(step.Name()+"_"+strconv.Itoa(i), func(t *testing.T) { + util.T = t + step.Run(util) + }) + } +} + // Run executes the CLI using 'go run main.go' from the ./src directory with the given arguments and optional stdin, returning combined output and error. func (u *Utility) Run(args string, stdin ...string) (string, error) { + // TODO: need to allow using the pre-built binary + //cmd := exec.Command("opslevel", strings.Split(args, " ")...) + cmd := exec.Command("go", append([]string{"run", "main.go"}, strings.Split(args, " ")...)...) cmd.Dir = ".." cmd.Env = os.Environ() @@ -39,97 +68,107 @@ func (u *Utility) Run(args string, stdin ...string) (string, error) { return out.String() + errBuf.String(), err } -func (tc *TestCase) Run(t *testing.T) { - util := &Utility{T: t} - // Run non-deferred steps - for _, step := range tc.Steps { - if step.Deferred { - continue - } - t.Run(step.Name, func(t *testing.T) { - util.T = t - step.Run(util) - }) +// Create step +type Create struct { + Cmd string + Input string +} + +func (s Create) Run(u *Utility) { + out, err := u.Run(s.Cmd+" -f -", s.Input) + if err != nil { + panic("create failed: " + err.Error() + "\nout: " + out) } - // Run deferred steps - for _, step := range tc.Steps { - if !step.Deferred { - continue - } - t.Run(step.Name, func(t *testing.T) { - util.T = t - step.Run(util) - }) + u.ID = strings.TrimRight(strings.TrimLeft(strings.TrimSpace(out), "\""), "\"") + if u.ID == "" { + panic("expected ID, got: " + out) } } -func Create(cmd string, input string) Step { - return Step{ - Name: "Create", - Run: func(u *Utility) { - out, err := u.Run(cmd, input) - if err != nil { - u.Fatalf("create failed: %v\nout: %s", err, out) - } - u.ID = strings.TrimSpace(out) - if u.ID == "" { - u.Fatalf("expected ID, got: %q", out) - } - }, +func (s Create) Name() string { return "Create" } +func (s Create) Deferred() bool { return false } + +// Get step +type Get struct { + Cmd string + Validate func(u *Utility, out string) +} + +func (s Get) Run(u *Utility) { + out, err := u.Run(s.Cmd + " " + u.ID) + if err != nil { + u.Fatalf("get failed: %v\nout: %s", err, out) } + s.Validate(u, out) +} + +func (s Get) Name() string { return "Get" } +func (s Get) Deferred() bool { return false } + +// List step +type List struct { + Cmd string + Validate func(u *Utility, out string) } -func Delete(cmd string) Step { - return Step{ - Name: "Delete", - Deferred: true, - Run: func(u *Utility) { - out, err := u.Run(cmd + " " + u.ID) - if err != nil { - u.Fatalf("delete failed: %v\nout: %s", err, out) - } - }, +func (s List) Run(u *Utility) { + out, err := u.Run(s.Cmd) + if err != nil { + u.Fatalf("list failed: %v\nout: %s", err, out) } + if s.Validate != nil { + s.Validate(u, out) + } +} + +func (s List) Name() string { return "List" } +func (s List) Deferred() bool { return false } + +// Update step +type Update struct { + Cmd string + Input string + Validate func(u *Utility, out string) } -// Get returns a Step that runs the get command and validates the output using the provided function. -func Get(cmd string, validate func(u *Utility, stdout string)) Step { - return Step{ - Name: "Get", - Run: func(u *Utility) { - out, err := u.Run(cmd + " " + u.ID) - if err != nil { - u.Fatalf("get failed: %v\nout: %s", err, out) - } - validate(u, out) - }, +func (s Update) Run(u *Utility) { + out, err := u.Run(s.Cmd+" -f - "+u.ID, s.Input) + if err != nil { + u.Fatalf("update failed: %v\nout: %s", err, out) + } + if s.Validate != nil { + s.Validate(u, out) } } -// List returns a Step that runs the list command and validates the output using the provided function. -func List(cmd string, validate func(u *Utility, stdout string)) Step { - return Step{ - Name: "List", - Run: func(u *Utility) { - out, err := u.Run(cmd) - if err != nil { - u.Fatalf("list failed: %v\nout: %s", err, out) - } - validate(u, out) - }, +func (s Update) Name() string { return "Update" } +func (s Update) Deferred() bool { return false } + +type Delete struct { + Cmd string +} + +func (s Delete) Run(u *Utility) { + out, err := u.Run(s.Cmd + " " + u.ID) + if err != nil { + u.Fatalf("delete failed: %v\nout: %s", err, out) } } -// Update returns a Step that runs the update command with input and validates the output using the provided function. -func Update(cmd string, input string, validate func(u *Utility, stdout string)) Step { - return Step{ - Name: "Update", - Run: func(u *Utility) { - out, err := u.Run(cmd+" "+u.ID+" -f -", input) - if err != nil { - u.Fatalf("update failed: %v\nout: %s", err, out) - } - validate(u, out) - }, +func (s Delete) Name() string { return "Delete" } +func (s Delete) Deferred() bool { return true } + +type Missing struct { + Cmd string +} + +func (s Missing) Run(u *Utility) { + out, err := u.Run(s.Cmd + " " + u.ID) + lower := strings.ToLower(out) + if err == nil || !(strings.Contains(lower, "not found") || strings.Contains(lower, "missing") || strings.Contains(lower, "does not exist on this account")) { + u.Fatalf("expected get after delete to fail with not found, got: %v\nout: %s", err, out) } } + +func (s Missing) Name() string { return "Missing" } +func (s Missing) Deferred() bool { return true } diff --git a/src/e2e/infrastructure_test.go b/src/e2e/infrastructure_test.go new file mode 100644 index 00000000..95595cb3 --- /dev/null +++ b/src/e2e/infrastructure_test.go @@ -0,0 +1,68 @@ +package e2e + +import ( + "strings" + "testing" +) + +func TestInfrastructureHappyPath(t *testing.T) { + tc := CLITest{ + Steps: []Step{ + Create{ + Cmd: "create infra", + Input: ` +schema: "Database" +provider: + account: "Dev - 123456789" + name: "GCP" + type: "BigQuery" + url: "https://google.com" +data: + name: "my-big-query" + endpoint: "https://google.com" + engine: "BigQuery" + replica: false +`, + }, + Get{ + Cmd: "get infra", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "my-big-query") { + u.Fatalf("get after create failed: %s", out) + } + }, + }, + List{ + Cmd: "list infra", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "my-big-query") { + u.Fatalf("list missing infra: %s", out) + } + }, + }, + Update{ + Cmd: "update infra", + Input: ` +schema: "Database" +data: + name: "my-big-query-updated" +`, + }, + Get{ + Cmd: "get infra", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "my-big-query-updated") { + u.Fatalf("update1 failed\nout: %s", out) + } + }, + }, + Delete{ + Cmd: "delete infra", + }, + Missing{ + Cmd: "get infra", + }, + }, + } + tc.Run(t) +} diff --git a/src/e2e/service_test.go b/src/e2e/service_test.go new file mode 100644 index 00000000..4ad3ac5e --- /dev/null +++ b/src/e2e/service_test.go @@ -0,0 +1,74 @@ +package e2e + +import ( + "strings" + "testing" +) + +func TestServiceHappyPath(t *testing.T) { + tc := CLITest{ + Steps: []Step{ + Create{ + Cmd: "create service", + Input: ` +name: "TestService" +description: "Created by integration test" +`, + }, + Get{ + Cmd: "get service", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "TestService") { + u.Fatalf("get after create failed: %s", out) + } + }, + }, + List{ + Cmd: "list service", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "TestService") { + u.Fatalf("list missing service: %s", out) + } + }, + }, + Update{ + Cmd: "update service", + Input: ` +name: "TestServiceUpdated" +description: "Updated by integration test" +`, + }, + Get{ + Cmd: "get service", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "TestServiceUpdated") || !strings.Contains(out, "Updated by integration test") { + u.Fatalf("update1 failed\nout: %s", out) + } + }, + }, + // TODO: description cannot be unset yet + // Update{ + // Cmd: "update service", + // Input: ` + //name: "TestServiceUpdatedAgain" + //description: null + //`, + // }, + // Get{ + // Cmd: "get service", + // Validate: func(u *Utility, out string) { + // if !strings.Contains(out, "TestServiceUpdatedAgain") || strings.Contains(out, "Updated by integration test") { + // u.Fatalf("update2 failed (description should be unset)\nout: %s", out) + // } + // }, + // }, + Delete{ + Cmd: "delete service", + }, + Missing{ + Cmd: "get service", + }, + }, + } + tc.Run(t) +} diff --git a/src/e2e/team_test.go b/src/e2e/team_test.go new file mode 100644 index 00000000..d31dad7c --- /dev/null +++ b/src/e2e/team_test.go @@ -0,0 +1,74 @@ +package e2e + +import ( + "strings" + "testing" +) + +func TestTeamHappyPath(t *testing.T) { + tc := CLITest{ + Steps: []Step{ + Create{ + Cmd: "create team", + Input: ` +name: "TestTeam" +responsibilities: "Created by integration test" +`, + }, + Get{ + Cmd: "get team", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "TestTeam") { + u.Fatalf("get after create failed: %s", out) + } + }, + }, + List{ + Cmd: "list team", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "TestTeam") { + u.Fatalf("list missing team: %s", out) + } + }, + }, + Update{ + Cmd: "update team", + Input: ` +name: "TestTeam Updated" +responsibilities: "Updated by integration test" +`, + }, + Get{ + Cmd: "get team", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "TestTeam Updated") || !strings.Contains(out, "Updated by integration test") { + u.Fatalf("update1 failed\nout: %s", out) + } + }, + }, + // TODO: responsibilities cannot be unset yet + // Update{ + // Cmd: "update team", + // Input: ` + //name: "Integration Test Team Updated Again" + //responsibilities: null + //`, + // }, + // Get{ + // Cmd: "get team", + // Validate: func(u *Utility, out string) { + // if !strings.Contains(out, "Integration Test Team Updated Again") || strings.Contains(out, "Updated by integration test") { + // u.Fatalf("update2 failed (responsibilities should be unset)\nout: %s", out) + // } + // }, + // }, + Delete{ + Cmd: "delete team", + }, + Missing{ + Cmd: "get team", + }, + }, + } + tc.Run(t) +} From 821a69866239bffcb6a57c6c0fc642770895d459 Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Wed, 18 Jun 2025 12:20:13 -0500 Subject: [PATCH 05/15] Add system test --- src/e2e/system_test.go | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/e2e/system_test.go diff --git a/src/e2e/system_test.go b/src/e2e/system_test.go new file mode 100644 index 00000000..e66ad558 --- /dev/null +++ b/src/e2e/system_test.go @@ -0,0 +1,74 @@ +package e2e + +import ( + "strings" + "testing" +) + +func TestSystemHappyPath(t *testing.T) { + tc := CLITest{ + Steps: []Step{ + Create{ + Cmd: "create system", + Input: ` +name: "Integration Test System" +description: "Created by integration test" +`, + }, + Get{ + Cmd: "get system", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test System") { + u.Fatalf("get after create failed: %s", out) + } + }, + }, + List{ + Cmd: "list system", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test System") { + u.Fatalf("list missing system: %s", out) + } + }, + }, + Update{ + Cmd: "update system", + Input: ` +name: "Integration Test System Updated" +description: "Updated by integration test" +`, + }, + Get{ + Cmd: "get system", + Validate: func(u *Utility, out string) { + if !strings.Contains(out, "Integration Test System Updated") || !strings.Contains(out, "Updated by integration test") { + u.Fatalf("update1 failed\nout: %s", out) + } + }, + }, + // TODO: description cannot be unset yet + // Update{ + // Cmd: "update system", + // Input: ` + //name: "Integration Test System Updated Again" + //description: null + //`, + // }, + // Get{ + // Cmd: "get system", + // Validate: func(u *Utility, out string) { + // if !strings.Contains(out, "Integration Test System Updated Again") || strings.Contains(out, "Updated by integration test") { + // u.Fatalf("update2 failed (description should be unset)\nout: %s", out) + // } + // }, + // }, + Delete{ + Cmd: "delete system", + }, + Missing{ + Cmd: "get system", + }, + }, + } + tc.Run(t) +} \ No newline at end of file From b7fee1795b3d4444be69e3f588dc0e100c3e2424 Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Wed, 18 Jun 2025 13:52:37 -0500 Subject: [PATCH 06/15] First pass at fixing example command --- src/cmd/example.go | 14 ++++++++++++++ src/cmd/system.go | 8 +++++++- src/e2e/helpers.go | 20 ++++++++++++++++++++ src/e2e/system_test.go | 11 ++++++++++- src/submodules/opslevel-go | 2 +- 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/cmd/example.go b/src/cmd/example.go index 92fd8d15..7bd92690 100644 --- a/src/cmd/example.go +++ b/src/cmd/example.go @@ -24,6 +24,20 @@ func getExample[T any]() string { return getYaml[T]() } +func getExample2[T any](v T) string { + var out []byte + var err error + if exampleIsJson { + out, err = json.Marshal(v) + } else { + out, err = yaml.Marshal(v) + } + if err != nil { + panic("unexpected error getting example") + } + return string(out) +} + func getJson[T any]() string { var ( out []byte diff --git a/src/cmd/system.go b/src/cmd/system.go index fd06fcb2..070a0a55 100644 --- a/src/cmd/system.go +++ b/src/cmd/system.go @@ -18,7 +18,13 @@ var exampleSystemCmd = &cobra.Command{ Short: "Example system", Long: `Example system`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.SystemInput]()) + fmt.Println(getExample2(opslevel.SystemInput{ + Name: opslevel.RefOf("example_name"), + Description: opslevel.RefOf("example_description"), + OwnerId: opslevel.RefOf(opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk")), + //Parent: opslevel.NewIdentifier("domain-alias"), + Note: opslevel.RefOf("example_note"), + })) }, } diff --git a/src/e2e/helpers.go b/src/e2e/helpers.go index 0a131dd5..d5a33f95 100644 --- a/src/e2e/helpers.go +++ b/src/e2e/helpers.go @@ -172,3 +172,23 @@ func (s Missing) Run(u *Utility) { func (s Missing) Name() string { return "Missing" } func (s Missing) Deferred() bool { return true } + +type Example struct { + Cmd string + Yaml string +} + +func (s Example) Run(u *Utility) { + out, err := u.Run(s.Cmd + " --yaml") + if err != nil { + panic("example failed: " + err.Error() + "\nout: " + out) + } + wip := strings.TrimSpace(out) + expected := strings.TrimSpace(s.Yaml) + if wip != expected { + u.Fatalf("example mismatch for '%s'\nExpected:\n%s\nWIP:\n%s", s.Cmd, expected, wip) + } +} + +func (s Example) Name() string { return "Example" } +func (s Example) Deferred() bool { return false } diff --git a/src/e2e/system_test.go b/src/e2e/system_test.go index e66ad558..8fd58619 100644 --- a/src/e2e/system_test.go +++ b/src/e2e/system_test.go @@ -8,6 +8,15 @@ import ( func TestSystemHappyPath(t *testing.T) { tc := CLITest{ Steps: []Step{ + Example{ + Cmd: "example system", + Yaml: ` +description: example_description +name: example_name +note: example_note +ownerId: Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk +`, + }, Create{ Cmd: "create system", Input: ` @@ -71,4 +80,4 @@ description: "Updated by integration test" }, } tc.Run(t) -} \ No newline at end of file +} diff --git a/src/submodules/opslevel-go b/src/submodules/opslevel-go index 095e4b04..fc57f4af 160000 --- a/src/submodules/opslevel-go +++ b/src/submodules/opslevel-go @@ -1 +1 @@ -Subproject commit 095e4b041e53c38dff17aa0a23501e0a52c79d07 +Subproject commit fc57f4af07fd26bff92998437fff6ecfc2bb8e23 From bebfe70a29ac938c42abda47d6ed93490c06ac68 Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Wed, 18 Jun 2025 13:59:09 -0500 Subject: [PATCH 07/15] more tweaks --- src/cmd/domain.go | 8 +++++++- src/cmd/system.go | 4 ++-- src/e2e/domain_test.go | 9 +++++++++ src/e2e/system_test.go | 2 ++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/cmd/domain.go b/src/cmd/domain.go index 1b64e48e..6d0b62d4 100644 --- a/src/cmd/domain.go +++ b/src/cmd/domain.go @@ -17,7 +17,13 @@ var exampleDomainCmd = &cobra.Command{ Short: "Example Domain", Long: `Example Domain`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.DomainInput]()) + fmt.Println(getExample2(opslevel.DomainInput{ + Name: opslevel.RefOf("example_name"), + Description: opslevel.RefOf("example_description"), + OwnerId: opslevel.RefOf(opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk")), + //Parent: opslevel.NewIdentifier("domain-alias"), + Note: opslevel.RefOf("example_note"), + })) }, } diff --git a/src/cmd/system.go b/src/cmd/system.go index 070a0a55..586ad461 100644 --- a/src/cmd/system.go +++ b/src/cmd/system.go @@ -22,8 +22,8 @@ var exampleSystemCmd = &cobra.Command{ Name: opslevel.RefOf("example_name"), Description: opslevel.RefOf("example_description"), OwnerId: opslevel.RefOf(opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk")), - //Parent: opslevel.NewIdentifier("domain-alias"), - Note: opslevel.RefOf("example_note"), + Parent: opslevel.NewIdentifier("domain-alias"), + Note: opslevel.RefOf("example_note"), })) }, } diff --git a/src/e2e/domain_test.go b/src/e2e/domain_test.go index 3f46e7cf..05b98455 100644 --- a/src/e2e/domain_test.go +++ b/src/e2e/domain_test.go @@ -8,6 +8,15 @@ import ( func TestDomainHappyPath(t *testing.T) { tc := CLITest{ Steps: []Step{ + Example{ + Cmd: "example domain", + Yaml: ` +description: example_description +name: example_name +note: example_note +ownerId: Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk +`, + }, Create{ Cmd: "create domain", Input: ` diff --git a/src/e2e/system_test.go b/src/e2e/system_test.go index 8fd58619..0b4b02be 100644 --- a/src/e2e/system_test.go +++ b/src/e2e/system_test.go @@ -15,6 +15,8 @@ description: example_description name: example_name note: example_note ownerId: Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk +parent: + alias: domain-alias `, }, Create{ From 720052ae07cfdc51d80f5032888d2065dde0778d Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Mon, 23 Jun 2025 11:57:10 -0500 Subject: [PATCH 08/15] Fix CI --- src/cmd/domain.go | 3 +-- src/cmd/integration.go | 6 +++--- src/e2e/helpers.go | 2 +- src/e2e/infrastructure_test.go | 12 ++++++++++++ src/e2e/service_test.go | 13 +++++++++++++ src/e2e/team_test.go | 9 +++++++++ src/go.mod | 10 +++++----- src/go.sum | 32 ++++++++++++++++---------------- 8 files changed, 60 insertions(+), 27 deletions(-) diff --git a/src/cmd/domain.go b/src/cmd/domain.go index 6d0b62d4..2a9b8c8f 100644 --- a/src/cmd/domain.go +++ b/src/cmd/domain.go @@ -21,8 +21,7 @@ var exampleDomainCmd = &cobra.Command{ Name: opslevel.RefOf("example_name"), Description: opslevel.RefOf("example_description"), OwnerId: opslevel.RefOf(opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk")), - //Parent: opslevel.NewIdentifier("domain-alias"), - Note: opslevel.RefOf("example_note"), + Note: opslevel.RefOf("example_note"), })) }, } diff --git a/src/cmd/integration.go b/src/cmd/integration.go index 84e89c52..e36d243b 100644 --- a/src/cmd/integration.go +++ b/src/cmd/integration.go @@ -39,9 +39,9 @@ type IntegrationInputType struct { type IntegrationInput interface { opslevel.AWSIntegrationInput | - opslevel.AzureResourcesIntegrationInput | - EventIntegrationInputDTO | - opslevel.GoogleCloudIntegrationInput + opslevel.AzureResourcesIntegrationInput | + EventIntegrationInputDTO | + opslevel.GoogleCloudIntegrationInput } func validateIntegrationInput() (*IntegrationInputType, error) { diff --git a/src/e2e/helpers.go b/src/e2e/helpers.go index d5a33f95..0893e32c 100644 --- a/src/e2e/helpers.go +++ b/src/e2e/helpers.go @@ -52,7 +52,7 @@ func (tc *CLITest) Run(t *testing.T) { // Run executes the CLI using 'go run main.go' from the ./src directory with the given arguments and optional stdin, returning combined output and error. func (u *Utility) Run(args string, stdin ...string) (string, error) { // TODO: need to allow using the pre-built binary - //cmd := exec.Command("opslevel", strings.Split(args, " ")...) + // cmd := exec.Command("opslevel", strings.Split(args, " ")...) cmd := exec.Command("go", append([]string{"run", "main.go"}, strings.Split(args, " ")...)...) cmd.Dir = ".." diff --git a/src/e2e/infrastructure_test.go b/src/e2e/infrastructure_test.go index 95595cb3..a69c217c 100644 --- a/src/e2e/infrastructure_test.go +++ b/src/e2e/infrastructure_test.go @@ -8,6 +8,18 @@ import ( func TestInfrastructureHappyPath(t *testing.T) { tc := CLITest{ Steps: []Step{ + Example{ + Cmd: "example infra", + Yaml: ` +ownerId: Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk +data: + endpoint: https://google.com + engine: BigQuery + name: my-big-query + replica: false +providerResourceType: example_type +`, + }, Create{ Cmd: "create infra", Input: ` diff --git a/src/e2e/service_test.go b/src/e2e/service_test.go index 4ad3ac5e..7082251c 100644 --- a/src/e2e/service_test.go +++ b/src/e2e/service_test.go @@ -8,6 +8,19 @@ import ( func TestServiceHappyPath(t *testing.T) { tc := CLITest{ Steps: []Step{ + Example{ + Cmd: "example service", + Yaml: ` +name: example_name +product: example_product +description: example_description +language: example_language +framework: example_framework +tier: example_alias +lifecycle: example_alias +skipAliasesValidation: false +`, + }, Create{ Cmd: "create service", Input: ` diff --git a/src/e2e/team_test.go b/src/e2e/team_test.go index d31dad7c..f08c7317 100644 --- a/src/e2e/team_test.go +++ b/src/e2e/team_test.go @@ -8,6 +8,15 @@ import ( func TestTeamHappyPath(t *testing.T) { tc := CLITest{ Steps: []Step{ + Example{ + Cmd: "example team", + Yaml: ` +responsibilities: example description of responsibilities +members: [] +name: example_name +contacts: [] +`, + }, Create{ Cmd: "create team", Input: ` diff --git a/src/go.mod b/src/go.mod index 7c73e9a4..c55ce7d1 100644 --- a/src/go.mod +++ b/src/go.mod @@ -55,8 +55,8 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/gosimple/unidecode v1.0.1 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect - github.com/hasura/go-graphql-client v0.14.3 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect + github.com/hasura/go-graphql-client v0.14.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect @@ -92,10 +92,10 @@ require ( go.opentelemetry.io/otel/sdk v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.38.0 // indirect - golang.org/x/net v0.40.0 // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/net v0.41.0 // indirect golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.25.0 // indirect + golang.org/x/text v0.26.0 // indirect google.golang.org/protobuf v1.36.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/src/go.sum b/src/go.sum index 27b79c9a..09abc552 100644 --- a/src/go.sum +++ b/src/go.sum @@ -141,10 +141,10 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= -github.com/hasura/go-graphql-client v0.14.3 h1:7La92TuA/FRkVmFd1IN8E+WGW8Lxyn6NKOXAgWcoBDA= -github.com/hasura/go-graphql-client v0.14.3/go.mod h1:jfSZtBER3or+88Q9vFhWHiFMPppfYILRyl+0zsgPIIw= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= +github.com/hasura/go-graphql-client v0.14.4 h1:bYU7/+V50T2YBGdNQXt6l4f2cMZPECPUd8cyCR+ixtw= +github.com/hasura/go-graphql-client v0.14.4/go.mod h1:jfSZtBER3or+88Q9vFhWHiFMPppfYILRyl+0zsgPIIw= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -285,17 +285,17 @@ go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -313,13 +313,13 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= From e13b4aee27cfda302cb86f4c89df28c70e2bfc1a Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Mon, 23 Jun 2025 12:04:26 -0500 Subject: [PATCH 09/15] Fix up all example commands --- src/cmd/action.go | 11 ++++++++++- src/cmd/dependency.go | 8 +++++++- src/cmd/filter.go | 12 +++++++++++- src/cmd/infra.go | 11 ++++++++++- src/cmd/scorecard.go | 7 ++++++- src/cmd/secret.go | 5 ++++- src/cmd/service.go | 13 ++++++++++++- src/cmd/tag.go | 5 ++++- src/cmd/team.go | 18 +++++++++++++++--- 9 files changed, 79 insertions(+), 11 deletions(-) diff --git a/src/cmd/action.go b/src/cmd/action.go index f26e48aa..06ff0f3e 100644 --- a/src/cmd/action.go +++ b/src/cmd/action.go @@ -17,7 +17,16 @@ var exampleActionCmd = &cobra.Command{ Short: "Example action", Long: `Example action`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.CustomActionsWebhookActionCreateInput]()) + fmt.Println(getExample2(opslevel.CustomActionsWebhookActionCreateInput{ + Name: "example_name", + Description: opslevel.RefOf("example_description"), + WebhookUrl: "example_webhook_url", + HttpMethod: opslevel.RefOf("POST"), + Headers: map[string]string{ + "example_header": "example_value", + }, + LiquidTemplate: opslevel.RefOf("example_liquid_template"), + })) }, } diff --git a/src/cmd/dependency.go b/src/cmd/dependency.go index 3fe55c91..5528eae9 100644 --- a/src/cmd/dependency.go +++ b/src/cmd/dependency.go @@ -20,7 +20,13 @@ var exampleServiceDependencyCmd = &cobra.Command{ Short: "Example service dependency", Long: `Example service dependency`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.ServiceDependencyCreateInput]()) + fmt.Println(getExample2(opslevel.ServiceDependencyCreateInput{ + DependencyKey: opslevel.ServiceDependencyKey{ + SourceIdentifier: opslevel.NewIdentifier("example_source"), + DestinationIdentifier: opslevel.NewIdentifier("example_destination"), + }, + Notes: opslevel.RefOf("example_notes"), + })) }, } diff --git a/src/cmd/filter.go b/src/cmd/filter.go index 840e3bda..228e101b 100644 --- a/src/cmd/filter.go +++ b/src/cmd/filter.go @@ -15,7 +15,17 @@ var exampleFilterCmd = &cobra.Command{ Short: "Example filter", Long: `Example filter`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.FilterCreateInput]()) + fmt.Println(getExample2(opslevel.FilterCreateInput{ + Name: "example_name", + Predicates: &[]opslevel.FilterPredicateInput{ + { + Key: opslevel.PredicateKeyEnumAliases, + Type: opslevel.PredicateTypeEnumEquals, + Value: opslevel.RefOf("example_value"), + CaseSensitive: opslevel.RefOf(false), + }, + }, + })) }, } diff --git a/src/cmd/infra.go b/src/cmd/infra.go index 588e0d96..18b1c96f 100644 --- a/src/cmd/infra.go +++ b/src/cmd/infra.go @@ -20,7 +20,16 @@ var exampleInfraCmd = &cobra.Command{ Short: "Example infrastructure resource", Long: `Example infrastructure resource`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.InfrastructureResourceInput]()) + fmt.Println(getExample2(opslevel.InfrastructureResourceInput{ + Schema: opslevel.RefOf("example_schema"), + ProviderData: &opslevel.InfrastructureResourceProviderDataInput{ + AccountName: "example_account", + ExternalUrl: opslevel.RefOf("example_external_url"), + ProviderName: opslevel.RefOf("example_provider"), + }, + ProviderResourceType: opslevel.RefOf("example_provider_resource_type"), + OwnerId: opslevel.RefOf(opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk")), + })) }, } diff --git a/src/cmd/scorecard.go b/src/cmd/scorecard.go index ec62b515..7322ba87 100644 --- a/src/cmd/scorecard.go +++ b/src/cmd/scorecard.go @@ -16,7 +16,12 @@ var exampleScorecardCmd = &cobra.Command{ Short: "Example Scorecard", Long: `Example Scorecard`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.ScorecardInput]()) + fmt.Println(getExample2(opslevel.ScorecardInput{ + Name: "example_name", + Description: opslevel.RefOf("example_description"), + OwnerId: opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"), + AffectsOverallServiceLevels: opslevel.RefOf(false), + })) }, } diff --git a/src/cmd/secret.go b/src/cmd/secret.go index 231a6eb9..74430f70 100644 --- a/src/cmd/secret.go +++ b/src/cmd/secret.go @@ -18,7 +18,10 @@ var exampleSecretCmd = &cobra.Command{ Short: "Example Secret", Long: `Example Secret`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.SecretInput]()) + fmt.Println(getExample2(opslevel.SecretInput{ + Owner: opslevel.NewIdentifier("example_owner"), + Value: opslevel.RefOf("example_value"), + })) }, } diff --git a/src/cmd/service.go b/src/cmd/service.go index bbee6c69..82662df9 100644 --- a/src/cmd/service.go +++ b/src/cmd/service.go @@ -21,7 +21,18 @@ var exampleServiceCmd = &cobra.Command{ Short: "Example service", Long: `Example service`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.ServiceCreateInput]()) + fmt.Println(getExample2(opslevel.ServiceCreateInput{ + Name: "example_name", + Description: opslevel.RefOf("example_description"), + Framework: opslevel.RefOf("example_framework"), + Language: opslevel.RefOf("example_language"), + LifecycleAlias: opslevel.RefOf("example_lifecycle"), + OwnerAlias: opslevel.RefOf("example_owner"), + Parent: opslevel.NewIdentifier("example_parent"), + Product: opslevel.RefOf("example_product"), + TierAlias: opslevel.RefOf("example_tier"), + Type: opslevel.NewIdentifier("example_type"), + })) }, } diff --git a/src/cmd/tag.go b/src/cmd/tag.go index 347cd3b9..0865e7a0 100644 --- a/src/cmd/tag.go +++ b/src/cmd/tag.go @@ -19,7 +19,10 @@ var exampleTagCmd = &cobra.Command{ Short: "Example tag to assign to a resource", Long: `Example tag to assign to a resource`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.TagInput]()) + fmt.Println(getExample2(opslevel.TagInput{ + Key: "example_key", + Value: "example_value", + })) }, } diff --git a/src/cmd/team.go b/src/cmd/team.go index fc53ecfb..0e1447c7 100644 --- a/src/cmd/team.go +++ b/src/cmd/team.go @@ -16,7 +16,12 @@ var exampleTeamCmd = &cobra.Command{ Short: "Example team", Long: `Example team`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.TeamCreateInput]()) + fmt.Println(getExample2(opslevel.TeamCreateInput{ + Name: "example_name", + ManagerEmail: opslevel.RefOf("example_manager_email"), + ParentTeam: opslevel.NewIdentifier("example_parent_team"), + Responsibilities: opslevel.RefOf("example_responsibilities"), + })) }, } @@ -49,7 +54,11 @@ var exampleMemberCmd = &cobra.Command{ Short: "Example member", Long: `Example member`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.TeamMembershipUserInput]()) + fmt.Println(getExample2(opslevel.TeamMembershipUserInput{ + Email: opslevel.RefOf("example_email"), + Role: opslevel.RefOf("example_role"), + User: opslevel.NewUserIdentifier("example_user"), + })) }, } @@ -92,7 +101,10 @@ var exampleContactCmd = &cobra.Command{ Short: "Example contact to a team", Long: `Example contact to a team`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.ContactInput]()) + fmt.Println(getExample2(opslevel.ContactInput{ + DisplayName: opslevel.RefOf("example_display_name"), + Address: opslevel.RefOf("example_address"), + })) }, } From ec5bf41460cdd5c85afb01376bb22d5efba0143e Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Mon, 23 Jun 2025 12:18:46 -0500 Subject: [PATCH 10/15] More fixes --- src/cmd/action.go | 4 ++-- src/cmd/alias.go | 5 ++++- src/cmd/example.go | 7 ------- src/cmd/infra.go | 4 +++- src/cmd/property.go | 14 ++++++++++++-- src/cmd/rubric.go | 8 ++++++-- src/cmd/team.go | 2 +- src/cmd/trigger_definition.go | 5 ++++- src/cmd/user.go | 4 +++- 9 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/cmd/action.go b/src/cmd/action.go index 06ff0f3e..220875ed 100644 --- a/src/cmd/action.go +++ b/src/cmd/action.go @@ -21,8 +21,8 @@ var exampleActionCmd = &cobra.Command{ Name: "example_name", Description: opslevel.RefOf("example_description"), WebhookUrl: "example_webhook_url", - HttpMethod: opslevel.RefOf("POST"), - Headers: map[string]string{ + HttpMethod: opslevel.CustomActionsHttpMethodEnumPost, + Headers: &opslevel.JSON{ "example_header": "example_value", }, LiquidTemplate: opslevel.RefOf("example_liquid_template"), diff --git a/src/cmd/alias.go b/src/cmd/alias.go index b26c1270..3184ad55 100644 --- a/src/cmd/alias.go +++ b/src/cmd/alias.go @@ -16,7 +16,10 @@ var exampleAliasCmd = &cobra.Command{ Short: "Example alias", Long: `Example alias`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.AliasCreateInput]()) + fmt.Println(getExample2(opslevel.AliasCreateInput{ + OwnerId: opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"), + Alias: "example_alias", + })) }, } diff --git a/src/cmd/example.go b/src/cmd/example.go index 7bd92690..22514205 100644 --- a/src/cmd/example.go +++ b/src/cmd/example.go @@ -17,13 +17,6 @@ var exampleCmd = &cobra.Command{ Long: "Examples of OpsLevel resources in different formats", } -func getExample[T any]() string { - if exampleIsJson { - return getJson[T]() - } - return getYaml[T]() -} - func getExample2[T any](v T) string { var out []byte var err error diff --git a/src/cmd/infra.go b/src/cmd/infra.go index 18b1c96f..7efcf664 100644 --- a/src/cmd/infra.go +++ b/src/cmd/infra.go @@ -21,7 +21,9 @@ var exampleInfraCmd = &cobra.Command{ Long: `Example infrastructure resource`, Run: func(cmd *cobra.Command, args []string) { fmt.Println(getExample2(opslevel.InfrastructureResourceInput{ - Schema: opslevel.RefOf("example_schema"), + Schema: &opslevel.InfrastructureResourceSchemaInput{ + Type: "example_schema", + }, ProviderData: &opslevel.InfrastructureResourceProviderDataInput{ AccountName: "example_account", ExternalUrl: opslevel.RefOf("example_external_url"), diff --git a/src/cmd/property.go b/src/cmd/property.go index 9735e9f0..1b2e8f2c 100644 --- a/src/cmd/property.go +++ b/src/cmd/property.go @@ -20,7 +20,11 @@ var examplePropertyCmd = &cobra.Command{ Short: "Example Property", Long: `Example Property`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.PropertyInput]()) + fmt.Println(getExample2(opslevel.PropertyInput{ + Definition: *opslevel.NewIdentifier("example_definition"), + Owner: *opslevel.NewIdentifier("example_owner"), + Value: opslevel.JsonString("example_value"), + })) }, } @@ -149,7 +153,13 @@ var examplePropertyDefinitionCmd = &cobra.Command{ Short: "Example Property Definition", Long: `Example Property Definition`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.PropertyDefinitionInput]()) + fmt.Println(getExample2(opslevel.PropertyDefinitionInput{ + Name: opslevel.RefOf("example_name"), + Description: opslevel.RefOf("example_description"), + Schema: opslevel.JSONSchema{ + "type": "string", + }, + })) }, } diff --git a/src/cmd/rubric.go b/src/cmd/rubric.go index 4db95af7..2d78dedd 100644 --- a/src/cmd/rubric.go +++ b/src/cmd/rubric.go @@ -16,7 +16,9 @@ var exampleCategoryCmd = &cobra.Command{ Short: "Example rubric category", Long: `Example rubric category`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.CategoryCreateInput]()) + fmt.Println(getExample2(opslevel.CategoryCreateInput{ + Name: "example_name", + })) }, } @@ -92,7 +94,9 @@ var exampleLevelCmd = &cobra.Command{ Short: "Example rubric level", Long: `Example rubric level`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.LevelCreateInput]()) + fmt.Println(getExample2(opslevel.LevelCreateInput{ + Name: "example_name", + })) }, } diff --git a/src/cmd/team.go b/src/cmd/team.go index 0e1447c7..bb2f9348 100644 --- a/src/cmd/team.go +++ b/src/cmd/team.go @@ -103,7 +103,7 @@ var exampleContactCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { fmt.Println(getExample2(opslevel.ContactInput{ DisplayName: opslevel.RefOf("example_display_name"), - Address: opslevel.RefOf("example_address"), + Address: "example_address", })) }, } diff --git a/src/cmd/trigger_definition.go b/src/cmd/trigger_definition.go index 8ba3ba60..1642bd70 100644 --- a/src/cmd/trigger_definition.go +++ b/src/cmd/trigger_definition.go @@ -16,7 +16,10 @@ var exampleTriggerDefinitionCmd = &cobra.Command{ Short: "Example Scorecard", Long: `Example Scorecard`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.CustomActionsTriggerDefinitionCreateInput]()) + fmt.Println(getExample2(opslevel.CustomActionsTriggerDefinitionCreateInput{ + Name: "example_name", + OwnerId: opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"), + })) }, } diff --git a/src/cmd/user.go b/src/cmd/user.go index 4bb8ad8c..27045075 100644 --- a/src/cmd/user.go +++ b/src/cmd/user.go @@ -20,7 +20,9 @@ var exampleUserCmd = &cobra.Command{ Short: "Example User", Long: `Example User`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample[opslevel.UserInput]()) + fmt.Println(getExample2(opslevel.UserInput{ + Name: opslevel.RefOf("example_name"), + })) }, } From 64b26d28ac84ddcf598fb9f95fef9b7d1d727205 Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Mon, 23 Jun 2025 12:24:30 -0500 Subject: [PATCH 11/15] fixes --- src/cmd/property.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/property.go b/src/cmd/property.go index 1b2e8f2c..5066df36 100644 --- a/src/cmd/property.go +++ b/src/cmd/property.go @@ -156,7 +156,7 @@ var examplePropertyDefinitionCmd = &cobra.Command{ fmt.Println(getExample2(opslevel.PropertyDefinitionInput{ Name: opslevel.RefOf("example_name"), Description: opslevel.RefOf("example_description"), - Schema: opslevel.JSONSchema{ + Schema: &opslevel.JSONSchema{ "type": "string", }, })) From 3684f29e614f292ff8942ae59282907fd266fb1c Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Mon, 23 Jun 2025 14:13:54 -0500 Subject: [PATCH 12/15] more fixes for removal of old code --- src/cmd/action.go | 2 +- src/cmd/alias.go | 2 +- src/cmd/dependency.go | 2 +- src/cmd/domain.go | 2 +- src/cmd/example.go | 29 +------------------------- src/cmd/filter.go | 2 +- src/cmd/infra.go | 2 +- src/cmd/property.go | 38 +++++++++++++++++++++-------------- src/cmd/rubric.go | 4 ++-- src/cmd/scorecard.go | 2 +- src/cmd/secret.go | 2 +- src/cmd/service.go | 2 +- src/cmd/system.go | 2 +- src/cmd/tag.go | 2 +- src/cmd/team.go | 6 +++--- src/cmd/trigger_definition.go | 2 +- src/cmd/user.go | 2 +- 17 files changed, 42 insertions(+), 61 deletions(-) diff --git a/src/cmd/action.go b/src/cmd/action.go index 220875ed..a0f610e7 100644 --- a/src/cmd/action.go +++ b/src/cmd/action.go @@ -17,7 +17,7 @@ var exampleActionCmd = &cobra.Command{ Short: "Example action", Long: `Example action`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.CustomActionsWebhookActionCreateInput{ + fmt.Println(getExample(opslevel.CustomActionsWebhookActionCreateInput{ Name: "example_name", Description: opslevel.RefOf("example_description"), WebhookUrl: "example_webhook_url", diff --git a/src/cmd/alias.go b/src/cmd/alias.go index 3184ad55..cd3c530f 100644 --- a/src/cmd/alias.go +++ b/src/cmd/alias.go @@ -16,7 +16,7 @@ var exampleAliasCmd = &cobra.Command{ Short: "Example alias", Long: `Example alias`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.AliasCreateInput{ + fmt.Println(getExample(opslevel.AliasCreateInput{ OwnerId: opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"), Alias: "example_alias", })) diff --git a/src/cmd/dependency.go b/src/cmd/dependency.go index 5528eae9..b7c6a715 100644 --- a/src/cmd/dependency.go +++ b/src/cmd/dependency.go @@ -20,7 +20,7 @@ var exampleServiceDependencyCmd = &cobra.Command{ Short: "Example service dependency", Long: `Example service dependency`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.ServiceDependencyCreateInput{ + fmt.Println(getExample(opslevel.ServiceDependencyCreateInput{ DependencyKey: opslevel.ServiceDependencyKey{ SourceIdentifier: opslevel.NewIdentifier("example_source"), DestinationIdentifier: opslevel.NewIdentifier("example_destination"), diff --git a/src/cmd/domain.go b/src/cmd/domain.go index 2a9b8c8f..277a75a2 100644 --- a/src/cmd/domain.go +++ b/src/cmd/domain.go @@ -17,7 +17,7 @@ var exampleDomainCmd = &cobra.Command{ Short: "Example Domain", Long: `Example Domain`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.DomainInput{ + fmt.Println(getExample(opslevel.DomainInput{ Name: opslevel.RefOf("example_name"), Description: opslevel.RefOf("example_description"), OwnerId: opslevel.RefOf(opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk")), diff --git a/src/cmd/example.go b/src/cmd/example.go index 22514205..9effd75e 100644 --- a/src/cmd/example.go +++ b/src/cmd/example.go @@ -3,7 +3,6 @@ package cmd import ( "encoding/json" - "github.com/opslevel/opslevel-go/v2025" "github.com/spf13/cobra" "github.com/spf13/viper" "gopkg.in/yaml.v2" @@ -17,7 +16,7 @@ var exampleCmd = &cobra.Command{ Long: "Examples of OpsLevel resources in different formats", } -func getExample2[T any](v T) string { +func getExample[T any](v T) string { var out []byte var err error if exampleIsJson { @@ -31,32 +30,6 @@ func getExample2[T any](v T) string { return string(out) } -func getJson[T any]() string { - var ( - out []byte - err error - ) - t := opslevel.NewExampleOf[T]() - out, err = json.Marshal(t) - if err != nil { - panic("unexpected error getting example json") - } - return string(out) -} - -func getYaml[T any]() string { - var ( - out []byte - err error - ) - t := opslevel.NewExampleOf[T]() - out, err = yaml.Marshal(t) - if err != nil { - panic("unexpected error getting example yaml") - } - return string(out) -} - func init() { rootCmd.AddCommand(exampleCmd) diff --git a/src/cmd/filter.go b/src/cmd/filter.go index 228e101b..2c3c91dd 100644 --- a/src/cmd/filter.go +++ b/src/cmd/filter.go @@ -15,7 +15,7 @@ var exampleFilterCmd = &cobra.Command{ Short: "Example filter", Long: `Example filter`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.FilterCreateInput{ + fmt.Println(getExample(opslevel.FilterCreateInput{ Name: "example_name", Predicates: &[]opslevel.FilterPredicateInput{ { diff --git a/src/cmd/infra.go b/src/cmd/infra.go index 7efcf664..2608dfde 100644 --- a/src/cmd/infra.go +++ b/src/cmd/infra.go @@ -20,7 +20,7 @@ var exampleInfraCmd = &cobra.Command{ Short: "Example infrastructure resource", Long: `Example infrastructure resource`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.InfrastructureResourceInput{ + fmt.Println(getExample(opslevel.InfrastructureResourceInput{ Schema: &opslevel.InfrastructureResourceSchemaInput{ Type: "example_schema", }, diff --git a/src/cmd/property.go b/src/cmd/property.go index 5066df36..f37f72fc 100644 --- a/src/cmd/property.go +++ b/src/cmd/property.go @@ -14,17 +14,31 @@ import ( "github.com/spf13/cobra" ) +func buildExamplePropertyInput() string { + return getExample(opslevel.PropertyInput{ + Definition: *opslevel.NewIdentifier("example_definition"), + Owner: *opslevel.NewIdentifier("example_owner"), + Value: opslevel.JsonString("example_value"), + }) +} + +func buildExamplePropertyDefinitionInput() string { + return getExample(opslevel.PropertyDefinitionInput{ + Name: opslevel.RefOf("example_name"), + Description: opslevel.RefOf("example_description"), + Schema: &opslevel.JSONSchema{ + "type": "string", + }, + }) +} + var examplePropertyCmd = &cobra.Command{ Use: "property", Aliases: []string{"prop"}, Short: "Example Property", Long: `Example Property`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.PropertyInput{ - Definition: *opslevel.NewIdentifier("example_definition"), - Owner: *opslevel.NewIdentifier("example_owner"), - Value: opslevel.JsonString("example_value"), - })) + fmt.Println(buildExamplePropertyInput()) }, } @@ -108,7 +122,7 @@ EOF cat << EOF | opslevel assign property -f - %s -EOF`, getYaml[opslevel.PropertyInput]()), +EOF`, buildExamplePropertyInput()), Run: func(cmd *cobra.Command, args []string) { input, err := readResourceInput[opslevel.PropertyInput]() cobra.CheckErr(err) @@ -153,13 +167,7 @@ var examplePropertyDefinitionCmd = &cobra.Command{ Short: "Example Property Definition", Long: `Example Property Definition`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.PropertyDefinitionInput{ - Name: opslevel.RefOf("example_name"), - Description: opslevel.RefOf("example_description"), - Schema: &opslevel.JSONSchema{ - "type": "string", - }, - })) + fmt.Println(buildExamplePropertyDefinitionInput()) }, } @@ -171,7 +179,7 @@ var createPropertyDefinitionCmd = &cobra.Command{ Example: fmt.Sprintf(` cat << EOF | opslevel create property-definition -f - %s -EOF`, getYaml[opslevel.PropertyDefinitionInput]()), +EOF`, buildExamplePropertyDefinitionInput()), Run: func(cmd *cobra.Command, args []string) { input, err := readPropertyDefinitionInput() cobra.CheckErr(err) @@ -190,7 +198,7 @@ var updatePropertyDefinitionCmd = &cobra.Command{ Example: fmt.Sprintf(` cat << EOF | opslevel update property-definition propdef3 -f - %s -EOF`, getYaml[opslevel.PropertyDefinitionInput]()), +EOF`, buildExamplePropertyDefinitionInput()), Args: cobra.ExactArgs(1), ArgAliases: []string{"ID", "ALIAS"}, Run: func(cmd *cobra.Command, args []string) { diff --git a/src/cmd/rubric.go b/src/cmd/rubric.go index 2d78dedd..7cf16763 100644 --- a/src/cmd/rubric.go +++ b/src/cmd/rubric.go @@ -16,7 +16,7 @@ var exampleCategoryCmd = &cobra.Command{ Short: "Example rubric category", Long: `Example rubric category`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.CategoryCreateInput{ + fmt.Println(getExample(opslevel.CategoryCreateInput{ Name: "example_name", })) }, @@ -94,7 +94,7 @@ var exampleLevelCmd = &cobra.Command{ Short: "Example rubric level", Long: `Example rubric level`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.LevelCreateInput{ + fmt.Println(getExample(opslevel.LevelCreateInput{ Name: "example_name", })) }, diff --git a/src/cmd/scorecard.go b/src/cmd/scorecard.go index 7322ba87..0742cb5d 100644 --- a/src/cmd/scorecard.go +++ b/src/cmd/scorecard.go @@ -16,7 +16,7 @@ var exampleScorecardCmd = &cobra.Command{ Short: "Example Scorecard", Long: `Example Scorecard`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.ScorecardInput{ + fmt.Println(getExample(opslevel.ScorecardInput{ Name: "example_name", Description: opslevel.RefOf("example_description"), OwnerId: opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"), diff --git a/src/cmd/secret.go b/src/cmd/secret.go index 74430f70..98d15e0d 100644 --- a/src/cmd/secret.go +++ b/src/cmd/secret.go @@ -18,7 +18,7 @@ var exampleSecretCmd = &cobra.Command{ Short: "Example Secret", Long: `Example Secret`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.SecretInput{ + fmt.Println(getExample(opslevel.SecretInput{ Owner: opslevel.NewIdentifier("example_owner"), Value: opslevel.RefOf("example_value"), })) diff --git a/src/cmd/service.go b/src/cmd/service.go index 82662df9..bbbf8c42 100644 --- a/src/cmd/service.go +++ b/src/cmd/service.go @@ -21,7 +21,7 @@ var exampleServiceCmd = &cobra.Command{ Short: "Example service", Long: `Example service`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.ServiceCreateInput{ + fmt.Println(getExample(opslevel.ServiceCreateInput{ Name: "example_name", Description: opslevel.RefOf("example_description"), Framework: opslevel.RefOf("example_framework"), diff --git a/src/cmd/system.go b/src/cmd/system.go index 586ad461..88bd581e 100644 --- a/src/cmd/system.go +++ b/src/cmd/system.go @@ -18,7 +18,7 @@ var exampleSystemCmd = &cobra.Command{ Short: "Example system", Long: `Example system`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.SystemInput{ + fmt.Println(getExample(opslevel.SystemInput{ Name: opslevel.RefOf("example_name"), Description: opslevel.RefOf("example_description"), OwnerId: opslevel.RefOf(opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk")), diff --git a/src/cmd/tag.go b/src/cmd/tag.go index 0865e7a0..dd7eb300 100644 --- a/src/cmd/tag.go +++ b/src/cmd/tag.go @@ -19,7 +19,7 @@ var exampleTagCmd = &cobra.Command{ Short: "Example tag to assign to a resource", Long: `Example tag to assign to a resource`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.TagInput{ + fmt.Println(getExample(opslevel.TagInput{ Key: "example_key", Value: "example_value", })) diff --git a/src/cmd/team.go b/src/cmd/team.go index bb2f9348..491c5300 100644 --- a/src/cmd/team.go +++ b/src/cmd/team.go @@ -16,7 +16,7 @@ var exampleTeamCmd = &cobra.Command{ Short: "Example team", Long: `Example team`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.TeamCreateInput{ + fmt.Println(getExample(opslevel.TeamCreateInput{ Name: "example_name", ManagerEmail: opslevel.RefOf("example_manager_email"), ParentTeam: opslevel.NewIdentifier("example_parent_team"), @@ -54,7 +54,7 @@ var exampleMemberCmd = &cobra.Command{ Short: "Example member", Long: `Example member`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.TeamMembershipUserInput{ + fmt.Println(getExample(opslevel.TeamMembershipUserInput{ Email: opslevel.RefOf("example_email"), Role: opslevel.RefOf("example_role"), User: opslevel.NewUserIdentifier("example_user"), @@ -101,7 +101,7 @@ var exampleContactCmd = &cobra.Command{ Short: "Example contact to a team", Long: `Example contact to a team`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.ContactInput{ + fmt.Println(getExample(opslevel.ContactInput{ DisplayName: opslevel.RefOf("example_display_name"), Address: "example_address", })) diff --git a/src/cmd/trigger_definition.go b/src/cmd/trigger_definition.go index 1642bd70..d346cd3f 100644 --- a/src/cmd/trigger_definition.go +++ b/src/cmd/trigger_definition.go @@ -16,7 +16,7 @@ var exampleTriggerDefinitionCmd = &cobra.Command{ Short: "Example Scorecard", Long: `Example Scorecard`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.CustomActionsTriggerDefinitionCreateInput{ + fmt.Println(getExample(opslevel.CustomActionsTriggerDefinitionCreateInput{ Name: "example_name", OwnerId: opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"), })) diff --git a/src/cmd/user.go b/src/cmd/user.go index 27045075..df0c4c48 100644 --- a/src/cmd/user.go +++ b/src/cmd/user.go @@ -20,7 +20,7 @@ var exampleUserCmd = &cobra.Command{ Short: "Example User", Long: `Example User`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample2(opslevel.UserInput{ + fmt.Println(getExample(opslevel.UserInput{ Name: opslevel.RefOf("example_name"), })) }, From 8f7d5eb68302ac06aa15ab052e08ceca7e853feb Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 23 Jun 2025 14:16:11 -0500 Subject: [PATCH 13/15] Update Taskfile.yml --- Taskfile.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Taskfile.yml b/Taskfile.yml index 302f68a3..16116292 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -57,7 +57,7 @@ tasks: - go test -race -coverprofile=coverage.txt -covermode=atomic -v ./cmd/... {{ .CLI_ARGS }} test-e2e: - desc: Run Integration tests + desc: Run end to end Integration tests dir: "{{.SRC_DIR}}" cmds: - go test -v ./e2e/... {{ .CLI_ARGS }} From 0b3bdc4869dad2da1a96e610150a124a29995b9f Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Mon, 23 Jun 2025 14:28:48 -0500 Subject: [PATCH 14/15] fix e2e integration tests --- src/e2e/helpers.go | 2 +- src/e2e/infrastructure_test.go | 13 +++++++------ src/e2e/service_test.go | 16 ++++++++++------ src/e2e/team_test.go | 7 ++++--- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/e2e/helpers.go b/src/e2e/helpers.go index 0893e32c..fa1e54e5 100644 --- a/src/e2e/helpers.go +++ b/src/e2e/helpers.go @@ -186,7 +186,7 @@ func (s Example) Run(u *Utility) { wip := strings.TrimSpace(out) expected := strings.TrimSpace(s.Yaml) if wip != expected { - u.Fatalf("example mismatch for '%s'\nExpected:\n%s\nWIP:\n%s", s.Cmd, expected, wip) + u.Fatalf("example mismatch for '%s'\nExpected:\n%s\nGot:\n%s", s.Cmd, expected, wip) } } diff --git a/src/e2e/infrastructure_test.go b/src/e2e/infrastructure_test.go index a69c217c..63faa97c 100644 --- a/src/e2e/infrastructure_test.go +++ b/src/e2e/infrastructure_test.go @@ -12,12 +12,13 @@ func TestInfrastructureHappyPath(t *testing.T) { Cmd: "example infra", Yaml: ` ownerId: Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk -data: - endpoint: https://google.com - engine: BigQuery - name: my-big-query - replica: false -providerResourceType: example_type +providerData: + accountName: example_account + externalUrl: example_external_url + providerName: example_provider +providerResourceType: example_provider_resource_type +schema: + type: example_schema `, }, Create{ diff --git a/src/e2e/service_test.go b/src/e2e/service_test.go index 7082251c..6e73789f 100644 --- a/src/e2e/service_test.go +++ b/src/e2e/service_test.go @@ -11,14 +11,18 @@ func TestServiceHappyPath(t *testing.T) { Example{ Cmd: "example service", Yaml: ` -name: example_name -product: example_product description: example_description -language: example_language framework: example_framework -tier: example_alias -lifecycle: example_alias -skipAliasesValidation: false +language: example_language +lifecycleAlias: example_lifecycle +name: example_name +ownerAlias: example_owner +parent: + alias: example_parent +product: example_product +tierAlias: example_tier +type: + alias: example_type `, }, Create{ diff --git a/src/e2e/team_test.go b/src/e2e/team_test.go index f08c7317..dc519cf3 100644 --- a/src/e2e/team_test.go +++ b/src/e2e/team_test.go @@ -11,10 +11,11 @@ func TestTeamHappyPath(t *testing.T) { Example{ Cmd: "example team", Yaml: ` -responsibilities: example description of responsibilities -members: [] +managerEmail: example_manager_email name: example_name -contacts: [] +parentTeam: + alias: example_parent_team +responsibilities: example_responsibilities `, }, Create{ From c09bb44305aaaf021bf9cc956f5d31f0ff8f93dc Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Tue, 24 Jun 2025 09:59:29 -0500 Subject: [PATCH 15/15] few more tweaks after testing manually --- src/cmd/infra.go | 22 +++++++++++++--------- src/cmd/team.go | 4 +++- src/e2e/infrastructure_test.go | 20 ++++++++++++-------- src/e2e/team_test.go | 2 ++ 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/cmd/infra.go b/src/cmd/infra.go index 2608dfde..21547737 100644 --- a/src/cmd/infra.go +++ b/src/cmd/infra.go @@ -20,17 +20,21 @@ var exampleInfraCmd = &cobra.Command{ Short: "Example infrastructure resource", Long: `Example infrastructure resource`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(getExample(opslevel.InfrastructureResourceInput{ - Schema: &opslevel.InfrastructureResourceSchemaInput{ - Type: "example_schema", + fmt.Println(getExample(opslevel.InfraInput{ + Schema: "example_schema", + Owner: opslevel.NewID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"), + Provider: &opslevel.InfraProviderInput{ + Account: "example_account", + Name: "example_provider_name", + Type: "example_provider_type", + URL: "example_external_url", }, - ProviderData: &opslevel.InfrastructureResourceProviderDataInput{ - AccountName: "example_account", - ExternalUrl: opslevel.RefOf("example_external_url"), - ProviderName: opslevel.RefOf("example_provider"), + Data: &opslevel.JSON{ + "name": "my-big-query", + "endpoint": "https://google.com", + "engine": "BigQuery", + "replica": false, }, - ProviderResourceType: opslevel.RefOf("example_provider_resource_type"), - OwnerId: opslevel.RefOf(opslevel.ID("Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk")), })) }, } diff --git a/src/cmd/team.go b/src/cmd/team.go index 491c5300..1ca6faff 100644 --- a/src/cmd/team.go +++ b/src/cmd/team.go @@ -17,8 +17,10 @@ var exampleTeamCmd = &cobra.Command{ Long: `Example team`, Run: func(cmd *cobra.Command, args []string) { fmt.Println(getExample(opslevel.TeamCreateInput{ - Name: "example_name", + Contacts: &[]opslevel.ContactInput{}, ManagerEmail: opslevel.RefOf("example_manager_email"), + Members: &[]opslevel.TeamMembershipUserInput{}, + Name: "example_name", ParentTeam: opslevel.NewIdentifier("example_parent_team"), Responsibilities: opslevel.RefOf("example_responsibilities"), })) diff --git a/src/e2e/infrastructure_test.go b/src/e2e/infrastructure_test.go index 63faa97c..ee935844 100644 --- a/src/e2e/infrastructure_test.go +++ b/src/e2e/infrastructure_test.go @@ -11,14 +11,18 @@ func TestInfrastructureHappyPath(t *testing.T) { Example{ Cmd: "example infra", Yaml: ` -ownerId: Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk -providerData: - accountName: example_account - externalUrl: example_external_url - providerName: example_provider -providerResourceType: example_provider_resource_type -schema: - type: example_schema +schema: example_schema +owner: Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk +provider: + account: example_account + name: example_provider_name + type: example_provider_type + url: example_external_url +data: + endpoint: https://google.com + engine: BigQuery + name: my-big-query + replica: false `, }, Create{ diff --git a/src/e2e/team_test.go b/src/e2e/team_test.go index dc519cf3..b5910189 100644 --- a/src/e2e/team_test.go +++ b/src/e2e/team_test.go @@ -11,7 +11,9 @@ func TestTeamHappyPath(t *testing.T) { Example{ Cmd: "example team", Yaml: ` +contacts: [] managerEmail: example_manager_email +members: [] name: example_name parentTeam: alias: example_parent_team