Skip to content

Commit

Permalink
Implement install version command (#426)
Browse files Browse the repository at this point in the history
Adds `packages install` and `packages show terraform|helm` to support specific named version installs to make it easier to toggle versions.
  • Loading branch information
michaeljguarino authored Aug 9, 2023
1 parent 2677a9f commit fe45980
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 5 deletions.
86 changes: 85 additions & 1 deletion cmd/plural/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ import (

func (p *Plural) packagesCommands() []cli.Command {
return []cli.Command{
{
Name: "install",
Usage: "installs a package at a specific version",
ArgsUsage: "helm|terraform REPO NAME VSN",
Action: affirmed(requireArgs(p.installPackage, []string{"TYPE", "REPO", "NAME", "VERSION"}), "Are you sure you want to install this package?", "PLURAL_PACKAGES_INSTALL"),
},
{
Name: "uninstall",
Usage: "uninstall a helm or terraform package",
ArgsUsage: "TYPE REPO NAME",
ArgsUsage: "helm|terraform REPO NAME",
Action: latestVersion(affirmed(requireArgs(rooted(p.uninstallPackage), []string{"TYPE", "REPO", "NAME"}), "Are you sure you want to uninstall this package?", "PLURAL_PACKAGES_UNINSTALL")),
},
{
Expand All @@ -25,7 +31,85 @@ func (p *Plural) packagesCommands() []cli.Command {
ArgsUsage: "REPO",
Action: latestVersion(requireArgs(rooted(p.listPackages), []string{"REPO"})),
},
{
Name: "show",
Usage: "Shows version information for packages within a plural repo",
Subcommands: p.showCommands(),
},
}
}

func (p *Plural) showCommands() []cli.Command {
return []cli.Command{
{
Name: "helm",
Usage: "list versions for a helm chart",
ArgsUsage: "REPO NAME",
Action: requireArgs(p.showHelm, []string{"REPO", "NAME"}),
},
{
Name: "terraform",
Usage: "list versions for a terraform module",
ArgsUsage: "REPO NAME",
Action: requireArgs(p.showTerraform, []string{"REPO", "NAME"}),
},
}
}

func (p *Plural) installPackage(c *cli.Context) error {
p.InitPluralClient()
tp, repo, name, vsn := c.Args().Get(0), c.Args().Get(1), c.Args().Get(2), c.Args().Get(3)
if err := p.Client.InstallVersion(tp, repo, name, vsn); err != nil {
return err
}

utils.Success("Successfully installed %s %s version %s in %s\n", tp, name, vsn, repo)
utils.Highlight("To apply the module in your cluster, you'll need to run `plural build --only %s && plural deploy", repo)
return nil
}

func (p *Plural) showHelm(c *cli.Context) error {
p.InitPluralClient()
repo, name := c.Args().Get(0), c.Args().Get(1)
chart, err := api.FindChart(p.Client, repo, name)
if err != nil {
return err
}

vsns, err := p.Client.GetVersions(chart.Id)
if err != nil {
return err
}

header := []string{"Name", "Version", "App Version", "Created"}
return utils.PrintTable(vsns, header, func(vsn *api.Version) ([]string, error) {
appVsn := ""
if app, ok := vsn.Helm["appVersion"]; ok {
if v, ok := app.(string); ok {
appVsn = v
}
}
return []string{chart.Name, vsn.Version, appVsn, vsn.InsertedAt}, nil
})
}

func (p *Plural) showTerraform(c *cli.Context) error {
p.InitPluralClient()
repo, name := c.Args().Get(0), c.Args().Get(1)
chart, err := api.FindTerraform(p.Client, repo, name)
if err != nil {
return err
}

vsns, err := p.Client.GetTerraformVersions(chart.Id)
if err != nil {
return err
}

header := []string{"Name", "Version", "Created"}
return utils.PrintTable(vsns, header, func(vsn *api.Version) ([]string, error) {
return []string{chart.Name, vsn.Version, vsn.InsertedAt}, nil
})
}

func (p *Plural) listPackages(c *cli.Context) error {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,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.6.0
github.com/pluralsh/gqlclient v1.7.0
github.com/pluralsh/plural-operator v0.5.3
github.com/pluralsh/polly v0.1.1
github.com/rodaine/hclencoder v0.0.1
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,10 @@ github.com/pluralsh/controller-reconcile-helper v0.0.4 h1:1o+7qYSyoeqKFjx+WgQTxD
github.com/pluralsh/controller-reconcile-helper v0.0.4/go.mod h1:AfY0gtteD6veBjmB6jiRx/aR4yevEf6K0M13/pGan/s=
github.com/pluralsh/gqlclient v1.6.0 h1:7R0H98XrZdBdl8rQQGVGKkCY9iMStyrX+0lZ3zuArqo=
github.com/pluralsh/gqlclient v1.6.0/go.mod h1:qSXKUlio1F2DRPy8el4oFYsmpKbkUYspgPB87T4it5I=
github.com/pluralsh/gqlclient v1.6.1 h1:E2VTJYwoEc6X3Nfm30lKDlPw+N+6l9NiPHJcRQqJ0Ng=
github.com/pluralsh/gqlclient v1.6.1/go.mod h1:qSXKUlio1F2DRPy8el4oFYsmpKbkUYspgPB87T4it5I=
github.com/pluralsh/gqlclient v1.7.0 h1:QUNVxAwu0CrkZAo9sYPav+nGxlCyvGypmDqxY2HBgoA=
github.com/pluralsh/gqlclient v1.7.0/go.mod h1:qSXKUlio1F2DRPy8el4oFYsmpKbkUYspgPB87T4it5I=
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
4 changes: 3 additions & 1 deletion pkg/api/charts.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,15 @@ func convertVersion(version *gqlclient.VersionFragment) *Version {
if version.TemplateType != nil {
v.TemplateType = *version.TemplateType
}
if version.InsertedAt != nil {
v.InsertedAt = *version.InsertedAt
}

v.Crds = make([]Crd, 0)
for _, crd := range version.Crds {
v.Crds = append(v.Crds, convertCrd(crd))
}
v.Dependencies = convertDependencies(version.Dependencies)

return v
}

Expand Down
40 changes: 40 additions & 0 deletions pkg/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"context"
"encoding/json"
"fmt"
"net/http"

rawclient "github.com/Yamashou/gqlgenc/client"
Expand All @@ -11,6 +12,7 @@ import (

"github.com/pluralsh/plural/pkg/config"
"github.com/pluralsh/plural/pkg/utils"
"github.com/samber/lo"
)

type authedTransport struct {
Expand Down Expand Up @@ -51,6 +53,7 @@ type Client interface {
UpdateVersion(spec *VersionSpec, tags []string) error
GetCharts(repoId string) ([]*Chart, error)
GetVersions(chartId string) ([]*Version, error)
GetTerraformVersions(id string) ([]*Version, error)
GetChartInstallations(repoId string) ([]*ChartInstallation, error)
GetPackageInstallations(repoId string) (charts []*ChartInstallation, tfs []*TerraformInstallation, err error)
CreateCrd(repo string, chart string, file string) error
Expand Down Expand Up @@ -89,6 +92,7 @@ type Client interface {
TransferOwnership(name, email string) error
Release(name string, tags []string) error
Chat(history []*ChatMessage) (*ChatMessage, error)
InstallVersion(tp, repo, pkg, vsn string) error
}

type client struct {
Expand Down Expand Up @@ -143,3 +147,39 @@ func GetErrorResponse(err error, methodName string) error {

return errList
}

func FindChart(client Client, repo, name string) (*Chart, error) {
r, err := client.GetRepository(repo)
if err != nil {
return nil, err
}

charts, err := client.GetCharts(r.Id)
if err != nil {
return nil, err
}

chart, ok := lo.Find(charts, func(c *Chart) bool { return c.Name == name })
if !ok {
return nil, fmt.Errorf("No chart found for repo %s and name %s", repo, name)
}
return chart, nil
}

func FindTerraform(client Client, repo, name string) (*Terraform, error) {
r, err := client.GetRepository(repo)
if err != nil {
return nil, err
}

tfs, err := client.GetTerraforma(r.Id)
if err != nil {
return nil, err
}

tf, ok := lo.Find(tfs, func(c *Terraform) bool { return c.Name == name })
if !ok {
return nil, fmt.Errorf("No terraform module found for repo %s and name %s", repo, name)
}
return tf, nil
}
1 change: 1 addition & 0 deletions pkg/api/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type Version struct {
TemplateType gqlclient.TemplateType
Crds []Crd
Dependencies *Dependencies
InsertedAt string
}

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

import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -209,6 +210,17 @@ func (client *client) ListRepositories(query string) ([]*Repository, error) {
return res, err
}

func (client *client) InstallVersion(tp, repo, name, vsn string) error {
tp = strings.ToUpper(tp)
dt := gqlclient.DependencyType(tp)
if !dt.IsValid() {
return fmt.Errorf("invalid package type %s", tp)
}

_, err := client.pluralClient.InstallVersion(context.Background(), dt, repo, name, vsn)
return err
}

func (client *client) Release(name string, tags []string) error {
_, err := client.pluralClient.Release(context.Background(), name, tags)
return err
Expand Down
14 changes: 14 additions & 0 deletions pkg/api/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ func (client *client) GetTerraforma(repoId string) ([]*Terraform, error) {
return terraform, err
}

func (client *client) GetTerraformVersions(id string) ([]*Version, error) {
resp, err := client.pluralClient.GetTerraformVersions(client.ctx, id)
if err != nil {
return nil, err
}

versions := make([]*Version, 0)
for _, version := range resp.Versions.Edges {
versions = append(versions, convertVersion(version.Node))
}

return versions, nil
}

func (client *client) GetTerraformInstallations(repoId string) ([]*TerraformInstallation, error) {
resp, err := client.pluralClient.GetTerraformInstallations(client.ctx, repoId)
if err != nil {
Expand Down
42 changes: 41 additions & 1 deletion pkg/test/mocks/Client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/test/mocks/Kube.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fe45980

Please sign in to comment.