logs: replace config methods with functions

API types are only supposed to have methods related to serialization.
This commit is contained in:
Patrick Ohly 2022-05-31 10:08:54 +02:00
parent ea3f25f49b
commit 4c6338ac0f
15 changed files with 40 additions and 34 deletions

View File

@ -29,6 +29,7 @@ import (
"k8s.io/component-base/logs"
"k8s.io/component-base/metrics"
logsapi "k8s.io/component-base/logs/api/v1"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/cluster/ports"
"k8s.io/kubernetes/pkg/controlplane/reconcilers"
@ -155,7 +156,7 @@ func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) {
s.EgressSelector.AddFlags(fss.FlagSet("egress selector"))
s.Admission.AddFlags(fss.FlagSet("admission"))
s.Metrics.AddFlags(fss.FlagSet("metrics"))
s.Logs.AddFlags(fss.FlagSet("logs"))
logsapi.AddFlags(s.Logs, fss.FlagSet("logs"))
s.Traces.AddFlags(fss.FlagSet("traces"))
// Note: the weird ""+ in below lines seems to be the only way to get gofmt to

View File

@ -110,7 +110,7 @@ cluster's shared state through which all other components interact.`,
// Activate logging as soon as possible, after that
// show flags with the final logging configuration.
if err := s.Logs.ValidateAndApply(utilfeature.DefaultFeatureGate); err != nil {
if err := logsapi.ValidateAndApply(s.Logs, utilfeature.DefaultFeatureGate); err != nil {
return err
}
cliflag.PrintFlags(fs)

View File

@ -124,7 +124,7 @@ controller, and serviceaccounts controller.`,
// Activate logging as soon as possible, after that
// show flags with the final logging configuration.
if err := s.Logs.ValidateAndApply(utilfeature.DefaultFeatureGate); err != nil {
if err := logsapi.ValidateAndApply(s.Logs, utilfeature.DefaultFeatureGate); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}

View File

@ -34,6 +34,7 @@ import (
cpoptions "k8s.io/cloud-provider/options"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/component-base/logs"
logsapi "k8s.io/component-base/logs/api/v1"
"k8s.io/component-base/metrics"
cmoptions "k8s.io/controller-manager/options"
kubectrlmgrconfigv1alpha1 "k8s.io/kube-controller-manager/config/v1alpha1"
@ -256,7 +257,7 @@ func (s *KubeControllerManagerOptions) Flags(allControllers []string, disabledBy
s.SAController.AddFlags(fss.FlagSet("serviceaccount controller"))
s.TTLAfterFinishedController.AddFlags(fss.FlagSet("ttl-after-finished controller"))
s.Metrics.AddFlags(fss.FlagSet("metrics"))
s.Logs.AddFlags(fss.FlagSet("logs"))
logsapi.AddFlags(s.Logs, fss.FlagSet("logs"))
fs := fss.FlagSet("misc")
fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig).")

View File

@ -40,6 +40,7 @@ import (
componentbaseconfig "k8s.io/component-base/config"
"k8s.io/component-base/config/options"
"k8s.io/component-base/logs"
logsapi "k8s.io/component-base/logs/api/v1"
"k8s.io/component-base/metrics"
schedulerappconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config"
"k8s.io/kubernetes/pkg/scheduler"
@ -194,7 +195,7 @@ func (o *Options) initFlags() {
options.BindLeaderElectionFlags(o.LeaderElection, nfs.FlagSet("leader election"))
utilfeature.DefaultMutableFeatureGate.AddFlag(nfs.FlagSet("feature gate"))
o.Metrics.AddFlags(nfs.FlagSet("metrics"))
o.Logs.AddFlags(nfs.FlagSet("logs"))
logsapi.AddFlags(o.Logs, nfs.FlagSet("logs"))
o.Flags = &nfs
}

View File

@ -120,7 +120,7 @@ func runCommand(cmd *cobra.Command, opts *options.Options, registryOptions ...Op
// Activate logging as soon as possible, after that
// show flags with the final logging configuration.
if err := opts.Logs.ValidateAndApply(utilfeature.DefaultFeatureGate); err != nil {
if err := logsapi.ValidateAndApply(opts.Logs, utilfeature.DefaultFeatureGate); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature"
cliflag "k8s.io/component-base/cli/flag"
logsapi "k8s.io/component-base/logs/api/v1"
"k8s.io/kubelet/config/v1beta1"
kubeletapis "k8s.io/kubelet/pkg/apis"
"k8s.io/kubernetes/pkg/cluster/ports"
@ -499,7 +500,7 @@ func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfig
fs.StringSliceVar(&c.EnforceNodeAllocatable, "enforce-node-allocatable", c.EnforceNodeAllocatable, "A comma separated list of levels of node allocatable enforcement to be enforced by kubelet. Acceptable options are 'none', 'pods', 'system-reserved', and 'kube-reserved'. If the latter two options are specified, '--system-reserved-cgroup' and '--kube-reserved-cgroup' must also be set, respectively. If 'none' is specified, no additional options should be set. See https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/ for more details.")
fs.StringVar(&c.SystemReservedCgroup, "system-reserved-cgroup", c.SystemReservedCgroup, "Absolute name of the top level cgroup that is used to manage non-kubernetes components for which compute resources were reserved via '--system-reserved' flag. Ex. '/system-reserved'. [default='']")
fs.StringVar(&c.KubeReservedCgroup, "kube-reserved-cgroup", c.KubeReservedCgroup, "Absolute name of the top level cgroup that is used to manage kubernetes components for which compute resources were reserved via '--kube-reserved' flag. Ex. '/kube-reserved'. [default='']")
c.Logging.AddFlags(fs)
logsapi.AddFlags(&c.Logging, fs)
// Memory Manager Flags
fs.StringVar(&c.MemoryManagerPolicy, "memory-manager-policy", c.MemoryManagerPolicy, "Memory Manager policy to use. Possible values: 'None', 'Static'.")

View File

@ -215,7 +215,7 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
// Config and flags parsed, now we can initialize logging.
logs.InitLogs()
if err := kubeletConfig.Logging.ValidateAndApplyAsField(utilfeature.DefaultFeatureGate, field.NewPath("logging")); err != nil {
if err := logsapi.ValidateAndApplyAsField(&kubeletConfig.Logging, utilfeature.DefaultFeatureGate, field.NewPath("logging")); err != nil {
return fmt.Errorf("initialize logging: %v", err)
}
cliflag.PrintFlags(cleanFlagSet)

View File

@ -24,6 +24,7 @@ import (
kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1"
// TODO: Cut references to k8s.io/kubernetes, eventually there should be none from this package
logsapi "k8s.io/component-base/logs/api/v1"
"k8s.io/kubernetes/pkg/cluster/ports"
"k8s.io/kubernetes/pkg/kubelet/qos"
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
@ -244,7 +245,7 @@ func SetDefaults_KubeletConfiguration(obj *kubeletconfigv1beta1.KubeletConfigura
obj.VolumePluginDir = DefaultVolumePluginDir
}
// Use the Default LoggingConfiguration option
obj.Logging.SetRecommendedLoggingConfiguration()
logsapi.SetRecommendedLoggingConfiguration(&obj.Logging)
if obj.EnableSystemLogHandler == nil {
obj.EnableSystemLogHandler = utilpointer.BoolPtr(true)
}

View File

@ -25,6 +25,7 @@ import (
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/component-base/featuregate"
logsapi "k8s.io/component-base/logs/api/v1"
"k8s.io/component-base/metrics"
"k8s.io/kubernetes/pkg/features"
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
@ -236,7 +237,7 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration, featur
}
allErrors = append(allErrors, metrics.ValidateShowHiddenMetricsVersion(kc.ShowHiddenMetricsForVersion)...)
if errs := kc.Logging.Validate(localFeatureGate, field.NewPath("logging")); len(errs) > 0 {
if errs := logsapi.Validate(&kc.Logging, localFeatureGate, field.NewPath("logging")); len(errs) > 0 {
allErrors = append(allErrors, errs.ToAggregate().Errors()...)
}

View File

@ -50,7 +50,7 @@ const (
// NewLoggingConfiguration returns a struct holding the default logging configuration.
func NewLoggingConfiguration() *LoggingConfiguration {
c := LoggingConfiguration{}
c.SetRecommendedLoggingConfiguration()
SetRecommendedLoggingConfiguration(&c)
return &c
}
@ -61,26 +61,26 @@ func NewLoggingConfiguration() *LoggingConfiguration {
//
// The optional FeatureGate controls logging features. If nil, the default for
// these features is used.
func (c *LoggingConfiguration) ValidateAndApply(featureGate featuregate.FeatureGate) error {
return c.ValidateAndApplyAsField(featureGate, nil)
func ValidateAndApply(c *LoggingConfiguration, featureGate featuregate.FeatureGate) error {
return ValidateAndApplyAsField(c, featureGate, nil)
}
// ValidateAndApplyAsField is a variant of ValidateAndApply that should be used
// when the LoggingConfiguration is embedded in some larger configuration
// structure.
func (c *LoggingConfiguration) ValidateAndApplyAsField(featureGate featuregate.FeatureGate, fldPath *field.Path) error {
errs := c.Validate(featureGate, fldPath)
func ValidateAndApplyAsField(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) error {
errs := Validate(c, featureGate, fldPath)
if len(errs) > 0 {
return errs.ToAggregate()
}
return c.apply(featureGate)
return apply(c, featureGate)
}
// Validate can be used to check for invalid settings without applying them.
// Most binaries should validate and apply the logging configuration as soon
// as possible via ValidateAndApply. The field path is optional: nil
// can be passed when the struct is not embedded in some larger struct.
func (c *LoggingConfiguration) Validate(featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
func Validate(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
errs := field.ErrorList{}
if c.Format != DefaultLogFormat {
// WordSepNormalizeFunc is just a guess. Commands should use it,
@ -127,17 +127,17 @@ func (c *LoggingConfiguration) Validate(featureGate featuregate.FeatureGate, fld
}
}
errs = append(errs, c.validateFormatOptions(featureGate, fldPath.Child("options"))...)
errs = append(errs, validateFormatOptions(c, featureGate, fldPath.Child("options"))...)
return errs
}
func (c *LoggingConfiguration) validateFormatOptions(featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
func validateFormatOptions(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
errs := field.ErrorList{}
errs = append(errs, c.validateJSONOptions(featureGate, fldPath.Child("json"))...)
errs = append(errs, validateJSONOptions(c, featureGate, fldPath.Child("json"))...)
return errs
}
func (c *LoggingConfiguration) validateJSONOptions(featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
func validateJSONOptions(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
errs := field.ErrorList{}
if gate := LoggingAlphaOptions; c.Options.JSON.SplitStream && !featureEnabled(featureGate, gate) {
errs = append(errs, field.Forbidden(fldPath.Child("splitStream"), fmt.Sprintf("Feature %s is disabled", gate)))
@ -156,7 +156,7 @@ func featureEnabled(featureGate featuregate.FeatureGate, feature featuregate.Fea
return enabled
}
func (c *LoggingConfiguration) apply(featureGate featuregate.FeatureGate) error {
func apply(c *LoggingConfiguration, featureGate featuregate.FeatureGate) error {
contextualLoggingEnabled := contextualLoggingDefault
if featureGate != nil {
contextualLoggingEnabled = featureGate.Enabled(ContextualLogging)
@ -182,7 +182,7 @@ func (c *LoggingConfiguration) apply(featureGate featuregate.FeatureGate) error
}
// AddFlags adds command line flags for the configuration.
func (c *LoggingConfiguration) AddFlags(fs *pflag.FlagSet) {
func AddFlags(c *LoggingConfiguration, fs *pflag.FlagSet) {
// 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.
@ -210,7 +210,7 @@ func (c *LoggingConfiguration) AddFlags(fs *pflag.FlagSet) {
// Consumers who embed LoggingConfiguration in their own configuration structs
// may set custom defaults and then should call this function to add the
// global defaults.
func (c *LoggingConfiguration) SetRecommendedLoggingConfiguration() {
func SetRecommendedLoggingConfiguration(c *LoggingConfiguration) {
if c.Format == "" {
c.Format = "text"
}

View File

@ -35,7 +35,7 @@ func TestFlags(t *testing.T) {
c := NewLoggingConfiguration()
fs := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError)
output := bytes.Buffer{}
c.AddFlags(fs)
AddFlags(c, fs)
fs.SetOutput(&output)
fs.PrintDefaults()
want := ` --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
@ -88,12 +88,12 @@ func TestOptions(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
c := NewLoggingConfiguration()
fs := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError)
c.AddFlags(fs)
AddFlags(c, fs)
fs.Parse(tc.args)
if !assert.Equal(t, tc.want, c) {
t.Errorf("Wrong Validate() result for %q. expect %v, got %v", tc.name, tc.want, c)
}
errs := c.ValidateAndApply(nil /* We don't care about feature gates here. */)
errs := ValidateAndApply(c, nil /* We don't care about feature gates here. */)
defer klog.StopFlushDaemon()
if !assert.ElementsMatch(t, tc.errs, errs) {
t.Errorf("Wrong Validate() result for %q.\n expect:\t%+v\n got:\t%+v", tc.name, tc.errs, errs)
@ -120,7 +120,7 @@ func testContextualLogging(t *testing.T, enabled bool) {
AddFeatureGates(featureGate)
err = featureGate.SetFromMap(map[string]bool{string(ContextualLogging): enabled})
require.NoError(t, err)
err = c.ValidateAndApply(featureGate)
err = ValidateAndApply(c, featureGate)
require.NoError(t, err)
defer klog.StopFlushDaemon()
defer klog.EnableContextualLogging(true)

View File

@ -151,7 +151,7 @@ func TestValidation(t *testing.T) {
if featureGate == nil {
featureGate = defaultFeatureGate
}
err := test.config.Validate(featureGate, test.path)
err := Validate(&test.config, featureGate, test.path)
if len(err) == 0 {
if test.expectErrors != "" {
t.Fatalf("did not get expected error(s): %s", test.expectErrors)

View File

@ -53,7 +53,7 @@ func NewLoggerCommand() *cobra.Command {
cmd := &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
logs.InitLogs()
if err := c.ValidateAndApply(featureGate); err != nil {
if err := logsapi.ValidateAndApply(c, featureGate); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
@ -67,7 +67,7 @@ func NewLoggerCommand() *cobra.Command {
}
logsapi.AddFeatureGates(featureGate)
featureGate.AddFlag(cmd.Flags())
c.AddFlags(cmd.Flags())
logsapi.AddFlags(c, cmd.Flags())
return cmd
}

View File

@ -34,7 +34,7 @@ func TestJSONFlag(t *testing.T) {
c := logsapi.NewLoggingConfiguration()
fs := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError)
output := bytes.Buffer{}
c.AddFlags(fs)
logsapi.AddFlags(c, fs)
fs.SetOutput(&output)
fs.PrintDefaults()
wantSubstring := `Permitted formats: "json" (gated by LoggingBetaOptions), "text".`
@ -142,7 +142,7 @@ func TestJSONFormatRegister(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
c := logsapi.NewLoggingConfiguration()
fs := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError)
c.AddFlags(fs)
logsapi.AddFlags(c, fs)
fs.Parse(tc.args)
if !assert.Equal(t, tc.want, c) {
t.Errorf("Wrong Validate() result for %q. expect %v, got %v", tc.name, tc.want, c)
@ -155,7 +155,7 @@ func TestJSONFormatRegister(t *testing.T) {
err := mutable.SetFromMap(map[string]bool{string(logsapi.ContextualLogging): tc.contextualLogging})
require.NoError(t, err)
featureGate = mutable
errs := c.ValidateAndApply(featureGate)
errs := logsapi.ValidateAndApply(c, featureGate)
defer klog.ClearLogger()
if !assert.ElementsMatch(t, tc.errs, errs) {
t.Errorf("Wrong Validate() result for %q.\n expect:\t%+v\n got:\t%+v", tc.name, tc.errs, errs)