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

Add ability to build with runtime coverage instrumentation #67971

Merged

Conversation

Katharine
Copy link
Member

What this PR does / why we need it:

This PR adds the ability to instrument a subset of kubernetes binaries to report code coverage information. The specific use-case is to help determine coverage of our end-to-end Conformance tests, as well as provide data that can be used to help determine where to focus. This PR focuses on making it possible to build with instrumentation; collecting and using the generated coverage data will be done in later PRs. For more details as to the intent, see the design doc (google doc; requires kubernetes-dev membership).

Specifically, this PR adds a new KUBE_BUILD_WITH_COVERAGE make variable, which when set will cause kube-apiserver, kube-controller-manager, kube-scheduler, kube-proxy and kubelet to be built with coverage instrumentation. These coverage-instrumented binaries will flush coverage information to disk every five seconds, defaulting to a temporary directory unless the KUBE_COVERAGE_FILE environment variable is set at launch, in which case it will write to that file instead.

The mechanism used to achieve coverage instrumentation is to build the targeted binaries as "unit tests" with coverage enabled, and then rigging the unit tests to just execute the binary's usual entry point. This is implemented only for the bash build system.

/sig testing

NONE

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. sig/testing Categorizes an issue or PR as relevant to SIG Testing. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 28, 2018
@Katharine Katharine changed the title Coverage instrumentation Add ability to build with runtime coverage instrumentation Aug 28, 2018
@ixdy
Copy link
Member

ixdy commented Aug 28, 2018

/ok-to-test

@k8s-ci-robot k8s-ci-robot removed the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Aug 28, 2018
@Katharine
Copy link
Member Author

/retest

func InitCoverage(name string) {
// We read the coverage destination in from the KUBE_COVERAGE_FILE env var,
// or if it's empty we just use a default in /tmp
coverageFile = os.Getenv("KUBE_COVERAGE_FILE")
Copy link
Member

Choose a reason for hiding this comment

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

Glad to see the runtime configuration options within util.
I wonder if something like this could be use to augment client-go rest api-calls?

Copy link
Member

Choose a reason for hiding this comment

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

Use of an env var for config makes me wince a bit. We do have prior art that uses it, but I'm curious if there's a way we could do this via a command line flag instead. ie: have the dummy test add a command line flag with a default value, call this with the parsed value?

Copy link
Member

Choose a reason for hiding this comment

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

adding package scoped flags is generally pretty awful, env are not great for lots of config but it's just one simple string and only when coverage is enabled. doing it this way has the upside of not mutating any global state within the binary. this is probably the way to go imho.

Copy link
Member Author

@Katharine Katharine Aug 31, 2018

Choose a reason for hiding this comment

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

Another downside to using a flag instead of an environment variable is that, because this feature is not always compiled in, you now need to be particularly careful about when you are passing the flag. By contrast, the environment variable will be silently ignored when it isn't relevant.

I am personally inclined to stick to the env var approach.

Copy link
Member

Choose a reason for hiding this comment

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

OK I'm sold

func FlushCoverage() {
// We're not actually going to run any tests, but we need Go to think we did so it writes
// coverage information to disk. To achieve this, we create a bunch of empty test suites and
// have it "run" them.
Copy link
Member

Choose a reason for hiding this comment

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

this is great 😂

Copy link
Member

Choose a reason for hiding this comment

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

💯

// originals away and set it up with this set.
originalArgs := os.Args
testArgs := []string{os.Args[0], "-test.coverprofile=" + tempCoveragePath()}
os.Args = testArgs
Copy link
Member

Choose a reason for hiding this comment

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

we should be able to pass testArgs to flag.CommandLine.Parse() instead I think.

os.Args = testArgs

// This is sufficient for the unit tests to be set up.
flag.Parse()
Copy link
Member

Choose a reason for hiding this comment

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

@BenTheElder
Copy link
Member

/lint

Copy link
Contributor

@k8s-ci-robot k8s-ci-robot left a comment

Choose a reason for hiding this comment

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

@BenTheElder: 3 warnings.

In response to this:

/lint

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

limitations under the License.
*/

package coverage
Copy link
Contributor

Choose a reason for hiding this comment

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

Golint comments: should have a package comment, unless it's in another file for this package. More info.

pkg/util/coverage/coverage_disabled.go Show resolved Hide resolved
pkg/util/coverage/fake_test_deps.go Show resolved Hide resolved
@Katharine
Copy link
Member Author

/retest

(the code hasn't even changed since this last passed...)

@BenTheElder
Copy link
Member

for build/ and hack/:
/assign @cblecker @ixdy

"${build_args[@]}" \
-tags coverage \
"$package"
kube::golang::delete_coverage_dummy_test "$package"
Copy link
Member

Choose a reason for hiding this comment

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

I'd like this to be trapped, so it can be cleaned up even if the previous command exits non-zero

# Argument: the name of a Kubernetes package (e.g. k8s.io/kubernetes/cmd/kube-scheduler)
# Echos the path to a dummy test used for coverage information.
kube::golang::path_for_coverage_dummy_test() {
local package=$1
Copy link
Member

Choose a reason for hiding this comment

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

nit: whitespace

# Echos the path to a dummy test used for coverage information.
kube::golang::path_for_coverage_dummy_test() {
local package=$1
local path="${KUBE_GOPATH}/src/$package"
Copy link
Member

Choose a reason for hiding this comment

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

nit: can we curly bracket all these variables?

@Katharine
Copy link
Member Author

/retest

@thockin
Copy link
Member

thockin commented Aug 31, 2018

/approve

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 31, 2018
@spiffxp
Copy link
Member

spiffxp commented Aug 31, 2018

/hold
for /lgtm once comments are resolved

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 31, 2018
@Katharine
Copy link
Member Author

/retest

Copy link
Member

@BenTheElder BenTheElder left a comment

Choose a reason for hiding this comment

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

/lgtm
despite the bash though 😬

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

@BenTheElder BenTheElder left a comment

Choose a reason for hiding this comment

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

/lgtm

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: BenTheElder, Katharine, spiffxp, 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

if coverageFile == "" {
coverageFile = "/tmp/k8s-" + name + ".cov"
}
fmt.Println("Dumping coverage information to " + coverageFile)
Copy link
Member

Choose a reason for hiding this comment

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

Can this be a glog.Infof?

Copy link
Member Author

Choose a reason for hiding this comment

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

No; glog isn't initialised at this point.

@spiffxp
Copy link
Member

spiffxp commented Sep 1, 2018

/hold cancel

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Sep 1, 2018
@BenTheElder
Copy link
Member

/retest

@k8s-github-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@k8s-github-robot
Copy link

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here: https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md.

@k8s-github-robot k8s-github-robot merged commit 68d22a8 into kubernetes:master Sep 1, 2018
k8s-ci-robot added a commit that referenced this pull request Oct 19, 2018
…971-upstream-release-1.11

Automated cherry pick of #67971: Add ability to build with runtime coverage instrumentation
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. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note-none Denotes a PR that doesn't merit a release note. sig/testing Categorizes an issue or PR as relevant to SIG Testing. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants