Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into release-1.28
Browse files Browse the repository at this point in the history
  • Loading branch information
k8s-release-robot committed Aug 10, 2023
2 parents ea916b5 + 18c3c7e commit 52bf1d6
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 3 deletions.
45 changes: 43 additions & 2 deletions cmd/kube-proxy/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func NewOptions() *Options {
}

// Complete completes all the required options.
func (o *Options) Complete() error {
func (o *Options) Complete(fs *pflag.FlagSet) error {
if len(o.ConfigFile) == 0 && len(o.WriteConfigTo) == 0 {
o.config.HealthzBindAddress = addressFromDeprecatedFlags(o.config.HealthzBindAddress, o.healthzPort)
o.config.MetricsBindAddress = addressFromDeprecatedFlags(o.config.MetricsBindAddress, o.metricsPort)
Expand All @@ -247,6 +247,14 @@ func (o *Options) Complete() error {
if err != nil {
return err
}

// Before we overwrite the config which holds the parsed
// command line parameters, we need to copy all modified
// logging settings over to the loaded config (i.e. logging
// command line flags have priority). Otherwise `--config
// ... -v=5` doesn't work (config resets verbosity even
// when it contains no logging settings).
copyLogsFromFlags(fs, &c.Logging)
o.config = c

if err := o.initWatcher(); err != nil {
Expand All @@ -263,6 +271,39 @@ func (o *Options) Complete() error {
return utilfeature.DefaultMutableFeatureGate.SetFromMap(o.config.FeatureGates)
}

// copyLogsFromFlags applies the logging flags from the given flag set to the given
// configuration. Fields for which the corresponding flag was not used are left
// unmodified. For fields that have multiple values (like vmodule), the values from
// the flags get joined so that the command line flags have priority.
//
// TODO (pohly): move this to logsapi
func copyLogsFromFlags(from *pflag.FlagSet, to *logsapi.LoggingConfiguration) error {
var cloneFS pflag.FlagSet
logsapi.AddFlags(to, &cloneFS)
vmodule := to.VModule
to.VModule = nil
var err error
cloneFS.VisitAll(func(f *pflag.Flag) {
if err != nil {
return
}
fsFlag := from.Lookup(f.Name)
if fsFlag == nil {
err = fmt.Errorf("logging flag %s not found in flag set", f.Name)
return
}
if !fsFlag.Changed {
return
}
if setErr := f.Value.Set(fsFlag.Value.String()); setErr != nil {
err = fmt.Errorf("copying flag %s value: %v", f.Name, setErr)
return
}
})
to.VModule = append(to.VModule, vmodule...)
return err
}

// Creates a new filesystem watcher and adds watches for the config file.
func (o *Options) initWatcher() error {
fswatcher := filesystem.NewFsnotifyWatcher()
Expand Down Expand Up @@ -476,7 +517,7 @@ with the apiserver API to configure the proxy.`,
return fmt.Errorf("failed os init: %w", err)
}

if err := opts.Complete(); err != nil {
if err := opts.Complete(cmd.Flags()); err != nil {
return fmt.Errorf("failed complete: %w", err)
}

Expand Down
3 changes: 2 additions & 1 deletion cmd/kube-proxy/app/server_others_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"testing"
"time"

"github.com/spf13/pflag"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -563,7 +564,7 @@ detectLocalMode: "BridgeInterface"`)

opt := NewOptions()
opt.ConfigFile = file.Name()
err = opt.Complete()
err = opt.Complete(new(pflag.FlagSet))
if err != nil {
t.Fatal(err)
}
Expand Down
124 changes: 124 additions & 0 deletions cmd/kube-proxy/app/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,18 @@ package app
import (
"errors"
"fmt"
"io/ioutil"
"path"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientsetfake "k8s.io/client-go/kubernetes/fake"
componentbaseconfig "k8s.io/component-base/config"
Expand Down Expand Up @@ -364,6 +369,125 @@ func TestProcessHostnameOverrideFlag(t *testing.T) {
}
}

// TestOptionsComplete checks that command line flags are combined with a
// config properly.
func TestOptionsComplete(t *testing.T) {
header := `apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
`

// Determine default config (depends on platform defaults).
o := NewOptions()
require.NoError(t, o.Complete(new(pflag.FlagSet)))
expected := o.config

config := header + `logging:
format: json
flushFrequency: 1s
verbosity: 10
vmodule:
- filePattern: foo.go
verbosity: 6
- filePattern: bar.go
verbosity: 8
`
expectedLoggingConfig := logsapi.LoggingConfiguration{
Format: "json",
FlushFrequency: logsapi.TimeOrMetaDuration{Duration: metav1.Duration{Duration: time.Second}, SerializeAsString: true},
Verbosity: 10,
VModule: []logsapi.VModuleItem{
{
FilePattern: "foo.go",
Verbosity: 6,
},
{
FilePattern: "bar.go",
Verbosity: 8,
},
},
Options: logsapi.FormatOptions{
JSON: logsapi.JSONOptions{
InfoBufferSize: resource.QuantityValue{Quantity: resource.MustParse("0")},
},
},
}

for name, tc := range map[string]struct {
config string
flags []string
expected *kubeproxyconfig.KubeProxyConfiguration
}{
"empty": {
expected: expected,
},
"empty-config": {
config: header,
expected: expected,
},
"logging-config": {
config: config,
expected: func() *kubeproxyconfig.KubeProxyConfiguration {
c := expected.DeepCopy()
c.Logging = *expectedLoggingConfig.DeepCopy()
return c
}(),
},
"flags": {
flags: []string{
"-v=7",
"--vmodule", "goo.go=8",
},
expected: func() *kubeproxyconfig.KubeProxyConfiguration {
c := expected.DeepCopy()
c.Logging.Verbosity = 7
c.Logging.VModule = append(c.Logging.VModule, logsapi.VModuleItem{
FilePattern: "goo.go",
Verbosity: 8,
})
return c
}(),
},
"both": {
config: config,
flags: []string{
"-v=7",
"--vmodule", "goo.go=8",
"--ipvs-scheduler", "some-scheduler", // Overwritten by config.
},
expected: func() *kubeproxyconfig.KubeProxyConfiguration {
c := expected.DeepCopy()
c.Logging = *expectedLoggingConfig.DeepCopy()
// Flag wins.
c.Logging.Verbosity = 7
// Flag and config get merged with command line flags first.
c.Logging.VModule = append([]logsapi.VModuleItem{
{
FilePattern: "goo.go",
Verbosity: 8,
},
}, c.Logging.VModule...)
return c
}(),
},
} {
t.Run(name, func(t *testing.T) {
options := NewOptions()
fs := new(pflag.FlagSet)
options.AddFlags(fs)
flags := tc.flags
if len(tc.config) > 0 {
tmp := t.TempDir()
configFile := path.Join(tmp, "kube-proxy.conf")
require.NoError(t, ioutil.WriteFile(configFile, []byte(tc.config), 0666))
flags = append(flags, "--config", configFile)
}
require.NoError(t, fs.Parse(flags))
require.NoError(t, options.Complete(fs))
assert.Equal(t, tc.expected, options.config)
})
}
}

type fakeProxyServerLongRun struct{}

// Run runs the specified ProxyServer.
Expand Down

0 comments on commit 52bf1d6

Please sign in to comment.