command lines: always show flags with hyphens

All Kubernetes commands should show flags with hyphens in their help text even
when the flag originally was defined with underscore. Converting a command to
this style is not breaking its command line API because the old-style parameter
with underscore is accepted as alias.

The easiest solution to achieve this is to set normalization shortly before
running the command in the new central cli.Run or the few places where that
function isn't used yet.

There may be some texts which depends on normalization at flag definition time,
like the --logging-format usage warning. Those get generated assuming that
hyphens will be used.
This commit is contained in:
Patrick Ohly 2021-09-28 20:59:15 +02:00
parent 21d1bcd6b8
commit 00e4a599f6
24 changed files with 13 additions and 73 deletions

View File

@ -27,8 +27,6 @@ package main
import (
"os"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/wait"
cloudprovider "k8s.io/cloud-provider"
"k8s.io/cloud-provider/app"
@ -44,8 +42,6 @@ import (
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
ccmOptions, err := options.NewCloudControllerManagerOptions()
if err != nil {
klog.Fatalf("unable to initialize command options: %v", err)

View File

@ -21,10 +21,7 @@ package main
import (
"os"
"github.com/spf13/pflag"
"k8s.io/component-base/cli"
cliflag "k8s.io/component-base/cli/flag"
_ "k8s.io/component-base/logs/json/register" // for JSON log format registration
_ "k8s.io/component-base/metrics/prometheus/clientgo" // load all the prometheus client-go plugins
_ "k8s.io/component-base/metrics/prometheus/version" // for version metric registration
@ -32,8 +29,6 @@ import (
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
command := app.NewAPIServerCommand()
code := cli.Run(command)
os.Exit(code)

View File

@ -23,10 +23,7 @@ package main
import (
"os"
"github.com/spf13/pflag"
"k8s.io/component-base/cli"
cliflag "k8s.io/component-base/cli/flag"
_ "k8s.io/component-base/logs/json/register" // for JSON log format registration
_ "k8s.io/component-base/metrics/prometheus/clientgo" // load all the prometheus client-go plugin
_ "k8s.io/component-base/metrics/prometheus/version" // for version metric registration
@ -34,8 +31,6 @@ import (
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
command := app.NewControllerManagerCommand()
code := cli.Run(command)
os.Exit(code)

View File

@ -510,7 +510,6 @@ with the apiserver API to configure the proxy.`,
return nil
},
}
cmd.SetGlobalNormalizationFunc(pflag.CommandLine.GetNormalizeFunc())
var err error
opts.config, err = opts.ApplyDefaults(opts.config)

View File

@ -19,18 +19,13 @@ package main
import (
"os"
"github.com/spf13/pflag"
"k8s.io/component-base/cli"
cliflag "k8s.io/component-base/cli/flag"
_ "k8s.io/component-base/metrics/prometheus/restclient" // for client metric registration
_ "k8s.io/component-base/metrics/prometheus/version" // for version metric registration
"k8s.io/kubernetes/cmd/kube-proxy/app"
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
command := app.NewProxyCommand()
code := cli.Run(command)
os.Exit(code)

View File

@ -25,7 +25,6 @@ import (
goruntime "runtime"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apiserver/pkg/authentication/authenticator"
@ -100,7 +99,6 @@ for more information about scheduling and the kube-scheduler component.`,
return nil
},
}
cmd.SetGlobalNormalizationFunc(pflag.CommandLine.GetNormalizeFunc())
fs := cmd.Flags()
verflag.AddFlags(namedFlagSets.FlagSet("global"))

View File

@ -19,10 +19,7 @@ package main
import (
"os"
"github.com/spf13/pflag"
"k8s.io/component-base/cli"
cliflag "k8s.io/component-base/cli/flag"
_ "k8s.io/component-base/logs/json/register" // for JSON log format registration
_ "k8s.io/component-base/metrics/prometheus/clientgo"
_ "k8s.io/component-base/metrics/prometheus/version" // for version metric registration
@ -30,8 +27,6 @@ import (
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
command := app.NewSchedulerCommand()
code := cli.Run(command)
os.Exit(code)

View File

@ -23,15 +23,12 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/component-base/cli"
cliflag "k8s.io/component-base/cli/flag"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/cmd/convert"
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
flags := pflag.NewFlagSet("kubectl-convert", pflag.ExitOnError)
flags.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
pflag.CommandLine = flags
kubeConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag()

View File

@ -19,10 +19,7 @@ package main
import (
"os"
"github.com/spf13/pflag"
"k8s.io/component-base/cli"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/kubectl/pkg/cmd"
// Import to initialize client auth plugins.
@ -30,8 +27,6 @@ import (
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
command := cmd.NewDefaultKubectlCommand()
code := cli.Run(command)
os.Exit(code)

View File

@ -383,7 +383,6 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) {
// AddKubeletConfigFlags adds flags for a specific kubeletconfig.KubeletConfiguration to the specified FlagSet
func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfiguration) {
fs := pflag.NewFlagSet("", pflag.ExitOnError)
fs.SetNormalizeFunc(mainfs.GetNormalizeFunc())
defer func() {
// All KubeletConfiguration flags are now deprecated, and any new flags that point to
// KubeletConfiguration fields are deprecated-on-creation. When removing flags at the end

View File

@ -130,8 +130,6 @@ func (c *hollowNodeConfig) createHollowKubeletOptions() *kubemark.HollowKubletOp
}
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
command := newHollowNodeCommand()
code := cli.Run(command)
os.Exit(code)
@ -160,7 +158,6 @@ func newHollowNodeCommand() *cobra.Command {
return nil
},
}
cmd.SetGlobalNormalizationFunc(pflag.CommandLine.GetNormalizeFunc())
fs := cmd.Flags()
fs.AddGoFlagSet(goflag.CommandLine) // for flags like --docker-only

View File

@ -20,7 +20,6 @@ import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/klog/v2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -101,7 +100,6 @@ func NewCmdConvert(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *co
cmdutil.CheckErr(o.RunConvert())
},
}
cmd.SetGlobalNormalizationFunc(pflag.CommandLine.GetNormalizeFunc())
cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, convert will NOT try to contact api-server but run locally.")
cmd.Flags().StringVar(&o.OutputVersion, "output-version", o.OutputVersion, i18n.T("Output the formatted object with the given group version (for ex: 'extensions/v1beta1')."))

View File

@ -25,7 +25,6 @@ import (
"time"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@ -103,7 +102,6 @@ the cloud specific control loops shipped with Kubernetes.`,
return nil
},
}
cmd.SetGlobalNormalizationFunc(pflag.CommandLine.GetNormalizeFunc())
fs := cmd.Flags()
namedFlagSets := s.Flags(ControllerNames(controllerInitFuncConstructors), ControllersDisabledByDefault.List())

View File

@ -25,7 +25,6 @@ import (
"strings"
"time"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
@ -33,7 +32,6 @@ import (
"k8s.io/cloud-provider/app"
"k8s.io/cloud-provider/app/config"
"k8s.io/cloud-provider/options"
cliflag "k8s.io/component-base/cli/flag"
)
// TearDownFunc is to be called to tear down a test server.
@ -104,7 +102,6 @@ func StartTestServer(t Logger, customFlags []string) (result TestServer, err err
}
fss := cliflag.NamedFlagSets{}
command := app.NewCloudControllerManagerCommand(s, cloudInitializer, app.DefaultInitFuncConstructors, fss, stopCh)
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
commandArgs := []string{}
listeners := []net.Listener{}

View File

@ -23,7 +23,6 @@ package main
import (
"os"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/wait"
cloudprovider "k8s.io/cloud-provider"
"k8s.io/cloud-provider/app"
@ -39,8 +38,6 @@ import (
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
ccmOptions, err := options.NewCloudControllerManagerOptions()
if err != nil {
klog.Fatalf("unable to initialize command options: %v", err)

View File

@ -25,15 +25,20 @@ import (
"github.com/spf13/cobra"
"k8s.io/component-base/logs"
cliflag "k8s.io/component-base/cli/flag"
)
// Run provides the common boilerplate code around executing a cobra command.
// For example, it ensures that logging is set up properly. Logging
// flags get added to the command line if not added already.
// flags get added to the command line if not added already. Flags get normalized
// so that help texts show them with hyphens. Underscores are accepted
// as alternative for the command parameters.
func Run(cmd *cobra.Command) int {
rand.Seed(time.Now().UnixNano())
defer logs.FlushLogs()
cmd.SetGlobalNormalizationFunc(cliflag.WordSepNormalizeFunc)
// This is idempotent.
logs.AddFlags(cmd.PersistentFlags())

View File

@ -24,6 +24,7 @@ import (
"github.com/spf13/pflag"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/component-base/config"
"k8s.io/klog/v2"
)
@ -58,7 +59,10 @@ var supportedLogsFlags = map[string]struct{}{
// BindLoggingFlags binds the Options struct fields to a flagset
func BindLoggingFlags(c *config.LoggingConfiguration, fs *pflag.FlagSet) {
unsupportedFlags := strings.Join(unsupportedLoggingFlagNames(fs.GetNormalizeFunc()), ", ")
// The help text is generated assuming that flags will eventually use
// hyphens, even if currently no normalization function is set for the
// flag set yet.
unsupportedFlags := strings.Join(unsupportedLoggingFlagNames(cliflag.WordSepNormalizeFunc), ", ")
formats := fmt.Sprintf(`"%s"`, strings.Join(LogRegistry.List(), `", "`))
fs.StringVar(&c.Format, "logging-format", c.Format, fmt.Sprintf("Sets the log format. Permitted formats: %s.\nNon-default formats don't honor these flags: %s.\nNon-default choices are currently alpha and subject to change without warning.", formats, unsupportedFlags))
// No new log formats should be added after generation is of flag options

View File

@ -22,10 +22,8 @@ import (
"os"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/component-base/cli"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/component-base/logs"
"k8s.io/klog/v2"
@ -33,11 +31,6 @@ import (
)
func main() {
// NamedFlagSets use the global pflag.CommandLine. We don't use those
// in this command (yet), but set it globally anyway for consistency
// with other commands.
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
command := NewLoggerCommand()
code := cli.Run(command)
os.Exit(code)
@ -56,8 +49,6 @@ func NewLoggerCommand() *cobra.Command {
runLogger()
},
}
cmd.SetGlobalNormalizationFunc(pflag.CommandLine.GetNormalizeFunc())
o.AddFlags(cmd.Flags())
return cmd
}

View File

@ -37,7 +37,7 @@ func TestFlags(t *testing.T) {
want := ` --experimental-logging-sanitization [Experimental] When enabled prevents logging of fields tagged as sensitive (passwords, keys, tokens).
Runtime log sanitization may introduce significant computation overhead and therefore should not be enabled in production.
--logging-format string Sets the log format. Permitted formats: "text".
Non-default formats don't honor these flags: --add_dir_header, --alsologtostderr, --log_backtrace_at, --log_dir, --log_file, --log_file_max_size, --logtostderr, --one_output, --skip_headers, --skip_log_headers, --stderrthreshold, --vmodule.
Non-default formats don't honor these flags: --add-dir-header, --alsologtostderr, --log-backtrace-at, --log-dir, --log-file, --log-file-max-size, --logtostderr, --one-output, --skip-headers, --skip-log-headers, --stderrthreshold, --vmodule.
Non-default choices are currently alpha and subject to change without warning. (default "text")
`
if !assert.Equal(t, want, output.String()) {

View File

@ -27,7 +27,7 @@ import (
func ValidateLoggingConfiguration(c *config.LoggingConfiguration, fldPath *field.Path) field.ErrorList {
errs := field.ErrorList{}
if c.Format != DefaultLogFormat {
// WordSepNormalizeFunc is just a guess. Most commands use it,
// WordSepNormalizeFunc is just a guess. Commands should use it,
// but we cannot know for sure.
allFlags := UnsupportedLoggingFlags(cliflag.WordSepNormalizeFunc)
for _, f := range allFlags {

View File

@ -27,7 +27,6 @@ import (
"time"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
admissionv1 "k8s.io/api/admission/v1"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
@ -59,7 +58,6 @@ Security Standards.`,
},
Args: cobra.NoArgs,
}
cmd.SetGlobalNormalizationFunc(pflag.CommandLine.GetNormalizeFunc())
opts.AddFlags(cmd.Flags())
return cmd

View File

@ -25,9 +25,6 @@ import (
)
func main() {
// Due to historic reasons, this command does *not* normalize command
// line flags.
command := server.NewServerCommand()
code := cli.Run(command)
os.Exit(code)

View File

@ -7,7 +7,6 @@ go 1.16
require (
github.com/google/gofuzz v1.1.0
github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5
k8s.io/apimachinery v0.0.0
k8s.io/apiserver v0.0.0
k8s.io/client-go v0.0.0

View File

@ -19,17 +19,12 @@ package main
import (
"os"
"github.com/spf13/pflag"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/component-base/cli"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/sample-apiserver/pkg/cmd/server"
)
func main() {
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
stopCh := genericapiserver.SetupSignalHandler()
options := server.NewWardleServerOptions(os.Stdout, os.Stderr)
cmd := server.NewCommandStartWardleServer(options, stopCh)