diff --git a/.github/workflows/build_images.yml b/.github/workflows/build_images.yml index 2fce318..4a176af 100644 --- a/.github/workflows/build_images.yml +++ b/.github/workflows/build_images.yml @@ -31,6 +31,12 @@ jobs: strategy: matrix: include: + - service: services/authentication + target: web + uses_buf: false + - service: services/authentication + target: migrate + uses_buf: false - service: services/flights uses_buf: true - service: services/aircraft @@ -39,8 +45,6 @@ jobs: - service: services/search needs_app_file: true uses_buf: false - - service: services/authentication - uses_buf: false - service: services/gateway uses_buf: false @@ -78,6 +82,7 @@ jobs: context: ./${{ matrix.service }} file: ./${{ matrix.service }}/Dockerfile push: true + target: ${{ matrix.target || '' }} tags: | - ${{ env.IMAGE_PREFIX }}-${{ matrix.service }}:${{ github.sha }} - ${{ github.ref_name == 'main' && format('{0}-{1}:latest', env.IMAGE_PREFIX, matrix.service) || '' }} + ${{ env.IMAGE_PREFIX }}-${{ matrix.service }}${{ matrix.target && format('-{0}', matrix.target) || '' }}:${{ github.ref_name }} + ${{ github.ref_name == 'main' && format('{0}-{1}{2}:latest', env.IMAGE_PREFIX, matrix.service, matrix.target && format('-{0}', matrix.target) || '') || '' }} diff --git a/docker-compose.yml b/docker-compose.yml index 49fa54c..47cfb2b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ services: - graphql-router: + router-service: image: ghcr.io/apollographql/router:v2.6.2 - container_name: graphql-router + container_name: router-service volumes: - ./supergraph.graphql:/dist/supergraph.graphql - ./router.yml:/dist/router.yml diff --git a/k8s/00-namespace.yml b/k8s/00-namespace.yml new file mode 100644 index 0000000..9b5457b --- /dev/null +++ b/k8s/00-namespace.yml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: aviation +--- +apiVersion: v1 +kind: Namespace +metadata: + name: authentication +--- +apiVersion: v1 +kind: Namespace +metadata: + name: flights +--- +apiVersion: v1 +kind: Namespace +metadata: + name: aircraft +--- +apiVersion: v1 +kind: Namespace +metadata: + name: monitoring +--- +apiVersion: v1 +kind: Namespace +metadata: + name: messaging +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + name: ingress-nginx +--- +apiVersion: v1 +kind: Namespace +metadata: + name: search +--- \ No newline at end of file diff --git a/k8s/01-ingress-controller.yml b/k8s/01-ingress-controller.yml new file mode 100644 index 0000000..cc731e3 --- /dev/null +++ b/k8s/01-ingress-controller.yml @@ -0,0 +1,665 @@ +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx + namespace: ingress-nginx +rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - coordination.k8s.io + resourceNames: + - ingress-nginx-leader + resources: + - leases + verbs: + - get + - update + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission + namespace: ingress-nginx +rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets + - namespaces + verbs: + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission +rules: + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + verbs: + - get + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx + namespace: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx +subjects: + - kind: ServiceAccount + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission + namespace: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx-admission +subjects: + - kind: ServiceAccount + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx +subjects: + - kind: ServiceAccount + name: ingress-nginx + namespace: ingress-nginx +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx-admission +subjects: + - kind: ServiceAccount + name: ingress-nginx-admission + namespace: ingress-nginx +--- +apiVersion: v1 +data: null +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-controller + namespace: ingress-nginx +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-controller + namespace: ingress-nginx +spec: + externalTrafficPolicy: Local + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - appProtocol: http + name: http + port: 80 + protocol: TCP + targetPort: http + - appProtocol: https + name: https + port: 443 + protocol: TCP + targetPort: https + selector: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + type: LoadBalancer +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-controller-admission + namespace: ingress-nginx +spec: + ports: + - appProtocol: https + name: https-webhook + port: 443 + targetPort: webhook + selector: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-controller + namespace: ingress-nginx +spec: + minReadySeconds: 0 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + strategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + spec: + automountServiceAccountToken: true + containers: + - args: + - /nginx-ingress-controller + - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller + - --election-id=ingress-nginx-leader + - --controller-class=k8s.io/ingress-nginx + - --ingress-class=nginx + - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller + - --validating-webhook=:8443 + - --validating-webhook-certificate=/usr/local/certificates/cert + - --validating-webhook-key=/usr/local/certificates/key + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + image: registry.k8s.io/ingress-nginx/controller:v1.13.3@sha256:1b044f6dcac3afbb59e05d98463f1dec6f3d3fb99940bc12ca5d80270358e3bd + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /wait-shutdown + livenessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: controller + ports: + - containerPort: 80 + name: http + protocol: TCP + - containerPort: 443 + name: https + protocol: TCP + - containerPort: 8443 + name: webhook + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + readOnlyRootFilesystem: false + runAsGroup: 82 + runAsNonRoot: true + runAsUser: 101 + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /usr/local/certificates/ + name: webhook-cert + readOnly: true + dnsPolicy: ClusterFirst + nodeSelector: + kubernetes.io/os: linux + serviceAccountName: ingress-nginx + terminationGracePeriodSeconds: 300 + volumes: + - name: webhook-cert + secret: + secretName: ingress-nginx-admission +--- +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission-create + namespace: ingress-nginx +spec: + template: + metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission-create + spec: + automountServiceAccountToken: true + containers: + - args: + - create + - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc + - --namespace=$(POD_NAMESPACE) + - --secret-name=ingress-nginx-admission + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.3@sha256:3d671cf20a35cd94efc5dcd484970779eb21e7938c98fbc3673693b8a117cf39 + imagePullPolicy: IfNotPresent + name: create + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + seccompProfile: + type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux + restartPolicy: OnFailure + serviceAccountName: ingress-nginx-admission + ttlSecondsAfterFinished: 0 +--- +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission-patch + namespace: ingress-nginx +spec: + template: + metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission-patch + spec: + automountServiceAccountToken: true + containers: + - args: + - patch + - --webhook-name=ingress-nginx-admission + - --namespace=$(POD_NAMESPACE) + - --patch-mutating=false + - --secret-name=ingress-nginx-admission + - --patch-failure-policy=Fail + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.3@sha256:3d671cf20a35cd94efc5dcd484970779eb21e7938c98fbc3673693b8a117cf39 + imagePullPolicy: IfNotPresent + name: patch + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + seccompProfile: + type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux + restartPolicy: OnFailure + serviceAccountName: ingress-nginx-admission + ttlSecondsAfterFinished: 0 +--- +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: nginx +spec: + controller: k8s.io/ingress-nginx +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/component: admission-webhook + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/version: 1.13.3 + name: ingress-nginx-admission +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: ingress-nginx-controller-admission + namespace: ingress-nginx + path: /networking/v1/ingresses + port: 443 + failurePolicy: Fail + matchPolicy: Equivalent + name: validate.nginx.ingress.kubernetes.io + rules: + - apiGroups: + - networking.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - ingresses + sideEffects: None \ No newline at end of file diff --git a/k8s/02-cross-namespace-services.yml b/k8s/02-cross-namespace-services.yml new file mode 100644 index 0000000..c9cd795 --- /dev/null +++ b/k8s/02-cross-namespace-services.yml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: flights-service.flights.svc.cluster.local + ports: + - port: 8081 +--- +apiVersion: v1 +kind: Service +metadata: + name: aircraft-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: aircraft-service.aircraft.svc.cluster.local + ports: + - port: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: authentication-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: authentication-service.authentication.svc.cluster.local + ports: + - port: 8000 +--- +apiVersion: v1 +kind: Service +metadata: + name: search-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: search-service.search.svc.cluster.local + ports: + - port: 8082 +--- +apiVersion: v1 +kind: Service +metadata: + name: router-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: router-service.aviation.svc.cluster.local + ports: + - port: 4000 +--- +apiVersion: v1 +kind: Service +metadata: + name: gateway-service + namespace: ingress-nginx +spec: + type: ExternalName + externalName: gateway-service.aviation.svc.cluster.local + ports: + - port: 4001 \ No newline at end of file diff --git a/k8s/03-ingress.yml b/k8s/03-ingress.yml new file mode 100644 index 0000000..07bd35e --- /dev/null +++ b/k8s/03-ingress.yml @@ -0,0 +1,104 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: aviation-ingress + namespace: ingress-nginx + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$1 +spec: + ingressClassName: nginx + rules: + - host: api.aviation.local + http: + paths: + - path: /router/(.*) + pathType: ImplementationSpecific + backend: + service: + name: router-service + port: + number: 4000 + - path: /router + pathType: Prefix + backend: + service: + name: router-service + port: + number: 4000 + - path: /flights/(.*) + pathType: ImplementationSpecific + backend: + service: + name: flights-service + port: + number: 8081 + - path: /flights + pathType: Prefix + backend: + service: + name: flights-service + port: + number: 8081 + - path: /aircraft/(.*) + pathType: ImplementationSpecific + backend: + service: + name: aircraft-service + port: + number: 8080 + - path: /aircraft + pathType: Prefix + backend: + service: + name: aircraft-service + port: + number: 8080 + - path: /auth/(.*) + pathType: ImplementationSpecific + backend: + service: + name: authentication-service + port: + number: 8000 + - path: /auth + pathType: Prefix + backend: + service: + name: authentication-service + port: + number: 8000 + - path: /gateway/(.*) + pathType: ImplementationSpecific + backend: + service: + name: gateway-service + port: + number: 4001 + - path: /gateway + pathType: Prefix + backend: + service: + name: gateway-service + port: + number: 4001 + - path: /search/(.*) + pathType: ImplementationSpecific + backend: + service: + name: search-service + port: + number: 8082 + - path: /search + pathType: Prefix + backend: + service: + name: search-service + port: + number: 8082 + - path: /(.*) + pathType: ImplementationSpecific + backend: + service: + name: gateway-service + port: + number: 4001 \ No newline at end of file diff --git a/k8s/README.md b/k8s/README.md new file mode 100644 index 0000000..5b1e0b7 --- /dev/null +++ b/k8s/README.md @@ -0,0 +1,50 @@ +# Kubernetes Deployment + +This directory contains Kubernetes manifests for deploying the distributed aviation system components. + + + +## Components + +### Namespace + +- **File**: `00-namespace.yml` +- **Purpose**: Creates the `aviation` namespace for all resources + +## Deployment + +1. Apply the namespace first: + ```bash + kubectl apply -f 00-namespace.yml + ``` + +2. Deploy the flights stack: + ```bash + kubectl apply -f flights/ + ``` + +3. Verify deployment: + ```bash + kubectl get pods -n aviation + ``` + +Or you can deploy everything with: + +```bash +kubectl apply -R -f k8s/ +``` + +## Environment Variables + +The flights service is configured with: + +- Database connection to internal PostgreSQL +- Redis cache connection +- Kafka broker and schema registry endpoints +- OTLP observability endpoint +- gRPC aircraft service endpoint + +## Notes + +- All services run in the `aviation` namespace +- Database uses persistent storage via StatefulSet diff --git a/k8s/aircraft/README.md b/k8s/aircraft/README.md new file mode 100644 index 0000000..0e44af6 --- /dev/null +++ b/k8s/aircraft/README.md @@ -0,0 +1,29 @@ +### Aircraft Service Stack + +#### Database + +- **Type**: PostgreSQL 17.6 StatefulSet +- **Storage**: 1Gi persistent volume +- **Port**: 5432 +- **Credentials**: postgres/postgres +- **Database**: aircraft + +#### Cache + +- **Type**: Redis 8.2 Deployment +- **Port**: 6379 +- **Purpose**: Caching layer for aircraft service + +#### Migrations + +- **Type**: Job +- **Image**: `liquibase/liquibase:4.31` +- **Dependencies**: Waits for database to be ready + +#### Service + +- **Type**: Deployment with Service +- **Port**: 8080 +- **Image**: `ghcr.io/edinstance/distributed-aviation-system-services/aircraft:latest` +- **Dependencies**: Waits for database, migrations and cache to be ready +- **Health Check**: `/health` endpoint diff --git a/k8s/aircraft/cache.yml b/k8s/aircraft/cache.yml new file mode 100644 index 0000000..f460b4d --- /dev/null +++ b/k8s/aircraft/cache.yml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: Service +metadata: + name: aircraft-cache + namespace: aircraft +spec: + ports: + - port: 6379 + selector: + app: aircraft-cache +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: aircraft-cache + namespace: aircraft +spec: + replicas: 1 + selector: + matchLabels: + app: aircraft-cache + template: + metadata: + labels: + app: aircraft-cache + spec: + containers: + - name: redis + image: redis:8.2 + ports: + - containerPort: 6379 + readinessProbe: + exec: + command: [ "redis-cli","ping" ] + initialDelaySeconds: 5 + periodSeconds: 5 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi \ No newline at end of file diff --git a/k8s/aircraft/database.yml b/k8s/aircraft/database.yml new file mode 100644 index 0000000..1412b06 --- /dev/null +++ b/k8s/aircraft/database.yml @@ -0,0 +1,66 @@ +apiVersion: v1 +kind: Service +metadata: + name: aircraft-database + namespace: aircraft +spec: + clusterIP: None + ports: + - port: 5432 + selector: + app: aircraft-database +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: aircraft-database + namespace: aircraft +spec: + serviceName: aircraft-database + replicas: 1 + selector: + matchLabels: + app: aircraft-database + template: + metadata: + labels: + app: aircraft-database + spec: + containers: + - name: postgres + image: postgres:17.6 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: aircraft + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: aircraft-database-password + key: password + readinessProbe: + exec: + command: [ "pg_isready","-U","postgres","-d","aircraft" ] + initialDelaySeconds: 10 + periodSeconds: 5 + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1024Mi + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/k8s/aircraft/migrations.yml b/k8s/aircraft/migrations.yml new file mode 100644 index 0000000..766c9a2 --- /dev/null +++ b/k8s/aircraft/migrations.yml @@ -0,0 +1,71 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: aircraft-migrations + namespace: aircraft +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for Postgres to become available..." + until nc -z aircraft-database.aircraft.svc.cluster.local 5432; do + echo "Still waiting for DB..."; sleep 2; + done + echo "Database is ready!" + - name: fetch-repo + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning Liquibase project repo..." + git clone https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Repository cloned successfully." + volumeMounts: + - name: repo-volume + mountPath: /repo + containers: + - name: liquibase + image: liquibase/liquibase:4.31 + command: + - sh + - -c + - | + set -e + echo "Running Liquibase migrations..." + cd /repo/services/aircraft/src/main/resources/db + liquibase \ + --url="jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}" \ + --username="${DATABASE_USER}" \ + --password="${DATABASE_PASSWORD}" \ + --changelog-file="changelog/db.changelog-master.xml" \ + update + echo "Liquibase migrations completed successfully." + env: + - name: DATABASE_HOST + value: aircraft-database + - name: DATABASE_PORT + value: "5432" + - name: DATABASE_NAME + value: aircraft + - name: DATABASE_USER + value: postgres + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: aircraft-database-password + key: password + volumeMounts: + - name: repo-volume + mountPath: /repo + volumes: + - name: repo-volume + emptyDir: {} \ No newline at end of file diff --git a/k8s/aircraft/secrets.yml b/k8s/aircraft/secrets.yml new file mode 100644 index 0000000..4f90b25 --- /dev/null +++ b/k8s/aircraft/secrets.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: aircraft-database-password + namespace: aircraft +type: Opaque +data: + password: cG9zdGdyZXM= +--- \ No newline at end of file diff --git a/k8s/aircraft/service.yml b/k8s/aircraft/service.yml new file mode 100644 index 0000000..5fa1173 --- /dev/null +++ b/k8s/aircraft/service.yml @@ -0,0 +1,98 @@ +apiVersion: v1 +kind: Service +metadata: + name: aircraft-service + namespace: aircraft +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + - port: 9090 + targetPort: 9090 + protocol: TCP + name: grpc + selector: + app: aircraft-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: aircraft-service + namespace: aircraft +spec: + replicas: 1 + selector: + matchLabels: + app: aircraft-service + template: + metadata: + labels: + app: aircraft-service + spec: + initContainers: + - name: wait-for-db + image: busybox + command: [ "sh", "-c", "until nc -z aircraft-database.aircraft.svc.cluster.local 5432; do sleep 2; done;" ] + - name: wait-for-cache + image: busybox + command: [ "sh", "-c", "until nc -z aircraft-cache.aircraft.svc.cluster.local 6379; do sleep 2; done;" ] + containers: + - name: aircraft-service + image: ghcr.io/edinstance/distributed-aviation-system-services/aircraft:dev + ports: + - containerPort: 8080 + name: http + - containerPort: 9090 + name: grpc + env: + - name: ENVIRONMENT + value: "prod" + - name: PORT + value: "8080" + - name: GRPC_PORT + value: "9090" + - name: DATABASE_URL + value: "jdbc:postgresql://aircraft-database:5432/aircraft" + - name: DATABASE_USERNAME + value: "postgres" + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: aircraft-database-password + key: password + - name: CACHE_URL + value: "redis://aircraft-cache:6379" + - name: LIQUIBASE_ENABLED + value: "false" + - name: OTEL_SERVICE_NAME + value: "aircraft-service" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://otel-collector.monitoring:4317" + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: "grpc" + - name: OTEL_TRACES_EXPORTER + value: "otlp" + - name: OTEL_METRICS_EXPORTER + value: "otlp" + - name: OTEL_LOGS_EXPORTER + value: "otlp" + - name: OTEL_METRIC_EXPORT_INTERVAL + value: "5000" + - name: OTEL_BSP_SCHEDULE_DELAY + value: "5000" + readinessProbe: + httpGet: + path: /details/health + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 500m + memory: 512Mi \ No newline at end of file diff --git a/k8s/authentication/database.yml b/k8s/authentication/database.yml new file mode 100644 index 0000000..a61843c --- /dev/null +++ b/k8s/authentication/database.yml @@ -0,0 +1,66 @@ +apiVersion: v1 +kind: Service +metadata: + name: authentication-database + namespace: authentication +spec: + clusterIP: None + ports: + - port: 5432 + selector: + app: authentication-database +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: authentication-database + namespace: authentication +spec: + serviceName: authentication-database + replicas: 1 + selector: + matchLabels: + app: authentication-database + template: + metadata: + labels: + app: authentication-database + spec: + containers: + - name: postgres + image: postgres:17.6 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: authentication + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: authentication-database-password + key: password + readinessProbe: + exec: + command: [ "pg_isready","-U","postgres","-d","authentication" ] + initialDelaySeconds: 10 + periodSeconds: 5 + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1024Mi + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/k8s/authentication/keygen.yml b/k8s/authentication/keygen.yml new file mode 100644 index 0000000..d0e78ff --- /dev/null +++ b/k8s/authentication/keygen.yml @@ -0,0 +1,63 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: authentication-keygen + namespace: authentication +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + containers: + - name: keygen + image: python:3.12-alpine + workingDir: /app + command: + - sh + - -c + - | + set -e + echo "Installing dependencies..." + pip install --no-cache-dir cryptography==46.0.2 + echo "Cloning repository..." + apk add --no-cache git >/dev/null + git clone https://github.com/edinstance/distributed-aviation-system.git /repo + cd /repo/services/authentication/keys + echo "Generating keys..." + python generate_keys.py + echo "Key generation completed successfully." + env: + - name: KEYS_DIR + value: "/keys" + - name: KEY_PASSWORD + valueFrom: + secretKeyRef: + name: authentication-key-password + key: password + volumeMounts: + - name: keys-volume + mountPath: /keys + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 256Mi + volumes: + - name: keys-volume + persistentVolumeClaim: + claimName: authentication-keys-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: authentication-keys-pvc + namespace: authentication +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Mi +--- \ No newline at end of file diff --git a/k8s/authentication/migrations.yml b/k8s/authentication/migrations.yml new file mode 100644 index 0000000..a16490e --- /dev/null +++ b/k8s/authentication/migrations.yml @@ -0,0 +1,77 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: authentication-migrations + namespace: authentication +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for PostgreSQL to become available..." + until nc -z authentication-database.authentication.svc.cluster.local 5432; do + echo "Still waiting for DB..."; sleep 2; + done + echo "Database is ready!" + - name: wait-for-keys + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for keys to be generated..." + until [ -f /keys/private.pem ] && [ -f /keys/public.pem ]; do + echo "Still waiting for keys..."; sleep 2; + done + echo "Keys are ready!" + volumeMounts: + - name: keys-volume + mountPath: /keys + containers: + - name: authentication-service + image: ghcr.io/edinstance/distributed-aviation-system-services/authentication-migrate:dev + env: + - name: SECRET_KEY + value: insecure-key + - name: KEYS_DIR + value: /keys + - name: KEY_PASSWORD + valueFrom: + secretKeyRef: + name: authentication-key-password + key: password + - name: DATABASE_NAME + value: authentication + - name: DATABASE_USER + value: postgres + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: authentication-database-password + key: password + - name: DATABASE_HOST + value: authentication-database + - name: DATABASE_PORT + value: "5432" + volumeMounts: + - name: keys-volume + mountPath: /keys + readOnly: true + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1024Mi + volumes: + - name: keys-volume + persistentVolumeClaim: + claimName: authentication-keys-pvc \ No newline at end of file diff --git a/k8s/authentication/secrets.yml b/k8s/authentication/secrets.yml new file mode 100644 index 0000000..f35a535 --- /dev/null +++ b/k8s/authentication/secrets.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Secret +metadata: + name: authentication-key-password + namespace: authentication +type: Opaque +data: + password: cGFzc3dvcmQ= +--- +apiVersion: v1 +kind: Secret +metadata: + name: authentication-database-password + namespace: authentication +type: Opaque +data: + password: cG9zdGdyZXM= +--- \ No newline at end of file diff --git a/k8s/authentication/service.yml b/k8s/authentication/service.yml new file mode 100644 index 0000000..432f9c4 --- /dev/null +++ b/k8s/authentication/service.yml @@ -0,0 +1,144 @@ +apiVersion: v1 +kind: Service +metadata: + name: authentication-service + namespace: authentication +spec: + type: ClusterIP + ports: + - port: 8000 + targetPort: 8000 + protocol: TCP + selector: + app: authentication-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: authentication-service + namespace: authentication +spec: + replicas: 1 + selector: + matchLabels: + app: authentication-service + template: + metadata: + labels: + app: authentication-service + spec: + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: [ "sh", "-c", "until nc -z authentication-database.authentication.svc.cluster.local 5432; do sleep 2; done;" ] + - name: wait-for-keygen + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for key generation to complete..." + until [ -f /keys/private.pem ] && [ -f /keys/public.pem ]; do + echo "Keys not ready, waiting..."; sleep 2; + done + echo "Keys are ready!" + volumeMounts: + - name: keys-volume + mountPath: /keys + - name: wait-for-migrations + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Checking if migrations job completed..." + # In a real setup, you'd check job status via API or use a different approach + # For now, we'll just wait a bit after keys are ready + sleep 10 + echo "Migrations should be complete!" + containers: + - name: authentication-service + image: ghcr.io/edinstance/distributed-aviation-system-services/authentication-web:dev + ports: + - containerPort: 8000 + env: + - name: SECRET_KEY + value: insecure-key + - name: DEBUG + value: "False" + - name: ALLOWED_HOSTS + value: localhost,127.0.0.1,authentication-service.authentication.svc.cluster.local,authentication-service.aviation.svc.cluster.local,*.authentication.svc.cluster.local,api.authentication.local,api.aviation.local + - name: DATABASE_NAME + value: authentication + - name: DATABASE_USER + value: postgres + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: authentication-database-password + key: password + - name: DATABASE_HOST + value: authentication-database + - name: DATABASE_PORT + value: "5432" + - name: CORS_ALLOWED_ORIGINS + value: http://localhost:3000,http://127.0.0.1:3000,https://aviation-frontend.cluster.local + - name: CORS_ALLOW_ALL_ORIGINS + value: "False" + - name: CORS_ALLOW_CREDENTIALS + value: "True" + - name: CORS_ALLOWED_HEADERS + value: accept,accept-encoding,authorization,content-type,dnt,origin,user-agent,x-csrftoken,x-requested-with,x-tenant-id + - name: LOG_LEVEL + value: INFO + - name: ENVIRONMENT + value: dev + - name: OTEL_SERVICE_NAME + value: authentication-service + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://otel-collector.monitoring:4317 + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: grpc + - name: OTEL_TRACES_EXPORTER + value: otlp + - name: OTEL_METRICS_EXPORTER + value: otlp + - name: OTEL_LOGS_EXPORTER + value: otlp + - name: OTEL_METRIC_EXPORT_INTERVAL + value: "5000" + - name: OTEL_BSP_SCHEDULE_DELAY + value: "5000" + - name: PORT + value: "8000" + - name: KEYS_DIR + value: /keys + - name: KEY_PASSWORD + valueFrom: + secretKeyRef: + name: authentication-key-password + key: password + volumeMounts: + - name: keys-volume + mountPath: /keys + readOnly: true + readinessProbe: + httpGet: + path: /health + port: 8000 + httpHeaders: + - name: Host + value: authentication-service.aviation.svc.cluster.local + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 500m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi + volumes: + - name: keys-volume + persistentVolumeClaim: + claimName: authentication-keys-pvc \ No newline at end of file diff --git a/k8s/cross-namespace-services-aviation.yml b/k8s/cross-namespace-services-aviation.yml new file mode 100644 index 0000000..4aed627 --- /dev/null +++ b/k8s/cross-namespace-services-aviation.yml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-service + namespace: aviation +spec: + type: ExternalName + externalName: flights-service.flights.svc.cluster.local + ports: + - port: 8081 +--- +apiVersion: v1 +kind: Service +metadata: + name: aircraft-service + namespace: aviation +spec: + type: ExternalName + externalName: aircraft-service.aircraft.svc.cluster.local + ports: + - port: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: search-service + namespace: aviation +spec: + type: ExternalName + externalName: search-service.search.svc.cluster.local + ports: + - port: 8082 \ No newline at end of file diff --git a/k8s/flights/README.md b/k8s/flights/README.md new file mode 100644 index 0000000..ec7ac32 --- /dev/null +++ b/k8s/flights/README.md @@ -0,0 +1,29 @@ +### Flights Service Stack + +#### Database + +- **Type**: PostgreSQL 17.6 StatefulSet +- **Storage**: 1Gi persistent volume +- **Port**: 5432 +- **Credentials**: postgres/postgres +- **Database**: flights + +#### Cache + +- **Type**: Redis 8.2 Deployment +- **Port**: 6379 +- **Purpose**: Caching layer for flights service + +#### Migrations + +- **Type**: Job +- **Image**: `migrate:migrate` +- **Dependencies**: Waits for database to be ready + +#### Service + +- **Type**: Deployment with Service +- **Port**: 8081 +- **Image**: `ghcr.io/edinstance/distributed-aviation-system-services/flights:latest` +- **Dependencies**: Waits for database, migrations and cache to be ready +- **Health Check**: `/health` endpoint diff --git a/k8s/flights/cache.yml b/k8s/flights/cache.yml new file mode 100644 index 0000000..7037fbb --- /dev/null +++ b/k8s/flights/cache.yml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-cache + namespace: flights +spec: + ports: + - port: 6379 + selector: + app: flights-cache +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flights-cache + namespace: flights +spec: + replicas: 1 + selector: + matchLabels: + app: flights-cache + template: + metadata: + labels: + app: flights-cache + spec: + containers: + - name: redis + image: redis:8.2 + ports: + - containerPort: 6379 + readinessProbe: + exec: + command: [ "redis-cli","ping" ] + initialDelaySeconds: 5 + periodSeconds: 5 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi \ No newline at end of file diff --git a/k8s/flights/database.yml b/k8s/flights/database.yml new file mode 100644 index 0000000..777f129 --- /dev/null +++ b/k8s/flights/database.yml @@ -0,0 +1,66 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-database + namespace: flights +spec: + clusterIP: None + ports: + - port: 5432 + selector: + app: flights-database +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: flights-database + namespace: flights +spec: + serviceName: flights-database + replicas: 1 + selector: + matchLabels: + app: flights-database + template: + metadata: + labels: + app: flights-database + spec: + containers: + - name: postgres + image: postgres:17.6 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: flights + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: flights-database-password + key: password + readinessProbe: + exec: + command: [ "pg_isready","-U","postgres","-d","flights" ] + initialDelaySeconds: 10 + periodSeconds: 5 + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1024Mi + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/k8s/flights/migrations.yml b/k8s/flights/migrations.yml new file mode 100644 index 0000000..5727570 --- /dev/null +++ b/k8s/flights/migrations.yml @@ -0,0 +1,51 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: flights-migrations + namespace: flights +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + initContainers: + - name: wait-for-db + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for Postgres to become available..." + until nc -z flights-database.flights.svc.cluster.local 5432; do + echo "Still waiting for DB..."; sleep 2; + done + echo "Database is ready!" + containers: + - name: migrate + image: migrate/migrate:4 + command: + - sh + - -c + - | + set -e + echo "Cloning migration repo..." + apk add --no-cache git curl >/dev/null + git clone https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Running migrations..." + migrate -path /repo/services/flights/migrations \ + -database "postgres://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}?sslmode=disable" up + echo "Migrations completed successfully." + env: + - name: DATABASE_HOST + value: flights-database + - name: DATABASE_PORT + value: "5432" + - name: DATABASE_NAME + value: flights + - name: DATABASE_USER + value: postgres + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: flights-database-password + key: password \ No newline at end of file diff --git a/k8s/flights/secrets.yml b/k8s/flights/secrets.yml new file mode 100644 index 0000000..17a622b --- /dev/null +++ b/k8s/flights/secrets.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: flights-database-password + namespace: flights +type: Opaque +data: + password: cG9zdGdyZXM= +--- \ No newline at end of file diff --git a/k8s/flights/service.yml b/k8s/flights/service.yml new file mode 100644 index 0000000..6cb7474 --- /dev/null +++ b/k8s/flights/service.yml @@ -0,0 +1,73 @@ +apiVersion: v1 +kind: Service +metadata: + name: flights-service + namespace: flights +spec: + type: ClusterIP + ports: + - port: 8081 + targetPort: 8081 + protocol: TCP + selector: + app: flights-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flights-service + namespace: flights +spec: + replicas: 1 + selector: + matchLabels: + app: flights-service + template: + metadata: + labels: + app: flights-service + spec: + initContainers: + - name: wait-for-db + image: busybox + command: [ "sh", "-c", "until nc -z flights-database.flights.svc.cluster.local 5432; do sleep 2; done;" ] + - name: wait-for-cache + image: busybox + command: [ "sh", "-c", "until nc -z flights-cache.flights.svc.cluster.local 6379; do sleep 2; done;" ] + containers: + - name: flights-service + image: ghcr.io/edinstance/distributed-aviation-system-services/flights:dev + ports: + - containerPort: 8081 + env: + - name: DATABASE_URL + value: "postgres://postgres:postgres@flights-database:5432/flights?sslmode=disable" + - name: CACHE_URL + value: "redis://flights-cache:6379" + - name: ENVIRONMENT + value: "prod" + - name: PORT + value: "8081" + - name: AIRCRAFT_SERVICE_GRPC_URL + value: aircraft-service.aircraft:9090 + - name: OTLP_GRPC_URL + value: otel-collector.monitoring:4317 + - name: KAFKA_BROKER_URL + value: kafka.messaging.svc.cluster.local:9092 + - name: KAFKA_SCHEMA_REGISTRY_URL + value: http://schema-registry.messaging.svc.cluster.local:8081 + - name: KAFKA_FLIGHTS_TOPIC + value: flights + readinessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 500m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi \ No newline at end of file diff --git a/k8s/gateway/service.yml b/k8s/gateway/service.yml new file mode 100644 index 0000000..37fc454 --- /dev/null +++ b/k8s/gateway/service.yml @@ -0,0 +1,64 @@ +apiVersion: v1 +kind: Service +metadata: + name: gateway-service + namespace: aviation +spec: + type: ClusterIP + ports: + - port: 4001 + targetPort: 4001 + protocol: TCP + selector: + app: gateway-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gateway-service + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: gateway-service + template: + metadata: + labels: + app: gateway-service + spec: + containers: + - name: gateway-service + image: ghcr.io/edinstance/distributed-aviation-system-services/gateway:dev + ports: + - containerPort: 4001 + env: + - name: ENVIRONMENT + value: "prod" + - name: PORT + value: "4001" + - name: ROUTER_URL + value: http://router-service:4000 + - name: JWKS_URL + value: http://authentication-service:8000/.well-known/jwks.json + - name: LOG_LEVEL + value: "info" + - name: JSON_LOGS + value: "true" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://otel-collector.monitoring:4317 + - name: OTEL_SERVICE_NAME + value: gateway-service + readinessProbe: + httpGet: + path: /health + port: 4001 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 500m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi \ No newline at end of file diff --git a/k8s/messaging/kafka.yml b/k8s/messaging/kafka.yml new file mode 100644 index 0000000..5bc445d --- /dev/null +++ b/k8s/messaging/kafka.yml @@ -0,0 +1,118 @@ +apiVersion: v1 +kind: Service +metadata: + name: kafka + namespace: messaging +spec: + clusterIP: None + selector: + app: kafka + ports: + - name: internal + port: 9092 + protocol: TCP + - name: external + port: 19092 + protocol: TCP + - name: controller + port: 9093 + protocol: TCP +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: kafka + namespace: messaging +spec: + serviceName: kafka + replicas: 3 + selector: + matchLabels: + app: kafka + template: + metadata: + labels: + app: kafka + spec: + containers: + - name: kafka + image: apache/kafka:4.0.0 + ports: + - containerPort: 9092 + - containerPort: 19092 + - containerPort: 9093 + env: + # Make HOSTNAME available to Kafka (Kubernetes will expand this) + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + + # Cluster settings + - name: CLUSTER_ID + value: "7sWhx1QdSqGGl3a57SSZXA" + - name: KAFKA_PROCESS_ROLES + value: "broker,controller" + + # Controller quorum definition – all 3 brokers are voters + - name: KAFKA_CONTROLLER_QUORUM_VOTERS + value: "0@kafka-0.kafka.messaging.svc.cluster.local:9093,1@kafka-1.kafka.messaging.svc.cluster.local:9093,2@kafka-2.kafka.messaging.svc.cluster.local:9093" + + # Define listeners + - name: KAFKA_LISTENERS + value: "INTERNAL://0.0.0.0:9092,EXTERNAL://0.0.0.0:19092,CONTROLLER://0.0.0.0:9093" + + # Advertised listeners (now correctly expands HOSTNAME) + - name: KAFKA_ADVERTISED_LISTENERS + value: "INTERNAL://$(HOSTNAME).kafka.messaging.svc.cluster.local:9092,EXTERNAL://$(HOSTNAME).kafka.messaging.svc.cluster.local:19092" + + # Listener protocol mappings + - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP + value: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT" + + - name: KAFKA_INTER_BROKER_LISTENER_NAME + value: "INTERNAL" + - name: KAFKA_CONTROLLER_LISTENER_NAMES + value: "CONTROLLER" + + # Replication settings + - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR + value: "3" + - name: KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR + value: "3" + - name: KAFKA_TRANSACTION_STATE_LOG_MIN_ISR + value: "2" + - name: KAFKA_MIN_INSYNC_REPLICAS + value: "2" + + # Node ID for KRaft mode + - name: KAFKA_NODE_ID + valueFrom: + fieldRef: + fieldPath: metadata.labels['apps.kubernetes.io/pod-index'] + + # Log directories + - name: KAFKA_LOG_DIRS + value: /var/lib/kafka/data + + volumeMounts: + - name: kafka-data + mountPath: /var/lib/kafka + + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: 1 + memory: 1Gi + volumeClaimTemplates: + - metadata: + name: kafka-data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path \ No newline at end of file diff --git a/k8s/messaging/schema-loader.yml b/k8s/messaging/schema-loader.yml new file mode 100644 index 0000000..e9a4226 --- /dev/null +++ b/k8s/messaging/schema-loader.yml @@ -0,0 +1,54 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: schema-loader + namespace: messaging +spec: + template: + metadata: + labels: + app: schema-loader + spec: + restartPolicy: OnFailure + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning repository..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying schema files and script..." + mkdir -p /config /schemas + cp /repo/kafka/script.sh /config/ + cp -r /repo/kafka/schemas/* /schemas/ + chmod +x /config/script.sh + echo "Config and schemas ready." + volumeMounts: + - name: config-volume + mountPath: /config + - name: schemas-volume + mountPath: /schemas + containers: + - name: schema-loader + image: alpine:3.20 + command: ["/bin/sh", "-c"] + args: ["apk add --no-cache curl jq && /config/script.sh"] + volumeMounts: + - name: config-volume + mountPath: /config + - name: schemas-volume + mountPath: /schemas + resources: + requests: + cpu: 100m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi + volumes: + - name: config-volume + emptyDir: {} + - name: schemas-volume + emptyDir: {} \ No newline at end of file diff --git a/k8s/messaging/schema-registry.yml b/k8s/messaging/schema-registry.yml new file mode 100644 index 0000000..fe20998 --- /dev/null +++ b/k8s/messaging/schema-registry.yml @@ -0,0 +1,58 @@ +apiVersion: v1 +kind: Service +metadata: + name: schema-registry + namespace: messaging +spec: + ports: + - name: http + port: 8081 + protocol: TCP + selector: + app: schema-registry +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: schema-registry + namespace: messaging +spec: + replicas: 1 + selector: + matchLabels: + app: schema-registry + template: + metadata: + labels: + app: schema-registry + spec: + enableServiceLinks: false # Required for Kafka to work + containers: + - name: schema-registry + image: confluentinc/cp-schema-registry:8.1.0 + ports: + - containerPort: 8081 + env: + - name: SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS + value: "kafka.messaging.svc.cluster.local:9092" + - name: SCHEMA_REGISTRY_LISTENERS + value: "http://0.0.0.0:8081" + - name: SCHEMA_REGISTRY_HOST_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: SCHEMA_REGISTRY_LOG4J_ROOT_LOGLEVEL + value: "INFO" + - name: SCHEMA_REGISTRY_KAFKASTORE_TOPIC_REPLICATION_FACTOR + value: "1" + - name: SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL + value: "PLAINTEXT" + - name: SCHEMA_REGISTRY_SCHEMA_COMPATIBILITY_LEVEL + value: "BACKWARD" + resources: + requests: + cpu: 250m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi \ No newline at end of file diff --git a/k8s/monitoring/grafana.yml b/k8s/monitoring/grafana.yml new file mode 100644 index 0000000..05474b2 --- /dev/null +++ b/k8s/monitoring/grafana.yml @@ -0,0 +1,73 @@ +apiVersion: v1 +kind: Service +metadata: + name: grafana + namespace: monitoring +spec: + type: ClusterIP + selector: + app: grafana + ports: + - port: 3000 + targetPort: 3000 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: grafana + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: grafana + template: + metadata: + labels: + app: grafana + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying grafana config files..." + mkdir -p /config + cp -r /repo/monitoring/grafana/provisioning/* /config/ + echo "Config ready." + volumeMounts: + - name: grafana-config + mountPath: /config + containers: + - name: grafana + image: grafana/grafana:12.2.0 + env: + - name: GF_SECURITY_ADMIN_USER + value: admin + - name: GF_SECURITY_ADMIN_PASSWORD + value: admin + - name: GF_USERS_ALLOW_SIGN_UP + value: "false" + - name: GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS + value: "grafana-exploretraces-app,grafana-metricsdrilldown-app,grafana-lokiexplore-app" + ports: + - containerPort: 3000 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: grafana-config + mountPath: /etc/grafana/provisioning + readOnly: true + volumes: + - name: grafana-config + emptyDir: { } \ No newline at end of file diff --git a/k8s/monitoring/jaeger.yml b/k8s/monitoring/jaeger.yml new file mode 100644 index 0000000..918bbe2 --- /dev/null +++ b/k8s/monitoring/jaeger.yml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: Service +metadata: + name: jaeger + namespace: monitoring +spec: + type: ClusterIP + selector: + app: jaeger + ports: + - port: 16686 + targetPort: 16686 + name: jaeger-ui + protocol: TCP + - port: 14268 + targetPort: 14268 + name: jaeger-http + protocol: TCP + - port: 14250 + targetPort: 14250 + name: jaeger-grpc + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jaeger + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: jaeger + template: + metadata: + labels: + app: jaeger + spec: + containers: + - name: jaeger + image: jaegertracing/all-in-one:1.65.0 + ports: + - containerPort: 16686 + - containerPort: 14268 + - containerPort: 14250 + env: + - name: COLLECTOR_OTLP_ENABLED + value: "true" + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi diff --git a/k8s/monitoring/loki.yml b/k8s/monitoring/loki.yml new file mode 100644 index 0000000..69bec9f --- /dev/null +++ b/k8s/monitoring/loki.yml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: Service +metadata: + name: loki + namespace: monitoring +spec: + type: ClusterIP + selector: + app: loki + ports: + - port: 3100 + targetPort: 3100 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: loki + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: loki + template: + metadata: + labels: + app: loki + spec: + containers: + - name: loki + image: grafana/loki:3.3.0 + ports: + - containerPort: 3100 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi diff --git a/k8s/monitoring/mimir.yml b/k8s/monitoring/mimir.yml new file mode 100644 index 0000000..d486c70 --- /dev/null +++ b/k8s/monitoring/mimir.yml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Service +metadata: + name: mimir + namespace: monitoring +spec: + type: ClusterIP + selector: + app: mimir + ports: + - port: 9009 + targetPort: 9009 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mimir + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: mimir + template: + metadata: + labels: + app: mimir + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying mimir config files..." + mkdir -p /config + cp /repo/monitoring/mimir/config/mimir.yml /config/config.yaml + echo "Config ready." + volumeMounts: + - name: mimir-config + mountPath: /config + containers: + - name: mimir + image: grafana/mimir:2.17.1 + args: ["-config.file=/etc/mimir/config.yaml"] + ports: + - containerPort: 9009 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: mimir-config + mountPath: /etc/mimir + readOnly: true + volumes: + - name: mimir-config + emptyDir: { } \ No newline at end of file diff --git a/k8s/monitoring/otel.yml b/k8s/monitoring/otel.yml new file mode 100644 index 0000000..cebc8e3 --- /dev/null +++ b/k8s/monitoring/otel.yml @@ -0,0 +1,81 @@ +apiVersion: v1 +kind: Service +metadata: + name: otel-collector + namespace: monitoring +spec: + type: ClusterIP + selector: + app: otel-collector + ports: + - port: 4317 + targetPort: 4317 + name: otlp-grpc + protocol: TCP + - port: 4318 + targetPort: 4318 + name: otlp-http + protocol: TCP + - port: 9464 + targetPort: 9464 + name: prometheus-metrics + protocol: TCP + - port: 8888 + targetPort: 8888 + name: service-metrics + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: otel-collector + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: otel-collector + template: + metadata: + labels: + app: otel-collector + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying otel config files..." + mkdir -p /config + cp /repo/monitoring/otel/otel.yml /config/config.yaml + echo "Config ready." + volumeMounts: + - name: otel-collector-config + mountPath: /config + containers: + - name: otel-collector + image: otel/opentelemetry-collector:0.136.0 + args: ["--config=/etc/otel/config.yaml"] + ports: + - containerPort: 4317 + - containerPort: 4318 + - containerPort: 8888 + - containerPort: 9464 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: otel-collector-config + mountPath: /etc/otel + readOnly: true + volumes: + - name: otel-collector-config + emptyDir: { } \ No newline at end of file diff --git a/k8s/monitoring/promethus.yml b/k8s/monitoring/promethus.yml new file mode 100644 index 0000000..5ce465f --- /dev/null +++ b/k8s/monitoring/promethus.yml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Service +metadata: + name: prometheus + namespace: monitoring +spec: + type: ClusterIP + selector: + app: prometheus + ports: + - port: 9090 + targetPort: 9090 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prometheus + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + spec: + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning configuration..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying prometheus config files..." + mkdir -p /config + cp /repo/monitoring/prometheus/prometheus.yml /config/config.yaml + echo "Config ready." + volumeMounts: + - name: prometheus-config + mountPath: /config + containers: + - name: prometheus + image: prom/prometheus:v3.6.0 + args: ["--config.file=/etc/prometheus/config.yaml"] + ports: + - containerPort: 9090 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: prometheus-config + mountPath: /etc/prometheus + readOnly: true + volumes: + - name: prometheus-config + emptyDir: { } \ No newline at end of file diff --git a/k8s/router/router-config-job.yml b/k8s/router/router-config-job.yml new file mode 100644 index 0000000..f40cd6c --- /dev/null +++ b/k8s/router/router-config-job.yml @@ -0,0 +1,53 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: router-config-fetch + namespace: aviation +spec: + backoffLimit: 0 + template: + spec: + restartPolicy: Never + containers: + - name: config-fetch + image: alpine:3.19 + workingDir: /app + command: + - sh + - -c + - | + set -e + echo "Installing dependencies..." + apk add --no-cache git >/dev/null + echo "Cloning repository..." + git clone https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying router configuration..." + cp /repo/router.yml /config/router.yml + echo "Router configuration fetched successfully." + ls -la /config/ + volumeMounts: + - name: router-config-volume + mountPath: /config + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 256Mi + volumes: + - name: router-config-volume + persistentVolumeClaim: + claimName: router-config-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: router-config-pvc + namespace: aviation +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Mi \ No newline at end of file diff --git a/k8s/router/service.yml b/k8s/router/service.yml new file mode 100644 index 0000000..0f29bc3 --- /dev/null +++ b/k8s/router/service.yml @@ -0,0 +1,83 @@ +apiVersion: v1 +kind: Service +metadata: + name: router-service + namespace: aviation +spec: + type: ClusterIP + selector: + app: router-service + ports: + - port: 4000 + targetPort: 4000 + name: http + protocol: TCP + - port: 8088 + targetPort: 8088 + name: health + protocol: TCP + - port: 8089 + targetPort: 8089 + name: metrics + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: router-service + namespace: aviation +spec: + replicas: 1 + selector: + matchLabels: + app: router-service + template: + metadata: + labels: + app: router-service + spec: + containers: + - name: apollo-router + image: ghcr.io/apollographql/router:v2.6.2 + args: + - "--supergraph" + - /etc/apollo/supergraph.graphql + - "--config" + - /etc/router/router.yml + - "--hot-reload" + ports: + - containerPort: 4000 + - containerPort: 8088 + - containerPort: 8089 + env: + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://otel-collector.monitoring.svc.cluster.local:4317 + - name: OTEL_METRICS_EXPORTER_ENDPOINT + value: http://otel-collector.monitoring.svc.cluster.local:4317 + readinessProbe: + httpGet: + path: /health + port: 8088 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: shared-schema + mountPath: /etc/apollo + readOnly: true + - name: router-config + mountPath: /etc/router + readOnly: true + volumes: + - name: shared-schema + persistentVolumeClaim: + claimName: supergraph-schema-pvc + - name: router-config + persistentVolumeClaim: + claimName: router-config-pvc \ No newline at end of file diff --git a/k8s/router/supergraph-job.yml b/k8s/router/supergraph-job.yml new file mode 100644 index 0000000..5e1f4ca --- /dev/null +++ b/k8s/router/supergraph-job.yml @@ -0,0 +1,83 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: supergraph-config + namespace: aviation +data: + supergraph.yml: | + federation_version: =2.3.2 + subgraphs: + flights: + routing_url: http://flights-service.flights.svc.cluster.local:8081/graphql + schema: + subgraph_url: http://flights-service.flights.svc.cluster.local:8081/graphql + aircraft: + routing_url: http://aircraft-service.aircraft.svc.cluster.local:8080/graphql + schema: + subgraph_url: http://aircraft-service.aircraft.svc.cluster.local:8080/graphql + search: + routing_url: http://search-service.search.svc.cluster.local:8082/graphql + schema: + subgraph_url: http://search-service.search.svc.cluster.local:8082/graphql +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: supergraph-composer + namespace: aviation +spec: + template: + spec: + restartPolicy: OnFailure + containers: + - name: rover + image: ubuntu:22.04 + command: + - bash + - -c + - | + echo "Installing Rover..." + apt-get update && apt-get install -y curl + curl -sSL https://rover.apollo.dev/nix/latest | sh + export PATH="/root/.rover/bin:$PATH" + + echo "Composing supergraph schema..." + rover supergraph compose \ + --config /config/supergraph.yml \ + --output /shared/supergraph.graphql \ + --elv2-license accept + + echo "Supergraph composed successfully!" + ls -la /shared/ + volumeMounts: + - name: supergraph-config + mountPath: /config + readOnly: true + - name: shared-schema + mountPath: /shared + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 200m + memory: 256Mi + volumes: + - name: supergraph-config + configMap: + name: supergraph-config + - name: shared-schema + persistentVolumeClaim: + claimName: supergraph-schema-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: supergraph-schema-pvc + namespace: aviation +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/k8s/search/dashboards.yml b/k8s/search/dashboards.yml new file mode 100644 index 0000000..c0203bf --- /dev/null +++ b/k8s/search/dashboards.yml @@ -0,0 +1,67 @@ +apiVersion: v1 +kind: Service +metadata: + name: opensearch-dashboards + namespace: search +spec: + selector: + app: opensearch-dashboards + ports: + - name: http + port: 5601 + targetPort: 5601 + protocol: TCP + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: opensearch-dashboards + namespace: search +spec: + replicas: 1 + selector: + matchLabels: + app: opensearch-dashboards + template: + metadata: + labels: + app: opensearch-dashboards + spec: + containers: + - name: opensearch-dashboards + image: opensearchproject/opensearch-dashboards:2.11.1 + ports: + - containerPort: 5601 + name: http + env: + - name: OPENSEARCH_HOSTS + value: '["http://opensearch.search.svc.cluster.local:9200"]' + - name: OPENSEARCH_SSL_VERIFICATIONMODE + value: "none" + - name: OPENSEARCH_SECURITY_ENABLED + value: "false" + - name: DISABLE_SECURITY_DASHBOARDS_PLUGIN + value: "true" + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 500m + memory: 1Gi + readinessProbe: + httpGet: + path: /api/status + port: 5601 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + livenessProbe: + httpGet: + path: /api/status + port: 5601 + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 10 +--- \ No newline at end of file diff --git a/k8s/search/init-job.yml b/k8s/search/init-job.yml new file mode 100644 index 0000000..8f68ba4 --- /dev/null +++ b/k8s/search/init-job.yml @@ -0,0 +1,63 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: opensearch-init + namespace: search +spec: + template: + metadata: + labels: + app: opensearch-init + spec: + restartPolicy: OnFailure + initContainers: + - name: fetch-config + image: alpine/git:2.49.1 + command: + - sh + - -c + - | + echo "Cloning repository..." + git clone --branch main https://github.com/edinstance/distributed-aviation-system.git /repo + echo "Copying init files and script..." + mkdir -p /config /init/indexes /init/visualizations /init/searches /init/dashboards + cp /repo/services/search/init/setup-dashboard.sh /config/ + cp -r /repo/services/search/init/indexes/* /init/indexes/ + cp -r /repo/services/search/init/visualizations/* /init/visualizations/ + cp -r /repo/services/search/init/searches/* /init/searches/ + cp -r /repo/services/search/init/dashboards/* /init/dashboards/ + chmod +x /config/setup-dashboard.sh + echo "Init files ready." + volumeMounts: + - name: config-volume + mountPath: /config + - name: init-volume + mountPath: /init + containers: + - name: opensearch-init + image: alpine:3.20 + command: ["/bin/sh", "-c"] + args: + - | + apk add --no-cache curl jq bash + # Update URLs for Kubernetes services + sed -i 's|opensearch-node-1:9200|opensearch.search.svc.cluster.local:9200|g' /config/setup-dashboard.sh + sed -i 's|opensearch-dashboards:5601|opensearch-dashboards.search.svc.cluster.local:5601|g' /config/setup-dashboard.sh + /config/setup-dashboard.sh + volumeMounts: + - name: config-volume + mountPath: /config + - name: init-volume + mountPath: /init + resources: + requests: + cpu: 100m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi + volumes: + - name: config-volume + emptyDir: {} + - name: init-volume + emptyDir: {} \ No newline at end of file diff --git a/k8s/search/opensearch.yml b/k8s/search/opensearch.yml new file mode 100644 index 0000000..1d90b2e --- /dev/null +++ b/k8s/search/opensearch.yml @@ -0,0 +1,98 @@ +apiVersion: v1 +kind: Service +metadata: + name: opensearch + namespace: search +spec: + clusterIP: None + selector: + app: opensearch + ports: + - name: http + port: 9200 + protocol: TCP + - name: transport + port: 9300 + protocol: TCP +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: opensearch + namespace: search +spec: + serviceName: opensearch + replicas: 2 + selector: + matchLabels: + app: opensearch + template: + metadata: + labels: + app: opensearch + spec: + containers: + - name: opensearch + image: opensearchproject/opensearch:2.11.1 + ports: + - containerPort: 9200 + name: http + - containerPort: 9300 + name: transport + env: + - name: OPENSEARCH_JAVA_OPTS + value: "-Xms512m -Xmx512m" + - name: bootstrap.memory_lock + value: "true" + - name: discovery.seed_hosts + value: "opensearch-0.opensearch.search.svc.cluster.local,opensearch-1.opensearch.search.svc.cluster.local" + - name: cluster.initial_cluster_manager_nodes + value: "opensearch-0" + - name: cluster.name + value: "aviation-search-cluster" + - name: node.name + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: network.host + value: "0.0.0.0" + - name: DISABLE_SECURITY_PLUGIN + value: "true" + - name: DISABLE_INSTALL_DEMO_CONFIG + value: "true" + volumeMounts: + - name: opensearch-data + mountPath: /usr/share/opensearch/data + resources: + requests: + cpu: 500m + memory: 1Gi + limits: + cpu: 1 + memory: 2Gi + readinessProbe: + httpGet: + path: /_cluster/health + port: 9200 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + livenessProbe: + httpGet: + path: /_cluster/health + port: 9200 + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 10 + securityContext: + fsGroup: 1000 + volumeClaimTemplates: + - metadata: + name: opensearch-data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + storageClassName: local-path \ No newline at end of file diff --git a/k8s/search/service.yml b/k8s/search/service.yml new file mode 100644 index 0000000..fddef9f --- /dev/null +++ b/k8s/search/service.yml @@ -0,0 +1,82 @@ +apiVersion: v1 +kind: Service +metadata: + name: search-service + namespace: search +spec: + type: ClusterIP + ports: + - port: 8082 + targetPort: 8082 + protocol: TCP + selector: + app: search-service +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: search-service + namespace: search +spec: + replicas: 1 + selector: + matchLabels: + app: search-service + template: + metadata: + labels: + app: search-service + spec: + containers: + - name: search-service + image: ghcr.io/edinstance/distributed-aviation-system-services/search:dev + ports: + - containerPort: 8082 + env: + - name: ENVIRONMENT + value: "prod" + - name: PORT + value: "8082" + - name: OPENSEARCH_HOST + value: "opensearch.search.svc.cluster.local" + - name: OPENSEARCH_PORT + value: "9200" + - name: OPENSEARCH_SCHEME + value: "http" + - name: OPENSEARCH_USERNAME + value: "admin" + - name: OPENSEARCH_PASSWORD + value: "admin" + - name: KAFKA_BOOTSTRAP_SERVERS + value: "kafka.messaging.svc.cluster.local:9092" + - name: SCHEMA_REGISTRY_URL + value: "http://schema-registry.messaging.svc.cluster.local:8081" + - name: OTEL_SERVICE_NAME + value: "search-service" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://otel-collector.monitoring:4317" + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: "grpc" + - name: OTEL_TRACES_EXPORTER + value: "otlp" + - name: OTEL_METRICS_EXPORTER + value: "otlp" + - name: OTEL_LOGS_EXPORTER + value: "otlp" + - name: OTEL_METRIC_EXPORT_INTERVAL + value: "5000" + - name: OTEL_BSP_SCHEDULE_DELAY + value: "5000" + readinessProbe: + httpGet: + path: /details/health + port: 8082 + initialDelaySeconds: 10 + periodSeconds: 10 + resources: + requests: + cpu: 500m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi \ No newline at end of file diff --git a/load-tests/src/config.ts b/load-tests/src/config.ts index dc3023a..9d11741 100644 --- a/load-tests/src/config.ts +++ b/load-tests/src/config.ts @@ -1,7 +1,7 @@ export const CONFIG = { - flightServiceUrl: __ENV.FLIGHT_URL || "http://localhost:8081/graphql", - aircraftServiceUrl: __ENV.AIRCRAFT_URL || "http://localhost:8080/graphql", - routerUrl: __ENV.ROUTER_URL || "http://localhost:4000", - gatewayUrl: __ENV.GATEWAY_URL || "http://localhost:4001", - authServiceUrl: __ENV.AUTHENTICATION_URL || "http://localhost:8000", + flightServiceUrl: __ENV.FLIGHT_URL || "http://api.aviation.local/flights/graphql", + aircraftServiceUrl: __ENV.AIRCRAFT_URL || "http://api.aviation.local/aircraft/graphql", + routerUrl: __ENV.ROUTER_URL || "http://api.aviation.local/router", + gatewayUrl: __ENV.GATEWAY_URL || "http://api.aviation.local/gateway", + authServiceUrl: __ENV.AUTHENTICATION_URL || "http://api.aviation.local/auth", }; diff --git a/load-tests/src/helpers/auth_headers.ts b/load-tests/src/helpers/auth_headers.ts new file mode 100644 index 0000000..d9a14c0 --- /dev/null +++ b/load-tests/src/helpers/auth_headers.ts @@ -0,0 +1,29 @@ +import { AuthContext } from "../types/auth_context"; + +/** + * Builds authentication headers for GraphQL requests + * @param accessToken - JWT token (for gateway requests) + * @param authContext - Auth context (for direct router/service requests) + * @param useDirectHeaders - Whether to include direct headers (x-user-sub, x-org-id, x-org-name) + */ +export function buildAuthHeaders( + accessToken?: string, + authContext?: AuthContext, + useDirectHeaders: boolean = true +): Record { + const headers: Record = {}; + + // Add JWT token for gateway requests + if (accessToken) { + headers["Authorization"] = `Bearer ${accessToken}`; + } + + // Add direct headers for router/service requests (when JWT isn't being processed by gateway) + if (useDirectHeaders && authContext) { + headers["x-org-id"] = authContext.organization.id; + headers["x-user-sub"] = authContext.admin.id; + headers["x-org-name"] = authContext.organization.name; + } + + return headers; +} \ No newline at end of file diff --git a/load-tests/src/tests/shells/aircraft.ts b/load-tests/src/tests/shells/aircraft.ts index de8074a..192a797 100644 --- a/load-tests/src/tests/shells/aircraft.ts +++ b/load-tests/src/tests/shells/aircraft.ts @@ -11,17 +11,21 @@ import { import { uuidv4 } from "https://jslib.k6.io/k6-utils/1.4.0/index.js"; import { check } from "k6"; import { AuthContext } from "src/types/auth_context"; +import { buildAuthHeaders } from "../../helpers/auth_headers"; export function runAircraftScenario( url: string, accessToken?: string, authContext?: AuthContext, ) { + // Determine if we should use direct headers (for router) vs JWT (for gateway) + const useDirectHeaders = !url.includes("/gateway"); + graphql( url, GetAircraftDocument, { id: uuidv4() }, - accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); const createAircraftRes = graphql< @@ -40,15 +44,7 @@ export function runAircraftScenario( yearOfManufacture: 2020, }, }, - { - ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}), - ...(authContext - ? { - "x-org-id": authContext.organization.id, - "x-user-sub": authContext.admin.id, - } - : {}), - }, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); check(createAircraftRes, { @@ -62,7 +58,7 @@ export function runAircraftScenario( url, GetAircraftDocument, { id: aircraftId }, - accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); } diff --git a/load-tests/src/tests/shells/flights.ts b/load-tests/src/tests/shells/flights.ts index 7b530a3..3b3a389 100644 --- a/load-tests/src/tests/shells/flights.ts +++ b/load-tests/src/tests/shells/flights.ts @@ -10,6 +10,7 @@ import { import { uuidv4 } from "https://jslib.k6.io/k6-utils/1.4.0/index.js"; import { check } from "k6"; import { AuthContext } from "src/types/auth_context"; +import { buildAuthHeaders } from "../../helpers/auth_headers"; function randomFlightNumber(): string { const airlines = ["BA", "UA", "LH", "AF"]; @@ -23,11 +24,14 @@ export function runFlightScenario( accessToken?: string, authContext?: AuthContext, ) { + // Determine if we should use direct headers (for router) vs JWT (for gateway) + const useDirectHeaders = !url.includes("/gateway"); + graphql( url, GetFlightByIdDocument, { id: uuidv4() }, - accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); const createRes = graphql< @@ -44,15 +48,7 @@ export function runFlightScenario( departureTime: new Date().toISOString(), arrivalTime: new Date(Date.now() + 3600 * 1000).toISOString(), }, - { - ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}), - ...(authContext - ? { - "x-org-id": authContext.organization.id, - "x-user-sub": authContext.admin.id, - } - : {}), - }, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); check(createRes, { @@ -66,7 +62,7 @@ export function runFlightScenario( url, GetFlightByIdDocument, { id: flightId }, - accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, + buildAuthHeaders(accessToken, authContext, useDirectHeaders), ); } diff --git a/monitoring/docker-compose.yml b/monitoring/docker-compose.yml index d2fabbf..98b8d99 100644 --- a/monitoring/docker-compose.yml +++ b/monitoring/docker-compose.yml @@ -75,7 +75,6 @@ services: restart: unless-stopped ports: - "3100:3100" - command: -config.file=/etc/loki/local-config.yaml volumes: - loki_data:/loki networks: diff --git a/router.yml b/router.yml index b5f1963..a0212a1 100644 --- a/router.yml +++ b/router.yml @@ -33,7 +33,7 @@ telemetry: service_name: "graphql-router" otlp: enabled: true - endpoint: http://otel-collector:4317 + endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://otel-collector:4317} protocol: grpc metrics: common: @@ -41,7 +41,7 @@ telemetry: service_name: "graphql-router" otlp: enabled: true - endpoint: http://otel-collector:4317 + endpoint: ${OTEL_METRICS_EXPORTER_ENDPOINT:http://otel-collector:4317} protocol: grpc logging: stdout: diff --git a/services/authentication/authentication/settings.py b/services/authentication/authentication/settings.py index 1a5ff30..f105559 100644 --- a/services/authentication/authentication/settings.py +++ b/services/authentication/authentication/settings.py @@ -209,6 +209,20 @@ def load_verifying_key(): default="http://localhost:3000,http://127.0.0.1:3000", cast=lambda v: [s.strip() for s in v.split(",")], ) +CORS_ALLOW_CREDENTIALS = config("CORS_ALLOW_CREDENTIALS", default=True, cast=bool) +CORS_ALLOWED_HEADERS = config( + "CORS_ALLOWED_HEADERS", + default="accept,accept-encoding,authorization,content-type,dnt,origin,user-agent,x-csrftoken,x-requested-with,x-tenant-id", + cast=lambda v: [s.strip() for s in v.split(",")], +) +CORS_ALLOW_METHODS = [ + "DELETE", + "GET", + "OPTIONS", + "PATCH", + "POST", + "PUT", +] # Logging Configuration LOG_LEVEL = config("LOG_LEVEL", default="INFO") diff --git a/services/authentication/docker-compose.yml b/services/authentication/docker-compose.yml index b715f4d..b51ba79 100644 --- a/services/authentication/docker-compose.yml +++ b/services/authentication/docker-compose.yml @@ -7,14 +7,16 @@ services: environment: SECRET_KEY: ${SECRET_KEY:-insecure-key} DEBUG: ${DEBUG:-False} - ALLOWED_HOSTS: ${ALLOWED_HOSTS:-localhost,127.0.0.1,authentication-service} + ALLOWED_HOSTS: ${ALLOWED_HOSTS:-localhost,127.0.0.1,authentication-service,host.docker.internal} DATABASE_NAME: ${DATABASE_NAME:-authentication} DATABASE_USER: ${DATABASE_USER:-postgres} DATABASE_PASSWORD: ${DATABASE_PASSWORD:-postgres} DATABASE_HOST: ${DATABASE_HOST:-authentication-database} DATABASE_PORT: ${DATABASE_PORT:-5432} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-http://localhost:3000,http://127.0.0.1:3000,http://gateway-service:4001} - CORS_ALLOW_ALL_ORIGINS: ${CORS_ALLOW_ALL_ORIGINS:-True} + CORS_ALLOW_ALL_ORIGINS: ${CORS_ALLOW_ALL_ORIGINS:-False} + CORS_ALLOW_CREDENTIALS: ${CORS_ALLOW_CREDENTIALS:-True} + CORS_ALLOWED_HEADERS: ${CORS_ALLOWED_HEADERS:-accept,accept-encoding,authorization,content-type,dnt,origin,user-agent,x-csrftoken,x-requested-with,x-tenant-id} LOG_LEVEL: ${LOG_LEVEL:-INFO} ENVIRONMENT: ${ENVIRONMENT:-dev} OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-authentication-service} diff --git a/services/gateway/src/handling/health_handler.rs b/services/gateway/src/handling/health_handler.rs new file mode 100644 index 0000000..f0d4670 --- /dev/null +++ b/services/gateway/src/handling/health_handler.rs @@ -0,0 +1,6 @@ +use axum::Json; +use serde_json::json; + +pub async fn health_handler() -> impl axum::response::IntoResponse { + Json(json!({ "status": "UP" })) +} \ No newline at end of file diff --git a/services/gateway/src/handling/mod.rs b/services/gateway/src/handling/mod.rs index ce22eec..2908ab3 100644 --- a/services/gateway/src/handling/mod.rs +++ b/services/gateway/src/handling/mod.rs @@ -1,3 +1,5 @@ mod route_handler; +mod health_handler; -pub use route_handler::route_handler; \ No newline at end of file +pub use route_handler::route_handler; +pub use health_handler::health_handler; \ No newline at end of file diff --git a/services/gateway/src/main.rs b/services/gateway/src/main.rs index 287bb54..cd6d35e 100644 --- a/services/gateway/src/main.rs +++ b/services/gateway/src/main.rs @@ -5,7 +5,7 @@ mod requests; mod verify; use crate::config::Config; -use crate::handling::route_handler; +use crate::handling::{route_handler, health_handler}; use crate::observability::{ObservabilityConfig, init_observability, shutdown_observability}; use crate::verify::JwksCache; use axum::{Router, routing::any}; @@ -38,34 +38,21 @@ async fn main() { let client = Arc::new( Client::builder() - .timeout(std::time::Duration::from_secs(30)) + .timeout(Duration::from_secs(30)) .build() .expect("Failed to create HTTP client"), ); let app = Router::new() - .route( - "/", - any({ - let router_url = router_url.clone(); - let client = client.clone(); - let jwks_cache = jwks_cache.clone(); - move |req| { - route_handler(req, router_url.clone(), client.clone(), jwks_cache.clone()) - } - }), - ) - .route( - "/{*wildcard}", - any({ - let router_url = router_url.clone(); - let client = client.clone(); - let jwks_cache = jwks_cache.clone(); - move |req| { - route_handler(req, router_url.clone(), client.clone(), jwks_cache.clone()) - } - }), - ); + .route("/health", any(health_handler)) + .fallback({ + let router_url = router_url.clone(); + let client = client.clone(); + let jwks_cache = jwks_cache.clone(); + move |req| { + route_handler(req, router_url.clone(), client.clone(), jwks_cache.clone()) + } + }); let addr = SocketAddr::from(([0, 0, 0, 0], config.port)); info!(address = %addr, "Aviation gateway service started"); diff --git a/services/search/src/main/java/search/config/OpenSearchConfig.java b/services/search/src/main/java/search/config/OpenSearchConfig.java index ac44222..b3f2e0c 100644 --- a/services/search/src/main/java/search/config/OpenSearchConfig.java +++ b/services/search/src/main/java/search/config/OpenSearchConfig.java @@ -1,4 +1,4 @@ -package aviation.search.config; +package search.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; diff --git a/services/search/src/main/java/search/config/SearchLogger.java b/services/search/src/main/java/search/config/SearchLogger.java index 28a67ba..103f61c 100644 --- a/services/search/src/main/java/search/config/SearchLogger.java +++ b/services/search/src/main/java/search/config/SearchLogger.java @@ -1,4 +1,4 @@ -package aviation.search.config; +package search.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/services/search/src/main/java/search/config/metrics/graphql/GraphqlMetricsHelpers.java b/services/search/src/main/java/search/config/metrics/graphql/GraphqlMetricsHelpers.java index 045250c..ebe4839 100644 --- a/services/search/src/main/java/search/config/metrics/graphql/GraphqlMetricsHelpers.java +++ b/services/search/src/main/java/search/config/metrics/graphql/GraphqlMetricsHelpers.java @@ -1,4 +1,4 @@ -package aviation.search.config.metrics.graphql; +package search.config.metrics.graphql; import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters; import graphql.language.Definition; diff --git a/services/search/src/main/java/search/config/metrics/graphql/GraphqlMetricsInstrumentation.java b/services/search/src/main/java/search/config/metrics/graphql/GraphqlMetricsInstrumentation.java index 1444dfa..b5ced18 100644 --- a/services/search/src/main/java/search/config/metrics/graphql/GraphqlMetricsInstrumentation.java +++ b/services/search/src/main/java/search/config/metrics/graphql/GraphqlMetricsInstrumentation.java @@ -1,4 +1,4 @@ -package aviation.search.config.metrics.graphql; +package search.config.metrics.graphql; import graphql.ExecutionResult; import graphql.execution.DataFetcherResult; @@ -37,7 +37,7 @@ public class GraphqlMetricsInstrumentation implements Instrumentation { * A constructor for the instrumentation. */ public GraphqlMetricsInstrumentation() { - Meter meter = GlobalOpenTelemetry.getMeter("aviation.search.graphql"); + Meter meter = GlobalOpenTelemetry.getMeter("search.graphql"); this.graphqlRequests = meter.counterBuilder("search_graphql_requests_total") .setDescription("Total GraphQL operations") diff --git a/services/search/src/main/java/search/consumer/FlightEventConsumer.java b/services/search/src/main/java/search/consumer/FlightEventConsumer.java index c8d8133..f0aae70 100644 --- a/services/search/src/main/java/search/consumer/FlightEventConsumer.java +++ b/services/search/src/main/java/search/consumer/FlightEventConsumer.java @@ -1,8 +1,8 @@ -package aviation.search.consumer; +package search.consumer; -import aviation.search.config.SearchLogger; -import aviation.search.model.FlightDocument; -import aviation.search.service.FlightSearchService; +import search.config.SearchLogger; +import search.model.FlightDocument; +import search.service.FlightSearchService; import java.time.Instant; import lombok.RequiredArgsConstructor; import org.apache.avro.Schema; diff --git a/services/search/src/main/java/search/exceptions/DomainException.java b/services/search/src/main/java/search/exceptions/DomainException.java index d0cf911..bd0554e 100644 --- a/services/search/src/main/java/search/exceptions/DomainException.java +++ b/services/search/src/main/java/search/exceptions/DomainException.java @@ -1,4 +1,4 @@ -package aviation.search.exceptions; +package search.exceptions; import lombok.Getter; diff --git a/services/search/src/main/java/search/exceptions/ExceptionCategories.java b/services/search/src/main/java/search/exceptions/ExceptionCategories.java index a6956ea..2ce91bb 100644 --- a/services/search/src/main/java/search/exceptions/ExceptionCategories.java +++ b/services/search/src/main/java/search/exceptions/ExceptionCategories.java @@ -1,4 +1,4 @@ -package aviation.search.exceptions; +package search.exceptions; /** * An enum for managing exception categories. diff --git a/services/search/src/main/java/search/exceptions/GlobalGraphQlExceptionHandler.java b/services/search/src/main/java/search/exceptions/GlobalGraphQlExceptionHandler.java index 36aa776..a1ae453 100644 --- a/services/search/src/main/java/search/exceptions/GlobalGraphQlExceptionHandler.java +++ b/services/search/src/main/java/search/exceptions/GlobalGraphQlExceptionHandler.java @@ -1,4 +1,4 @@ -package aviation.search.exceptions; +package search.exceptions; import graphql.GraphQLError; import graphql.GraphqlErrorBuilder; diff --git a/services/search/src/main/java/search/exceptions/UnauthorizedException.java b/services/search/src/main/java/search/exceptions/UnauthorizedException.java index 23cc32f..5ad648a 100644 --- a/services/search/src/main/java/search/exceptions/UnauthorizedException.java +++ b/services/search/src/main/java/search/exceptions/UnauthorizedException.java @@ -1,4 +1,4 @@ -package aviation.search.exceptions; +package search.exceptions; /** * An exception for when a user is unauthorized. diff --git a/services/search/src/main/java/search/helpers/SearchHelpers.java b/services/search/src/main/java/search/helpers/SearchHelpers.java index 257b555..481f2a7 100644 --- a/services/search/src/main/java/search/helpers/SearchHelpers.java +++ b/services/search/src/main/java/search/helpers/SearchHelpers.java @@ -1,7 +1,7 @@ -package aviation.search.helpers; +package search.helpers; -import aviation.search.model.FlightDocument; -import aviation.search.service.FlightIndexService; +import search.model.FlightDocument; +import search.service.FlightIndexService; import java.io.IOException; import java.util.List; import java.util.stream.Collectors; diff --git a/services/search/src/main/java/search/model/FlightDocument.java b/services/search/src/main/java/search/model/FlightDocument.java index 2b31dc4..54d96f3 100644 --- a/services/search/src/main/java/search/model/FlightDocument.java +++ b/services/search/src/main/java/search/model/FlightDocument.java @@ -1,4 +1,4 @@ -package aviation.search.model; +package search.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/services/search/src/main/java/search/resolver/FlightSearchResolver.java b/services/search/src/main/java/search/resolver/FlightSearchResolver.java index 025a883..f044f39 100644 --- a/services/search/src/main/java/search/resolver/FlightSearchResolver.java +++ b/services/search/src/main/java/search/resolver/FlightSearchResolver.java @@ -1,7 +1,7 @@ -package aviation.search.resolver; +package search.resolver; -import aviation.search.model.FlightDocument; -import aviation.search.service.FlightSearchService; +import search.model.FlightDocument; +import search.service.FlightSearchService; import com.netflix.graphql.dgs.DgsComponent; import com.netflix.graphql.dgs.DgsQuery; import com.netflix.graphql.dgs.InputArgument; diff --git a/services/search/src/main/java/search/service/FlightIndexService.java b/services/search/src/main/java/search/service/FlightIndexService.java index 892920f..cb61adf 100644 --- a/services/search/src/main/java/search/service/FlightIndexService.java +++ b/services/search/src/main/java/search/service/FlightIndexService.java @@ -1,4 +1,4 @@ -package aviation.search.service; +package search.service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/services/search/src/main/java/search/service/FlightSearchService.java b/services/search/src/main/java/search/service/FlightSearchService.java index 0e520f2..1f3c5a6 100644 --- a/services/search/src/main/java/search/service/FlightSearchService.java +++ b/services/search/src/main/java/search/service/FlightSearchService.java @@ -1,8 +1,8 @@ -package aviation.search.service; +package search.service; -import aviation.search.config.SearchLogger; -import aviation.search.helpers.SearchHelpers; -import aviation.search.model.FlightDocument; +import search.config.SearchLogger; +import search.helpers.SearchHelpers; +import search.model.FlightDocument; import java.io.IOException; import java.util.List; import lombok.RequiredArgsConstructor; diff --git a/services/search/src/test/java/aviation/search/ApplicationTests.java b/services/search/src/test/java/search/ApplicationTests.java similarity index 91% rename from services/search/src/test/java/aviation/search/ApplicationTests.java rename to services/search/src/test/java/search/ApplicationTests.java index bbe923c..c2e7f30 100644 --- a/services/search/src/test/java/aviation/search/ApplicationTests.java +++ b/services/search/src/test/java/search/ApplicationTests.java @@ -1,4 +1,4 @@ -package aviation.search; +package search; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/supergraph.yml b/supergraph.yml index 8cd1187..c0bd031 100644 --- a/supergraph.yml +++ b/supergraph.yml @@ -1,14 +1,14 @@ federation_version: =2.3.2 subgraphs: flights: - routing_url: http://flights-service:8081/graphql + routing_url: ${FLIGHTS_SERVICE_URL:-http://flights-service:8081/graphql} schema: file: ./services/flights/internal/graphql/schema.graphqls aircraft: - routing_url: http://aircraft-service:8080/graphql + routing_url: ${AIRCRAFT_SERVICE_URL:-http://aircraft-service:8080/graphql} schema: file: ./services/aircraft/src/main/resources/schema/schema.graphqls search: - routing_url: http://search-service:8082/graphql + routing_url: ${SEARCH_SERVICE_URL:-http://search-service:8082/graphql} schema: file: ./services/search/src/main/resources/schema/schema.graphqls \ No newline at end of file