From 30b4b95d846b5b1c6cdd5f7d4229a57cfc20dae0 Mon Sep 17 00:00:00 2001 From: Shikhar Soni Date: Fri, 10 May 2024 12:42:02 +0530 Subject: [PATCH] Replace bincover with built-in Go profiling and coverage tool Fixes #4962 Signed-off-by: Shikhar Soni --- Makefile | 8 +- .../antrea/templates/agent/daemonset.yaml | 11 ++- .../templates/controller/deployment.yaml | 11 ++- .../flow-aggregator/templates/deployment.yaml | 13 ++- build/images/Dockerfile.build.agent.coverage | 8 +- .../Dockerfile.build.controller.coverage | 8 +- build/images/Dockerfile.build.coverage | 52 ++++++++++ .../flow-aggregator/Dockerfile.coverage | 8 +- ci/jenkins/test-mc.sh | 6 +- ci/jenkins/test-vmc.sh | 12 ++- ci/kind/test-e2e-kind.sh | 9 ++ cmd/antctl/bincover_run_main_test.go | 28 ------ cmd/antrea-agent/bincover_run_main_test.go | 28 ------ .../bincover_run_main_test.go | 28 ------ cmd/flow-aggregator/bincover_run_main_test.go | 28 ------ go.mod | 1 - go.sum | 3 - multicluster/Makefile | 2 +- .../build/images/Dockerfile.build.coverage | 7 ++ .../bincover_run_main_test.go | 28 ------ .../manager_command_patch_coverage.yaml | 7 +- .../manager_command_patch_coverage.yaml | 7 +- .../manager_command_patch_coverage.yaml | 7 +- test/e2e/antctl_test.go | 36 +------ test/e2e/coverage/agent-arg-file | 9 -- test/e2e/coverage/controller-arg-file | 9 -- test/e2e/coverage/flow-aggregator-arg-file | 8 -- test/e2e/flowaggregator_test.go | 4 +- test/e2e/framework.go | 98 +++++++++---------- test/e2e/utils/run_cov_binary.sh | 29 ++++++ 30 files changed, 231 insertions(+), 282 deletions(-) create mode 100644 build/images/Dockerfile.build.coverage delete mode 100644 cmd/antctl/bincover_run_main_test.go delete mode 100644 cmd/antrea-agent/bincover_run_main_test.go delete mode 100644 cmd/antrea-controller/bincover_run_main_test.go delete mode 100644 cmd/flow-aggregator/bincover_run_main_test.go delete mode 100644 multicluster/cmd/multicluster-controller/bincover_run_main_test.go delete mode 100644 test/e2e/coverage/agent-arg-file delete mode 100644 test/e2e/coverage/controller-arg-file delete mode 100644 test/e2e/coverage/flow-aggregator-arg-file create mode 100755 test/e2e/utils/run_cov_binary.sh diff --git a/Makefile b/Makefile index ea691137060..4c420f5c961 100644 --- a/Makefile +++ b/Makefile @@ -106,7 +106,7 @@ antrea-agent-simulator: .PHONY: antrea-agent-instr-binary antrea-agent-instr-binary: @mkdir -p $(BINDIR) - GOOS=linux $(GO) test -tags testbincover -covermode count -coverpkg=antrea.io/antrea/pkg/... -c -o $(BINDIR)/antrea-agent-coverage $(GOFLAGS) -ldflags '$(LDFLAGS)' antrea.io/antrea/cmd/antrea-agent + GOOS=linux $(GO) build -cover -o $(BINDIR)/antrea-agent-coverage -coverpkg=antrea.io/antrea/cmd/antrea-agent,antrea.io/antrea/pkg/... $(GOFLAGS) -ldflags '$(LDFLAGS)' antrea.io/antrea/cmd/antrea-agent .PHONY: antrea-controller antrea-controller: @@ -120,7 +120,7 @@ antrea-controller: .PHONY: antrea-controller-instr-binary antrea-controller-instr-binary: @mkdir -p $(BINDIR) - GOOS=linux $(GO) test -tags testbincover -covermode count -coverpkg=antrea.io/antrea/pkg/... -c -o $(BINDIR)/antrea-controller-coverage $(GOFLAGS) -ldflags '$(LDFLAGS)' antrea.io/antrea/cmd/antrea-controller + GOOS=linux $(GO) build -cover -o $(BINDIR)/antrea-controller-coverage -coverpkg=antrea.io/antrea/cmd/antrea-controller,antrea.io/antrea/pkg/... $(GOFLAGS) -ldflags '$(LDFLAGS)' antrea.io/antrea/cmd/antrea-controller .PHONY: antrea-cni antrea-cni: @@ -135,7 +135,7 @@ antrea-cni-release: .PHONY: antctl-instr-binary antctl-instr-binary: @mkdir -p $(BINDIR) - GOOS=linux $(GO) test -tags testbincover -covermode count -coverpkg=antrea.io/antrea/pkg/... -c -o $(BINDIR)/antctl-coverage $(GOFLAGS) -ldflags '$(LDFLAGS)' antrea.io/antrea/cmd/antctl + GOOS=linux $(GO) build -cover -o $(BINDIR)/antctl-coverage -coverpkg=antrea.io/antrea/cmd/antctl,antrea.io/antrea/pkg/... $(GOFLAGS) -ldflags '$(LDFLAGS)' antrea.io/antrea/cmd/antctl .PHONY: windows-bin windows-bin: @@ -150,7 +150,7 @@ flow-aggregator: .PHONY: flow-aggregator-instr-binary flow-aggregator-instr-binary: @mkdir -p $(BINDIR) - GOOS=linux $(GO) test -tags testbincover -covermode count -coverpkg=antrea.io/antrea/pkg/... -c -o $(BINDIR)/flow-aggregator-coverage $(GOFLAGS) -ldflags '$(LDFLAGS)' antrea.io/antrea/cmd/flow-aggregator + GOOS=linux $(GO) build -cover -o $(BINDIR)/flow-aggregator-coverage -coverpkg=antrea.io/antrea/cmd/flow-aggregator,antrea.io/antrea/pkg/... $(GOFLAGS) -ldflags '$(LDFLAGS)' antrea.io/antrea/cmd/flow-aggregator .PHONY: test-unit test-integration ifeq ($(UNAME_S),Linux) diff --git a/build/charts/antrea/templates/agent/daemonset.yaml b/build/charts/antrea/templates/agent/daemonset.yaml index 3afd45aa41e..40c41c65f46 100644 --- a/build/charts/antrea/templates/agent/daemonset.yaml +++ b/build/charts/antrea/templates/agent/daemonset.yaml @@ -130,8 +130,15 @@ spec: image: {{ include "antreaAgentImage" . | quote }} imagePullPolicy: {{ include "antreaAgentImagePullPolicy" . }} {{- if ((.Values.testing).coverage) }} - command: ["/bin/sh"] - args: ["-c", "sleep 2; antrea-agent-coverage -test.run=TestBincoverRunMain -test.coverprofile=antrea-agent.cov.out -args-file=/agent-arg-file; while true; do sleep 5 & wait $!; done"] + args: + - "antrea-agent-coverage" + - "--config=/etc/antrea/antrea-agent.conf" + - "--logtostderr=false" + - "--log_dir=/var/log/antrea" + - "--alsologtostderr" + - "--log_file_max_size=100" + - "--log_file_max_num=4" + - "--v=4" {{- else}} command: ["antrea-agent"] # Log to both "/var/log/antrea/" and stderr (so "kubectl logs" can work).- diff --git a/build/charts/antrea/templates/controller/deployment.yaml b/build/charts/antrea/templates/controller/deployment.yaml index c2ec527e981..5fb81822e65 100644 --- a/build/charts/antrea/templates/controller/deployment.yaml +++ b/build/charts/antrea/templates/controller/deployment.yaml @@ -64,8 +64,15 @@ spec: imagePullPolicy: {{ include "antreaControllerImagePullPolicy" . }} resources: {{- .Values.controller.antreaController.resources | toYaml | nindent 12 }} {{- if ((.Values.testing).coverage) }} - command: ["/bin/sh"] - args: ["-c", "antrea-controller-coverage -test.run=TestBincoverRunMain -test.coverprofile=antrea-controller.cov.out -args-file=/controller-arg-file; while true; do sleep 5 & wait $!; done"] + args: + - "antrea-controller-coverage" + - "--config=/etc/antrea/antrea-controller.conf" + - "--logtostderr=false" + - "--log_dir=/var/log/antrea" + - "--alsologtostderr" + - "--log_file_max_size=100" + - "--log_file_max_num=4" + - "--v=4" {{- else }} command: ["antrea-controller"] # Log to both "/var/log/antrea/" and stderr (so "kubectl logs" can work). diff --git a/build/charts/flow-aggregator/templates/deployment.yaml b/build/charts/flow-aggregator/templates/deployment.yaml index 3c8202440db..fc231c79a4b 100644 --- a/build/charts/flow-aggregator/templates/deployment.yaml +++ b/build/charts/flow-aggregator/templates/deployment.yaml @@ -27,9 +27,16 @@ spec: - name: flow-aggregator image: {{ include "flowAggregatorImage" . | quote }} imagePullPolicy: {{ .Values.image.pullPolicy }} - {{- if .Values.testing.coverage }} - command: [ "/bin/sh" ] - args: [ "-c", "flow-aggregator-coverage -test.run=TestBincoverRunMain -test.coverprofile=flow-aggregator.cov.out -args-file=/flow-aggregator-arg-file; while true; do sleep 5 & wait $!; done" ] + {{- if ((.Values.testing).coverage) }} + args: + - flow-aggregator-coverage + - --config=/etc/flow-aggregator/flow-aggregator.conf + - --logtostderr=false + - --log_dir=/var/log/antrea/flow-aggregator + - --alsologtostderr + - --log_file_max_size=100 + - --log_file_max_num=4 + - --v=4 {{- else }} args: - --config diff --git a/build/images/Dockerfile.build.agent.coverage b/build/images/Dockerfile.build.agent.coverage index e318b41f2a6..2d19d99ba43 100644 --- a/build/images/Dockerfile.build.agent.coverage +++ b/build/images/Dockerfile.build.agent.coverage @@ -41,4 +41,10 @@ COPY --from=antrea-build /antrea/bin/antrea-agent-coverage /usr/local/bin/ COPY --from=antrea-build /antrea/bin/antrea-cni /usr/local/bin/ COPY --from=antrea-build /antrea/bin/antctl /usr/local/bin/ COPY --from=antrea-build /antrea/bin/antctl-coverage /usr/local/bin/ -COPY --from=antrea-build /antrea/test/e2e/coverage/agent-arg-file / +COPY --from=antrea-build /antrea/test/e2e/utils/run_cov_binary.sh / + +# This environment variable will persist when running the container, but can also be overwritten if needed +ENV GOCOVERDIR=/tmp/coverage +RUN mkdir -p $GOCOVERDIR + +ENTRYPOINT [ "/run_cov_binary.sh" ] diff --git a/build/images/Dockerfile.build.controller.coverage b/build/images/Dockerfile.build.controller.coverage index 6e3499f76d9..bb19a038034 100644 --- a/build/images/Dockerfile.build.controller.coverage +++ b/build/images/Dockerfile.build.controller.coverage @@ -39,4 +39,10 @@ COPY --from=antrea-build /antrea/bin/antrea-controller /usr/local/bin/ COPY --from=antrea-build /antrea/bin/antctl /usr/local/bin/ COPY --from=antrea-build /antrea/bin/antrea-controller-coverage /usr/local/bin/ COPY --from=antrea-build /antrea/bin/antctl-coverage /usr/local/bin/ -COPY --from=antrea-build /antrea/test/e2e/coverage/controller-arg-file / +COPY --from=antrea-build /antrea/test/e2e/utils/run_cov_binary.sh / + +# This environment variable will persist when running the container, but can also be overwritten if needed +ENV GOCOVERDIR=/tmp/coverage +RUN mkdir -p $GOCOVERDIR + +ENTRYPOINT [ "/run_cov_binary.sh" ] diff --git a/build/images/Dockerfile.build.coverage b/build/images/Dockerfile.build.coverage new file mode 100644 index 00000000000..19b0123da12 --- /dev/null +++ b/build/images/Dockerfile.build.coverage @@ -0,0 +1,52 @@ +# Copyright 2022 Antrea Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG GO_VERSION +ARG BUILD_TAG +FROM golang:${GO_VERSION} as antrea-build + +WORKDIR /antrea + +COPY go.mod /antrea/go.mod + +RUN go mod download + +COPY . /antrea + +# Build antctl first in order to share an extra layer with +# build/images/Dockerfile.build.agent.coverage and build/images/Dockerfile.build.controller.coverage. +RUN make antctl-linux antctl-instr-binary && mv bin/antctl-linux bin/antctl + +# Then build antrea-agent and antrea-cni, in order to share an extra layer with +# build/images/Dockerfile.build.agent.coverage. +RUN make antrea-agent antrea-cni antrea-agent-instr-binary + +RUN make antrea-controller antrea-controller-instr-binary + +FROM antrea/base-ubuntu:${BUILD_TAG} + +LABEL maintainer="Antrea " +LABEL description="The Docker image to deploy the Antrea CNI with code coverage measurement enabled (used for testing)." + +USER root + +COPY build/images/scripts/* /usr/local/bin/ +COPY --from=antrea-build /antrea/bin/* /usr/local/bin/ +COPY --from=antrea-build /antrea/test/e2e/utils/run_cov_binary.sh / + +# This environment variable will persist when running the container, but can also be overwritten if needed +ENV GOCOVERDIR=/tmp/coverage +RUN mkdir -p $GOCOVERDIR + +ENTRYPOINT [ "/run_cov_binary.sh" ] diff --git a/build/images/flow-aggregator/Dockerfile.coverage b/build/images/flow-aggregator/Dockerfile.coverage index 031fa7c573f..02bc626ab96 100644 --- a/build/images/flow-aggregator/Dockerfile.coverage +++ b/build/images/flow-aggregator/Dockerfile.coverage @@ -30,9 +30,15 @@ LABEL description="The docker image for the flow aggregator with code coverage m USER root COPY --from=flow-aggregator-build /antrea/bin/flow-aggregator* /usr/local/bin/ -COPY --from=flow-aggregator-build /antrea/test/e2e/coverage/flow-aggregator-arg-file / COPY --from=flow-aggregator-build /antrea/bin/antctl* /usr/local/bin/ +COPY --from=flow-aggregator-build /antrea/test/e2e/utils/run_cov_binary.sh / + +# This environment variable will persist when running the container, but can also be overwritten if needed +ENV GOCOVERDIR=/tmp/coverage +RUN mkdir -p $GOCOVERDIR RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates \ && rm -rf /var/lib/apt/lists/* + +ENTRYPOINT [ "/run_cov_binary.sh" ] diff --git a/ci/jenkins/test-mc.sh b/ci/jenkins/test-mc.sh index f7f1f7c7b8c..b7d005f7bb5 100755 --- a/ci/jenkins/test-mc.sh +++ b/ci/jenkins/test-mc.sh @@ -466,7 +466,11 @@ function collect_coverage { mc_controller_pod_name="$(kubectl get pods --selector=app=antrea,component=antrea-mc-controller -n ${namespace} --no-headers=true ${kubeconfig} | awk '{ print $1 }')" controller_pid="$(kubectl exec -i $mc_controller_pod_name -n ${namespace} ${kubeconfig} -- pgrep antrea)" kubectl exec -i $mc_controller_pod_name -n ${namespace} ${kubeconfig} -- kill -SIGINT $controller_pid - kubectl cp ${namespace}/$mc_controller_pod_name:antrea-mc-controller.cov.out ${COVERAGE_DIR}/$mc_controller_pod_name-$timestamp ${kubeconfig} + cov_dir="${COVERAGE_DIR}/$mc_controller_pod_name-$timestamp" + mkdir -p $cov_dir + kubectl cp ${namespace}/$mc_controller_pod_name:/tmp/coverage/* $cov_dir/ ${kubeconfig} + go tool covdata textfmt -i="${cov_dir}" -o "${cov_dir}.cov.out" + rm -rf "${cov_dir}" done } diff --git a/ci/jenkins/test-vmc.sh b/ci/jenkins/test-vmc.sh index 3d868e5094a..3b9c5f82e2b 100755 --- a/ci/jenkins/test-vmc.sh +++ b/ci/jenkins/test-vmc.sh @@ -625,7 +625,11 @@ function collect_coverage() { controller_pid="$(kubectl exec -i $antrea_controller_pod_name -n kube-system -- pgrep antrea)" kubectl exec -i $antrea_controller_pod_name -n kube-system -- kill -SIGINT $controller_pid timestamp=$(date +%Y%m%d%H%M%S) - kubectl cp kube-system/$antrea_controller_pod_name:antrea-controller.cov.out ${GIT_CHECKOUT_DIR}/conformance-coverage/$antrea_controller_pod_name-$timestamp + cov_dir="${GIT_CHECKOUT_DIR}/conformance-coverage/$antrea_controller_pod_name-$timestamp" + mkdir -p $cov_dir + kubectl cp kube-system/$antrea_controller_pod_name:/tmp/coverage/* $cov_dir/ + go tool covdata textfmt -i="${cov_dir}" -o "${cov_dir}.cov.out" + rm -rf "${cov_dir}" antrea_agent_pod_names="$(kubectl get pods --selector=app=antrea,component=antrea-agent -n kube-system --no-headers=true | awk '{ print $1 }')" for agent in ${antrea_agent_pod_names} @@ -633,7 +637,11 @@ function collect_coverage() { agent_pid="$(kubectl exec -i $agent -n kube-system -- pgrep antrea)" kubectl exec -i $agent -c antrea-agent -n kube-system -- kill -SIGINT $agent_pid timestamp=$(date +%Y%m%d%H%M%S) - kubectl cp kube-system/$agent:antrea-agent.cov.out -c antrea-agent ${GIT_CHECKOUT_DIR}/conformance-coverage/$agent-$timestamp + cov_dir="${GIT_CHECKOUT_DIR}/conformance-coverage/$agent-$timestamp" + mkdir -p $cov_dir + kubectl cp kube-system/$agent:/tmp/coverage/* -c antrea-agent $cov_dir/ + go tool covdata textfmt -i="${cov_dir}" -o "${cov_dir}.cov.out" + rm -rf "${cov_dir}" done } diff --git a/ci/kind/test-e2e-kind.sh b/ci/kind/test-e2e-kind.sh index 34c28b4821b..0585116186f 100755 --- a/ci/kind/test-e2e-kind.sh +++ b/ci/kind/test-e2e-kind.sh @@ -384,6 +384,15 @@ function run_test { EXTRA_ARGS="$vlan_args --external-server-ips $external_server_ips" go test -v -timeout=$timeout $RUN_OPT antrea.io/antrea/test/e2e $flow_visibility_args -provider=kind --logs-export-dir=$ANTREA_LOG_DIR $np_evaluation_flag --skip-cases=$skiplist $coverage_args $EXTRA_ARGS + + if $coverage; then + pushd $ANTREA_COV_DIR + for dir in */; do + go tool covdata textfmt -i="${dir}" -o "${dir%?}_$(date +%Y-%m-%d_%H-%M-%S).cov.out" + rm -rf "${dir}"; + done + popd + fi } if [[ "$mode" == "" ]] || [[ "$mode" == "encap" ]]; then diff --git a/cmd/antctl/bincover_run_main_test.go b/cmd/antctl/bincover_run_main_test.go deleted file mode 100644 index c8eb2554671..00000000000 --- a/cmd/antctl/bincover_run_main_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2022 Antrea Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build testbincover -// +build testbincover - -package main - -import ( - "testing" - - "github.com/confluentinc/bincover" -) - -func TestBincoverRunMain(t *testing.T) { - bincover.RunTest(main) -} diff --git a/cmd/antrea-agent/bincover_run_main_test.go b/cmd/antrea-agent/bincover_run_main_test.go deleted file mode 100644 index c8eb2554671..00000000000 --- a/cmd/antrea-agent/bincover_run_main_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2022 Antrea Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build testbincover -// +build testbincover - -package main - -import ( - "testing" - - "github.com/confluentinc/bincover" -) - -func TestBincoverRunMain(t *testing.T) { - bincover.RunTest(main) -} diff --git a/cmd/antrea-controller/bincover_run_main_test.go b/cmd/antrea-controller/bincover_run_main_test.go deleted file mode 100644 index c8eb2554671..00000000000 --- a/cmd/antrea-controller/bincover_run_main_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2022 Antrea Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build testbincover -// +build testbincover - -package main - -import ( - "testing" - - "github.com/confluentinc/bincover" -) - -func TestBincoverRunMain(t *testing.T) { - bincover.RunTest(main) -} diff --git a/cmd/flow-aggregator/bincover_run_main_test.go b/cmd/flow-aggregator/bincover_run_main_test.go deleted file mode 100644 index c8eb2554671..00000000000 --- a/cmd/flow-aggregator/bincover_run_main_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2022 Antrea Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build testbincover -// +build testbincover - -package main - -import ( - "testing" - - "github.com/confluentinc/bincover" -) - -func TestBincoverRunMain(t *testing.T) { - bincover.RunTest(main) -} diff --git a/go.mod b/go.mod index 45e998636d9..60469c42c39 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/s3 v1.27.4 github.com/blang/semver v3.5.1+incompatible github.com/cheggaaa/pb/v3 v3.1.5 - github.com/confluentinc/bincover v0.1.0 github.com/containernetworking/cni v1.1.1 github.com/containernetworking/plugins v1.1.1 github.com/coreos/go-iptables v0.7.0 diff --git a/go.sum b/go.sum index 39a598cd606..f7ad2129e8c 100644 --- a/go.sum +++ b/go.sum @@ -140,8 +140,6 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/confluentinc/bincover v0.1.0 h1:M4Gfj4rCXuUQVe8TqT/VXcAMjLyvN81oDRy79fjSv3o= -github.com/confluentinc/bincover v0.1.0/go.mod h1:qeI1wx0RxdGTZtrJY0HVlgJ4NqC/X2Z+fHbvy87tgHE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/containerd v1.6.26 h1:VVfrE6ZpyisvB1fzoY8Vkiq4sy+i5oF4uk7zu03RaHs= @@ -1062,7 +1060,6 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/multicluster/Makefile b/multicluster/Makefile index 6fef2e7f306..c799a07aba5 100644 --- a/multicluster/Makefile +++ b/multicluster/Makefile @@ -82,7 +82,7 @@ bin: fmt vet ## Build manager binary. .PHONY: antrea-mc-instr-binary antrea-mc-instr-binary: - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go test -tags testbincover -covermode count -coverpkg=antrea.io/antrea/multicluster/... -c -o bin/antrea-mc-controller-coverage antrea.io/antrea/multicluster/cmd/... + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -cover -coverpkg=antrea.io/antrea/multicluster/...,antrea.io/antrea/multicluster/cmd/... -o bin/antrea-mc-controller-coverage antrea.io/antrea/multicluster/cmd/... run: manifests generate fmt vet ## Run a controller from your host. go run ./main.go diff --git a/multicluster/build/images/Dockerfile.build.coverage b/multicluster/build/images/Dockerfile.build.coverage index f768f70d1c9..9ab152159b1 100644 --- a/multicluster/build/images/Dockerfile.build.coverage +++ b/multicluster/build/images/Dockerfile.build.coverage @@ -33,3 +33,10 @@ LABEL description="The Docker image to deploy the Antrea Multi-cluster Controlle USER root COPY --from=antrea-build /antrea/multicluster/bin/antrea-mc-controller-coverage / +COPY --from=antrea-build /antrea/test/e2e/utils/run_cov_binary.sh / + +# This environment variable will persist when running the container, but can also be overwritten if needed +ENV GOCOVERDIR=/tmp/coverage +RUN mkdir -p $GOCOVERDIR + +ENTRYPOINT [ "/run_cov_binary.sh" ] diff --git a/multicluster/cmd/multicluster-controller/bincover_run_main_test.go b/multicluster/cmd/multicluster-controller/bincover_run_main_test.go deleted file mode 100644 index c8eb2554671..00000000000 --- a/multicluster/cmd/multicluster-controller/bincover_run_main_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2022 Antrea Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build testbincover -// +build testbincover - -package main - -import ( - "testing" - - "github.com/confluentinc/bincover" -) - -func TestBincoverRunMain(t *testing.T) { - bincover.RunTest(main) -} diff --git a/multicluster/config/overlays/leader-ns/coverage/manager_command_patch_coverage.yaml b/multicluster/config/overlays/leader-ns/coverage/manager_command_patch_coverage.yaml index e683f7ac078..0e7af4c9c4b 100644 --- a/multicluster/config/overlays/leader-ns/coverage/manager_command_patch_coverage.yaml +++ b/multicluster/config/overlays/leader-ns/coverage/manager_command_patch_coverage.yaml @@ -7,7 +7,10 @@ spec: template: spec: containers: - - command: ["/bin/sh"] - args: ["-c", "/antrea-mc-controller-coverage -test.run=TestBincoverRunMain -test.coverprofile=antrea-mc-controller.cov.out leader --config=/controller_manager_config.yaml; while true; do sleep 5 & wait $!; done"] + - command: [ "/run_cov_binary.sh" ] + args: + - /antrea-mc-controller-coverage + - leader + - --config=/controller_manager_config.yaml name: antrea-mc-controller image: antrea/antrea-mc-controller-coverage:latest diff --git a/multicluster/config/overlays/leader/coverage/manager_command_patch_coverage.yaml b/multicluster/config/overlays/leader/coverage/manager_command_patch_coverage.yaml index e683f7ac078..0e7af4c9c4b 100644 --- a/multicluster/config/overlays/leader/coverage/manager_command_patch_coverage.yaml +++ b/multicluster/config/overlays/leader/coverage/manager_command_patch_coverage.yaml @@ -7,7 +7,10 @@ spec: template: spec: containers: - - command: ["/bin/sh"] - args: ["-c", "/antrea-mc-controller-coverage -test.run=TestBincoverRunMain -test.coverprofile=antrea-mc-controller.cov.out leader --config=/controller_manager_config.yaml; while true; do sleep 5 & wait $!; done"] + - command: [ "/run_cov_binary.sh" ] + args: + - /antrea-mc-controller-coverage + - leader + - --config=/controller_manager_config.yaml name: antrea-mc-controller image: antrea/antrea-mc-controller-coverage:latest diff --git a/multicluster/config/overlays/member/coverage/manager_command_patch_coverage.yaml b/multicluster/config/overlays/member/coverage/manager_command_patch_coverage.yaml index 34fb88f28a6..c5f647f48d5 100644 --- a/multicluster/config/overlays/member/coverage/manager_command_patch_coverage.yaml +++ b/multicluster/config/overlays/member/coverage/manager_command_patch_coverage.yaml @@ -7,7 +7,10 @@ spec: template: spec: containers: - - command: ["/bin/sh"] - args: ["-c", "/antrea-mc-controller-coverage -test.run=TestBincoverRunMain -test.coverprofile=antrea-mc-controller.cov.out member --config=/controller_manager_config.yaml; while true; do sleep 5 & wait $!; done"] + - command: [ "/run_cov_binary.sh" ] + args: + - /antrea-mc-controller-coverage + - member + - --config=/controller_manager_config.yaml name: antrea-mc-controller image: antrea/antrea-mc-controller-coverage:latest diff --git a/test/e2e/antctl_test.go b/test/e2e/antctl_test.go index bb4f2dcea5e..41de9a18105 100644 --- a/test/e2e/antctl_test.go +++ b/test/e2e/antctl_test.go @@ -19,7 +19,6 @@ import ( "encoding/json" "fmt" "net" - "path" "strings" "testing" "time" @@ -116,16 +115,6 @@ func runAntctl(podName string, cmds []string, data *TestData) (string, string, e return stdout, stderr, err } -func antctlCoverageArgs(antctlPath string, covDir string) []string { - const timeFormat = "20060102T150405Z0700" - timestamp := time.Now().Format(timeFormat) - covFile := fmt.Sprintf("antctl-%s.out", timestamp) - if covDir != "" { - covFile = path.Join(covDir, covFile) - } - return []string{antctlPath, "-test.run=TestBincoverRunMain", fmt.Sprintf("-test.coverprofile=%s", covFile)} -} - // testAntctlAgentLocalAccess ensures antctl is accessible in an agent Pod. func testAntctlAgentLocalAccess(t *testing.T, data *TestData) { podName, err := data.getAntreaPodOnNode(controlPlaneNodeName()) @@ -135,25 +124,13 @@ func testAntctlAgentLocalAccess(t *testing.T, data *TestData) { antctlName := antctlName() for _, c := range antctl.CommandList.GetDebugCommands(runtime.ModeAgent) { args := []string{antctlName} - if testOptions.enableCoverage { - antctlCovArgs := antctlCoverageArgs(antctlName, "") - args = append(antctlCovArgs, c...) - } else { - args = append(args, c...) - } + args = append(args, c...) t.Logf("args: %s", args) cmd := strings.Join(args, " ") t.Run(cmd, func(t *testing.T) { stdout, stderr, err := runAntctl(podName, args, data) - // After upgrading from Go v1.19 to Go v1.21, stderr will also include the - // following warning in the error case: - // warning: GOCOVERDIR not set, no coverage data emitted - // As a result, we temporarily replace strings.HasSuffix with strings.Contains. - // We can revert this change when the following issue is addressed: - // https://github.com/antrea-io/antrea/issues/4962 - // if err != nil && !strings.HasSuffix(stderr, "not enabled\n") { - if err != nil && !strings.Contains(stderr, "not enabled\n") { + if err != nil && !strings.HasSuffix(stderr, "not enabled\n") { t.Fatalf("Error when running `antctl %s` from %s: %v\n%s", c, podName, err, antctlOutput(stdout, stderr)) } }) @@ -183,7 +160,7 @@ func runAntctlCommandFromPod(data *TestData, podName string, cmd []string) (stri // Pod. func testAntctlControllerRemoteAccess(t *testing.T, data *TestData, antctlServiceAccountName string, antctlImage string) { const podName = "antctl" - const covDir = "/coverage" + const covDir = "/tmp/coverage" antctlName := antctlName() runAntctlPod(t, data, podName, antctlServiceAccountName, antctlImage, covDir) @@ -193,12 +170,7 @@ func testAntctlControllerRemoteAccess(t *testing.T, data *TestData, antctlServic // Add all controller commands. for _, c := range antctl.CommandList.GetDebugCommands(runtime.ModeController) { cmd := []string{antctlName} - if testOptions.enableCoverage { - antctlCovArgs := antctlCoverageArgs(antctlName, covDir) - cmd = append(antctlCovArgs, c...) - } else { - cmd = append(cmd, c...) - } + cmd = append(cmd, c...) testCmds = append(testCmds, cmdAndReturnCode{args: cmd, expectedReturnCode: 0}) } testCmds = append(testCmds, diff --git a/test/e2e/coverage/agent-arg-file b/test/e2e/coverage/agent-arg-file deleted file mode 100644 index 3b027201e37..00000000000 --- a/test/e2e/coverage/agent-arg-file +++ /dev/null @@ -1,9 +0,0 @@ ---config -/etc/antrea/antrea-agent.conf ---logtostderr=false ---log_dir=/var/log/antrea ---alsologtostderr ---log_file_max_size=100 ---log_file_max_num=4 ---v=4 - diff --git a/test/e2e/coverage/controller-arg-file b/test/e2e/coverage/controller-arg-file deleted file mode 100644 index 677653b5b7e..00000000000 --- a/test/e2e/coverage/controller-arg-file +++ /dev/null @@ -1,9 +0,0 @@ ---config -/etc/antrea/antrea-controller.conf ---logtostderr=false ---log_dir=/var/log/antrea ---alsologtostderr ---log_file_max_size=100 ---log_file_max_num=4 ---v=4 - diff --git a/test/e2e/coverage/flow-aggregator-arg-file b/test/e2e/coverage/flow-aggregator-arg-file deleted file mode 100644 index a0489d11e82..00000000000 --- a/test/e2e/coverage/flow-aggregator-arg-file +++ /dev/null @@ -1,8 +0,0 @@ ---config -/etc/flow-aggregator/flow-aggregator.conf ---logtostderr=false ---log_dir=/var/log/antrea/flow-aggregator ---alsologtostderr ---log_file_max_size=100 ---log_file_max_num=4 ---v=4 diff --git a/test/e2e/flowaggregator_test.go b/test/e2e/flowaggregator_test.go index 79531f7e640..c7978648471 100644 --- a/test/e2e/flowaggregator_test.go +++ b/test/e2e/flowaggregator_test.go @@ -897,7 +897,7 @@ func testHelper(t *testing.T, data *TestData, isIPv6 bool) { for _, args := range antctl.CommandList.GetDebugCommands(runtime.ModeFlowAggregator) { command := []string{} if testOptions.enableCoverage { - antctlCovArgs := antctlCoverageArgs("antctl-coverage", "") + antctlCovArgs := []string{"antctl-coverage"} command = append(antctlCovArgs, args...) } else { command = append([]string{"antctl", "-v"}, args...) @@ -937,7 +937,7 @@ func checkAntctlGetFlowRecordsJson(t *testing.T, data *TestData, podName string, var command []string args := []string{"get", "flowrecords", "-o", "json", "--srcip", srcIP, "--srcport", srcPort} if testOptions.enableCoverage { - antctlCovArgs := antctlCoverageArgs("antctl-coverage", "") + antctlCovArgs := []string{"antctl-coverage"} command = append(antctlCovArgs, args...) } else { command = append([]string{"antctl"}, args...) diff --git a/test/e2e/framework.go b/test/e2e/framework.go index c72a9907890..87b4f09e852 100644 --- a/test/e2e/framework.go +++ b/test/e2e/framework.go @@ -23,6 +23,7 @@ import ( "math/rand" "net" "os" + "path" "path/filepath" "reflect" "regexp" @@ -116,9 +117,6 @@ const ( antreaControllerCovBinary = "antrea-controller-coverage" antreaAgentCovBinary = "antrea-agent-coverage" flowAggregatorCovBinary = "flow-aggregator-coverage" - antreaControllerCovFile = "antrea-controller.cov.out" - antreaAgentCovFile = "antrea-agent.cov.out" - flowAggregatorCovFile = "flow-aggregator.cov.out" cpNodeCoverageDir = "/tmp/antrea-e2e-coverage" antreaAgentConfName = "antrea-agent.conf" @@ -2643,11 +2641,7 @@ func (data *TestData) mutateAntreaConfigMap( return nil } -func (data *TestData) killProcessAndCollectCovFiles(namespace, podName, containerName, processName, covFile, covDir string) error { - if err := data.collectAntctlCovFiles(podName, containerName, namespace, covDir); err != nil { - return fmt.Errorf("error when copying antctl coverage files out: %v", err) - } - +func (data *TestData) killProcessAndCollectCovFiles(namespace, podName, containerName, processName, covDir string) error { cmds := []string{"pgrep", "-f", processName, "-P", "1"} stdout, stderr, err := data.RunCommandFromPod(namespace, podName, containerName, cmds) if err != nil { @@ -2661,14 +2655,8 @@ func (data *TestData) killProcessAndCollectCovFiles(namespace, podName, containe } log.Infof("Copying coverage files from Pod '%s'", podName) - if err := wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 5*time.Second, true, func(ctx context.Context) (bool, error) { - if err = data.copyPodFiles(podName, containerName, namespace, covFile, covDir); err != nil { - log.Infof("Coverage file not available yet for copy: %v", err) - return false, nil - } - return true, nil - }); err != nil { - return fmt.Errorf("timeout when waiting for coverage file") + if err := data.collectCovFiles(podName, containerName, namespace, covDir); err != nil { + return fmt.Errorf("error when copying antctl coverage files: %v", err) } return nil @@ -2682,7 +2670,7 @@ func (data *TestData) gracefulExitAntreaController(covDir string) error { } podName := antreaController.Name - if err := data.killProcessAndCollectCovFiles(antreaNamespace, podName, "antrea-controller", antreaControllerCovBinary, antreaControllerCovFile, covDir); err != nil { + if err := data.killProcessAndCollectCovFiles(antreaNamespace, podName, "antrea-controller", antreaControllerCovBinary, covDir); err != nil { return fmt.Errorf("error when gracefully exiting Antrea Controller: %w", err) } @@ -2704,7 +2692,7 @@ func (data *TestData) gracefulExitAntreaAgent(covDir string, nodeName string) er } for _, pod := range pods.Items { podName := pod.Name - if err := data.killProcessAndCollectCovFiles(antreaNamespace, podName, "antrea-agent", antreaAgentCovBinary, antreaAgentCovFile, covDir); err != nil { + if err := data.killProcessAndCollectCovFiles(antreaNamespace, podName, "antrea-agent", antreaAgentCovBinary, covDir); err != nil { return fmt.Errorf("error when gracefully exiting Antrea Agent: %w", err) } } @@ -2719,30 +2707,39 @@ func (data *TestData) gracefulExitFlowAggregator(covDir string) error { } podName := flowAggPod.Name - if err := data.killProcessAndCollectCovFiles(flowAggregatorNamespace, podName, "flow-aggregator", flowAggregatorCovBinary, flowAggregatorCovFile, covDir); err != nil { + if err := data.killProcessAndCollectCovFiles(flowAggregatorNamespace, podName, "flow-aggregator", flowAggregatorCovBinary, covDir); err != nil { return fmt.Errorf("error when gracefully exiting Flow Aggregator: %w", err) } return nil } -// collectAntctlCovFiles collects coverage files for the antctl binary from the Pod and saves them to the coverage directory -func (data *TestData) collectAntctlCovFiles(podName string, containerName string, nsName string, covDir string) error { +// collectCovFiles collects coverage files from the Pod and saves them to the coverage directory +func (data *TestData) collectCovFiles(podName string, containerName string, nsName string, covDir string) error { // copy antctl coverage files from Pod to the coverage directory - cmds := []string{"bash", "-c", "find . -maxdepth 1 -name 'antctl*.out' -exec basename {} ';'"} + cmds := []string{"bash", "-c", "find /tmp/coverage -mindepth 1"} stdout, stderr, err := data.RunCommandFromPod(nsName, podName, containerName, cmds) if err != nil { return fmt.Errorf("error when running this find command '%s' on Pod '%s', stderr: <%v>, err: <%v>", cmds, podName, stderr, err) } + covDir = filepath.Join(covDir, podName+"-coverage") + if err := os.Mkdir(covDir, os.ModePerm); err != nil { + return fmt.Errorf("error creating coverage directory for Pod %s: %v", podName, err) + } stdout = strings.TrimSpace(stdout) files := strings.Split(stdout, "\n") for _, file := range files { if len(file) == 0 { continue } - err := data.copyPodFiles(podName, containerName, nsName, file, covDir) - if err != nil { - return fmt.Errorf("error when copying coverage files for antctl from Pod '%s' to coverage directory '%s': %v", podName, covDir, err) + if err := wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 5*time.Second, true, func(ctx context.Context) (bool, error) { + if err = data.copyPodFiles(podName, containerName, nsName, file, covDir); err != nil { + log.Infof("Coverage file not available yet for copy: %v", err) + return false, nil + } + return true, nil + }); err != nil { + return fmt.Errorf("timeout when waiting for coverage file") } } return nil @@ -2751,19 +2748,15 @@ func (data *TestData) collectAntctlCovFiles(podName string, containerName string // collectAntctlCovFilesFromControlPlaneNode collects coverage files for the antctl binary from the control-plane Node and saves them to the coverage directory func (data *TestData) collectAntctlCovFilesFromControlPlaneNode(covDir string) error { // copy antctl coverage files from node to the coverage directory - var cmd string - if testOptions.providerName == "kind" { - // Do not use single quotes here, as they will be interpreted literally. - // RunDockerExecCommand does not invoke a shell by default and it will split this - // string into a list of args. - cmd = fmt.Sprintf("find %s -maxdepth 1 -name antctl*.out", cpNodeCoverageDir) - } else { - cmd = fmt.Sprintf("find %s -maxdepth 1 -name 'antctl*.out'", cpNodeCoverageDir) - } + log.Infof("Copying coverage files from Node: %s", controlPlaneNodeName()) + cmd := fmt.Sprintf("find %s -mindepth 1", cpNodeCoverageDir) rc, stdout, stderr, err := data.RunCommandOnNode(controlPlaneNodeName(), cmd) if err != nil || rc != 0 { return fmt.Errorf("error when running this find command '%s' on control-plane Node '%s', stderr: <%v>, err: <%v>", cmd, controlPlaneNodeName(), stderr, err) - + } + covDir = filepath.Join(covDir, fmt.Sprintf("%s-coverage", controlPlaneNodeName())) + if err := os.Mkdir(covDir, os.ModePerm); err != nil { + return fmt.Errorf("error creating coverage directory for the control plane Node %v", err) } stdout = strings.TrimSpace(stdout) files := strings.Split(stdout, "\n") @@ -2771,7 +2764,7 @@ func (data *TestData) collectAntctlCovFilesFromControlPlaneNode(covDir string) e if len(file) == 0 { continue } - err := data.copyNodeFiles(controlPlaneNodeName(), file, covDir) + err := data.copyNodeFiles(file, covDir) if err != nil { return fmt.Errorf("error when copying coverage files for antctl from Node '%s' to coverage directory '%s': %v", controlPlaneNodeName(), covDir, err) } @@ -2784,26 +2777,24 @@ func (data *TestData) collectAntctlCovFilesFromControlPlaneNode(covDir string) e func (data *TestData) copyPodFiles(podName string, containerName string, nsName string, fileName string, destDir string) error { // getPodWriter creates the file with name podName-fileName-suffix. It returns nil if the // file cannot be created. File must be closed by the caller. - getPodWriter := func(podName, fileName, suffix string) *os.File { - destFile := filepath.Join(destDir, fmt.Sprintf("%s-%s-%s", podName, fileName, suffix)) + getPodWriter := func(fileName string) *os.File { + destFile := filepath.Join(destDir, fileName) f, err := os.Create(destFile) if err != nil { - _ = fmt.Errorf("error when creating destination file '%s': %v", destFile, err) + log.Infof("Error when creating destination file '%s': %v\n", destFile, err) return nil } return f } - // dump the file from Antrea Pods to disk. - // a filepath-friendly timestamp format. - const timeFormat = "Jan02-15-04-05" - timeStamp := time.Now().Format(timeFormat) - w := getPodWriter(podName, fileName, timeStamp) + basename := path.Base(fileName) + w := getPodWriter(basename) if w == nil { return nil } defer w.Close() cmd := []string{"cat", fileName} + log.Infof("Copying file: %s", basename) stdout, stderr, err := data.RunCommandFromPod(nsName, podName, containerName, cmd) if err != nil { return fmt.Errorf("cannot retrieve content of file '%s' from Pod '%s', stderr: <%v>, err: <%v>", fileName, podName, stderr, err) @@ -2816,29 +2807,28 @@ func (data *TestData) copyPodFiles(podName string, containerName string, nsName } // copyNodeFiles copies a file from a Node and save it to specified directory -func (data *TestData) copyNodeFiles(nodeName string, fileName string, covDir string) error { +func (data *TestData) copyNodeFiles(fileName string, destDir string) error { // getNodeWriter creates the file with name nodeName-suffix. It returns nil if the file // cannot be created. File must be closed by the caller. - getNodeWriter := func(nodeName, fileName, suffix string) *os.File { - covFile := filepath.Join(covDir, fmt.Sprintf("%s-%s-%s", nodeName, fileName, suffix)) - f, err := os.Create(covFile) + getNodeWriter := func(fileName string) *os.File { + destFile := filepath.Join(destDir, fileName) + f, err := os.Create(destFile) if err != nil { - _ = fmt.Errorf("error when creating coverage file '%s': %v", covFile, err) + log.Infof("Error when creating coverage file '%s': %v\n", destFile, err) return nil } return f } - // dump the file from Antrea Pods to disk. - // a filepath-friendly timestamp format. - const timeFormat = "Jan02-15-04-05" - timeStamp := time.Now().Format(timeFormat) - w := getNodeWriter(nodeName, fileName, timeStamp) + // dump the file from Nodes to disk. + basename := path.Base(fileName) + w := getNodeWriter(basename) if w == nil { return nil } defer w.Close() cmd := fmt.Sprintf("cat %s", fileName) + log.Infof("Copying file: %s", basename) rc, stdout, stderr, err := data.RunCommandOnNode(controlPlaneNodeName(), cmd) if err != nil || rc != 0 { return fmt.Errorf("cannot retrieve content of file '%s' from Node '%s', stderr: <%v>, err: <%v>", fileName, controlPlaneNodeName(), stderr, err) diff --git a/test/e2e/utils/run_cov_binary.sh b/test/e2e/utils/run_cov_binary.sh new file mode 100755 index 00000000000..7cf28c58df7 --- /dev/null +++ b/test/e2e/utils/run_cov_binary.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# Copyright 2024 Antrea Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script is meant to wrap a coverage instrumented binary. +# When the main process is killed, the script will start sleeping until a signal +# is received, providing the opportunity for the user to retrieve code coverage +# files. + +set -x + +"$@" + +while true; do + # Sleep in the background, to allow exiting as soon as a signal is received + sleep 5 & wait $! +done