diff --git a/.gitignore b/.gitignore index 8a748bd5..62204235 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,4 @@ __pycache__/ .vscode **/.vscode .azure +.terraform \ No newline at end of file diff --git a/README.md b/README.md index 05497cc4..0376a980 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,12 @@ git clone https://github.com/Azure-Samples/aks-store-demo.git cd aks-store-demo ``` -Configure your Azure OpenAI or OpenAI API keys in [`docker-compose.yml`](./docker-compose.yml) using the environment variables in the `aiservice` section: +Configure your Azure OpenAI or OpenAI API keys in [`docker-compose.yml`](./docker-compose.yml) using the environment variables in the `ai-service` section: ```yaml - aiservice: + ai-service: build: src/ai-service - container_name: 'aiservice' + container_name: 'ai-service' ... environment: - USE_AZURE_OPENAI=True # set to False if you are not using Azure OpenAI @@ -82,12 +82,12 @@ Configure your Azure OpenAI or OpenAI API keys in [`docker-compose.yml`](./docke ... ``` -Alternatively, if you do not have access to Azure OpenAI or OpenAI API keys, you can run the app without the `ai-service` by commenting out the `aiservice` section in [`docker-compose.yml`](./docker-compose.yml). For example: +Alternatively, if you do not have access to Azure OpenAI or OpenAI API keys, you can run the app without the `ai-service` by commenting out the `ai-service` section in [`docker-compose.yml`](./docker-compose.yml). For example: ```yaml -# aiservice: +# ai-service: # build: src/ai-service -# container_name: 'aiservice' +# container_name: 'ai-service' ... # networks: # - backend_services @@ -119,7 +119,29 @@ azd auth login az login ``` -Deploy the app with a single command. +The `makeline-service` supports both MongoDB and SQL API for accessing data in Azure CosmosDB. The default API is `MongoDB`, but you can use SQL API. To use the SQL API for Azure CosmosDB, you must provision the service using the `GlobalDocumentDB` account kind. You can set the Azure CosmosDB account kind by running the following command prior to running `azd up`: + +```bash +azd env set AZURE_COSMOSDB_ACCOUNT_KIND GlobalDocumentDB +``` + +By default, all application containers will be sourced from the [GitHub Container Registry](https://github.com/orgs/Azure-Samples/packages?repo_name=aks-store-demo). If you want to deploy apps from an Azure Container registry instead, you can do so by setting the following environment variable. + +```bash +azd env set DEPLOY_AZURE_CONTAINER_REGISTRY true +``` + +This will instruct the Terraform templates to provision an Azure Container Registry and enable authentication from the AKS cluster. + +When you choose to deploy containers from Azure Container Registry, you will have the option to import containers from GitHub Container Registry using the `az acr import` command or build containers from source using the `az acr build` command. + +To build containers from source, run the following command. + +```bash +azd env set BUILD_CONTAINERS true +``` + +Provision and deploy the app with a single command. ```bash azd up @@ -131,11 +153,6 @@ Once the deployment is complete, you can verify all the services are running and - In the Azure portal, navigate to your Azure Service Bus resource and use Azure Service Bus explorer to check for order messages - In the Azure portal, navigate to your Azure Cosmos DB resource and use the database explorer to check for order records -- Port-forward the store-admin service (using the command below) then open http://localhost:8081 in your browser and ensure you can add product descriptions using the AI service - - ```bash - kubectl port-forward svc/store-admin 8081:80 - ``` ## Additional Resources diff --git a/aks-store-all-in-one.yaml b/aks-store-all-in-one.yaml index 25eed65c..c3f72cd2 100644 --- a/aks-store-all-in-one.yaml +++ b/aks-store-all-in-one.yaml @@ -300,13 +300,16 @@ spec: image: ghcr.io/azure-samples/aks-store-demo/product-service:latest ports: - containerPort: 3002 + env: + - name: AI_SERVICE_URL + value: "http://ai-service:5001/" resources: requests: cpu: 1m memory: 1Mi limits: - cpu: 1m - memory: 7Mi + cpu: 2m + memory: 10Mi readinessProbe: httpGet: path: /health @@ -374,7 +377,7 @@ spec: path: /health port: 8080 failureThreshold: 3 - initialDelaySeconds: 15 + initialDelaySeconds: 5 periodSeconds: 5 readinessProbe: httpGet: @@ -430,8 +433,6 @@ spec: value: "http://product-service:3002/" - name: VUE_APP_MAKELINE_SERVICE_URL value: "http://makeline-service:3001/" - - name: VUE_APP_AI_SERVICE_URL - value: "http://ai-service:5001/" resources: requests: cpu: 1m @@ -444,7 +445,7 @@ spec: path: /health port: 8081 failureThreshold: 3 - initialDelaySeconds: 15 + initialDelaySeconds: 5 periodSeconds: 5 readinessProbe: httpGet: diff --git a/aks-store-quickstart.yaml b/aks-store-quickstart.yaml index 0cfdd4a7..eeda0c9a 100644 --- a/aks-store-quickstart.yaml +++ b/aks-store-quickstart.yaml @@ -179,13 +179,16 @@ spec: image: ghcr.io/azure-samples/aks-store-demo/product-service:latest ports: - containerPort: 3002 + env: + - name: AI_SERVICE_URL + value: "http://ai-service:5001/" resources: requests: cpu: 1m memory: 1Mi limits: - cpu: 1m - memory: 7Mi + cpu: 2m + memory: 10Mi readinessProbe: httpGet: path: /health @@ -253,7 +256,7 @@ spec: path: /health port: 8080 failureThreshold: 3 - initialDelaySeconds: 15 + initialDelaySeconds: 5 periodSeconds: 5 readinessProbe: httpGet: diff --git a/azure.yaml b/azure.yaml index dcb4c483..2c7fd43b 100644 --- a/azure.yaml +++ b/azure.yaml @@ -2,7 +2,7 @@ name: aks-store-demo metadata: - template: aks-store-dmeo@1.0.0 + template: aks-store-demo@1.0.0 hooks: preprovision: shell: sh @@ -14,5 +14,10 @@ hooks: continueOnError: false interactive: false run: infra/azd-hooks/postprovision.sh + predeploy: + shell: sh + continueOnError: false + interactive: false + run: infra/azd-hooks/predeploy.sh infra: provider: terraform \ No newline at end of file diff --git a/charts/aks-store-demo/templates/ai-service.yaml b/charts/aks-store-demo/templates/ai-service.yaml index 0784fd46..697df893 100644 --- a/charts/aks-store-demo/templates/ai-service.yaml +++ b/charts/aks-store-demo/templates/ai-service.yaml @@ -54,7 +54,7 @@ spec: "kubernetes.io/os": linux containers: - name: order-service - image: ghcr.io/azure-samples/aks-store-demo/ai-service:1.0.0 + image: {{ .Values.aiService.image.repository }}:{{ .Values.aiService.image.tag }} ports: - containerPort: 5001 envFrom: diff --git a/charts/aks-store-demo/templates/makeline-service.yaml b/charts/aks-store-demo/templates/makeline-service.yaml index 857df1cb..79ce503f 100644 --- a/charts/aks-store-demo/templates/makeline-service.yaml +++ b/charts/aks-store-demo/templates/makeline-service.yaml @@ -9,7 +9,14 @@ data: ORDER_QUEUE_NAME: "{{ .Values.makelineService.orderQueueName }}" ORDER_DB_URI: "{{ .Values.makelineService.orderDBUri }}" ORDER_DB_NAME: "{{ .Values.makelineService.orderDBName }}" + {{- if eq .Values.makelineService.useSqlApi true }} + ORDER_DB_API: cosmosdbsql + ORDER_DB_CONTAINER_NAME: "{{ .Values.makelineService.orderDBContainerName }}" + ORDER_DB_PARTITION_KEY: "storeId" + ORDER_DB_PARTITION_VALUE: "pets" + {{- else }} ORDER_DB_COLLECTION_NAME: "{{ .Values.makelineService.orderDBCollectionName }}" + {{- end }} --- {{- if and .Values.makelineService.orderDBUsername .Values.makelineService.orderDBPassword }} apiVersion: v1 @@ -39,7 +46,7 @@ spec: "kubernetes.io/os": linux containers: - name: makeline-service - image: ghcr.io/azure-samples/aks-store-demo/makeline-service:1.0.0 + image: {{ .Values.makelineService.image.repository }}:{{ .Values.makelineService.image.tag }} ports: - containerPort: 3001 envFrom: diff --git a/charts/aks-store-demo/templates/order-service.yaml b/charts/aks-store-demo/templates/order-service.yaml index b2b25d67..d834e1a7 100644 --- a/charts/aks-store-demo/templates/order-service.yaml +++ b/charts/aks-store-demo/templates/order-service.yaml @@ -37,7 +37,7 @@ spec: "kubernetes.io/os": linux containers: - name: order-service - image: ghcr.io/azure-samples/aks-store-demo/order-service:1.0.0 + image: {{ .Values.orderService.image.repository }}:{{ .Values.orderService.image.tag }} ports: - containerPort: 3000 envFrom: diff --git a/charts/aks-store-demo/templates/product-service.yaml b/charts/aks-store-demo/templates/product-service.yaml index 1653cc62..d242d663 100644 --- a/charts/aks-store-demo/templates/product-service.yaml +++ b/charts/aks-store-demo/templates/product-service.yaml @@ -16,16 +16,19 @@ spec: "kubernetes.io/os": linux containers: - name: product-service - image: ghcr.io/azure-samples/aks-store-demo/product-service:1.0.0 + image: {{ .Values.productService.image.repository }}:{{ .Values.productService.image.tag }} ports: - containerPort: 3002 + env: + - name: AI_SERVICE_URL + value: "http://ai-service:5001/" resources: requests: cpu: 1m memory: 1Mi limits: - cpu: 1m - memory: 6Mi + cpu: 2m + memory: 10Mi readinessProbe: httpGet: path: /health diff --git a/charts/aks-store-demo/templates/store-admin.yaml b/charts/aks-store-demo/templates/store-admin.yaml index c96823fb..ebd1249f 100644 --- a/charts/aks-store-demo/templates/store-admin.yaml +++ b/charts/aks-store-demo/templates/store-admin.yaml @@ -16,7 +16,7 @@ spec: "kubernetes.io/os": linux containers: - name: store-admin - image: ghcr.io/azure-samples/aks-store-demo/store-admin:1.0.0 + image: {{ .Values.storeAdmin.image.repository }}:{{ .Values.storeAdmin.image.tag }} ports: - containerPort: 8081 name: store-admin @@ -25,8 +25,8 @@ spec: value: "http://product-service:3002/" - name: VUE_APP_MAKELINE_SERVICE_URL value: "http://makeline-service:3001/" - - name: VUE_APP_AI_SERVICE_URL - value: "http://ai-service:5001/" + - name: VUE_APP_AI_SERVICE_URL # this key/value pair is to support previous versions of store-admin <= 1.1.0 + value: "http://ai-service:5001/" # container images hosted on ghcr.io and will be removed in future releases resources: requests: cpu: 1m @@ -39,7 +39,7 @@ spec: path: /health port: 8081 failureThreshold: 3 - initialDelaySeconds: 15 + initialDelaySeconds: 5 periodSeconds: 5 readinessProbe: httpGet: diff --git a/charts/aks-store-demo/templates/store-front.yaml b/charts/aks-store-demo/templates/store-front.yaml index 2a78a1f6..e82abdd8 100644 --- a/charts/aks-store-demo/templates/store-front.yaml +++ b/charts/aks-store-demo/templates/store-front.yaml @@ -16,7 +16,7 @@ spec: "kubernetes.io/os": linux containers: - name: store-front - image: ghcr.io/azure-samples/aks-store-demo/store-front:1.0.0 + image: {{ .Values.storeFront.image.repository }}:{{ .Values.storeFront.image.tag }} ports: - containerPort: 8080 name: store-front @@ -37,7 +37,7 @@ spec: path: /health port: 8080 failureThreshold: 3 - initialDelaySeconds: 15 + initialDelaySeconds: 5 periodSeconds: 5 readinessProbe: httpGet: diff --git a/charts/aks-store-demo/templates/virtual-customer.yaml b/charts/aks-store-demo/templates/virtual-customer.yaml index 80388502..cd11855f 100644 --- a/charts/aks-store-demo/templates/virtual-customer.yaml +++ b/charts/aks-store-demo/templates/virtual-customer.yaml @@ -16,7 +16,7 @@ spec: "kubernetes.io/os": linux containers: - name: virtual-customer - image: ghcr.io/azure-samples/aks-store-demo/virtual-customer:1.0.0 + image: {{ .Values.virtualCustomer.image.repository }}:{{ .Values.virtualCustomer.image.tag }} env: - name: ORDER_SERVICE_URL value: http://order-service:3000/ diff --git a/charts/aks-store-demo/templates/virtual-worker.yaml b/charts/aks-store-demo/templates/virtual-worker.yaml index f5d929e1..3a667bc5 100644 --- a/charts/aks-store-demo/templates/virtual-worker.yaml +++ b/charts/aks-store-demo/templates/virtual-worker.yaml @@ -16,7 +16,7 @@ spec: "kubernetes.io/os": linux containers: - name: virtual-worker - image: ghcr.io/azure-samples/aks-store-demo/virtual-worker:1.0.0 + image: {{ .Values.virtualWorker.image.repository }}:{{ .Values.virtualWorker.image.tag }} env: - name: MAKELINE_SERVICE_URL value: http://makeline-service:3001 diff --git a/charts/aks-store-demo/values.yaml b/charts/aks-store-demo/values.yaml index 11d8efa6..90bc469b 100644 --- a/charts/aks-store-demo/values.yaml +++ b/charts/aks-store-demo/values.yaml @@ -16,6 +16,9 @@ aiService: managedIdentityClientId: "" useAzureOpenAi: true useAzureAd: true + image: + repository: "ghcr.io/azure-samples/aks-store-demo/ai-service" + tag: "latest" orderService: useAzureServiceBus: false # when false, local rabbitmq will be used @@ -25,9 +28,13 @@ orderService: queuePassword: "password" queueName: "orders" queueTransport: "" + image: + repository: "ghcr.io/azure-samples/aks-store-demo/order-service" + tag: "latest" makelineService: useAzureCosmosDB: false # when false, local mongodb will be used + useSqlApi: false # when false, mongodb api for azure cosmosdb will be used orderQueueUri: "amqp://rabbitmq:5672" orderQueueUsername: "username" orderQueuePassword: "password" @@ -35,15 +42,40 @@ makelineService: orderDBUri: "mongodb://mongodb:27017" orderDBName: "orderdb" orderDBCollectionName: "orders" + orderDBContainerName: "orders" orderDBUsername: "" orderDBPassword: "" + image: + repository: "ghcr.io/azure-samples/aks-store-demo/makeline-service" + tag: "latest" -storeFront: - serviceType: LoadBalancer +productService: + image: + repository: "ghcr.io/azure-samples/aks-store-demo/product-service" + tag: "latest" storeAdmin: + image: + repository: "ghcr.io/azure-samples/aks-store-demo/store-admin" + tag: "latest" serviceType: LoadBalancer +storeFront: + image: + repository: "ghcr.io/azure-samples/aks-store-demo/store-front" + tag: "latest" + serviceType: LoadBalancer + +virtualCustomer: + image: + repository: "ghcr.io/azure-samples/aks-store-demo/virtual-customer" + tag: "latest" + +virtualWorker: + image: + repository: "ghcr.io/azure-samples/aks-store-demo/virtual-worker" + tag: "latest" + podAnnotations: {} podSecurityContext: {} diff --git a/docker-compose-quickstart.yml b/docker-compose-quickstart.yml index 622fd3a0..193818f3 100644 --- a/docker-compose-quickstart.yml +++ b/docker-compose-quickstart.yml @@ -19,14 +19,14 @@ services: - ./rabbitmq_enabled_plugins:/etc/rabbitmq/enabled_plugins networks: - backend_services - orderservice: + order-service: build: src/order-service - container_name: 'orderservice' + container_name: 'order-service' restart: always ports: - 3000:3000 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://orderservice:3000/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://order-service:3000/health"] interval: 30s timeout: 10s retries: 5 @@ -42,38 +42,40 @@ services: depends_on: rabbitmq: condition: service_healthy - productservice: + product-service: build: src/product-service - container_name: 'productservice' + container_name: 'product-service' restart: always ports: - 3002:3002 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://productservice:3002/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://product-service:3002/health"] interval: 30s timeout: 10s retries: 5 + environment: + - AI_SERVICE_URL=http://ai-service:5001/ networks: - backend_services - storefront: + store-front: build: src/store-front - container_name: 'storefront' + container_name: 'store-front' restart: always ports: - 8080:8080 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://storefront:80/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://store-front:80/health"] interval: 30s timeout: 10s retries: 5 environment: - - VUE_APP_PRODUCT_SERVICE_URL=http://productservice:3002/ - - VUE_APP_ORDER_SERVICE_URL=http://orderservice:3000/ + - VUE_APP_PRODUCT_SERVICE_URL=http://product-service:3002/ + - VUE_APP_ORDER_SERVICE_URL=http://order-service:3000/ networks: - backend_services depends_on: - - productservice - - orderservice + - product-service + - order-service networks: backend_services: driver: bridge \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 1296330a..13b33c05 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,14 +32,14 @@ services: - ./rabbitmq_enabled_plugins:/etc/rabbitmq/enabled_plugins networks: - backend_services - orderservice: + order-service: build: src/order-service - container_name: 'orderservice' + container_name: 'order-service' restart: always ports: - 3000:3000 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://orderservice:3000/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://order-service:3000/health"] interval: 30s timeout: 10s retries: 5 @@ -55,14 +55,14 @@ services: depends_on: rabbitmq: condition: service_healthy - makelineservice: + makeline-service: build: src/makeline-service - container_name: 'makelineservice' + container_name: 'makeline-service' restart: always ports: - 3001:3001 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://makelineservice:3001/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://makeline-service:3001/health"] interval: 30s timeout: 10s retries: 5 @@ -81,90 +81,91 @@ services: condition: service_healthy mongodb: condition: service_healthy - productservice: + product-service: build: src/product-service - container_name: 'productservice' + container_name: 'product-service' restart: always ports: - 3002:3002 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://productservice:3002/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://product-service:3002/health"] interval: 30s timeout: 10s retries: 5 + environment: + - AI_SERVICE_URL=http://ai-service:5001/ networks: - backend_services - storefront: + store-front: build: src/store-front - container_name: 'storefront' + container_name: 'store-front' restart: always ports: - 8080:8080 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://storefront:80/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://store-front:80/health"] interval: 30s timeout: 10s retries: 5 environment: - - VUE_APP_PRODUCT_SERVICE_URL=http://productservice:3002/ - - VUE_APP_ORDER_SERVICE_URL=http://orderservice:3000/ + - VUE_APP_PRODUCT_SERVICE_URL=http://product-service:3002/ + - VUE_APP_ORDER_SERVICE_URL=http://order-service:3000/ networks: - backend_services depends_on: - - productservice - - orderservice - storeadmin: + - product-service + - order-service + store-admin: build: src/store-admin - container_name: 'storeadmin' + container_name: 'store-admin' restart: always ports: - 8081:8081 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://storeadmin:80/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://store-admin:80/health"] interval: 30s timeout: 10s retries: 5 environment: - - VUE_APP_PRODUCT_SERVICE_URL=http://productservice:3002/ - - VUE_APP_MAKELINE_SERVICE_URL=http://makelineservice:3001/ - - VUE_APP_AI_SERVICE_URL=http://aiservice:5001/ + - VUE_APP_PRODUCT_SERVICE_URL=http://product-service:3002/ + - VUE_APP_MAKELINE_SERVICE_URL=http://makeline-service:3001/ networks: - backend_services depends_on: - - productservice - - makelineservice - virtualcustomer: + - product-service + - makeline-service + virtual-customer: build: src/virtual-customer - container_name: 'virtualcustomer' + container_name: 'virtual-customer' restart: always environment: - - ORDER_SERVICE_URL=http://orderservice:3000/ + - ORDER_SERVICE_URL=http://order-service:3000/ - ORDERS_PER_HOUR=500 networks: - backend_services depends_on: - orderservice: + order-service: condition: service_healthy - virtualworker: + virtual-worker: build: src/virtual-worker - container_name: 'virtualworker' + container_name: 'virtual-worker' restart: always environment: - - MAKELINE_SERVICE_URL=http://makelineservice:3001 + - MAKELINE_SERVICE_URL=http://makeline-service:3001 - ORDERS_PER_HOUR=400 networks: - backend_services depends_on: - makelineservice: + makeline-service: condition: service_healthy - aiservice: + ai-service: build: src/ai-service - container_name: 'aiservice' + container_name: 'ai-service' restart: always ports: - 5001:5001 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://aiservice:5001/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://ai-service:5001/health"] interval: 30s timeout: 10s retries: 5 diff --git a/infra/azd-hooks/postprovision.sh b/infra/azd-hooks/postprovision.sh index f1fd3ca5..c6837321 100755 --- a/infra/azd-hooks/postprovision.sh +++ b/infra/azd-hooks/postprovision.sh @@ -1,29 +1,19 @@ #!/bin/bash -echo "Retrieving cluster credentials" -az aks get-credentials --resource-group ${rg_name} --name ${aks_name} +services=("ai-service" "makeline-service" "order-service" "product-service" "store-admin" "store-front" "virtual-customer" "virtual-worker") -# echo "Deploy the manifests" -# kubectl apply -f manifests/ - -echo "Deploy Helm chart" -helm upgrade aks-store-demo ./charts/aks-store-demo \ - --install \ - --set aiService.create=true \ - --set aiService.modelDeploymentName=${ai_model_name} \ - --set aiService.openAiEndpoint=${ai_endpoint} \ - --set aiService.managedIdentityClientId=${ai_managed_identity_client_id} \ - --set orderService.useAzureServiceBus=true \ - --set orderService.queueHost=${sb_namespace_host} \ - --set orderService.queuePort=5671 \ - --set orderService.queueUsername=${sb_sender_username} \ - --set orderService.queuePassword=${sb_sender_key} \ - --set orderService.queueTransport=tls \ - --set makelineService.useAzureCosmosDB=true \ - --set makelineService.orderQueueUri=${sb_namespace_uri} \ - --set makelineService.orderQueueUsername=${sb_listener_username} \ - --set makelineService.orderQueuePassword=${sb_listener_key} \ - --set makelineService.orderDBUri=${db_uri} \ - --set makelineService.orderDBUsername=${db_account_name} \ - --set makelineService.orderDBPassword=${db_key} \ - \ No newline at end of file +if [ -n "$DEPLOY_AZURE_CONTAINER_REGISTRY" ] && [ "$BUILD_CONTAINERS" == "true" ]; then + echo "Build container images" + for service in "${services[@]}"; do + echo "Building aks-store-demo/${service}:latest" + az acr build --registry ${registry_name} --image aks-store-demo/${service}:latest ./src/${service}/ + done +elif [ -n "$DEPLOY_AZURE_CONTAINER_REGISTRY" ] && ([ -z "$BUILD_CONTAINERS" ] || [ "$BUILD_CONTAINERS" == "false" ]); then + echo "Import container images" + for service in "${services[@]}"; do + echo "Importing aks-store-demo/${service}:latest" + az acr import --name ${registry_name} --source ghcr.io/azure-samples/aks-store-demo/${service}:latest --image aks-store-demo/${service}:latest + done +else + echo "No BUILD_CONTAINERS variable set, skipping container build/import" +fi \ No newline at end of file diff --git a/infra/azd-hooks/predeploy.sh b/infra/azd-hooks/predeploy.sh new file mode 100755 index 00000000..600e485b --- /dev/null +++ b/infra/azd-hooks/predeploy.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +echo "Retrieving cluster credentials" +az aks get-credentials --resource-group ${rg_name} --name ${aks_name} + +echo "Deploy Helm chart" +helm upgrade aks-store-demo ./charts/aks-store-demo \ + --install \ + --set aiService.create=true \ + --set aiService.modelDeploymentName=${ai_model_name} \ + --set aiService.openAiEndpoint=${ai_endpoint} \ + --set aiService.managedIdentityClientId=${ai_managed_identity_client_id} \ + --set aiService.image.repository=${registry_uri}/aks-store-demo/ai-service \ + --set orderService.useAzureServiceBus=true \ + --set orderService.queueHost=${sb_namespace_host} \ + --set orderService.queuePort=5671 \ + --set orderService.queueUsername=${sb_sender_username} \ + --set orderService.queuePassword=${sb_sender_key} \ + --set orderService.queueTransport=tls \ + --set orderService.image.repository=${registry_uri}/aks-store-demo/order-service \ + --set makelineService.useAzureCosmosDB=true \ + --set makelineService.orderQueueUri=${sb_namespace_uri} \ + --set makelineService.orderQueueUsername=${sb_listener_username} \ + --set makelineService.orderQueuePassword=${sb_listener_key} \ + --set makelineService.orderDBUri=${db_uri} \ + --set makelineService.orderDBUsername=${db_account_name} \ + --set makelineService.orderDBPassword=${db_key} \ + --set makelineService.image.repository=${registry_uri}/aks-store-demo/makeline-service \ + --set productService.image.repository=${registry_uri}/aks-store-demo/product-service \ + --set storeAdmin.image.repository=${registry_uri}/aks-store-demo/store-admin \ + --set storeFront.image.repository=${registry_uri}/aks-store-demo/store-front \ + --set virtualCustomer.image.repository=${registry_uri}/aks-store-demo/virtual-customer \ + --set virtualWorker.image.repository=${registry_uri}/aks-store-demo/virtual-worker \ + $(if [ "${db_api}" == "cosmosdbsql" ]; then echo "--set makelineService.useSqlApi=true"; fi) diff --git a/infra/cosmosdb.tf b/infra/cosmosdb.tf index e7839b92..f21af43d 100644 --- a/infra/cosmosdb.tf +++ b/infra/cosmosdb.tf @@ -3,24 +3,15 @@ resource "azurerm_cosmosdb_account" "example" { location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name offer_type = "Standard" - kind = "MongoDB" + kind = local.cosmosdb_account_kind enable_automatic_failover = false - capabilities { - name = "EnableAggregationPipeline" - } - - capabilities { - name = "mongoEnableDocLevelTTL" - } - - capabilities { - name = "MongoDBv3.4" - } - - capabilities { - name = "EnableMongo" + dynamic "capabilities" { + for_each = local.cosmosdb_account_kind == "MongoDB" ? ["EnableAggregationPipeline", "mongoEnableDocLevelTTL", "MongoDBv3.4", "EnableMongo"] : ["EnableAggregationPipeline"] + content { + name = capabilities.value + } } consistency_policy { @@ -41,6 +32,7 @@ resource "azurerm_cosmosdb_account" "example" { } resource "azurerm_cosmosdb_mongo_database" "example" { + count = local.cosmosdb_account_kind == "MongoDB" ? 1 : 0 name = "orderdb" resource_group_name = azurerm_cosmosdb_account.example.resource_group_name account_name = azurerm_cosmosdb_account.example.name @@ -48,14 +40,34 @@ resource "azurerm_cosmosdb_mongo_database" "example" { } resource "azurerm_cosmosdb_mongo_collection" "example" { + count = local.cosmosdb_account_kind == "MongoDB" ? 1 : 0 name = "orders" resource_group_name = azurerm_cosmosdb_account.example.resource_group_name account_name = azurerm_cosmosdb_account.example.name - database_name = azurerm_cosmosdb_mongo_database.example.name + database_name = azurerm_cosmosdb_mongo_database.example[0].name throughput = 400 index { keys = ["_id"] unique = true } +} + +resource "azurerm_cosmosdb_sql_database" "example" { + count = local.cosmosdb_account_kind == "GlobalDocumentDB" ? 1 : 0 + name = "orderdb" + resource_group_name = azurerm_cosmosdb_account.example.resource_group_name + account_name = azurerm_cosmosdb_account.example.name + throughput = 400 +} + +resource "azurerm_cosmosdb_sql_container" "example" { + count = local.cosmosdb_account_kind == "GlobalDocumentDB" ? 1 : 0 + name = "orders" + resource_group_name = azurerm_cosmosdb_account.example.resource_group_name + account_name = azurerm_cosmosdb_account.example.name + database_name = azurerm_cosmosdb_sql_database.example[0].name + partition_key_path = "/storeId" + partition_key_version = 1 + throughput = 400 } \ No newline at end of file diff --git a/infra/kubernetes.tf b/infra/kubernetes.tf index 47255a3c..6c8cd30b 100644 --- a/infra/kubernetes.tf +++ b/infra/kubernetes.tf @@ -1,3 +1,11 @@ +resource "azurerm_container_registry" "example" { + count = local.deploy_acr ? 1 : 0 + name = "acr${local.name}" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + sku = "Premium" +} + resource "azurerm_kubernetes_cluster" "example" { name = "aks-${local.name}" location = azurerm_resource_group.example.location @@ -24,4 +32,12 @@ resource "azurerm_kubernetes_cluster" "example" { microsoft_defender ] } +} + +resource "azurerm_role_assignment" "example" { + count = local.deploy_acr ? 1 : 0 + principal_id = azurerm_kubernetes_cluster.example.kubelet_identity[0].object_id + role_definition_name = "AcrPull" + scope = azurerm_container_registry.example[0].id + skip_service_principal_aad_check = true } \ No newline at end of file diff --git a/infra/locals.tf b/infra/locals.tf new file mode 100644 index 00000000..c8caf81b --- /dev/null +++ b/infra/locals.tf @@ -0,0 +1,7 @@ +locals { + name = "${random_pet.example.id}${random_integer.example.result}" + location = var.location + default_cosmosdb_account_kind = "MongoDB" + cosmosdb_account_kind = var.cosmosdb_account_kind != "" ? var.cosmosdb_account_kind : local.default_cosmosdb_account_kind + deploy_acr = var.deploy_acr == "true" ? true : false +} \ No newline at end of file diff --git a/infra/main.tf b/infra/main.tf index b2f27ae3..83e75dd8 100644 --- a/infra/main.tf +++ b/infra/main.tf @@ -42,11 +42,6 @@ resource "random_pet" "example" { } } -locals { - name = "${random_pet.example.id}${random_integer.example.result}" - location = var.location -} - data "azurerm_subscription" "current" {} data "azurerm_client_config" "current" {} diff --git a/infra/main.tfvars.json b/infra/main.tfvars.json index 9618150e..f1a7f544 100644 --- a/infra/main.tfvars.json +++ b/infra/main.tfvars.json @@ -1,4 +1,6 @@ { "location": "${AZURE_LOCATION}", - "ai_location": "${AZURE_LOCATION}" + "ai_location": "${AZURE_LOCATION}", + "cosmosdb_account_kind": "${AZURE_COSMOSDB_ACCOUNT_KIND}", + "deploy_acr": "${DEPLOY_AZURE_CONTAINER_REGISTRY}" } \ No newline at end of file diff --git a/infra/outputs.tf b/infra/outputs.tf index 52ed2216..3c67d098 100644 --- a/infra/outputs.tf +++ b/infra/outputs.tf @@ -54,8 +54,12 @@ output "db_account_name" { value = azurerm_cosmosdb_account.example.name } +output "db_api" { + value = local.cosmosdb_account_kind == "MongoDB" ? "mongodb" : "cosmosdbsql" +} + output "db_uri" { - value = "mongodb://${azurerm_cosmosdb_account.example.name}.mongo.cosmos.azure.com:10255/?retryWrites=false" + value = local.cosmosdb_account_kind == "MongoDB" ? "mongodb://${azurerm_cosmosdb_account.example.name}.mongo.cosmos.azure.com:10255/?retryWrites=false" : "https://${azurerm_cosmosdb_account.example.name}.documents.azure.com:443/" } output "db_key" { @@ -65,4 +69,12 @@ output "db_key" { output "k8s_namespace" { value = var.k8s_namespace +} + +output "registry_name" { + value = local.deploy_acr ? azurerm_container_registry.example[0].name : "" +} + +output "registry_uri" { + value = local.deploy_acr ? azurerm_container_registry.example[0].login_server : "ghcr.io/azure-samples" } \ No newline at end of file diff --git a/infra/variables.tf b/infra/variables.tf index f9d5e04b..b540e38f 100644 --- a/infra/variables.tf +++ b/infra/variables.tf @@ -28,4 +28,21 @@ variable "k8s_namespace" { description = "value of kubernetes namespace" type = string default = "default" -} \ No newline at end of file +} + +variable "cosmosdb_account_kind" { + description = "value of cosmosdb account kind. this string value will be used to set the local variable" + type = string + default = "MongoDB" + + # validation { + # condition = contains(["MongoDB", "GlobalDocumentDB"], local.cosmosdb_account_kind) + # error_message = "Valid values for var: cosmosdb_account_kind are (MongoDB, GlobalDocumentDB)." + # } +} + +variable "deploy_acr" { + description = "value of deploy acr. this string value will be used to set the local variable" + type = string + default = "false" +} diff --git a/src/makeline-service/README.md b/src/makeline-service/README.md index 032d2f89..9ab8cf18 100644 --- a/src/makeline-service/README.md +++ b/src/makeline-service/README.md @@ -65,7 +65,7 @@ export ORDER_QUEUE_PASSWORD=$PASSWORD export ORDER_QUEUE_NAME=orders ``` -> NOTE: If you are using Azure Service Bus, you will want your `order-service` to write orders to it instead of RabbitMQ. If that is the case, then you'll need to update the [`docker-compose.yml`](./docker-compose.yml) and modify the environment variables for the `orderservice` to include the proper connection info to connect to Azure Service Bus. Also you will need to add the `ORDER_QUEUE_TRANSPORT=tls` configuration to connect over TLS. +> NOTE: If you are using Azure Service Bus, you will want your `order-service` to write orders to it instead of RabbitMQ. If that is the case, then you'll need to update the [`docker-compose.yml`](./docker-compose.yml) and modify the environment variables for the `order-service` to include the proper connection info to connect to Azure Service Bus. Also you will need to add the `ORDER_QUEUE_TRANSPORT=tls` configuration to connect over TLS. ## Database options diff --git a/src/makeline-service/docker-compose.yml b/src/makeline-service/docker-compose.yml index d72589a9..5a92881b 100644 --- a/src/makeline-service/docker-compose.yml +++ b/src/makeline-service/docker-compose.yml @@ -32,14 +32,14 @@ services: - ../../rabbitmq_enabled_plugins:/etc/rabbitmq/enabled_plugins networks: - backend_services - orderservice: + order-service: build: ../order-service - container_name: 'orderservice' + container_name: 'order-service' restart: always ports: - 3000:3000 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://orderservice:3000/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://order-service:3000/health"] interval: 30s timeout: 10s retries: 5 @@ -55,17 +55,17 @@ services: depends_on: rabbitmq: condition: service_healthy - virtualcustomer: + virtual-customer: build: ../virtual-customer - container_name: 'virtualcustomer' + container_name: 'virtual-customer' restart: always environment: - - ORDER_SERVICE_URL=http://orderservice:3000/ + - ORDER_SERVICE_URL=http://order-service:3000/ - ORDERS_PER_HOUR=60 networks: - backend_services depends_on: - orderservice: + order-service: condition: service_healthy networks: backend_services: diff --git a/src/product-service/Cargo.lock b/src/product-service/Cargo.lock index de9bb6b2..60bbc79a 100644 --- a/src/product-service/Cargo.lock +++ b/src/product-service/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bytes", "futures-core", "futures-sink", @@ -46,7 +46,7 @@ dependencies = [ "actix-utils", "ahash 0.8.3", "base64", - "bitflags", + "bitflags 1.3.2", "brotli", "bytes", "bytestring", @@ -269,6 +269,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + [[package]] name = "block-buffer" version = "0.10.4" @@ -299,6 +305,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + [[package]] name = "bytes" version = "1.4.0" @@ -346,6 +358,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "cpufeatures" version = "0.2.7" @@ -433,7 +461,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -446,6 +474,12 @@ dependencies = [ "libc", ] +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "flate2" version = "1.0.26" @@ -462,6 +496,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -471,6 +520,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", +] + [[package]] name = "futures-core" version = "0.3.28" @@ -586,6 +644,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.8.0" @@ -604,6 +673,43 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "idna" version = "0.4.0" @@ -632,9 +738,15 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "is-terminal" version = "0.4.7" @@ -643,8 +755,8 @@ checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix", - "windows-sys", + "rustix 0.37.25", + "windows-sys 0.48.0", ] [[package]] @@ -662,12 +774,27 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "language-tags" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.146" @@ -680,6 +807,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + [[package]] name = "local-channel" version = "0.1.3" @@ -744,7 +877,25 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] @@ -763,6 +914,50 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl" +version = "0.10.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -783,7 +978,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.0", ] [[package]] @@ -839,6 +1034,7 @@ dependencies = [ "actix-web", "env_logger", "futures-util", + "reqwest", "serde", "serde_json", ] @@ -888,7 +1084,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -908,6 +1104,44 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +[[package]] +name = "reqwest" +version = "0.11.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "rustc_version" version = "0.4.0" @@ -923,12 +1157,25 @@ version = "0.37.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", - "windows-sys", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac5ffa1efe7548069688cd7028f32591853cd7b5b756d41bcffd2353e4fc75b4" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys 0.4.13", + "windows-sys 0.48.0", ] [[package]] @@ -937,12 +1184,44 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.17" @@ -1059,6 +1338,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix 0.38.3", + "windows-sys 0.48.0", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -1124,7 +1437,17 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "socket2", - "windows-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", ] [[package]] @@ -1141,6 +1464,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.37" @@ -1162,6 +1491,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.16.0" @@ -1200,18 +1535,109 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.18", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" + +[[package]] +name = "web-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1249,7 +1675,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1258,13 +1693,28 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -1273,42 +1723,94 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "zstd" version = "0.12.3+zstd.1.5.2" diff --git a/src/product-service/Cargo.toml b/src/product-service/Cargo.toml index 482ecd2a..1cb1e8f5 100644 --- a/src/product-service/Cargo.toml +++ b/src/product-service/Cargo.toml @@ -10,5 +10,6 @@ actix-cors = "0.6.4" actix-web = "4.3.1" env_logger = "0.10.0" futures-util = "0.3.28" +reqwest = { version = "0.11.23", features = ["json"] } serde = { version = "1.0.164", features = ["derive"] } serde_json = "1.0.96" diff --git a/src/product-service/src/main.rs b/src/product-service/src/main.rs index d00577db..9b59b4e0 100644 --- a/src/product-service/src/main.rs +++ b/src/product-service/src/main.rs @@ -1,10 +1,14 @@ use actix_cors::Cors; use actix_web::middleware::Logger; -use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer}; +use actix_web::{ + error, error::ResponseError, middleware, web, App, Error, HttpResponse, HttpServer, +}; use env_logger::Env; use futures_util::StreamExt; use serde::{Deserialize, Serialize}; use serde_json::json; +use std::collections::HashMap; +use std::fmt; use std::sync::Mutex; const MAX_SIZE: usize = 262_144; // max payload size is 256k @@ -110,6 +114,73 @@ async fn delete_product( Ok(HttpResponse::Ok().body("")) } +////////////////////////// +// Proxy for AI service +////////////////////////// + +#[derive(Debug)] +struct ProxyError(reqwest::Error); + +impl fmt::Display for ProxyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl ResponseError for ProxyError { + fn error_response(&self) -> HttpResponse { + HttpResponse::InternalServerError().json(self.0.to_string()) + } +} + +impl From for ProxyError { + fn from(err: reqwest::Error) -> ProxyError { + ProxyError(err) + } +} + +fn get_ai_service_url() -> String { + let ai_service_url = std::env::var("AI_SERVICE_URL").unwrap_or_else(|_| "http://127.0.0.1:5001".to_string()); + ai_service_url.trim_end_matches('/').to_string() +} + +async fn ai_health() -> Result { + let client = reqwest::Client::new(); + let resp = client.get(get_ai_service_url() + "/health").send().await.unwrap(); + let status = resp.status(); + if status.is_success() { + let body: HashMap = resp.json().await.map_err(ProxyError::from)?; + let body_json = serde_json::to_string(&body).unwrap(); + Ok(HttpResponse::Ok().body(body_json)) + } else { + Ok(HttpResponse::build(actix_web::http::StatusCode::NOT_FOUND).body("")) + } +} + +async fn ai_generate_description(mut payload: web::Payload) -> Result { + let mut body = web::BytesMut::new(); + while let Some(chunk) = payload.next().await { + let chunk = chunk?; + body.extend_from_slice(&chunk); + } + let client = reqwest::Client::new(); + let resp = client + .post(get_ai_service_url() + "/generate/description") + .body(body.to_vec()) + .send() + .await + .unwrap(); + + let status = resp.status(); + let body: HashMap = resp.json().await.map_err(ProxyError::from)?; + let body_json = serde_json::to_string(&body).unwrap(); + if status.is_success() { + Ok(HttpResponse::Ok().body(body_json)) + } else { + Ok(HttpResponse::build(actix_web::http::StatusCode::INTERNAL_SERVER_ERROR).body(body_json)) + } +} + #[actix_web::main] async fn main() -> std::io::Result<()> { let products = vec![ @@ -209,6 +280,12 @@ async fn main() -> std::io::Result<()> { .route("/", web::post().to(add_product)) .route("/", web::put().to(update_product)) .route("/{product_id}", web::delete().to(delete_product)) + .route("/ai/health", web::get().to(ai_health)) + .route("/ai/health", web::head().to(ai_health)) + .route( + "/ai/generate/description", + web::post().to(ai_generate_description), + ) }) .bind(("0.0.0.0", 3002))? .run() diff --git a/src/product-service/test-product-service.http b/src/product-service/test-product-service.http index 5f0a540d..d842f5f5 100644 --- a/src/product-service/test-product-service.http +++ b/src/product-service/test-product-service.http @@ -38,4 +38,19 @@ Host: localhost:3002 ### Delete product by id DELETE /11 -Host: localhost:3002 \ No newline at end of file +Host: localhost:3002 + +### Get ai service health +GET /ai/health +Host: localhost:3002 + +### Get product description from ai service +POST /ai/generate/description +Host: localhost:3002 +Content-Type: application/json + +{ + "name": "Seafarer's Tug Rope", + "tags": ["toy","dog"] +} + diff --git a/src/store-admin/Dockerfile b/src/store-admin/Dockerfile index 6f52b8d9..1d7cb718 100644 --- a/src/store-admin/Dockerfile +++ b/src/store-admin/Dockerfile @@ -3,9 +3,6 @@ FROM node:18.16.0-alpine as builder WORKDIR /app -# Set the build argument for the app version number -ARG APP_VERSION=0.1.0 - # Copy package.json and package-lock.json to the container COPY package*.json ./ @@ -15,24 +12,26 @@ RUN npm install # Copy the rest of the app source code to the container COPY . . -# Expose the port the app listens on -EXPOSE 80 +# Build the app +RUN npm run build -# Set the environment variable for the app version number -ENV APP_VERSION=$APP_VERSION +# Run the app on nginx +FROM nginx:stable-alpine as runner -# Start the app -CMD [ "npm", "run", "serve" ] +# Copy the build output to replace the default nginx contents +COPY --from=builder /app/dist /usr/share/nginx/html -# # Build the app -# RUN npm run build --mode production +# Expose the port the app listens on +EXPOSE 8081 -# # Run the app on nginx -# FROM nginx:stable-alpine as runner -# WORKDIR /app +# Set the build argument for the app version number +ARG APP_VERSION=0.1.0 -# # Copy the build output to replace the default nginx contents -# COPY --from=builder /app/dist /app +# Set the environment variable for the app version number +ENV APP_VERSION=$APP_VERSION + +# Copy the nginx configuration template to the container +COPY nginx.conf /etc/nginx/conf.d/nginx.conf.template -# # Copy the nginx configuration -# COPY nginx.conf /etc/nginx/nginx.conf \ No newline at end of file +# Start the app +CMD ["sh", "-c", "envsubst '${APP_VERSION}' < /etc/nginx/conf.d/nginx.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"] diff --git a/src/store-admin/README.md b/src/store-admin/README.md index cc60b1e8..3307426b 100644 --- a/src/store-admin/README.md +++ b/src/store-admin/README.md @@ -18,7 +18,7 @@ The app relies on the [product-service](../product-service), [makeline-service]( To run the necessary services, clone the repo, open a terminal, and navigate to the `store-admin` directory. -If you have access to OpenAI or Azure OpenAI, open the `docker-compose.yml` file, uncomment the `aiservices` block, and add your OpenAI or Azure OpenAI credentials. +If you have access to OpenAI or Azure OpenAI, open the `docker-compose.yml` file, uncomment the `ai-services` block, and add your OpenAI or Azure OpenAI credentials. > IMPORTANT: When filling in the values, do not put the value in double-quotes. @@ -42,7 +42,6 @@ With the services running, open a new terminal and navigate to the `store-admin` ```bash export VUE_APP_PRODUCT_SERVICE_URL=http://localhost:3002/ export VUE_APP_MAKELINE_SERVICE_URL=http://localhost:3001/ -export VUE_APP_AI_SERVICE_URL=http://localhost:5001/ npm install npm run serve diff --git a/src/store-admin/docker-compose.yml b/src/store-admin/docker-compose.yml index 0bd33fec..a0fbe347 100644 --- a/src/store-admin/docker-compose.yml +++ b/src/store-admin/docker-compose.yml @@ -32,14 +32,14 @@ services: - ../../rabbitmq_enabled_plugins:/etc/rabbitmq/enabled_plugins networks: - backend_services - orderservice: + order-service: build: ../order-service - container_name: 'orderservice' + container_name: 'order-service' restart: always ports: - 3000:3000 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://orderservice:3000/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://order-service:3000/health"] interval: 30s timeout: 10s retries: 5 @@ -55,14 +55,14 @@ services: depends_on: rabbitmq: condition: service_healthy - makelineservice: + makeline-service: build: ../makeline-service - container_name: 'makelineservice' + container_name: 'makeline-service' restart: always ports: - 3001:3001 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://makelineservice:3001/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://makeline-service:3001/health"] interval: 30s timeout: 10s retries: 5 @@ -81,39 +81,39 @@ services: condition: service_healthy mongodb: condition: service_healthy - productservice: + product-service: build: ../product-service - container_name: 'productservice' + container_name: 'product-service' restart: always ports: - 3002:3002 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://productservice:3002/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://product-service:3002/health"] interval: 30s timeout: 10s retries: 5 networks: - backend_services - virtualcustomer: + virtual-customer: build: ../virtual-customer - container_name: 'virtualcustomer' + container_name: 'virtual-customer' restart: always environment: - - ORDER_SERVICE_URL=http://orderservice:3000/ + - ORDER_SERVICE_URL=http://order-service:3000/ - ORDERS_PER_HOUR=3600 networks: - backend_services depends_on: - orderservice: + order-service: condition: service_healthy - # aiservice: + # ai-service: # build: ../ai-service - # container_name: 'aiservice' + # container_name: 'ai-service' # restart: always # ports: # - 5001:5001 # healthcheck: - # test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://aiservice:5001/health"] + # test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://ai-service:5001/health"] # interval: 30s # timeout: 10s # retries: 5 diff --git a/src/store-admin/nginx.conf b/src/store-admin/nginx.conf index 57e735ad..51bb45d5 100644 --- a/src/store-admin/nginx.conf +++ b/src/store-admin/nginx.conf @@ -1,32 +1,78 @@ -# Ref: https://cli.vuejs.org/guide/deployment.html#docker-nginx - -user nginx; -worker_processes 1; -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; -events { - worker_connections 1024; -} -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - access_log /var/log/nginx/access.log main; - sendfile on; - keepalive_timeout 65; - server { - listen 80; +server { + listen 8081; + listen [::]:8081; server_name localhost; + + #access_log /var/log/nginx/host.access.log main; + location / { - root /app; - index index.html; - try_files $uri $uri/ /index.html; + root /usr/share/nginx/html; + index index.html index.htm; } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # error_page 500 502 503 504 /50x.html; location = /50x.html { - root /usr/share/nginx/html; + root /usr/share/nginx/html; + } + + location /health { + default_type application/json; + return 200 '{"status":"ok","version":"${APP_VERSION}"}'; + } + + location ~ ^/makeline/order/(?\w+) { + proxy_pass http://makeline-service:3001/order/$id; + } + + location /makeline/order { + proxy_pass http://makeline-service:3001/order; + } + + location /makeline/order/fetch { + proxy_pass http://makeline-service:3001/order/fetch; + } + + location /order { + proxy_pass http://order-service:3000/; + } + + location /products/ { + proxy_pass http://product-service:3002/; + } + + location /products { + proxy_pass http://product-service:3002/; + } + + # location ~* ^/products { + # proxy_pass http://product-service:3002/; + # } + + location ~ ^/product/(?\w+) { + proxy_pass http://product-service:3002/$id; + } + + # location ~* ^/product { + # proxy_pass http://product-service:3002/; + # } + + location /product { + proxy_pass http://product-service:3002/; + } + + location /product/ { + proxy_pass http://product-service:3002/; + } + + location /ai/health { + proxy_pass http://product-service:3002/ai/health; + } + + location /ai/generate/description { + proxy_pass http://product-service:3002/ai/generate/description; } - } } \ No newline at end of file diff --git a/src/store-admin/vue.config.js b/src/store-admin/vue.config.js index 0fe86299..9d67e20d 100644 --- a/src/store-admin/vue.config.js +++ b/src/store-admin/vue.config.js @@ -4,7 +4,6 @@ const bodyParser = require('body-parser') const PRODUCT_SERVICE_URL = (process.env.VUE_APP_PRODUCT_SERVICE_URL || "http://172.19.0.2:3002/") const MAKELINE_SERVICE_URL = (process.env.VUE_APP_MAKELINE_SERVICE_URL || "http://172.19.0.6:3001/") -const AI_SERVICE_URL = (process.env.VUE_APP_AI_SERVICE_URL || "http://172.19.0.6:5001/") module.exports = defineConfig({ transpileDependencies: true, @@ -141,7 +140,7 @@ module.exports = defineConfig({ // Get AI service health devServer.app.get('/ai/health', (_, res) => { - fetch(`${AI_SERVICE_URL}health`) + fetch(`${PRODUCT_SERVICE_URL}/ai/health`) .then(response => { if (response.status === 200) { res.send(response.json()); @@ -161,7 +160,7 @@ module.exports = defineConfig({ const product = req.body console.log(product) - fetch(`${AI_SERVICE_URL}generate/description`, { + fetch(`${PRODUCT_SERVICE_URL}/ai/generate/description`, { method: 'POST', body: JSON.stringify(product), headers: { 'Content-Type': 'application/json' } diff --git a/src/store-front/Dockerfile b/src/store-front/Dockerfile index 6f52b8d9..76208391 100644 --- a/src/store-front/Dockerfile +++ b/src/store-front/Dockerfile @@ -3,9 +3,6 @@ FROM node:18.16.0-alpine as builder WORKDIR /app -# Set the build argument for the app version number -ARG APP_VERSION=0.1.0 - # Copy package.json and package-lock.json to the container COPY package*.json ./ @@ -15,24 +12,26 @@ RUN npm install # Copy the rest of the app source code to the container COPY . . -# Expose the port the app listens on -EXPOSE 80 +# Build the app +RUN npm run build -# Set the environment variable for the app version number -ENV APP_VERSION=$APP_VERSION +# Run the app on nginx +FROM nginx:stable-alpine as runner -# Start the app -CMD [ "npm", "run", "serve" ] +# Copy the build output to replace the default nginx contents +COPY --from=builder /app/dist /usr/share/nginx/html -# # Build the app -# RUN npm run build --mode production +# Expose the port the app listens on +EXPOSE 8080 -# # Run the app on nginx -# FROM nginx:stable-alpine as runner -# WORKDIR /app +# Set the build argument for the app version number +ARG APP_VERSION=0.1.0 -# # Copy the build output to replace the default nginx contents -# COPY --from=builder /app/dist /app +# Set the environment variable for the app version number +ENV APP_VERSION=$APP_VERSION + +# Copy the nginx configuration template to the container +COPY nginx.conf /etc/nginx/conf.d/nginx.conf.template -# # Copy the nginx configuration -# COPY nginx.conf /etc/nginx/nginx.conf \ No newline at end of file +# Start the app +CMD ["sh", "-c", "envsubst '${APP_VERSION}' < /etc/nginx/conf.d/nginx.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"] diff --git a/src/store-front/docker-compose.yml b/src/store-front/docker-compose.yml index 5e3cb214..b5dd1769 100644 --- a/src/store-front/docker-compose.yml +++ b/src/store-front/docker-compose.yml @@ -19,14 +19,14 @@ services: - ../../rabbitmq_enabled_plugins:/etc/rabbitmq/enabled_plugins networks: - backend_services - orderservice: + order-service: build: ../order-service - container_name: 'orderservice' + container_name: 'order-service' restart: always ports: - 3000:3000 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://orderservice:3000/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://order-service:3000/health"] interval: 30s timeout: 10s retries: 5 @@ -42,14 +42,14 @@ services: depends_on: rabbitmq: condition: service_healthy - productservice: + product-service: build: ../product-service - container_name: 'productservice' + container_name: 'product-service' restart: always ports: - 3002:3002 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://productservice:3002/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://product-service:3002/health"] interval: 30s timeout: 10s retries: 5 diff --git a/src/store-front/nginx.conf b/src/store-front/nginx.conf index 57e735ad..2a823203 100644 --- a/src/store-front/nginx.conf +++ b/src/store-front/nginx.conf @@ -1,32 +1,34 @@ -# Ref: https://cli.vuejs.org/guide/deployment.html#docker-nginx - -user nginx; -worker_processes 1; -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; -events { - worker_connections 1024; -} -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - access_log /var/log/nginx/access.log main; - sendfile on; - keepalive_timeout 65; - server { - listen 80; +server { + listen 8080; + listen [::]:8080; server_name localhost; + + #access_log /var/log/nginx/host.access.log main; + location / { - root /app; - index index.html; - try_files $uri $uri/ /index.html; + root /usr/share/nginx/html; + index index.html index.htm; } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # error_page 500 502 503 504 /50x.html; location = /50x.html { - root /usr/share/nginx/html; + root /usr/share/nginx/html; + } + + location /health { + default_type application/json; + return 200 '{"status":"ok","version":"${APP_VERSION}"}'; + } + + location /order { + proxy_pass http://order-service:3000/; + } + + location /products { + proxy_pass http://product-service:3002/; } - } } \ No newline at end of file diff --git a/src/virtual-customer/docker-compose.yml b/src/virtual-customer/docker-compose.yml index 2f43a5fa..e686f79c 100644 --- a/src/virtual-customer/docker-compose.yml +++ b/src/virtual-customer/docker-compose.yml @@ -19,14 +19,14 @@ services: - ../../rabbitmq_enabled_plugins:/etc/rabbitmq/enabled_plugins networks: - backend_services - orderservice: + order-service: build: ../order-service - container_name: 'orderservice' + container_name: 'order-service' restart: always ports: - 3000:3000 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://orderservice:3000/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://order-service:3000/health"] interval: 30s timeout: 10s retries: 5 diff --git a/src/virtual-worker/docker-compose.yml b/src/virtual-worker/docker-compose.yml index 61fb6734..d16db15f 100644 --- a/src/virtual-worker/docker-compose.yml +++ b/src/virtual-worker/docker-compose.yml @@ -32,14 +32,14 @@ services: - ../../rabbitmq_enabled_plugins:/etc/rabbitmq/enabled_plugins networks: - backend_services - orderservice: + order-service: build: ../order-service - container_name: 'orderservice' + container_name: 'order-service' restart: always ports: - 3000:3000 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://orderservice:3000/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://order-service:3000/health"] interval: 30s timeout: 10s retries: 5 @@ -55,14 +55,14 @@ services: depends_on: rabbitmq: condition: service_healthy - makelineservice: + makeline-service: build: ../makeline-service - container_name: 'makelineservice' + container_name: 'makeline-service' restart: always ports: - 3001:3001 healthcheck: - test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://makelineservice:3001/health"] + test: ["CMD", "wget", "-O", "/dev/null", "-q", "http://makeline-service:3001/health"] interval: 30s timeout: 10s retries: 5 @@ -81,17 +81,17 @@ services: condition: service_healthy mongodb: condition: service_healthy - virtualcustomer: + virtual-customer: build: ../virtual-customer - container_name: 'virtualcustomer' + container_name: 'virtual-customer' restart: always environment: - - ORDER_SERVICE_URL=http://orderservice:3000/ + - ORDER_SERVICE_URL=http://order-service:3000/ - ORDERS_PER_HOUR=3600 networks: - backend_services depends_on: - orderservice: + order-service: condition: service_healthy networks: backend_services: