Cleans up renew kube flags and adds --namespace validation

Signed-off-by: JoshVanL <vleeuwenjoshua@gmail.com>
This commit is contained in:
JoshVanL 2020-04-27 14:49:08 +01:00
parent 28639c366b
commit 28f7e7bc78
No known key found for this signature in database
GPG Key ID: E7A7196576A219DA
6 changed files with 100 additions and 41 deletions

View File

@ -8,7 +8,12 @@ go_library(
deps = [
"//cmd/ctl/cmd:go_default_library",
"//pkg/util/cmd:go_default_library",
<<<<<<< HEAD
"@io_k8s_klog//:go_default_library",
=======
"@com_github_spf13_cobra//:go_default_library",
"@io_k8s_cli_runtime//pkg/genericclioptions:go_default_library",
>>>>>>> 65e8ff5db... Cleans up renew kube flags and adds --namespace validation
],
)

View File

@ -17,13 +17,18 @@ limitations under the License.
package cmd
import (
"flag"
"fmt"
"io"
"os"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
// Load all auth plugins
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/klog"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"github.com/jetstack/cert-manager/cmd/ctl/pkg/convert"
"github.com/jetstack/cert-manager/cmd/ctl/pkg/renew"
@ -45,10 +50,19 @@ cert-manager-ctl is a CLI tool manage and configure cert-manager resources for K
matchVersionKubeConfigFlags.AddFlags(cmds.PersistentFlags())
factory := cmdutil.NewFactory(matchVersionKubeConfigFlags)
cmds.Flags().AddGoFlagSet(flag.CommandLine)
flag.CommandLine.Parse([]string{})
fakefs := flag.NewFlagSet("fake", flag.ExitOnError)
klog.InitFlags(fakefs)
if err := fakefs.Parse([]string{"-logtostderr=false"}); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
ioStreams := genericclioptions.IOStreams{In: in, Out: out, ErrOut: err}
cmds.AddCommand(version.NewCmdVersion(ioStreams))
cmds.AddCommand(convert.NewCmdConvert(ioStreams))
cmds.AddCommand(renew.NewCmdRenew(ioStreams, factory))
cmds.AddCommand(renew.NewCmdRenew(ioStreams))
return cmds
}

View File

@ -17,27 +17,16 @@ limitations under the License.
package main
import (
"flag"
"fmt"
"os"
"k8s.io/klog"
ctlcmd "github.com/jetstack/cert-manager/cmd/ctl/cmd"
utilcmd "github.com/jetstack/cert-manager/pkg/util/cmd"
"github.com/jetstack/cert-manager/pkg/util/cmd"
)
func main() {
stopCh := utilcmd.SetupSignalHandler()
cmd := ctlcmd.NewCertManagerCtlCommand(os.Stdin, os.Stdout, os.Stderr, stopCh)
cmd.Flags().AddGoFlagSet(flag.CommandLine)
flag.CommandLine.Parse([]string{})
fakefs := flag.NewFlagSet("fake", flag.ExitOnError)
klog.InitFlags(fakefs)
if err := fakefs.Parse([]string{"-logtostderr=false"}); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
stopCh := cmd.SetupSignalHandler()
cmd := NewCertManagerCtlCommand(os.Stdin, os.Stdout, os.Stderr, stopCh)
if err := cmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
}

View File

@ -15,7 +15,9 @@ go_library(
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
"@io_k8s_cli_runtime//pkg/genericclioptions:go_default_library",
"@io_k8s_client_go//kubernetes:go_default_library",
"@io_k8s_client_go//plugin/pkg/client/auth:go_default_library",
"@io_k8s_client_go//rest:go_default_library",
"@io_k8s_klog//:go_default_library",
"@io_k8s_kubectl//pkg/cmd/util:go_default_library",
"@io_k8s_kubectl//pkg/util/i18n:go_default_library",
"@io_k8s_kubectl//pkg/util/templates:go_default_library",
@ -40,4 +42,5 @@ go_test(
name = "go_default_test",
srcs = ["renew_test.go"],
embed = [":go_default_library"],
deps = ["@io_k8s_cli_runtime//pkg/genericclioptions:go_default_library"],
)

View File

@ -19,14 +19,19 @@ package renew
import (
"context"
"errors"
"flag"
"fmt"
"os"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
// Load all auth plugins
_ "k8s.io/client-go/plugin/pkg/client/auth"
restclient "k8s.io/client-go/rest"
"k8s.io/klog"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
@ -39,27 +44,27 @@ import (
var (
long = templates.LongDesc(i18n.T(`
Mark cert-manager Certificate resources for manual renewal.
`))
Mark cert-manager Certificate resources for manual renewal.`))
example = templates.Examples(i18n.T(`
# Renew the Certificates named 'my-app' and 'vault' in the current context namespace.
ctl renew my-app vault
# Renew the Certificates named 'my-app' and 'vault' in the current context namespace.
ctl renew my-app vault
# Renew all Certificates in the 'kube-system' namespace.
ctl renew --namespace kube-system --all
# Renew all Certificates in the 'kube-system' namespace.
ctl renew --namespace kube-system --all
# Renew all Certificates in all namespaces that have the label 'app=my-service'.
ctl renew --all-namespaces -l app=my-service`))
# Renew all Certificates in all namespaces, provided those Certificates have the label 'app=my-service
ctl renew --all-namespaces -l app=my-service`))
)
// Options is a struct to support renew command
type Options struct {
// The Namespace that the Certificate to be renewed resided in
Namespace string
CMClient cmclient.Interface
RestConfig *restclient.Config
RESTConfig *restclient.Config
// The Namespace that the Certificate to be renewed resided in.
// This flag registration is handled by cmdutil.Factory
Namespace string
LabelSelector string
All bool
AllNamespaces bool
@ -75,17 +80,18 @@ func NewOptions(ioStreams genericclioptions.IOStreams) *Options {
}
// NewCmdRenew returns a cobra command for renewing Certificates
func NewCmdRenew(ioStreams genericclioptions.IOStreams, factory cmdutil.Factory) *cobra.Command {
func NewCmdRenew(ioStreams genericclioptions.IOStreams) *cobra.Command {
o := NewOptions(ioStreams)
var factory cmdutil.Factory
cmd := &cobra.Command{
Use: "renew",
Short: "Mark a Certificate for manual renewal",
Long: "Mark a Certificate for manual renewal",
Long: long,
Example: example,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(factory))
cmdutil.CheckErr(o.Validate(args))
cmdutil.CheckErr(o.Validate(cmd, args))
cmdutil.CheckErr(o.Run(args))
},
}
@ -94,11 +100,26 @@ func NewCmdRenew(ioStreams genericclioptions.IOStreams, factory cmdutil.Factory)
cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If present, mark Certificates across namespaces for manual renewal. Namespace in current context is ignored even if specified with --namespace.")
cmd.Flags().BoolVar(&o.All, "all", o.All, "Renew all Certificates in the given Namespace, or all namespaces with --all-namespaces enabled.")
kubeConfigFlags := genericclioptions.NewConfigFlags(true)
kubeConfigFlags.AddFlags(cmd.PersistentFlags())
matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags)
matchVersionKubeConfigFlags.AddFlags(cmd.PersistentFlags())
factory = cmdutil.NewFactory(matchVersionKubeConfigFlags)
cmd.Flags().AddGoFlagSet(flag.CommandLine)
flag.CommandLine.Parse([]string{})
fakefs := flag.NewFlagSet("fake", flag.ExitOnError)
klog.InitFlags(fakefs)
if err := fakefs.Parse([]string{"-logtostderr=false"}); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
return cmd
}
// Validate validates the provided options
func (o *Options) Validate(args []string) error {
func (o *Options) Validate(cmd *cobra.Command, args []string) error {
if len(o.LabelSelector) > 0 && len(args) > 0 {
return errors.New("cannot specify Certificate names in conjunction with label selectors")
}
@ -111,6 +132,10 @@ func (o *Options) Validate(args []string) error {
return errors.New("cannot specify Certificate names in conjunction with --all flag")
}
if o.All && cmd.PersistentFlags().Changed("namespace") {
return errors.New("cannot specify --namespace flag in conjunction with --all flag")
}
return nil
}
@ -122,12 +147,12 @@ func (o *Options) Complete(f cmdutil.Factory) error {
return err
}
o.RestConfig, err = f.ToRESTConfig()
o.RESTConfig, err = f.ToRESTConfig()
if err != nil {
return err
}
o.CMClient, err = cmclient.NewForConfig(o.RestConfig)
o.CMClient, err = cmclient.NewForConfig(o.RESTConfig)
if err != nil {
return err
}
@ -141,10 +166,8 @@ func (o *Options) Run(args []string) error {
nss := []corev1.Namespace{{ObjectMeta: metav1.ObjectMeta{Name: o.Namespace}}}
// TODO: handle network context
if o.AllNamespaces {
kubeClient, err := kubernetes.NewForConfig(o.RestConfig)
kubeClient, err := kubernetes.NewForConfig(o.RESTConfig)
if err != nil {
return err
}

View File

@ -18,13 +18,20 @@ package renew
import (
"testing"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
type stringFlag struct {
name, value string
}
func TestValidate(t *testing.T) {
tests := map[string]struct {
options *Options
args []string
expErr bool
options *Options
args []string
setStringFlags []stringFlag
expErr bool
}{
"If there are arguments, as well as label selector, error": {
options: &Options{
@ -55,12 +62,30 @@ func TestValidate(t *testing.T) {
},
expErr: false,
},
"If --namespace and --all namespace specified, error": {
options: &Options{
All: true,
},
setStringFlags: []stringFlag{
{name: "namespace", value: "foo"},
},
expErr: true,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
err := test.options.Validate(test.args)
cmd := NewCmdRenew(genericclioptions.IOStreams{})
if test.setStringFlags != nil {
for _, s := range test.setStringFlags {
if err := cmd.PersistentFlags().Set(s.name, s.value); err != nil {
t.Fatal(err)
}
}
}
err := test.options.Validate(cmd, test.args)
if test.expErr != (err != nil) {
t.Errorf("expected error=%t got=%v",
test.expErr, err)