From 39aa9f0941d3d53ca653d302c3846fc571194fdd Mon Sep 17 00:00:00 2001 From: Piyush Jain <122745947+d3vb0ox@users.noreply.github.com> Date: Mon, 17 Mar 2025 23:15:32 +0530 Subject: [PATCH] chore(infra-updates): updates and fixes (#4976) --- .../workflows/terrafrom-plan-and-apply.yml | 30 +--- helm-chart/templates/cronjob.yaml | 164 +++++++++++------- helm-chart/templates/deployment.yaml | 13 +- helm-chart/values.yaml | 6 +- infra/terraform/clouwatch.tf | 27 +++ infra/terraform/main.tf | 76 +++++++- 6 files changed, 213 insertions(+), 103 deletions(-) create mode 100644 infra/terraform/clouwatch.tf diff --git a/.github/workflows/terrafrom-plan-and-apply.yml b/.github/workflows/terrafrom-plan-and-apply.yml index 25b1422d0f..a2f0bc2107 100644 --- a/.github/workflows/terrafrom-plan-and-apply.yml +++ b/.github/workflows/terrafrom-plan-and-apply.yml @@ -2,12 +2,12 @@ name: 'Terraform' on: workflow_dispatch: - pull_request: push: branches: - main - paths: - - 'infra/terraform/**' + pull_request: + branches: + - main permissions: id-token: write @@ -37,40 +37,16 @@ jobs: continue-on-error: true working-directory: infra/terraform -# - name: Post Format -# if: always() && github.ref != 'refs/heads/main' && (steps.fmt.outcome == 'success' || steps.fmt.outcome == 'failure') -# uses: robburger/terraform-pr-commenter@v1 -# with: -# commenter_type: fmt -# commenter_input: ${{ format('{0}{1}', steps.fmt.outputs.stdout, steps.fmt.outputs.stderr) }} -# commenter_exitcode: ${{ steps.fmt.outputs.exitcode }} - - name: Terraform Init id: init run: terraform init working-directory: infra/terraform -# - name: Post Init -# if: always() && github.ref != 'refs/heads/main' && (steps.init.outcome == 'success' || steps.init.outcome == 'failure') -# uses: robburger/terraform-pr-commenter@v1 -# with: -# commenter_type: init -# commenter_input: ${{ format('{0}{1}', steps.init.outputs.stdout, steps.init.outputs.stderr) }} -# commenter_exitcode: ${{ steps.init.outputs.exitcode }} - - name: Terraform Validate id: validate run: terraform validate working-directory: infra/terraform -# - name: Post Validate -# if: always() && github.ref != 'refs/heads/main' && (steps.validate.outcome == 'success' || steps.validate.outcome == 'failure') -# uses: robburger/terraform-pr-commenter@v1 -# with: -# commenter_type: validate -# commenter_input: ${{ format('{0}{1}', steps.validate.outputs.stdout, steps.validate.outputs.stderr) }} -# commenter_exitcode: ${{ steps.validate.outputs.exitcode }} - - name: Terraform Plan id: plan run: terraform plan -out .planfile diff --git a/helm-chart/templates/cronjob.yaml b/helm-chart/templates/cronjob.yaml index b6051079ea..6c3cbbe46f 100644 --- a/helm-chart/templates/cronjob.yaml +++ b/helm-chart/templates/cronjob.yaml @@ -1,49 +1,40 @@ {{- if (.Values.cronJob).enabled }} {{- range $name, $job := .Values.cronJob.jobs }} --- -apiVersion: {{ if $.Capabilities.APIVersions.Has "batch/v1/CronJob" }}batch/v1{{ else }}batch/v1beta1{{ end }} +{{ if $.Capabilities.APIVersions.Has "batch/v1/CronJob" -}} +apiVersion: batch/v1 +{{- else -}} +apiVersion: batch/v1beta1 +{{- end }} kind: CronJob metadata: - name: {{ $name }} labels: - # Standard labels for tracking CronJobs - {{- include "formbricks.labels" $ | nindent 4 }} - - # Additional labels if specified - {{- if $job.additionalLabels }} - {{- toYaml $job.additionalLabels | indent 4 }} - {{- end }} - - # Additional annotations if specified - {{- if $job.annotations }} + {{- include "formbricks.labels" $ | nindent 4 }} +{{- if $job.additionalLabels }} +{{ $job.additionalLabels | indent 4 }} +{{- end }} +{{- if $job.annotations }} annotations: - {{- toYaml $job.annotations | indent 4 }} - {{- end }} - +{{ $job.annotations | indent 4 }} +{{- end }} + name: {{ $name }} + namespace: {{ template "formbricks.namespace" $ }} spec: - # Define the execution schedule for the job schedule: {{ $job.schedule | quote }} - - # Kubernetes 1.27+ supports time zones for CronJobs - {{- if ge (int $.Capabilities.KubeVersion.Minor) 27 }} - {{- if $job.timeZone }} +{{- if ge (int $.Capabilities.KubeVersion.Minor) 27 }} +{{- if $job.timeZone }} timeZone: {{ $job.timeZone }} - {{- end }} - {{- end }} - - # Define job retention policies - {{- if $job.successfulJobsHistoryLimit }} +{{ end }} +{{- end }} +{{- if $job.successfulJobsHistoryLimit }} successfulJobsHistoryLimit: {{ $job.successfulJobsHistoryLimit }} - {{- end }} - {{- if $job.failedJobsHistoryLimit }} - failedJobsHistoryLimit: {{ $job.failedJobsHistoryLimit }} - {{- end }} - - # Define concurrency policy - {{- if $job.concurrencyPolicy }} +{{ end }} +{{- if $job.concurrencyPolicy }} concurrencyPolicy: {{ $job.concurrencyPolicy }} - {{- end }} - +{{ end }} +{{- if $job.failedJobsHistoryLimit }} + failedJobsHistoryLimit: {{ $job.failedJobsHistoryLimit }} +{{ end }} jobTemplate: spec: {{- with $job.activeDeadlineSeconds }} @@ -55,48 +46,101 @@ spec: template: metadata: labels: - {{- include "formbricks.labels" $ | nindent 12 }} - - # Additional pod-level labels + {{- include "formbricks.labels" $ | nindent 12 }} {{- with $job.additionalPodLabels }} {{- toYaml . | nindent 12 }} {{- end }} - - # Additional annotations {{- with $job.additionalPodAnnotations }} - annotations: {{- toYaml . | nindent 12 }} + annotations: {{ toYaml . | nindent 12 }} {{- end }} - spec: - # Define the service account if RBAC is enabled {{- if $.Values.rbac.enabled }} + {{- if $.Values.rbac.serviceAccount.name }} + serviceAccountName: {{ $.Values.rbac.serviceAccount.name }} + {{- else }} serviceAccountName: {{ template "formbricks.name" $ }} {{- end }} - - # Define the job container + {{- end }} containers: - - name: {{ $name }} - image: "{{ required "Image repository is undefined" $job.image.repository }}:{{ $job.image.tag | default "latest" }}" - imagePullPolicy: {{ $job.image.imagePullPolicy | default "IfNotPresent" }} - - # Environment variables from values + - name: {{ $name }} + {{- $image := required (print "Undefined image repo for container '" $name "'") $job.image.repository }} + {{- with $job.image.tag }} {{- $image = print $image ":" . }} {{- end }} + {{- with $job.image.digest }} {{- $image = print $image "@" . }} {{- end }} + image: {{ $image }} + {{- if $job.image.imagePullPolicy }} + imagePullPolicy: {{ $job.image.imagePullPolicy }} + {{ end }} {{- with $job.env }} - env: + env: {{- range $key, $value := $job.env }} - - name: {{ $key }} - value: {{ $value | quote }} + - name: {{ include "formbricks.tplvalues.render" ( dict "value" $key "context" $ ) }} + {{- if kindIs "string" $value }} + value: {{ include "formbricks.tplvalues.render" ( dict "value" $value "context" $ ) | quote }} + {{- else }} + {{- toYaml $value | nindent 16 }} + {{- end }} {{- end }} {{- end }} - - # Define command and arguments if specified - {{- with $job.command }} - command: {{- toYaml . | indent 14 }} + {{- with $job.envFrom }} + envFrom: + {{ toYaml . | indent 12 }} + {{- end }} + {{- if $job.command }} + command: {{ $job.command }} {{- end }} - {{- with $job.args }} - args: {{- toYaml . | indent 14 }} + args: + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} + {{- with $job.resources }} + resources: + {{ toYaml . | indent 14 }} {{- end }} - - restartPolicy: {{ $job.restartPolicy | default "OnFailure" }} + {{- with $job.volumeMounts }} + volumeMounts: +{{ toYaml . | indent 12 }} + {{- end }} + {{- with $job.securityContext }} + securityContext: {{ toYaml . | nindent 14 }} + {{- end }} + {{- with $job.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 12 }} + {{- end }} + {{- with $job.affinity }} + affinity: +{{ toYaml . | indent 12 }} + {{- end }} + {{- with $job.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with $job.tolerations }} + tolerations: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with $job.topologySpreadConstraints }} + topologySpreadConstraints: {{ toYaml . | nindent 12 }} + {{- end }} + {{- if $job.restartPolicy }} + restartPolicy: {{ $job.restartPolicy }} + {{ else }} + restartPolicy: OnFailure + {{ end }} + {{- with $job.imagePullSecrets }} + imagePullSecrets: +{{ toYaml . | indent 12 }} + {{ end }} + {{- if $job.dnsConfig }} + dnsConfig: +{{ toYaml $job.dnsConfig | indent 12 }} + {{- end }} + {{- if $job.dnsPolicy }} + dnsPolicy: {{ $job.dnsPolicy }} + {{- end }} + {{- with $job.volumes }} + volumes: +{{ toYaml . | indent 12 }} + {{- end }} {{- end }} {{- end }} diff --git a/helm-chart/templates/deployment.yaml b/helm-chart/templates/deployment.yaml index 378233d183..a9fe7fd64e 100644 --- a/helm-chart/templates/deployment.yaml +++ b/helm-chart/templates/deployment.yaml @@ -13,6 +13,9 @@ metadata: {{- if .Values.deployment.annotations }} {{- toYaml .Values.deployment.annotations | nindent 4 }} {{- end }} + {{- if .Values.deployment.reloadOnChange }} + reloader.stakater.com/auto: "true" + {{- end }} {{- end }} spec: {{- if .Values.deployment.replicas }} @@ -124,13 +127,13 @@ spec: {{- end }} {{- end }} env: - {{- if and (.Values.enterprise.enabled) (ne .Values.enterprise.licenseKey "") }} - - name: ENTERPRISE_LICENSE_KEY - value: {{ .Values.enterprise.licenseKey | quote }} - {{- end }} {{- range $key, $value := .Values.deployment.env }} - name: {{ include "formbricks.tplvalues.render" ( dict "value" $key "context" $ ) }} - {{ include "formbricks.tplvalues.render" ( dict "value" $value "context" $ ) | indent 10 }} + {{- if kindIs "string" $value }} + value: {{ include "formbricks.tplvalues.render" ( dict "value" $value "context" $ ) | quote }} + {{- else }} + {{- toYaml $value | nindent 14 }} + {{- end }} {{- end }} {{- if .Values.deployment.resources }} resources: diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml index 684b3ec130..def45c5aa5 100644 --- a/helm-chart/values.yaml +++ b/helm-chart/values.yaml @@ -60,10 +60,8 @@ deployment: # Environment variables passed to the app container env: - EMAIL_VERIFICATION_DISABLED: - value: "1" - PASSWORD_RESET_DISABLED: - value: "1" + DOCKER_CRON_ENABLED: + value: "0" # Tolerations for scheduling pods on tainted nodes tolerations: [] diff --git a/infra/terraform/clouwatch.tf b/infra/terraform/clouwatch.tf new file mode 100644 index 0000000000..2dc70cf68d --- /dev/null +++ b/infra/terraform/clouwatch.tf @@ -0,0 +1,27 @@ +data "aws_ssm_parameter" "slack_notification_channel" { + name = "/prod/formbricks/slack-webhook-url" + with_decryption = true +} + +resource "aws_cloudwatch_log_group" "cloudwatch_cis_benchmark" { + name = "/aws/cis-benchmark-group" + retention_in_days = 365 +} + +module "notify-slack" { + source = "terraform-aws-modules/notify-slack/aws" + version = "6.6.0" + + slack_channel = "kubernetes" + slack_username = "formbricks-cloudwatch" + slack_webhook_url = data.aws_ssm_parameter.slack_notification_channel.value + sns_topic_name = "cloudwatch-alarms" + create_sns_topic = true +} + +module "cloudwatch_cis-alarms" { + source = "terraform-aws-modules/cloudwatch/aws//modules/cis-alarms" + version = "5.7.1" + log_group_name = aws_cloudwatch_log_group.cloudwatch_cis_benchmark.name + alarm_actions = [module.notify-slack.slack_topic_arn] +} diff --git a/infra/terraform/main.tf b/infra/terraform/main.tf index 1f020e7f5c..7cb6c8ca86 100644 --- a/infra/terraform/main.tf +++ b/infra/terraform/main.tf @@ -32,11 +32,6 @@ module "route53_zones" { } } -output "route53_ns_records" { - value = module.route53_zones.route53_zone_name_servers -} - - module "acm" { source = "terraform-aws-modules/acm/aws" version = "5.1.1" @@ -641,6 +636,7 @@ resource "helm_release" "formbricks" { eks.amazonaws.com/role-arn: ${module.formkey-aws-access.iam_role_arn} serviceMonitor: enabled: true + reloadOnChange: true deployment: image: repository: "ghcr.io/formbricks/formbricks-experimental" @@ -656,13 +652,13 @@ resource "helm_release" "formbricks" { type: secret nameSuffix: app-env annotations: - deployed_at: ${timestamp()} + last_updated_at: ${timestamp()} externalSecret: enabled: true # Enable/disable ExternalSecrets secretStore: name: aws-secrets-manager kind: ClusterSecretStore - refreshInterval: "1h" + refreshInterval: "1m" files: app-env: dataFrom: @@ -670,6 +666,72 @@ resource "helm_release" "formbricks" { app-secrets: dataFrom: key: "prod/formbricks/secrets" + cronJob: + enabled: true + jobs: + survey-status: + schedule: "0 0 * * *" + env: + CRON_SECRET: + valueFrom: + secretKeyRef: + name: "formbricks-app-env" + key: "CRON_SECRET" + WEBAPP_URL: + valueFrom: + secretKeyRef: + name: "formbricks-app-env" + key: "WEBAPP_URL" + image: + repository: curlimages/curl + tag: latest + imagePullPolicy: IfNotPresent + args: + - "/bin/sh" + - "-c" + - 'curl -X POST -H "content-type: application/json" -H "x-api-key: $CRON_SECRET" "$WEBAPP_URL/api/cron/survey-status"' + weekely-summary: + schedule: "0 8 * * 1" + env: + CRON_SECRET: + valueFrom: + secretKeyRef: + name: "formbricks-app-env" + key: "CRON_SECRET" + WEBAPP_URL: + valueFrom: + secretKeyRef: + name: "formbricks-app-env" + key: "WEBAPP_URL" + image: + repository: curlimages/curl + tag: latest + imagePullPolicy: IfNotPresent + args: + - "/bin/sh" + - "-c" + - 'curl -X POST -H "content-type: application/json" -H "x-api-key: $CRON_SECRET" "$WEBAPP_URL/api/cron/weekly-summary"' + ping: + schedule: "0 9 * * *" + env: + CRON_SECRET: + valueFrom: + secretKeyRef: + name: "formbricks-app-env" + key: "CRON_SECRET" + WEBAPP_URL: + valueFrom: + secretKeyRef: + name: "formbricks-app-env" + key: "WEBAPP_URL" + image: + repository: curlimages/curl + tag: latest + imagePullPolicy: IfNotPresent + args: + - "/bin/sh" + - "-c" + - 'curl -X POST -H "content-type: application/json" -H "x-api-key: $CRON_SECRET" "$WEBAPP_URL/api/cron/ping"' EOT ] }