github.com/kotalco/kotal@v0.3.0/controllers/ipfs/cluster_peer_controller_test.go (about)

     1  package controllers
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  	"time"
     9  
    10  	. "github.com/onsi/ginkgo/v2"
    11  	. "github.com/onsi/gomega"
    12  	"github.com/onsi/gomega/gstruct"
    13  
    14  	ipfsv1alpha1 "github.com/kotalco/kotal/apis/ipfs/v1alpha1"
    15  	ipfsClients "github.com/kotalco/kotal/clients/ipfs"
    16  	"github.com/kotalco/kotal/controllers/shared"
    17  
    18  	appsv1 "k8s.io/api/apps/v1"
    19  	corev1 "k8s.io/api/core/v1"
    20  	"k8s.io/apimachinery/pkg/api/resource"
    21  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    22  	"k8s.io/apimachinery/pkg/types"
    23  	"k8s.io/apimachinery/pkg/util/intstr"
    24  )
    25  
    26  var _ = Describe("IPFS cluster peer controller", func() {
    27  	ns := &corev1.Namespace{
    28  		ObjectMeta: metav1.ObjectMeta{
    29  			Name: "ipfs-cluster-peer",
    30  		},
    31  	}
    32  
    33  	key := types.NamespacedName{
    34  		Name:      "my-cluster-peer",
    35  		Namespace: ns.Name,
    36  	}
    37  
    38  	image := "kotalco/ipfs-cluster:test"
    39  
    40  	spec := ipfsv1alpha1.ClusterPeerSpec{
    41  		Image:                image,
    42  		ID:                   "12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq",
    43  		PrivateKeySecretName: "cluster-privatekey",
    44  		ClusterSecretName:    "cluster-secret",
    45  		Consensus:            ipfsv1alpha1.CRDT,
    46  		TrustedPeers: []string{
    47  			"12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq",
    48  			"12D3KooWQ9yZnqowEDme3gSgS45KY9ZoEmAiGYRxusdEaqtFa9pr",
    49  		},
    50  		PeerEndpoint: "/dns4/ipfs-peer/tcp/5001",
    51  	}
    52  
    53  	toCreate := &ipfsv1alpha1.ClusterPeer{
    54  		ObjectMeta: metav1.ObjectMeta{
    55  			Name:      key.Name,
    56  			Namespace: key.Namespace,
    57  		},
    58  		Spec: spec,
    59  	}
    60  
    61  	t := true
    62  
    63  	peerOwnerReference := metav1.OwnerReference{
    64  		APIVersion:         "ipfs.kotal.io/v1alpha1",
    65  		Kind:               "ClusterPeer",
    66  		Name:               toCreate.Name,
    67  		Controller:         &t,
    68  		BlockOwnerDeletion: &t,
    69  	}
    70  
    71  	It(fmt.Sprintf("Should create %s namespace", ns.Name), func() {
    72  		Expect(k8sClient.Create(context.TODO(), ns)).To(Succeed())
    73  	})
    74  
    75  	It("should create cluster privatekey secret", func() {
    76  		secret := &corev1.Secret{
    77  			ObjectMeta: metav1.ObjectMeta{
    78  				Name:      "cluster-privatekey",
    79  				Namespace: ns.Name,
    80  			},
    81  			StringData: map[string]string{
    82  				"key": "CAESQOH/DvUJmeJ9z6m3wAStpkrlBwJQxIyNSK0YGf0EI5ZRGpwsWxl4wmgReqmHl8LQjTC2iPM0QbYAjeY3Z63AFnI=",
    83  			},
    84  		}
    85  
    86  		Expect(k8sClient.Create(context.TODO(), secret)).To(Succeed())
    87  	})
    88  
    89  	It("should create cluster secret", func() {
    90  		secret := &corev1.Secret{
    91  			ObjectMeta: metav1.ObjectMeta{
    92  				Name:      "cluster-secret",
    93  				Namespace: ns.Name,
    94  			},
    95  			StringData: map[string]string{
    96  				"secret": "clu$ter$3cr3t",
    97  			},
    98  		}
    99  
   100  		Expect(k8sClient.Create(context.TODO(), secret)).To(Succeed())
   101  	})
   102  
   103  	It("should create ipfs cluster peer", func() {
   104  		if os.Getenv(shared.EnvUseExistingCluster) != "true" {
   105  			toCreate.Default()
   106  		}
   107  		Expect(k8sClient.Create(context.Background(), toCreate)).Should(Succeed())
   108  	})
   109  
   110  	It("should get ipfs cluster peer", func() {
   111  		fetched := &ipfsv1alpha1.ClusterPeer{}
   112  		Expect(k8sClient.Get(context.TODO(), key, fetched)).To(Succeed())
   113  		Expect(fetched.Spec).To(Equal(toCreate.Spec))
   114  		peerOwnerReference.UID = fetched.UID
   115  		time.Sleep(5 * time.Second)
   116  	})
   117  
   118  	It("Should create ipfs cluster peer statefulset with correct image and arguments", func() {
   119  		fetched := &appsv1.StatefulSet{}
   120  		Expect(k8sClient.Get(context.Background(), key, fetched)).To(Succeed())
   121  		Expect(fetched.OwnerReferences).To(ContainElements(peerOwnerReference))
   122  		Expect(*fetched.Spec.Template.Spec.SecurityContext).To(gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{
   123  			"RunAsUser":    gstruct.PointTo(Equal(int64(1000))),
   124  			"RunAsGroup":   gstruct.PointTo(Equal(int64(3000))),
   125  			"FSGroup":      gstruct.PointTo(Equal(int64(2000))),
   126  			"RunAsNonRoot": gstruct.PointTo(Equal(true)),
   127  		}))
   128  		container := fetched.Spec.Template.Spec.Containers[0]
   129  		Expect(container.Image).To(Equal(image))
   130  
   131  	})
   132  
   133  	It("Should pass correct environment variables to ipfs cluster peer statefulset containers", func() {
   134  		fetched := &appsv1.StatefulSet{}
   135  		Expect(k8sClient.Get(context.Background(), key, fetched)).To(Succeed())
   136  
   137  		container := fetched.Spec.Template.Spec.Containers[0]
   138  		Expect(container.Env).To(ContainElements([]corev1.EnvVar{
   139  			{
   140  				Name:  ipfsClients.EnvIPFSClusterPath,
   141  				Value: shared.PathData(ipfsClients.GoIPFSClusterHomeDir),
   142  			},
   143  			{
   144  				Name:  ipfsClients.EnvIPFSClusterPeerName,
   145  				Value: toCreate.Name,
   146  			},
   147  		}))
   148  
   149  		initContainer := fetched.Spec.Template.Spec.InitContainers[0]
   150  		Expect(initContainer.Env).To(ContainElements([]corev1.EnvVar{
   151  			{
   152  				Name:  ipfsClients.EnvIPFSClusterPath,
   153  				Value: shared.PathData(ipfsClients.GoIPFSClusterHomeDir),
   154  			},
   155  			{
   156  				Name:  ipfsClients.EnvIPFSClusterConsensus,
   157  				Value: string(toCreate.Spec.Consensus),
   158  			},
   159  			{
   160  				Name:  ipfsClients.EnvIPFSClusterPeerEndpoint,
   161  				Value: toCreate.Spec.PeerEndpoint,
   162  			},
   163  			{
   164  				Name: ipfsClients.EnvIPFSClusterSecret,
   165  				ValueFrom: &corev1.EnvVarSource{
   166  					SecretKeyRef: &corev1.SecretKeySelector{
   167  						LocalObjectReference: corev1.LocalObjectReference{
   168  							Name: toCreate.Spec.ClusterSecretName,
   169  						},
   170  						Key: "secret",
   171  					},
   172  				},
   173  			},
   174  			{
   175  				Name:  ipfsClients.EnvIPFSClusterTrustedPeers,
   176  				Value: strings.Join(toCreate.Spec.TrustedPeers, ","),
   177  			},
   178  			{
   179  				Name:  ipfsClients.EnvIPFSClusterId,
   180  				Value: toCreate.Spec.ID,
   181  			},
   182  			{
   183  				Name: ipfsClients.EnvIPFSClusterPrivateKey,
   184  				ValueFrom: &corev1.EnvVarSource{
   185  					SecretKeyRef: &corev1.SecretKeySelector{
   186  						LocalObjectReference: corev1.LocalObjectReference{
   187  							Name: toCreate.Spec.PrivateKeySecretName,
   188  						},
   189  						Key: "key",
   190  					},
   191  				},
   192  			},
   193  		}))
   194  	})
   195  
   196  	It("Should create allocate correct resources to cluster peer statefulset", func() {
   197  		fetched := &appsv1.StatefulSet{}
   198  		expectedResources := corev1.ResourceRequirements{
   199  			Requests: corev1.ResourceList{
   200  				corev1.ResourceCPU:    resource.MustParse(ipfsv1alpha1.DefaultNodeCPURequest),
   201  				corev1.ResourceMemory: resource.MustParse(ipfsv1alpha1.DefaultNodeMemoryRequest),
   202  			},
   203  			Limits: corev1.ResourceList{
   204  				corev1.ResourceCPU:    resource.MustParse(ipfsv1alpha1.DefaultNodeCPULimit),
   205  				corev1.ResourceMemory: resource.MustParse(ipfsv1alpha1.DefaultNodeMemoryLimit),
   206  			},
   207  		}
   208  		Expect(k8sClient.Get(context.Background(), key, fetched)).To(Succeed())
   209  		Expect(fetched.Spec.Template.Spec.Containers[0].Resources).To(Equal(expectedResources))
   210  	})
   211  
   212  	It("Should create peer configmap", func() {
   213  		fetched := &corev1.ConfigMap{}
   214  		Expect(k8sClient.Get(context.Background(), key, fetched)).To(Succeed())
   215  		Expect(fetched.OwnerReferences).To(ContainElements(peerOwnerReference))
   216  		Expect(fetched.Data).To(HaveKey("init_ipfs_cluster_config.sh"))
   217  	})
   218  
   219  	It("Should create peer data persistent volume with correct resources", func() {
   220  		fetched := &corev1.PersistentVolumeClaim{}
   221  		Expect(k8sClient.Get(context.Background(), key, fetched)).To(Succeed())
   222  		Expect(fetched.OwnerReferences).To(ContainElements(peerOwnerReference))
   223  
   224  		expectedResources := corev1.VolumeResourceRequirements{
   225  			Requests: corev1.ResourceList{
   226  				corev1.ResourceStorage: resource.MustParse(ipfsv1alpha1.DefaultNodeStorageRequest),
   227  			},
   228  		}
   229  		Expect(fetched.Spec.Resources).To(Equal(expectedResources))
   230  	})
   231  
   232  	It("Should create peer service", func() {
   233  		fetched := &corev1.Service{}
   234  		Expect(k8sClient.Get(context.Background(), key, fetched)).To(Succeed())
   235  		Expect(fetched.OwnerReferences).To(ContainElements(peerOwnerReference))
   236  		Expect(fetched.Spec.Ports).To(ContainElements(
   237  			[]corev1.ServicePort{
   238  				{
   239  					Name:       "swarm",
   240  					Port:       9096,
   241  					TargetPort: intstr.FromString("swarm"),
   242  					Protocol:   corev1.ProtocolTCP,
   243  				},
   244  				{
   245  					Name:       "swarm-udp",
   246  					Port:       9096,
   247  					TargetPort: intstr.FromString("swarm-udp"),
   248  					Protocol:   corev1.ProtocolUDP,
   249  				},
   250  				{
   251  					Name:       "api",
   252  					Port:       5001,
   253  					TargetPort: intstr.FromString("api"),
   254  					Protocol:   corev1.ProtocolTCP,
   255  				},
   256  				{
   257  					Name:       "proxy-api",
   258  					Port:       9095,
   259  					TargetPort: intstr.FromString("proxy-api"),
   260  					Protocol:   corev1.ProtocolTCP,
   261  				},
   262  				{
   263  					Name:       "rest",
   264  					Port:       9094,
   265  					TargetPort: intstr.FromString("rest"),
   266  					Protocol:   corev1.ProtocolTCP,
   267  				},
   268  				{
   269  					Name:       "metrics",
   270  					Port:       8888,
   271  					TargetPort: intstr.FromString("metrics"),
   272  					Protocol:   corev1.ProtocolTCP,
   273  				},
   274  				{
   275  					Name:       "tracing",
   276  					Port:       6831,
   277  					TargetPort: intstr.FromString("tracing"),
   278  					Protocol:   corev1.ProtocolTCP,
   279  				},
   280  			},
   281  		))
   282  	})
   283  
   284  	It(fmt.Sprintf("Should delete %s namespace", ns.Name), func() {
   285  		Expect(k8sClient.Delete(context.Background(), ns)).To(Succeed())
   286  	})
   287  
   288  })