From 9a8b93ec9571704eb05a961351ff825011056df8 Mon Sep 17 00:00:00 2001 From: Martin Kysel Date: Thu, 19 Dec 2024 08:21:32 -0500 Subject: [PATCH] Force payer service to use 1 replica (#19) Force the helm charts to only ever run 1 replica. Some drive-by test cleanup. --- helm/xmtp-payer/Chart.yaml | 2 +- helm/xmtp-payer/templates/deployment.yaml | 7 +- helm/xmtp-payer/values.yaml | 7 +- helm/xmtpd/Chart.yaml | 2 +- test/testlib/objects.go | 99 +++++++++++++++++++++++ test/testlib/xmtp_xmtpd.go | 1 - test/xmtp-helm/base_payer_test.go | 7 -- test/xmtp-helm/template_payer_test.go | 32 ++++++-- test/xmtp-helm/template_xmtpd_test.go | 71 ++-------------- 9 files changed, 143 insertions(+), 85 deletions(-) create mode 100644 test/testlib/objects.go diff --git a/helm/xmtp-payer/Chart.yaml b/helm/xmtp-payer/Chart.yaml index 8b49e61..18f85a8 100644 --- a/helm/xmtp-payer/Chart.yaml +++ b/helm/xmtp-payer/Chart.yaml @@ -5,4 +5,4 @@ type: application maintainers: - name: XMTPD version: 0.1.0 -appVersion: "v0.1.1" +appVersion: "v0.1.3" diff --git a/helm/xmtp-payer/templates/deployment.yaml b/helm/xmtp-payer/templates/deployment.yaml index 827075f..e7b91a1 100644 --- a/helm/xmtp-payer/templates/deployment.yaml +++ b/helm/xmtp-payer/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: {{- include "xmtp-payer.labels" . | nindent 4 }} spec: - replicas: {{ .Values.replicaCount }} + replicas: 1 selector: matchLabels: {{- include "xmtp-payer.selectorLabels" . | nindent 6 }} @@ -66,3 +66,8 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 \ No newline at end of file diff --git a/helm/xmtp-payer/values.yaml b/helm/xmtp-payer/values.yaml index 6fe514e..1ffb4ff 100644 --- a/helm/xmtp-payer/values.yaml +++ b/helm/xmtp-payer/values.yaml @@ -1,7 +1,10 @@ -# Default values for xmtpd. +# Default values for Payer. # This is a YAML-formatted file. # Declare variables to be passed into your templates. -replicaCount: 1 + +# we do not support more than 1 process with the same key +# https://github.com/xmtp/xmtpd/issues/334 +# replicaCount: 1 # This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ image: diff --git a/helm/xmtpd/Chart.yaml b/helm/xmtpd/Chart.yaml index 13e0424..f407701 100644 --- a/helm/xmtpd/Chart.yaml +++ b/helm/xmtpd/Chart.yaml @@ -5,4 +5,4 @@ type: application maintainers: - name: XMTPD version: 0.1.0 -appVersion: "v0.1.1" +appVersion: "v0.1.3" diff --git a/test/testlib/objects.go b/test/testlib/objects.go new file mode 100644 index 0000000..2f404c8 --- /dev/null +++ b/test/testlib/objects.go @@ -0,0 +1,99 @@ +package testlib + +import ( + "fmt" + "github.com/gruntwork-io/terratest/modules/helm" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + netv1 "k8s.io/api/networking/v1" + "strings" + "testing" +) + +func ExtractIngressE(t *testing.T, output string) *netv1.Ingress { + parts := strings.Split(output, "---") + for _, part := range parts { + if len(part) == 0 { + continue + } + + if !strings.Contains(part, "kind: Ingress") { + continue + } + + var object netv1.Ingress + helm.UnmarshalK8SYaml(t, part, &object) + + return &object + } + + return nil +} + +func ExtractIngress(t *testing.T, output string) *netv1.Ingress { + ingress := ExtractIngressE(t, output) + + if ingress == nil { + t.Fatalf("Could not extract ingress from template") + } + + return ingress +} + +func ExtractNamedSecretE(t *testing.T, output string, secretName string) *corev1.Secret { + parts := strings.Split(output, "---") + for _, part := range parts { + if len(part) == 0 { + continue + } + + if !strings.Contains(part, "kind: Secret") { + continue + } + + if !strings.Contains(part, fmt.Sprintf("name: %s", secretName)) { + continue + } + + var object corev1.Secret + helm.UnmarshalK8SYaml(t, part, &object) + + return &object + } + + return nil +} + +func ExtractDeploymentE(t *testing.T, output string, deploymentName string) *appsv1.Deployment { + parts := strings.Split(output, "---") + for _, part := range parts { + if len(part) == 0 { + continue + } + + if !strings.Contains(part, "kind: Deployment") { + continue + } + + if !strings.Contains(part, fmt.Sprintf("name: %s", deploymentName)) { + continue + } + + var object appsv1.Deployment + helm.UnmarshalK8SYaml(t, part, &object) + + return &object + } + + return nil +} + +func ExtractDeployment(t *testing.T, output string, deploymentName string) *appsv1.Deployment { + deployment := ExtractDeploymentE(t, output, deploymentName) + + if deployment == nil { + t.Fatalf("Could not extract deployment from template") + } + + return deployment +} diff --git a/test/testlib/xmtp_xmtpd.go b/test/testlib/xmtp_xmtpd.go index 953f3bb..21cefd6 100644 --- a/test/testlib/xmtp_xmtpd.go +++ b/test/testlib/xmtp_xmtpd.go @@ -114,7 +114,6 @@ func getLastSection(envKey string) string { // 3. Default values. func GetDefaultSecrets(t *testing.T) map[string]string { defaultSecrets := map[string]string{ - "env.secret.XMTPD_DB_WRITER_CONNECTION_STRING": "", "env.secret.XMTPD_SIGNER_PRIVATE_KEY": "", "env.secret.XMTPD_PAYER_PRIVATE_KEY": "", "env.secret.XMTPD_CONTRACTS_RPC_URL": "https://rpc-testnet-staging-88dqtxdinc.t.conduit.xyz/", diff --git a/test/xmtp-helm/base_payer_test.go b/test/xmtp-helm/base_payer_test.go index 2132160..5cad3f6 100644 --- a/test/xmtp-helm/base_payer_test.go +++ b/test/xmtp-helm/base_payer_test.go @@ -17,14 +17,7 @@ func TestKubernetesBasicPayerInstall(t *testing.T) { SetValues: map[string]string{}, } - // technically the payer does NOT require a DB - // but XMTPD 0.1.1 has some incorrect defaults - // which will prevent the start of the service without DB connectivity - defer testlib.Teardown(testlib.TEARDOWN_DATABASE) - _, _, db := testlib.StartDB(t, &options, namespace) - secrets := testlib.GetDefaultSecrets(t) - secrets["env.secret.XMTPD_DB_WRITER_CONNECTION_STRING"] = db.ConnString options = helm.Options{ SetValues: secrets, diff --git a/test/xmtp-helm/template_payer_test.go b/test/xmtp-helm/template_payer_test.go index c4777a3..48a1ecc 100644 --- a/test/xmtp-helm/template_payer_test.go +++ b/test/xmtp-helm/template_payer_test.go @@ -4,7 +4,7 @@ import ( "github.com/gruntwork-io/terratest/modules/helm" "github.com/stretchr/testify/assert" "github.com/xmtp/xmtpd-infrastructure/v1/test/testlib" - v1 "k8s.io/api/networking/v1" + netv1 "k8s.io/api/networking/v1" "testing" ) @@ -14,9 +14,8 @@ func TestPayerEmpty(t *testing.T) { } output := helm.RenderTemplate(t, options, testlib.XMTP_PAYER_HELM_CHART_PATH, "release-name", []string{}) - ingress := extractIngressE(t, output) + ingress := testlib.ExtractIngressE(t, output) assert.Nil(t, ingress) - } func TestPayerEnableIngress(t *testing.T) { @@ -29,7 +28,7 @@ func TestPayerEnableIngress(t *testing.T) { output := helm.RenderTemplate(t, options, testlib.XMTP_PAYER_HELM_CHART_PATH, "release-name", []string{}) - ingress := extractIngress(t, output) + ingress := testlib.ExtractIngress(t, output) assert.Contains(t, ingress.Annotations, "kubernetes.io/ingress.class") assert.Equal(t, "nginx", *ingress.Spec.IngressClassName) } @@ -45,7 +44,7 @@ func TestPayerIngressTLSNoSecret(t *testing.T) { output := helm.RenderTemplate(t, options, testlib.XMTP_PAYER_HELM_CHART_PATH, "release-name", []string{}) - ingress := extractIngress(t, output) + ingress := testlib.ExtractIngress(t, output) assert.Contains(t, ingress.Annotations, "cert-manager.io/cluster-issuer") assert.Equal(t, "cert-manager", ingress.Annotations["cert-manager.io/cluster-issuer"]) assert.Empty(t, ingress.Spec.TLS) @@ -64,16 +63,33 @@ func TestPayerIngressTLSSecretNoCreate(t *testing.T) { output := helm.RenderTemplate(t, options, testlib.XMTP_PAYER_HELM_CHART_PATH, "release-name", []string{}) - ingress := extractIngress(t, output) + ingress := testlib.ExtractIngress(t, output) assert.Contains(t, ingress.Annotations, "cert-manager.io/cluster-issuer") assert.Equal(t, "cert-manager", ingress.Annotations["cert-manager.io/cluster-issuer"]) - expectedTLS := v1.IngressTLS{ + expectedTLS := netv1.IngressTLS{ Hosts: []string{"my-host"}, SecretName: "my-secret", } assert.Contains(t, ingress.Spec.TLS, expectedTLS) - secret := extractNamedSecretE(t, output, "my-secret") + secret := testlib.ExtractNamedSecretE(t, output, "my-secret") assert.Nil(t, secret) } + +func TestPayerMax1Replica(t *testing.T) { + // once we have fixed https://github.com/xmtp/xmtpd/issues/334, this should be adjusted + + options := &helm.Options{ + SetValues: map[string]string{ + "replicas": "7", + }, + } + output := helm.RenderTemplate(t, options, testlib.XMTP_PAYER_HELM_CHART_PATH, "release-name", []string{}) + + deployment := testlib.ExtractDeployment(t, output, "release-name-xmtp-payer") + + assert.EqualValues(t, 1, *deployment.Spec.Replicas) + assert.NotNil(t, deployment.Spec.Strategy.RollingUpdate) + +} diff --git a/test/xmtp-helm/template_xmtpd_test.go b/test/xmtp-helm/template_xmtpd_test.go index 89f7e53..f75f11b 100644 --- a/test/xmtp-helm/template_xmtpd_test.go +++ b/test/xmtp-helm/template_xmtpd_test.go @@ -1,77 +1,20 @@ package xmtp_helm import ( - "fmt" "github.com/gruntwork-io/terratest/modules/helm" "github.com/stretchr/testify/assert" "github.com/xmtp/xmtpd-infrastructure/v1/test/testlib" - v2 "k8s.io/api/core/v1" - v1 "k8s.io/api/networking/v1" - "strings" + netv1 "k8s.io/api/networking/v1" "testing" ) -func extractIngressE(t *testing.T, output string) *v1.Ingress { - parts := strings.Split(output, "---") - for _, part := range parts { - if len(part) == 0 { - continue - } - - if !strings.Contains(part, "kind: Ingress") { - continue - } - - var object v1.Ingress - helm.UnmarshalK8SYaml(t, part, &object) - - return &object - } - - return nil -} - -func extractIngress(t *testing.T, output string) *v1.Ingress { - ingress := extractIngressE(t, output) - - if ingress == nil { - t.Fatalf("Could not extract ingress from template") - } - - return ingress -} - -func extractNamedSecretE(t *testing.T, output string, secretName string) *v2.Secret { - parts := strings.Split(output, "---") - for _, part := range parts { - if len(part) == 0 { - continue - } - - if !strings.Contains(part, "kind: Secret") { - continue - } - - if !strings.Contains(part, fmt.Sprintf("name: %s", secretName)) { - continue - } - - var object v2.Secret - helm.UnmarshalK8SYaml(t, part, &object) - - return &object - } - - return nil -} - func TestXmtpdEmpty(t *testing.T) { options := &helm.Options{ SetValues: map[string]string{}, } output := helm.RenderTemplate(t, options, testlib.XMTPD_HELM_CHART_PATH, "release-name", []string{}) - ingress := extractIngressE(t, output) + ingress := testlib.ExtractIngressE(t, output) assert.Nil(t, ingress) } @@ -86,7 +29,7 @@ func TestXmtpdEnableIngress(t *testing.T) { output := helm.RenderTemplate(t, options, testlib.XMTPD_HELM_CHART_PATH, "release-name", []string{}) - ingress := extractIngress(t, output) + ingress := testlib.ExtractIngress(t, output) assert.Contains(t, ingress.Annotations, "kubernetes.io/ingress.class") assert.Equal(t, "nginx", *ingress.Spec.IngressClassName) } @@ -102,7 +45,7 @@ func TestXmtpdIngressTLSNoSecret(t *testing.T) { output := helm.RenderTemplate(t, options, testlib.XMTPD_HELM_CHART_PATH, "release-name", []string{}) - ingress := extractIngress(t, output) + ingress := testlib.ExtractIngress(t, output) assert.Contains(t, ingress.Annotations, "cert-manager.io/cluster-issuer") assert.Equal(t, "cert-manager", ingress.Annotations["cert-manager.io/cluster-issuer"]) assert.Empty(t, ingress.Spec.TLS) @@ -121,16 +64,16 @@ func TestXmtpdIngressTLSSecretNoCreate(t *testing.T) { output := helm.RenderTemplate(t, options, testlib.XMTPD_HELM_CHART_PATH, "release-name", []string{}) - ingress := extractIngress(t, output) + ingress := testlib.ExtractIngress(t, output) assert.Contains(t, ingress.Annotations, "cert-manager.io/cluster-issuer") assert.Equal(t, "cert-manager", ingress.Annotations["cert-manager.io/cluster-issuer"]) - expectedTLS := v1.IngressTLS{ + expectedTLS := netv1.IngressTLS{ Hosts: []string{"my-host"}, SecretName: "my-secret", } assert.Contains(t, ingress.Spec.TLS, expectedTLS) - secret := extractNamedSecretE(t, output, "my-secret") + secret := testlib.ExtractNamedSecretE(t, output, "my-secret") assert.Nil(t, secret) }