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 E2E Tests #23

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ jobs:
- name: Build
run: make build

- name: Test
run: go test -v ./...
- name: Unit Test
run: go test -v ./pkg/...

go-lint:
runs-on: ubuntu-latest
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ bin/
.DS_Store

vendor/

e2e/opentofu/.terraform/**
Copy link

Choose a reason for hiding this comment

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

Just FYI, in other projects we use Linode Cluster API because Terraform provider is deprecated as i know.

e2e/opentofu/.terraform.lock.hcl
e2e/opentofu/terraform.tfstate
e2e/opentofu/terraform.tfstate.backup
75 changes: 75 additions & 0 deletions e2e/decorator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package e2e

import (
"context"
"fmt"
"path/filepath"
"testing"
"time"

corev1 "k8s.io/api/core/v1"

"sigs.k8s.io/e2e-framework/pkg/envconf"
"sigs.k8s.io/e2e-framework/pkg/features"
"sigs.k8s.io/e2e-framework/third_party/helm"
)

func assertLabelsSet(t *testing.T, nodes corev1.NodeList) bool {
t.Helper()

for _, node := range nodes.Items {
for _, label := range expectedLabels {
if _, ok := node.Labels[label]; !ok {
return ok
}
}
}
return true
}

func TestSetLabels(t *testing.T) {
feature := features.New("Set Labels").
Setup(func(ctx context.Context, t *testing.T, config *envconf.Config) context.Context {
manager := helm.New(config.KubeconfigFile())
err := manager.RunInstall(
helm.WithName("test-decorator"),
helm.WithNamespace(namespace),
helm.WithChart(filepath.Join(curDir, "..", "helm", "k8s-node-decorator")),
helm.WithArgs("--set", fmt.Sprintf("decorator.image.tag=%s", tag)),
helm.WithArgs("--set", fmt.Sprintf("decorator.image.repository=%s", repo)),
helm.WithArgs("--set", fmt.Sprintf("decorator.prefix=%s", LabelPrefix)),
helm.WithArgs("--set", fmt.Sprintf("rbac.name=%s", rbacName)),
helm.WithWait(),
helm.WithTimeout("10m"),
)
if err != nil {
t.Fatal("failed to invoke helm install operation due to an error", err)
}
return ctx
}).
Assess("Check Label", func(ctx context.Context, t *testing.T, config *envconf.Config) context.Context {
nodes := corev1.NodeList{}

err := config.Client().Resources().List(ctx, &nodes)
if err != nil {
t.Fatal(err)
}

// retry when labels are not set in a timely manner
for i := 1; i <= 3; i++ {
ok := assertLabelsSet(t, nodes)
if ok {
t.Log("all expected labels are set")
break
} else {
t.Log("failed to assert decorator labels, retrying after 5s...")
time.Sleep(5 * time.Second)
}
}

return ctx
}).
Feature()

testenv.Test(t, feature)
}
109 changes: 109 additions & 0 deletions e2e/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package e2e

import (
"context"
"fmt"
"os"
"testing"

"sigs.k8s.io/e2e-framework/klient/conf"
"sigs.k8s.io/e2e-framework/pkg/env"
"sigs.k8s.io/e2e-framework/pkg/envconf"
"sigs.k8s.io/e2e-framework/pkg/envfuncs"

rbacv1 "k8s.io/api/rbac/v1"
)

const (
TagEnvVar = "DECORATOR_TEST_TAG"
RepoEnvVar = "DECORATOR_TEST_REPO"

LabelPrefix = "decorator.linode.com"
)

var (
testenv env.Environment
curDir string
namespace string
tag string
repo string
expectedLabels []string
rbacName string
)

func configureRBACName() {
rbacName = envconf.RandomName("test-decorator-rbac", 32)
}

func configureExpectedNodeLabels() {
expectedLabels = []string{
LabelPrefix + "/label",
LabelPrefix + "/instance-id",
LabelPrefix + "/region",
LabelPrefix + "/instance-type",
LabelPrefix + "/host",
}
}

func configureImage() {
tag = os.Getenv(TagEnvVar)
if tag == "" {
panic(fmt.Sprintf(
"you have to configure the environment variable %q "+
"for the test container image.",
TagEnvVar,
))
}

repo = os.Getenv(RepoEnvVar)
if repo == "" {
repo = "docker.io/linode/k8s-node-decorator"
}
}

func configureCurrentDirectory() {
c, err := os.Getwd()
if err != nil {
panic(err)
}
curDir = c
}

func cleanupDecoratorClusterRoles(ctx context.Context, config *envconf.Config) (context.Context, error) {
clusterRole := rbacv1.ClusterRole{}
clusterRoleBinding := rbacv1.ClusterRoleBinding{}

config.Client().Resources().Get(ctx, rbacName, namespace, &clusterRole)
config.Client().Resources().Get(ctx, rbacName, namespace, &clusterRoleBinding)

config.Client().Resources().Delete(ctx, &clusterRole)
config.Client().Resources().Delete(ctx, &clusterRoleBinding)

return ctx, nil
}

func TestMain(m *testing.M) {
configureRBACName()
configureCurrentDirectory()
configureImage()
configureExpectedNodeLabels()

testenv = env.New()
namespace = envconf.RandomName("test-decorator", 32)
path := conf.ResolveKubeConfigFile()
if path == "" {
panic("a kubeconfig file is required for e2e testing.")
}
cfg := envconf.NewWithKubeConfig(path)
testenv = env.NewWithConfig(cfg)

testenv.Setup(
envfuncs.CreateNamespace(namespace),
)
testenv.Finish(
envfuncs.DeleteNamespace(namespace),
cleanupDecoratorClusterRoles,
)

os.Exit(testenv.Run(m))
}
27 changes: 27 additions & 0 deletions e2e/opentofu/lke_cluster.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
terraform {
required_providers {
linode = {
source = "linode/linode"
}
}
}

provider "linode" {
}

resource "linode_lke_cluster" "e2e-test-cluster" {
label = var.lke_cluster_label
k8s_version = var.lke_k8s_version
region = var.linode_region

pool {
type = "g6-standard-1"
count = 1
}
}

resource "local_sensitive_file" "kubeconfig" {
content_base64 = linode_lke_cluster.e2e-test-cluster.kubeconfig
filename = var.lke_kubeconfig_path
file_permission = "0600"
}
19 changes: 19 additions & 0 deletions e2e/opentofu/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
variable "linode_region" {
type = string
default = "us-mia"
}

variable "lke_k8s_version" {
type = string
default = "1.29"
}

variable "lke_cluster_label" {
type = string
default = "test-decorator"
}

variable "lke_kubeconfig_path" {
type = string
default = "./kubeconfig.yaml"
}
43 changes: 26 additions & 17 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,55 @@ go 1.21

require (
github.com/linode/go-metadata v0.1.0
k8s.io/api v0.28.4
k8s.io/apimachinery v0.28.4
k8s.io/client-go v0.28.4
k8s.io/klog/v2 v2.110.1
k8s.io/api v0.29.4
k8s.io/apimachinery v0.29.4
k8s.io/client-go v0.29.4
k8s.io/klog/v2 v2.120.1
sigs.k8s.io/e2e-framework v0.3.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-resty/resty/v2 v2.9.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/vladimirvivien/gexe v0.2.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/controller-runtime v0.15.1 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
Loading