diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b464979c..b152c6ff 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -5,8 +5,9 @@ ARG MIGRATE_VERSION=4.15.2 ARG WATCH_VERSION=8.4.0 ARG CARGO_LLVM_COV_VERSION=0.5.36 -RUN go install github.com/99designs/gqlgen@latest && \ - go install github.com/golang/mock/mockgen@latest && \ +RUN wget -O- https://carvel.dev/install.sh > install.sh && \ + sudo bash install.sh && \ + rm install.sh && \ go install github.com/mikefarah/yq/v4@latest && \ chmod -R a+w /go/pkg && \ curl -fSsl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ diff --git a/Cargo.lock b/Cargo.lock index a362fdb2..d6f854f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2651,6 +2651,7 @@ dependencies = [ "axum 0.7.5", "fred", "futures", + "http 1.0.0", "pg", "rust_decimal", "serde", diff --git a/client/entrypoint.sh b/client/entrypoint.sh new file mode 100644 index 00000000..97557f5b --- /dev/null +++ b/client/entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +# recursively replace all default GRAPHQL_URI Dockerfile +# assignments in the /usr/share/nginx/html directory with +# the value of the GRAPHQL_URI environment variable +find /usr/share/nginx/html -type f -exec sed -i "s/aHR0cDovL2xvY2FsaG9zdDoxMDAwMAo=/$GRAPHQL_URI/g" {} \; +exec "$@" \ No newline at end of file diff --git a/client/makefile b/client/makefile index ae9305ea..208a7a6b 100644 --- a/client/makefile +++ b/client/makefile @@ -19,6 +19,10 @@ HOST=http://$(LOCAL_ADDRESS) GRAPHQL_URI=$(HOST):$(shell yq '.services.graphql.env_var.set.GRAPHQL_PORT.default' $(PROJECT_CONF)) B64_GRAPHQL_URI=$(shell if [ `uname -s` == 'Darwin' ]; then printf $(GRAPHQL_URI) | base64; else printf $(GRAPHQL_URI) | base64 -w 0; fi) NOHUP_LOG=$(RELATIVE_PROJECT_ROOT_PATH)/$(shell yq '.env_var.set.NOHUP_LOG.default' $(PROJECT_CONF)) +GITHUB_ORG=$(shell yq '.[".github"].env_var.set.GITHUB_ORG.default' $(PROJECT_CONF)) +GITHUB_REPO_NAME=$(shell yq '.[".github"].env_var.set.GITHUB_REPO_NAME.default' $(PROJECT_CONF)) +GITHUB_REGISTRY=$(shell yq '.[".github"].workflows.env_var.set.GITHUB_REGISTRY.default' $(PROJECT_CONF)) +CONTAINER_REGISTRY=$(GITHUB_REGISTRY)/$(GITHUB_ORG)/$(GITHUB_REPO_NAME)/$(APP_NAME) dev: @$(MAKE) start @@ -159,6 +163,15 @@ up: down: docker compose -f ../docker/compose.yaml down +###################### k8s ###################### + +build-k8s: + cd $(RELATIVE_PROJECT_ROOT_PATH); \ + docker build -f ./docker/client.Dockerfile -t $(CONTAINER_REGISTRY):latest . + +push-k8s: + docker push $(CONTAINER_REGISTRY):latest + ###################### utils ###################### date: diff --git a/docker/.gitpod.Dockerfile b/docker/.gitpod.Dockerfile index f7e654b7..d2707659 100644 --- a/docker/.gitpod.Dockerfile +++ b/docker/.gitpod.Dockerfile @@ -3,6 +3,9 @@ FROM gitpod/workspace-full:latest ARG TF_VERSION=1.2.7 RUN bash -lc "rustup default stable" && \ + wget -O- https://carvel.dev/install.sh > install.sh && \ + sudo bash install.sh && \ + rm install.sh && \ go install github.com/mikefarah/yq/v4@latest && \ sudo apt-get install bc -y && \ sudo apt-get clean && \ diff --git a/docker/client.Dockerfile b/docker/client.Dockerfile index 31cfb5a2..ebab20d9 100644 --- a/docker/client.Dockerfile +++ b/docker/client.Dockerfile @@ -1,6 +1,6 @@ -FROM mxfactorial/client-base:v1 as builder1 +FROM mxfactorial/client-base:v1 AS builder1 -ARG GRAPHQL_URI +ARG GRAPHQL_URI=aHR0cDovL2xvY2FsaG9zdDoxMDAwMAo= COPY client . @@ -12,6 +12,10 @@ FROM nginx:latest EXPOSE 80 +COPY --from=builder1 /app/entrypoint.sh /docker-entrypoint.d/40-set-env-vars.sh + +RUN chmod +x /docker-entrypoint.d/40-set-env-vars.sh + COPY --from=builder1 /app/.svelte-kit/output/prerendered/pages/index.html /usr/share/nginx/html COPY --from=builder1 /app/.svelte-kit/output/client/ /usr/share/nginx/html diff --git a/docker/compose.yaml b/docker/compose.yaml index 1a446b64..1b11a5e2 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -247,6 +247,7 @@ services: REDIS_USERNAME: default REDIS_PASSWORD: test MEASURE_PORT: 10010 + READINESS_CHECK_PATH: "/healthz" depends_on: redis: condition: service_healthy @@ -256,7 +257,5 @@ services: build: context: ../ dockerfile: ./docker/client.Dockerfile - args: - - GRAPHQL_URI=${GRAPHQL_URI:-aHR0cDovL2xvY2FsaG9zdDoxMDAwMAo=} ports: - "10009:80" diff --git a/k8s/balance-by-account.yml b/k8s/balance-by-account.yml new file mode 100644 index 00000000..69c929e3 --- /dev/null +++ b/k8s/balance-by-account.yml @@ -0,0 +1,76 @@ +#@ load("@ytt:data", "data") +#@ app = "balance-by-account" +#@ app_port = data.values.BALANCE_BY_ACCOUNT_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: PG_MAX_CONNECTIONS + value: "20" + - name: PG_IDLE_TIMEOUT + value: "10000" + - name: PG_CONN_TIMEOUT + value: "500" + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: #@ app.upper().replace("-", "_") + "_PORT" + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/client.yml b/k8s/client.yml new file mode 100644 index 00000000..91508cc1 --- /dev/null +++ b/k8s/client.yml @@ -0,0 +1,52 @@ +#@ load("@ytt:data", "data") +#@ app = "client" +#@ app_port = 80 +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: GRAPHQL_URI + valueFrom: + configMapKeyRef: + name: client-config + key: GRAPHQL_URI +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: client-config +data: + GRAPHQL_URI: aHR0cDovL2xvY2FsaG9zdDozMDAwMAo= \ No newline at end of file diff --git a/k8s/event.yml b/k8s/event.yml new file mode 100644 index 00000000..98befe14 --- /dev/null +++ b/k8s/event.yml @@ -0,0 +1,54 @@ +#@ load("@ytt:data", "data") +#@ app = "event" +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: REDIS_DB + value: #@ "{}".format(data.values.REDIS_DB) + - name: REDIS_HOST + #! todo: remove hardcode + value: redis + - name: REDIS_PORT + value: #@ "{}".format(data.values.REDIS_PORT) + - name: REDIS_USERNAME + value: #@ data.values.REDIS_USERNAME + - name: REDIS_PASSWORD + value: #@ data.values.REDIS_PASSWORD + livenessProbe: + exec: + command: + - /bin/sh + - -c + - echo + - -n + initialDelaySeconds: 5 + periodSeconds: 5 \ No newline at end of file diff --git a/k8s/graphql.yml b/k8s/graphql.yml new file mode 100644 index 00000000..18c2b7d9 --- /dev/null +++ b/k8s/graphql.yml @@ -0,0 +1,78 @@ +#@ load("@ytt:data", "data") +#@ app = "graphql" +#@ app_port = data.values.GRAPHQL_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: RULE_URL + value: #@ "http://rule:" + "{}".format(data.values.RULE_PORT) + - name: REQUEST_CREATE_URL + value: #@ "http://request-create:" + "{}".format(data.values.REQUEST_CREATE_PORT) + - name: REQUEST_APPROVE_URL + value: #@ "http://request-approve:" + "{}".format(data.values.REQUEST_APPROVE_PORT) + - name: REQUEST_BY_ID_URL + value: #@ "http://request-by-id:" + "{}".format(data.values.REQUEST_BY_ID_PORT) + - name: REQUESTS_BY_ACCOUNT_URL + value: #@ "http://requests-by-account:" + "{}".format(data.values.REQUESTS_BY_ACCOUNT_PORT) + - name: TRANSACTIONS_BY_ACCOUNT_URL + value: #@ "http://transactions-by-account:" + "{}".format(data.values.TRANSACTIONS_BY_ACCOUNT_PORT) + - name: TRANSACTION_BY_ID_URL + value: #@ "http://transaction-by-id:" + "{}".format(data.values.TRANSACTION_BY_ID_PORT) + - name: BALANCE_BY_ACCOUNT_URL + value: #@ "http://balance-by-account:" + "{}".format(data.values.BALANCE_BY_ACCOUNT_PORT) + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: RUST_LOG + value: "info" + - name: GRAPHQL_PORT + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/local/makefile b/k8s/local/makefile new file mode 100644 index 00000000..b2374ba5 --- /dev/null +++ b/k8s/local/makefile @@ -0,0 +1,2 @@ +RELATIVE_PROJECT_ROOT_PATH=$(shell REL_PATH="."; while [ $$(ls "$$REL_PATH" | grep project.yaml | wc -l | xargs) -eq 0 ]; do REL_PATH="$$REL_PATH./.."; done; printf '%s' "$$REL_PATH") +include $(RELATIVE_PROJECT_ROOT_PATH)/make/shared.mk \ No newline at end of file diff --git a/k8s/local/node-ports.yml b/k8s/local/node-ports.yml new file mode 100644 index 00000000..851e0b34 --- /dev/null +++ b/k8s/local/node-ports.yml @@ -0,0 +1,166 @@ +#@ load("@ytt:data", "data") +#@ def convert_to_node_port(port): +#@ if port == 5432: +#@ return 32345 +#@ end +#@ port_str = str(port) +#@ if len(port_str) == 5: +#@ new_port_str = "3" + port_str[1:] +#@ return int(new_port_str) +#@ end +#@ return port +#@ end +--- +apiVersion: v1 +kind: Service +metadata: + name: graphql-node-port +spec: + selector: + app: graphql + ports: + - protocol: TCP + port: #@ data.values.GRAPHQL_PORT + targetPort: #@ data.values.GRAPHQL_PORT + nodePort: #@ convert_to_node_port(data.values.GRAPHQL_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: rule-node-port +spec: + selector: + app: rule + ports: + - protocol: TCP + port: #@ data.values.RULE_PORT + targetPort: #@ data.values.RULE_PORT + nodePort: #@ convert_to_node_port(data.values.RULE_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: request-create-node-port +spec: + selector: + app: request-create + ports: + - protocol: TCP + port: #@ data.values.REQUEST_CREATE_PORT + targetPort: #@ data.values.REQUEST_CREATE_PORT + nodePort: #@ convert_to_node_port(data.values.REQUEST_CREATE_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: request-approve-node-port +spec: + selector: + app: request-approve + ports: + - protocol: TCP + port: #@ data.values.REQUEST_APPROVE_PORT + targetPort: #@ data.values.REQUEST_APPROVE_PORT + nodePort: #@ convert_to_node_port(data.values.REQUEST_APPROVE_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: balance-by-account-node-port +spec: + selector: + app: balance-by-account + ports: + - protocol: TCP + port: #@ data.values.BALANCE_BY_ACCOUNT_PORT + targetPort: #@ data.values.BALANCE_BY_ACCOUNT_PORT + nodePort: #@ convert_to_node_port(data.values.BALANCE_BY_ACCOUNT_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: request-by-id-node-port +spec: + selector: + app: request-by-id + ports: + - protocol: TCP + port: #@ data.values.REQUEST_BY_ID_PORT + targetPort: #@ data.values.REQUEST_BY_ID_PORT + nodePort: #@ convert_to_node_port(data.values.REQUEST_BY_ID_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: requests-by-account-node-port +spec: + selector: + app: requests-by-account + ports: + - protocol: TCP + port: #@ data.values.REQUESTS_BY_ACCOUNT_PORT + targetPort: #@ data.values.REQUESTS_BY_ACCOUNT_PORT + nodePort: #@ convert_to_node_port(data.values.REQUESTS_BY_ACCOUNT_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: transaction-by-id-node-port +spec: + selector: + app: transaction-by-id + ports: + - protocol: TCP + port: #@ data.values.TRANSACTION_BY_ID_PORT + targetPort: #@ data.values.TRANSACTION_BY_ID_PORT + nodePort: #@ convert_to_node_port(data.values.TRANSACTION_BY_ID_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: transactions-by-account-node-port +spec: + selector: + app: transactions-by-account + ports: + - protocol: TCP + port: #@ data.values.TRANSACTIONS_BY_ACCOUNT_PORT + targetPort: #@ data.values.TRANSACTIONS_BY_ACCOUNT_PORT + nodePort: #@ convert_to_node_port(data.values.TRANSACTIONS_BY_ACCOUNT_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: client-node-port +spec: + selector: + app: client + ports: + - protocol: TCP + port: #@ data.values.CLIENT_PORT + targetPort: #@ data.values.CLIENT_PORT + nodePort: #@ convert_to_node_port(data.values.CLIENT_PORT) + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres-node-port +spec: + selector: + app: postgres + ports: + - protocol: TCP + port: #@ data.values.PGPORT + targetPort: #@ data.values.PGPORT + nodePort: #@ convert_to_node_port(data.values.PGPORT) + type: NodePort \ No newline at end of file diff --git a/k8s/makefile b/k8s/makefile new file mode 100644 index 00000000..4ddc062b --- /dev/null +++ b/k8s/makefile @@ -0,0 +1,18 @@ +RELATIVE_PROJECT_ROOT_PATH=.. +include $(RELATIVE_PROJECT_ROOT_PATH)/make/shared.mk + +deploy-local: + @$(MAKE) --no-print-directory -C local env ENV=local + @$(MAKE) --no-print-directory env ENV=local + ytt --data-values-file ./local/$(ENV_FILE_NAME) --data-values-file $(ENV_FILE_NAME) -f . | kubectl apply -f - + +delete-local: + @$(MAKE) --no-print-directory -C local env ENV=local + @$(MAKE) --no-print-directory env ENV=local + ytt --data-values-file ./local/$(ENV_FILE_NAME) --data-values-file $(ENV_FILE_NAME) -f . | kubectl delete -f - + +delete-all-local: + kubectl delete all --all -n default + +list-all: + kubectl get all -n default \ No newline at end of file diff --git a/k8s/measure.yml b/k8s/measure.yml new file mode 100644 index 00000000..fbbad233 --- /dev/null +++ b/k8s/measure.yml @@ -0,0 +1,81 @@ +#@ load("@ytt:data", "data") +#@ app = "measure" +#@ app_port = data.values.MEASURE_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: REDIS_DB + value: #@ "{}".format(data.values.REDIS_DB) + - name: REDIS_HOST + #! todo: remove hardcode + value: redis + - name: REDIS_PORT + value: #@ "{}".format(data.values.REDIS_PORT) + - name: REDIS_USERNAME + value: #@ data.values.REDIS_USERNAME + - name: REDIS_PASSWORD + value: #@ data.values.REDIS_PASSWORD + - name: MEASURE_PORT + value: #@ "{}".format(app_port) + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP diff --git a/k8s/postgres.yml b/k8s/postgres.yml new file mode 100644 index 00000000..bbeda985 --- /dev/null +++ b/k8s/postgres.yml @@ -0,0 +1,59 @@ +#@ load("@ytt:data", "data") +#@ app = "postgres" +#@ app_port = data.values.PGPORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + livenessProbe: + exec: + command: + - pg_isready + - -U + - postgres + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + exec: + command: + - pg_isready + - -U + - postgres + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/redis.yml b/k8s/redis.yml new file mode 100644 index 00000000..66a46b85 --- /dev/null +++ b/k8s/redis.yml @@ -0,0 +1,67 @@ +#@ load("@ytt:data", "data") +#@ app = "redis" +#@ app_port = data.values.REDIS_PORT +#@ image = "bitnami/redis:latest" +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: REDIS_PORT_NUMBER + value: #@ "{}".format(app_port) + - name: REDIS_PASSWORD + value: #@ data.values.REDIS_PASSWORD + livenessProbe: + exec: + command: + - redis-cli + - --no-auth-warning + - -a + - test + - PING + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + exec: + command: + - redis-cli + - --no-auth-warning + - -a + - test + - PING + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/request-approve.yml b/k8s/request-approve.yml new file mode 100644 index 00000000..3464e0eb --- /dev/null +++ b/k8s/request-approve.yml @@ -0,0 +1,76 @@ +#@ load("@ytt:data", "data") +#@ app = "request-approve" +#@ app_port = data.values.REQUEST_APPROVE_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: PG_MAX_CONNECTIONS + value: "20" + - name: PG_IDLE_TIMEOUT + value: "10000" + - name: PG_CONN_TIMEOUT + value: "500" + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: REQUEST_APPROVE_PORT + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/request-by-id.yml b/k8s/request-by-id.yml new file mode 100644 index 00000000..42f30538 --- /dev/null +++ b/k8s/request-by-id.yml @@ -0,0 +1,76 @@ +#@ load("@ytt:data", "data") +#@ app = "request-by-id" +#@ app_port = data.values.REQUEST_BY_ID_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: PG_MAX_CONNECTIONS + value: "20" + - name: PG_IDLE_TIMEOUT + value: "10000" + - name: PG_CONN_TIMEOUT + value: "500" + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: REQUEST_BY_ID_PORT + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/request-create.yml b/k8s/request-create.yml new file mode 100644 index 00000000..69e925de --- /dev/null +++ b/k8s/request-create.yml @@ -0,0 +1,78 @@ +#@ load("@ytt:data", "data") +#@ app = "request-create" +#@ app_port = data.values.REQUEST_CREATE_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: PG_MAX_CONNECTIONS + value: "20" + - name: PG_IDLE_TIMEOUT + value: "10000" + - name: PG_CONN_TIMEOUT + value: "500" + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: RULE_URL + value: #@ "http://rule:" + "{}".format(data.values.RULE_PORT) + - name: REQUEST_CREATE_PORT + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/requests-by-account.yml b/k8s/requests-by-account.yml new file mode 100644 index 00000000..82cdfeeb --- /dev/null +++ b/k8s/requests-by-account.yml @@ -0,0 +1,78 @@ +#@ load("@ytt:data", "data") +#@ app = "requests-by-account" +#@ app_port = data.values.REQUESTS_BY_ACCOUNT_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: PG_MAX_CONNECTIONS + value: "20" + - name: PG_IDLE_TIMEOUT + value: "10000" + - name: PG_CONN_TIMEOUT + value: "500" + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: RETURN_RECORD_LIMIT + value: #@ "{}".format(data.values.RETURN_RECORD_LIMIT) + - name: REQUESTS_BY_ACCOUNT_PORT + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/rule.yml b/k8s/rule.yml new file mode 100644 index 00000000..3fb92fda --- /dev/null +++ b/k8s/rule.yml @@ -0,0 +1,78 @@ +#@ load("@ytt:data", "data") +#@ app = "rule" +#@ app_port = data.values.RULE_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: PG_MAX_CONNECTIONS + value: "20" + - name: PG_IDLE_TIMEOUT + value: "10000" + - name: PG_CONN_TIMEOUT + value: "500" + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: RUST_LOG + value: "info" + - name: RULE_PORT + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/transaction-by-id.yml b/k8s/transaction-by-id.yml new file mode 100644 index 00000000..b0596634 --- /dev/null +++ b/k8s/transaction-by-id.yml @@ -0,0 +1,76 @@ +#@ load("@ytt:data", "data") +#@ app = "transaction-by-id" +#@ app_port = data.values.TRANSACTION_BY_ID_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: #@ image + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: PG_MAX_CONNECTIONS + value: "20" + - name: PG_IDLE_TIMEOUT + value: "10000" + - name: PG_CONN_TIMEOUT + value: "500" + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: TRANSACTION_BY_ID_PORT + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/k8s/transactions-by-account.yml b/k8s/transactions-by-account.yml new file mode 100644 index 00000000..eca789f9 --- /dev/null +++ b/k8s/transactions-by-account.yml @@ -0,0 +1,78 @@ +#@ load("@ytt:data", "data") +#@ app = "transactions-by-account" +#@ app_port = data.values.TRANSACTIONS_BY_ACCOUNT_PORT +#@ image_version = "latest" +#@ image = "{}/{}/{}/{}:{}".format(data.values.GITHUB_REGISTRY, data.values.GITHUB_ORG, data.values.GITHUB_REPO_NAME, app, image_version) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: #@ app + "-deployment" + labels: + app: #@ app +spec: + replicas: 1 + selector: + matchLabels: + app: #@ app + template: + metadata: + labels: + app: #@ app + spec: + containers: + - name: #@ app + image: ghcr.io/systemaccounting/mxfactorial/transactions-by-account:latest + ports: + - containerPort: #@ app_port + env: + - name: PGDATABASE + value: #@ data.values.PGDATABASE + - name: PGUSER + value: #@ data.values.PGUSER + - name: PGPASSWORD + value: #@ data.values.PGPASSWORD + - name: PGHOST + value: postgres + - name: PGPORT + value: #@ "{}".format(data.values.PGPORT) + - name: PG_MAX_CONNECTIONS + value: "20" + - name: PG_IDLE_TIMEOUT + value: "10000" + - name: PG_CONN_TIMEOUT + value: "500" + - name: READINESS_CHECK_PATH + value: #@ data.values.READINESS_CHECK_PATH + - name: RETURN_RECORD_LIMIT + value: #@ "{}".format(data.values.RETURN_RECORD_LIMIT) + - name: TRANSACTIONS_BY_ACCOUNT_PORT + value: #@ "{}".format(app_port) + livenessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + httpGet: + path: #@ data.values.READINESS_CHECK_PATH + port: #@ app_port + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: #@ app +spec: + selector: + app: #@ app + ports: + - protocol: TCP + port: #@ app_port + targetPort: #@ app_port + type: ClusterIP \ No newline at end of file diff --git a/makefile b/makefile index 05520ea8..f9525311 100644 --- a/makefile +++ b/makefile @@ -15,6 +15,11 @@ TFSTATE_EXT=$(shell yq '.infrastructure.terraform.env_var.set.TFSTATE_EXT.defaul TFSTATE_ENV_FILE=$(TFSTATE_ENV_SUFFIX).$(TFSTATE_EXT) COMPOSE_DIR=./docker NOHUP_LOG=$(shell yq '.env_var.set.NOHUP_LOG.default' $(PROJECT_CONF)) +REDIS_DB=$(shell yq '.services.event.env_var.set.REDIS_DB.default' $(PROJECT_CONF)) +REDIS_USERNAME=$(shell yq '.services.event.env_var.set.REDIS_USERNAME.default' $(PROJECT_CONF)) +REDIS_PASSWORD=$(shell yq '.services.event.env_var.set.REDIS_PASSWORD.default' $(PROJECT_CONF)) +REDIS_PORT=$(shell yq '.services.event.env_var.set.REDIS_PORT.default' $(PROJECT_CONF)) +REDIS_HOST=$(shell yq '.services.event.env_var.set.REDIS_HOST.default' $(PROJECT_CONF)) # approx 10 minutes all: @@ -150,6 +155,9 @@ clean: @$(MAKE) --no-print-directory -C tests clean @rm -f ./$(NOHUP_LOG) +redis-uri: + @echo "redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/$(REDIS_DB)" + ###################### docker ###################### test-up: @@ -248,7 +256,6 @@ insert: @$(MAKE) -C ./migrations insert continue-insert: - bash scripts/manage-redis.sh --flush bash scripts/insert-transactions.sh --continue ###################### secrets ###################### diff --git a/project.yaml b/project.yaml index 22f07518..7004de8b 100644 --- a/project.yaml +++ b/project.yaml @@ -228,6 +228,54 @@ infrastructure: TFSTATE_BUCKET_PREFIX: ssm: null default: mxfactorial-tfstate +k8s: + type: lib + params: [] + env_var: + set: null + get: + - BALANCE_BY_ACCOUNT_PORT + - PGDATABASE + - PGUSER + - PGPASSWORD + # - PGHOST # sets localhost instead of "postgres" in k8s + - PGPORT + - READINESS_CHECK_PATH + - GITHUB_REGISTRY + - GITHUB_ORG + - GITHUB_REPO_NAME + - REDIS_DB + # - REDIS_HOST # sets localhost instead of "redis" in k8s + - REDIS_PORT + - REDIS_USERNAME + - REDIS_PASSWORD + - GRAPHQL_PORT + - RULE_PORT + - REQUEST_CREATE_PORT + - REQUEST_APPROVE_PORT + - REQUEST_BY_ID_PORT + - REQUESTS_BY_ACCOUNT_PORT + - TRANSACTIONS_BY_ACCOUNT_PORT + - TRANSACTION_BY_ID_PORT + - MEASURE_PORT + - RETURN_RECORD_LIMIT + local: + type: lib + params: [] + env_var: + set: null + get: + - CLIENT_PORT + - PGPORT + - GRAPHQL_PORT + - RULE_PORT + - REQUEST_CREATE_PORT + - REQUEST_APPROVE_PORT + - BALANCE_BY_ACCOUNT_PORT + - REQUEST_BY_ID_PORT + - REQUESTS_BY_ACCOUNT_PORT + - TRANSACTION_BY_ID_PORT + - TRANSACTIONS_BY_ACCOUNT_PORT migrations: type: lib params: [] @@ -648,6 +696,7 @@ services: - REDIS_USERNAME - REDIS_PASSWORD - MEASURE_PORT + - READINESS_CHECK_PATH auto-confirm: runtime: rust1.x min_code_cov: null @@ -763,4 +812,8 @@ params: [] - name: cargo-llvm-cov os: osx: - install: 'cargo install cargo-llvm-cov' \ No newline at end of file + install: 'cargo install cargo-llvm-cov' + - name: ytt + os: + osx: + install: 'brew tap carvel-dev/carvel && brew install ytt' \ No newline at end of file diff --git a/scripts/README.md b/scripts/README.md index ac571a46..e755e0cf 100755 --- a/scripts/README.md +++ b/scripts/README.md @@ -337,4 +337,7 @@ watches a redis key in docker lists apps configured in `project.yaml` with `deploy: true` ##### `test-all.sh` -run all tests before before creating a pull request \ No newline at end of file +run all tests before before creating a pull request + +##### `set-k8s-ports.sh` +changes ports set in `project.yaml` to 3xxxx for access through kubernetes [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) \ No newline at end of file diff --git a/scripts/create-env-file.sh b/scripts/create-env-file.sh index 73966bda..d3016058 100644 --- a/scripts/create-env-file.sh +++ b/scripts/create-env-file.sh @@ -9,11 +9,20 @@ fi # https://stackoverflow.com/a/33826763 while [[ "$#" -gt 0 ]]; do - case $1 in - --app-name) APP_NAME="$2"; shift ;; - --env) ENV="$2"; shift ;; - *) echo "unknown parameter passed: $1"; exit 1 ;; - esac + case $1 in + --app-name) + APP_NAME="$2" + shift + ;; + --env) + ENV="$2" + shift + ;; + *) + echo "unknown parameter passed: $1" + exit 1 + ;; + esac shift done @@ -68,21 +77,21 @@ function set_default_values() { SVC_NAME=$(printf '%s' "$s" | sed 's/_URL//') PORT_ENV_VAR="$SVC_NAME"_PORT PORT_VAL=$(yq "... | select(has(\"$PORT_ENV_VAR\")).$PORT_ENV_VAR.default" $PROJECT_CONF) - echo "$s=ws://$LOCAL_ADDRESS:$PORT_VAL" >> $ENV_FILE + echo "$s=ws://$LOCAL_ADDRESS:$PORT_VAL" >>$ENV_FILE continue elif [[ "$s" == *'_URL' ]]; then SVC_NAME=$(printf '%s' "$s" | sed 's/_URL//') PORT_ENV_VAR="$SVC_NAME"_PORT PORT_VAL=$(yq "... | select(has(\"$PORT_ENV_VAR\")).$PORT_ENV_VAR.default" $PROJECT_CONF) - echo "$s=$HOST:$PORT_VAL" >> $ENV_FILE + echo "$s=$HOST:$PORT_VAL" >>$ENV_FILE elif [[ "$s" == 'GRAPHQL_URI' ]]; then # todo: change GRAPHQL_URI to GRAPHQL_URL SVC_NAME=$(printf '%s' "$s" | sed 's/_URI//') PORT_ENV_VAR="$SVC_NAME"_PORT PORT_VAL=$(yq "... | select(has(\"$PORT_ENV_VAR\")).$PORT_ENV_VAR.default" $PROJECT_CONF) if [[ $GITPOD_WORKSPACE_URL ]] || [[ $CODESPACES ]]; then - echo "$s=$GRAPHQL_URI" >> $ENV_FILE + echo "$s=$GRAPHQL_URI" >>$ENV_FILE else - echo "$s=$HOST:$PORT_VAL" >> $ENV_FILE + echo "$s=$HOST:$PORT_VAL" >>$ENV_FILE fi elif [[ "$s" == 'GRAPHQL_SUBSCRIPTIONS_URI' ]]; then SVC_NAME=$(printf '%s' "$s" | sed 's/_SUBSCRIPTIONS_URI//') @@ -90,18 +99,18 @@ function set_default_values() { PORT_VAL=$(yq "... | select(has(\"$PORT_ENV_VAR\")).$PORT_ENV_VAR.default" $PROJECT_CONF) # todo: handle in scripts/set-uri-vars.sh if [[ $GITPOD_WORKSPACE_URL ]] || [[ $CODESPACES ]]; then - echo "$s=$GRAPHQL_URI" >> $ENV_FILE + echo "$s=$GRAPHQL_URI" >>$ENV_FILE else - echo "$s=ws://$LOCAL_ADDRESS:$PORT_VAL/ws" >> $ENV_FILE + echo "$s=ws://$LOCAL_ADDRESS:$PORT_VAL/ws" >>$ENV_FILE fi elif [[ "$s" == 'CLIENT_URI' ]]; then # todo: change CLIENT_URI to CLIENT_URL SVC_NAME=$(printf '%s' "$s" | sed 's/_URI//') PORT_ENV_VAR="$SVC_NAME"_PORT PORT_VAL=$(yq "... | select(has(\"$PORT_ENV_VAR\")).$PORT_ENV_VAR.default" $PROJECT_CONF) if [[ $GITPOD_WORKSPACE_URL ]] || [[ $CODESPACES ]]; then - echo "$s=$CLIENT_URI" >> $ENV_FILE + echo "$s=$CLIENT_URI" >>$ENV_FILE else - echo "$s=$HOST:$PORT_VAL" >> $ENV_FILE + echo "$s=$HOST:$PORT_VAL" >>$ENV_FILE fi elif [[ "$s" == 'AWS_LAMBDA_FUNCTION_NAME' ]]; then continue # skip setting when ENV=local @@ -110,7 +119,7 @@ function set_default_values() { if [[ $ENV_VAR == 'null' ]]; then ENV_VAR= fi - echo $s=$ENV_VAR >> $ENV_FILE + echo $s=$ENV_VAR >>$ENV_FILE fi done } @@ -129,7 +138,7 @@ function set_secrets() { else ENV_VAR=$(echo "$CONF_OBJ" | yq ".default") fi - echo $s=$ENV_VAR >> $ENV_FILE + echo $s=$ENV_VAR >>$ENV_FILE unset ENV_VAR done } @@ -137,9 +146,9 @@ function set_secrets() { function set_params() { for p in ${PARAMS[@]}; do if [[ $p == 'AWS_REGION' ]]; then - echo $p=$REGION >> $ENV_FILE + echo $p=$REGION >>$ENV_FILE elif [[ $p == 'ENABLE_API_AUTH' ]]; then - echo ENABLE_API_AUTH=$ENABLE_API_AUTH >> $ENV_FILE + echo ENABLE_API_AUTH=$ENABLE_API_AUTH >>$ENV_FILE fi done } @@ -159,11 +168,21 @@ fi # add ENV_ID back if was removed if [[ $ADD_BACK ]]; then - echo ENV_ID=$ENV_ID >> $ENV_FILE + echo ENV_ID=$ENV_ID >>$ENV_FILE fi set_params +# ytt requires yaml format +# convert $ENV_FILE to yaml if k8s dir is an $ENV_FILE substring +if [[ $ENV_FILE == *'k8s/'* ]]; then + if [[ $(uname) == 'Darwin' ]]; then + sed -i '' 's/=/: /' $ENV_FILE + else + sed -i 's/=/: /' $ENV_FILE + fi +fi + if [[ ! -s $ENV_FILE ]]; then rm -f $ENV_FILE echo 'no env vars required' diff --git a/scripts/insert-transactions.sh b/scripts/insert-transactions.sh index 37126d51..8e2ec613 100644 --- a/scripts/insert-transactions.sh +++ b/scripts/insert-transactions.sh @@ -20,6 +20,12 @@ while [[ "$#" -gt 0 ]]; do done PROJECT_CONF=project.yaml + +# temp set k8s ports if pods are running +if [[ $(kubectl get pods | wc -l | xargs) -gt 3 ]]; then + bash scripts/set-k8s-ports.sh +fi + LOCAL_ADDRESS=$(yq '.env_var.set.LOCAL_ADDRESS.default' $PROJECT_CONF) HOST="http://$LOCAL_ADDRESS" REQUEST_CREATE_PORT=$(yq ".services.request-create.env_var.set.REQUEST_CREATE_PORT.default" $PROJECT_CONF) @@ -42,6 +48,7 @@ export PGPORT=$(yq ".${ENV_VAR_PATH}.PGPORT.default" $PROJECT_CONF) # reset postgres in docker ( + bash scripts/manage-redis.sh --flush cd $MIGRATIONS_DIR make resetdocker DB=test ) @@ -49,6 +56,12 @@ echo "*** finished migrations" echo "" +# reset ports if k8s +if [[ $(kubectl get pods | wc -l | xargs) -gt 3 ]]; then + bash scripts/set-k8s-ports.sh --reset +fi + + function request() { local request="$1" # create transaction request diff --git a/scripts/manage-redis.sh b/scripts/manage-redis.sh index c36863da..9bb5a4af 100644 --- a/scripts/manage-redis.sh +++ b/scripts/manage-redis.sh @@ -35,8 +35,15 @@ function flush() { REDIS_URI="redis://$REDIS_USERNAME:$REDIS_PASSWORD@$REDIS_HOST:$REDIS_PORT/$REDIS_DB" COMPOSE_PROJECT_NAME=$(yq '.name' ./docker/compose.yaml) CONTAINER_NAME="$COMPOSE_PROJECT_NAME-redis-1" + PGPORT=$(yq '.infrastructure.terraform.aws.modules.environment.env_var.set.PGPORT.default' $PROJECT_CONF) - docker exec -it $CONTAINER_NAME redis-cli --no-auth-warning -u $REDIS_URI FLUSHDB + # test for compose or k8s + if [[ "$PGPORT" == "5432" ]]; then + docker exec -it $CONTAINER_NAME redis-cli --no-auth-warning -u $REDIS_URI FLUSHDB + else + POD=$(kubectl get pods -l app=redis -o jsonpath='{.items[0].metadata.name}') + kubectl --stdin --tty exec $POD -- redis-cli --no-auth-warning -u $REDIS_URI FLUSHDB + fi } while [[ "$#" -gt 0 ]]; do diff --git a/scripts/set-k8s-ports.sh b/scripts/set-k8s-ports.sh new file mode 100644 index 00000000..60fa7b50 --- /dev/null +++ b/scripts/set-k8s-ports.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# sets first digit of *_PORT env var values in project.yaml to 1 or 3, e.g. 30001 -> 10001 or 30001 -> 10001 + +if [[ "$#" -gt 1 ]]; then + echo "use: bash scripts/set-k8s-ports.sh # OPTIONAL: --reset" + exit 1 +fi + +while [[ "$#" -gt 0 ]]; do + case $1 in + --reset) RESET=1 ;; + *) + echo "unknown parameter passed: $1" + exit 1 + ;; + esac + shift +done + +PROJECT_CONF=project.yaml + +function set() { + local one_or_three=$1 + + if [[ "$one_or_three" != '1' && "$one_or_three" != '3' ]]; then + echo "function set() requires one argument: 1 or 3" + exit 1 + fi + + declare sed_arg + declare pgport + + if [[ "$one_or_three" == '1' ]]; then + sed_arg='s/^3/1/' + pgport=5432 + else + sed_arg='s/^1/3/' + pgport=32345 + fi + + CONF_PORTS=($(bash scripts/list-env-vars.sh | grep _PORT)) + + for port in "${CONF_PORTS[@]}"; do + SVC_NAME=$(printf '%s' "$port" | sed 's/_PORT//') + # switching redis port unnecessary + if [[ "$SVC_NAME" == 'REDIS' ]]; then + continue + fi + BASE_PATH=$(yq ".. | select(has(\"$port\")) | path | join(\".\")" $PROJECT_CONF) + CONF_PATH=".$BASE_PATH.$SVC_NAME"_PORT.default + CURR_PORT_VALUE=$(yq "$CONF_PATH" $PROJECT_CONF) + export NEW_PORT_VALUE=$(printf '%s' "$CURR_PORT_VALUE" | sed "$sed_arg") + yq -i "$CONF_PATH = env(NEW_PORT_VALUE)" $PROJECT_CONF + unset NEW_PORT_VALUE + done + + # set PGPORT separately to ./k8s/postgres-node-port.yml:spec.ports.containerPort + yq -i ".infrastructure.terraform.aws.modules.environment.env_var.set.PGPORT.default = $pgport" project.yaml + + # remove trailing newline if empty + if [[ -z $(tail -c 1 $PROJECT_CONF) ]]; then + truncate -s -1 $PROJECT_CONF + fi +} + +if [[ -n "$RESET" ]]; then + set 1 +else + set 3 +fi diff --git a/scripts/watch-redis-key.sh b/scripts/watch-redis-key.sh index 73d19d9d..c5ded363 100644 --- a/scripts/watch-redis-key.sh +++ b/scripts/watch-redis-key.sh @@ -1,24 +1,42 @@ #!/bin/bash if [[ "$#" -ne 4 ]] && [[ "$#" -ne 5 ]]; then - cat <<- 'EOF' - use: - bash scripts/watch-redis-key.sh --key gdp:usa:cal:sac --cmd watch # OR sub # OPTIONAL: --no-prefix-date + cat <<-'EOF' + use: + bash scripts/watch-redis-key.sh --key gdp:usa:cal:sac --cmd watch # OR sub # OPTIONAL: --no-prefix-date EOF exit 1 fi while [[ "$#" -gt 0 ]]; do - case $1 in - --key) KEY="$2"; shift ;; - --cmd) CMD="$2"; shift ;; - --no-prefix-date) NO_PREFIX_DATE=1; shift ;; - *) echo "unknown parameter passed: $1"; exit 1 ;; - esac + case $1 in + --key) + KEY="$2" + shift + ;; + --cmd) + CMD="$2" + shift + ;; + --no-prefix-date) + NO_PREFIX_DATE=1 + shift + ;; + *) + echo "unknown parameter passed: $1" + exit 1 + ;; + esac shift done PROJECT_CONF=project.yaml + +# temp set k8s ports if pods are running +if [[ $(kubectl get pods | wc -l | xargs) -gt 3 ]]; then + bash scripts/set-k8s-ports.sh +fi + REDIS_DB=$(yq '.services.event.env_var.set.REDIS_DB.default' $PROJECT_CONF) REDIS_USERNAME=$(yq '.services.event.env_var.set.REDIS_USERNAME.default' $PROJECT_CONF) REDIS_PASSWORD=$(yq '.services.event.env_var.set.REDIS_PASSWORD.default' $PROJECT_CONF) @@ -27,14 +45,31 @@ REDIS_HOST=$(yq '.services.event.env_var.set.REDIS_HOST.default' $PROJECT_CONF) REDIS_URI="redis://$REDIS_USERNAME:$REDIS_PASSWORD@$REDIS_HOST:$REDIS_PORT/$REDIS_DB" COMPOSE_PROJECT_NAME=$(yq '.name' ./docker/compose.yaml) CONTAINER_NAME="$COMPOSE_PROJECT_NAME-redis-1" +PGPORT=$(yq '.infrastructure.terraform.aws.modules.environment.env_var.set.PGPORT.default' $PROJECT_CONF) + +# reset ports if k8s +if [[ $(kubectl get pods | wc -l | xargs) -gt 3 ]]; then + bash scripts/set-k8s-ports.sh --reset +fi if [[ -z "$NO_PREFIX_DATE" ]]; then KEY=$(date -u "+%Y-%m-%d"):$KEY fi if [[ "$CMD" == "sub" ]]; then - docker exec -it $CONTAINER_NAME redis-cli --csv --no-auth-warning -u $REDIS_URI SUBSCRIBE $KEY + # test for compose or k8s + if [[ "$PGPORT" == "5432" ]]; then + docker exec -it $CONTAINER_NAME redis-cli --csv --no-auth-warning -u $REDIS_URI SUBSCRIBE $KEY + else + POD=$(kubectl get pods -l app=redis -o jsonpath='{.items[0].metadata.name}') + kubectl --stdin --tty exec $POD -- redis-cli --csv --no-auth-warning -u $REDIS_URI SUBSCRIBE $KEY + fi exit 0 fi -watch -n 0.5 "docker exec -it $CONTAINER_NAME redis-cli --no-auth-warning -u $REDIS_URI GET $KEY | xargs" \ No newline at end of file +if [[ "$PGPORT" == "5432" ]]; then + watch -n 0.5 "docker exec -it $CONTAINER_NAME redis-cli --no-auth-warning -u $REDIS_URI GET $KEY | xargs" +else + POD=$(kubectl get pods -l app=redis -o jsonpath='{.items[0].metadata.name}') + watch -n 0.5 "kubectl --stdin --tty exec $POD -- redis-cli --no-auth-warning -u $REDIS_URI GET $KEY | xargs" +fi diff --git a/services/event/src/main.rs b/services/event/src/main.rs index f70b7945..64147bad 100644 --- a/services/event/src/main.rs +++ b/services/event/src/main.rs @@ -50,13 +50,25 @@ async fn main() { let redis_uri = redis_conn_uri(); let redis_config = RedisConfig::from_url(&redis_uri).unwrap(); let redis_client = Builder::from_config(redis_config).build().unwrap(); - redis_client.init().await.unwrap(); + + loop { + match redis_client.init().await { + Ok(_) => { + // println!("event connected to redis"); + break; + } + Err(_e) => { + // println!("failed to connect to redis: {}", _e); + tokio::time::sleep(std::time::Duration::from_secs(5)).await; + } + } + } loop { let (client, mut connection) = match tokio_postgres::connect(pg_uri.as_str(), NoTls).await { Ok(conn) => conn, Err(_e) => { - // println!("failed to connect to postgres: {}", e); + // println!("failed to connect to postgres: {}", _e); tokio::time::sleep(std::time::Duration::from_secs(5)).await; continue; } diff --git a/services/measure/Cargo.toml b/services/measure/Cargo.toml index 0b8ed497..5794fd43 100644 --- a/services/measure/Cargo.toml +++ b/services/measure/Cargo.toml @@ -15,3 +15,4 @@ serde = { version = "1.0.208", features = ["serde_derive"] } fred = { version = "9.1.1", default-features = false, features = ["i-pubsub"] } pg = { path = "../../crates/pg" } rust_decimal = "1.34.3" +http = "1.0.0" \ No newline at end of file diff --git a/services/measure/src/main.rs b/services/measure/src/main.rs index 9abd2fce..c76acf76 100644 --- a/services/measure/src/main.rs +++ b/services/measure/src/main.rs @@ -18,6 +18,9 @@ use rust_decimal::Decimal; use serde::Deserialize; use shutdown::shutdown_signal; use std::{env, net::SocketAddr}; +use http::StatusCode; + +const READINESS_CHECK_PATH: &str = "READINESS_CHECK_PATH"; fn redis_conn_uri() -> String { let redis_db = std::env::var("REDIS_DB").unwrap(); @@ -66,10 +69,19 @@ impl Params { #[tokio::main] async fn main() { + let readiness_check_path = env::var(READINESS_CHECK_PATH) + .unwrap_or_else(|_| panic!("{READINESS_CHECK_PATH} variable assignment")); + let conn_uri = DB::create_conn_uri_from_env_vars(); let pool = DB::new_pool(&conn_uri).await; - let app = Router::new().route("/ws", get(ws_handler)).with_state(pool); + let app = Router::new() + .route("/ws", get(ws_handler)) + .route( + readiness_check_path.as_str(), // absolute path so format not used + get(|| async { StatusCode::OK }), + ) + .with_state(pool); let hostname_or_ip = env::var("HOSTNAME_OR_IP").unwrap_or("0.0.0.0".to_string()); let port = env::var("MEASURE_PORT").unwrap(); diff --git a/tests/makefile b/tests/makefile index 61f9afbc..f3ff222e 100644 --- a/tests/makefile +++ b/tests/makefile @@ -23,6 +23,15 @@ test-cloud: @$(MAKE) --no-print-directory -S get-secrets ENV=$(ENV) cargo test --features integration_tests -- --test-threads=1 +test-k8s: + (cd $(RELATIVE_PROJECT_ROOT_PATH); bash scripts/set-k8s-ports.sh) + @$(MAKE) get-secrets ENV=local + @until pg_isready -h localhost -p 32345; do sleep 1; done + @$(MAKE) -S -C ../migrations resetdocker + @$(MAKE) -S -C ../migrations/dumps dump-testseed + cargo test --features integration_tests -- --test-threads=1 + (cd $(RELATIVE_PROJECT_ROOT_PATH); bash scripts/set-k8s-ports.sh --reset) + ###################### secrets ###################### test-env-arg: