fix: normalise install flags to match other commands

Signed-off-by: Adam Talbot <adam.talbot@venafi.com>
This commit is contained in:
Adam Talbot 2023-12-19 16:33:34 +00:00
parent a10d81be5d
commit 6e83949f64
4 changed files with 128 additions and 47 deletions

View File

@ -58,6 +58,10 @@ type Factory struct {
// KubeClient is a Kubernetes clientset for interacting with the base
// Kubernetes APIs.
KubeClient kubernetes.Interface
// RESTClientGetter is used to get RESTConfig, DiscoveryClients and
// RESTMapper implementations
RESTClientGetter genericclioptions.RESTClientGetter
}
// New returns a new Factory. The supplied command will have flags registered
@ -109,5 +113,7 @@ func (f *Factory) complete() error {
return err
}
f.RESTClientGetter = factory
return nil
}

View File

@ -0,0 +1,90 @@
/*
Copyright 2021 The cert-manager Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package helm
import (
"context"
"strconv"
"github.com/cert-manager/cert-manager/cmd/ctl/pkg/factory"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"helm.sh/helm/v3/pkg/cli"
)
const defaultCertManagerNamespace = "cert-manager"
const debugLogLevel = 3
type NormalisedEnvSettings struct {
EnvSettings *cli.EnvSettings
Factory *factory.Factory
}
func NewNormalisedEnvSettings() *NormalisedEnvSettings {
return &NormalisedEnvSettings{
EnvSettings: cli.New(),
}
}
func (n *NormalisedEnvSettings) Namespace() string {
return n.Factory.Namespace
}
func (n *NormalisedEnvSettings) Setup(ctx context.Context, cmd *cobra.Command) {
n.Factory = factory.New(ctx, cmd)
n.addEnvSettingsFlags(cmd)
// Fix the default namespace to be cert-manager
cmd.Flag("namespace").DefValue = defaultCertManagerNamespace
cmd.Flag("namespace").Value.Set(defaultCertManagerNamespace)
}
func (n *NormalisedEnvSettings) addEnvSettingsFlags(cmd *cobra.Command) {
fs := cmd.Flags()
// Create a tempoary flag set to add the EnvSettings flags to, this
// can then be iterated over to copy the flags we want to the command
var tmpFlagSet pflag.FlagSet
n.EnvSettings.AddFlags(&tmpFlagSet)
tmpFlagSet.VisitAll(func(f *pflag.Flag) {
switch f.Name {
case "debug":
// Setup a PreRun to set the helm debug flag. Catch the
// existing PreRun Debug command if one was defined, and execute
// it second.
existingPreRun := cmd.PreRun
cmd.PreRun = func(cmd *cobra.Command, args []string) {
if isLogLevelDebug(cmd) {
f.Value.Set("true")
}
if existingPreRun != nil {
existingPreRun(cmd, args)
}
}
case "registry-config", "repository-config", "repository-cache":
fs.AddFlag(f)
}
})
}
func isLogLevelDebug(cmd *cobra.Command) bool {
flagValue := cmd.Flag("v").Value.String()
logLevel, _ := strconv.Atoi(flagValue)
return logLevel >= debugLogLevel
}

View File

@ -29,7 +29,6 @@ import (
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/cli/values"
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/release"
@ -41,10 +40,11 @@ import (
)
type InstallOptions struct {
settings *cli.EnvSettings
settings *helm.NormalisedEnvSettings
client *action.Install
cfg *action.Configuration
valueOpts *values.Options
logFn func(format string, v ...interface{})
ChartName string
DryRun bool
@ -54,8 +54,7 @@ type InstallOptions struct {
}
const (
installCRDsFlagName = "installCRDs"
defaultCertManagerNamespace = "cert-manager"
installCRDsFlagName = "installCRDs"
)
func installDesc() string {
@ -80,12 +79,18 @@ pass in a file or use the '--set' flag and pass configuration from the command l
}
func NewCmdInstall(ctx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command {
settings := cli.New()
cfg := new(action.Configuration)
log := logf.FromContext(ctx, "install")
logFn := func(format string, v ...interface{}) {
log.Info(fmt.Sprintf(format, v...))
}
settings := helm.NewNormalisedEnvSettings()
cfg := &action.Configuration{Log: logFn}
options := &InstallOptions{
settings: settings,
cfg: cfg,
logFn: logFn,
client: action.NewInstall(cfg),
valueOpts: &values.Options{},
@ -116,18 +121,7 @@ func NewCmdInstall(ctx context.Context, ioStreams genericclioptions.IOStreams) *
SilenceErrors: true,
}
settings.AddFlags(cmd.Flags())
// The Helm cli.New function does not provide an easy way to
// override the default of the namespace flag.
// See https://github.com/helm/helm/issues/9790
//
// Here we set the default value shown in the usage message.
cmd.Flag("namespace").DefValue = defaultCertManagerNamespace
// Here we set the default value.
// The returned error is ignored because
// pflag.stringValue.Set always returns a nil.
cmd.Flag("namespace").Value.Set(defaultCertManagerNamespace)
settings.Setup(ctx, cmd)
addInstallUninstallFlags(cmd.Flags(), &options.client.Timeout, &options.Wait)
@ -163,7 +157,7 @@ func (o *InstallOptions) runInstall(ctx context.Context) (*release.Release, erro
log := logf.FromContext(ctx, "install")
// Find chart
cp, err := o.client.ChartPathOptions.LocateChart(o.ChartName, o.settings)
cp, err := o.client.ChartPathOptions.LocateChart(o.ChartName, o.settings.EnvSettings)
if err != nil {
return nil, err
}
@ -184,7 +178,7 @@ func (o *InstallOptions) runInstall(ctx context.Context) (*release.Release, erro
}
// Merge all values flags
p := getter.All(o.settings)
p := getter.All(o.settings.EnvSettings)
chartValues, err := o.valueOpts.MergeValues(p)
if err != nil {
return nil, err
@ -213,9 +207,7 @@ func (o *InstallOptions) runInstall(ctx context.Context) (*release.Release, erro
return dryRunResult, nil
}
if err := o.cfg.Init(o.settings.RESTClientGetter(), o.settings.Namespace(), os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) {
log.Info(fmt.Sprintf(format, v...))
}); err != nil {
if err := o.cfg.Init(o.settings.Factory.RESTClientGetter, o.settings.Namespace(), os.Getenv("HELM_DRIVER"), o.logFn); err != nil {
return nil, err
}

View File

@ -25,20 +25,22 @@ import (
"github.com/spf13/cobra"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/storage/driver"
"k8s.io/cli-runtime/pkg/genericclioptions"
"github.com/cert-manager/cert-manager/cmd/ctl/pkg/build"
"github.com/cert-manager/cert-manager/cmd/ctl/pkg/install/helm"
logf "github.com/cert-manager/cert-manager/pkg/logs"
)
type options struct {
settings *cli.EnvSettings
settings *helm.NormalisedEnvSettings
client *action.Uninstall
cfg *action.Configuration
logFn func(format string, v ...interface{})
releaseName string
disableHooks bool
dryRun bool
wait bool
@ -47,8 +49,7 @@ type options struct {
}
const (
defaultCertManagerNamespace = "cert-manager"
releaseName = "cert-manager"
releaseName = "cert-manager"
)
func description() string {
@ -70,13 +71,19 @@ or
}
func NewCmd(ctx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command {
settings := cli.New()
cfg := new(action.Configuration)
log := logf.FromContext(ctx, "install")
logFn := func(format string, v ...interface{}) {
log.Info(fmt.Sprintf(format, v...))
}
settings := helm.NewNormalisedEnvSettings()
cfg := &action.Configuration{Log: logFn}
options := options{
settings: settings,
cfg: cfg,
client: action.NewUninstall(cfg),
logFn: logFn,
IOStreams: ioStreams,
}
@ -102,20 +109,10 @@ func NewCmd(ctx context.Context, ioStreams genericclioptions.IOStreams) *cobra.C
SilenceErrors: true,
}
settings.AddFlags(cmd.Flags())
// The Helm cli.New function does not provide an easy way to
// override the default of the namespace flag.
// See https://github.com/helm/helm/issues/9790
//
// set the default value shown in the usage message.
cmd.Flag("namespace").DefValue = defaultCertManagerNamespace
// The returned error is ignored because
// pflag.stringValue.Set always returns a nil.
cmd.Flag("namespace").Value.Set(defaultCertManagerNamespace)
settings.Setup(ctx, cmd)
cmd.Flags().DurationVar(&options.client.Timeout, "timeout", 5*time.Minute, "time to wait for any individual Kubernetes operation (like Jobs for hooks)")
cmd.Flags().StringVar(&options.releaseName, "release-name", releaseName, "name of the helm release to uninstall")
cmd.Flags().BoolVar(&options.wait, "wait", true, "if set, will wait until all the resources are deleted before returning. It will wait for as long as --timeout")
cmd.Flags().BoolVar(&options.dryRun, "dry-run", false, "simulate uninstall and output manifests to be deleted")
cmd.Flags().BoolVar(&options.disableHooks, "no-hooks", false, "prevent hooks from running during uninstallation (pre- and post-uninstall hooks)")
@ -126,11 +123,7 @@ func NewCmd(ctx context.Context, ioStreams genericclioptions.IOStreams) *cobra.C
// run assumes cert-manager was installed as a Helm release named cert-manager.
// this is not configurable to avoid uninstalling non-cert-manager releases.
func run(ctx context.Context, o options) (*release.UninstallReleaseResponse, error) {
log := logf.FromContext(ctx, "install")
if err := o.cfg.Init(o.settings.RESTClientGetter(), o.settings.Namespace(), os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) {
log.Info(fmt.Sprintf(format, v...))
}); err != nil {
if err := o.cfg.Init(o.settings.Factory.RESTClientGetter, o.settings.Namespace(), os.Getenv("HELM_DRIVER"), o.logFn); err != nil {
return nil, fmt.Errorf("o.cfg.Init: %v", err)
}
@ -138,7 +131,7 @@ func run(ctx context.Context, o options) (*release.UninstallReleaseResponse, err
o.client.DryRun = o.dryRun
o.client.Wait = o.wait
res, err := o.client.Run(releaseName)
res, err := o.client.Run(o.releaseName)
if errors.Is(err, driver.ErrReleaseNotFound) {
return nil, fmt.Errorf("release %v not found in namespace %v, did you use the correct namespace?", releaseName, o.settings.Namespace())