mirror of
https://github.com/YuzuZensai/netbird-kubernetes-operator.git
synced 2026-09-13 18:59:09 +00:00
This change does a few things, none of these are breaking. It changes the registry from Docker Hub to GHCR, as we dont have the same rate limiting issues with unauthenticated pulls. It changes the release process to push the Helm chart as an OCI artifact removing the need for GH pages. It renames both the image and chart from kubernetes-operator to netbird-operator. This name is cleaner and easier for people to understand in a sea of Helm charts. Funnily enough this is not a breaking change as the release name is used and not the chart name. So in place upgrades just work. Fixes #207 Signed-off-by: Philip Laine <philip.laine@gmail.com>
194 lines
5.5 KiB
Go
194 lines
5.5 KiB
Go
package e2e
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-openapi/testify/v2/require"
|
|
"github.com/moby/moby/client"
|
|
"helm.sh/helm/v4/pkg/action"
|
|
"helm.sh/helm/v4/pkg/chart/loader"
|
|
"helm.sh/helm/v4/pkg/kube"
|
|
"helm.sh/helm/v4/pkg/registry"
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
kindv1alpha1 "sigs.k8s.io/kind/pkg/apis/config/v1alpha4"
|
|
"sigs.k8s.io/kind/pkg/cluster"
|
|
"sigs.k8s.io/kind/pkg/cluster/nodeutils"
|
|
)
|
|
|
|
const (
|
|
netbirdNamespace = "netbird"
|
|
)
|
|
|
|
func TestE2E(t *testing.T) {
|
|
imgRef := os.Getenv("IMG_REF")
|
|
require.NotEmpty(t, imgRef)
|
|
|
|
mobyClient, err := client.New(client.FromEnv)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
err = mobyClient.Close()
|
|
if err != nil {
|
|
t.Log("could not close moby client", err)
|
|
}
|
|
})
|
|
|
|
t.Log("Exporting image", imgRef)
|
|
saveRes, err := mobyClient.ImageSave(t.Context(), []string{imgRef})
|
|
require.NoError(t, err)
|
|
imgPath := filepath.Join(t.TempDir(), "image")
|
|
f, err := os.OpenFile(imgPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o644)
|
|
require.NoError(t, err)
|
|
_, err = io.Copy(f, saveRes)
|
|
require.NoError(t, err)
|
|
err = f.Close()
|
|
require.NoError(t, err)
|
|
|
|
kubernetesVersions := []string{
|
|
"1.36.0",
|
|
}
|
|
for _, kubernetesVersion := range kubernetesVersions {
|
|
t.Run(kubernetesVersion, func(t *testing.T) {
|
|
t.Log("Creating Kind cluster")
|
|
kcPath := filepath.Join(t.TempDir(), "kind.kubeconfig")
|
|
provider := cluster.NewProvider()
|
|
createCfg := &kindv1alpha1.Cluster{
|
|
Nodes: []kindv1alpha1.Node{
|
|
{
|
|
Role: kindv1alpha1.ControlPlaneRole,
|
|
},
|
|
},
|
|
}
|
|
createOpts := []cluster.CreateOption{
|
|
cluster.CreateWithV1Alpha4Config(createCfg),
|
|
cluster.CreateWithNodeImage(fmt.Sprintf("ghcr.io/spegel-org/test-images/kind-node:%s", kubernetesVersion)),
|
|
cluster.CreateWithKubeconfigPath(kcPath),
|
|
}
|
|
kindName := fmt.Sprintf("netbird-operator-e2e-%s", strings.ReplaceAll(kubernetesVersion, ".", "-"))
|
|
err = provider.Create(kindName, createOpts...)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
if t.Failed() {
|
|
return
|
|
}
|
|
err = provider.Delete(kindName, "")
|
|
require.NoError(t, err)
|
|
})
|
|
kindNodes, err := provider.ListNodes(kindName)
|
|
require.NoError(t, err)
|
|
|
|
k8sCfg, err := clientcmd.BuildConfigFromFlags("", kcPath)
|
|
require.NoError(t, err)
|
|
k8sClient, err := kubernetes.NewForConfig(k8sCfg)
|
|
require.NoError(t, err)
|
|
|
|
require.Eventually(t, func(ctx context.Context) error {
|
|
for _, kindNode := range kindNodes {
|
|
node, err := k8sClient.CoreV1().Nodes().Get(ctx, kindNode.String(), metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
idx := slices.IndexFunc(node.Status.Conditions, func(cond corev1.NodeCondition) bool {
|
|
return cond.Type == corev1.NodeReady
|
|
})
|
|
if idx == -1 {
|
|
return errors.New("ready condition not found")
|
|
}
|
|
if node.Status.Conditions[idx].Status != corev1.ConditionTrue {
|
|
return fmt.Errorf("node %s is not ready", kindNode.String())
|
|
}
|
|
}
|
|
return nil
|
|
}, 30*time.Second, 1*time.Second)
|
|
|
|
t.Log("Importing image", imgRef)
|
|
f, err := os.Open(imgPath)
|
|
require.NoError(t, err)
|
|
for _, node := range kindNodes {
|
|
_, err = f.Seek(0, io.SeekStart)
|
|
require.NoError(t, err)
|
|
err = nodeutils.LoadImageArchive(node, f)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
t.Log("Deploying Netbird operator")
|
|
namespace := &corev1.Namespace{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: netbirdNamespace,
|
|
},
|
|
}
|
|
_, err = k8sClient.CoreV1().Namespaces().Create(t.Context(), namespace, metav1.CreateOptions{})
|
|
require.NoError(t, err)
|
|
|
|
secret := &corev1.Secret{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "netbird-mgmt-api-key",
|
|
Namespace: netbirdNamespace,
|
|
},
|
|
StringData: map[string]string{
|
|
"NB_API_KEY": "dummy",
|
|
},
|
|
}
|
|
_, err = k8sClient.CoreV1().Secrets(netbirdNamespace).Create(t.Context(), secret, metav1.CreateOptions{})
|
|
require.NoError(t, err)
|
|
|
|
regClient, err := registry.NewClient()
|
|
require.NoError(t, err)
|
|
actionCfg := &action.Configuration{
|
|
RegistryClient: regClient,
|
|
}
|
|
actionCfg.SetLogger(slog.DiscardHandler)
|
|
clientGetter := &genericclioptions.ConfigFlags{KubeConfig: &kcPath, Namespace: new(netbirdNamespace)}
|
|
err = actionCfg.Init(clientGetter, netbirdNamespace, "secret")
|
|
require.NoError(t, err)
|
|
|
|
charter, err := loader.Load("../../charts/netbird-operator")
|
|
require.NoError(t, err)
|
|
|
|
vals := map[string]any{
|
|
"operator": map[string]any{
|
|
"image": map[string]any{
|
|
"tag": "dev",
|
|
"pullPolicy": "Never",
|
|
},
|
|
},
|
|
"webhook": map[string]any{
|
|
"enableCertManager": false,
|
|
"failurePolicy": "Ignore",
|
|
},
|
|
}
|
|
_, err = action.NewGet(actionCfg).Run(netbirdNamespace)
|
|
if err != nil {
|
|
install := action.NewInstall(actionCfg)
|
|
install.ReleaseName = "netbird-operator"
|
|
install.Namespace = netbirdNamespace
|
|
install.CreateNamespace = true
|
|
install.WaitStrategy = kube.StatusWatcherStrategy
|
|
install.Timeout = 60 * time.Second
|
|
_, err = install.RunWithContext(t.Context(), charter, vals)
|
|
require.NoError(t, err)
|
|
} else {
|
|
upgrade := action.NewUpgrade(actionCfg)
|
|
upgrade.Namespace = netbirdNamespace
|
|
upgrade.WaitStrategy = kube.StatusWatcherStrategy
|
|
upgrade.Timeout = 60 * time.Second
|
|
_, err := upgrade.RunWithContext(t.Context(), "netbird-operator", charter, vals)
|
|
require.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|