Skip to content

Commit

Permalink
Add cluster promotion commands (#361)
Browse files Browse the repository at this point in the history
* Add cluster promotion commands

These commands will allow users to perform all the main CRUD for cluster promotions

* clean up file input
  • Loading branch information
michaeljguarino authored Mar 9, 2023
1 parent 557968d commit f83d74f
Show file tree
Hide file tree
Showing 13 changed files with 515 additions and 67 deletions.
133 changes: 133 additions & 0 deletions cmd/plural/clusters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package main

import (
"fmt"

"github.com/pluralsh/plural/pkg/api"
"github.com/pluralsh/plural/pkg/manifest"
"github.com/pluralsh/plural/pkg/utils"
"github.com/urfave/cli"
)

func (p *Plural) clusterCommands() []cli.Command {
return []cli.Command{
{
Name: "list",
Usage: "lists clusters accessible to your user",
Action: latestVersion(p.listClusters),
},
{
Name: "view",
Usage: "shows info for a cluster",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Usage: "the id of the source cluster",
},
},
Action: latestVersion(p.showCluster),
},
{
Name: "depend",
Usage: "have a cluster wait for promotion on another cluster",
Flags: []cli.Flag{
cli.StringFlag{
Name: "source-id",
Usage: "the id of the source cluster",
},
cli.StringFlag{
Name: "dest-id",
Usage: "the id of the cluster waiting for promotion",
},
},
Action: latestVersion(p.dependCluster),
},
{
Name: "promote",
Usage: "promote pending upgrades to your cluster",
Action: latestVersion(p.promoteCluster),
},
}
}

func (p *Plural) listClusters(c *cli.Context) error {
p.InitPluralClient()
clusters, err := p.Client.Clusters()
if err != nil {
return err
}

headers := []string{"ID", "Name", "Provider", "Git Url", "Owner"}
return utils.PrintTable(clusters, headers, func(c *api.Cluster) ([]string, error) {
return []string{c.Id, c.Name, c.Provider, c.GitUrl, c.Owner.Email}, nil
})
}

func (p *Plural) showCluster(c *cli.Context) error {
p.InitPluralClient()
id := c.String("id")
if id == "" {
clusters, err := p.Client.Clusters()
if err != nil {
return err
}

project, err := manifest.FetchProject()
if err != nil {
return err
}
for _, cluster := range clusters {
if cluster.Name == project.Cluster && cluster.Owner.Email == project.Owner.Email {
id = cluster.Id
break
}
}
}
cluster, err := p.Client.Cluster(id)
if err != nil {
return err
}

fmt.Printf("Cluster %s:\n\n", cluster.Id)

utils.PrintAttributes(map[string]string{
"Id": cluster.Id,
"Name": cluster.Name,
"Provider": cluster.Provider,
"Git Url": cluster.GitUrl,
"Owner": cluster.Owner.Email,
})

fmt.Println("")
if len(cluster.UpgradeInfo) > 0 {
fmt.Printf("Pending Upgrades:\n\n")
headers := []string{"Repository", "Count"}
return utils.PrintTable(cluster.UpgradeInfo, headers, func(c *api.UpgradeInfo) ([]string, error) {
return []string{c.Installation.Repository.Name, fmt.Sprintf("%d", c.Count)}, nil
})
}

fmt.Println("No pending upgrades")
return nil
}

func (p *Plural) dependCluster(c *cli.Context) error {
p.InitPluralClient()
source, dest := c.String("source-id"), c.String("dest-id")
if err := p.Client.CreateDependency(source, dest); err != nil {
return err
}

utils.Highlight("Cluster %s will now delegate upgrades to %s", dest, source)
return nil
}

func (p *Plural) promoteCluster(c *cli.Context) error {
p.InitPluralClient()
if err := p.Client.PromoteCluster(); err != nil {
return err
}

utils.Success("Upgrades promoted!")
return nil
}
5 changes: 5 additions & 0 deletions cmd/plural/plural.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ func (p *Plural) getCommands() []cli.Command {
Subcommands: shellCommands(),
Category: "Workspace",
},
{
Name: "clusters",
Usage: "commands related to managing plural clusters",
Subcommands: p.clusterCommands(),
},
{
Name: "repos",
Usage: "view and manage plural repositories",
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ require (
github.com/olekukonko/tablewriter v0.0.5
github.com/packethost/packngo v0.29.0
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
github.com/pluralsh/gqlclient v1.3.9
github.com/pluralsh/gqlclient v1.3.10
github.com/pluralsh/plural-operator v0.5.3
github.com/pluralsh/polly v0.0.6
github.com/rodaine/hclencoder v0.0.1
Expand All @@ -55,7 +55,7 @@ require (
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64
go.mercari.io/hcledit v0.0.8
golang.org/x/crypto v0.5.0
golang.org/x/mod v0.6.0
golang.org/x/mod v0.9.0
golang.org/x/oauth2 v0.5.0
gopkg.in/yaml.v2 v2.4.0
helm.sh/helm/v3 v3.11.0
Expand Down Expand Up @@ -250,9 +250,9 @@ require (
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.5.0
golang.org/x/text v0.7.0
golang.org/x/text v0.8.0
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.110.0
Expand Down
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -897,8 +897,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pluralsh/controller-reconcile-helper v0.0.4 h1:1o+7qYSyoeqKFjx+WgQTxDz4Q2VMpzprJIIKShxqG0E=
github.com/pluralsh/controller-reconcile-helper v0.0.4/go.mod h1:AfY0gtteD6veBjmB6jiRx/aR4yevEf6K0M13/pGan/s=
github.com/pluralsh/gqlclient v1.3.9 h1:cJ6Vu+N1pI5z46JS2o13fh4Oc9CbnTljwu3HTTQCPN8=
github.com/pluralsh/gqlclient v1.3.9/go.mod h1:VHjVCSOaD9lzOI3u7tOuaQY7vrLdiAKPSbeihaWYX28=
github.com/pluralsh/gqlclient v1.3.10 h1:B5Rd4cjAfTllMc4oPMR/PEebxdVb0gIyPm+VT3lvzEM=
github.com/pluralsh/gqlclient v1.3.10/go.mod h1:z1qHnvPeqIN/a+5OzFs40e6HI6tDxzh1+yJuEpvqGy4=
github.com/pluralsh/oauth v0.9.2 h1:tM9hBK4tCnJUeCOgX0ctxBBCS3hiCDPoxkJLODtedmQ=
github.com/pluralsh/oauth v0.9.2/go.mod h1:aTUw/75rzcsbvW+/TLvWtHVDXFIdtFrDtUncOq9vHyM=
github.com/pluralsh/plural-operator v0.5.3 h1:GaPL3LgimfzKZNHt7zXzqYZpb0hgyW9noHYnkA+rqNs=
Expand Down Expand Up @@ -1190,8 +1190,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -1375,8 +1375,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand All @@ -1395,8 +1395,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
4 changes: 4 additions & 0 deletions pkg/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ type Client interface {
ListKeyBackups() ([]*KeyBackup, error)
GetHelp(prompt string) (string, error)
DestroyCluster(domain, name, provider string) error
CreateDependency(source, dest string) error
PromoteCluster() error
Clusters() ([]*Cluster, error)
Cluster(id string) (*Cluster, error)
}

type client struct {
Expand Down
67 changes: 67 additions & 0 deletions pkg/api/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"github.com/pluralsh/gqlclient"
"github.com/samber/lo"
)

func (client *client) DestroyCluster(domain, name, provider string) error {
Expand All @@ -12,3 +13,69 @@ func (client *client) DestroyCluster(domain, name, provider string) error {

return nil
}

func (client *client) CreateDependency(source, dest string) error {
_, err := client.pluralClient.CreateDependency(client.ctx, source, dest)
return err
}

func (client *client) PromoteCluster() error {
_, err := client.pluralClient.PromoteCluster(client.ctx)
return err
}

func (client *client) Clusters() ([]*Cluster, error) {
resp, err := client.pluralClient.Clusters(client.ctx, nil)
if err != nil {
return nil, err
}
clusters := make([]*Cluster, 0)
for _, edge := range resp.Clusters.Edges {
node := edge.Node
clusters = append(clusters, &Cluster{
Id: node.ID,
Name: node.Name,
Provider: string(node.Provider),
GitUrl: lo.FromPtr(node.GitURL),
Owner: &User{
Id: node.Owner.ID,
Name: node.Owner.Name,
Email: node.Owner.Email,
},
})
}

return clusters, nil
}

func (client *client) Cluster(id string) (*Cluster, error) {
resp, err := client.pluralClient.ClusterInfo(client.ctx, id)
if err != nil {
return nil, err
}

node := resp.Cluster
upgradeInfo := make([]*UpgradeInfo, 0)
for _, info := range node.UpgradeInfo {
upgradeInfo = append(upgradeInfo, &UpgradeInfo{
Count: lo.FromPtr(info.Count),
Installation: &Installation{
Repository: convertRepository(info.Installation.Repository),
},
})
}

cluster := &Cluster{
Id: node.ID,
Name: node.Name,
Provider: string(node.Provider),
GitUrl: lo.FromPtr(node.GitURL),
Owner: &User{
Id: node.Owner.ID,
Name: node.Owner.Name,
Email: node.Owner.Email,
},
UpgradeInfo: upgradeInfo,
}
return cluster, nil
}
15 changes: 15 additions & 0 deletions pkg/api/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,21 @@ type KeyBackup struct {
InsertedAt string
}

type Cluster struct {
Id string
Name string
Provider string
UpgradeInfo []*UpgradeInfo
Source string
GitUrl string
Owner *User
}

type UpgradeInfo struct {
Count int64
Installation *Installation
}

const CrdFragment = `
fragment CrdFragment on Crd {
id
Expand Down
1 change: 1 addition & 0 deletions pkg/api/recipes.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type RecipeInput struct {
Description string
Provider string
Restricted bool
Primary bool
Tests []RecipeTestInput `yaml:"tests" json:"tests,omitempty"`
Sections []RecipeSectionInput
Dependencies []DependencyInput
Expand Down
20 changes: 12 additions & 8 deletions pkg/api/repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,21 @@ func (client *client) GetRepository(repo string) (*Repository, error) {
return nil, err
}

return convertRepository(resp.Repository), nil
}

func convertRepository(repo *gqlclient.RepositoryFragment) *Repository {
return &Repository{
Id: resp.Repository.ID,
Name: resp.Repository.Name,
Description: utils.ConvertStringPointer(resp.Repository.Description),
Icon: utils.ConvertStringPointer(resp.Repository.Icon),
DarkIcon: utils.ConvertStringPointer(resp.Repository.DarkIcon),
Notes: utils.ConvertStringPointer(resp.Repository.Notes),
Id: repo.ID,
Name: repo.Name,
Description: utils.ConvertStringPointer(repo.Description),
Icon: utils.ConvertStringPointer(repo.Icon),
DarkIcon: utils.ConvertStringPointer(repo.DarkIcon),
Notes: utils.ConvertStringPointer(repo.Notes),
Publisher: &Publisher{
Name: resp.Repository.Publisher.Name,
Name: repo.Publisher.Name,
},
}, nil
}
}

func (client *client) CreateRepository(name, publisher string, input *gqlclient.RepositoryAttributes) error {
Expand Down
6 changes: 5 additions & 1 deletion pkg/bundle/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,15 @@ func Configure(ctx map[string]interface{}, item *api.ConfigurationItem, context
if value := getEnvVar(repo, item.Name); value != "" {
res = value
} else {
prompt, opts := fileSurvey(def)
prompt, opts := fileSurvey(def, item)
if err := survey.AskOne(prompt, &res, opts...); err != nil {
return err
}
}
if res == "" {
return
}

path, err := homedir.Expand(res)
if err != nil {
return err
Expand Down
Loading

0 comments on commit f83d74f

Please sign in to comment.