mirror of https://gitlab.com/gitlab-org/cli.git
feat(cluster): add cluster agent list command
This commit is contained in:
parent
f0916553df
commit
68473b8eda
|
@ -0,0 +1,16 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import "github.com/xanzy/go-gitlab"
|
||||||
|
|
||||||
|
var ListAgents = func(client *gitlab.Client, projectID interface{}, opts *gitlab.ListAgentsOptions) ([]*gitlab.Agent, error) {
|
||||||
|
if client == nil {
|
||||||
|
client = apiClient.Lab()
|
||||||
|
}
|
||||||
|
|
||||||
|
agents, _, err := client.ClusterAgents.ListAgents(projectID, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return agents, nil
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
agentListCmd "gitlab.com/gitlab-org/cli/commands/cluster/agent/list"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCmdAgent(f *cmdutils.Factory) *cobra.Command {
|
||||||
|
agentCmd := &cobra.Command{
|
||||||
|
Use: "agent <command> [flags]",
|
||||||
|
Short: `Manage GitLab Agents for Kubernetes`,
|
||||||
|
Long: ``,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdutils.EnableRepoOverride(agentCmd, f)
|
||||||
|
|
||||||
|
agentCmd.AddCommand(agentListCmd.NewCmdAgentList(f))
|
||||||
|
|
||||||
|
return agentCmd
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewCmdAgent(t *testing.T) {
|
||||||
|
old := os.Stdout // keep backup of the real stdout
|
||||||
|
r, w, _ := os.Pipe()
|
||||||
|
os.Stdout = w
|
||||||
|
|
||||||
|
assert.Nil(t, NewCmdAgent(&cmdutils.Factory{}).Execute())
|
||||||
|
|
||||||
|
outC := make(chan string)
|
||||||
|
// copy the output in a separate goroutine so printing can't block indefinitely
|
||||||
|
go func() {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
_, _ = io.Copy(&buf, r)
|
||||||
|
outC <- buf.String()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// back to normal state
|
||||||
|
w.Close()
|
||||||
|
os.Stdout = old // restoring the real stdout
|
||||||
|
out := <-outC
|
||||||
|
|
||||||
|
assert.Contains(t, out, "Manage GitLab Agents for Kubernetes")
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package agentutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/xanzy/go-gitlab"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/iostreams"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/tableprinter"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DisplayAllAgents(io *iostreams.IOStreams, agents []*gitlab.Agent) string {
|
||||||
|
c := io.Color()
|
||||||
|
table := tableprinter.NewTablePrinter()
|
||||||
|
table.AddRow(c.Bold("ID"), c.Bold("Name"), c.Bold(c.Gray("Created At")))
|
||||||
|
for _, r := range agents {
|
||||||
|
table.AddRow(r.ID, r.Name, c.Gray(utils.TimeToPrettyTimeAgo(*r.CreatedAt)))
|
||||||
|
}
|
||||||
|
return table.Render()
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package list
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gitlab.com/gitlab-org/cli/api"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cluster/agent/agentutils"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/utils"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/xanzy/go-gitlab"
|
||||||
|
)
|
||||||
|
|
||||||
|
var factory *cmdutils.Factory
|
||||||
|
|
||||||
|
func NewCmdAgentList(f *cmdutils.Factory) *cobra.Command {
|
||||||
|
factory = f
|
||||||
|
agentListCmd := &cobra.Command{
|
||||||
|
Use: "list [flags]",
|
||||||
|
Short: `List GitLab Agents for Kubernetes in a project`,
|
||||||
|
Long: ``,
|
||||||
|
Aliases: []string{"ls"},
|
||||||
|
Args: cobra.MaximumNArgs(3),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
factory = f
|
||||||
|
page, err := cmd.Flags().GetUint("page")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
perPage, err := cmd.Flags().GetUint("per-page")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return listAgents(int(page), int(perPage))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
agentListCmd.Flags().UintP("page", "p", 1, "Page number")
|
||||||
|
agentListCmd.Flags().UintP("per-page", "P", uint(api.DefaultListLimit), "Number of items to list per page.")
|
||||||
|
|
||||||
|
return agentListCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func listAgents(page, perPage int) error {
|
||||||
|
apiClient, err := factory.HttpClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
repo, err := factory.BaseRepo()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
agents, err := api.ListAgents(apiClient, repo.FullName(), &gitlab.ListAgentsOptions{
|
||||||
|
Page: page,
|
||||||
|
PerPage: perPage,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
title := utils.NewListTitle("agent")
|
||||||
|
title.RepoName = repo.FullName()
|
||||||
|
title.Page = page
|
||||||
|
title.CurrentPageTotal = len(agents)
|
||||||
|
err = factory.IO.StartPager()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer factory.IO.StopPager()
|
||||||
|
|
||||||
|
fmt.Fprintf(factory.IO.StdOut, "%s\n%s\n", title.Describe(), agentutils.DisplayAllAgents(factory.IO, agents))
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
package list
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/httpmock"
|
||||||
|
"gitlab.com/gitlab-org/cli/test"
|
||||||
|
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdtest"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runCommand(rt http.RoundTripper, isTTY bool, cli string, doHyperlinks string) (*test.CmdOut, error) {
|
||||||
|
ios, _, stdout, stderr := cmdtest.InitIOStreams(isTTY, doHyperlinks)
|
||||||
|
f := cmdtest.InitFactory(ios, rt)
|
||||||
|
|
||||||
|
// TODO: shouldn't be there but the stub doesn't work without it
|
||||||
|
_, _ = f.HttpClient()
|
||||||
|
|
||||||
|
cmd := NewCmdAgentList(f)
|
||||||
|
|
||||||
|
return cmdtest.ExecuteCommand(cmd, cli, stdout, stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAgentList(t *testing.T) {
|
||||||
|
fakeHTTP := httpmock.New()
|
||||||
|
defer fakeHTTP.Verify(t)
|
||||||
|
|
||||||
|
deterministicCreatedAt := time.Now().Add(-24 * time.Hour).Format(time.RFC3339)
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/cluster_agents",
|
||||||
|
httpmock.NewStringResponse(http.StatusOK, fmt.Sprintf(`
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "local",
|
||||||
|
"created_at": "%[1]s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "prd",
|
||||||
|
"created_at": "%[1]s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
`, deterministicCreatedAt)))
|
||||||
|
|
||||||
|
output, err := runCommand(fakeHTTP, true, "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error running command `cluster agent list`: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, heredoc.Doc(`
|
||||||
|
Showing 2 agents on OWNER/REPO (Page 1)
|
||||||
|
|
||||||
|
ID Name Created At
|
||||||
|
1 local about 1 day ago
|
||||||
|
2 prd about 1 day ago
|
||||||
|
|
||||||
|
`), output.String())
|
||||||
|
assert.Equal(t, ``, output.Stderr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAgentList_Pagination(t *testing.T) {
|
||||||
|
fakeHTTP := httpmock.New()
|
||||||
|
defer fakeHTTP.Verify(t)
|
||||||
|
|
||||||
|
deterministicCreatedAt := time.Now().Add(-24 * time.Hour).Format(time.RFC3339)
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodGet, "/projects/OWNER/REPO/cluster_agents",
|
||||||
|
httpmock.NewStringResponse(http.StatusOK, fmt.Sprintf(`
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "local",
|
||||||
|
"created_at": "%[1]s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "prd",
|
||||||
|
"created_at": "%[1]s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
`, deterministicCreatedAt)))
|
||||||
|
|
||||||
|
cli := "--page 42 --per-page 10"
|
||||||
|
output, err := runCommand(fakeHTTP, true, cli, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error running command `cluster agent list`: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, heredoc.Doc(`
|
||||||
|
Showing 2 agents on OWNER/REPO (Page 42)
|
||||||
|
|
||||||
|
ID Name Created At
|
||||||
|
1 local about 1 day ago
|
||||||
|
2 prd about 1 day ago
|
||||||
|
|
||||||
|
`), output.String())
|
||||||
|
assert.Equal(t, ``, output.Stderr())
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
agentCmd "gitlab.com/gitlab-org/cli/commands/cluster/agent"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCmdCluster(f *cmdutils.Factory) *cobra.Command {
|
||||||
|
clusterCmd := &cobra.Command{
|
||||||
|
Use: "cluster <command> [flags]",
|
||||||
|
Short: `Manage GitLab Agents for Kubernetes and their clusters`,
|
||||||
|
Long: ``,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdutils.EnableRepoOverride(clusterCmd, f)
|
||||||
|
|
||||||
|
clusterCmd.AddCommand(agentCmd.NewCmdAgent(f))
|
||||||
|
|
||||||
|
return clusterCmd
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewCmdCluster(t *testing.T) {
|
||||||
|
old := os.Stdout // keep backup of the real stdout
|
||||||
|
r, w, _ := os.Pipe()
|
||||||
|
os.Stdout = w
|
||||||
|
|
||||||
|
assert.Nil(t, NewCmdCluster(&cmdutils.Factory{}).Execute())
|
||||||
|
|
||||||
|
outC := make(chan string)
|
||||||
|
// copy the output in a separate goroutine so printing can't block indefinitely
|
||||||
|
go func() {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
_, _ = io.Copy(&buf, r)
|
||||||
|
outC <- buf.String()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// back to normal state
|
||||||
|
w.Close()
|
||||||
|
os.Stdout = old // restoring the real stdout
|
||||||
|
out := <-outC
|
||||||
|
|
||||||
|
assert.Contains(t, out, "Manage GitLab Agents for Kubernetes and their clusters")
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import (
|
||||||
authCmd "gitlab.com/gitlab-org/cli/commands/auth"
|
authCmd "gitlab.com/gitlab-org/cli/commands/auth"
|
||||||
changelogCmd "gitlab.com/gitlab-org/cli/commands/changelog"
|
changelogCmd "gitlab.com/gitlab-org/cli/commands/changelog"
|
||||||
pipelineCmd "gitlab.com/gitlab-org/cli/commands/ci"
|
pipelineCmd "gitlab.com/gitlab-org/cli/commands/ci"
|
||||||
|
clusterCmd "gitlab.com/gitlab-org/cli/commands/cluster"
|
||||||
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
completionCmd "gitlab.com/gitlab-org/cli/commands/completion"
|
completionCmd "gitlab.com/gitlab-org/cli/commands/completion"
|
||||||
configCmd "gitlab.com/gitlab-org/cli/commands/config"
|
configCmd "gitlab.com/gitlab-org/cli/commands/config"
|
||||||
|
@ -110,6 +111,7 @@ func NewCmdRoot(f *cmdutils.Factory, version, buildDate string) *cobra.Command {
|
||||||
cmdutils.HTTPClientFactory(f) // Initialize HTTP Client
|
cmdutils.HTTPClientFactory(f) // Initialize HTTP Client
|
||||||
|
|
||||||
rootCmd.AddCommand(changelogCmd.NewCmdChangelog(f))
|
rootCmd.AddCommand(changelogCmd.NewCmdChangelog(f))
|
||||||
|
rootCmd.AddCommand(clusterCmd.NewCmdCluster(f))
|
||||||
rootCmd.AddCommand(issueCmd.NewCmdIssue(f))
|
rootCmd.AddCommand(issueCmd.NewCmdIssue(f))
|
||||||
rootCmd.AddCommand(incidentCmd.NewCmdIncident(f))
|
rootCmd.AddCommand(incidentCmd.NewCmdIncident(f))
|
||||||
rootCmd.AddCommand(labelCmd.NewCmdLabel(f))
|
rootCmd.AddCommand(labelCmd.NewCmdLabel(f))
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
stage: Create
|
||||||
|
group: Code Review
|
||||||
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This documentation is auto generated by a script.
|
||||||
|
Please do not edit this file directly. Run `make gen-docs` instead.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# `glab cluster agent`
|
||||||
|
|
||||||
|
Manage GitLab Agents for Kubernetes
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
-R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options inherited from parent commands
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
--help Show help for command
|
||||||
|
```
|
||||||
|
|
||||||
|
## Subcommands
|
||||||
|
|
||||||
|
- [list](list.md)
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
stage: Create
|
||||||
|
group: Code Review
|
||||||
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This documentation is auto generated by a script.
|
||||||
|
Please do not edit this file directly. Run `make gen-docs` instead.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# `glab cluster agent list`
|
||||||
|
|
||||||
|
List GitLab Agents for Kubernetes in a project
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
glab cluster agent list [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
ls
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
-p, --page uint Page number (default 1)
|
||||||
|
-P, --per-page uint Number of items to list per page. (default 30)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options inherited from parent commands
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
--help Show help for command
|
||||||
|
-R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL
|
||||||
|
```
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
stage: Create
|
||||||
|
group: Code Review
|
||||||
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This documentation is auto generated by a script.
|
||||||
|
Please do not edit this file directly. Run `make gen-docs` instead.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# `glab cluster help`
|
||||||
|
|
||||||
|
Help about any command
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
glab cluster help [command] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options inherited from parent commands
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
--help Show help for command
|
||||||
|
-R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL
|
||||||
|
```
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
stage: Create
|
||||||
|
group: Code Review
|
||||||
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This documentation is auto generated by a script.
|
||||||
|
Please do not edit this file directly. Run `make gen-docs` instead.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# `glab cluster`
|
||||||
|
|
||||||
|
Manage GitLab Agents for Kubernetes and their clusters
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
-R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options inherited from parent commands
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
--help Show help for command
|
||||||
|
```
|
||||||
|
|
||||||
|
## Subcommands
|
||||||
|
|
||||||
|
- [agent](agent/index.md)
|
Loading…
Reference in New Issue