diff --git a/frontend/Dockerfile.kubernetes b/frontend/Dockerfile.kubernetes index e65ec07b..7fb24905 100644 --- a/frontend/Dockerfile.kubernetes +++ b/frontend/Dockerfile.kubernetes @@ -35,35 +35,8 @@ COPY nginx.conf /etc/nginx/conf.d/ # Copy built application from builder stage COPY --from=builder /app/dist /usr/share/nginx/html -# Create a script to substitute environment variables at runtime -COPY <<'EOF' /docker-entrypoint.d/30-substitute-env.sh -#!/bin/sh -set -e - -# Handle VITE_API_URL specially to preserve empty values -# If VITE_API_URL is unset, use default; if empty, preserve empty; otherwise use value -if [ -z "${VITE_API_URL+x}" ]; then - export VITE_API_URL="/api" -elif [ -z "$VITE_API_URL" ]; then - # If VITE_API_URL is explicitly set to empty string, use relative API path - export VITE_API_URL="/api" -fi - -# Default values for other environment variables -export VITE_APP_TITLE=${VITE_APP_TITLE:-"PanIA Dashboard"} -export VITE_APP_VERSION=${VITE_APP_VERSION:-"1.0.0"} - -# Create a runtime configuration file that can be loaded by the frontend -cat > /usr/share/nginx/html/runtime-config.js << EOL -window.__RUNTIME_CONFIG__ = { - VITE_API_URL: '${VITE_API_URL}', - VITE_APP_TITLE: '${VITE_APP_TITLE}', - VITE_APP_VERSION: '${VITE_APP_VERSION}' -}; -EOL - -echo "Runtime configuration created with API URL: ${VITE_API_URL}" -EOF +# Copy and setup environment substitution script +COPY substitute-env.sh /docker-entrypoint.d/30-substitute-env.sh # Make the script executable RUN chmod +x /docker-entrypoint.d/30-substitute-env.sh diff --git a/frontend/src/api/client/apiClient.ts b/frontend/src/api/client/apiClient.ts index 6e50f9b7..d99161b0 100644 --- a/frontend/src/api/client/apiClient.ts +++ b/frontend/src/api/client/apiClient.ts @@ -56,7 +56,7 @@ class ApiClient { config: AxiosRequestConfig; }> = []; - constructor(baseURL: string = getApiUrl() + '/api/v1') { + constructor(baseURL: string = getApiUrl() + '/v1') { this.baseURL = baseURL; this.client = axios.create({ diff --git a/frontend/substitute-env.sh b/frontend/substitute-env.sh new file mode 100644 index 00000000..1325c994 --- /dev/null +++ b/frontend/substitute-env.sh @@ -0,0 +1,26 @@ +#!/bin/sh +set -e + +# Handle VITE_API_URL specially to preserve empty values +# If VITE_API_URL is unset, use default; if empty, preserve empty; otherwise use value +if [ -z "${VITE_API_URL+x}" ]; then + export VITE_API_URL="/api" +elif [ -z "$VITE_API_URL" ]; then + # If VITE_API_URL is explicitly set to empty string, use relative API path + export VITE_API_URL="/api" +fi + +# Default values for other environment variables +export VITE_APP_TITLE=${VITE_APP_TITLE:-"PanIA Dashboard"} +export VITE_APP_VERSION=${VITE_APP_VERSION:-"1.0.0"} + +# Create a runtime configuration file that can be loaded by the frontend +cat > /usr/share/nginx/html/runtime-config.js << EOL +window.__RUNTIME_CONFIG__ = { + VITE_API_URL: '${VITE_API_URL}', + VITE_APP_TITLE: '${VITE_APP_TITLE}', + VITE_APP_VERSION: '${VITE_APP_VERSION}' +}; +EOL + +echo "Runtime configuration created with API URL: ${VITE_API_URL}" \ No newline at end of file diff --git a/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml b/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml index f3a7284a..51df6808 100644 --- a/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml +++ b/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml @@ -19,9 +19,33 @@ spec: app.kubernetes.io/name: alert-processor-service app.kubernetes.io/component: worker spec: + initContainers: + - name: wait-for-rabbitmq + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for RabbitMQ to be ready..." + until nc -z $RABBITMQ_HOST $RABBITMQ_PORT; do + echo "RabbitMQ not ready yet, waiting..." + sleep 2 + done + echo "RabbitMQ is ready!" + env: + - name: RABBITMQ_HOST + valueFrom: + configMapKeyRef: + name: bakery-config + key: RABBITMQ_HOST + - name: RABBITMQ_PORT + valueFrom: + configMapKeyRef: + name: bakery-config + key: RABBITMQ_PORT containers: - name: alert-processor-service - image: bakery/alert-processor:latest + image: bakery/alert-processor:f246381-dirty env: - name: ENVIRONMENT valueFrom: @@ -110,8 +134,28 @@ spec: key: NOTIFICATION_SERVICE_URL resources: requests: - memory: "256Mi" - cpu: "100m" + memory: "128Mi" + cpu: "50m" limits: - memory: "512Mi" - cpu: "500m" \ No newline at end of file + memory: "256Mi" + cpu: "200m" + readinessProbe: + exec: + command: + - python + - -c + - "import sys; sys.exit(0)" + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + livenessProbe: + exec: + command: + - python + - -c + - "import sys; sys.exit(0)" + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 \ No newline at end of file diff --git a/infrastructure/kubernetes/base/ingress.yaml b/infrastructure/kubernetes/base/ingress.yaml index ec4dfb67..1dd3faee 100644 --- a/infrastructure/kubernetes/base/ingress.yaml +++ b/infrastructure/kubernetes/base/ingress.yaml @@ -8,10 +8,8 @@ metadata: app.kubernetes.io/component: ingress annotations: # Kind-specific nginx ingress controller annotations - nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/force-ssl-redirect: "false" - nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/proxy-body-size: "10m" nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" nginx.ingress.kubernetes.io/proxy-send-timeout: "600" @@ -75,4 +73,21 @@ spec: service: name: prometheus-service port: - number: 9090 \ No newline at end of file + number: 9090 + - host: localhost + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: frontend-service + port: + number: 3000 + - path: /api + pathType: Prefix + backend: + service: + name: gateway-service + port: + number: 8000 \ No newline at end of file diff --git a/kind-config.yaml b/kind-config.yaml new file mode 100644 index 00000000..b6540047 --- /dev/null +++ b/kind-config.yaml @@ -0,0 +1,26 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +name: bakery-ia-local +nodes: +- role: control-plane + image: kindest/node:v1.29.0 + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + protocol: TCP + - containerPort: 443 + hostPort: 443 + protocol: TCP + - containerPort: 30080 + hostPort: 30080 + protocol: TCP +- role: worker + image: kindest/node:v1.29.0 +- role: worker + image: kindest/node:v1.29.0 \ No newline at end of file diff --git a/services/inventory/app/services/inventory_service.py b/services/inventory/app/services/inventory_service.py index d9956a16..0f7ccba5 100644 --- a/services/inventory/app/services/inventory_service.py +++ b/services/inventory/app/services/inventory_service.py @@ -760,9 +760,9 @@ class InventoryService: # Add business validation logic here if ingredient_data.reorder_point <= ingredient_data.low_stock_threshold: raise ValueError("Reorder point must be greater than low stock threshold") - - if ingredient_data.requires_freezing and ingredient_data.requires_refrigeration: - raise ValueError("Item cannot require both freezing and refrigeration") - + + # Storage requirements validation moved to stock level (not ingredient level) + # This is now handled in stock creation/update validation + # Add more validations as needed pass \ No newline at end of file diff --git a/shared/config/base.py b/shared/config/base.py index 4a72e871..8e628162 100644 --- a/shared/config/base.py +++ b/shared/config/base.py @@ -55,7 +55,7 @@ class BaseServiceSettings(BaseSettings): # REDIS CONFIGURATION # ================================================================ - REDIS_URL: str = os.getenv("REDIS_URL", "redis://redis:6379") + REDIS_URL: str = os.getenv("REDIS_URL", "redis://redis-service:6379") REDIS_DB: int = int(os.getenv("REDIS_DB", "0")) REDIS_MAX_CONNECTIONS: int = int(os.getenv("REDIS_MAX_CONNECTIONS", "50")) REDIS_RETRY_ON_TIMEOUT: bool = True diff --git a/skaffold.yaml b/skaffold.yaml new file mode 100644 index 00000000..d57d8cf1 --- /dev/null +++ b/skaffold.yaml @@ -0,0 +1,147 @@ +apiVersion: skaffold/v2beta28 +kind: Config +metadata: + name: bakery-ia-local + +build: + local: + push: false + artifacts: + # Gateway + - image: bakery/gateway + context: . + docker: + dockerfile: gateway/Dockerfile + + # Frontend + - image: bakery/dashboard + context: ./frontend + docker: + dockerfile: Dockerfile.kubernetes + + # Microservices + - image: bakery/auth-service + context: . + docker: + dockerfile: services/auth/Dockerfile + + - image: bakery/tenant-service + context: . + docker: + dockerfile: services/tenant/Dockerfile + + - image: bakery/training-service + context: . + docker: + dockerfile: services/training/Dockerfile + + - image: bakery/forecasting-service + context: . + docker: + dockerfile: services/forecasting/Dockerfile + + - image: bakery/sales-service + context: . + docker: + dockerfile: services/sales/Dockerfile + + - image: bakery/external-service + context: . + docker: + dockerfile: services/external/Dockerfile + + - image: bakery/notification-service + context: . + docker: + dockerfile: services/notification/Dockerfile + + - image: bakery/inventory-service + context: . + docker: + dockerfile: services/inventory/Dockerfile + + - image: bakery/recipes-service + context: . + docker: + dockerfile: services/recipes/Dockerfile + + - image: bakery/suppliers-service + context: . + docker: + dockerfile: services/suppliers/Dockerfile + + - image: bakery/pos-service + context: . + docker: + dockerfile: services/pos/Dockerfile + + - image: bakery/orders-service + context: . + docker: + dockerfile: services/orders/Dockerfile + + - image: bakery/production-service + context: . + docker: + dockerfile: services/production/Dockerfile + + - image: bakery/alert-processor + context: . + docker: + dockerfile: services/alert_processor/Dockerfile + +deploy: + kustomize: + paths: + - infrastructure/kubernetes/overlays/dev + +portForward: + - resourceType: service + resourceName: frontend-service + namespace: bakery-ia + port: 3000 + localPort: 3000 + - resourceType: service + resourceName: gateway-service + namespace: bakery-ia + port: 8000 + localPort: 8000 + +profiles: + - name: dev + build: + local: + push: false + tagPolicy: + gitCommit: {} + deploy: + kustomize: + paths: + - infrastructure/kubernetes/overlays/dev + + - name: debug + build: + local: + push: false + tagPolicy: + sha256: {} + deploy: + kustomize: + paths: + - infrastructure/kubernetes/overlays/dev + portForward: + - resourceType: service + resourceName: frontend-service + namespace: bakery-ia + port: 3000 + localPort: 3000 + - resourceType: service + resourceName: gateway-service + namespace: bakery-ia + port: 8000 + localPort: 8000 + - resourceType: service + resourceName: auth-service + namespace: bakery-ia + port: 8000 + localPort: 8001 \ No newline at end of file