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

Test Coverage Reports for E2E tests #7526

Merged
merged 12 commits into from
Jun 5, 2023
32 changes: 27 additions & 5 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ steps:
image: rancher/dapper:v0.5.0
commands:
- DOCKER_BUILDKIT=1 docker build --target test-e2e -t test-e2e -f Dockerfile.test .
- SKIP_VALIDATE=true SKIP_AIRGAP=true dapper ci
- SKIP_VALIDATE=true SKIP_AIRGAP=true GOCOVER=1 dapper ci
- cp dist/artifacts/* /tmp/artifacts/
volumes:
- name: cache
Expand Down Expand Up @@ -742,21 +742,24 @@ steps:
- docker run -d -p 5000:5000 -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io --name registry registry:2
- cd tests/e2e/validatecluster
- vagrant destroy -f
- go test -v -timeout=45m ./validatecluster_test.go -ci -local
- E2E_GOCOVER=1 go test -v -timeout=45m ./validatecluster_test.go -ci -local
- cp ./coverage.out /tmp/artifacts/validate-coverage.out
- cd ../secretsencryption
- vagrant destroy -f
- go test -v -timeout=30m ./secretsencryption_test.go -ci -local
- E2E_GOCOVER=1 go test -v -timeout=30m ./secretsencryption_test.go -ci -local
- cp ./coverage.out /tmp/artifacts/se-coverage.out
- cd ../startup
- vagrant destroy -f
- go test -v -timeout=30m ./startup_test.go -ci -local
- E2E_GOCOVER=1 go test -v -timeout=30m ./startup_test.go -ci -local
- cp ./coverage.out /tmp/artifacts/startup-coverage.out
- |
if [ "$DRONE_BUILD_EVENT" = "pull_request" ]; then
cd ../upgradecluster
vagrant destroy -f
E2E_RELEASE_CHANNEL="latest" go test -v -timeout=45m ./upgradecluster_test.go -ci -local
fi
- docker stop registry && docker rm registry

volumes:
- name: libvirt
path: /var/run/libvirt/
Expand All @@ -765,6 +768,25 @@ steps:
- name: cache
path: /tmp/artifacts

- name: upload to codecov
image: robertstettner/drone-codecov
Copy link
Member

@brandond brandond May 31, 2023

Choose a reason for hiding this comment

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

I love images that just are just from some dude.

Does this have a project somewhere, or should we consider mirroring or building it ourselves into an org we can trust?

Copy link
Member Author

Choose a reason for hiding this comment

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

I swear this is the De Facto plugin for CodeCov in Drone. If you go looking at drone plugins, its the only one https://plugins.drone.io/?search=codecov. The source files are here https://github.com/robertstettner/drone-codecov. Codecov documentation sends to a 404 non existent Drone plugin https://about.codecov.io/tool/drone/. Longhorn is currently using this plugin.

Copy link
Member

Choose a reason for hiding this comment

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

the repo hasn't been touched in 6 years, is the image also that old!?

Copy link
Member

@brandond brandond May 31, 2023

Choose a reason for hiding this comment

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

It looks like it's also just a simple wrapper around the deprecated bash uploader
https://github.com/robertstettner/drone-codecov/blob/master/Dockerfile#L4

I wonder if we should just toss together a proper plugin that uses the new one from https://docs.codecov.com/docs/codecov-uploader

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll open a future PR to move to directly uploading via their bash tool

Copy link
Member

Choose a reason for hiding this comment

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

no, bash is bad, we want to use the new non-bash one.

settings:
token:
from_secret: codecov_token
files:
- /tmp/artifacts/validate-coverage.out
- /tmp/artifacts/se-coverage.out
- /tmp/artifacts/startup-coverage.out
flags:
- e2etests
when:
event:
- pull_request

volumes:
- name: cache
path: /tmp/artifacts

volumes:
- name: docker
host:
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile.test
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ RUN vagrant box add generic/ubuntu2004 --provider libvirt --force
RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"; \
chmod +x ./kubectl; \
mv ./kubectl /usr/local/bin/kubectl
ENV GO_VERSION 1.19.2
RUN curl -O -L "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz"; \
RUN GO_VERSION=$(curl https://go.dev/VERSION?m=text); \
curl -O -L "https://golang.org/dl/${GO_VERSION}.linux-amd64.tar.gz"; \
rm -rf /usr/local/go; \
tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz;
tar -C /usr/local -xzf ${GO_VERSION}.linux-amd64.tar.gz;

ENV PATH="${PATH}:/usr/local/go/bin"

Expand Down
2 changes: 2 additions & 0 deletions pkg/cli/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,7 @@ func Run(ctx *cli.Context) error {

contextCtx := signals.SetupSignalContext()

go cmds.WriteCoverage(contextCtx)

return agent.Run(contextCtx, cfg)
}
7 changes: 7 additions & 0 deletions pkg/cli/cmds/cover_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//go:build !linux || !cover

package cmds

import "context"

func WriteCoverage(ctx context.Context) {}
6 changes: 3 additions & 3 deletions pkg/server/cover.go → pkg/cli/cmds/cover_linux.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//go:build cover
//go:build linux && cover

package server
package cmds

import (
"context"
Expand All @@ -13,7 +13,7 @@ import (

// writeCoverage checks if GOCOVERDIR is set on startup and writes coverage files to that directory
// every 20 seconds. This is done to ensure that the coverage files are written even if the process is killed.
func writeCoverage(ctx context.Context) {
func WriteCoverage(ctx context.Context) {
if k, ok := os.LookupEnv("GOCOVERDIR"); ok {
for {
select {
Expand Down
2 changes: 2 additions & 0 deletions pkg/cli/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
return err
}

go cmds.WriteCoverage(ctx)

go func() {
if !serverConfig.ControlConfig.DisableAPIServer {
<-serverConfig.ControlConfig.Runtime.APIServerReady
Expand Down
7 changes: 0 additions & 7 deletions pkg/server/no_cover.go

This file was deleted.

1 change: 0 additions & 1 deletion pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ func StartServer(ctx context.Context, config *Config, cfg *cmds.Server) error {
return errors.Wrap(err, "startup hook")
}
}
go writeCoverage(ctx)
go startOnAPIServerReady(ctx, config)

if err := printTokens(&config.ControlConfig); err != nil {
Expand Down
5 changes: 5 additions & 0 deletions tests/e2e/secretsencryption/Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ NODE_BOXES = (ENV['E2E_NODE_BOXES'] ||
['generic/ubuntu2004', 'generic/ubuntu2004', 'generic/ubuntu2004'])
GITHUB_BRANCH = (ENV['E2E_GITHUB_BRANCH'] || "master")
RELEASE_VERSION = (ENV['E2E_RELEASE_VERSION'] || "")
GOCOVER = (ENV['E2E_GOCOVER'] || "")
NODE_CPUS = (ENV['E2E_NODE_CPUS'] || 2).to_i
NODE_MEMORY = (ENV['E2E_NODE_MEMORY'] || 2048).to_i
# Virtualbox >= 6.1.28 require `/etc/vbox/network.conf` for expanded private networks
Expand All @@ -25,6 +26,10 @@ def provision(vm, role, role_num, node_num)

vm.provision "shell", inline: "ping -c 2 k3s.io"

if !GOCOVER.empty?
addCoverageDir(vm, role)
end

if role.include?("server") && role_num == 0
vm.provision 'k3s-install', type: 'k3s', run: 'once' do |k3s|
k3s.args = %W[server --cluster-init --node-external-ip=#{NETWORK_PREFIX}.100 --flannel-iface=eth1 --secrets-encryption]
Expand Down
3 changes: 3 additions & 0 deletions tests/e2e/secretsencryption/secretsencryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,9 @@ var _ = AfterEach(func() {
})

var _ = AfterSuite(func() {
if os.Getenv("E2E_GOCOVER") != "" {
Expect(e2e.GetCoverageReport(serverNodeNames)).To(Succeed())
}
if failed && !*ci {
fmt.Println("FAILED!")
} else {
Expand Down
7 changes: 6 additions & 1 deletion tests/e2e/startup/Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ NODE_BOXES = (ENV['E2E_NODE_BOXES'] ||
['generic/ubuntu2004', 'generic/ubuntu2004'])
GITHUB_BRANCH = (ENV['E2E_GITHUB_BRANCH'] || "master")
RELEASE_VERSION = (ENV['E2E_RELEASE_VERSION'] || "")
GOCOVER = (ENV['E2E_GOCOVER'] || "")
NODE_CPUS = (ENV['E2E_NODE_CPUS'] || 2).to_i
NODE_MEMORY = (ENV['E2E_NODE_MEMORY'] || 2048).to_i
# Virtualbox >= 6.1.28 require `/etc/vbox/network.conf` for expanded private networks
Expand All @@ -26,7 +27,7 @@ def provision(vm, role, role_num, node_num)
node_ip = "#{NETWORK_PREFIX}.#{100+node_num}"

vm.provision "shell", inline: "ping -c 2 k3s.io"

if role.include?("server")
vm.provision 'k3s-install', type: 'k3s', run: 'once' do |k3s|
k3s.args = "server "
Expand All @@ -52,6 +53,10 @@ def provision(vm, role, role_num, node_num)
end
end

if !GOCOVER.empty?
addCoverageDir(vm, role)
end

if vm.box.to_s.include?("microos")
vm.provision 'k3s-reload', type: 'reload', run: 'once'
end
Expand Down
3 changes: 3 additions & 0 deletions tests/e2e/startup/startup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ var _ = AfterEach(func() {
})

var _ = AfterSuite(func() {
if os.Getenv("E2E_GOCOVER") != "" {
Expect(e2e.GetCoverageReport(append(serverNodeNames, agentNodeNames...))).To(Succeed())
}
if failed && !*ci {
fmt.Println("FAILED!")
} else {
Expand Down
29 changes: 29 additions & 0 deletions tests/e2e/testutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,35 @@ func UpgradeCluster(nodeNames []string, local bool) error {
return nil
}

func GetCoverageReport(nodeNames []string) error {
covDirs := []string{}
for _, nodeName := range nodeNames {
covDir := nodeName + "-cov"
covDirs = append(covDirs, covDir)
os.MkdirAll(covDir, 0755)
cmd := "vagrant scp " + nodeName + ":/tmp/k3scov/* " + covDir
if _, err := RunCommand(cmd); err != nil {
return err
}
}
cmd := "go tool covdata textfmt -i " + strings.Join(covDirs, ",") + " -o coverage.out"
if out, err := RunCommand(cmd); err != nil {
return fmt.Errorf("failed to generate coverage report: %s, %v", out, err)
}
cmd = "go tool covdata func -i " + strings.Join(covDirs, ",") + " | tail -n 1"
out, err := RunCommand(cmd)
if err != nil {
return fmt.Errorf("failed to generate coverage report: %s, %v", out, err)
}
fmt.Println(strings.Fields(out))
for _, covDir := range covDirs {
if err := os.RemoveAll(covDir); err != nil {
return err
}
}
return nil
}

// getPodIPs returns the IPs of all pods
func GetPodIPs(kubeConfigFile string) ([]ObjIP, error) {
cmd := `kubectl get pods -A -o=jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.podIPs[*].ip}{"\n"}{end}' --kubeconfig=` + kubeConfigFile
Expand Down
10 changes: 10 additions & 0 deletions tests/e2e/vagrantdefaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ def getInstallType(vm, release_version, branch)
end
end

def addCoverageDir(vm, role)
service = role.include?("agent") ? "k3s-agent" : "k3s"
script = <<~SHELL
mkdir -p /tmp/k3scov
echo -e 'GOCOVERDIR=/tmp/k3scov' >> /etc/default/#{service}
systemctl daemon-reload
SHELL
vm.provision "go coverage", type: "shell", inline: script
end

def getHardenedArg(vm, hardened, scripts_location)
if hardened.empty?
return ""
Expand Down
6 changes: 5 additions & 1 deletion tests/e2e/validatecluster/Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ EXTERNAL_DB = (ENV['E2E_EXTERNAL_DB'] || "etcd")
HARDENED = (ENV['E2E_HARDENED'] || "")
REGISTRY = (ENV['E2E_REGISTRY'] || "")
RANCHER = (ENV['E2E_RANCHER'] || "")
GOCOVER = (ENV['E2E_GOCOVER'] || "")
NODE_CPUS = (ENV['E2E_NODE_CPUS'] || 2).to_i
NODE_MEMORY = (ENV['E2E_NODE_MEMORY'] || 2048).to_i
# Virtualbox >= 6.1.28 require `/etc/vbox/network.conf` for expanded private networks
Expand Down Expand Up @@ -39,6 +40,9 @@ def provision(vm, role, role_num, node_num)
vm.provision "Set private registry", type: "shell", path: scripts_location + "/registry.sh", args: [ "#{NETWORK_PREFIX}.1" ]
end

if !GOCOVER.empty?
addCoverageDir(vm, role)
end

if role.include?("server") && role_num == 0
vm.provision 'k3s-primary-server', type: 'k3s', run: 'once' do |k3s|
Expand Down Expand Up @@ -133,7 +137,7 @@ def getDBType(role, role_num, vm)
end

Vagrant.configure("2") do |config|
config.vagrant.plugins = ["vagrant-k3s", "vagrant-reload"]
config.vagrant.plugins = ["vagrant-k3s", "vagrant-reload", "vagrant-scp"]
# Default provider is libvirt, virtualbox is only provided as a backup
config.vm.provider "libvirt" do |v|
v.cpus = NODE_CPUS
Expand Down
3 changes: 3 additions & 0 deletions tests/e2e/validatecluster/validatecluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ var _ = AfterEach(func() {
})

var _ = AfterSuite(func() {
if os.Getenv("E2E_GOCOVER") != "" {
Expect(e2e.GetCoverageReport(append(serverNodeNames, agentNodeNames...))).To(Succeed())
}
if failed && !*ci {
fmt.Println("FAILED!")
} else {
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/longhorn/longhorn_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ var _ = AfterEach(func() {
})

var _ = AfterSuite(func() {
if !testutil.IsExistingServer() {
if !testutil.IsExistingServer() && server != nil {
if failed {
testutil.K3sSaveLog(server, false)
}
Expand Down