diff --git a/action/dashboard/add.go b/action/dashboard/add.go new file mode 100644 index 00000000..cb98f6cb --- /dev/null +++ b/action/dashboard/add.go @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "github.com/sirupsen/logrus" + + "github.com/go-vela/sdk-go/vela" + api "github.com/go-vela/server/api/types" +) + +// Add creates a dashboard based off the provided configuration. +func (c *Config) Add(client *vela.Client) error { + logrus.Debug("executing add for dashboard configuration") + + dashRepos := []*api.DashboardRepo{} + dashAdmins := []*api.User{} + + // generate dashboard repos + for _, r := range c.AddRepos { + repo := new(api.DashboardRepo) + repo.SetName(r) + + if len(c.Branches) > 0 { + repo.SetBranches(c.Branches) + } + + if len(c.Events) > 0 { + repo.SetEvents(c.Events) + } + + dashRepos = append(dashRepos, repo) + } + + // generate dashboard admins + for _, u := range c.AddAdmins { + admin := new(api.User) + admin.SetName(u) + + dashAdmins = append(dashAdmins, admin) + } + + // create the dashboard object + d := &api.Dashboard{ + Name: vela.String(c.Name), + Repos: &dashRepos, + Admins: &dashAdmins, + } + + logrus.Tracef("adding dashboard %s", c.Name) + + // send API call to add a dashboard + dashboard, _, err := client.Dashboard.Add(d) + if err != nil { + return err + } + + return outputDashboard(dashboard, c) +} diff --git a/action/dashboard/add_test.go b/action/dashboard/add_test.go new file mode 100644 index 00000000..632bd638 --- /dev/null +++ b/action/dashboard/add_test.go @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "net/http/httptest" + "testing" + + "github.com/go-vela/sdk-go/vela" + "github.com/go-vela/server/mock/server" +) + +func TestDashboard_Config_Add(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: "add", + Name: "my-dashboard", + AddRepos: []string{"github/octocat"}, + AddAdmins: []string{"octocat"}, + Branches: []string{"main", "dev"}, + Events: []string{"push", "tag"}, + Output: "json", + }, + }, + { + failure: false, + config: &Config{ + Action: "add", + Name: "my-dashboard", + }, + }, + } + + // run tests + for _, test := range tests { + err := test.config.Add(client) + + if test.failure { + if err == nil { + t.Errorf("Add should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("Add returned err: %v", err) + } + } +} diff --git a/action/dashboard/dashboard.go b/action/dashboard/dashboard.go new file mode 100644 index 00000000..ac35e77b --- /dev/null +++ b/action/dashboard/dashboard.go @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +// Config represents the configuration necessary +// to perform dashboard related requests with Vela. +type Config struct { + Action string + Name string + ID string + AddRepos []string + TargetRepos []string + DropRepos []string + Branches []string + Events []string + AddAdmins []string + DropAdmins []string + Full bool + Output string +} diff --git a/action/dashboard/doc.go b/action/dashboard/doc.go new file mode 100644 index 00000000..9dd465a7 --- /dev/null +++ b/action/dashboard/doc.go @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 + +// Package dashboard provides the defined CLI dashboard actions for Vela. +// +// Usage: +// +// import "github.com/go-vela/cli/action/dashboard" +package dashboard diff --git a/action/dashboard/get.go b/action/dashboard/get.go new file mode 100644 index 00000000..61f9e56f --- /dev/null +++ b/action/dashboard/get.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "github.com/sirupsen/logrus" + + "github.com/go-vela/sdk-go/vela" + api "github.com/go-vela/server/api/types" +) + +// Get captures a list of dashboards based off the provided configuration. +func (c *Config) Get(client *vela.Client) error { + logrus.Debug("executing get for dashboard configuration") + + // send API call to capture a list of dashboards + dashCards, _, err := client.Dashboard.GetAllUser() + if err != nil { + return err + } + + if c.Full { + err = outputDashboard(dashCards, c) + } else { + dashboards := []*api.Dashboard{} + + for _, d := range *dashCards { + dashboards = append(dashboards, d.Dashboard) + } + + err = outputDashboard(dashboards, c) + } + + return err +} diff --git a/action/dashboard/get_test.go b/action/dashboard/get_test.go new file mode 100644 index 00000000..86431557 --- /dev/null +++ b/action/dashboard/get_test.go @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "net/http/httptest" + "testing" + + "github.com/go-vela/sdk-go/vela" + "github.com/go-vela/server/mock/server" +) + +func TestDashboard_Config_Get(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: "get", + Full: true, + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "get", + Full: false, + Output: "dump", + }, + }, + } + + // run tests + for _, test := range tests { + err := test.config.Get(client) + + if test.failure { + if err == nil { + t.Errorf("Get should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("Get returned err: %v", err) + } + } +} diff --git a/action/dashboard/update.go b/action/dashboard/update.go new file mode 100644 index 00000000..718ea55b --- /dev/null +++ b/action/dashboard/update.go @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "fmt" + "slices" + + "github.com/sirupsen/logrus" + + "github.com/go-vela/sdk-go/vela" + api "github.com/go-vela/server/api/types" + "github.com/go-vela/server/constants" +) + +// Update modifies a dashboard based off the provided configuration. +func (c *Config) Update(client *vela.Client) error { + logrus.Debug("executing update for dashboard configuration") + + dashCard, _, err := client.Dashboard.Get(c.ID) + if err != nil { + return err + } + + // pull dashboard metadata from the API response + dashboard := dashCard.Dashboard + + // drop specified repositories from the dashboard + if len(c.DropRepos) > 0 { + newRepos := []*api.DashboardRepo{} + + for _, r := range dashboard.GetRepos() { + if !slices.Contains(c.DropRepos, r.GetName()) { + newRepos = append(newRepos, r) + } + } + + dashboard.SetRepos(newRepos) + } + + // add specified repositories from the dashboard + if len(c.AddRepos) > 0 { + repos := dashboard.GetRepos() + + for _, r := range c.AddRepos { + repo := new(api.DashboardRepo) + repo.SetName(r) + + if len(c.Branches) > 0 { + repo.SetBranches(c.Branches) + } + + if len(c.Events) > 0 { + repo.SetEvents(c.Events) + } + + repos = append(repos, repo) + } + + dashboard.SetRepos(repos) + } + + // update specified repositories from the dashboard + if len(c.TargetRepos) > 0 { + repos := dashboard.GetRepos() + for _, r := range repos { + if slices.Contains(c.TargetRepos, r.GetName()) { + if len(c.Branches) > 0 { + r.SetBranches(c.Branches) + } + + if len(c.Events) > 0 { + r.SetEvents(c.Events) + } + } + } + + dashboard.SetRepos(repos) + } + + // drop specified admins from the dashboard + if len(c.DropAdmins) > 0 { + newAdmins := []*api.User{} + + for _, a := range dashboard.GetAdmins() { + if !slices.Contains(c.DropAdmins, a.GetName()) { + newAdmins = append(newAdmins, a) + } + } + + dashboard.SetAdmins(newAdmins) + } + + // add specified admins from the dashboard + if len(c.AddAdmins) > 0 { + admins := dashboard.GetAdmins() + + for _, a := range c.AddAdmins { + admin := new(api.User) + admin.SetName(a) + + admins = append(admins, admin) + } + + dashboard.SetAdmins(admins) + } + + // update the name of the dashboard + if len(c.Name) > 0 { + dashboard.SetName(c.Name) + } + + // verify the number of repositories for a dashboard + if len(dashboard.GetRepos()) > constants.DashboardRepoLimit { + return fmt.Errorf("maximum number of repositories for a dashboard is %d", constants.DashboardRepoLimit) + } + + // send API call to modify a dashboard + dashboard, _, err = client.Dashboard.Update(dashboard) + if err != nil { + return err + } + + return outputDashboard(dashboard, c) +} diff --git a/action/dashboard/update_test.go b/action/dashboard/update_test.go new file mode 100644 index 00000000..ce8b46c6 --- /dev/null +++ b/action/dashboard/update_test.go @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "net/http/httptest" + "testing" + + "github.com/go-vela/sdk-go/vela" + "github.com/go-vela/server/mock/server" +) + +func TestDashboard_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", + ID: "c8da1302-07d6-11ea-882f-4893bca275b8", + Name: "my-dashboard", + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + ID: "c8da1302-07d6-11ea-882f-4893bca275b8", + AddRepos: []string{"github/octocat"}, + AddAdmins: []string{"octocat"}, + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + ID: "c8da1302-07d6-11ea-882f-4893bca275b8", + DropRepos: []string{"github/octocat"}, + DropAdmins: []string{"octocat"}, + }, + }, + { + failure: false, + config: &Config{ + Action: "update", + ID: "c8da1302-07d6-11ea-882f-4893bca275b8", + Branches: []string{"main", "dev"}, + Events: []string{"push", "tag"}, + TargetRepos: []string{"github/octocat"}, + Output: "json", + }, + }, + { + failure: true, + config: &Config{ + Action: "update", + ID: "c8da1302-07d6-11ea-882f-4893bca275b8", + AddRepos: []string{"github/octocat", "github/octocat", "github/octocat", "github/octocat", "github/octocat", "github/octocat", "github/octocat", "github/octocat", "github/octocat", "github/octocat", "github/octocat"}, + }, + }, + } + + // 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) + } + } +} diff --git a/action/dashboard/validate.go b/action/dashboard/validate.go new file mode 100644 index 00000000..41b77ae5 --- /dev/null +++ b/action/dashboard/validate.go @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "fmt" + + "github.com/sirupsen/logrus" + + "github.com/go-vela/server/constants" +) + +// Validate verifies the configuration provided. +func (c *Config) Validate() error { + logrus.Debug("validating dashboard configuration") + + if c.Action == "add" { + // check if dashboard name is set + if len(c.Name) == 0 { + return fmt.Errorf("no dashboard name provided") + } + + if len(c.AddRepos) > constants.DashboardRepoLimit { + return fmt.Errorf("maximum number of repositories for a dashboard is %d", constants.DashboardRepoLimit) + } + } + + // check if dashboard action is update or view + if c.Action == "update" || c.Action == "view" { + // check if dashboard ID is set + if len(c.ID) == 0 { + return fmt.Errorf("no dashboard ID provided") + } + } + + // if the dashboard action is update with target repos + if c.Action == "update" && len(c.TargetRepos) > 0 { + if len(c.Events) == 0 && len(c.Branches) == 0 { + return fmt.Errorf("no events or branches updates provided for target repos") + } + } + + return nil +} diff --git a/action/dashboard/view.go b/action/dashboard/view.go new file mode 100644 index 00000000..925c2409 --- /dev/null +++ b/action/dashboard/view.go @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "github.com/sirupsen/logrus" + + "github.com/go-vela/cli/internal/output" + "github.com/go-vela/sdk-go/vela" +) + +// View inspects a dashboard based off the provided configuration. +func (c *Config) View(client *vela.Client) error { + logrus.Debug("executing view for dashboard configuration") + + // send API call to capture a dashboard + dashCard, _, err := client.Dashboard.Get(c.ID) + if err != nil { + return err + } + + if c.Full { + err = outputDashboard(dashCard, c) + } else { + err = outputDashboard(dashCard.Dashboard, c) + } + + return err +} + +func outputDashboard(dashboard interface{}, c *Config) error { + // handle the output based off the provided configuration + switch c.Output { + case output.DriverDump: + // output the dashboard in dump format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Dump + return output.Dump(dashboard) + case output.DriverJSON: + // output the dashboard in JSON format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#JSON + return output.JSON(dashboard) + case output.DriverSpew: + // output the dashboard in spew format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Spew + return output.Spew(dashboard) + case output.DriverYAML: + // output the dashboard in YAML format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#YAML + return output.YAML(dashboard) + default: + // output the dashboard in stdout format + // + // https://pkg.go.dev/github.com/go-vela/cli/internal/output?tab=doc#Stdout + return output.Stdout(dashboard) + } +} diff --git a/action/dashboard/view_test.go b/action/dashboard/view_test.go new file mode 100644 index 00000000..a11b9fa5 --- /dev/null +++ b/action/dashboard/view_test.go @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "net/http/httptest" + "testing" + + "github.com/go-vela/sdk-go/vela" + "github.com/go-vela/server/mock/server" +) + +func TestDashboard_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", + ID: "c8da1302-07d6-11ea-882f-4893bca275b8", + Full: true, + Output: "", + }, + }, + { + failure: false, + config: &Config{ + Action: "view", + ID: "c8da1302-07d6-11ea-882f-4893bca275b8", + Full: false, + Output: "dump", + }, + }, + } + + // 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/add.go b/cmd/vela-cli/add.go index 7171ebdd..8564da54 100644 --- a/cmd/vela-cli/add.go +++ b/cmd/vela-cli/add.go @@ -5,6 +5,7 @@ package main import ( "github.com/urfave/cli/v2" + "github.com/go-vela/cli/command/dashboard" "github.com/go-vela/cli/command/deployment" "github.com/go-vela/cli/command/repo" "github.com/go-vela/cli/command/schedule" @@ -21,6 +22,10 @@ var addCmds = &cli.Command{ Usage: "Add resources to Vela via subcommands", UseShortOptionHandling: true, Subcommands: []*cli.Command{ + // add the sub command for creating a dashboard + // + // https://pkg.go.dev/github.com/go-vela/cli/command/dashboard?tab=doc#CommandAdd + dashboard.CommandAdd, // add the sub command for creating a deployment // // https://pkg.go.dev/github.com/go-vela/cli/command/deployment?tab=doc#CommandAdd diff --git a/cmd/vela-cli/get.go b/cmd/vela-cli/get.go index 8fca110a..6b0b4c2d 100644 --- a/cmd/vela-cli/get.go +++ b/cmd/vela-cli/get.go @@ -6,6 +6,7 @@ import ( "github.com/urfave/cli/v2" "github.com/go-vela/cli/command/build" + "github.com/go-vela/cli/command/dashboard" "github.com/go-vela/cli/command/deployment" "github.com/go-vela/cli/command/hook" "github.com/go-vela/cli/command/log" @@ -32,6 +33,11 @@ var getCmds = &cli.Command{ // https://pkg.go.dev/github.com/go-vela/cli/command/build?tab=doc#CommandGet build.CommandGet, + // add the sub command for getting a list of user dashboards + // + // https://pkg.go.dev/github.com/go-vela/cli/command/dashboard?tab=doc#CommandGet + dashboard.CommandGet, + // add the sub command for getting a list of deployments // // https://pkg.go.dev/github.com/go-vela/cli/command/deployment?tab=doc#CommandGet diff --git a/cmd/vela-cli/update.go b/cmd/vela-cli/update.go index 5c1e76d7..40f1eaf6 100644 --- a/cmd/vela-cli/update.go +++ b/cmd/vela-cli/update.go @@ -6,6 +6,7 @@ import ( "github.com/urfave/cli/v2" "github.com/go-vela/cli/command/config" + "github.com/go-vela/cli/command/dashboard" "github.com/go-vela/cli/command/repo" "github.com/go-vela/cli/command/schedule" "github.com/go-vela/cli/command/secret" @@ -26,6 +27,11 @@ var updateCmds = &cli.Command{ // https://pkg.go.dev/github.com/go-vela/cli/command/config?tab=doc#CommandUpdate config.CommandUpdate, + // add the sub command for modifying a dashboard + // + // https://pkg.go.dev/github.com/go-vela/cli/command/dashboard?tab=doc#CommandUpdate + dashboard.CommandUpdate, + // add the sub command for modifying a repository // // https://pkg.go.dev/github.com/go-vela/cli/command/repo?tab=doc#CommandUpdate diff --git a/cmd/vela-cli/view.go b/cmd/vela-cli/view.go index 5414481b..eb98a328 100644 --- a/cmd/vela-cli/view.go +++ b/cmd/vela-cli/view.go @@ -7,6 +7,7 @@ import ( "github.com/go-vela/cli/command/build" "github.com/go-vela/cli/command/config" + "github.com/go-vela/cli/command/dashboard" "github.com/go-vela/cli/command/deployment" "github.com/go-vela/cli/command/hook" "github.com/go-vela/cli/command/log" @@ -33,6 +34,11 @@ var viewCmds = &cli.Command{ // https://pkg.go.dev/github.com/go-vela/cli/command/build?tab=doc#CommandView build.CommandView, + // add the sub command for viewing a dashboard + // + // https://pkg.go.dev/github.com/go-vela/cli/command/dashboard?tab=doc#CommandView + dashboard.CommandView, + // add the sub command for viewing a config file // // https://pkg.go.dev/github.com/go-vela/cli/command/config?tab=doc#CommandView diff --git a/command/dashboard/add.go b/command/dashboard/add.go new file mode 100644 index 00000000..00be3986 --- /dev/null +++ b/command/dashboard/add.go @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "fmt" + + "github.com/urfave/cli/v2" + + "github.com/go-vela/cli/action" + "github.com/go-vela/cli/action/dashboard" + "github.com/go-vela/cli/internal" + "github.com/go-vela/cli/internal/client" +) + +// CommandAdd defines the command for creating a dashboard. +var CommandAdd = &cli.Command{ + Name: "dashboard", + Description: "Use this command to add a dashboard.", + Usage: "Add a new dashboard from the provided configuration", + Action: add, + Flags: []cli.Flag{ + + // Dashboard Flags + + &cli.StringFlag{ + EnvVars: []string{"VELA_DASHBOARD_NAME", "DASHBOARD_NAME"}, + Name: "name", + Usage: "provide the name for the dashboard", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_REPOS", "DASHBOARD_REPOS"}, + Name: "repos", + Aliases: []string{"add-repos"}, + Usage: "provide the list of repositories (org/repo) for the dashboard", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_REPOS_BRANCH", "DASHBOARD_REPOS_BRANCH"}, + Name: "branches", + Aliases: []string{"branch"}, + Usage: "filter builds in all repositories by branch", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_REPOS_EVENT", "DASHBOARD_REPOS_EVENT"}, + Name: "events", + Aliases: []string{"event"}, + Usage: "filter builds in all repositories by event", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_ADMINS", "DASHBOARD_ADMINS"}, + Name: "admins", + Usage: "provide the list of admins for the dashboard", + }, + + // Output Flags + + &cli.StringFlag{ + EnvVars: []string{"VELA_OUTPUT", "REPO_OUTPUT"}, + Name: internal.FlagOutput, + Aliases: []string{"op"}, + Usage: "format the output in json, spew or yaml", + }, + }, + CustomHelpTemplate: fmt.Sprintf(`%s +EXAMPLES: + 1. Add a dashboard. + $ {{.HelpName}} --name my-dashboard + 2. Add a dashboard with repositories. + $ {{.HelpName}} --name my-dashboard --repos Org-1/Repo-1,Org-2/Repo-2 + 3. Add a dashboard with repositories filtering builds by pushes to main. + $ {{.HelpName}} --name my-dashboard --repos Org-1/Repo-1,Org-2/Repo-2 --branch main --event push + 4. Add a dashboard with multiple admins. + $ {{.HelpName}} --name my-dashboard --admins JohnDoe,JaneDoe + +DOCUMENTATION: + + https://go-vela.github.io/docs/reference/cli/dashboard/add/ +`, cli.CommandHelpTemplate), +} + +// helper function to capture the provided input +// and create the object used to create a dashboard. +func add(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 dashboard configuration + d := &dashboard.Config{ + Action: internal.ActionAdd, + Name: c.String("name"), + AddRepos: c.StringSlice("repos"), + Branches: c.StringSlice("branches"), + Events: c.StringSlice("events"), + AddAdmins: c.StringSlice("admins"), + Output: c.String(internal.FlagOutput), + } + + // validate dashboard configuration + err = d.Validate() + if err != nil { + return err + } + + // execute the add call for the dashboard configuration + return d.Add(client) +} diff --git a/command/dashboard/add_test.go b/command/dashboard/add_test.go new file mode 100644 index 00000000..9fc5a12e --- /dev/null +++ b/command/dashboard/add_test.go @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +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 TestDashboard_Add(t *testing.T) { + // setup test server + s := httptest.NewServer(server.FakeHandler()) + + // setup flags + authSet := flag.NewFlagSet("test", 0) + authSet.String("api.addr", s.URL, "doc") + authSet.String("api.token.access", test.TestTokenGood, "doc") + authSet.String("api.token.refresh", "superSecretRefreshToken", "doc") + + 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("repos", "Org-1/Repo-1,Org-2/Repo-2", "doc") + fullSet.String("admins", "octocat,octokitty", "doc") + fullSet.String("name", "octo-dashboard", "doc") + fullSet.String("branches", "main,dev", "doc") + fullSet.String("events", "push,tag", "doc") + fullSet.String("output", "json", "doc") + + // setup tests + tests := []struct { + failure bool + set *flag.FlagSet + }{ + { + failure: false, + set: fullSet, + }, + { + failure: true, + set: authSet, + }, + { + failure: true, + set: flag.NewFlagSet("test", 0), + }, + } + + // run tests + for _, test := range tests { + err := add(cli.NewContext(&cli.App{Name: "vela", Version: "v0.0.0"}, test.set, nil)) + + if test.failure { + if err == nil { + t.Errorf("add should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("add returned err: %v", err) + } + } +} diff --git a/command/dashboard/get.go b/command/dashboard/get.go new file mode 100644 index 00000000..b52d611f --- /dev/null +++ b/command/dashboard/get.go @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "fmt" + + "github.com/urfave/cli/v2" + + "github.com/go-vela/cli/action" + "github.com/go-vela/cli/action/dashboard" + "github.com/go-vela/cli/internal" + "github.com/go-vela/cli/internal/client" +) + +// CommandGet defines the command for viewing all user dashboards. +var CommandGet = &cli.Command{ + Name: "dashboard", + Aliases: []string{"dashboards"}, + Description: "Use this command to get user dashboards.", + Usage: "Get user dashboards from the provided configuration", + Action: get, + Flags: []cli.Flag{ + // Output Flags + &cli.BoolFlag{ + EnvVars: []string{"VELA_FULL", "DASHBOARD_FULL"}, + Name: "full", + Usage: "output the repo and build information for the dashboard", + }, + + &cli.StringFlag{ + EnvVars: []string{"VELA_OUTPUT", "DASHBOARD_OUTPUT"}, + Name: internal.FlagOutput, + Aliases: []string{"op"}, + Usage: "format the output in json, spew or yaml", + }, + }, + CustomHelpTemplate: fmt.Sprintf(`%s +EXAMPLES: + 1. Get user dashboards. + $ {{.HelpName}} + 2. Get user dashboards with repo and build information. + $ {{.HelpName}} --full + +DOCUMENTATION: + + https://go-vela.github.io/docs/reference/cli/dashboard/get/ +`, cli.CommandHelpTemplate), +} + +// helper function to capture the provided input +// and create the object used to get user dashboards. +func get(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 dashboard configuration + d := &dashboard.Config{ + Action: internal.ActionGet, + Full: c.Bool("full"), + Output: c.String(internal.FlagOutput), + } + + // validate dashboard configuration + err = d.Validate() + if err != nil { + return err + } + + // execute the get call for the dashboard configuration + return d.Get(client) +} diff --git a/command/dashboard/get_test.go b/command/dashboard/get_test.go new file mode 100644 index 00000000..5c393dad --- /dev/null +++ b/command/dashboard/get_test.go @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +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 TestDashboard_Get(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.Bool("full", true, "doc") + fullSet.String("output", "json", "doc") + + // setup tests + tests := []struct { + failure bool + set *flag.FlagSet + }{ + { + failure: false, + set: fullSet, + }, + { + failure: true, + set: flag.NewFlagSet("test", 0), + }, + } + + // run tests + for _, test := range tests { + err := get(cli.NewContext(&cli.App{Name: "vela", Version: "v0.0.0"}, test.set, nil)) + + if test.failure { + if err == nil { + t.Errorf("get should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("get returned err: %v", err) + } + } +} diff --git a/command/dashboard/update.go b/command/dashboard/update.go new file mode 100644 index 00000000..985a8ad1 --- /dev/null +++ b/command/dashboard/update.go @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "fmt" + + "github.com/urfave/cli/v2" + + "github.com/go-vela/cli/action" + "github.com/go-vela/cli/action/dashboard" + "github.com/go-vela/cli/internal" + "github.com/go-vela/cli/internal/client" +) + +// CommandUpdate defines the command for updating a dashboard. +var CommandUpdate = &cli.Command{ + Name: "dashboard", + Description: "Use this command to update a dashboard.", + Usage: "Update a dashboard from the provided configuration", + Action: update, + Flags: []cli.Flag{ + + // Dashboard Flags + + &cli.StringFlag{ + EnvVars: []string{"VELA_DASHBOARD_ID", "DASHBOARD_ID"}, + Name: "id", + Usage: "provide the uuid for the dashboard", + }, + &cli.StringFlag{ + EnvVars: []string{"VELA_DASHBOARD_NAME", "DASHBOARD_NAME"}, + Name: "name", + Usage: "provide the name for the dashboard", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_ADD_REPOS", "DASHBOARD_ADD_REPOS"}, + Name: "add-repos", + Usage: "provide the list of repositories to add for the dashboard", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_DROP_REPOS", "DASHBOARD_DROP_REPOS"}, + Name: "drop-repos", + Usage: "provide the list of repositories to remove from the dashboard", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_TARGET_REPOS", "DASHBOARD_TARGET_REPOS"}, + Name: "target-repos", + Usage: "provide the list of repositories to target for updates for the dashboard", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_ADD_ADMINS", "DASHBOARD_ADD_ADMINS"}, + Name: "add-admins", + Usage: "provide the list of admins to add for the dashboard", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_DROP_ADMINS", "DASHBOARD_DROP_ADMINS"}, + Name: "drop-admins", + Usage: "provide the list of admins to remove from the dashboard", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_REPOS_BRANCH", "DASHBOARD_REPOS_BRANCH"}, + Name: "branches", + Aliases: []string{"branch"}, + Usage: "filter builds in all repositories by branch", + }, + &cli.StringSliceFlag{ + EnvVars: []string{"VELA_DASHBOARD_REPOS_EVENT", "DASHBOARD_REPOS_EVENT"}, + Name: "events", + Aliases: []string{"event"}, + Usage: "filter builds in all repositories by event", + }, + + // Output Flags + + &cli.StringFlag{ + EnvVars: []string{"VELA_OUTPUT", "REPO_OUTPUT"}, + Name: internal.FlagOutput, + Aliases: []string{"op"}, + Usage: "format the output in json, spew or yaml", + }, + }, + CustomHelpTemplate: fmt.Sprintf(`%s +EXAMPLES: + 1. Update a dashboard to add a repository. + $ {{.HelpName}} --id c8da1302-07d6-11ea-882f-4893bca275b8 --add-repos Org-1/Repo-1 + 2. Update a dashboard to remove a repository. + $ {{.HelpName}} --id c8da1302-07d6-11ea-882f-4893bca275b8 --drop-repos Org-1/Repo-1 + 3. Update a dashboard to add event and branch filters to specific repositories. + $ {{.HelpName}} --id c8da1302-07d6-11ea-882f-4893bca275b8 --target-repos Org-1/Repo-1,Org-2/Repo-2 --branches main --events push + 4. Update a dashboard to change the name. + $ {{.HelpName}} --id c8da1302-07d6-11ea-882f-4893bca275b8 --name MyDashboard + 5. Update a dashboard to add an admin. + $ {{.HelpName}} --id c8da1302-07d6-11ea-882f-4893bca275b8 --add-admins JohnDoe + 6. Update a dashboard to remove an admin. + $ {{.HelpName}} --id c8da1302-07d6-11ea-882f-4893bca275b8 --drop-admins JohnDoe + +DOCUMENTATION: + + https://go-vela.github.io/docs/reference/cli/dashboard/update/ +`, cli.CommandHelpTemplate), +} + +// helper function to capture the provided input +// and create the object used to update a dashboard. +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 dashboard configuration + d := &dashboard.Config{ + Action: internal.ActionUpdate, + ID: c.String("id"), + Name: c.String("name"), + AddRepos: c.StringSlice("add-repos"), + DropRepos: c.StringSlice("drop-repos"), + TargetRepos: c.StringSlice("target-repos"), + Branches: c.StringSlice("branches"), + Events: c.StringSlice("events"), + AddAdmins: c.StringSlice("add-admins"), + DropAdmins: c.StringSlice("drop-admins"), + Output: c.String(internal.FlagOutput), + } + + // validate dashboard configuration + err = d.Validate() + if err != nil { + return err + } + + // execute the update call for the dashboard configuration + return d.Update(client) +} diff --git a/command/dashboard/update_test.go b/command/dashboard/update_test.go new file mode 100644 index 00000000..84cb1e1c --- /dev/null +++ b/command/dashboard/update_test.go @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +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 TestDashboard_Update(t *testing.T) { + // setup test server + s := httptest.NewServer(server.FakeHandler()) + + // setup flags + authSet := flag.NewFlagSet("test", 0) + authSet.String("api.addr", s.URL, "doc") + authSet.String("api.token.access", test.TestTokenGood, "doc") + authSet.String("api.token.refresh", "superSecretRefreshToken", "doc") + + 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("id", "c8da1302-07d6-11ea-882f-4893bca275b8", "doc") + fullSet.String("add-repos", "Org-1/Repo-1,Org-2/Repo-2", "doc") + fullSet.String("drop-repos", "Org-3/Repo-3", "doc") + fullSet.String("target-repos", "Org-4/Repo-4", "doc") + fullSet.String("add-admins", "octocat,octokitty", "doc") + fullSet.String("drop-admins", "octokitten", "doc") + fullSet.String("name", "octo-dashboard", "doc") + fullSet.String("branches", "main,dev", "doc") + fullSet.String("events", "push,tag", "doc") + fullSet.String("output", "json", "doc") + + // setup tests + tests := []struct { + failure bool + set *flag.FlagSet + }{ + { + failure: false, + set: fullSet, + }, + { + failure: true, + set: authSet, + }, + { + failure: true, + set: flag.NewFlagSet("test", 0), + }, + } + + // 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/dashboard/view.go b/command/dashboard/view.go new file mode 100644 index 00000000..03559af1 --- /dev/null +++ b/command/dashboard/view.go @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +import ( + "fmt" + + "github.com/urfave/cli/v2" + + "github.com/go-vela/cli/action" + "github.com/go-vela/cli/action/dashboard" + "github.com/go-vela/cli/internal" + "github.com/go-vela/cli/internal/client" +) + +// CommandView defines the command for viewing a dashboard. +var CommandView = &cli.Command{ + Name: "dashboard", + Description: "Use this command to view a dashboard.", + Usage: "View a dashboard from the provided configuration", + Action: view, + Flags: []cli.Flag{ + + // Dashboard Flags + + &cli.StringFlag{ + EnvVars: []string{"VELA_DASHBOARD_ID", "DASHBOARD_ID"}, + Name: "id", + Usage: "provide the uuid for the dashboard", + }, + + // Output Flags + + &cli.BoolFlag{ + EnvVars: []string{"VELA_FULL", "DASHBOARD_FULL"}, + Name: "full", + Usage: "output the repo and build information for the dashboard", + }, + &cli.StringFlag{ + EnvVars: []string{"VELA_OUTPUT", "REPO_OUTPUT"}, + Name: internal.FlagOutput, + Aliases: []string{"op"}, + Usage: "format the output in json, spew or yaml", + }, + }, + CustomHelpTemplate: fmt.Sprintf(`%s +EXAMPLES: + 1. View a dashboard. + $ {{.HelpName}} --id c8da1302-07d6-11ea-882f-4893bca275b8 + 2. View a dashboard with repo and build information. + $ {{.HelpName}} --id c8da1302-07d6-11ea-882f-4893bca275b8 --full + +DOCUMENTATION: + + https://go-vela.github.io/docs/reference/cli/dashboard/view/ +`, cli.CommandHelpTemplate), +} + +// helper function to capture the provided input +// and create the object used to view a dashboard. +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 + // + // 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 dashboard configuration + d := &dashboard.Config{ + Action: internal.ActionView, + ID: c.String("id"), + Full: c.Bool("full"), + Output: c.String(internal.FlagOutput), + } + + // validate dashboard configuration + err = d.Validate() + if err != nil { + return err + } + + // execute the view call for the dashboard configuration + return d.View(client) +} diff --git a/command/dashboard/view_test.go b/command/dashboard/view_test.go new file mode 100644 index 00000000..e51f3f6f --- /dev/null +++ b/command/dashboard/view_test.go @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: Apache-2.0 + +package dashboard + +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 TestDashboard_View(t *testing.T) { + // setup test server + s := httptest.NewServer(server.FakeHandler()) + + // setup flags + authSet := flag.NewFlagSet("test", 0) + authSet.String("api.addr", s.URL, "doc") + authSet.String("api.token.access", test.TestTokenGood, "doc") + authSet.String("api.token.refresh", "superSecretRefreshToken", "doc") + + 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("id", "c8da1302-07d6-11ea-882f-4893bca275b8", "doc") + fullSet.Bool("full", true, "doc") + fullSet.String("output", "json", "doc") + + // setup tests + tests := []struct { + failure bool + set *flag.FlagSet + }{ + { + failure: false, + set: fullSet, + }, + { + failure: true, + set: authSet, + }, + { + failure: true, + set: flag.NewFlagSet("test", 0), + }, + } + + // 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 5b784d4f..59b77574 100644 --- a/go.mod +++ b/go.mod @@ -10,9 +10,9 @@ 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.20240424150003-64f8eb0ebcc0 - github.com/go-vela/server v0.23.4-0.20240424144436-b55aa2bb3684 - github.com/go-vela/types v0.23.4-0.20240405205548-f24f795ac0b7 + github.com/go-vela/sdk-go v0.23.3-0.20240507145321-54c8961e00a9 + github.com/go-vela/server v0.23.4-0.20240506154118-8ad123451469 + 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 github.com/gosuri/uitable v0.0.4 diff --git a/go.sum b/go.sum index 63f962b5..1c45ae30 100644 --- a/go.sum +++ b/go.sum @@ -123,12 +123,12 @@ 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.20240424150003-64f8eb0ebcc0 h1:AYltea00KRHeIqVW0A1BDNH10Kb6Djfl69rCtztAqM0= -github.com/go-vela/sdk-go v0.23.3-0.20240424150003-64f8eb0ebcc0/go.mod h1:WB3MAFpnwvuvSGJLrGGbt6VO8aS1URiWa5kqjngO8mU= -github.com/go-vela/server v0.23.4-0.20240424144436-b55aa2bb3684 h1:O0gfupNx7aYPCCrXwVuisrbbqbVkvrRqRBAkSg1bIww= -github.com/go-vela/server v0.23.4-0.20240424144436-b55aa2bb3684/go.mod h1:QV9JFv+LdpAgkRJhHE92dh4vVdh0kNv8OJnyOLt++84= -github.com/go-vela/types v0.23.4-0.20240405205548-f24f795ac0b7 h1:3mN7ej69dMH3Vis3G/tPLzLL0Rfp8nR5qd0gpj5ejRM= -github.com/go-vela/types v0.23.4-0.20240405205548-f24f795ac0b7/go.mod h1:mEF9dLkk00rUXf/t39n2WvXZgJbxnPEEWy+DHqIlRUo= +github.com/go-vela/sdk-go v0.23.3-0.20240507145321-54c8961e00a9 h1:05QVYi/gRn0ZphF/cMQFEdsmmzROdDssX5dXZv+BrvQ= +github.com/go-vela/sdk-go v0.23.3-0.20240507145321-54c8961e00a9/go.mod h1:uBY1/Vcz6m2emXJw5vbYDnUOYn1F9aFsmlMaLNHr/2k= +github.com/go-vela/server v0.23.4-0.20240506154118-8ad123451469 h1:t+g5Gqdhrv7E7XGAD3ZaoxQ1hko/lKA7N1Az0dcXrgI= +github.com/go-vela/server v0.23.4-0.20240506154118-8ad123451469/go.mod h1:2KcNYX+DfNH/aWwu0pu89Gj9+wAm3S70VMy53/LMZjs= +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= github.com/go-vela/worker v0.23.3-0.20240424172515-3d4399807a4b/go.mod h1:e8iHziW2wNTDhF5LC1LGAW8N2doD0G8Q3aS2tC5Iwl4= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=