Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable strict serializer in kube-proxy #82927

Merged

Conversation

obitech
Copy link
Contributor

@obitech obitech commented Sep 20, 2019

What type of PR is this?
/kind feature

What this PR does / why we need it:
With strict serializers enabled, an error will be thrown on things such as duplicate or unknown fields when parsing a YAML file. This will improve code quality of user's configuration files as it enforces a proper configuration file to be present when starting a component.

Which issue(s) this PR fixes:

Ref #82924

Special notes for your reviewer:

Does this PR introduce a user-facing change?:

kube-proxy: a configuration file specified via `--config` is now loaded with strict deserialization, which fails if the config file contains duplicate or unknown fields. This protects against accidentally running with config files that are malformed, mis-indented, or have typos in field names, and getting unexpected behavior.

Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:

NONE

/sig cluster-lifecycle
/sig api-machinery
/wg component-standard
/cc @mtaufen @stealthybox

@k8s-ci-robot k8s-ci-robot added the release-note-none Denotes a PR that doesn't merit a release note. label Sep 20, 2019
@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. kind/feature Categorizes issue or PR as related to a new feature. sig/cluster-lifecycle Categorizes an issue or PR as relevant to SIG Cluster Lifecycle. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. wg/component-standard Categorizes an issue or PR as relevant to WG Component Standard. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. labels Sep 20, 2019
@obitech obitech added this to In progress in component-base Sep 20, 2019
@k8s-ci-robot k8s-ci-robot added the sig/network Categorizes an issue or PR as relevant to SIG Network. label Sep 20, 2019
@obitech
Copy link
Contributor Author

obitech commented Sep 20, 2019

/assign @thockin

Copy link
Member

@stealthybox stealthybox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job on this!
Here's my feedback:

@@ -279,35 +281,130 @@ nodePortAddresses:

// TestLoadConfigFailures tests failure modes for loadConfig()
func TestLoadConfigFailures(t *testing.T) {
duplicateKeyYAMLTemplate := `bindAddress: 0.0.0.0
bindAddress: 1.2.3.4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could just represent the minimal config for these:

duplicateKeyYAMLTemplate := `bindAddress: 0.0.0.0
bindAddress: 1.2.3.4
clusterCIDR: "1.2.3.0/24"
configSyncPeriod: 15s
configSyncPeriod: 30s
kind: KubeProxyConfiguration`

Looking at the test runner, the apiVersion is appended to every test to reduce maintenance burden.
Being less specific about the fields make these strings easier to maintain.

There's already a happy path test for TestLoadConfig

It's possible to prepend some unrelated fields if a more robust test is desired, but this isn't a rigorous suite for the YAML parser.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's much cleaner. I provided a basicYAMLTemplate which gets appended to in each tests accordingly.

{
name: "Duplicate fields",
config: duplicateKeyYAMLTemplate,
errFn: func(err error) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can change to:

errFn: kuberuntime.IsStrictDecodingError

That function contains a nil check, and it should already have been asserted an error exists before running it because of the nature of this range test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

},
{
name: "Bad config type test",
config: "kind: KubeSchedulerConfiguration",
expErr: "no kind",
errFn: func(err error) bool { return err != nil },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions can be omitted since the test will assert an error exists for every case.
Leaving the fields unspecified will result in a zero-value of nil.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

options := NewOptions()
config := fmt.Sprintf("%s\n%s", version, tc.config)
_, err := options.loadConfig([]byte(config))
if assert.Error(t, err, tc.name) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition of t.Run 👍

We should keep this:

if assert.Error(t, err, tc.name) {

This whole test is about failures, so we assert that one should exist.
This is equivalent to if err != nil. It protects us from operating on nil errors.
The sneaky benefit of using assert.Error is that it will also fail the test if it is a nil error.

We can keep the old test behavior for string matching the error text.
To gate it, just check for the zero value "".
The gate is not strictly necessary since Contains will always pass with an empty string, but it's more clear.

We should also check that errFn != nil before running it, otherwise go will
panic: runtime error: invalid memory address or nil pointer dereference.
Gating this has the added benefit of making this errFn optional as well.

Finally, we should use the assert library to maintain style.

ex:

t.Run(tc.name, func(t *testing.T) {
	options := NewOptions()
	config := fmt.Sprintf("%s\n%s", version, tc.config)
	_, err := options.loadConfig([]byte(config))
	if assert.Error(t, err, tc.name) {
		if tc.expErr != "" {
			assert.Contains(t, err.Error(), tc.expErr, tc.name)
		}
		if tc.errFn != nil {
			assert.True(t, tc.errFn(err), tc.name)
		}
	}
})

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errFn may be better named as checkFn.
The verb/purpose is not "to error" but rather "to check and return a bool".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it much better! I adjusted it accordingly

@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Sep 23, 2019
@stealthybox
Copy link
Member

/retest
/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Sep 23, 2019
@stealthybox
Copy link
Member

/retest

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Sep 23, 2019
@obitech
Copy link
Contributor Author

obitech commented Sep 23, 2019

/retest

@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed release-note-none Denotes a PR that doesn't merit a release note. labels Sep 23, 2019
@roycaihw
Copy link
Member

/cc @caesarxuchao

@caesarxuchao
Copy link
Member

/assign

@obitech
Copy link
Contributor Author

obitech commented Oct 7, 2019

/assign @caseydavenport @bowei @dcbw

@mtaufen mtaufen added the priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. label Oct 8, 2019
@k8s-ci-robot k8s-ci-robot removed the needs-priority Indicates a PR lacks a `priority/foo` label and requires one. label Oct 8, 2019
@thockin
Copy link
Member

thockin commented Oct 9, 2019

Thanks!

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 9, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: obitech, thockin

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 9, 2019
@k8s-ci-robot k8s-ci-robot merged commit 0ff761b into kubernetes:master Oct 9, 2019
@k8s-ci-robot k8s-ci-robot added this to the v1.17 milestone Oct 9, 2019
@obitech obitech moved this from In progress to Done in component-base Oct 10, 2019
@@ -29,7 +29,7 @@ var (
Scheme = runtime.NewScheme()
// Codecs provides methods for retrieving codecs and serializers for specific
// versions and content types.
Codecs = serializer.NewCodecFactory(Scheme)
Codecs = serializer.NewCodecFactory(Scheme, serializer.EnableStrict)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@obitech I noticed this merged, did you plan to add a lenient path to this PR before then?

ohsewon pushed a commit to ohsewon/kubernetes that referenced this pull request Oct 16, 2019
…rializer

Enable strict serializer in kube-proxy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. sig/cluster-lifecycle Categorizes an issue or PR as relevant to SIG Cluster Lifecycle. sig/network Categorizes an issue or PR as relevant to SIG Network. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. wg/component-standard Categorizes an issue or PR as relevant to WG Component Standard.
Projects
Development

Successfully merging this pull request may close these issues.

None yet

10 participants