Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli: status command #768

Merged
merged 11 commits into from
Oct 25, 2021
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
IMPROVEMENTS:
* Helm Chart
* Automatic retry for `gossip-encryption-autogenerate-job` on failure [[GH-789](https://github.com/hashicorp/consul-k8s/pull/789)]
* CLI
* Add `status` command. [[GH-768](https://github.com/hashicorp/consul-k8s/pull/768)]

## 0.35.0 (October 19, 2021)

Expand Down
34 changes: 34 additions & 0 deletions cli/cmd/common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package common

import (
"embed"
"errors"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -95,3 +96,36 @@ func InitActionConfig(actionConfig *action.Configuration, namespace string, sett
}
return actionConfig, nil
}

// CheckForPreviousInstallations uses the helm Go SDK to find helm releases in all namespaces where the chart name is
// "consul", and returns the release name and namespace if found, or an error if not found.
func CheckForInstallations(settings *helmCLI.EnvSettings, uiLogger action.DebugLog) (string, string, error) {
// Need a specific action config to call helm list, where namespace is NOT specified.
listConfig := new(action.Configuration)
if err := listConfig.Init(settings.RESTClientGetter(), "",
os.Getenv("HELM_DRIVER"), uiLogger); err != nil {
return "", "", fmt.Errorf("couldn't initialize helm config: %s", err)
}

lister := action.NewList(listConfig)
lister.AllNamespaces = true
lister.StateMask = action.ListAll
res, err := lister.Run()
if err != nil {
return "", "", fmt.Errorf("couldn't check for installations: %s", err)
}

for _, rel := range res {
if rel.Chart.Metadata.Name == "consul" {
return rel.Name, rel.Namespace, nil
}
}
return "", "", errors.New("couldn't find consul installation")
}

func CloseWithError(c *BaseCommand) {
if err := c.Close(); err != nil {
c.Log.Error(err.Error())
os.Exit(1)
}
}
47 changes: 8 additions & 39 deletions cli/cmd/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,7 @@ func (c *Command) Run(args []string) int {
// The logger is initialized in main with the name cli. Here, we reset the name to install so log lines would be prefixed with install.
c.Log.ResetNamed("install")

defer func() {
if err := c.Close(); err != nil {
c.Log.Error(err.Error())
os.Exit(1)
}
}()
defer common.CloseWithError(c.BaseCommand)

if err := c.validateFlags(args); err != nil {
c.UI.Output(err.Error())
Expand Down Expand Up @@ -218,9 +213,14 @@ func (c *Command) Run(args []string) int {

c.UI.Output("Pre-Install Checks", terminal.WithHeaderStyle())

if err := c.checkForPreviousInstallations(settings, uiLogger); err != nil {
c.UI.Output(err.Error(), terminal.WithErrorStyle())
// Note the logic here, common's CheckForPreviousInstallations function returns an error if
// the release is not found, which in the install command is what we need for a successful install.
if name, ns, err := common.CheckForInstallations(settings, uiLogger); err == nil {
c.UI.Output(fmt.Sprintf("existing Consul installation found (name=%s, namespace=%s) - run "+
"consul-k8s uninstall if you wish to re-install", name, ns), terminal.WithErrorStyle())
return 1
} else {
c.UI.Output("No existing installations found.")
}

// Ensure there's no previous PVCs lying around.
Expand Down Expand Up @@ -341,37 +341,6 @@ func (c *Command) Synopsis() string {
return "Install Consul on Kubernetes."
}

// checkForPreviousInstallations uses the helm Go SDK to find helm releases in all namespaces where the chart name is
// "consul", and returns an error if there is an existing installation.
// Note that this function is tricky to test because mocking out the action.Configuration struct requires a
// RegistryClient field that is from an internal helm package, so we are not unit testing it.
func (c *Command) checkForPreviousInstallations(settings *helmCLI.EnvSettings, uiLogger action.DebugLog) error {
// Need a specific action config to call helm list, where namespace is NOT specified.
listConfig := new(action.Configuration)
if err := listConfig.Init(settings.RESTClientGetter(), "",
os.Getenv("HELM_DRIVER"), uiLogger); err != nil {
return fmt.Errorf("couldn't initialize helm config: %s", err)
}

lister := action.NewList(listConfig)
lister.AllNamespaces = true
res, err := lister.Run()
if err != nil {
return fmt.Errorf("couldn't check for installations: %s", err)
}

for _, rel := range res {
if rel.Chart.Metadata.Name == "consul" {
// TODO: In the future the user will be prompted with our own uninstall command.
return fmt.Errorf("existing Consul installation found (name=%s, namespace=%s) - run helm "+
"delete %s -n %s if you wish to re-install",
rel.Name, rel.Namespace, rel.Name, rel.Namespace)
}
}
c.UI.Output("No existing installations found", terminal.WithSuccessStyle())
return nil
}

// checkForPreviousPVCs checks for existing PVCs with a name containing "consul-server" and returns an error and lists
// the PVCs it finds matches.
func (c *Command) checkForPreviousPVCs() error {
Expand Down
Loading