From b1e221d7ebc3ca6c4b2c81e00181ef04110aa645 Mon Sep 17 00:00:00 2001 From: dave vader <48764154+plyr4@users.noreply.github.com> Date: Wed, 15 May 2024 12:05:47 -0500 Subject: [PATCH] feat: db driven platform settings (#554) --- action/dashboard/update.go | 4 +- action/pipeline/validate_test.go | 9 +- action/settings/doc.go | 8 + action/settings/file.go | 11 ++ action/settings/settings.go | 37 ++++ action/settings/testdata/all.yml | 10 + action/settings/testdata/compiler.yml | 6 + action/settings/testdata/noplatform.yml | 2 + action/settings/testdata/platform.yml | 4 + action/settings/testdata/queue.yml | 4 + action/settings/update.go | 249 ++++++++++++++++++++++++ action/settings/update_test.go | 144 ++++++++++++++ action/settings/validate.go | 14 ++ action/settings/validate_test.go | 85 ++++++++ action/settings/view.go | 53 +++++ action/settings/view_test.go | 88 +++++++++ cmd/vela-cli/update.go | 6 + cmd/vela-cli/view.go | 6 + command/pipeline/exec.go | 8 +- command/pipeline/validate.go | 8 +- command/pipeline/validate_test.go | 3 + command/settings/doc.go | 8 + command/settings/update.go | 208 ++++++++++++++++++++ command/settings/update_test.go | 54 +++++ command/settings/view.go | 79 ++++++++ command/settings/view_test.go | 54 +++++ go.mod | 8 +- go.sum | 12 +- 28 files changed, 1159 insertions(+), 23 deletions(-) create mode 100644 action/settings/doc.go create mode 100644 action/settings/file.go create mode 100644 action/settings/settings.go create mode 100644 action/settings/testdata/all.yml create mode 100644 action/settings/testdata/compiler.yml create mode 100644 action/settings/testdata/noplatform.yml create mode 100644 action/settings/testdata/platform.yml create mode 100644 action/settings/testdata/queue.yml create mode 100644 action/settings/update.go create mode 100644 action/settings/update_test.go create mode 100644 action/settings/validate.go create mode 100644 action/settings/validate_test.go create mode 100644 action/settings/view.go create mode 100644 action/settings/view_test.go create mode 100644 command/settings/doc.go create mode 100644 command/settings/update.go create mode 100644 command/settings/update_test.go create mode 100644 command/settings/view.go create mode 100644 command/settings/view_test.go diff --git a/action/dashboard/update.go b/action/dashboard/update.go index 718ea55b..23efcc2d 100644 --- a/action/dashboard/update.go +++ b/action/dashboard/update.go @@ -38,7 +38,7 @@ func (c *Config) Update(client *vela.Client) error { dashboard.SetRepos(newRepos) } - // add specified repositories from the dashboard + // add specified repositories to the dashboard if len(c.AddRepos) > 0 { repos := dashboard.GetRepos() @@ -91,7 +91,7 @@ func (c *Config) Update(client *vela.Client) error { dashboard.SetAdmins(newAdmins) } - // add specified admins from the dashboard + // add specified admins to the dashboard if len(c.AddAdmins) > 0 { admins := dashboard.GetAdmins() diff --git a/action/pipeline/validate_test.go b/action/pipeline/validate_test.go index b05ca794..5103dbe2 100644 --- a/action/pipeline/validate_test.go +++ b/action/pipeline/validate_test.go @@ -169,15 +169,18 @@ func TestPipeline_Config_Validate(t *testing.T) { func TestPipeline_Config_ValidateLocal(t *testing.T) { // setup types - c := cli.NewContext(&cli.App{Name: "vela", Version: "v0.0.0"}, flag.NewFlagSet("test", 0), nil) + set := flag.NewFlagSet("test", 0) + set.String("clone-image", "target/vela-git:latest", "doc") + + c := cli.NewContext(&cli.App{Name: "vela", Version: "v0.0.0"}, set, nil) // create a vela client - client, err := native.New(c) + client, err := native.FromCLIContext(c) if err != nil { t.Errorf("unable to create client: %v", err) } - client.TemplateDepth = 1 + client.SetTemplateDepth(1) // setup tests tests := []struct { diff --git a/action/settings/doc.go b/action/settings/doc.go new file mode 100644 index 00000000..349ff46a --- /dev/null +++ b/action/settings/doc.go @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 + +// The defined CLI settings actions for Vela. +// +// Usage: +// +// import "github.com/go-vela/cli/action/settings" +package settings diff --git a/action/settings/file.go b/action/settings/file.go new file mode 100644 index 00000000..312fce18 --- /dev/null +++ b/action/settings/file.go @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import "github.com/go-vela/server/api/types/settings" + +// ConfigFile represents the configuration necessary +// to perform settings related requests from a file with Vela. +type ConfigFile struct { + *settings.Platform `yaml:"platform,omitempty"` +} diff --git a/action/settings/settings.go b/action/settings/settings.go new file mode 100644 index 00000000..487a387f --- /dev/null +++ b/action/settings/settings.go @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +// Config represents the configuration necessary +// to perform settings related requests with Vela. +type Config struct { + Action string + Output string + File string + Compiler + Queue + + RepoAllowlist *[]string + RepoAllowlistAddRepos []string + RepoAllowlistDropRepos []string + + ScheduleAllowlist *[]string + ScheduleAllowlistAddRepos []string + ScheduleAllowlistDropRepos []string +} + +// Compiler represents the compiler configurations used +// to modify the compiler settings for Vela. +type Compiler struct { + CloneImage *string + TemplateDepth *int + StarlarkExecLimit *uint64 +} + +// Queue represents the compiler configurations used +// to modify the queue settings for Vela. +type Queue struct { + Routes *[]string + AddRoutes []string + DropRoutes []string +} diff --git a/action/settings/testdata/all.yml b/action/settings/testdata/all.yml new file mode 100644 index 00000000..a9e411b3 --- /dev/null +++ b/action/settings/testdata/all.yml @@ -0,0 +1,10 @@ +--- +platform: + compiler: + clone_image: "target/vela-git:latest" + template_depth: 10 + starlark_exec_limit: 100 + queue: + routes: [ "vela", "foobar" ] + repo_allowlist: [ "foo/bar", "octocat/hello-world" ] + schedule_allowlist: [ "*", "octocat/*" ] \ No newline at end of file diff --git a/action/settings/testdata/compiler.yml b/action/settings/testdata/compiler.yml new file mode 100644 index 00000000..da7398ad --- /dev/null +++ b/action/settings/testdata/compiler.yml @@ -0,0 +1,6 @@ +--- +platform: + compiler: + clone_image: "target/vela-git:latest" + template_depth: 10 + starlark_exec_limit: 100 \ No newline at end of file diff --git a/action/settings/testdata/noplatform.yml b/action/settings/testdata/noplatform.yml new file mode 100644 index 00000000..95f455c0 --- /dev/null +++ b/action/settings/testdata/noplatform.yml @@ -0,0 +1,2 @@ +--- +foo: bar \ No newline at end of file diff --git a/action/settings/testdata/platform.yml b/action/settings/testdata/platform.yml new file mode 100644 index 00000000..2df61a01 --- /dev/null +++ b/action/settings/testdata/platform.yml @@ -0,0 +1,4 @@ +--- +platform: + repo_allowlist: [ "foo/bar", "octocat/hello-world" ] + schedule_allowlist: [ "*", "octocat/*" ] \ No newline at end of file diff --git a/action/settings/testdata/queue.yml b/action/settings/testdata/queue.yml new file mode 100644 index 00000000..fa12f2bc --- /dev/null +++ b/action/settings/testdata/queue.yml @@ -0,0 +1,4 @@ +--- +platform: + queue: + routes: [ "vela", "foobar" ] \ No newline at end of file diff --git a/action/settings/update.go b/action/settings/update.go new file mode 100644 index 00000000..d3a7bc4f --- /dev/null +++ b/action/settings/update.go @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "bytes" + "errors" + "os" + "path/filepath" + "slices" + + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" + + "github.com/go-vela/cli/internal" + "github.com/go-vela/cli/internal/output" + "github.com/go-vela/sdk-go/vela" + "github.com/go-vela/server/api/types/settings" +) + +// Update modifies settings based off the provided configuration. +func (c *Config) Update(client *vela.Client) error { + logrus.Debug("executing update for settings configuration") + + // send API call to retrieve current settings + s, _, err := client.Admin.Settings.Get() + if err != nil { + return err + } + + // create the settings object + sUpdate := &settings.Platform{ + Queue: &settings.Queue{ + Routes: vela.Strings(s.GetRoutes()), + }, + Compiler: &settings.Compiler{ + CloneImage: c.Compiler.CloneImage, + TemplateDepth: c.Compiler.TemplateDepth, + StarlarkExecLimit: c.Compiler.StarlarkExecLimit, + }, + RepoAllowlist: vela.Strings(s.GetRepoAllowlist()), + ScheduleAllowlist: vela.Strings(s.GetScheduleAllowlist()), + } + + // drop specified routes + if len(c.Queue.DropRoutes) > 0 { + newRoutes := []string{} + + for _, r := range sUpdate.GetRoutes() { + if !slices.Contains(c.Queue.DropRoutes, r) { + newRoutes = append(newRoutes, r) + } + } + + sUpdate.SetRoutes(newRoutes) + } + + // add specified routes + if len(c.Queue.AddRoutes) > 0 { + routes := sUpdate.GetRoutes() + + for _, r := range c.Queue.AddRoutes { + if !slices.Contains(routes, r) { + routes = append(routes, r) + } + } + + sUpdate.SetRoutes(routes) + } + + // drop specified repositories from the allowlist + if len(c.RepoAllowlistDropRepos) > 0 { + newRepos := []string{} + + for _, r := range sUpdate.GetRepoAllowlist() { + if !slices.Contains(c.RepoAllowlistDropRepos, r) { + newRepos = append(newRepos, r) + } + } + + sUpdate.SetRepoAllowlist(newRepos) + } + + // add specified repositories to the allowlist + if len(c.RepoAllowlistAddRepos) > 0 { + repos := sUpdate.GetRepoAllowlist() + + for _, r := range c.RepoAllowlistAddRepos { + if !slices.Contains(repos, r) { + repos = append(repos, r) + } + } + + sUpdate.SetRepoAllowlist(repos) + } + + // drop specified repositories from the allowlist + if len(c.ScheduleAllowlistDropRepos) > 0 { + newRepos := []string{} + + for _, r := range sUpdate.GetScheduleAllowlist() { + if !slices.Contains(c.ScheduleAllowlistDropRepos, r) { + newRepos = append(newRepos, r) + } + } + + sUpdate.SetScheduleAllowlist(newRepos) + } + + // add specified repositories to the allowlist + if len(c.ScheduleAllowlistAddRepos) > 0 { + repos := sUpdate.GetScheduleAllowlist() + + for _, r := range c.ScheduleAllowlistAddRepos { + if !slices.Contains(repos, r) { + repos = append(repos, r) + } + } + + sUpdate.SetScheduleAllowlist(repos) + } + + // manual overrides (from file) + if c.RepoAllowlist != nil { + sUpdate.RepoAllowlist = c.RepoAllowlist + } + + if c.ScheduleAllowlist != nil { + sUpdate.ScheduleAllowlist = c.ScheduleAllowlist + } + + if c.Queue.Routes != nil { + sUpdate.Queue.Routes = c.Queue.Routes + } + + logrus.Trace("updating settings") + + // send API call to modify settings + sUpdated, _, err := client.Admin.Settings.Update(sUpdate) + if err != nil { + return err + } + + // handle the output based off the provided configuration + switch c.Output { + case output.DriverDump: + // output in dump format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Dump + return output.Dump(sUpdated) + case output.DriverJSON: + // output in JSON format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#JSON + return output.JSON(sUpdated) + case output.DriverSpew: + // output in spew format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Spew + return output.Spew(sUpdated) + case output.DriverYAML: + // output in YAML format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#YAML + return output.YAML(sUpdated) + default: + // output in stdout format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Stdout + return output.Stdout(sUpdated) + } +} + +// UpdateFromFile updates from a file based on the provided configuration. +func (c *Config) UpdateFromFile(client *vela.Client) error { + logrus.Debug("executing update from file for platform settings configuration") + + // capture absolute path to file + path, err := filepath.Abs(c.File) + if err != nil { + return err + } + + logrus.Tracef("reading platform settings contents from %s", path) + + // read contents of file + contents, err := os.ReadFile(path) + if err != nil { + return err + } + + input := yaml.NewDecoder(bytes.NewReader(contents)) + + f := new(ConfigFile) + + for input.Decode(f) == nil { + if f.Platform == nil { + return errors.New("invalid input, expected key 'platform'") + } + + s := &Config{ + Action: internal.ActionUpdate, + Output: c.Output, + Compiler: Compiler{}, + Queue: Queue{}, + } + + if f.Platform.RepoAllowlist != nil { + s.RepoAllowlist = f.Platform.RepoAllowlist + } + + if f.Platform.ScheduleAllowlist != nil { + s.ScheduleAllowlist = f.Platform.ScheduleAllowlist + } + + // update values if set + if f.Compiler != nil { + if f.Compiler.CloneImage != nil { + s.Compiler.CloneImage = vela.String(f.Compiler.GetCloneImage()) + } + + if f.Compiler.TemplateDepth != nil { + s.Compiler.TemplateDepth = vela.Int(f.Compiler.GetTemplateDepth()) + } + + if f.Compiler.StarlarkExecLimit != nil { + s.Compiler.StarlarkExecLimit = vela.UInt64(f.Compiler.GetStarlarkExecLimit()) + } + } + + if f.Queue != nil { + if f.Queue.Routes != nil { + s.Queue.Routes = f.Queue.Routes + } + } + + err = s.Validate() + if err != nil { + return err + } + + err = s.Update(client) + if err != nil { + return err + } + } + + return nil +} diff --git a/action/settings/update_test.go b/action/settings/update_test.go new file mode 100644 index 00000000..9dd58f6a --- /dev/null +++ b/action/settings/update_test.go @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "net/http/httptest" + "testing" + + "github.com/go-vela/sdk-go/vela" + "github.com/go-vela/server/mock/server" +) + +func TestSettings_Config_Update(t *testing.T) { + // setup test server + s := httptest.NewServer(server.FakeHandler()) + + // create a vela client + client, err := vela.NewClient(s.URL, "vela", nil) + if err != nil { + t.Errorf("unable to create client: %v", err) + } + + // setup tests + tests := []struct { + failure bool + config *Config + }{ + { + failure: false, + config: &Config{ + Action: "update", + Output: "", + + Queue: Queue{ + Routes: &[]string{"test"}, + }, + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + Output: "", + Compiler: Compiler{ + CloneImage: vela.String("test"), + TemplateDepth: vela.Int(1), + StarlarkExecLimit: vela.UInt64(1), + }, + }, + }, + } + + // run tests + for _, test := range tests { + err := test.config.Update(client) + + if test.failure { + if err == nil { + t.Errorf("Update should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("Update returned err: %v", err) + } + } +} + +func TestSettings_Config_UpdateFromFile(t *testing.T) { + // setup test server + s := httptest.NewServer(server.FakeHandler()) + + // create a vela client + client, err := vela.NewClient(s.URL, "vela", nil) + if err != nil { + t.Errorf("unable to create client: %v", err) + } + + // setup tests + tests := []struct { + failure bool + config *Config + }{ + { + failure: false, + config: &Config{ + Action: "update", + File: "testdata/all.yml", + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + File: "testdata/platform.yml", + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + File: "testdata/compiler.yml", + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + File: "testdata/queue.yml", + Output: "", + }, + }, + { + failure: true, + config: &Config{ + Action: "update", + File: "testdata/noplatform.yml", + Output: "", + }, + }, + } + + // run tests + for _, test := range tests { + err := test.config.UpdateFromFile(client) + + if test.failure { + if err == nil { + t.Errorf("UpdateFromFile should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("UpdateFromFile returned err: %v", err) + } + } +} diff --git a/action/settings/validate.go b/action/settings/validate.go new file mode 100644 index 00000000..01124278 --- /dev/null +++ b/action/settings/validate.go @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "github.com/sirupsen/logrus" +) + +// Validate verifies the configuration provided. +func (c *Config) Validate() error { + logrus.Debug("validating settings configuration") + + return nil +} diff --git a/action/settings/validate_test.go b/action/settings/validate_test.go new file mode 100644 index 00000000..9eb3c51c --- /dev/null +++ b/action/settings/validate_test.go @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "testing" + + "github.com/go-vela/sdk-go/vela" +) + +func TestSettings_Config_Validate(t *testing.T) { + // setup tests + tests := []struct { + failure bool + config *Config + }{ + { + failure: false, + config: &Config{ + Action: "update", + Compiler: Compiler{ + CloneImage: vela.String("test"), + }, + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + Compiler: Compiler{ + TemplateDepth: vela.Int(1), + }, + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + Compiler: Compiler{ + StarlarkExecLimit: vela.UInt64(1), + }, + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + Queue: Queue{ + Routes: &[]string{"test"}, + }, + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + Queue: Queue{ + Routes: vela.Strings([]string{"test"}), + }, + Output: "", + }, + }, + } + + // run tests + for _, test := range tests { + err := test.config.Validate() + + if test.failure { + if err == nil { + t.Errorf("Validate should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("Validate returned err: %v", err) + } + } +} diff --git a/action/settings/view.go b/action/settings/view.go new file mode 100644 index 00000000..146f2051 --- /dev/null +++ b/action/settings/view.go @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "fmt" + + "github.com/sirupsen/logrus" + + "github.com/go-vela/cli/internal/output" + "github.com/go-vela/sdk-go/vela" +) + +// View inspects settings based off the provided configuration. +func (c *Config) View(client *vela.Client) error { + logrus.Debug("executing view for settings configuration") + + logrus.Trace("inspecting settings") + + response, _, err := client.Admin.Settings.Get() + if err != nil { + return fmt.Errorf("unable to retrieve settings: %w", err) + } + + // handle the output based off the provided configuration + switch c.Output { + case output.DriverDump: + // output in dump format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Dump + return output.Dump(response) + case output.DriverJSON: + // output in JSON format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#JSON + return output.JSON(response) + case output.DriverSpew: + // output in spew format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Spew + return output.Spew(response) + case output.DriverYAML: + // output in YAML format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#YAML + return output.YAML(response) + default: + // output in stdout format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Stdout + return output.Stdout(response) + } +} diff --git a/action/settings/view_test.go b/action/settings/view_test.go new file mode 100644 index 00000000..6e796afb --- /dev/null +++ b/action/settings/view_test.go @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "net/http/httptest" + "testing" + + "github.com/go-vela/sdk-go/vela" + "github.com/go-vela/server/mock/server" +) + +func TestSettings_Config_View(t *testing.T) { + // setup test server + s := httptest.NewServer(server.FakeHandler()) + + // create a vela client + client, err := vela.NewClient(s.URL, "vela", nil) + if err != nil { + t.Errorf("unable to create client: %v", err) + } + + // setup tests + tests := []struct { + failure bool + config *Config + }{ + { + failure: false, + config: &Config{ + Action: "view", + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "view", + Output: "dump", + }, + }, + { + failure: false, + config: &Config{ + Action: "view", + Output: "json", + }, + }, + { + failure: false, + config: &Config{ + Action: "view", + Output: "spew", + }, + }, + { + failure: false, + config: &Config{ + Action: "view", + Output: "yaml", + }, + }, + { + failure: false, + config: &Config{ + Action: "view", + Output: "yaml", + }, + }, + } + + // run tests + for _, test := range tests { + err := test.config.View(client) + + if test.failure { + if err == nil { + t.Errorf("View should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("View returned err: %v", err) + } + } +} diff --git a/cmd/vela-cli/update.go b/cmd/vela-cli/update.go index 40f1eaf6..ef6fc5d4 100644 --- a/cmd/vela-cli/update.go +++ b/cmd/vela-cli/update.go @@ -10,6 +10,7 @@ import ( "github.com/go-vela/cli/command/repo" "github.com/go-vela/cli/command/schedule" "github.com/go-vela/cli/command/secret" + "github.com/go-vela/cli/command/settings" "github.com/go-vela/cli/command/worker" ) @@ -47,6 +48,11 @@ var updateCmds = &cli.Command{ // https://pkg.go.dev/github.com/go-vela/cli/command/secret?tab=doc#CommandUpdate secret.CommandUpdate, + // add the sub command for modifying settings + // + // https://pkg.go.dev/github.com/go-vela/cli/command/settings?tab=doc#CommandUpdate + settings.CommandUpdate, + // add the sub command for modifying a worker // // https://pkg.go.dev/github.com/go-vela/cli/command/worker?tab=doc#CommandUpdate diff --git a/cmd/vela-cli/view.go b/cmd/vela-cli/view.go index eb98a328..4fa61076 100644 --- a/cmd/vela-cli/view.go +++ b/cmd/vela-cli/view.go @@ -16,6 +16,7 @@ import ( "github.com/go-vela/cli/command/schedule" "github.com/go-vela/cli/command/secret" "github.com/go-vela/cli/command/service" + "github.com/go-vela/cli/command/settings" "github.com/go-vela/cli/command/step" "github.com/go-vela/cli/command/worker" ) @@ -84,6 +85,11 @@ var viewCmds = &cli.Command{ // https://pkg.go.dev/github.com/go-vela/cli/command/service?tab=doc#CommandView service.CommandView, + // add the sub command for viewing settings + // + // https://pkg.go.dev/github.com/go-vela/cli/command/settings?tab=doc#CommandView + settings.CommandView, + // add the sub command for viewing a step // // https://pkg.go.dev/github.com/go-vela/cli/command/step?tab=doc#CommandView diff --git a/command/pipeline/exec.go b/command/pipeline/exec.go index f6f2221a..dd2bddcd 100644 --- a/command/pipeline/exec.go +++ b/command/pipeline/exec.go @@ -310,22 +310,22 @@ func exec(c *cli.Context) error { // create a compiler client // // https://godoc.org/github.com/go-vela/server/compiler/native#New - client, err := native.New(c) + client, err := native.FromCLIContext(c) if err != nil { return err } // set starlark exec limit - client.StarlarkExecLimit = c.Uint64("compiler-starlark-exec-limit") + client.SetStarlarkExecLimit(c.Uint64("compiler-starlark-exec-limit")) // set when user is sourcing templates from local machine if len(p.TemplateFiles) != 0 { client.WithLocalTemplates(p.TemplateFiles) - client.TemplateDepth = util.MinInt(c.Int("max-template-depth"), 10) + client.SetTemplateDepth(util.MinInt(c.Int("max-template-depth"), 10)) } else { // set max template depth to minimum of 5 and provided value if local templates are not provided. // This prevents users from spamming SCM - client.TemplateDepth = util.MinInt(c.Int("max-template-depth"), 5) + client.SetTemplateDepth(util.MinInt(c.Int("max-template-depth"), 5)) logrus.Debugf("no local template files provided, setting max template depth to %d", client.TemplateDepth) } diff --git a/command/pipeline/validate.go b/command/pipeline/validate.go index a5aac5b5..2bc7c9ae 100644 --- a/command/pipeline/validate.go +++ b/command/pipeline/validate.go @@ -241,22 +241,22 @@ func validate(c *cli.Context) error { // create a compiler client // // https://godoc.org/github.com/go-vela/server/compiler/native#New - client, err := native.New(c) + client, err := native.FromCLIContext(c) if err != nil { return err } // set starlark exec limit - client.StarlarkExecLimit = c.Uint64("compiler-starlark-exec-limit") + client.SetStarlarkExecLimit(c.Uint64("compiler-starlark-exec-limit")) // set when user is sourcing templates from local machine if len(p.TemplateFiles) != 0 { client.WithLocalTemplates(p.TemplateFiles) - client.TemplateDepth = c.Int("max-template-depth") + client.SetTemplateDepth(c.Int("max-template-depth")) } else { // set max template depth to minimum of 5 and provided value if local templates are not provided. // This prevents users from spamming SCM - client.TemplateDepth = util.MinInt(c.Int("max-template-depth"), 5) + client.SetTemplateDepth(util.MinInt(c.Int("max-template-depth"), 5)) logrus.Debugf("no local template files provided, setting max template depth to %d", client.TemplateDepth) } diff --git a/command/pipeline/validate_test.go b/command/pipeline/validate_test.go index da4a052c..ab2171ac 100644 --- a/command/pipeline/validate_test.go +++ b/command/pipeline/validate_test.go @@ -22,6 +22,7 @@ func TestPipeline_Validate(t *testing.T) { authSet.String("api.addr", s.URL, "doc") authSet.String("api.token.access", test.TestTokenGood, "doc") authSet.String("api.token.refresh", "superSecretRefreshToken", "doc") + authSet.String("clone-image", "target/vela-git:latest", "doc") fullSet := flag.NewFlagSet("test", 0) fullSet.String("api.addr", s.URL, "doc") @@ -40,11 +41,13 @@ func TestPipeline_Validate(t *testing.T) { fullSet.String("file-changeset", "README.md,main,go", "doc") fullSet.Uint64("compiler-starlark-exec-limit", 10000, "doc") fullSet.Bool("remote", true, "doc") + fullSet.String("clone-image", "target/vela-git:latest", "doc") // setup flags localSet := flag.NewFlagSet("test", 0) localSet.String("file", "generate.yml", "doc") localSet.String("path", "../../action/pipeline/testdata", "doc") + localSet.String("clone-image", "target/vela-git:latest", "doc") // setup tests tests := []struct { diff --git a/command/settings/doc.go b/command/settings/doc.go new file mode 100644 index 00000000..af9fbab2 --- /dev/null +++ b/command/settings/doc.go @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 + +// Package settings provides the defined settings CLI command for Vela. +// +// Usage: +// +// import "github.com/go-vela/cli/command/settings" +package settings diff --git a/command/settings/update.go b/command/settings/update.go new file mode 100644 index 00000000..2bfd00c4 --- /dev/null +++ b/command/settings/update.go @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "fmt" + + "github.com/urfave/cli/v2" + + "github.com/go-vela/cli/action" + "github.com/go-vela/cli/action/settings" + "github.com/go-vela/cli/internal" + "github.com/go-vela/cli/internal/client" + "github.com/go-vela/sdk-go/vela" +) + +const ( + CompilerCloneImageKey = "compiler.clone-image" + CompilerTemplateDepthKey = "compiler.template-depth" + CompilerStarlarkExecLimitKey = "compiler.starlark-exec-limit" + QueueRouteAddKey = "queue.add-route" + QueueRouteDropKey = "queue.drop-route" + RepoAllowlistAddKey = "add-repo" + RepoAllowlistDropKey = "drop-repo" + ScheduleAllowAddlistKey = "add-schedule" + ScheduleAllowDroplistKey = "drop-schedule" +) + +// CommandUpdate defines the command for modifying a settings. +var CommandUpdate = &cli.Command{ + Name: "settings", + Description: "(Platform Admin Only) Use this command to update settings.", + Usage: "Update settings from the provided configuration", + Action: update, + Flags: []cli.Flag{ + + // Queue Flags + + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_QUEUE_ADD_ROUTES", "QUEUE_ADD_ROUTES"}, + Name: QueueRouteAddKey, + Aliases: []string{"queue-route", "add-route", "routes", "route", "r"}, + Usage: "list of routes to add to the queue", + }, + + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_QUEUE_DROP_ROUTES", "QUEUE_DROP_ROUTES"}, + Name: QueueRouteDropKey, + Aliases: []string{"drop-route"}, + Usage: "list of routes to drop from the queue", + }, + + // Compiler Flags + + &cli.IntFlag{ + EnvVars: []string{"VELA_COMPILER_TEMPLATE_DEPTH", "VELA_TEMPLATE_DEPTH", "TEMPLATE_DEPTH"}, + Name: CompilerTemplateDepthKey, + Aliases: []string{"templates", "template-depth", "templatedepth", "td"}, + Usage: "max template depth for the compiler", + }, + + &cli.StringFlag{ + EnvVars: []string{"VELA_COMPILER_CLONE_IMAGE", "COMPILER_CLONE_IMAGE"}, + Name: CompilerCloneImageKey, + Aliases: []string{"clone", "clone-image", "cloneimage", "ci"}, + Usage: "image used to clone the repository for the compiler", + }, + + &cli.IntFlag{ + EnvVars: []string{"VELA_COMPILER_STARLARK_EXEC_LIMIT", "COMPILER_STARLARK_EXEC_LIMIT"}, + Name: CompilerStarlarkExecLimitKey, + Aliases: []string{"starlark-exec-limit", "starklark-limit", "starlarklimit", "sel"}, + Usage: "max starlark execution limit for the compiler", + }, + + // Misc Flags + + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_REPO_ALLOWLIST_ADD_REPOS", "REPO_ALLOWLIST_ADD_REPOS"}, + Name: RepoAllowlistAddKey, + Aliases: []string{"repo", "repos", "ral"}, + Usage: "the list of repositories to add to the list of all those permitted to use Vela", + }, + + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_REPO_ALLOWLIST_DROP_REPOS", "REPO_ALLOWLIST_DROP_REPOS"}, + Name: RepoAllowlistDropKey, + Usage: "the list of repositories to drop from the list of all those permitted to use Vela", + }, + + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_SCHEDULE_ALLOWLIST_ADD_REPOS", "SCHEDULE_ALLOWLIST_ADD_REPOS"}, + Name: ScheduleAllowAddlistKey, + Aliases: []string{"schedule", "schedules", "sal"}, + Usage: "the list of repositories to add to the list of all those permitted to use schedules in Vela", + }, + + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_SCHEDULE_ALLOWLIST_DROP_REPOS", "SCHEDULE_ALLOWLIST_DROP_REPOS"}, + Name: ScheduleAllowDroplistKey, + Usage: "the list of repositories to drop from the list of all those permitted to use schedules in Vela", + }, + + &cli.StringFlag{ + EnvVars: []string{"VELA_FILE", "SETTINGS_FILE"}, + Name: "file", + Aliases: []string{"f"}, + Usage: "provide a file to update settings", + }, + + // Output Flags + + &cli.StringFlag{ + EnvVars: []string{"VELA_OUTPUT", "SETTINGS_OUTPUT"}, + Name: internal.FlagOutput, + Aliases: []string{"op"}, + Usage: "format the output in json, spew or yaml", + Value: "yaml", + }, + }, + CustomHelpTemplate: fmt.Sprintf(`%s +EXAMPLES: + 1. Update settings to change the compiler clone image to target/vela-git:latest. + $ {{.HelpName}} --compiler.clone-image target/vela-git:latest + 2. Update settings to change the compiler template depth to 2. + $ {{.HelpName}} --compiler.template-depth 2 + 3. Update settings to change the compiler starlark exec limit to 5. + $ {{.HelpName}} --compiler.starlark-exec-limit 5 + 4. Update settings with additional queue routes. + $ {{.HelpName}} --queue.add-route large --queue.add-route small + 5. Update settings by dropping queue routes. + $ {{.HelpName}} --queue.drop-route large --queue.drop-route small + 6. Update settings with additional repos permitted to use Vela (patterns containing * wildcards must be wrapped in quotes on the commandline). + $ {{.HelpName}} --add-repo octocat/hello-world --add-repo 'octocat/*' + 7. Update settings with additional repos permitted to use schedules in Vela (patterns containing * wildcards must be wrapped in quotes on the commandline). + $ {{.HelpName}} --add-schedule octocat/hello-world --schedule 'octocat/*' + 8. Update settings from a file. + $ {{.HelpName}} --file settings.yml +DOCUMENTATION: + + https://go-vela.github.io/docs/reference/cli/settings/update/ +`, cli.CommandHelpTemplate), +} + +// helper function to capture the provided input +// and create the object used to modify settings. +func update(c *cli.Context) error { + // load variables from the config file + err := action.Load(c) + if err != nil { + return err + } + + // parse the Vela client from the context + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/client?tab=doc#Parse + client, err := client.Parse(c) + if err != nil { + return err + } + + // create the settings configuration + s := &settings.Config{ + Action: internal.ActionUpdate, + Output: c.String(internal.FlagOutput), + File: c.String("file"), + Queue: settings.Queue{ + AddRoutes: c.StringSlice(QueueRouteAddKey), + DropRoutes: c.StringSlice(QueueRouteDropKey), + }, + Compiler: settings.Compiler{}, + RepoAllowlistAddRepos: c.StringSlice(RepoAllowlistAddKey), + RepoAllowlistDropRepos: c.StringSlice(RepoAllowlistDropKey), + ScheduleAllowlistAddRepos: c.StringSlice(ScheduleAllowAddlistKey), + ScheduleAllowlistDropRepos: c.StringSlice(ScheduleAllowDroplistKey), + } + + // compiler + if c.IsSet(CompilerCloneImageKey) { + s.Compiler.CloneImage = vela.String(c.String(CompilerCloneImageKey)) + } + + if c.IsSet(CompilerTemplateDepthKey) { + s.Compiler.TemplateDepth = vela.Int(c.Int(CompilerTemplateDepthKey)) + } + + if c.IsSet(CompilerStarlarkExecLimitKey) { + s.Compiler.StarlarkExecLimit = vela.UInt64(c.Uint64(CompilerStarlarkExecLimitKey)) + } + + // validate settings configuration + // + // https://pkg.go.dev/github.com/go-vela/cli/action/settings?tab=doc#Config.Validate + err = s.Validate() + if err != nil { + return err + } + + // check if file is provided + if len(s.File) > 0 { + return s.UpdateFromFile(client) + } + + // execute the update call for the settings configuration + // + // https://pkg.go.dev/github.com/go-vela/cli/action/settings?tab=doc#Config.Update + return s.Update(client) +} diff --git a/command/settings/update_test.go b/command/settings/update_test.go new file mode 100644 index 00000000..00e1ff2d --- /dev/null +++ b/command/settings/update_test.go @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "flag" + "net/http/httptest" + "testing" + + "github.com/urfave/cli/v2" + + "github.com/go-vela/cli/test" + "github.com/go-vela/server/mock/server" +) + +func TestSettings_Update(t *testing.T) { + // setup test server + s := httptest.NewServer(server.FakeHandler()) + + // setup flags + fullSet := flag.NewFlagSet("test", 0) + fullSet.String("api.addr", s.URL, "doc") + fullSet.String("api.token.access", test.TestTokenGood, "doc") + fullSet.String("api.token.refresh", "superSecretRefreshToken", "doc") + fullSet.String("output", "json", "doc") + + // setup tests + tests := []struct { + failure bool + set *flag.FlagSet + }{ + { + failure: false, + set: fullSet, + }, + } + + // run tests + for _, test := range tests { + err := update(cli.NewContext(&cli.App{Name: "vela", Version: "v0.0.0"}, test.set, nil)) + + if test.failure { + if err == nil { + t.Errorf("update should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("update returned err: %v", err) + } + } +} diff --git a/command/settings/view.go b/command/settings/view.go new file mode 100644 index 00000000..96a3d7e1 --- /dev/null +++ b/command/settings/view.go @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "fmt" + + "github.com/urfave/cli/v2" + + "github.com/go-vela/cli/action" + "github.com/go-vela/cli/action/settings" + "github.com/go-vela/cli/internal" + "github.com/go-vela/cli/internal/client" +) + +// CommandView defines the command for inspecting the platform settings record. +var CommandView = &cli.Command{ + Name: "settings", + Description: "Use this command to view platform settings.", + Usage: "View details for platform settings", + Aliases: []string{"platform"}, + Action: view, + Flags: []cli.Flag{ + + // Output Flags + + &cli.StringFlag{ + EnvVars: []string{"VELA_OUTPUT", "SETTINGS_OUTPUT"}, + Name: internal.FlagOutput, + Aliases: []string{"op"}, + Usage: "format the output in json, spew or yaml", + Value: "yaml", + }, + }, + CustomHelpTemplate: fmt.Sprintf(`%s +EXAMPLES: + 1. View platform settings. + $ {{.HelpName}} + +DOCUMENTATION: + + https://go-vela.github.io/docs/reference/cli/settings/view/ +`, cli.CommandHelpTemplate), +} + +// helper function to capture the provided input +// and create the object used to inspect. +func view(c *cli.Context) error { + // load variables from the config file + err := action.Load(c) + if err != nil { + return err + } + + // parse the Vela client from the context + client, err := client.Parse(c) + if err != nil { + return err + } + + // create the configuration + s := &settings.Config{ + Action: internal.ActionView, + Output: c.String(internal.FlagOutput), + } + + // validate settings configuration + // + // https://pkg.go.dev/github.com/go-vela/cli/action/settings?tab=doc#Config.Validate + err = s.Validate() + if err != nil { + return err + } + + // execute the view call for the settings configuration + // + // https://pkg.go.dev/github.com/go-vela/cli/action/settings?tab=doc#Config.View + return s.View(client) +} diff --git a/command/settings/view_test.go b/command/settings/view_test.go new file mode 100644 index 00000000..bad7743b --- /dev/null +++ b/command/settings/view_test.go @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 + +package settings + +import ( + "flag" + "net/http/httptest" + "testing" + + "github.com/urfave/cli/v2" + + "github.com/go-vela/cli/test" + "github.com/go-vela/server/mock/server" +) + +func TestSettings_View(t *testing.T) { + // setup test server + s := httptest.NewServer(server.FakeHandler()) + + // setup flags + fullSet := flag.NewFlagSet("test", 0) + fullSet.String("api.addr", s.URL, "doc") + fullSet.String("api.token.access", test.TestTokenGood, "doc") + fullSet.String("api.token.refresh", "superSecretRefreshToken", "doc") + fullSet.String("output", "json", "doc") + + // setup tests + tests := []struct { + failure bool + set *flag.FlagSet + }{ + { + failure: false, + set: fullSet, + }, + } + + // run tests + for _, test := range tests { + err := view(cli.NewContext(&cli.App{Name: "vela", Version: "v0.0.0"}, test.set, nil)) + + if test.failure { + if err == nil { + t.Errorf("view should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("view returned err: %v", err) + } + } +} diff --git a/go.mod b/go.mod index 70c752d9..eaa6d09c 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,8 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/gin-gonic/gin v1.9.1 github.com/go-git/go-git/v5 v5.11.0 - github.com/go-vela/sdk-go v0.23.3-0.20240508193030-1cd2e5cf3dbd - github.com/go-vela/server v0.23.4-0.20240508133721-300ca456e3bb + github.com/go-vela/sdk-go v0.23.3-0.20240513192330-1d75672772e6 + github.com/go-vela/server v0.23.4-0.20240513143405-93571138ad3f github.com/go-vela/types v0.23.4-0.20240417135026-fb4a95c30338 github.com/go-vela/worker v0.23.3-0.20240424172515-3d4399807a4b github.com/golang-jwt/jwt/v5 v5.2.1 @@ -25,7 +25,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) -require gopkg.in/yaml.v2 v2.4.0 // indirect +require gopkg.in/yaml.v2 v2.4.0 require ( dario.cat/mergo v1.0.0 // indirect @@ -46,7 +46,7 @@ require ( github.com/coreos/go-semver v0.3.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/distribution/reference v0.5.0 // indirect + github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v26.0.0+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect diff --git a/go.sum b/go.sum index 5af7129f..865a8d5d 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxG github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU= github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= @@ -123,10 +123,10 @@ github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/go-vela/sdk-go v0.23.3-0.20240508193030-1cd2e5cf3dbd h1:69FJDdgtnu+jame1Mcu/KCQ51OuOMpKYNoZTvuXvZbc= -github.com/go-vela/sdk-go v0.23.3-0.20240508193030-1cd2e5cf3dbd/go.mod h1:382f+z7TrcBk+F92US53M+l490mGiU93/h86zGqMU94= -github.com/go-vela/server v0.23.4-0.20240508133721-300ca456e3bb h1:nzDitT5zNk5k49n/oEESPwL8xwLWf5iLLJDJkT3Vwik= -github.com/go-vela/server v0.23.4-0.20240508133721-300ca456e3bb/go.mod h1:2KcNYX+DfNH/aWwu0pu89Gj9+wAm3S70VMy53/LMZjs= +github.com/go-vela/sdk-go v0.23.3-0.20240513192330-1d75672772e6 h1:Iyn34V6BE92LOhobcnmYeBtDMiaV+OEUVDFx9uZFjgw= +github.com/go-vela/sdk-go v0.23.3-0.20240513192330-1d75672772e6/go.mod h1:0k5Xv6h+ZdO08+dHmTDqrXTKJFR4tTI+wVLX3Qc+npw= +github.com/go-vela/server v0.23.4-0.20240513143405-93571138ad3f h1:d2J/3+wCmP9gKjGZPvn2A4eQuvqz3Occw+B361ByzpI= +github.com/go-vela/server v0.23.4-0.20240513143405-93571138ad3f/go.mod h1:tnymHBBZZFdiVYlXNg4AG87F7iWChFiIqI9Q+zLD9YY= github.com/go-vela/types v0.23.4-0.20240417135026-fb4a95c30338 h1:I0v47dOdAvjX7lOFN4s28uONChmluD6TNgFL1hpav60= github.com/go-vela/types v0.23.4-0.20240417135026-fb4a95c30338/go.mod h1:vISsYDdjz9RPEK6qZ+MxtrdZEjTVU4K30NomB3826u8= github.com/go-vela/worker v0.23.3-0.20240424172515-3d4399807a4b h1:BAfnoo7pqj7girJPYloKybqehjf3uKT3p9n/aMWMQTU=