github.com/argoproj/argo-events@v1.9.1/controllers/eventbus/installer/jetstream_test.go (about) 1 package installer 2 3 import ( 4 "context" 5 6 "testing" 7 8 "github.com/argoproj/argo-events/common" 9 "github.com/argoproj/argo-events/pkg/apis/eventbus/v1alpha1" 10 "github.com/stretchr/testify/assert" 11 "go.uber.org/zap/zaptest" 12 appv1 "k8s.io/api/apps/v1" 13 corev1 "k8s.io/api/core/v1" 14 apiresource "k8s.io/apimachinery/pkg/api/resource" 15 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 16 "k8s.io/apimachinery/pkg/types" 17 k8sfake "k8s.io/client-go/kubernetes/fake" 18 "sigs.k8s.io/controller-runtime/pkg/client/fake" 19 ) 20 21 var ( 22 testJetStreamEventBus = &v1alpha1.EventBus{ 23 TypeMeta: metav1.TypeMeta{ 24 APIVersion: v1alpha1.SchemeGroupVersion.String(), 25 Kind: "EventBus", 26 }, 27 ObjectMeta: metav1.ObjectMeta{ 28 Namespace: testNamespace, 29 Name: testName, 30 }, 31 Spec: v1alpha1.EventBusSpec{ 32 JetStream: &v1alpha1.JetStreamBus{ 33 Version: "2.7.3", 34 }, 35 }, 36 } 37 38 testJetStreamExoticBus = &v1alpha1.EventBus{ 39 TypeMeta: metav1.TypeMeta{ 40 APIVersion: v1alpha1.SchemeGroupVersion.String(), 41 Kind: "EventBus", 42 }, 43 ObjectMeta: metav1.ObjectMeta{ 44 Namespace: testNamespace, 45 Name: testName, 46 }, 47 Spec: v1alpha1.EventBusSpec{ 48 JetStreamExotic: &v1alpha1.JetStreamConfig{ 49 URL: "nats://nats:4222", 50 }, 51 }, 52 } 53 ) 54 55 func TestJetStreamBadInstallation(t *testing.T) { 56 t.Run("bad installation", func(t *testing.T) { 57 badEventBus := testJetStreamEventBus.DeepCopy() 58 badEventBus.Spec.JetStream = nil 59 installer := &jetStreamInstaller{ 60 client: fake.NewClientBuilder().Build(), 61 kubeClient: k8sfake.NewSimpleClientset(), 62 eventBus: badEventBus, 63 config: fakeConfig, 64 labels: testLabels, 65 logger: zaptest.NewLogger(t).Sugar(), 66 } 67 _, err := installer.Install(context.TODO()) 68 assert.Error(t, err) 69 }) 70 } 71 72 func TestJetStreamGenerateNames(t *testing.T) { 73 n := generateJetStreamStatefulSetName(testJetStreamEventBus) 74 assert.Equal(t, "eventbus-"+testJetStreamEventBus.Name+"-js", n) 75 n = generateJetStreamServerSecretName(testJetStreamEventBus) 76 assert.Equal(t, "eventbus-"+testJetStreamEventBus.Name+"-js-server", n) 77 n = generateJetStreamClientAuthSecretName(testJetStreamEventBus) 78 assert.Equal(t, "eventbus-"+testJetStreamEventBus.Name+"-js-client-auth", n) 79 n = generateJetStreamConfigMapName(testJetStreamEventBus) 80 assert.Equal(t, "eventbus-"+testJetStreamEventBus.Name+"-js-config", n) 81 n = generateJetStreamPVCName(testJetStreamEventBus) 82 assert.Equal(t, "eventbus-"+testJetStreamEventBus.Name+"-js-vol", n) 83 n = generateJetStreamServiceName(testJetStreamEventBus) 84 assert.Equal(t, "eventbus-"+testJetStreamEventBus.Name+"-js-svc", n) 85 } 86 87 func TestJetStreamCreateObjects(t *testing.T) { 88 cl := fake.NewClientBuilder().Build() 89 ctx := context.TODO() 90 i := &jetStreamInstaller{ 91 client: cl, 92 kubeClient: k8sfake.NewSimpleClientset(), 93 eventBus: testJetStreamEventBus, 94 config: fakeConfig, 95 labels: testLabels, 96 logger: zaptest.NewLogger(t).Sugar(), 97 } 98 99 t.Run("test create sts", func(t *testing.T) { 100 testObj := testJetStreamEventBus.DeepCopy() 101 i.eventBus = testObj 102 err := i.createStatefulSet(ctx) 103 assert.NoError(t, err) 104 sts := &appv1.StatefulSet{} 105 err = cl.Get(ctx, types.NamespacedName{Namespace: testObj.Namespace, Name: generateJetStreamStatefulSetName(testObj)}, sts) 106 assert.NoError(t, err) 107 assert.Equal(t, 3, len(sts.Spec.Template.Spec.Containers)) 108 assert.Contains(t, sts.Annotations, common.AnnotationResourceSpecHash) 109 assert.Equal(t, testJetStreamImage, sts.Spec.Template.Spec.Containers[0].Image) 110 assert.Equal(t, testJSReloaderImage, sts.Spec.Template.Spec.Containers[1].Image) 111 assert.Equal(t, testJetStreamExporterImage, sts.Spec.Template.Spec.Containers[2].Image) 112 assert.True(t, len(sts.Spec.Template.Spec.Volumes) > 1) 113 envNames := []string{} 114 for _, e := range sts.Spec.Template.Spec.Containers[0].Env { 115 envNames = append(envNames, e.Name) 116 } 117 for _, e := range []string{"POD_NAME", "SERVER_NAME", "POD_NAMESPACE", "CLUSTER_ADVERTISE", "JS_KEY"} { 118 assert.Contains(t, envNames, e) 119 } 120 }) 121 122 t.Run("test create svc", func(t *testing.T) { 123 testObj := testJetStreamEventBus.DeepCopy() 124 i.eventBus = testObj 125 err := i.createService(ctx) 126 assert.NoError(t, err) 127 svc := &corev1.Service{} 128 err = cl.Get(ctx, types.NamespacedName{Namespace: testObj.Namespace, Name: generateJetStreamServiceName(testObj)}, svc) 129 assert.NoError(t, err) 130 assert.Equal(t, 4, len(svc.Spec.Ports)) 131 assert.Contains(t, svc.Annotations, common.AnnotationResourceSpecHash) 132 }) 133 134 t.Run("test create auth secrets", func(t *testing.T) { 135 testObj := testJetStreamEventBus.DeepCopy() 136 i.eventBus = testObj 137 err := i.createSecrets(ctx) 138 assert.NoError(t, err) 139 s := &corev1.Secret{} 140 err = cl.Get(ctx, types.NamespacedName{Namespace: testObj.Namespace, Name: generateJetStreamServerSecretName(testObj)}, s) 141 assert.NoError(t, err) 142 assert.Equal(t, 8, len(s.Data)) 143 assert.Contains(t, s.Data, common.JetStreamServerSecretAuthKey) 144 assert.Contains(t, s.Data, common.JetStreamServerSecretEncryptionKey) 145 assert.Contains(t, s.Data, common.JetStreamServerPrivateKeyKey) 146 assert.Contains(t, s.Data, common.JetStreamServerCertKey) 147 assert.Contains(t, s.Data, common.JetStreamServerCACertKey) 148 assert.Contains(t, s.Data, common.JetStreamClusterPrivateKeyKey) 149 assert.Contains(t, s.Data, common.JetStreamClusterCertKey) 150 assert.Contains(t, s.Data, common.JetStreamClusterCACertKey) 151 s = &corev1.Secret{} 152 err = cl.Get(ctx, types.NamespacedName{Namespace: testObj.Namespace, Name: generateJetStreamClientAuthSecretName(testObj)}, s) 153 assert.NoError(t, err) 154 assert.Equal(t, 1, len(s.Data)) 155 assert.Contains(t, s.Data, common.JetStreamClientAuthSecretKey) 156 }) 157 158 t.Run("test create configmap", func(t *testing.T) { 159 testObj := testJetStreamEventBus.DeepCopy() 160 i.eventBus = testObj 161 err := i.createConfigMap(ctx) 162 assert.NoError(t, err) 163 c := &corev1.ConfigMap{} 164 err = cl.Get(ctx, types.NamespacedName{Namespace: testObj.Namespace, Name: generateJetStreamConfigMapName(testObj)}, c) 165 assert.NoError(t, err) 166 assert.Equal(t, 1, len(c.Data)) 167 assert.Contains(t, c.Annotations, common.AnnotationResourceSpecHash) 168 }) 169 } 170 171 func TestBuildJetStreamStatefulSetSpec(t *testing.T) { 172 cl := fake.NewClientBuilder().Build() 173 i := &jetStreamInstaller{ 174 client: cl, 175 eventBus: testJetStreamEventBus, 176 config: fakeConfig, 177 labels: testLabels, 178 logger: zaptest.NewLogger(t).Sugar(), 179 } 180 181 t.Run("without persistence", func(t *testing.T) { 182 s := i.buildStatefulSetSpec(&fakeConfig.EventBus.JetStream.Versions[0]) 183 assert.Equal(t, int32(3), *s.Replicas) 184 assert.Equal(t, generateJetStreamServiceName(testJetStreamEventBus), s.ServiceName) 185 assert.Equal(t, testJetStreamImage, s.Template.Spec.Containers[0].Image) 186 assert.Equal(t, testJSReloaderImage, s.Template.Spec.Containers[1].Image) 187 assert.Equal(t, testJetStreamExporterImage, s.Template.Spec.Containers[2].Image) 188 assert.Equal(t, "test-controller", s.Selector.MatchLabels["controller"]) 189 assert.Equal(t, jsClientPort, s.Template.Spec.Containers[0].Ports[0].ContainerPort) 190 assert.Equal(t, jsClusterPort, s.Template.Spec.Containers[0].Ports[1].ContainerPort) 191 assert.Equal(t, jsMonitorPort, s.Template.Spec.Containers[0].Ports[2].ContainerPort) 192 assert.Equal(t, jsMetricsPort, s.Template.Spec.Containers[2].Ports[0].ContainerPort) 193 assert.False(t, len(s.VolumeClaimTemplates) > 0) 194 assert.True(t, len(s.Template.Spec.Volumes) > 0) 195 }) 196 197 t.Run("with persistence", func(t *testing.T) { 198 st := "test" 199 i.eventBus.Spec.JetStream = &v1alpha1.JetStreamBus{ 200 Persistence: &v1alpha1.PersistenceStrategy{ 201 StorageClassName: &st, 202 }, 203 } 204 s := i.buildStatefulSetSpec(&fakeConfig.EventBus.JetStream.Versions[0]) 205 assert.True(t, len(s.VolumeClaimTemplates) > 0) 206 }) 207 208 t.Run("with resource requests", func(t *testing.T) { 209 i.eventBus.Spec.JetStream = &v1alpha1.JetStreamBus{ 210 ContainerTemplate: &v1alpha1.ContainerTemplate{ 211 Resources: corev1.ResourceRequirements{ 212 Limits: corev1.ResourceList{ 213 corev1.ResourceCPU: apiresource.Quantity{Format: "1"}, 214 corev1.ResourceMemory: apiresource.Quantity{Format: "350Mi"}, 215 }, 216 Requests: corev1.ResourceList{ 217 corev1.ResourceCPU: apiresource.Quantity{Format: "1"}, 218 corev1.ResourceMemory: apiresource.Quantity{Format: "400Mi"}, 219 }, 220 }, 221 }, 222 223 MetricsContainerTemplate: &v1alpha1.ContainerTemplate{ 224 Resources: corev1.ResourceRequirements{ 225 Limits: corev1.ResourceList{ 226 corev1.ResourceCPU: apiresource.Quantity{Format: "1"}, 227 corev1.ResourceMemory: apiresource.Quantity{Format: "200Mi"}, 228 }, 229 Requests: corev1.ResourceList{ 230 corev1.ResourceCPU: apiresource.Quantity{Format: "1"}, 231 corev1.ResourceMemory: apiresource.Quantity{Format: "200Mi"}, 232 }, 233 }, 234 }, 235 236 ReloaderContainerTemplate: &v1alpha1.ContainerTemplate{ 237 Resources: corev1.ResourceRequirements{ 238 Limits: corev1.ResourceList{ 239 corev1.ResourceCPU: apiresource.Quantity{Format: ".3"}, 240 corev1.ResourceMemory: apiresource.Quantity{Format: "100Mi"}, 241 }, 242 Requests: corev1.ResourceList{ 243 corev1.ResourceCPU: apiresource.Quantity{Format: ".5"}, 244 corev1.ResourceMemory: apiresource.Quantity{Format: "100Mi"}, 245 }, 246 }, 247 }, 248 } 249 250 statefulSpec := i.buildStatefulSetSpec(&fakeConfig.EventBus.JetStream.Versions[0]) 251 252 podContainers := statefulSpec.Template.Spec.Containers 253 containers := map[string]*corev1.Container{} 254 for idx := range podContainers { 255 containers[podContainers[idx].Name] = &podContainers[idx] 256 } 257 258 js := i.eventBus.Spec.JetStream 259 assert.Equal(t, js.ContainerTemplate.Resources, containers["main"].Resources) 260 assert.Equal(t, js.MetricsContainerTemplate.Resources, containers["metrics"].Resources) 261 assert.Equal(t, js.ReloaderContainerTemplate.Resources, containers["reloader"].Resources) 262 }) 263 } 264 265 func TestJetStreamGetServiceSpec(t *testing.T) { 266 cl := fake.NewClientBuilder().Build() 267 i := &jetStreamInstaller{ 268 client: cl, 269 eventBus: testJetStreamEventBus, 270 config: fakeConfig, 271 labels: testLabels, 272 logger: zaptest.NewLogger(t).Sugar(), 273 } 274 spec := i.buildJetStreamServiceSpec() 275 assert.Equal(t, 4, len(spec.Ports)) 276 assert.Equal(t, corev1.ClusterIPNone, spec.ClusterIP) 277 } 278 279 func Test_JSBufferGetReplicas(t *testing.T) { 280 s := v1alpha1.JetStreamBus{} 281 assert.Equal(t, 3, s.GetReplicas()) 282 five := int32(5) 283 s.Replicas = &five 284 assert.Equal(t, 5, s.GetReplicas()) 285 }