github.com/kotalco/kotal@v0.3.0/controllers/ethereum2/beacon_node_controller_test.go (about) 1 package controllers 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "time" 8 9 appsv1 "k8s.io/api/apps/v1" 10 corev1 "k8s.io/api/core/v1" 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 13 "k8s.io/apimachinery/pkg/api/resource" 14 "k8s.io/apimachinery/pkg/types" 15 "k8s.io/apimachinery/pkg/util/intstr" 16 17 ethereum2v1alpha1 "github.com/kotalco/kotal/apis/ethereum2/v1alpha1" 18 "github.com/kotalco/kotal/controllers/shared" 19 20 . "github.com/onsi/ginkgo/v2" 21 . "github.com/onsi/gomega" 22 "github.com/onsi/gomega/gstruct" 23 ) 24 25 var _ = Describe("Ethereum 2.0 beacon node", func() { 26 27 Context("Joining Mainnet", func() { 28 ns := &corev1.Namespace{ 29 ObjectMeta: metav1.ObjectMeta{ 30 Name: "beacon-node", 31 }, 32 } 33 34 key := types.NamespacedName{ 35 Name: "my-node", 36 Namespace: ns.Name, 37 } 38 39 testImage := "kotalco/teku:controller-test" 40 41 spec := ethereum2v1alpha1.BeaconNodeSpec{ 42 Image: testImage, 43 Client: ethereum2v1alpha1.TekuClient, 44 Network: "mainnet", 45 } 46 47 toCreate := ðereum2v1alpha1.BeaconNode{ 48 ObjectMeta: metav1.ObjectMeta{ 49 Name: key.Name, 50 Namespace: key.Namespace, 51 }, 52 Spec: spec, 53 } 54 55 t := true 56 57 nodeOwnerReference := metav1.OwnerReference{ 58 APIVersion: "ethereum2.kotal.io/v1alpha1", 59 Kind: "BeaconNode", 60 Name: toCreate.Name, 61 Controller: &t, 62 BlockOwnerDeletion: &t, 63 } 64 65 It(fmt.Sprintf("Should create %s namespace", ns.Name), func() { 66 Expect(k8sClient.Create(context.TODO(), ns)) 67 }) 68 69 It("Should create beacon node", func() { 70 if os.Getenv(shared.EnvUseExistingCluster) != "true" { 71 toCreate.Default() 72 } 73 Expect(k8sClient.Create(context.Background(), toCreate)).Should(Succeed()) 74 }) 75 76 It("should get beacon node", func() { 77 fetched := ðereum2v1alpha1.BeaconNode{} 78 Expect(k8sClient.Get(context.Background(), key, fetched)).To(Succeed()) 79 Expect(fetched.Spec).To(Equal(toCreate.Spec)) 80 nodeOwnerReference.UID = fetched.GetUID() 81 time.Sleep(5 * time.Second) 82 }) 83 84 It("Should create statefulset with correct arguments", func() { 85 nodeSts := &appsv1.StatefulSet{} 86 87 Expect(k8sClient.Get(context.Background(), key, nodeSts)).To(Succeed()) 88 Expect(nodeSts.GetOwnerReferences()).To(ContainElement(nodeOwnerReference)) 89 Expect(*nodeSts.Spec.Template.Spec.SecurityContext).To(gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ 90 "RunAsUser": gstruct.PointTo(Equal(int64(1000))), 91 "RunAsGroup": gstruct.PointTo(Equal(int64(3000))), 92 "FSGroup": gstruct.PointTo(Equal(int64(2000))), 93 "RunAsNonRoot": gstruct.PointTo(Equal(true)), 94 })) 95 Expect(nodeSts.Spec.Template.Spec.Containers[0].Image).To(Equal(testImage)) 96 }) 97 98 It("Should allocate correct resources to bootnode statefulset", func() { 99 nodeSts := &appsv1.StatefulSet{} 100 expectedResources := corev1.ResourceRequirements{ 101 Requests: corev1.ResourceList{ 102 corev1.ResourceCPU: resource.MustParse(ethereum2v1alpha1.DefaultCPURequest), 103 corev1.ResourceMemory: resource.MustParse(ethereum2v1alpha1.DefaultMemoryRequest), 104 }, 105 Limits: corev1.ResourceList{ 106 corev1.ResourceCPU: resource.MustParse(ethereum2v1alpha1.DefaultCPULimit), 107 corev1.ResourceMemory: resource.MustParse(ethereum2v1alpha1.DefaultMemoryLimit), 108 }, 109 } 110 Expect(k8sClient.Get(context.Background(), key, nodeSts)).To(Succeed()) 111 Expect(nodeSts.Spec.Template.Spec.Containers[0].Resources).To(Equal(expectedResources)) 112 }) 113 114 It("Should create data persistent volume with correct resources", func() { 115 nodePVC := &corev1.PersistentVolumeClaim{} 116 expectedResources := corev1.VolumeResourceRequirements{ 117 Requests: corev1.ResourceList{ 118 corev1.ResourceStorage: resource.MustParse(ethereum2v1alpha1.DefaultStorage), 119 }, 120 } 121 Expect(k8sClient.Get(context.Background(), key, nodePVC)).To(Succeed()) 122 Expect(nodePVC.GetOwnerReferences()).To(ContainElement(nodeOwnerReference)) 123 Expect(nodePVC.Spec.Resources).To(Equal(expectedResources)) 124 }) 125 126 It("Should create node service", func() { 127 nodeSVC := &corev1.Service{} 128 Expect(k8sClient.Get(context.Background(), key, nodeSVC)).To(Succeed()) 129 Expect(nodeSVC.GetOwnerReferences()).To(ContainElement(nodeOwnerReference)) 130 Expect(nodeSVC.Spec.Ports).To(ContainElements([]corev1.ServicePort{ 131 { 132 Name: "discovery", 133 Port: int32(ethereum2v1alpha1.DefaultP2PPort), 134 TargetPort: intstr.FromString("discovery"), 135 Protocol: corev1.ProtocolUDP, 136 }, 137 { 138 Name: "p2p", 139 Port: int32(ethereum2v1alpha1.DefaultP2PPort), 140 TargetPort: intstr.FromString("p2p"), 141 Protocol: corev1.ProtocolTCP, 142 }, 143 })) 144 }) 145 146 It(fmt.Sprintf("Should delete %s namespace", ns.Name), func() { 147 Expect(k8sClient.Delete(context.Background(), ns)).To(Succeed()) 148 }) 149 150 }) 151 })