...

Source file src/edge-infra.dev/pkg/edge/webhooks/edge-injector/pod_secret_controller_test.go

Documentation: edge-infra.dev/pkg/edge/webhooks/edge-injector

     1  package edgeinjector
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"reflect"
     8  	"testing"
     9  	"time"
    10  
    11  	dsapi "edge-infra.dev/pkg/edge/datasync/apis/v1alpha1"
    12  	"edge-infra.dev/pkg/edge/datasync/couchdb"
    13  	"edge-infra.dev/pkg/edge/k8objectsutils/ownerref"
    14  	"edge-infra.dev/pkg/k8s/runtime/controller"
    15  	"edge-infra.dev/pkg/lib/fog"
    16  	v1ien "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
    17  	nodemeta "edge-infra.dev/pkg/sds/ien/node"
    18  	"edge-infra.dev/test/framework/k8s/envtest"
    19  
    20  	"github.com/google/uuid"
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  
    24  	appsv1 "k8s.io/api/apps/v1"
    25  	corev1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/types"
    28  	ctrl "sigs.k8s.io/controller-runtime"
    29  	"sigs.k8s.io/controller-runtime/pkg/client"
    30  )
    31  
    32  var (
    33  	namespace = "default"
    34  	timeout   = 5 * time.Second
    35  	interval  = time.Second
    36  	log       = fog.New()
    37  	testEnv   *envtest.Environment
    38  	cfg       = &Config{
    39  		EnableWebhook:        false,
    40  		ReconcileConcurrency: 1,
    41  		PollingInterval:      timeout,
    42  		RequeueTime:          interval,
    43  	}
    44  	mgr ctrl.Manager
    45  )
    46  
    47  func TestMain(m *testing.M) {
    48  	testEnv = envtest.Setup()
    49  	defer func() {
    50  		err := testEnv.Stop()
    51  		if err != nil {
    52  			panic(fmt.Errorf("failed to stop test environment, %w", err))
    53  		}
    54  	}()
    55  	var err error
    56  	mgr, err = create(log, cfg, controller.WithCfg(testEnv.Config))
    57  	if err != nil {
    58  		panic(fmt.Errorf("failed to create manager, %w", err))
    59  	}
    60  	go func() {
    61  		err = mgr.Start(ctrl.SetupSignalHandler())
    62  		if err != nil {
    63  			panic(fmt.Errorf("failed to start manager, %w", err))
    64  		}
    65  	}()
    66  	m.Run()
    67  }
    68  
    69  func TestCouchDBUserSecret(t *testing.T) {
    70  	ctx := context.Background()
    71  	uid := uuid.New().String()
    72  
    73  	cl := mgr.GetClient()
    74  
    75  	nodeName := fmt.Sprintf("node-%s", uid)
    76  	node := &corev1.Node{
    77  		TypeMeta: metav1.TypeMeta{
    78  			APIVersion: "v1",
    79  			Kind:       "Node",
    80  		},
    81  		ObjectMeta: metav1.ObjectMeta{
    82  			UID:  types.UID(uid),
    83  			Name: nodeName,
    84  			Labels: map[string]string{
    85  				nodemeta.RoleLabel:  string(v1ien.ControlPlane),
    86  				nodemeta.ClassLabel: string(v1ien.Server),
    87  			},
    88  		},
    89  	}
    90  	require.NoError(t, cl.Create(ctx, node), "fail to create node")
    91  
    92  	deployment := basicDeployment(namespace, fmt.Sprintf("deploy-%s", uid))
    93  	require.NoError(t, cl.Create(ctx, deployment), "fail to create deployment")
    94  
    95  	pod := basicPod(namespace, deployment.Name, nodeName, ownerReference(deployment))
    96  	require.NoError(t, cl.Create(ctx, pod), "fail to create pod")
    97  
    98  	require.Eventually(t, func() bool {
    99  		err := cl.Get(ctx, client.ObjectKeyFromObject(pod), pod)
   100  		return err == nil
   101  	}, timeout, interval, "pod does not exist")
   102  
   103  	if len(pod.Labels) == 0 {
   104  		pod.Labels = map[string]string{}
   105  	}
   106  
   107  	secretName := fmt.Sprintf("%s-%s", CouchDBSecret, uid)
   108  	pod.Labels[SecretLabel(CouchDBSecret)] = secretName
   109  	require.NoError(t, cl.Update(ctx, pod), "fail to update pod")
   110  
   111  	require.Eventually(t, func() bool { // Note: secret label triggers reconcile loop
   112  		err := cl.Get(ctx, client.ObjectKeyFromObject(pod), pod)
   113  		return err == nil && pod.Labels[SecretLabel(CouchDBSecret)] == secretName
   114  	}, timeout, interval, "pod does not contain secret label")
   115  
   116  	ref := metav1.OwnerReference{Name: fmt.Sprintf("deploy-%s", uid)}
   117  	username := ownerref.ResourceName(fmt.Sprintf("%s-%s", couchdb.CouchDBName, node.UID), ref, namespace, nodeName, false)
   118  
   119  	user := &dsapi.CouchDBUser{
   120  		TypeMeta: metav1.TypeMeta{
   121  			APIVersion: dsapi.GroupVersion.String(),
   122  			Kind:       "CouchDBUser",
   123  		},
   124  		ObjectMeta: metav1.ObjectMeta{
   125  			Name:      username,
   126  			Namespace: namespace,
   127  		},
   128  	}
   129  
   130  	// pod reconciler create CouchDBUser
   131  	require.Eventually(t, func() bool {
   132  		err := cl.Get(ctx, client.ObjectKeyFromObject(user), user)
   133  		return err == nil
   134  	}, timeout, interval, "CouchDBUser does not exist: %s", user.Name)
   135  
   136  	assert.Equal(t, user.Spec.Type, dsapi.UserCredentials)
   137  	assert.Equal(t, user.Spec.User.Name, "")
   138  	assert.Equal(t, user.Spec.User.Secret.Namespace, namespace)
   139  	assert.Equal(t, user.Spec.User.Secret.Name, secretName)
   140  	assert.Equal(t, ref.Name, user.OwnerReferences[0].Name)
   141  }
   142  
   143  func TestNodeSecret(t *testing.T) {
   144  	ctx := context.Background()
   145  	uid := uuid.New().String()
   146  	cl := mgr.GetClient()
   147  
   148  	nodeName := fmt.Sprintf("node-%s", uid)
   149  	node := &corev1.Node{
   150  		TypeMeta: metav1.TypeMeta{
   151  			APIVersion: "v1",
   152  			Kind:       "Node",
   153  		},
   154  		ObjectMeta: metav1.ObjectMeta{
   155  			Name: nodeName,
   156  			Labels: map[string]string{
   157  				nodemeta.HostnameLabel: "localhost",
   158  				nodemeta.LaneLabel:     "1",
   159  				nodemeta.ClassLabel:    "server",
   160  				nodemeta.RoleLabel:     "controlplane",
   161  			},
   162  		},
   163  	}
   164  	require.NoError(t, cl.Create(ctx, node), "fail to create node")
   165  	deployment := basicDeployment(namespace, fmt.Sprintf("deploy-%s", uid))
   166  	require.NoError(t, cl.Create(ctx, deployment), "fail to create deployment")
   167  
   168  	pod := basicPod(namespace, deployment.Name, nodeName, ownerReference(deployment))
   169  	require.NoError(t, cl.Create(ctx, pod), "fail to create pod")
   170  
   171  	require.Eventually(t, func() bool {
   172  		err := cl.Get(ctx, client.ObjectKeyFromObject(pod), pod)
   173  		return err == nil
   174  	}, timeout, interval, "pod does not exist")
   175  
   176  	if len(pod.Labels) == 0 {
   177  		pod.Labels = map[string]string{}
   178  	}
   179  	secretName := fmt.Sprintf("%s-%s", NodeSecret, uid)
   180  	pod.Labels[SecretLabel(NodeSecret)] = secretName
   181  
   182  	require.NoError(t, cl.Update(ctx, pod), "fail to update pod")
   183  
   184  	ref := metav1.OwnerReference{Name: deployment.Name}
   185  	secret := &corev1.Secret{
   186  		TypeMeta: metav1.TypeMeta{
   187  			APIVersion: "v1",
   188  			Kind:       "Secret",
   189  		},
   190  		ObjectMeta: metav1.ObjectMeta{
   191  			Name:      secretName,
   192  			Namespace: namespace,
   193  		},
   194  	}
   195  	// pod reconciler create CouchDBUser
   196  	require.Eventually(t, func() bool {
   197  		err := cl.Get(ctx, client.ObjectKeyFromObject(secret), secret)
   198  		return err == nil
   199  	}, timeout, interval, "Secret does not exist: %s", secret.Name)
   200  
   201  	assert.Equal(t, string(secret.Data[string(Hostname)]), "localhost")
   202  	assert.Equal(t, string(secret.Data[string(Lane)]), "1")
   203  	assert.Equal(t, string(secret.Data[string(Role)]), string(v1ien.ControlPlane))
   204  	assert.Equal(t, string(secret.Data[string(Class)]), string(v1ien.Server))
   205  	assert.Equal(t, ref.Name, secret.OwnerReferences[0].Name)
   206  }
   207  func basicPod(namespace, name, nodeName string, reference []metav1.OwnerReference) *corev1.Pod {
   208  	pod := &corev1.Pod{
   209  		TypeMeta: metav1.TypeMeta{
   210  			APIVersion: "v1",
   211  			Kind:       "Pod",
   212  		},
   213  		ObjectMeta: metav1.ObjectMeta{
   214  			Namespace:       namespace,
   215  			Name:            name,
   216  			Labels:          map[string]string{},
   217  			OwnerReferences: reference,
   218  		},
   219  		Spec: corev1.PodSpec{
   220  			Containers: []corev1.Container{
   221  				{
   222  					Name:  "podinfo",
   223  					Image: "podinfo:10.4",
   224  				},
   225  			},
   226  			NodeName: nodeName,
   227  		},
   228  	}
   229  
   230  	return pod
   231  }
   232  
   233  func basicDeployment(namespace, name string) *appsv1.Deployment {
   234  	label := "hola"
   235  	replica := int32(1)
   236  	return &appsv1.Deployment{
   237  		TypeMeta: metav1.TypeMeta{
   238  			Kind:       "Deployment",
   239  			APIVersion: "apps/v1",
   240  		},
   241  		ObjectMeta: metav1.ObjectMeta{
   242  			Namespace: namespace,
   243  			Name:      name,
   244  		},
   245  		Spec: appsv1.DeploymentSpec{
   246  			Replicas: &replica,
   247  			Selector: &metav1.LabelSelector{
   248  				MatchLabels: map[string]string{
   249  					"app": label,
   250  				},
   251  			},
   252  			Template: corev1.PodTemplateSpec{
   253  				ObjectMeta: metav1.ObjectMeta{
   254  					Labels: map[string]string{
   255  						"app": label,
   256  					},
   257  				},
   258  				Spec: corev1.PodSpec{
   259  					Containers: []corev1.Container{
   260  						{
   261  							Name:  "nginx",
   262  							Image: "nginx",
   263  						},
   264  					},
   265  				},
   266  			},
   267  		},
   268  	}
   269  }
   270  
   271  func ownerReference(obj *appsv1.Deployment) []metav1.OwnerReference {
   272  	return []metav1.OwnerReference{
   273  		*metav1.NewControllerRef(obj,
   274  			appsv1.SchemeGroupVersion.WithKind(reflect.TypeOf(appsv1.Deployment{}).Name())),
   275  	}
   276  }
   277  

View as plain text