diff --git a/.dockerignore b/.dockerignore index dd3d41423..5fbf98f1e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,7 +7,6 @@ docker-compose*.yml docker-compose.dcproj *.sln -!eShopOnContainers-ServicesAndWebApps.sln *.md hosts LICENSE @@ -31,4 +30,13 @@ cli-linux **/wwwroot/lib/* global.json **/appsettings.localhost.json -src/Web/WebSPA/wwwroot/ \ No newline at end of file +src/Web/WebSPA/wwwroot/ +packages/ +csproj-files/ +test-results/ +TestResults/ +src/Mobile/ +src/Web/Catalog.WebForms/ +src/Web/WebMonolithic/ +src/BuildingBlocks/CommandBus/ +src/Services/Marketing/Infrastructure/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 69800e3b7..f3fdf2b8f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,9 @@ bld/ # Visual Studio 2015 cache/options directory .vs/ +# Dockerfile projects folder for restore-packages script +csproj-files/ + # .js files created on build: src/Web/WebMVC/wwwroot/js/site* @@ -42,6 +45,8 @@ src/Web/WebMVC/wwwroot/js/site* *.VisualState.xml TestResult.xml +tests-results/ + # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ @@ -269,4 +274,9 @@ pub/ .mfractor # Ignore HealthCheckdb -*healthchecksdb* \ No newline at end of file +*healthchecksdb* + +# Ignores all extra inf.yaml and app.yaml that are copied by prepare-devspaces.ps1 +src/**/app.yaml +src/**/inf.yaml + diff --git a/README.md b/README.md index 6fceb20ee..b7f92ffa0 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,25 @@ -# eShopOnContainers - Microservices Architecture and Containers based Reference Application (**BETA state** - Visual Studio 2017 and CLI environments compatible) +# eShopOnContainers - Microservices Architecture and Containers based Reference Application (**BETA state** - Visual Studio and CLI environments compatible) Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers. ## Linux Build Status for 'dev' branch Dev branch contains the latest "stable" code, and their images are tagged with `:dev` in our [Docker Hub](https://cloud.docker.com/u/eshop/repository/list): -Api Gateways base image +| Basket API | Catalog API | Identity API | Location API | +| ------------- | ------------- | ------------- | ------------- | +| [![Basket API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/basket?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=199&branchName=dev) | [![Catalog API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/catalog?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=197&branchName=dev) | [![Identity API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/identity?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=200&branchName=dev) | [![Location API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/location?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=202&branchName=dev) | -[![Api Gateways base image](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/apigws?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=201&branchName=dev) +| Marketing API | Ordering API | Payment API | Api Gateways base image | +| ------------- | ------------- | ------------- | ------------- | +| [![Marketing API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/marketing?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=203&branchName=dev) | [![Ordering API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/ordering?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=198&branchName=dev) | [![Payment API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/payment?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=205&branchName=dev) | [![Api Gateways base image](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/apigws?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=201&branchName=dev) -Basket API - -[![Basket API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/basket?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=199&branchName=dev) - -Catalog API - -[![Catalog API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/catalog?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=197&branchName=dev) - -Identity API - -[![Identity API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/identity?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=200&branchName=dev) - -Location API - -[![Location API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/location?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=202&branchName=dev) - -Marketing API - -[![Marketing API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/marketing?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=203&branchName=dev) - -Ordering API - -[![Ordering API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/ordering?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=198&branchName=dev) - -Payment API - -[![Payment API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/payment?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=205&branchName=dev) - -Webhooks API - -[![Webhooks API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webhooks?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=207&branchName=dev) - -Web Shopping Aggregator - -[![Web Shopping Aggregator](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/web-shopping-agg?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=206&branchName=dev) - -Mobile Shopping Aggregator - -[![Mobile Shopping Aggregator](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/mobile-shopping-agg?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=204&branchName=dev) - -Webbhooks demo client - -[![Webhooks demo client](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webhooks-client?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=208&branchName=dev) - -WebMVC Client - -[![WebMVC Client](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webmvc?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=209&branchName=dev) - -WebSPA Client - -[![WebSPA Client](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webspa?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=210&branchName=dev) - -Web Status - -[![Web Status](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webstatus?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=211&branchName=dev) +| Web Shopping Aggregator | Mobile Shopping Aggregator | WebMVC Client | WebSPA Client | +| ------------- | ------------- | ------------- | ------------- | +| [![Web Shopping Aggregator](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/web-shopping-agg?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=206&branchName=dev) | [![Mobile Shopping Aggregator](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/mobile-shopping-agg?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=204&branchName=dev) | [![WebMVC Client](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webmvc?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=209&branchName=dev) | [![WebSPA Client](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webspa?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=210&branchName=dev) | +| Web Status | Webhooks API | Webbhooks demo client | +| ------------- | ------------- | ------------- | + [![Web Status](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webstatus?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=211&branchName=dev) | [![Webhooks API](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webhooks?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=207&branchName=dev) | [![Webhooks demo client](https://msftdevtools.visualstudio.com/eShopOnContainers/_apis/build/status/microservices/webhooks-client?branchName=dev)](https://msftdevtools.visualstudio.com/eShopOnContainers/_build/latest?definitionId=208&branchName=dev) | ## IMPORTANT NOTES! **You can use either the latest version of Visual Studio or simply Docker CLI and .NET CLI for Windows, Mac and Linux**. @@ -174,7 +129,7 @@ Finally, those microservices are consumed by multiple client web and mobile apps ## Setting up your development environment for eShopOnContainers -### Visual Studio 2017 and Windows based +### Visual Studio 2017 (or above) and Windows based This is the more straightforward way to get started: https://github.com/dotnet-architecture/eShopOnContainers/wiki/02.-Setting-eShopOnContainers-in-a-Visual-Studio-2017-environment @@ -194,5 +149,5 @@ As mentioned, we'd appreciate your feedback, improvements and ideas. You can create new issues at the issues section, do pull requests and/or send emails to **eshop_feedback@service.microsoft.com** ## Questions -[QUESTION] Answer +1 if the solution is working for you (Through VS2017 or CLI environment): +[QUESTION] Answer +1 if the solution is working for you (Through VS or CLI environment): https://github.com/dotnet/eShopOnContainers/issues/107 diff --git a/build/azure-devops/apigws/azure-pipelines.yml b/build/azure-devops/apigws/azure-pipelines.yml index d2f4708f6..0fe398c73 100644 --- a/build/azure-devops/apigws/azure-pipelines.yml +++ b/build/azure-devops/apigws/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -17,34 +15,71 @@ trigger: exclude: - src/ApiGateways/Mobile.Bff.Shopping/aggregator/* - src/ApiGateways/Web.Bff.Shopping/aggregator/* -steps: -- task: DockerCompose@0 - displayName: Compose build apigws - inputs: - dockerComposeCommand: 'build mobileshoppingapigw mobilemarketingapigw webshoppingapigw webmarketingapigw' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push apigws - inputs: - dockerComposeCommand: 'push mobileshoppingapigw mobilemarketingapigw webshoppingapigw webmarketingapigw' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build apigws + inputs: + dockerComposeCommand: 'build mobileshoppingapigw mobilemarketingapigw webshoppingapigw webmarketingapigw' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push apigws + inputs: + dockerComposeCommand: 'push mobileshoppingapigw mobilemarketingapigw webshoppingapigw webmarketingapigw' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build apigws + inputs: + dockerComposeCommand: 'build mobileshoppingapigw mobilemarketingapigw webshoppingapigw webmarketingapigw' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push apigws + inputs: + dockerComposeCommand: 'push mobileshoppingapigw mobilemarketingapigw webshoppingapigw webmarketingapigw' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: ocelotapigw + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) diff --git a/build/azure-devops/basket-api/azure-pipelines.yml b/build/azure-devops/basket-api/azure-pipelines.yml index 6d94c5918..6bd7e52da 100644 --- a/build/azure-devops/basket-api/azure-pipelines.yml +++ b/build/azure-devops/basket-api/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -12,34 +10,71 @@ trigger: - src/BuildingBlocks/* - src/Services/Basket/* - k8s/helm/basket-api/* -steps: -- task: DockerCompose@0 - displayName: Compose build basket - inputs: - dockerComposeCommand: 'build basket.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push basket - inputs: - dockerComposeCommand: 'push basket.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build basket + inputs: + dockerComposeCommand: 'build basket.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push basket + inputs: + dockerComposeCommand: 'push basket.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build basket + inputs: + dockerComposeCommand: 'build basket.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push basket + inputs: + dockerComposeCommand: 'push basket.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: basket.api + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) diff --git a/build/azure-devops/catalog-api/azure-pipelines.yml b/build/azure-devops/catalog-api/azure-pipelines.yml index d277d4777..03c588e8f 100644 --- a/build/azure-devops/catalog-api/azure-pipelines.yml +++ b/build/azure-devops/catalog-api/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -12,34 +10,71 @@ trigger: - src/BuildingBlocks/* - src/Services/Catalog/* - k8s/helm/catalog-api/* -steps: -- task: DockerCompose@0 - displayName: Compose build catalog - inputs: - dockerComposeCommand: 'build catalog.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push catalog - inputs: - dockerComposeCommand: 'push catalog.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build catalog + inputs: + dockerComposeCommand: 'build catalog.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push catalog + inputs: + dockerComposeCommand: 'push catalog.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindow + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build catalog + inputs: + dockerComposeCommand: 'build catalog.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push catalog + inputs: + dockerComposeCommand: 'push catalog.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: catalog.api + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) diff --git a/build/azure-devops/identity-api/azure-pipelines.yml b/build/azure-devops/identity-api/azure-pipelines.yml index 454c03d16..5e48bbccc 100644 --- a/build/azure-devops/identity-api/azure-pipelines.yml +++ b/build/azure-devops/identity-api/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -12,34 +10,71 @@ trigger: - src/BuildingBlocks/* - src/Services/Identity/* - k8s/helm/identity-api/* -steps: -- task: DockerCompose@0 - displayName: Compose build identity - inputs: - dockerComposeCommand: 'build identity.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push identity - inputs: - dockerComposeCommand: 'push identity.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build identity + inputs: + dockerComposeCommand: 'build identity.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push identity + inputs: + dockerComposeCommand: 'push identity.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build identity + inputs: + dockerComposeCommand: 'build identity.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push identity + inputs: + dockerComposeCommand: 'push identity.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: identity.api + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) diff --git a/build/azure-devops/location-api/azure-pipelines.yml b/build/azure-devops/location-api/azure-pipelines.yml index ab3d31b3f..adc814863 100644 --- a/build/azure-devops/location-api/azure-pipelines.yml +++ b/build/azure-devops/location-api/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -11,35 +9,72 @@ trigger: include: - src/BuildingBlocks/* - src/Services/Location/* - - k8s/helm/locations-api/* -steps: -- task: DockerCompose@0 - displayName: Compose build locations - inputs: - dockerComposeCommand: 'build locations.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push locations - inputs: - dockerComposeCommand: 'push locations.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm + - k8s/helm/locations-api/* +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build locations + inputs: + dockerComposeCommand: 'build locations.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push locations + inputs: + dockerComposeCommand: 'push locations.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build locations + inputs: + dockerComposeCommand: 'build locations.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push locations + inputs: + dockerComposeCommand: 'push locations.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: locations.api + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) diff --git a/build/azure-devops/marketing-api/azure-pipelines.yml b/build/azure-devops/marketing-api/azure-pipelines.yml index 193a0cccf..59fe1d843 100644 --- a/build/azure-devops/marketing-api/azure-pipelines.yml +++ b/build/azure-devops/marketing-api/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -11,35 +9,72 @@ trigger: include: - src/BuildingBlocks/* - src/Services/Marketing/* - - k8s/helm/marketing-api/* -steps: -- task: DockerCompose@0 - displayName: Compose build marketing - inputs: - dockerComposeCommand: 'build marketing.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push marketing - inputs: - dockerComposeCommand: 'push marketing.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm + - k8s/helm/marketing-api/* +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build marketing + inputs: + dockerComposeCommand: 'build marketing.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push marketing + inputs: + dockerComposeCommand: 'push marketing.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build marketing + inputs: + dockerComposeCommand: 'build marketing.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push marketing + inputs: + dockerComposeCommand: 'push marketing.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: marketing.api + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) diff --git a/build/azure-devops/mobile-shopping-agg/azure-pipelines.yml b/build/azure-devops/mobile-shopping-agg/azure-pipelines.yml index 6fb0018a1..029386084 100644 --- a/build/azure-devops/mobile-shopping-agg/azure-pipelines.yml +++ b/build/azure-devops/mobile-shopping-agg/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -10,35 +8,73 @@ trigger: paths: include: - src/ApiGateways/Mobile.Bff.Shopping/aggregator/* - - k8s/helm/mobileshoppingagg/* -steps: -- task: DockerCompose@0 - displayName: Compose build mobileshoppingagg - inputs: - dockerComposeCommand: 'build mobileshoppingagg' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push mobileshoppingagg - inputs: - dockerComposeCommand: 'push mobileshoppingagg' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm + - k8s/helm/mobileshoppingagg/* +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build mobileshoppingagg + inputs: + dockerComposeCommand: 'build mobileshoppingagg' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push mobileshoppingagg + inputs: + dockerComposeCommand: 'push mobileshoppingagg' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build mobileshoppingagg + inputs: + dockerComposeCommand: 'build mobileshoppingagg' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push mobileshoppingagg + inputs: + dockerComposeCommand: 'push mobileshoppingagg' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: mobileshoppingagg + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) + diff --git a/build/azure-devops/multiarch.yaml b/build/azure-devops/multiarch.yaml new file mode 100644 index 000000000..919eb9595 --- /dev/null +++ b/build/azure-devops/multiarch.yaml @@ -0,0 +1,27 @@ +parameters: + image: '' + branch: '' + registryEndpoint: '' + +jobs: +- job: manifest + pool: + vmImage: 'Ubuntu 16.04' + steps: + - task: Docker@1 + displayName: Docker Login + inputs: + command: login + containerregistrytype: 'Container Registry' + dockerRegistryEndpoint: ${{ parameters.registryEndpoint }} + - bash: | + mkdir -p ~/.docker + echo '{ "experimental": "enabled" }' > ~/.docker/config.json + docker --config ~/.docker manifest create eshop/${{ parameters.image }}:${{ parameters.branch }} eshop/${{ parameters.image }}:linux-${{ parameters.branch }} eshop/${{ parameters.image }}:win-${{ parameters.branch }} + docker --config ~/.docker manifest create eshop/${{ parameters.image }}:latest eshop/${{ parameters.image }}:linux-latest eshop/${{ parameters.image }}:win-latest + docker --config ~/.docker push eshop/${{ parameters.image }}:${{ parameters.branch }} + docker --config ~/.docker push eshop/${{ parameters.image }}:latest + displayName: 'Create Manifest' + dependsOn: + - BuildWindows + - BuildLinux diff --git a/build/azure-devops/ordering-api/azure-pipelines.yml b/build/azure-devops/ordering-api/azure-pipelines.yml index ef0b17a32..47cc0370e 100644 --- a/build/azure-devops/ordering-api/azure-pipelines.yml +++ b/build/azure-devops/ordering-api/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -14,34 +12,71 @@ trigger: - k8s/helm/ordering-api/* - k8s/helm/ordering-backgroundtasks/* - k8s/helm/ordering-signalrhub/* -steps: -- task: DockerCompose@0 - displayName: Compose build ordering - inputs: - dockerComposeCommand: 'build ordering.api ordering.backgroundtasks ordering.signalrhub' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push ordering - inputs: - dockerComposeCommand: 'push ordering.api ordering.backgroundtasks ordering.signalrhub' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build ordering + inputs: + dockerComposeCommand: 'build ordering.api ordering.backgroundtasks ordering.signalrhub' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push ordering + inputs: + dockerComposeCommand: 'push ordering.api ordering.backgroundtasks ordering.signalrhub' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build ordering + inputs: + dockerComposeCommand: 'build ordering.api ordering.backgroundtasks ordering.signalrhub' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push ordering + inputs: + dockerComposeCommand: 'push ordering.api ordering.backgroundtasks ordering.signalrhub' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: ordering.api + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) \ No newline at end of file diff --git a/build/azure-devops/payment-api/azure-pipelines.yml b/build/azure-devops/payment-api/azure-pipelines.yml index 8518c8841..f472470cb 100644 --- a/build/azure-devops/payment-api/azure-pipelines.yml +++ b/build/azure-devops/payment-api/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -12,34 +10,71 @@ trigger: - src/BuildingBlocks/* - src/Services/Payment/* - k8s/helm/payment-api/* -steps: -- task: DockerCompose@0 - displayName: Compose build payment - inputs: - dockerComposeCommand: 'build payment.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push payment - inputs: - dockerComposeCommand: 'push payment.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build payment + inputs: + dockerComposeCommand: 'build payment.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push payment + inputs: + dockerComposeCommand: 'push payment.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build payment + inputs: + dockerComposeCommand: 'build payment.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push payment + inputs: + dockerComposeCommand: 'push payment.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: payment.api + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) \ No newline at end of file diff --git a/build/azure-devops/web-shopping-agg/azure-pipelines.yml b/build/azure-devops/web-shopping-agg/azure-pipelines.yml index 70a4df950..7ba05c4f5 100644 --- a/build/azure-devops/web-shopping-agg/azure-pipelines.yml +++ b/build/azure-devops/web-shopping-agg/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -10,35 +8,72 @@ trigger: paths: include: - src/ApiGateways/Web.Bff.Shopping/aggregator/* - - k8s/helm/webshoppingagg/* -steps: -- task: DockerCompose@0 - displayName: Compose build webshoppingagg - inputs: - dockerComposeCommand: 'build webshoppingagg' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push webshoppingagg - inputs: - dockerComposeCommand: 'push webshoppingagg' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm + - k8s/helm/webshoppingagg/* +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build webshoppingagg + inputs: + dockerComposeCommand: 'build webshoppingagg' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push webshoppingagg + inputs: + dockerComposeCommand: 'push webshoppingagg' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build webshoppingagg + inputs: + dockerComposeCommand: 'build webshoppingagg' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push webshoppingagg + inputs: + dockerComposeCommand: 'push webshoppingagg' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: webshoppingagg + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) \ No newline at end of file diff --git a/build/azure-devops/webhooks-api/azure-pipelines.yml b/build/azure-devops/webhooks-api/azure-pipelines.yml index b48948111..d30ce074a 100644 --- a/build/azure-devops/webhooks-api/azure-pipelines.yml +++ b/build/azure-devops/webhooks-api/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -11,35 +9,72 @@ trigger: include: - src/BuildingBlocks/* - src/Services/Webhooks/* - - k8s/helm/webhooks-api/* -steps: -- task: DockerCompose@0 - displayName: Compose build webhooks - inputs: - dockerComposeCommand: 'build webhooks.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push webhooks - inputs: - dockerComposeCommand: 'push webhooks.api' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm + - k8s/helm/webhooks-api/* +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build webhooks + inputs: + dockerComposeCommand: 'build webhooks.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push webhooks + inputs: + dockerComposeCommand: 'push webhooks.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build webhooks + inputs: + dockerComposeCommand: 'build webhooks.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push webhooks + inputs: + dockerComposeCommand: 'push webhooks.api' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: webhooks.api + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) \ No newline at end of file diff --git a/build/azure-devops/webhooks-client/azure-pipelines.yml b/build/azure-devops/webhooks-client/azure-pipelines.yml index 71e3bbe16..30ad411e3 100644 --- a/build/azure-devops/webhooks-client/azure-pipelines.yml +++ b/build/azure-devops/webhooks-client/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -11,35 +9,72 @@ trigger: include: - src/BuildingBlocks/* - src/Web/WebhookClient/* - - k8s/helm/webhooks-web/* -steps: -- task: DockerCompose@0 - displayName: Compose build webhooks.client - inputs: - dockerComposeCommand: 'build webhooks.client' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push webhooks.client - inputs: - dockerComposeCommand: 'push webhooks.client' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm + - k8s/helm/webhooks-web/* +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build webhooks.client + inputs: + dockerComposeCommand: 'build webhooks.client' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push webhooks.client + inputs: + dockerComposeCommand: 'push webhooks.client' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build webhooks.client + inputs: + dockerComposeCommand: 'build webhooks.client' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push webhooks.client + inputs: + dockerComposeCommand: 'push webhooks.client' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName)v + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: webhooks.client + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) \ No newline at end of file diff --git a/build/azure-devops/webmvc/azure-pipelines.yml b/build/azure-devops/webmvc/azure-pipelines.yml index 66b8518fa..69fea5360 100644 --- a/build/azure-devops/webmvc/azure-pipelines.yml +++ b/build/azure-devops/webmvc/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -11,35 +9,72 @@ trigger: include: - src/BuildingBlocks/* - src/Web/WebMVC/* - - k8s/helm/webmvc/* -steps: -- task: DockerCompose@0 - displayName: Compose build webmvc - inputs: - dockerComposeCommand: 'build webmvc' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push webmvc - inputs: - dockerComposeCommand: 'push webmvc' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm + - k8s/helm/webmvc/* +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build webmvc + inputs: + dockerComposeCommand: 'build webmvc' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push webmvc + inputs: + dockerComposeCommand: 'push webmvc' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build webmvc + inputs: + dockerComposeCommand: 'build webmvc' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push webmvc + inputs: + dockerComposeCommand: 'push webmvc' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: webmvc + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) \ No newline at end of file diff --git a/build/azure-devops/webspa/azure-pipelines.yml b/build/azure-devops/webspa/azure-pipelines.yml index eee8cd25d..ea3e8a232 100644 --- a/build/azure-devops/webspa/azure-pipelines.yml +++ b/build/azure-devops/webspa/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -12,34 +10,73 @@ trigger: - src/BuildingBlocks/* - src/Web/WebSPA/* - k8s/helm/webspa/* -steps: -- task: DockerCompose@0 - displayName: Compose build webspa - inputs: - dockerComposeCommand: 'build webspa' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push webspa - inputs: - dockerComposeCommand: 'push webspa' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build webspa + inputs: + dockerComposeCommand: 'build webspa' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push webspa + inputs: + dockerComposeCommand: 'push webspa' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build webspa + inputs: + dockerComposeCommand: 'build webspa' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + NODE_IMAGE=stefanscherer/node-windows:8.11 + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push webspa + inputs: + dockerComposeCommand: 'push webspa' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + NODE_IMAGE=stefanscherer/node-windows:8.11 +- template: ../multiarch.yaml + parameters: + image: webspa + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) \ No newline at end of file diff --git a/build/azure-devops/webstatus/azure-pipelines.yml b/build/azure-devops/webstatus/azure-pipelines.yml index 311c457e2..34f79694a 100644 --- a/build/azure-devops/webstatus/azure-pipelines.yml +++ b/build/azure-devops/webstatus/azure-pipelines.yml @@ -1,5 +1,3 @@ -pool: - vmImage: 'ubuntu-16.04' variables: registryEndpoint: eshop-registry trigger: @@ -11,35 +9,72 @@ trigger: include: - src/BuildingBlocks/* - src/Web/WebStatus/* - - k8s/helm/webstatus/* -steps: -- task: DockerCompose@0 - displayName: Compose build webstatus - inputs: - dockerComposeCommand: 'build webstatus' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: DockerCompose@0 - displayName: Compose push webstatus - inputs: - dockerComposeCommand: 'push webstatus' - containerregistrytype: Container Registry - dockerRegistryEndpoint: $(registryEndpoint) - dockerComposeFile: docker-compose.yml - qualifyImageNames: true - projectName: "" - dockerComposeFileArgs: | - TAG=$(Build.SourceBranchName) -- task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory)/k8s/helm - targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm - artifactName: helm + - k8s/helm/webstatus/* +jobs: +- job: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: DockerCompose@0 + displayName: Compose build webstatus + inputs: + dockerComposeCommand: 'build webstatus' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: DockerCompose@0 + displayName: Compose push webstatus + inputs: + dockerComposeCommand: 'push webstatus' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)/k8s/helm + targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm + artifactName: helm +- job: BuildWindows + pool: + vmImage: 'windows-2019' + steps: + - task: DockerCompose@0 + displayName: Compose build webstatus + inputs: + dockerComposeCommand: 'build webstatus' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win + - task: DockerCompose@0 + displayName: Compose push webstatus + inputs: + dockerComposeCommand: 'push webstatus' + containerregistrytype: Container Registry + dockerRegistryEndpoint: $(registryEndpoint) + dockerComposeFile: docker-compose.yml + qualifyImageNames: true + projectName: "" + dockerComposeFileArgs: | + TAG=$(Build.SourceBranchName) + PLATFORM=win +- template: ../multiarch.yaml + parameters: + image: webstatus + branch: $(Build.SourceBranchName) + registryEndpoint: $(registryEndpoint) \ No newline at end of file diff --git a/build/multiarch-manifests/create-manifests.ps1 b/build/multiarch-manifests/create-manifests.ps1 new file mode 100644 index 000000000..cc7f05194 --- /dev/null +++ b/build/multiarch-manifests/create-manifests.ps1 @@ -0,0 +1,26 @@ +Param( + [parameter(Mandatory=$true)][string]$registry +) + +if ([String]::IsNullOrEmpty($registry)) { + Write-Host "Registry must be set to docker registry to use" -ForegroundColor Red + exit 1 +} + +Write-Host "This script creates the local manifests, for pushing the multi-arch manifests" -ForegroundColor Yellow +Write-Host "Tags used are linux-master, win-master, linux-dev, win-dev, linux-latest, win-latest" -ForegroundColor Yellow +Write-Host "Multiarch images tags will be master, dev, latest" -ForegroundColor Yellow + + +$services = "identity.api", "basket.api", "catalog.api", "ordering.api", "ordering.backgroundtasks", "marketing.api", "payment.api", "locations.api", "webhooks.api", "ocelotapigw", "mobileshoppingagg", "webshoppingagg", "ordering.signalrhub", "webstatus", "webspa", "webmvc", "webhooks.client" + +foreach ($svc in $services) { + Write-Host "Creating manifest for $svc and tags :latest, :master, and :dev" + docker manifest create $registry/${svc}:master $registry/${svc}:linux-master $registry/${svc}:win-master + docker manifest create $registry/${svc}:dev $registry/${svc}:linux-dev $registry/${svc}:win-dev + docker manifest create $registry/${svc}:latest $registry/${svc}:linux-latest $registry/${svc}:win-latest + Write-Host "Pushing manifest for $svc and tags :latest, :master, and :dev" + docker manifest push $registry/${svc}:latest + docker manifest push $registry/${svc}:dev + docker manifest push $registry/${svc}:master +} \ No newline at end of file diff --git a/cli-windows/set-dockernat-networkategory-to-private.ps1 b/cli-windows/set-dockernat-networkategory-to-private.ps1 new file mode 100644 index 000000000..6614c8e8a --- /dev/null +++ b/cli-windows/set-dockernat-networkategory-to-private.ps1 @@ -0,0 +1,2 @@ + #Requires -RunAsAdministrator + Get-NetConnectionProfile | Where-Object { $_.InterfaceAlias -match "(DockerNAT)" } | ForEach-Object { Set-NetConnectionProfile -InterfaceIndex $_.InterfaceIndex -NetworkCategory Private } diff --git a/docker-compose.elk.yml b/docker-compose.elk.yml new file mode 100644 index 000000000..04e6c8a05 --- /dev/null +++ b/docker-compose.elk.yml @@ -0,0 +1,37 @@ +version: '3.4' + +services: + + elasticsearch: + build: + context: elk/elasticsearch/ + volumes: + - ./elk/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro + ports: + - "9200:9200" + - "9300:9300" + environment: + ES_JAVA_OPTS: "-Xmx256m -Xms256m" + + logstash: + build: + context: elk/logstash/ + volumes: + - ./elk/logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro + - ./elk/logstash/pipeline:/usr/share/logstash/pipeline:ro + ports: + - "8080:8080" + environment: + LS_JAVA_OPTS: "-Xmx256m -Xms256m" + depends_on: + - elasticsearch + + kibana: + build: + context: elk/kibana/ + volumes: + - ./elk/kibana/config/:/usr/share/kibana/config:ro + ports: + - "5601:5601" + depends_on: + - elasticsearch \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml index e59a9a2e6..563d712c1 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -110,6 +110,8 @@ services: - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} - UseLoadTest=${USE_LOADTEST:-False} + - Serilog__MinimumLevel__Override__Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ=Verbose + - Serilog__MinimumLevel__Override__Ordering.API=Verbose ports: - "5102:80" # Important: In a production environment your should remove the external port (5102) kept here for microservice debugging purposes. # The API Gateway redirects and access through the internal port (80). @@ -130,6 +132,7 @@ services: - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} - UseLoadTest=${USE_LOADTEST:-False} + - Serilog__MinimumLevel__Override__Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ=Verbose ports: - "5111:80" @@ -168,6 +171,8 @@ services: - AzureServiceBusEnabled=False - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} + - Serilog__MinimumLevel__Override__Payment.API.IntegrationEvents.EventHandling=Verbose + - Serilog__MinimumLevel__Override__Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ=Verbose ports: - "5108:80" # Important: In a production environment your should remove the external port (5108) kept here for microservice debugging purposes. # The API Gateway redirects and access through the internal port (80). @@ -326,40 +331,40 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - - HealthChecks-UI__HealthChecks__1__Name=WebMVC HTTP Check - - HealthChecks-UI__HealthChecks__1__Uri=http://webmvc/hc - - HealthChecks-UI__HealthChecks__2__Name=WebSPA HTTP Check - - HealthChecks-UI__HealthChecks__2__Uri=http://webspa/hc - - HealthChecks-UI__HealthChecks__3__Name=Web Shopping Aggregator GW HTTP Check - - HealthChecks-UI__HealthChecks__3__Uri=http://webshoppingagg/hc - - HealthChecks-UI__HealthChecks__4__Name=Mobile Shopping Aggregator HTTP Check - - HealthChecks-UI__HealthChecks__4__Uri=http://mobileshoppingagg/hc - - HealthChecks-UI__HealthChecks__5__Name=Mobile Shopping API GW HTTP Check - - HealthChecks-UI__HealthChecks__5__Uri=http://mobileshoppingapigw/hc - - HealthChecks-UI__HealthChecks__6__Name=Mobile Marketing API GW HTTP Check - - HealthChecks-UI__HealthChecks__6__Uri=http://mobilemarketingapigw/hc - - HealthChecks-UI__HealthChecks__7__Name=Web Shopping API GW HTTP Check - - HealthChecks-UI__HealthChecks__7__Uri=http://webshoppingapigw/hc - - HealthChecks-UI__HealthChecks__8__Name=Web Marketing API GW HTTP Check - - HealthChecks-UI__HealthChecks__8__Uri=http://webmarketingapigw/hc - - HealthChecks-UI__HealthChecks__9__Name=Ordering HTTP Check - - HealthChecks-UI__HealthChecks__9__Uri=http://ordering.api/hc - - HealthChecks-UI__HealthChecks__10__Name=Ordering HTTP Background Check - - HealthChecks-UI__HealthChecks__10__Uri=http://ordering.backgroundtasks/hc - - HealthChecks-UI__HealthChecks__11__Name=Basket HTTP Check - - HealthChecks-UI__HealthChecks__11__Uri=http://basket.api/hc - - HealthChecks-UI__HealthChecks__12__Name=Catalog HTTP Check - - HealthChecks-UI__HealthChecks__12__Uri=http://catalog.api/hc - - HealthChecks-UI__HealthChecks__13__Name=Identity HTTP Check - - HealthChecks-UI__HealthChecks__13__Uri=http://identity.api/hc - - HealthChecks-UI__HealthChecks__14__Name=Marketing HTTP Check - - HealthChecks-UI__HealthChecks__14__Uri=http://marketing.api/hc - - HealthChecks-UI__HealthChecks__15__Name=Locations HTTP Check - - HealthChecks-UI__HealthChecks__15__Uri=http://locations.api/hc - - HealthChecks-UI__HealthChecks__16__Name=Payments HTTP Check - - HealthChecks-UI__HealthChecks__16__Uri=http://payment.api/hc - - HealthChecks-UI__HealthChecks__17__Name=Ordering SignalRHub HTTP Check - - HealthChecks-UI__HealthChecks__17__Uri=http://ordering.signalrhub/hc + - HealthChecks-UI__HealthChecks__0__Name=WebMVC HTTP Check + - HealthChecks-UI__HealthChecks__0__Uri=http://webmvc/hc + - HealthChecks-UI__HealthChecks__1__Name=WebSPA HTTP Check + - HealthChecks-UI__HealthChecks__1__Uri=http://webspa/hc + - HealthChecks-UI__HealthChecks__2__Name=Web Shopping Aggregator GW HTTP Check + - HealthChecks-UI__HealthChecks__2__Uri=http://webshoppingagg/hc + - HealthChecks-UI__HealthChecks__3__Name=Mobile Shopping Aggregator HTTP Check + - HealthChecks-UI__HealthChecks__3__Uri=http://mobileshoppingagg/hc + - HealthChecks-UI__HealthChecks__4__Name=Mobile Shopping API GW HTTP Check + - HealthChecks-UI__HealthChecks__4__Uri=http://mobileshoppingapigw/hc + - HealthChecks-UI__HealthChecks__5__Name=Mobile Marketing API GW HTTP Check + - HealthChecks-UI__HealthChecks__5__Uri=http://mobilemarketingapigw/hc + - HealthChecks-UI__HealthChecks__6__Name=Web Shopping API GW HTTP Check + - HealthChecks-UI__HealthChecks__6__Uri=http://webshoppingapigw/hc + - HealthChecks-UI__HealthChecks__7__Name=Web Marketing API GW HTTP Check + - HealthChecks-UI__HealthChecks__7__Uri=http://webmarketingapigw/hc + - HealthChecks-UI__HealthChecks__8__Name=Ordering HTTP Check + - HealthChecks-UI__HealthChecks__8__Uri=http://ordering.api/hc + - HealthChecks-UI__HealthChecks__9__Name=Ordering HTTP Background Check + - HealthChecks-UI__HealthChecks__9__Uri=http://ordering.backgroundtasks/hc + - HealthChecks-UI__HealthChecks__10__Name=Basket HTTP Check + - HealthChecks-UI__HealthChecks__10__Uri=http://basket.api/hc + - HealthChecks-UI__HealthChecks__11__Name=Catalog HTTP Check + - HealthChecks-UI__HealthChecks__11__Uri=http://catalog.api/hc + - HealthChecks-UI__HealthChecks__12__Name=Identity HTTP Check + - HealthChecks-UI__HealthChecks__12__Uri=http://identity.api/hc + - HealthChecks-UI__HealthChecks__13__Name=Marketing HTTP Check + - HealthChecks-UI__HealthChecks__13__Uri=http://marketing.api/hc + - HealthChecks-UI__HealthChecks__14__Name=Locations HTTP Check + - HealthChecks-UI__HealthChecks__14__Uri=http://locations.api/hc + - HealthChecks-UI__HealthChecks__15__Name=Payments HTTP Check + - HealthChecks-UI__HealthChecks__15__Uri=http://payment.api/hc + - HealthChecks-UI__HealthChecks__16__Name=Ordering SignalRHub HTTP Check + - HealthChecks-UI__HealthChecks__16__Uri=http://ordering.signalrhub/hc - OrderingBackgroundTasksUrl=http://ordering.backgroundtasks/hc - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} diff --git a/docker-compose.yml b/docker-compose.yml index 55d5b10e6..8950bdfe2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,7 @@ version: '3.4' services: + seq: image: datalust/seq:latest @@ -17,7 +18,7 @@ services: image: rabbitmq:3-management-alpine identity.api: - image: ${REGISTRY:-eshop}/identity.api:${TAG:-latest} + image: ${REGISTRY:-eshop}/identity.api:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Identity/Identity.API/Dockerfile @@ -25,7 +26,7 @@ services: - sql.data basket.api: - image: ${REGISTRY:-eshop}/basket.api:${TAG:-latest} + image: ${REGISTRY:-eshop}/basket.api:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Basket/Basket.API/Dockerfile @@ -35,7 +36,7 @@ services: - rabbitmq catalog.api: - image: ${REGISTRY:-eshop}/catalog.api:${TAG:-latest} + image: ${REGISTRY:-eshop}/catalog.api:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Catalog/Catalog.API/Dockerfile @@ -44,7 +45,7 @@ services: - rabbitmq ordering.api: - image: ${REGISTRY:-eshop}/ordering.api:${TAG:-latest} + image: ${REGISTRY:-eshop}/ordering.api:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Ordering/Ordering.API/Dockerfile @@ -53,7 +54,7 @@ services: - rabbitmq ordering.backgroundtasks: - image: ${REGISTRY:-eshop}/ordering.backgroundtasks:${TAG:-latest} + image: ${REGISTRY:-eshop}/ordering.backgroundtasks:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile @@ -62,7 +63,7 @@ services: - rabbitmq marketing.api: - image: ${REGISTRY:-eshop}/marketing.api:${TAG:-latest} + image: ${REGISTRY:-eshop}/marketing.api:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Marketing/Marketing.API/Dockerfile @@ -73,7 +74,7 @@ services: - rabbitmq payment.api: - image: ${REGISTRY:-eshop}/payment.api:${TAG:-latest} + image: ${REGISTRY:-eshop}/payment.api:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Payment/Payment.API/Dockerfile @@ -81,7 +82,7 @@ services: - rabbitmq locations.api: - image: ${REGISTRY:-eshop}/locations.api:${TAG:-latest} + image: ${REGISTRY:-eshop}/locations.api:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Location/Locations.API/Dockerfile @@ -90,7 +91,7 @@ services: - rabbitmq webhooks.api: - image: ${REGISTRY:-eshop}/webhooks.api:${TAG:-latest} + image: ${REGISTRY:-eshop}/webhooks.api:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Webhooks/Webhooks.API/Dockerfile @@ -98,7 +99,7 @@ services: - sql.data mobileshoppingapigw: - image: ${REGISTRY:-eshop}/ocelotapigw:${TAG:-latest} + image: ${REGISTRY:-eshop}/ocelotapigw:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile @@ -113,7 +114,7 @@ services: - basket.api mobilemarketingapigw: - image: ${REGISTRY:-eshop}/ocelotapigw:${TAG:-latest} + image: ${REGISTRY:-eshop}/ocelotapigw:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile @@ -128,7 +129,7 @@ services: - basket.api webshoppingapigw: - image: ${REGISTRY:-eshop}/ocelotapigw:${TAG:-latest} + image: ${REGISTRY:-eshop}/ocelotapigw:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile @@ -143,7 +144,7 @@ services: - basket.api webmarketingapigw: - image: ${REGISTRY:-eshop}/ocelotapigw:${TAG:-latest} + image: ${REGISTRY:-eshop}/ocelotapigw:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile @@ -158,7 +159,7 @@ services: - basket.api mobileshoppingagg: - image: ${REGISTRY:-eshop}/mobileshoppingagg:${TAG:-latest} + image: ${REGISTRY:-eshop}/mobileshoppingagg:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile @@ -173,7 +174,7 @@ services: - basket.api webshoppingagg: - image: ${REGISTRY:-eshop}/webshoppingagg:${TAG:-latest} + image: ${REGISTRY:-eshop}/webshoppingagg:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile @@ -188,7 +189,7 @@ services: - basket.api ordering.signalrhub: - image: ${REGISTRY:-eshop}/ordering.signalrhub:${TAG:-latest} + image: ${REGISTRY:-eshop}/ordering.signalrhub:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Services/Ordering/Ordering.SignalrHub/Dockerfile @@ -203,23 +204,25 @@ services: - basket.api webstatus: - image: ${REGISTRY:-eshop}/webstatus:${TAG:-latest} + image: ${REGISTRY:-eshop}/webstatus:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Web/WebStatus/Dockerfile webspa: - image: ${REGISTRY:-eshop}/webspa:${TAG:-latest} + image: ${REGISTRY:-eshop}/webspa:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Web/WebSPA/Dockerfile + args: + - NODE_IMAGE=${NODE_IMAGE:-node:8.11} # depends_on: # - webshoppingagg # - webshoppingapigw # - webmarketingapigw webmvc: - image: ${REGISTRY:-eshop}/webmvc:${TAG:-latest} + image: ${REGISTRY:-eshop}/webmvc:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Web/WebMVC/Dockerfile @@ -229,7 +232,7 @@ services: - webmarketingapigw webhooks.client: - image: ${REGISTRY:-eshop}/webhooks.client:${TAG:-latest} + image: ${REGISTRY:-eshop}/webhooks.client:${PLATFORM:-linux}-${TAG:-latest} build: context: . dockerfile: src/Web/WebhookClient/Dockerfile diff --git a/docker-scripts/linux/install-node.sh b/docker-scripts/linux/install-node.sh deleted file mode 100644 index 73407aae9..000000000 --- a/docker-scripts/linux/install-node.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -export NODE_DOWNLOAD_SHA 0e20787e2eda4cc31336d8327556ebc7417e8ee0a6ba0de96a09b0ec2b841f60 -curl -SL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz" --output nodejs.tar.gz \ - && echo "$NODE_DOWNLOAD_SHA nodejs.tar.gz" | sha256sum -c - \ - && tar -xzf "nodejs.tar.gz" -C /usr/local --strip-components=1 \ - && rm nodejs.tar.gz \ - && ln -s /usr/local/bin/node /usr/local/bin/nodejs diff --git a/docker-scripts/win/install-node.cmd b/docker-scripts/win/install-node.cmd deleted file mode 100644 index eaa4e356c..000000000 --- a/docker-scripts/win/install-node.cmd +++ /dev/null @@ -1,4 +0,0 @@ -set NODE_VERSION=8.11.1 -curl -SL "https://nodejs.org/dist/v%NODE_VERSION%/node-v%NODE_VERSION%-win-x64.zip" --output nodejs.zip -tar -xf nodejs.zip -C c:\ -setx PATH "%PATH%;c:\node-v%NODE_VERSION%-win-x64" \ No newline at end of file diff --git a/docs/MicrosoftAzure_StartGuide_Developers-old.pdf b/docs/MicrosoftAzure_StartGuide_Developers-old.pdf new file mode 100644 index 000000000..b843ec51c Binary files /dev/null and b/docs/MicrosoftAzure_StartGuide_Developers-old.pdf differ diff --git a/docs/MicrosoftAzure_StartGuide_Developers.pdf b/docs/MicrosoftAzure_StartGuide_Developers.pdf index b843ec51c..8d80c6d62 100644 Binary files a/docs/MicrosoftAzure_StartGuide_Developers.pdf and b/docs/MicrosoftAzure_StartGuide_Developers.pdf differ diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index 447b73073..882bca09f 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -142,9 +142,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payment.API", "src\Services EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Webhooks", "Webhooks", "{E0AA11C4-2873-461D-8F82-53392530FB7A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Webhooks.API", "src\Services\Webhooks\Webhooks.API\Webhooks.API.csproj", "{84E2016E-0435-44C6-8020-3D288AA38B2C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Webhooks.API", "src\Services\Webhooks\Webhooks.API\Webhooks.API.csproj", "{84E2016E-0435-44C6-8020-3D288AA38B2C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebhookClient", "src\Web\WebhookClient\WebhookClient.csproj", "{766D7E92-6AF0-476C-ADD5-282BF4D8C576}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebhookClient", "src\Web\WebhookClient\WebhookClient.csproj", "{766D7E92-6AF0-476C-ADD5-282BF4D8C576}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Devspace.Support", "Devspace.Support", "{68F5041D-51F2-4630-94B6-B49789F5E51A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Devspaces.Support", "src\BuildingBlocks\Devspaces.Support\Devspaces.Support.csproj", "{56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1744,6 +1748,54 @@ Global {766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|x64.Build.0 = Release|Any CPU {766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|x86.ActiveCfg = Release|Any CPU {766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|x86.Build.0 = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|ARM.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|iPhone.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|x64.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|x64.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|x86.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.AppStore|x86.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|ARM.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|ARM.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|iPhone.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|x64.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|x64.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|x86.ActiveCfg = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Debug|x86.Build.0 = Debug|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|Any CPU.Build.0 = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|ARM.ActiveCfg = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|ARM.Build.0 = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|iPhone.ActiveCfg = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|iPhone.Build.0 = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|x64.ActiveCfg = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|x64.Build.0 = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|x86.ActiveCfg = Release|Any CPU + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1808,6 +1860,8 @@ Global {E0AA11C4-2873-461D-8F82-53392530FB7A} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {84E2016E-0435-44C6-8020-3D288AA38B2C} = {E0AA11C4-2873-461D-8F82-53392530FB7A} {766D7E92-6AF0-476C-ADD5-282BF4D8C576} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04} + {68F5041D-51F2-4630-94B6-B49789F5E51A} = {DB0EFB20-B024-4E5E-A75C-52143C131D25} + {56C2EF0B-6BF2-41D9-BE07-6E6D08D06B35} = {68F5041D-51F2-4630-94B6-B49789F5E51A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} diff --git a/elk/Readme.md b/elk/Readme.md new file mode 100644 index 000000000..dddeab3fd --- /dev/null +++ b/elk/Readme.md @@ -0,0 +1,88 @@ +This article contains a brief introduction to centralized structured logging with [Serilog](https://serilog.net/) and event viewing with [ELK](https://www.elastic.co/elk-stack) in eShopOnContainers. ELK is an acronym of ElasticSearch, LogStash and Kibana. This is one of the most used tools in the industry standards. + +![](img/elk/kibana-working.png) + +## Wiring eshopOnContainers with ELK in Localhost + +eshopOnContainers is ready for work with ELK, you only need to setup the configuration parameter **LogstashUrl**, in **Serilog** Section, for achieve this, you can do it modifing this parameter in every appsettings.json of every service, or via Environment Variable **Serilog:LogstashUrl**. + +There is another option, a zero-configuration environment for testing the integration launching via ```docker-compose``` command, on the root directory of eshopOnContainers: + +```sh +docker-compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.elk.yml build + +docker-compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.elk.yml up +``` + +### Configuring Logstash index on Kibana + +Once time you have started and configured your application, you only need to configure the logstash index on kibana. +You can address to Kibana, with docker-compose setup is at [http://localhost:5601](http://localhost:5601) + +If you have accessed to kibana too early, you can see this error. It's normal, depending of your machine the kibana stack needs a bit of time to startup. +![](img/elk/kibana_startup.png) + +You can wait a bit and refresh the page, the first time you enter, you need to configure and index pattern, in the ```docker-compose``` configuration, the index pattern name is **eshops-\***. +![](img/elk/kibana_eshops_index.png) + +With the index pattern configured, you can enter in the discover section and start viewing how the tool is recollecting the logging information. + +![](img/elk/kibana_result.png) + +## Configuring ELK on Azure VM +Another option is to use a preconfigured virtual machine with Logstash, ElasticSearch and Kibana and point the configuration parameter **LogstashUrl**. For doing this you can address to Microsoft Azure, and start searching a Certified ELK Virtual Machine + +![](img/elk/create-vm-elk-azure.png) + +This options it have a certified preconfigured options (Network, VirtualMachine type, OS, RAM, Disks) for having a good starting point of ELK with good performance. + +![](img/elk/create-vm-elk-azure-summary.png) + +When you have configured the main aspects of your virtual machine, you will have a "review & create" last step like this: +![](img/elk/create-vm-elk-azure-last-step.png) + +### Configuring the bitnami environment + + This virtual machine has a lot of configuration pipeing done. If you want to change something of the default configuration you can address this documentation: + [https://docs.bitnami.com/virtual-machine/apps/elk/get-started/](https://docs.bitnami.com/virtual-machine/apps/elk/get-started/) + + The only thing you have to change is the logstash configuration inside the machine. This configuration is at the file ```/opt/bitnami/logstash/conf/logstash.conf``` + You must edit the file and overwrite with this configuration: + ```conf + input { + http { + #default host 0.0.0.0:8080 + codec => json + } +} + +## Add your filters / logstash plugins configuration here +filter { + split { + field => "events" + target => "e" + remove_field => "events" + } +} + +output { + elasticsearch { + hosts => "elasticsearch:9200" + index=>"eshops-%{+xxxx.ww}" + } +} +``` + +For doing this you can connect via ssh to the vm and edit the file using the vi editor for example. +When the file will be edited, check there are Inbound Port Rules created for the logstash service. You can do it going to Networking Menu on your ELK Virtual Machine Resource in Azure. + +![](img/elk/azure-nsg-inboundportsConfig.png) + +The only thing that remains is to connect to your vm vía browser. And check the bitnami splash page is showing. + +![](img/elk/bitnami_splash.png) + +You can get the password for accessing going to your virtual machine in azure and check the boot diagnostics, theres a message that shows to you which is your password. + +When you have the user and password you can access to the kibana tool, and create the ```eshops-*``` index pattern that is well documented at the beggining of this documentation and then start to discover. +![](img/elk/) \ No newline at end of file diff --git a/elk/elasticsearch/Dockerfile b/elk/elasticsearch/Dockerfile new file mode 100644 index 000000000..0ad46d887 --- /dev/null +++ b/elk/elasticsearch/Dockerfile @@ -0,0 +1,5 @@ +# https://github.com/elastic/elasticsearch-docker +FROM docker.elastic.co/elasticsearch/elasticsearch-oss:6.0.0 + +# Add your elasticsearch plugins setup here +# Example: RUN elasticsearch-plugin install analysis-icu diff --git a/elk/elasticsearch/config/elasticsearch.yml b/elk/elasticsearch/config/elasticsearch.yml new file mode 100644 index 000000000..e97577084 --- /dev/null +++ b/elk/elasticsearch/config/elasticsearch.yml @@ -0,0 +1,16 @@ +--- +## Default Elasticsearch configuration from elasticsearch-docker. +## from https://github.com/elastic/elasticsearch-docker/blob/master/build/elasticsearch/elasticsearch.yml +# +cluster.name: "docker-cluster" +network.host: 0.0.0.0 + +# minimum_master_nodes need to be explicitly set when bound on a public IP +# set to 1 to allow single node clusters +# Details: https://github.com/elastic/elasticsearch/pull/17288 +discovery.zen.minimum_master_nodes: 1 + +## Use single node discovery in order to disable production mode and avoid bootstrap checks +## see https://www.elastic.co/guide/en/elasticsearch/reference/current/bootstrap-checks.html +# +discovery.type: single-node diff --git a/elk/kibana/Dockerfile b/elk/kibana/Dockerfile new file mode 100644 index 000000000..1785734aa --- /dev/null +++ b/elk/kibana/Dockerfile @@ -0,0 +1,5 @@ +# https://github.com/elastic/kibana-docker +FROM docker.elastic.co/kibana/kibana-oss:6.0.0 + +# Add your kibana plugins setup here +# Example: RUN kibana-plugin install diff --git a/elk/kibana/config/kibana.yml b/elk/kibana/config/kibana.yml new file mode 100644 index 000000000..4b34a1606 --- /dev/null +++ b/elk/kibana/config/kibana.yml @@ -0,0 +1,7 @@ +--- +## Default Kibana configuration from kibana-docker. +## from https://github.com/elastic/kibana-docker/blob/master/build/kibana/config/kibana.yml +# +server.name: kibana +server.host: "0" +elasticsearch.url: http://elasticsearch:9200 diff --git a/elk/logstash/Dockerfile b/elk/logstash/Dockerfile new file mode 100644 index 000000000..d8bb475a5 --- /dev/null +++ b/elk/logstash/Dockerfile @@ -0,0 +1,6 @@ +# https://github.com/elastic/logstash-docker +FROM docker.elastic.co/logstash/logstash-oss:6.0.0 + +# Add your logstash plugins setup here +# Example: RUN logstash-plugin install logstash-filter-json +RUN logstash-plugin install logstash-input-http \ No newline at end of file diff --git a/elk/logstash/config/logstash.yml b/elk/logstash/config/logstash.yml new file mode 100644 index 000000000..d4f28f778 --- /dev/null +++ b/elk/logstash/config/logstash.yml @@ -0,0 +1,6 @@ +--- +## Default Logstash configuration from logstash-docker. +## from https://github.com/elastic/logstash-docker/blob/master/build/logstash/config/logstash-oss.yml +# +http.host: "0.0.0.0" +path.config: /usr/share/logstash/pipeline \ No newline at end of file diff --git a/elk/logstash/pipeline/logstash.conf b/elk/logstash/pipeline/logstash.conf new file mode 100644 index 000000000..b38a681d7 --- /dev/null +++ b/elk/logstash/pipeline/logstash.conf @@ -0,0 +1,22 @@ +input { + http { + #default host 0.0.0.0:8080 + codec => json + } +} + +## Add your filters / logstash plugins configuration here +filter { + split { + field => "events" + target => "e" + remove_field => "events" + } +} + +output { + elasticsearch { + hosts => "elasticsearch:9200" + index=>"eshops-%{+xxxx.ww}" + } +} diff --git a/img/eShopScreen.png b/img/eShopScreen.png new file mode 100644 index 000000000..a21df7c53 Binary files /dev/null and b/img/eShopScreen.png differ diff --git a/img/elk/azure-nsg-inboundportsConfig.png b/img/elk/azure-nsg-inboundportsConfig.png new file mode 100644 index 000000000..5a0371e66 Binary files /dev/null and b/img/elk/azure-nsg-inboundportsConfig.png differ diff --git a/img/elk/bitnami_splash.png b/img/elk/bitnami_splash.png new file mode 100644 index 000000000..a34643864 Binary files /dev/null and b/img/elk/bitnami_splash.png differ diff --git a/img/elk/create-vm-elk-azure-last-step.png b/img/elk/create-vm-elk-azure-last-step.png new file mode 100644 index 000000000..348f8843c Binary files /dev/null and b/img/elk/create-vm-elk-azure-last-step.png differ diff --git a/img/elk/create-vm-elk-azure-summary.png b/img/elk/create-vm-elk-azure-summary.png new file mode 100644 index 000000000..b56ae5af3 Binary files /dev/null and b/img/elk/create-vm-elk-azure-summary.png differ diff --git a/img/elk/create-vm-elk-azure.png b/img/elk/create-vm-elk-azure.png new file mode 100644 index 000000000..b7d98bb95 Binary files /dev/null and b/img/elk/create-vm-elk-azure.png differ diff --git a/img/elk/discover-kibana.png b/img/elk/discover-kibana.png new file mode 100644 index 000000000..3977042c7 Binary files /dev/null and b/img/elk/discover-kibana.png differ diff --git a/img/elk/kibana_eshops_index.png b/img/elk/kibana_eshops_index.png new file mode 100644 index 000000000..5a4be8ec3 Binary files /dev/null and b/img/elk/kibana_eshops_index.png differ diff --git a/img/elk/kibana_result.png b/img/elk/kibana_result.png new file mode 100644 index 000000000..55b7fd3ff Binary files /dev/null and b/img/elk/kibana_result.png differ diff --git a/img/elk/kibana_startup.png b/img/elk/kibana_startup.png new file mode 100644 index 000000000..e283d7de8 Binary files /dev/null and b/img/elk/kibana_startup.png differ diff --git a/img/elk/kibana_working.png b/img/elk/kibana_working.png new file mode 100644 index 000000000..e310e2710 Binary files /dev/null and b/img/elk/kibana_working.png differ diff --git a/k8s/README.k8s.md b/k8s/README.k8s.md index 62841aba1..84d9a72f0 100644 --- a/k8s/README.k8s.md +++ b/k8s/README.k8s.md @@ -20,7 +20,7 @@ For AKS: For ACS: >``` ->./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -createAcr true -orchestratorName k8s-cluster -dnsName k8s-dns +>./gen-k8s-env-aks -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -serviceName k8s-cluster -createAcr true -nodeCount 3 -nodeVMSize Standard_D2_v2 >``` * A Docker development environment with `docker` and `docker-compose`. diff --git a/k8s/helm/apigwmm/templates/_names.tpl b/k8s/helm/apigwmm/templates/_names.tpl index a6eeb9965..d44859fea 100644 --- a/k8s/helm/apigwmm/templates/_names.tpl +++ b/k8s/helm/apigwmm/templates/_names.tpl @@ -33,14 +33,13 @@ {{- end -}} + {{- define "pathBase" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if $ctx.Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" $ctx -}} -{{- printf "/%s-%s" $name $suffix -}} +{{- if .Values.inf.k8s.suffix -}} +{{- $suffix := include "suffix-name" . -}} +{{- printf "%s-%s" .Values.pathBase $suffix -}} {{- else -}} -{{- printf "/%s" $name -}} +{{- .Values.pathBase -}} {{- end -}} {{- end -}} diff --git a/k8s/helm/apigwmm/templates/deployment.yaml b/k8s/helm/apigwmm/templates/deployment.yaml index 6dc58bf50..c9abb0b62 100644 --- a/k8s/helm/apigwmm/templates/deployment.yaml +++ b/k8s/helm/apigwmm/templates/deployment.yaml @@ -61,10 +61,10 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} volumeMounts: - name: config - mountPath: /app/configuration + mountPath: {{ .Values.ocelot.configPath }} env: - name: PATH_BASE - value: {{ include "pathBase" (list .Values.app.ingress.entries.mobilemarketingapigw .) }} + value: {{ include "pathBase" . }} - name: k8sname value: {{ .Values.clusterName }} {{- if .Values.env.values -}} diff --git a/k8s/helm/apigwmm/templates/ingress.yaml b/k8s/helm/apigwmm/templates/ingress.yaml index 28e2aa84d..290aac0b3 100644 --- a/k8s/helm/apigwmm/templates/ingress.yaml +++ b/k8s/helm/apigwmm/templates/ingress.yaml @@ -1,5 +1,6 @@ {{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" (list .Values.app.ingress.entries.mobilemarketingapigw .) -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.mobilemarketingapigw -}} apiVersion: extensions/v1beta1 kind: Ingress metadata: @@ -23,11 +24,13 @@ spec: {{- end }} {{- end }} rules: - - host: {{ .Values.inf.k8s.dns }} + {{- range .Values.ingress.hosts }} + - host: {{ . }} http: paths: - path: {{ $ingressPath }} backend: - serviceName: {{ .Values.app.svc.mobilemarketingapigw }} + serviceName: {{ $serviceName }} servicePort: http + {{- end }} {{- end }} diff --git a/k8s/helm/apigwmm/values.yaml b/k8s/helm/apigwmm/values.yaml index 501266780..ea87a6c05 100644 --- a/k8s/helm/apigwmm/values.yaml +++ b/k8s/helm/apigwmm/values.yaml @@ -62,3 +62,5 @@ probes: initialDelaySeconds: 90 periodSeconds: 60 port: 80 +ocelot: + configPath: /app/configuration diff --git a/k8s/helm/apigwms/templates/_names.tpl b/k8s/helm/apigwms/templates/_names.tpl index 1e840c56c..d44859fea 100644 --- a/k8s/helm/apigwms/templates/_names.tpl +++ b/k8s/helm/apigwms/templates/_names.tpl @@ -35,13 +35,11 @@ {{- define "pathBase" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if $ctx.Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" $ctx -}} -{{- printf "/%s-%s" $name $suffix -}} +{{- if .Values.inf.k8s.suffix -}} +{{- $suffix := include "suffix-name" . -}} +{{- printf "%s-%s" .Values.pathBase $suffix -}} {{- else -}} -{{- printf "/%s" $name -}} +{{- .Values.pathBase -}} {{- end -}} {{- end -}} diff --git a/k8s/helm/apigwms/templates/deployment.yaml b/k8s/helm/apigwms/templates/deployment.yaml index 8a4fd8942..b22922f89 100644 --- a/k8s/helm/apigwms/templates/deployment.yaml +++ b/k8s/helm/apigwms/templates/deployment.yaml @@ -61,10 +61,10 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} volumeMounts: - name: config - mountPath: /app/configuration + mountPath: {{ .Values.ocelot.configPath }} env: - name: PATH_BASE - value: {{ include "pathBase" (list .Values.app.ingress.entries.mobileshoppingapigw .) }} + value: {{ include "pathBase" . }} - name: k8sname value: {{ .Values.clusterName }} {{- if .Values.env.values -}} diff --git a/k8s/helm/apigwms/templates/ingress.yaml b/k8s/helm/apigwms/templates/ingress.yaml index 7dd50d8dd..e93ddc2c6 100644 --- a/k8s/helm/apigwms/templates/ingress.yaml +++ b/k8s/helm/apigwms/templates/ingress.yaml @@ -1,5 +1,7 @@ {{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" (list .Values.app.ingress.entries.mobileshoppingapigw .) -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.mobileshoppingapigw -}} + apiVersion: extensions/v1beta1 kind: Ingress metadata: @@ -23,11 +25,13 @@ spec: {{- end }} {{- end }} rules: - - host: {{ .Values.inf.k8s.dns }} + {{- range .Values.ingress.hosts }} + - host: {{ . }} http: paths: - path: {{ $ingressPath }} backend: - serviceName: {{ .Values.app.svc.mobileshoppingapigw }} + serviceName: {{ $serviceName }} servicePort: http + {{- end }} {{- end }} diff --git a/k8s/helm/apigwms/values.yaml b/k8s/helm/apigwms/values.yaml index 58377ec5b..650ab6449 100644 --- a/k8s/helm/apigwms/values.yaml +++ b/k8s/helm/apigwms/values.yaml @@ -61,4 +61,6 @@ probes: timeoutSeconds: 5 initialDelaySeconds: 90 periodSeconds: 60 - port: 80 \ No newline at end of file + port: 80 +ocelot: + configPath: /app/configuration \ No newline at end of file diff --git a/k8s/helm/apigwwm/templates/_names.tpl b/k8s/helm/apigwwm/templates/_names.tpl index 1e840c56c..d44859fea 100644 --- a/k8s/helm/apigwwm/templates/_names.tpl +++ b/k8s/helm/apigwwm/templates/_names.tpl @@ -35,13 +35,11 @@ {{- define "pathBase" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if $ctx.Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" $ctx -}} -{{- printf "/%s-%s" $name $suffix -}} +{{- if .Values.inf.k8s.suffix -}} +{{- $suffix := include "suffix-name" . -}} +{{- printf "%s-%s" .Values.pathBase $suffix -}} {{- else -}} -{{- printf "/%s" $name -}} +{{- .Values.pathBase -}} {{- end -}} {{- end -}} diff --git a/k8s/helm/apigwwm/templates/deployment.yaml b/k8s/helm/apigwwm/templates/deployment.yaml index 5cbce9f22..d1f39ab6c 100644 --- a/k8s/helm/apigwwm/templates/deployment.yaml +++ b/k8s/helm/apigwwm/templates/deployment.yaml @@ -61,10 +61,10 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} volumeMounts: - name: config - mountPath: /app/configuration + mountPath: {{ .Values.ocelot.configPath }} env: - name: PATH_BASE - value: {{ include "pathBase" (list .Values.app.ingress.entries.webmarketingapigw .) }} + value: {{ include "pathBase" . }} - name: k8sname value: {{ .Values.clusterName }} {{- if .Values.env.values -}} diff --git a/k8s/helm/apigwwm/templates/ingress.yaml b/k8s/helm/apigwwm/templates/ingress.yaml index 0a79c4660..297fea52b 100644 --- a/k8s/helm/apigwwm/templates/ingress.yaml +++ b/k8s/helm/apigwwm/templates/ingress.yaml @@ -1,5 +1,7 @@ {{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" (list .Values.app.ingress.entries.webmarketingapigw .) -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.webmarketingapigw -}} + apiVersion: extensions/v1beta1 kind: Ingress metadata: @@ -23,11 +25,13 @@ spec: {{- end }} {{- end }} rules: - - host: {{ .Values.inf.k8s.dns }} + {{- range .Values.ingress.hosts }} + - host: {{ . }} http: paths: - path: {{ $ingressPath }} backend: - serviceName: {{ .Values.app.svc.webmarketingapigw }} + serviceName: {{ $serviceName }} servicePort: http + {{- end }} {{- end }} diff --git a/k8s/helm/apigwwm/values.yaml b/k8s/helm/apigwwm/values.yaml index 68cbb89c4..63deb5832 100644 --- a/k8s/helm/apigwwm/values.yaml +++ b/k8s/helm/apigwwm/values.yaml @@ -61,4 +61,6 @@ probes: timeoutSeconds: 5 initialDelaySeconds: 90 periodSeconds: 60 - port: 80 \ No newline at end of file + port: 80 +ocelot: + configPath: /app/configuration \ No newline at end of file diff --git a/k8s/helm/apigwws/templates/_names.tpl b/k8s/helm/apigwws/templates/_names.tpl index a6eeb9965..d44859fea 100644 --- a/k8s/helm/apigwws/templates/_names.tpl +++ b/k8s/helm/apigwws/templates/_names.tpl @@ -33,14 +33,13 @@ {{- end -}} + {{- define "pathBase" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if $ctx.Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" $ctx -}} -{{- printf "/%s-%s" $name $suffix -}} +{{- if .Values.inf.k8s.suffix -}} +{{- $suffix := include "suffix-name" . -}} +{{- printf "%s-%s" .Values.pathBase $suffix -}} {{- else -}} -{{- printf "/%s" $name -}} +{{- .Values.pathBase -}} {{- end -}} {{- end -}} diff --git a/k8s/helm/apigwws/templates/deployment.yaml b/k8s/helm/apigwws/templates/deployment.yaml index 4912d12bb..327eb50b7 100644 --- a/k8s/helm/apigwws/templates/deployment.yaml +++ b/k8s/helm/apigwws/templates/deployment.yaml @@ -60,10 +60,10 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} volumeMounts: - name: config - mountPath: /app/configuration + mountPath: {{ .Values.ocelot.configPath }} env: - name: PATH_BASE - value: {{ include "pathBase" (list .Values.app.ingress.entries.webshoppingapigw .) }} + value: {{ include "pathBase" . }} - name: k8sname value: {{ .Values.clusterName }} {{- if .Values.env.values -}} diff --git a/k8s/helm/apigwws/templates/ingress.yaml b/k8s/helm/apigwws/templates/ingress.yaml index ee1f681ad..8bd2cfc6d 100644 --- a/k8s/helm/apigwws/templates/ingress.yaml +++ b/k8s/helm/apigwws/templates/ingress.yaml @@ -1,5 +1,6 @@ {{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" (list .Values.app.ingress.entries.webshoppingapigw .) -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.webshoppingapigw -}} apiVersion: extensions/v1beta1 kind: Ingress metadata: @@ -23,11 +24,13 @@ spec: {{- end }} {{- end }} rules: - - host: {{ .Values.inf.k8s.dns }} + {{- range .Values.ingress.hosts }} + - host: {{ . }} http: paths: - path: {{ $ingressPath }} backend: - serviceName: {{ .Values.app.svc.webshoppingapigw }} + serviceName: {{ $serviceName }} servicePort: http + {{- end }} {{- end }} diff --git a/k8s/helm/apigwws/values.yaml b/k8s/helm/apigwws/values.yaml index 94b8a203f..2b047de99 100644 --- a/k8s/helm/apigwws/values.yaml +++ b/k8s/helm/apigwws/values.yaml @@ -62,3 +62,5 @@ probes: initialDelaySeconds: 90 periodSeconds: 60 port: 80 +ocelot: + configPath: /app/configuration \ No newline at end of file diff --git a/k8s/helm/app.yaml b/k8s/helm/app.yaml index 6b1c36922..91e829b27 100644 --- a/k8s/helm/app.yaml +++ b/k8s/helm/app.yaml @@ -29,7 +29,7 @@ app: # app global settings catalog: catalog # service name for catalog api ordering: ordering # service name for ordering api orderingbackgroundtasks: orderingbackgroundtasks # service name for orderingbackgroundtasks - orderingsignalrhub: ordering-signalrhub # service name for orderingsignalrhub + orderingsignalrhub: ordering-signalrhub # service name for orderingsignalrhub identity: identity # service name for identity api mvc: webmvc # service name for web mvc spa: webspa # service name for web spa diff --git a/k8s/helm/basket-api/templates/configmap.yaml b/k8s/helm/basket-api/templates/configmap.yaml index c851de359..911318fc1 100644 --- a/k8s/helm/basket-api/templates/configmap.yaml +++ b/k8s/helm/basket-api/templates/configmap.yaml @@ -15,5 +15,5 @@ data: urls__IdentityUrl: http://{{ $identity }} basket__EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/k8s/helm/basket-api/templates/ingress.yaml b/k8s/helm/basket-api/templates/ingress.yaml new file mode 100644 index 000000000..f99bd55a6 --- /dev/null +++ b/k8s/helm/basket-api/templates/ingress.yaml @@ -0,0 +1,37 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.basket -}} + +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ template "basket-api.fullname" . }} + labels: + app: {{ template "basket-api.name" . }} + chart: {{ template "basket-api.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + - {{ .Values.inf.k8s.dns }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $serviceName }} + servicePort: http + {{- end }} +{{- end }} \ No newline at end of file diff --git a/k8s/helm/basket-api/values.yaml b/k8s/helm/basket-api/values.yaml index 6c264afba..a773700fe 100644 --- a/k8s/helm/basket-api/values.yaml +++ b/k8s/helm/basket-api/values.yaml @@ -53,3 +53,6 @@ probes: initialDelaySeconds: 90 periodSeconds: 60 port: 80 + +ingress: + enabled: false \ No newline at end of file diff --git a/k8s/helm/catalog-api/templates/configmap.yaml b/k8s/helm/catalog-api/templates/configmap.yaml index 95d8f2f9b..902b65f5c 100644 --- a/k8s/helm/catalog-api/templates/configmap.yaml +++ b/k8s/helm/catalog-api/templates/configmap.yaml @@ -16,5 +16,5 @@ data: catalog__PicBaseUrl: http://{{ $webshoppingapigw }}/api/v1/c/catalog/items/[0]/pic/ catalog__AzureStorageEnabled: "{{ .Values.inf.misc.useAzureStorage }}" all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/k8s/helm/catalog-api/templates/ingress.yaml b/k8s/helm/catalog-api/templates/ingress.yaml new file mode 100644 index 000000000..238d7b07e --- /dev/null +++ b/k8s/helm/catalog-api/templates/ingress.yaml @@ -0,0 +1,37 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.catalog -}} + +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ template "catalog-api.fullname" . }} + labels: + app: {{ template "catalog-api.name" . }} + chart: {{ template "catalog-api.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + - {{ .Values.inf.k8s.dns }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $serviceName }} + servicePort: http + {{- end }} +{{- end }} \ No newline at end of file diff --git a/k8s/helm/deploy-all-istio.ps1 b/k8s/helm/deploy-all-istio.ps1 index eb1c6af56..ede371a57 100644 --- a/k8s/helm/deploy-all-istio.ps1 +++ b/k8s/helm/deploy-all-istio.ps1 @@ -57,6 +57,7 @@ kubectl apply -f ./istio/gateway.yml if ($useLocalk8s -eq $true) { $dns="localhost" + $externalDns="localhost" } else { Write-Host "Resolving DNS to Gateway public IP" -ForegroundColor Green diff --git a/k8s/helm/deploy-all.ps1 b/k8s/helm/deploy-all.ps1 index 42ba3ab27..3cf6936bc 100644 --- a/k8s/helm/deploy-all.ps1 +++ b/k8s/helm/deploy-all.ps1 @@ -5,6 +5,7 @@ Param( [parameter(Mandatory=$false)][string]$externalDns, [parameter(Mandatory=$false)][string]$appName="eshop", [parameter(Mandatory=$false)][bool]$deployInfrastructure=$true, + [parameter(Mandatory=$false)][bool]$deployCharts=$true, [parameter(Mandatory=$false)][bool]$clean=$true, [parameter(Mandatory=$false)][string]$aksName="", [parameter(Mandatory=$false)][string]$aksRg="", @@ -44,7 +45,7 @@ if ([string]::IsNullOrEmpty($dns)) { if ($clean) { Write-Host "Cleaning previous helm releases..." -ForegroundColor Green - helm delete --purge $(helm ls -q) + helm delete --purge $(helm ls -q eshop) Write-Host "Previous releases deleted" -ForegroundColor Green } @@ -66,20 +67,28 @@ $charts = ("eshop-common", "apigwmm", "apigwms", "apigwwm", "apigwws", "basket-a if ($deployInfrastructure) { foreach ($infra in $infras) { Write-Host "Installing infrastructure: $infra" -ForegroundColor Green - helm install --values app.yaml --values inf.yaml --values $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --name="$appName-$infra" $infra + helm install --values app.yaml --values inf.yaml --values $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set "ingress.hosts={$dns}" --name="$appName-$infra" $infra } } +else { + Write-Host "eShopOnContainers infrastructure (bbdd, redis, ...) charts aren't installed (-deployCharts is false)" -ForegroundColor Yellow +} -foreach ($chart in $charts) { - Write-Host "Installing: $chart" -ForegroundColor Green - if ($useCustomRegistry) { - helm install --set inf.registry.server=$registry --set inf.registry.login=$dockerUser --set inf.registry.pwd=$dockerPassword --set inf.registry.secretName=eshop-docker-scret --values app.yaml --values inf.yaml --values $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set image.tag=$imageTag --set image.pullPolicy=Always --name="$appName-$chart" $chart - } - else { - if ($chart -ne "eshop-common") { # eshop-common is ignored when no secret must be deployed - helm install --values app.yaml --values inf.yaml --values $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set image.tag=$imageTag --set image.pullPolicy=Always --name="$appName-$chart" $chart +if ($deployCharts) { + foreach ($chart in $charts) { + Write-Host "Installing: $chart" -ForegroundColor Green + if ($useCustomRegistry) { + helm install --set inf.registry.server=$registry --set inf.registry.login=$dockerUser --set inf.registry.pwd=$dockerPassword --set inf.registry.secretName=eshop-docker-scret --values app.yaml --values inf.yaml --values $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set "ingress.hosts={$dns}" --set image.tag=$imageTag --set image.pullPolicy=Always --name="$appName-$chart" $chart + } + else { + if ($chart -ne "eshop-common") { # eshop-common is ignored when no secret must be deployed + helm install --values app.yaml --values inf.yaml --values $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set "ingress.hosts={$dns}" --set image.tag=$imageTag --set image.pullPolicy=Always --name="$appName-$chart" $chart + } } } } +else { + Write-Host "eShopOnContainers non-infrastructure charts aren't installed (-deployCharts is false)" -ForegroundColor Yellow +} -Write-Host "helm charts installed." -ForegroundColor Green \ No newline at end of file +Write-Host "helm charts installed." -ForegroundColor Green diff --git a/k8s/helm/identity-api/templates/configmap.yaml b/k8s/helm/identity-api/templates/configmap.yaml index 24d71b699..264ceb745 100644 --- a/k8s/helm/identity-api/templates/configmap.yaml +++ b/k8s/helm/identity-api/templates/configmap.yaml @@ -24,7 +24,7 @@ metadata: data: identity__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.identity.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }}; identity__keystore: {{ .Values.inf.redis.keystore.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" mvc_e: http://{{ $mvc_url }} spa_e: http://{{ $spa_url }} locations_e: http://{{ $locations_url }} @@ -36,5 +36,4 @@ data: xamarin_callback_e: http://{{ $xamarincallback }} webhooksapi_e: http://{{ $webhooks_url }} webhooksweb_e: http://{{ $webhooksweb_url }} - - + enableDevspaces: "{{ .Values.enableDevspaces }}" \ No newline at end of file diff --git a/k8s/helm/identity-api/templates/ingress.yaml b/k8s/helm/identity-api/templates/ingress.yaml index 5824f91e2..1d2d3d5d5 100644 --- a/k8s/helm/identity-api/templates/ingress.yaml +++ b/k8s/helm/identity-api/templates/ingress.yaml @@ -1,5 +1,6 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.identity }} apiVersion: extensions/v1beta1 kind: Ingress metadata: @@ -23,11 +24,13 @@ spec: {{- end }} {{- end }} rules: - - host: {{ .Values.inf.k8s.dns }} + {{- range .Values.ingress.hosts }} + - host: {{ . }} http: paths: - path: {{ $ingressPath }} backend: - serviceName: {{ .Values.app.svc.identity }} + serviceName: {{ $serviceName }} servicePort: http + {{- end }} {{- end }} diff --git a/k8s/helm/identity-api/values.yaml b/k8s/helm/identity-api/values.yaml index c0fd38192..7b57dfde1 100644 --- a/k8s/helm/identity-api/values.yaml +++ b/k8s/helm/identity-api/values.yaml @@ -58,6 +58,8 @@ env: key: webhooksapi_e - name: WebhooksWebClient key: webhooksweb_e + - name: EnableDevspaces + key: enableDevspaces values: - name: ASPNETCORE_ENVIRONMENT value: Development @@ -65,6 +67,7 @@ env: value: 'K8S' - name: IsClusterEnv value: 'True' + probes: liveness: path: /liveness @@ -76,4 +79,6 @@ probes: timeoutSeconds: 5 initialDelaySeconds: 90 periodSeconds: 60 - port: 80 \ No newline at end of file + port: 80 + +enableDevspaces: "false" \ No newline at end of file diff --git a/k8s/helm/inf.yaml b/k8s/helm/inf.yaml index b6ff102b0..ee4d1fde6 100644 --- a/k8s/helm/inf.yaml +++ b/k8s/helm/inf.yaml @@ -1,4 +1,4 @@ -# This heml values file defines all infrastructure used by eShopOnContainers. +# This helm values file defines all infrastructure used by eShopOnContainers. # It is used on all charts, so ** MUST BE INCLUDED ** on every deployment inf: @@ -15,11 +15,11 @@ inf: identity: db: IdentityDb # Ordering API SQL db name marketing: - db: MarketingDb # Marketing API SQL db name + db: MarketingDb # Marketing API SQL db name webhooks: - db: WebhooksDb # Webhooks DB + db: WebhooksDb # Webhooks DB mongo: -# host: my-nosql-data # Uncomment to use specify custom mongo host. By default nosql-data is used +# host: my-nosql-data # Uncomment to use specify custom mongo host. By default nosql-data is used locations: database: LocationsDb marketing: diff --git a/k8s/helm/locations-api/templates/configmap.yaml b/k8s/helm/locations-api/templates/configmap.yaml index 84881087d..c5d752509 100644 --- a/k8s/helm/locations-api/templates/configmap.yaml +++ b/k8s/helm/locations-api/templates/configmap.yaml @@ -13,7 +13,7 @@ metadata: heritage: {{ .Release.Service }} data: all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" internalurls__IdentityUrl: http://{{ .Values.app.svc.identity }} diff --git a/k8s/helm/locations-api/templates/ingress.yaml b/k8s/helm/locations-api/templates/ingress.yaml new file mode 100644 index 000000000..8c846944e --- /dev/null +++ b/k8s/helm/locations-api/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.locations }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ template "locations-api.fullname" . }} + labels: + app: {{ template "locations-api.name" . }} + chart: {{ template "locations-api.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + - {{ .Values.inf.k8s.dns }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $serviceName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/k8s/helm/marketing-api/templates/configmap.yaml b/k8s/helm/marketing-api/templates/configmap.yaml index 45f21e57d..123b21adf 100644 --- a/k8s/helm/marketing-api/templates/configmap.yaml +++ b/k8s/helm/marketing-api/templates/configmap.yaml @@ -15,7 +15,7 @@ metadata: heritage: {{ .Release.Service }} data: all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" internalurls__IdentityUrl: http://{{ .Values.app.svc.identity }} diff --git a/k8s/helm/marketing-api/templates/ingress.yaml b/k8s/helm/marketing-api/templates/ingress.yaml new file mode 100644 index 000000000..7a5b29b12 --- /dev/null +++ b/k8s/helm/marketing-api/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.marketing }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ template "marketing-api.fullname" . }} + labels: + app: {{ template "marketing-api.name" . }} + chart: {{ template "marketing-api.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + - {{ .Values.inf.k8s.dns }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $serviceName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/k8s/helm/mobileshoppingagg/templates/configmap.yaml b/k8s/helm/mobileshoppingagg/templates/configmap.yaml index d3e935409..6cad653a9 100644 --- a/k8s/helm/mobileshoppingagg/templates/configmap.yaml +++ b/k8s/helm/mobileshoppingagg/templates/configmap.yaml @@ -10,7 +10,7 @@ metadata: release: {{ .Release.Name }} heritage: {{ .Release.Service }} data: - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" mobileshoppingagg__keystore: {{ .Values.inf.redis.keystore.constr }} internalurls__basket: http://{{ .Values.app.svc.basket }} diff --git a/k8s/helm/mobileshoppingagg/templates/ingress.yaml b/k8s/helm/mobileshoppingagg/templates/ingress.yaml new file mode 100644 index 000000000..6c50a574e --- /dev/null +++ b/k8s/helm/mobileshoppingagg/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.mobileshoppingagg }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ template "mobileshoppingagg.fullname" . }} + labels: + app: {{ template "mobileshoppingagg.name" . }} + chart: {{ template "mobileshoppingagg.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + - {{ .Values.inf.k8s.dns }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $serviceName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/k8s/helm/ordering-api/templates/configmap.yaml b/k8s/helm/ordering-api/templates/configmap.yaml index de4cb2d7a..efc829cda 100644 --- a/k8s/helm/ordering-api/templates/configmap.yaml +++ b/k8s/helm/ordering-api/templates/configmap.yaml @@ -16,5 +16,5 @@ data: ordering__EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" urls__IdentityUrl: http://{{ $identity }} all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/k8s/helm/ordering-backgroundtasks/templates/configmap.yaml b/k8s/helm/ordering-backgroundtasks/templates/configmap.yaml index 54fec785b..7ed4a0e8e 100644 --- a/k8s/helm/ordering-backgroundtasks/templates/configmap.yaml +++ b/k8s/helm/ordering-backgroundtasks/templates/configmap.yaml @@ -1,10 +1,11 @@ {{- $name := include "ordering-backgroundtasks.fullname" . -}} {{- $sqlsrv := include "sql-name" . -}} +{{- $cfgname := printf "cfg-%s" $name | trunc 63 }} apiVersion: v1 kind: ConfigMap metadata: - name: "cfg-{{ $name }}" + name: "{{ $cfgname }}" labels: app: {{ template "ordering-backgroundtasks.name" . }} chart: {{ template "ordering-backgroundtasks.chart" .}} @@ -14,7 +15,7 @@ data: ordering__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.ordering.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }}; ordering__EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" graceperiodmanager__CheckUpdateTime: "{{ .Values.cfg.checkUpdateTime }}" graceperiodmanager__GracePeriodTime: "{{ .Values.cfg.gracePeriodTime }}" \ No newline at end of file diff --git a/k8s/helm/ordering-backgroundtasks/templates/deployment.yaml b/k8s/helm/ordering-backgroundtasks/templates/deployment.yaml index 017f9f3dd..d93c7f764 100644 --- a/k8s/helm/ordering-backgroundtasks/templates/deployment.yaml +++ b/k8s/helm/ordering-backgroundtasks/templates/deployment.yaml @@ -1,11 +1,11 @@ {{- $name := include "ordering-backgroundtasks.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} +{{- $cfgname := printf "cfg-%s" $name | trunc 63 }} + apiVersion: apps/v1beta2 kind: Deployment metadata: name: {{ template "ordering-backgroundtasks.fullname" . }} labels: - ufo: {{ $cfgname}} app: {{ template "ordering-backgroundtasks.name" . }} chart: {{ template "ordering-backgroundtasks.chart" . }} release: {{ .Release.Name }} diff --git a/k8s/helm/ordering-signalrhub/templates/configmap.yaml b/k8s/helm/ordering-signalrhub/templates/configmap.yaml index addcf7e9d..bab4ebc94 100644 --- a/k8s/helm/ordering-signalrhub/templates/configmap.yaml +++ b/k8s/helm/ordering-signalrhub/templates/configmap.yaml @@ -12,7 +12,7 @@ metadata: heritage: {{ .Release.Service }} data: all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" signalr__StoreConnectionString: {{ .Values.inf.redis.keystore.constr }} urls__IdentityUrl: http://{{ $identity }} \ No newline at end of file diff --git a/k8s/helm/payment-api/templates/configmap.yaml b/k8s/helm/payment-api/templates/configmap.yaml index 6717705b5..3bdb95c0f 100644 --- a/k8s/helm/payment-api/templates/configmap.yaml +++ b/k8s/helm/payment-api/templates/configmap.yaml @@ -11,5 +11,5 @@ metadata: heritage: {{ .Release.Service }} data: all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/k8s/helm/webhooks-api/templates/configmap.yaml b/k8s/helm/webhooks-api/templates/configmap.yaml index a18126858..ba1f21c42 100644 --- a/k8s/helm/webhooks-api/templates/configmap.yaml +++ b/k8s/helm/webhooks-api/templates/configmap.yaml @@ -16,5 +16,5 @@ data: urls__IdentityUrl: http://{{ $identity }} urls__IdentityUrlExternal: http://{{ $identity }} all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/k8s/helm/webhooks-api/templates/ingress.yaml b/k8s/helm/webhooks-api/templates/ingress.yaml index 293f8e47e..debf0f84a 100644 --- a/k8s/helm/webhooks-api/templates/ingress.yaml +++ b/k8s/helm/webhooks-api/templates/ingress.yaml @@ -1,5 +1,6 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.webhooks }} apiVersion: extensions/v1beta1 kind: Ingress metadata: @@ -23,11 +24,13 @@ spec: {{- end }} {{- end }} rules: - - host: {{ .Values.inf.k8s.dns }} + {{- range .Values.ingress.hosts }} + - host: {{ . }} http: paths: - path: {{ $ingressPath }} backend: - serviceName: {{ .Values.app.svc.webhooks }} + serviceName: {{ $serviceName }} servicePort: http + {{- end }} {{- end }} diff --git a/k8s/helm/webmvc/templates/configmap.yaml b/k8s/helm/webmvc/templates/configmap.yaml index 60dacdadd..3e1e10cd1 100644 --- a/k8s/helm/webmvc/templates/configmap.yaml +++ b/k8s/helm/webmvc/templates/configmap.yaml @@ -2,7 +2,6 @@ {{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} {{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}} {{- $mvc := include "url-of" (list .Values.app.ingress.entries.mvc .) -}} -{{- $mongo := include "mongo-name" . -}} apiVersion: v1 @@ -15,7 +14,7 @@ metadata: release: {{ .Release.Name }} heritage: {{ .Release.Service }} data: - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" webmvc__keystore: {{ .Values.inf.redis.keystore.constr }} diff --git a/k8s/helm/webmvc/templates/ingress.yaml b/k8s/helm/webmvc/templates/ingress.yaml index abfb62b2f..892fa4273 100644 --- a/k8s/helm/webmvc/templates/ingress.yaml +++ b/k8s/helm/webmvc/templates/ingress.yaml @@ -1,5 +1,6 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.mvc -}} apiVersion: extensions/v1beta1 kind: Ingress metadata: @@ -23,11 +24,13 @@ spec: {{- end }} {{- end }} rules: - - host: {{ .Values.inf.k8s.dns }} + {{- range .Values.ingress.hosts }} + - host: {{ . }} http: paths: - path: {{ $ingressPath }} backend: - serviceName: {{ .Values.app.svc.mvc }} + serviceName: {{ $serviceName }} servicePort: http + {{- end }} {{- end }} diff --git a/k8s/helm/webshoppingagg/templates/configmap.yaml b/k8s/helm/webshoppingagg/templates/configmap.yaml index b4d3da041..efa3c7eaf 100644 --- a/k8s/helm/webshoppingagg/templates/configmap.yaml +++ b/k8s/helm/webshoppingagg/templates/configmap.yaml @@ -10,7 +10,7 @@ metadata: release: {{ .Release.Name }} heritage: {{ .Release.Service }} data: - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" webshoppingagg__keystore: {{ .Values.inf.redis.keystore.constr }} internalurls__basket: http://{{ .Values.app.svc.basket }} diff --git a/k8s/helm/webshoppingagg/templates/ingress.yaml b/k8s/helm/webshoppingagg/templates/ingress.yaml new file mode 100644 index 000000000..742db4d30 --- /dev/null +++ b/k8s/helm/webshoppingagg/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressPath := include "pathBase" . -}} +{{- $serviceName := .Values.app.svc.webshoppingagg }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ template "webshoppingagg.fullname" . }} + labels: + app: {{ template "webshoppingagg.name" . }} + chart: {{ template "webshoppingagg.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + - {{ .Values.inf.k8s.dns }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $serviceName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/k8s/helm/webspa/templates/configmap.yaml b/k8s/helm/webspa/templates/configmap.yaml index 7d4651a31..ea745436b 100644 --- a/k8s/helm/webspa/templates/configmap.yaml +++ b/k8s/helm/webspa/templates/configmap.yaml @@ -16,7 +16,7 @@ metadata: release: {{ .Release.Name }} heritage: {{ .Release.Service }} data: - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" webspa__keystore: {{ .Values.inf.redis.keystore.constr }} internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }} diff --git a/k8s/helm/webstatus/templates/configmap.yaml b/k8s/helm/webstatus/templates/configmap.yaml index 3f32d7adc..4a1b612f2 100644 --- a/k8s/helm/webstatus/templates/configmap.yaml +++ b/k8s/helm/webstatus/templates/configmap.yaml @@ -15,7 +15,7 @@ metadata: release: {{ .Release.Name }} heritage: {{ .Release.Service }} data: - all__InstrumentationKey: {{ .Values.inf.appinsights.key }} + all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" webstatus__keystore: {{ .Values.inf.redis.keystore.constr }} diff --git a/restore-packages.cmd b/restore-packages.cmd new file mode 100644 index 000000000..4e99614d6 --- /dev/null +++ b/restore-packages.cmd @@ -0,0 +1 @@ +for /R %%f in (*.csproj) do dotnet restore --no-dependencies %%f diff --git a/run-docker-compose-build.ps1 b/run-docker-compose-build.ps1 index 7d99ee0e7..ed4a14541 100644 --- a/run-docker-compose-build.ps1 +++ b/run-docker-compose-build.ps1 @@ -1,6 +1,6 @@ $startTime = $(Get-Date) -docker-compose build +docker-compose build --build-arg RUN=scripts/restore-packages $elapsedTime = $(Get-Date) - $startTime diff --git a/scripts/restore-packages b/scripts/restore-packages new file mode 100644 index 000000000..58bb10c62 --- /dev/null +++ b/scripts/restore-packages @@ -0,0 +1 @@ +echo RESTORING ALL PACKAGES...; for f in /src/csproj-files/*.csproj; do dotnet restore $f; done \ No newline at end of file diff --git a/scripts/restore-packages.cmd b/scripts/restore-packages.cmd new file mode 100644 index 000000000..9f3a8434e --- /dev/null +++ b/scripts/restore-packages.cmd @@ -0,0 +1 @@ +for %%p in (csproj-files\*.csproj) do dotnet restore %%p diff --git a/src/ApiGateways/ApiGw-Base/Dockerfile b/src/ApiGateways/ApiGw-Base/Dockerfile index ed6d75229..9dc86a846 100644 --- a/src/ApiGateways/ApiGw-Base/Dockerfile +++ b/src/ApiGateways/ApiGw-Base/Dockerfile @@ -4,13 +4,20 @@ EXPOSE 80 FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build WORKDIR /src + +COPY scripts scripts/ + +COPY src/ApiGateways/*/*.csproj /src/csproj-files/ +COPY src/ApiGateways/*/*/*.csproj /src/csproj-files/ +COPY src/BuildingBlocks/*/*/*.csproj /src/csproj-files/ +COPY src/Services/*/*/*.csproj /src/csproj-files/ +COPY src/Web/*/*.csproj /src/csproj-files/ + COPY . . WORKDIR /src/src/ApiGateways/ApiGw-Base/ -RUN dotnet restore -nowarn:msb3202,nu1503 -RUN dotnet build -c Release -o /app +RUN dotnet publish -c Release -o /app FROM build AS publish -RUN dotnet publish -c Release -o /app FROM base AS final WORKDIR /app diff --git a/src/ApiGateways/ApiGw-Base/Dockerfile.develop b/src/ApiGateways/ApiGw-Base/Dockerfile.develop new file mode 100644 index 000000000..4da230d68 --- /dev/null +++ b/src/ApiGateways/ApiGw-Base/Dockerfile.develop @@ -0,0 +1,14 @@ +FROM microsoft/dotnet:2.2-sdk +ARG BUILD_CONFIGURATION=Debug +ENV ASPNETCORE_ENVIRONMENT=Development +ENV DOTNET_USE_POLLING_FILE_WATCHER=true +EXPOSE 80 + +WORKDIR /src +COPY ["src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj", "src/ApiGateways/ApiGw-Base/"] +RUN dotnet restore "src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj" +COPY . . +WORKDIR "/src/src/ApiGateways/ApiGw-Base" +RUN dotnet build --no-restore "OcelotApiGw.csproj" -c $BUILD_CONFIGURATION + +ENTRYPOINT ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"] \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Marketing/apigw/azds.yaml b/src/ApiGateways/Mobile.Bff.Marketing/apigw/azds.yaml new file mode 100644 index 000000000..46375343b --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Marketing/apigw/azds.yaml @@ -0,0 +1,44 @@ +kind: helm-release +apiVersion: 1.1 +build: + context: ..\..\..\..\ + dockerfile: ..\..\..\ApiGateways\ApiGw-Base\Dockerfile +install: + chart: ../../../../k8s/helm/apigwmm + set: + replicaCount: 1 + image: + tag: $(tag) + pullPolicy: Never + ingress: + annotations: + kubernetes.io/ingress.class: traefik-azds + hosts: + # This expands to [space.s.]webmvc...aksapp.io + - $(spacePrefix)eshop$(hostSuffix) + inf: + k8s: + dns: $(spacePrefix)eshop$(hostSuffix) + values: + - values.dev.yaml? + - secrets.dev.yaml? + - inf.yaml + - app.yaml +configurations: + develop: + build: + useGitIgnore: true + dockerfile: ..\..\..\ApiGateways\ApiGw-Base\Dockerfile.develop + args: + BUILD_CONFIGURATION: ${BUILD_CONFIGURATION:-Debug} + container: + sync: + - '**/Pages/**' + - '**/Views/**' + - '**/wwwroot/**' + - '!**/*.{sln,csproj}' + command: [dotnet, run, --no-restore, --no-build, --no-launch-profile, -c, "${BUILD_CONFIGURATION:-Debug}"] + iterate: + processesToKill: [dotnet, vsdbg] + buildCommands: + - [dotnet, build, --no-restore, -c, "${BUILD_CONFIGURATION:-Debug}"] diff --git a/src/ApiGateways/Mobile.Bff.Marketing/apigw/values.dev.yaml b/src/ApiGateways/Mobile.Bff.Marketing/apigw/values.dev.yaml new file mode 100644 index 000000000..fb59d98d5 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Marketing/apigw/values.dev.yaml @@ -0,0 +1,2 @@ +ocelot: + configPath: /src/src/ApiGateways/ApiGw-Base/configuration \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs index 978b1858c..a2c0d1fea 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs @@ -36,15 +36,9 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers } // Retrieve the current basket - var currentBasket = await _basket.GetByIdAsync(data.BuyerId); - - if (currentBasket == null) - { - currentBasket = new BasketData(data.BuyerId); - } + var basket = await _basket.GetByIdAsync(data.BuyerId) ?? new BasketData(data.BuyerId); var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId)); - var newBasket = new BasketData(data.BuyerId); foreach (var bitem in data.Items) { @@ -54,7 +48,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); } - newBasket.Items.Add(new BasketDataItem() + basket.Items.Add(new BasketDataItem() { Id = bitem.Id, ProductId = catalogItem.Id.ToString(), @@ -65,9 +59,9 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers }); } - await _basket.UpdateAsync(newBasket); + await _basket.UpdateAsync(basket); - return newBasket; + return basket; } [HttpPut] diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile index d25a98e6c..9b03eccbd 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile @@ -4,13 +4,20 @@ EXPOSE 80 FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build WORKDIR /src + +COPY scripts scripts/ + +COPY src/ApiGateways/*/*.csproj /src/csproj-files/ +COPY src/ApiGateways/*/*/*.csproj /src/csproj-files/ +COPY src/BuildingBlocks/*/*/*.csproj /src/csproj-files/ +COPY src/Services/*/*/*.csproj /src/csproj-files/ +COPY src/Web/*/*.csproj /src/csproj-files/ + COPY . . WORKDIR /src/src/ApiGateways/Mobile.Bff.Shopping/aggregator -RUN dotnet restore -nowarn:msb3202,nu1503 -RUN dotnet build --no-restore -c Release -o /app +RUN dotnet publish -c Release -o /app FROM build AS publish -RUN dotnet publish --no-restore -c Release -o /app FROM base AS final WORKDIR /app diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile.develop b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile.develop new file mode 100644 index 000000000..c4330c370 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile.develop @@ -0,0 +1,16 @@ +FROM microsoft/dotnet:2.2-sdk +ARG BUILD_CONFIGURATION=Debug +ENV ASPNETCORE_ENVIRONMENT=Development +ENV DOTNET_USE_POLLING_FILE_WATCHER=true +EXPOSE 80 + +WORKDIR /src +COPY ["src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj", "src/ApiGateways/Mobile.Bff.Shopping/aggregator/"] +COPY ["src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj", "src/BuildingBlocks/Devspaces.Support/"] + +RUN dotnet restore src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj -nowarn:msb3202,nu1503 +COPY . . +WORKDIR "/src/src/ApiGateways/Mobile.Bff.Shopping/aggregator" +RUN dotnet build --no-restore -c $BUILD_CONFIGURATION + +CMD ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"]] \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs index b3a7246aa..21997360b 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -13,20 +13,21 @@ public void Apply(Operation operation, OperationFilterContext context) { // Check for authorize attribute - var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType().Any() || - context.ApiDescription.ActionAttributes().OfType().Any(); + var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || + context.MethodInfo.GetCustomAttributes(true).OfType().Any(); - if (hasAuthorize) - { - operation.Responses.Add("401", new Response { Description = "Unauthorized" }); - operation.Responses.Add("403", new Response { Description = "Forbidden" }); + if (!hasAuthorize) return; + + operation.Responses.TryAdd("401", new Response { Description = "Unauthorized" }); + operation.Responses.TryAdd("403", new Response { Description = "Forbidden" }); - operation.Security = new List>>(); - operation.Security.Add(new Dictionary> + operation.Security = new List>> { - { "oauth2", new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } } - }); - } + new Dictionary> + { + { "oauth2", new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } } + } + }; } } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj index fcb9fdf90..1dd1ba1b6 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj @@ -23,4 +23,8 @@ + + + + diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Properties/launchSettings.json b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Properties/launchSettings.json index 925e70b0d..c259d5094 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Properties/launchSettings.json +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Properties/launchSettings.json @@ -24,6 +24,13 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "applicationUrl": "http://localhost:61632/" + }, + "Azure Dev Spaces": { + "commandName": "AzureDevSpaces", + "launchBrowser": true, + "resourceGroup": "eshoptestedu", + "aksName": "eshoptestedu", + "subscriptionId": "e3035ac1-c06c-4daf-8939-57b3c5f1f759" } } } \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs index 924b5b1aa..eee0d9c6e 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs @@ -20,6 +20,7 @@ using Swashbuckle.AspNetCore.Swagger; using HealthChecks.UI.Client; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks; +using Devspaces.Support; namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator { @@ -47,6 +48,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator services.AddCustomMvc(Configuration) .AddCustomAuthentication(Configuration) + .AddDevspaces() .AddHttpServices(); } @@ -188,15 +190,18 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator services.AddHttpClient() .AddHttpMessageHandler() .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); + .AddPolicyHandler(GetCircuitBreakerPolicy()) + .AddDevspacesSupport(); services.AddHttpClient() .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); + .AddPolicyHandler(GetCircuitBreakerPolicy()) + .AddDevspacesSupport(); services.AddHttpClient() .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); + .AddPolicyHandler(GetCircuitBreakerPolicy()) + .AddDevspacesSupport(); return services; } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/azds.yaml b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/azds.yaml new file mode 100644 index 000000000..8dbac7128 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/azds.yaml @@ -0,0 +1,55 @@ +kind: helm-release +apiVersion: 1.1 +build: + context: ..\..\..\.. + dockerfile: Dockerfile +install: + chart: ../../../../k8s/helm/mobileshoppingagg + set: + image: + tag: $(tag) + pullPolicy: Never + ingress: + annotations: + kubernetes.io/ingress.class: traefik-azds + hosts: + # This expands to [space.s.]apigwms...aksapp.io + - $(spacePrefix)eshop$(hostSuffix) + inf: + k8s: + dns: $(spacePrefix)eshop$(hostSuffix) + values: + - values.dev.yaml? + - secrets.dev.yaml? + - app.yaml + - inf.yaml +configurations: + develop: + build: + useGitIgnore: true + dockerfile: Dockerfile.develop + container: + syncTarget: /src + sync: + - '**/Pages/**' + - '**/Views/**' + - '**/wwwroot/**' + - '!**/*.{sln,csproj}' + command: + - dotnet + - run + - --no-restore + - --no-build + - --no-launch-profile + - -c + - ${Configuration:-Debug} + iterate: + processesToKill: + - dotnet + - vsdbg + buildCommands: + - - dotnet + - build + - --no-restore + - -c + - ${Configuration:-Debug} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/values.dev.yaml b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/values.dev.yaml new file mode 100644 index 000000000..eaed45149 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/values.dev.yaml @@ -0,0 +1,3 @@ +ingress: + enabled: true + tls: [] \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Shopping/apigw/azds.yaml b/src/ApiGateways/Mobile.Bff.Shopping/apigw/azds.yaml new file mode 100644 index 000000000..9e2d09e42 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/apigw/azds.yaml @@ -0,0 +1,44 @@ +kind: helm-release +apiVersion: 1.1 +build: + context: ..\..\..\..\ + dockerfile: ..\..\..\ApiGateways\ApiGw-Base\Dockerfile +install: + chart: ../../../../k8s/helm/apigwms + set: + replicaCount: 1 + image: + tag: $(tag) + pullPolicy: Never + ingress: + annotations: + kubernetes.io/ingress.class: traefik-azds + hosts: + # This expands to [space.s.]webmvc...aksapp.io + - $(spacePrefix)eshop$(hostSuffix) + inf: + k8s: + dns: $(spacePrefix)eshop$(hostSuffix) + values: + - values.dev.yaml? + - secrets.dev.yaml? + - inf.yaml + - app.yaml +configurations: + develop: + build: + useGitIgnore: true + dockerfile: ..\..\..\ApiGateways\ApiGw-Base\Dockerfile.develop + args: + BUILD_CONFIGURATION: ${BUILD_CONFIGURATION:-Debug} + container: + sync: + - '**/Pages/**' + - '**/Views/**' + - '**/wwwroot/**' + - '!**/*.{sln,csproj}' + command: [dotnet, run, --no-restore, --no-build, --no-launch-profile, -c, "${BUILD_CONFIGURATION:-Debug}"] + iterate: + processesToKill: [dotnet, vsdbg] + buildCommands: + - [dotnet, build, --no-restore, -c, "${BUILD_CONFIGURATION:-Debug}"] diff --git a/src/ApiGateways/Mobile.Bff.Shopping/apigw/values.dev.yaml b/src/ApiGateways/Mobile.Bff.Shopping/apigw/values.dev.yaml new file mode 100644 index 000000000..fb59d98d5 --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/apigw/values.dev.yaml @@ -0,0 +1,2 @@ +ocelot: + configPath: /src/src/ApiGateways/ApiGw-Base/configuration \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Marketing/apigw/azds.yaml b/src/ApiGateways/Web.Bff.Marketing/apigw/azds.yaml new file mode 100644 index 000000000..8f60cbcc7 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Marketing/apigw/azds.yaml @@ -0,0 +1,44 @@ +kind: helm-release +apiVersion: 1.1 +build: + context: ..\..\..\..\ + dockerfile: ..\..\..\ApiGateways\ApiGw-Base\Dockerfile +install: + chart: ../../../../k8s/helm/apigwwm + set: + replicaCount: 1 + image: + tag: $(tag) + pullPolicy: Never + ingress: + annotations: + kubernetes.io/ingress.class: traefik-azds + hosts: + # This expands to [space.s.]webmvc...aksapp.io + - $(spacePrefix)eshop$(hostSuffix) + inf: + k8s: + dns: $(spacePrefix)eshop$(hostSuffix) + values: + - values.dev.yaml? + - secrets.dev.yaml? + - inf.yaml + - app.yaml +configurations: + develop: + build: + useGitIgnore: true + dockerfile: ..\..\..\ApiGateways\ApiGw-Base\Dockerfile.develop + args: + BUILD_CONFIGURATION: ${BUILD_CONFIGURATION:-Debug} + container: + sync: + - '**/Pages/**' + - '**/Views/**' + - '**/wwwroot/**' + - '!**/*.{sln,csproj}' + command: [dotnet, run, --no-restore, --no-build, --no-launch-profile, -c, "${BUILD_CONFIGURATION:-Debug}"] + iterate: + processesToKill: [dotnet, vsdbg] + buildCommands: + - [dotnet, build, --no-restore, -c, "${BUILD_CONFIGURATION:-Debug}"] diff --git a/src/ApiGateways/Web.Bff.Marketing/apigw/values.dev.yaml b/src/ApiGateways/Web.Bff.Marketing/apigw/values.dev.yaml new file mode 100644 index 000000000..fb59d98d5 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Marketing/apigw/values.dev.yaml @@ -0,0 +1,2 @@ +ocelot: + configPath: /src/src/ApiGateways/ApiGw-Base/configuration \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs index 6745ffa02..00cf506a4 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs @@ -36,14 +36,9 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers } // Retrieve the current basket - var currentBasket = await _basket.GetByIdAsync(data.BuyerId); - if (currentBasket == null) - { - currentBasket = new BasketData(data.BuyerId); - } + var basket = await _basket.GetByIdAsync(data.BuyerId) ?? new BasketData(data.BuyerId); var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId)); - var newBasket = new BasketData(data.BuyerId); foreach (var bitem in data.Items) { @@ -53,7 +48,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); } - newBasket.Items.Add(new BasketDataItem() + basket.Items.Add(new BasketDataItem() { Id = bitem.Id, ProductId = catalogItem.Id.ToString(), @@ -64,9 +59,9 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers }); } - await _basket.UpdateAsync(newBasket); + await _basket.UpdateAsync(basket); - return newBasket; + return basket; } [HttpPut] diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile index 75aa0f507..fbce2f0ab 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile @@ -4,13 +4,20 @@ EXPOSE 80 FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build WORKDIR /src + +COPY scripts scripts/ + +COPY src/ApiGateways/*/*.csproj /src/csproj-files/ +COPY src/ApiGateways/*/*/*.csproj /src/csproj-files/ +COPY src/BuildingBlocks/*/*/*.csproj /src/csproj-files/ +COPY src/Services/*/*/*.csproj /src/csproj-files/ +COPY src/Web/*/*.csproj /src/csproj-files/ + COPY . . WORKDIR /src/src/ApiGateways/Web.Bff.Shopping/aggregator -RUN dotnet restore -nowarn:msb3202,nu1503 -RUN dotnet build --no-restore -c Release -o /app +RUN dotnet publish -c Release -o /app FROM build AS publish -RUN dotnet publish --no-restore -c Release -o /app FROM base AS final WORKDIR /app diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile.develop b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile.develop new file mode 100644 index 000000000..3d0d16dd3 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile.develop @@ -0,0 +1,16 @@ +FROM microsoft/dotnet:2.2-sdk +ARG BUILD_CONFIGURATION=Debug +ENV ASPNETCORE_ENVIRONMENT=Development +ENV DOTNET_USE_POLLING_FILE_WATCHER=true +EXPOSE 80 + +WORKDIR /src +COPY ["src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj", "src/ApiGateways/Web.Bff.Shopping/aggregator/"] +COPY ["src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj", "src/BuildingBlocks/Devspaces.Support/"] + +RUN dotnet restore src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj -nowarn:msb3202,nu1503 +COPY . . +WORKDIR "/src/src/ApiGateways/Web.Bff.Shopping/aggregator" +RUN dotnet build --no-restore -c $BUILD_CONFIGURATION + +CMD ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"]] \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs index 3f382e5df..e93ec157c 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -13,20 +13,21 @@ public void Apply(Operation operation, OperationFilterContext context) { // Check for authorize attribute - var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType().Any() || - context.ApiDescription.ActionAttributes().OfType().Any(); + var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || + context.MethodInfo.GetCustomAttributes(true).OfType().Any(); - if (hasAuthorize) - { - operation.Responses.Add("401", new Response { Description = "Unauthorized" }); - operation.Responses.Add("403", new Response { Description = "Forbidden" }); + if (!hasAuthorize) return; + + operation.Responses.TryAdd("401", new Response { Description = "Unauthorized" }); + operation.Responses.TryAdd("403", new Response { Description = "Forbidden" }); - operation.Security = new List>>(); - operation.Security.Add(new Dictionary> + operation.Security = new List>> { - { "oauth2", new [] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } } - }); - } + new Dictionary> + { + { "oauth2", new [] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } } + } + }; } } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs index 6d3da29b7..dd5e1cc8c 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs @@ -21,6 +21,7 @@ using System.Net.Http; using HealthChecks.UI.Client; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.Extensions.Diagnostics.HealthChecks; +using Devspaces.Support; namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator { @@ -48,6 +49,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator services.AddCustomMvc(Configuration) .AddCustomAuthentication(Configuration) + .AddDevspaces() .AddApplicationServices(); } @@ -182,21 +184,23 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator services.AddSingleton(); //register http services - + services.AddHttpClient() .AddHttpMessageHandler() .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); + .AddPolicyHandler(GetCircuitBreakerPolicy()) + .AddDevspacesSupport(); services.AddHttpClient() .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); + .AddPolicyHandler(GetCircuitBreakerPolicy()) + .AddDevspacesSupport(); services.AddHttpClient() .AddHttpMessageHandler() .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - + .AddPolicyHandler(GetCircuitBreakerPolicy()) + .AddDevspacesSupport(); return services; } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj index 53a6db8f9..d438e4602 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj @@ -22,4 +22,8 @@ + + + + diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/azds.yaml b/src/ApiGateways/Web.Bff.Shopping/aggregator/azds.yaml new file mode 100644 index 000000000..189d2261d --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/azds.yaml @@ -0,0 +1,55 @@ +kind: helm-release +apiVersion: 1.1 +build: + context: ..\..\..\.. + dockerfile: Dockerfile +install: + chart: ../../../../k8s/helm/webshoppingagg + set: + image: + tag: $(tag) + pullPolicy: Never + ingress: + annotations: + kubernetes.io/ingress.class: traefik-azds + hosts: + # This expands to [space.s.]apigwms...aksapp.io + - $(spacePrefix)eshop$(hostSuffix) + inf: + k8s: + dns: $(spacePrefix)eshop$(hostSuffix) + values: + - values.dev.yaml? + - secrets.dev.yaml? + - app.yaml + - inf.yaml +configurations: + develop: + build: + useGitIgnore: true + dockerfile: Dockerfile.develop + container: + syncTarget: /src + sync: + - '**/Pages/**' + - '**/Views/**' + - '**/wwwroot/**' + - '!**/*.{sln,csproj}' + command: + - dotnet + - run + - --no-restore + - --no-build + - --no-launch-profile + - -c + - ${Configuration:-Debug} + iterate: + processesToKill: + - dotnet + - vsdbg + buildCommands: + - - dotnet + - build + - --no-restore + - -c + - ${Configuration:-Debug} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/values.dev.yaml b/src/ApiGateways/Web.Bff.Shopping/aggregator/values.dev.yaml new file mode 100644 index 000000000..45f664d6a --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/values.dev.yaml @@ -0,0 +1,2 @@ +ocelot: + configPath: /app/configuration \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Shopping/apigw/azds.yaml b/src/ApiGateways/Web.Bff.Shopping/apigw/azds.yaml new file mode 100644 index 000000000..69f26cdca --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/apigw/azds.yaml @@ -0,0 +1,43 @@ +kind: helm-release +apiVersion: 1.1 +build: + context: ..\..\..\..\ + dockerfile: ..\..\..\..\ApiGateways\ApiGw-Base\Dockerfile +install: + chart: ../../../../k8s/helm/apigwws + set: + replicaCount: 1 + image: + tag: $(tag) + pullPolicy: Never + ingress: + annotations: + kubernetes.io/ingress.class: traefik-azds + hosts: + - $(spacePrefix)eshop$(hostSuffix) + inf: + k8s: + dns: $(spacePrefix)eshop$(hostSuffix) + values: + - values.dev.yaml? + - secrets.dev.yaml? + - inf.yaml + - app.yaml +configurations: + develop: + build: + useGitIgnore: true + dockerfile: ..\..\..\ApiGateways\ApiGw-Base\Dockerfile.develop + args: + BUILD_CONFIGURATION: ${BUILD_CONFIGURATION:-Debug} + container: + sync: + - '**/Pages/**' + - '**/Views/**' + - '**/wwwroot/**' + - '!**/*.{sln,csproj}' + command: [dotnet, run, --no-restore, --no-build, --no-launch-profile, -c, "${BUILD_CONFIGURATION:-Debug}"] + iterate: + processesToKill: [dotnet, vsdbg] + buildCommands: + - [dotnet, build, --no-restore, -c, "${BUILD_CONFIGURATION:-Debug}"] diff --git a/src/ApiGateways/Web.Bff.Shopping/apigw/values.dev.yaml b/src/ApiGateways/Web.Bff.Shopping/apigw/values.dev.yaml new file mode 100644 index 000000000..fb59d98d5 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/apigw/values.dev.yaml @@ -0,0 +1,2 @@ +ocelot: + configPath: /src/src/ApiGateways/ApiGw-Base/configuration \ No newline at end of file diff --git a/src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj b/src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj new file mode 100644 index 000000000..81a897bad --- /dev/null +++ b/src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/src/BuildingBlocks/Devspaces.Support/DevspacesMessageHandler.cs b/src/BuildingBlocks/Devspaces.Support/DevspacesMessageHandler.cs new file mode 100644 index 000000000..0895b752a --- /dev/null +++ b/src/BuildingBlocks/Devspaces.Support/DevspacesMessageHandler.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Devspaces.Support +{ + public class DevspacesMessageHandler : DelegatingHandler + { + private const string DevspacesHeaderName = "azds-route-as"; + private readonly IHttpContextAccessor _httpContextAccessor; + public DevspacesMessageHandler(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var req = _httpContextAccessor.HttpContext.Request; + + if (req.Headers.ContainsKey(DevspacesHeaderName)) + { + request.Headers.Add(DevspacesHeaderName, req.Headers[DevspacesHeaderName] as IEnumerable); + } + return base.SendAsync(request, cancellationToken); + } + } +} diff --git a/src/BuildingBlocks/Devspaces.Support/HttpClientBuilderDevspacesExtensions.cs b/src/BuildingBlocks/Devspaces.Support/HttpClientBuilderDevspacesExtensions.cs new file mode 100644 index 000000000..60108301d --- /dev/null +++ b/src/BuildingBlocks/Devspaces.Support/HttpClientBuilderDevspacesExtensions.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Devspaces.Support +{ + public static class HttpClientBuilderDevspacesExtensions + { + public static IHttpClientBuilder AddDevspacesSupport(this IHttpClientBuilder builder) + { + builder.AddHttpMessageHandler(); + return builder; + } + } +} diff --git a/src/BuildingBlocks/Devspaces.Support/ServiceCollectionDevspacesExtensions.cs b/src/BuildingBlocks/Devspaces.Support/ServiceCollectionDevspacesExtensions.cs new file mode 100644 index 000000000..0ac5c9e1b --- /dev/null +++ b/src/BuildingBlocks/Devspaces.Support/ServiceCollectionDevspacesExtensions.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Devspaces.Support +{ + public static class ServiceCollectionDevspacesExtensions + { + public static IServiceCollection AddDevspaces(this IServiceCollection services) + { + services.AddTransient(); + return services; + } + } +} diff --git a/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs b/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs index e789081f3..ea1aca61e 100644 --- a/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs +++ b/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs @@ -115,10 +115,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus private void RaiseOnEventRemoved(string eventName) { var handler = OnEventRemoved; - if (handler != null) - { - OnEventRemoved(this, eventName); - } + handler?.Invoke(this, eventName); } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 9044a4283..99c5b4bbf 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -80,13 +80,16 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ _logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message); }); + var eventName = @event.GetType().Name; + + _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); + using (var channel = _persistentConnection.CreateModel()) { - var eventName = @event.GetType() - .Name; - channel.ExchangeDeclare(exchange: BROKER_NAME, - type: "direct"); + _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); + + channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); var message = JsonConvert.SerializeObject(@event); var body = Encoding.UTF8.GetBytes(message); @@ -96,11 +99,14 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; // persistent - channel.BasicPublish(exchange: BROKER_NAME, - routingKey: eventName, - mandatory: true, - basicProperties: properties, - body: body); + _logger.LogTrace("Publishing event to RabbitMQ: {EventId}", @event.Id); + + channel.BasicPublish( + exchange: BROKER_NAME, + routingKey: eventName, + mandatory: true, + basicProperties: properties, + body: body); }); } } @@ -176,29 +182,50 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ private void StartBasicConsume() { + _logger.LogTrace("Starting RabbitMQ basic consume"); + if (_consumerChannel != null) { - var consumer = new EventingBasicConsumer(_consumerChannel); - consumer.Received += async (model, ea) => - { - var eventName = ea.RoutingKey; - var message = Encoding.UTF8.GetString(ea.Body); + var consumer = new AsyncEventingBasicConsumer(_consumerChannel); - await ProcessEvent(eventName, message); + consumer.Received += Consumer_Received; - _consumerChannel.BasicAck(ea.DeliveryTag, multiple: false); - }; - - _consumerChannel.BasicConsume(queue: _queueName, - autoAck: false, - consumer: consumer); + _consumerChannel.BasicConsume( + queue: _queueName, + autoAck: false, + consumer: consumer); } else { - _logger.LogError("StartBasicConsume can not call on _consumerChannelCreated == false"); + _logger.LogError("StartBasicConsume can't call on _consumerChannel == null"); } } + private async Task Consumer_Received(object sender, BasicDeliverEventArgs eventArgs) + { + var eventName = eventArgs.RoutingKey; + var message = Encoding.UTF8.GetString(eventArgs.Body); + + try + { + if (message.ToLowerInvariant().Contains("throw-fake-exception")) + { + throw new InvalidOperationException($"Fake exception requested: \"{message}\""); + } + + await ProcessEvent(eventName, message); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "----- ERROR Processing message \"{Message}\"", message); + } + + // Even on exception we take the message off the queue. + // in a REAL WORLD app this should be handled with a Dead Letter Exchange (DLX). + // For more information see: https://www.rabbitmq.com/dlx.html + _consumerChannel.BasicAck(eventArgs.DeliveryTag, multiple: false); + } + private IModel CreateConsumerChannel() { if (!_persistentConnection.IsConnected) @@ -206,10 +233,12 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ _persistentConnection.TryConnect(); } + _logger.LogTrace("Creating RabbitMQ consumer channel"); + var channel = _persistentConnection.CreateModel(); channel.ExchangeDeclare(exchange: BROKER_NAME, - type: "direct"); + type: "direct"); channel.QueueDeclare(queue: _queueName, durable: true, @@ -219,6 +248,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ channel.CallbackException += (sender, ea) => { + _logger.LogWarning(ea.Exception, "Recreating RabbitMQ consumer channel"); + _consumerChannel.Dispose(); _consumerChannel = CreateConsumerChannel(); StartBasicConsume(); @@ -229,6 +260,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ private async Task ProcessEvent(string eventName, string message) { + _logger.LogTrace("Processing RabbitMQ event: {EventName}", eventName); + if (_subsManager.HasSubscriptionsForEvent(eventName)) { using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) @@ -255,6 +288,10 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ } } } + else + { + _logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName); + } } } } diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs index e5c3bc9ad..dc65fa525 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs @@ -12,7 +12,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF public class IntegrationEventLogEntry { private IntegrationEventLogEntry() { } - public IntegrationEventLogEntry(IntegrationEvent @event) + public IntegrationEventLogEntry(IntegrationEvent @event, Guid transactionId) { EventId = @event.Id; CreationTime = @event.CreationDate; @@ -20,7 +20,9 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF Content = JsonConvert.SerializeObject(@event); State = EventStateEnum.NotPublished; TimesSent = 0; + TransactionId = transactionId.ToString(); } + public Guid EventId { get; private set; } public string EventTypeName { get; private set; } [NotMapped] @@ -31,6 +33,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF public int TimesSent { get; set; } public DateTime CreationTime { get; private set; } public string Content { get; private set; } + public string TransactionId { get; private set; } public IntegrationEventLogEntry DeserializeJsonContent(Type type) { diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs index 6167d8ae8..cbf363c83 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs @@ -1,4 +1,5 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using System; using System.Collections.Generic; using System.Data.Common; @@ -9,8 +10,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Servi { public interface IIntegrationEventLogService { - Task> RetrieveEventLogsPendingToPublishAsync(); - Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction); + Task> RetrieveEventLogsPendingToPublishAsync(Guid transactionId); + Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction); Task MarkEventAsPublishedAsync(Guid eventId); Task MarkEventAsInProgressAsync(Guid eventId); Task MarkEventAsFailedAsync(Guid eventId); diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs index 2712c5e1c..758055e69 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Storage; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using Newtonsoft.Json; @@ -34,25 +35,24 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Servi .ToList(); } - public async Task> RetrieveEventLogsPendingToPublishAsync() + public async Task> RetrieveEventLogsPendingToPublishAsync(Guid transactionId) { + var tid = transactionId.ToString(); + return await _integrationEventLogContext.IntegrationEventLogs - .Where(e => e.State == EventStateEnum.NotPublished) + .Where(e => e.TransactionId == tid && e.State == EventStateEnum.NotPublished) .OrderBy(o => o.CreationTime) .Select(e => e.DeserializeJsonContent(_eventTypes.Find(t=> t.Name == e.EventTypeShortName))) .ToListAsync(); } - public Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction) + public Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction) { - if (transaction == null) - { - throw new ArgumentNullException(nameof(transaction), $"A {typeof(DbTransaction).FullName} is required as a pre-requisite to save the event."); - } + if (transaction == null) throw new ArgumentNullException(nameof(transaction)); - var eventLogEntry = new IntegrationEventLogEntry(@event); + var eventLogEntry = new IntegrationEventLogEntry(@event, transaction.TransactionId); - _integrationEventLogContext.Database.UseTransaction(transaction); + _integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction()); _integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry); return _integrationEventLogContext.SaveChangesAsync(); diff --git a/src/Services/Basket/Basket.API/.dockerignore b/src/Services/Basket/Basket.API/.dockerignore new file mode 100644 index 000000000..04f7b133d --- /dev/null +++ b/src/Services/Basket/Basket.API/.dockerignore @@ -0,0 +1,14 @@ +.dockerignore +.git +.gitignore +.vs +.vscode +**/*.*proj.user +**/azds.yaml +**/bin +**/charts +**/Dockerfile +**/Dockerfile.develop +**/obj +**/secrets.dev.yaml +**/values.dev.yaml \ No newline at end of file diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj index f7a2943ff..d5fc0a301 100644 --- a/src/Services/Basket/Basket.API/Basket.API.csproj +++ b/src/Services/Basket/Basket.API/Basket.API.csproj @@ -33,6 +33,7 @@ + diff --git a/src/Services/Basket/Basket.API/Controllers/BasketController.cs b/src/Services/Basket/Basket.API/Controllers/BasketController.cs index 7bab4e969..0bf15fc42 100644 --- a/src/Services/Basket/Basket.API/Controllers/BasketController.cs +++ b/src/Services/Basket/Basket.API/Controllers/BasketController.cs @@ -6,7 +6,6 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.Services.Basket.API.Model; using Microsoft.eShopOnContainers.Services.Basket.API.Services; using Microsoft.Extensions.Logging; -using Serilog.Context; using System; using System.Net; using System.Threading.Tasks; @@ -41,14 +40,14 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers { var basket = await _repository.GetBasketAsync(id); - return basket ?? new CustomerBasket(id); + return Ok(basket ?? new CustomerBasket(id)); } [HttpPost] [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] public async Task> UpdateBasketAsync([FromBody]CustomerBasket value) { - return await _repository.UpdateBasketAsync(value); + return Ok(await _repository.UpdateBasketAsync(value)); } [Route("checkout")] diff --git a/src/Services/Basket/Basket.API/Dockerfile b/src/Services/Basket/Basket.API/Dockerfile index af5c31654..909567b2c 100644 --- a/src/Services/Basket/Basket.API/Dockerfile +++ b/src/Services/Basket/Basket.API/Dockerfile @@ -4,19 +4,26 @@ EXPOSE 80 FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build WORKDIR /src + +COPY scripts scripts/ + +COPY src/ApiGateways/*/*.csproj /src/csproj-files/ +COPY src/ApiGateways/*/*/*.csproj /src/csproj-files/ +COPY src/BuildingBlocks/*/*/*.csproj /src/csproj-files/ +COPY src/Services/*/*/*.csproj /src/csproj-files/ +COPY src/Web/*/*.csproj /src/csproj-files/ + COPY . . WORKDIR /src/src/Services/Basket/Basket.API -RUN dotnet restore -nowarn:msb3202,nu1503 -RUN dotnet build --no-restore -c Release -o /app - -FROM build as functionaltest -WORKDIR /src/src/Services/Basket/Basket.FunctionalTests +RUN dotnet publish -c Release -o /app FROM build as unittest WORKDIR /src/src/Services/Basket/Basket.UnitTests +FROM build as functionaltest +WORKDIR /src/src/Services/Basket/Basket.FunctionalTests + FROM build AS publish -RUN dotnet publish --no-restore -c Release -o /app FROM base AS final WORKDIR /app diff --git a/src/Services/Basket/Basket.API/Dockerfile.develop b/src/Services/Basket/Basket.API/Dockerfile.develop new file mode 100644 index 000000000..5ae5cc235 --- /dev/null +++ b/src/Services/Basket/Basket.API/Dockerfile.develop @@ -0,0 +1,19 @@ +FROM microsoft/dotnet:2.2-sdk +ARG BUILD_CONFIGURATION=Debug +ENV ASPNETCORE_ENVIRONMENT=Development +ENV DOTNET_USE_POLLING_FILE_WATCHER=true +EXPOSE 80 + +WORKDIR /src + +COPY ["src/BuildingBlocks/EventBus/EventBus/EventBus.csproj", "src/BuildingBlocks/EventBus/EventBus/"] +COPY ["src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj", "src/BuildingBlocks/EventBus/EventBusRabbitMQ/"] +COPY ["src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj", "src/BuildingBlocks/EventBus/EventBusServiceBus/"] +COPY ["src/Services/Basket/Basket.API/Basket.API.csproj", "src/Services/Basket/Basket.API/"] + +RUN dotnet restore src/Services/Basket/Basket.API/Basket.API.csproj -nowarn:msb3202,nu1503 +COPY . . +WORKDIR /src/src/Services/Basket/Basket.API +RUN dotnet build --no-restore -c $BUILD_CONFIGURATION + +ENTRYPOINT ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"] \ No newline at end of file diff --git a/src/Services/Basket/Basket.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs b/src/Services/Basket/Basket.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs index f1c7b08d0..1ae38c8b0 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs @@ -11,22 +11,21 @@ namespace Basket.API.Infrastructure.Filters public void Apply(Operation operation, OperationFilterContext context) { // Check for authorize attribute - var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType().Any() || - context.ApiDescription.ActionAttributes().OfType().Any(); + var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || + context.MethodInfo.GetCustomAttributes(true).OfType().Any(); - if (hasAuthorize) - { - operation.Responses.Add("401", new Response { Description = "Unauthorized" }); - operation.Responses.Add("403", new Response { Description = "Forbidden" }); + if (!hasAuthorize) return; + + operation.Responses.TryAdd("401", new Response { Description = "Unauthorized" }); + operation.Responses.TryAdd("403", new Response { Description = "Forbidden" }); - operation.Security = new List>> + operation.Security = new List>> + { + new Dictionary> { - new Dictionary> - { - { "oauth2", new [] { "basketapi" } } - } - }; - } + { "oauth2", new [] { "basketapi" } } + } + }; } } } \ No newline at end of file diff --git a/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs b/src/Services/Basket/Basket.API/Infrastructure/Repositories/RedisBasketRepository.cs similarity index 91% rename from src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs rename to src/Services/Basket/Basket.API/Infrastructure/Repositories/RedisBasketRepository.cs index 5000e6c29..6653f5ed1 100644 --- a/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Repositories/RedisBasketRepository.cs @@ -1,11 +1,12 @@ -using Microsoft.Extensions.Logging; +using Microsoft.eShopOnContainers.Services.Basket.API.Model; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using StackExchange.Redis; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Model +namespace Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories { public class RedisBasketRepository : IBasketRepository { diff --git a/src/Services/Basket/Basket.API/Program.cs b/src/Services/Basket/Basket.API/Program.cs index 893a52400..40cc0eebc 100644 --- a/src/Services/Basket/Basket.API/Program.cs +++ b/src/Services/Basket/Basket.API/Program.cs @@ -57,13 +57,14 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 235b787d0..9cfabf20a 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -19,6 +19,7 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +using Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories; using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling; using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events; using Microsoft.eShopOnContainers.Services.Basket.API.Model; @@ -105,7 +106,8 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API var factory = new ConnectionFactory() { - HostName = Configuration["EventBusConnection"] + HostName = Configuration["EventBusConnection"], + DispatchConsumersAsync = true }; if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index 33f1c299f..fc8fc544a 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -1,6 +1,7 @@ { "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Basket/Basket.API/azds.yaml b/src/Services/Basket/Basket.API/azds.yaml new file mode 100644 index 000000000..4fbbb7be4 --- /dev/null +++ b/src/Services/Basket/Basket.API/azds.yaml @@ -0,0 +1,56 @@ +kind: helm-release +apiVersion: 1.1 +build: + context: ..\..\..\.. + dockerfile: Dockerfile +install: + chart: ../../../../k8s/helm/basket-api + set: + replicaCount: 1 + image: + tag: $(tag) + pullPolicy: Never + ingress: + annotations: + kubernetes.io/ingress.class: traefik-azds + hosts: + - $(spacePrefix)eshop$(hostSuffix) + inf: + k8s: + dns: $(spacePrefix)eshop$(hostSuffix) + values: + - values.dev.yaml? + - secrets.dev.yaml? + - inf.yaml + - app.yaml +configurations: + develop: + build: + useGitIgnore: true + dockerfile: Dockerfile.develop + args: + BUILD_CONFIGURATION: ${BUILD_CONFIGURATION:-Debug} + container: + sync: + - '**/Pages/**' + - '**/Views/**' + - '**/wwwroot/**' + - '!**/*.{sln,csproj}' + command: + - dotnet + - run + - --no-restore + - --no-build + - --no-launch-profile + - -c + - ${BUILD_CONFIGURATION:-Debug} + iterate: + processesToKill: + - dotnet + - vsdbg + buildCommands: + - - dotnet + - build + - --no-restore + - -c + - ${BUILD_CONFIGURATION:-Debug} diff --git a/src/Services/Basket/Basket.API/values.dev.yaml b/src/Services/Basket/Basket.API/values.dev.yaml new file mode 100644 index 000000000..eaed45149 --- /dev/null +++ b/src/Services/Basket/Basket.API/values.dev.yaml @@ -0,0 +1,3 @@ +ingress: + enabled: true + tls: [] \ No newline at end of file diff --git a/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj b/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj index e781b218d..4fd8cb9ec 100644 --- a/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj +++ b/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj @@ -17,6 +17,8 @@ + + diff --git a/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs b/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs index 84d41aa1a..f3f6d196d 100644 --- a/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs +++ b/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs @@ -1,14 +1,10 @@ using Basket.FunctionalTests.Base; -using Microsoft.eShopOnContainers.Services.Basket.API; +using Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories; using Microsoft.eShopOnContainers.Services.Basket.API.Model; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Moq; using StackExchange.Redis; -using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using Xunit; diff --git a/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs b/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs index 0045ce4aa..2864b8b9f 100644 --- a/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs +++ b/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs @@ -55,7 +55,7 @@ namespace UnitTest.Basket.Application //Assert Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); - Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId); + Assert.Equal((((ObjectResult)actionResult.Result).Value as CustomerBasket).BuyerId, fakeCustomerId); } [Fact] @@ -81,7 +81,7 @@ namespace UnitTest.Basket.Application //Assert Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); - Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId); + Assert.Equal((((ObjectResult)actionResult.Result).Value as CustomerBasket).BuyerId, fakeCustomerId); } [Fact] diff --git a/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj b/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj index bf5cb593a..27a851767 100644 --- a/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj +++ b/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj @@ -7,6 +7,8 @@ + + diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj index e5c3945c9..6150179ee 100644 --- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj +++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj @@ -53,6 +53,7 @@ + diff --git a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs index d9fa4002e..5dfb10a96 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs @@ -60,6 +60,15 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers .Take(pageSize) .ToListAsync(); + /* The "awesome" fix for testing Devspaces */ + + /* + foreach (var pr in itemsOnPage) { + pr.Name = "Awesome " + pr.Name; + } + + */ + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); var model = new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); diff --git a/src/Services/Catalog/Catalog.API/Dockerfile b/src/Services/Catalog/Catalog.API/Dockerfile index 317146c0c..facbb0ef3 100644 --- a/src/Services/Catalog/Catalog.API/Dockerfile +++ b/src/Services/Catalog/Catalog.API/Dockerfile @@ -4,10 +4,18 @@ EXPOSE 80 FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build WORKDIR /src + +COPY scripts scripts/ + +COPY src/ApiGateways/*/*.csproj /src/csproj-files/ +COPY src/ApiGateways/*/*/*.csproj /src/csproj-files/ +COPY src/BuildingBlocks/*/*/*.csproj /src/csproj-files/ +COPY src/Services/*/*/*.csproj /src/csproj-files/ +COPY src/Web/*/*.csproj /src/csproj-files/ + COPY . . WORKDIR /src/src/Services/Catalog/Catalog.API -RUN dotnet restore -nowarn:msb3202,nu1503 -RUN dotnet build --no-restore -c Release -o /app +RUN dotnet publish -c Release -o /app FROM build as unittest WORKDIR /src/src/Services/Catalog/Catalog.UnitTests @@ -16,7 +24,6 @@ FROM build as functionaltest WORKDIR /src/src/Services/Catalog/Catalog.FunctionalTests FROM build AS publish -RUN dotnet publish --no-restore -c Release -o /app FROM base AS final WORKDIR /app diff --git a/src/Services/Catalog/Catalog.API/Dockerfile.develop b/src/Services/Catalog/Catalog.API/Dockerfile.develop new file mode 100644 index 000000000..11034a2bc --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Dockerfile.develop @@ -0,0 +1,21 @@ +FROM microsoft/dotnet:2.2-sdk +ARG BUILD_CONFIGURATION=Debug +ENV ASPNETCORE_ENVIRONMENT=Development +ENV DOTNET_USE_POLLING_FILE_WATCHER=true +EXPOSE 80 + +WORKDIR /src + +COPY ["src/BuildingBlocks/EventBus/EventBus/EventBus.csproj", "src/BuildingBlocks/EventBus/EventBus/"] +COPY ["src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj", "src/BuildingBlocks/EventBus/EventBusRabbitMQ/"] +COPY ["src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj", "src/BuildingBlocks/EventBus/EventBusServiceBus/"] +COPY ["src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj", "src/BuildingBlocks/EventBus/IntegrationEventLogEF/"] +COPY ["src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj", "src/BuildingBlocks/WebHostCustomization/WebHost.Customization/"] +COPY ["src/Services/Catalog/Catalog.API/Catalog.API.csproj", "src/Services/Catalog/Catalog.API/"] + +RUN dotnet restore src/Services/Catalog/Catalog.API/Catalog.API.csproj -nowarn:msb3202,nu1503 +COPY . . +WORKDIR "/src/src/Services/Catalog/Catalog.API" +RUN dotnet build --no-restore -c $BUILD_CONFIGURATION + +ENTRYPOINT ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"] \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.Designer.cs b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.Designer.cs new file mode 100644 index 000000000..f0d694d07 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.Designer.cs @@ -0,0 +1,50 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; + +namespace Catalog.API.Infrastructure.IntegrationEventMigrations +{ + [DbContext(typeof(IntegrationEventLogContext))] + [Migration("20190507184807_AddTransactionId")] + partial class AddTransactionId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd(); + + b.Property("Content") + .IsRequired(); + + b.Property("CreationTime"); + + b.Property("EventTypeName") + .IsRequired(); + + b.Property("State"); + + b.Property("TimesSent"); + + b.Property("TransactionId"); + + b.HasKey("EventId"); + + b.ToTable("IntegrationEventLog"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.cs b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.cs new file mode 100644 index 000000000..473f26046 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Catalog.API.Infrastructure.IntegrationEventMigrations +{ + public partial class AddTransactionId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TransactionId", + table: "IntegrationEventLog", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "TransactionId", + table: "IntegrationEventLog"); + } + } +} diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs new file mode 100644 index 000000000..3841e3a20 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs @@ -0,0 +1,18 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; + +namespace Catalog.API.Infrastructure.IntegrationEventMigrations +{ + public class IntegrationEventLogContextDesignTimeFactory : IDesignTimeDbContextFactory + { + public IntegrationEventLogContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + + optionsBuilder.UseSqlServer(".", options => options.MigrationsAssembly(GetType().Assembly.GetName().Name)); + + return new IntegrationEventLogContext(optionsBuilder.Options); + } + } +} \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs index ab2414bb5..672690c14 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs @@ -1,8 +1,9 @@ -using System; +// +using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; namespace Catalog.API.Migrations @@ -12,8 +13,10 @@ namespace Catalog.API.Migrations { protected override void BuildModel(ModelBuilder modelBuilder) { +#pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "1.1.1") + .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") + .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b => @@ -33,10 +36,13 @@ namespace Catalog.API.Migrations b.Property("TimesSent"); + b.Property("TransactionId"); + b.HasKey("EventId"); b.ToTable("IntegrationEventLog"); }); +#pragma warning restore 612, 618 } } } diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs index 3b9476b9f..bb3a23d40 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs @@ -62,7 +62,7 @@ namespace Catalog.API.IntegrationEvents { // Achieving atomicity between original catalog database operation and the IntegrationEventLog thanks to a local transaction await _catalogContext.SaveChangesAsync(); - await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction.GetDbTransaction()); + await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction); }); } } diff --git a/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs b/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs index 459c60098..2e4579f7f 100644 --- a/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs +++ b/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs @@ -64,7 +64,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model if (quantityDesired <= 0) { - throw new CatalogDomainException($"Item units desired should be greater than cero"); + throw new CatalogDomainException($"Item units desired should be greater than zero"); } int removed = Math.Min(quantityDesired, this.AvailableStock); diff --git a/src/Services/Catalog/Catalog.API/Program.cs b/src/Services/Catalog/Catalog.API/Program.cs index c75b56c39..39b071c46 100644 --- a/src/Services/Catalog/Catalog.API/Program.cs +++ b/src/Services/Catalog/Catalog.API/Program.cs @@ -71,13 +71,14 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json index 8f2cde4db..f842f80d0 100644 --- a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json +++ b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json @@ -16,7 +16,8 @@ "ConnectionString": "server=localhost,5433;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word", "ASPNETCORE_ENVIRONMENT": "Development", "EventBusConnection": "localhost", - "Serilog:SeqServerUrl": "http://locahost:5340" + "Serilog:SeqServerUrl": "http://locahost:5340", + "Serilog:LogstashgUrl":"http://locahost:8080", } }, "Microsoft.eShopOnContainers.Services.Catalog.API": { @@ -26,6 +27,13 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "Azure Dev Spaces": { + "commandName": "AzureDevSpaces", + "launchBrowser": true, + "resourceGroup": "edu-devspaces3", + "aksName": "edu-devspaces3", + "subscriptionId": "e3035ac1-c06c-4daf-8939-57b3c5f1f759" } } } \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index 0258a0a98..1a51a86fb 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -297,7 +297,8 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API var factory = new ConnectionFactory() { - HostName = configuration["EventBusConnection"] + HostName = configuration["EventBusConnection"], + DispatchConsumersAsync = true }; if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) diff --git a/src/Services/Catalog/Catalog.API/appsettings.json b/src/Services/Catalog/Catalog.API/appsettings.json index b26f63bff..cc7b1b1fb 100644 --- a/src/Services/Catalog/Catalog.API/appsettings.json +++ b/src/Services/Catalog/Catalog.API/appsettings.json @@ -4,6 +4,7 @@ "UseCustomizationData": false, "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Catalog/Catalog.API/azds.yaml b/src/Services/Catalog/Catalog.API/azds.yaml new file mode 100644 index 000000000..9f98a3793 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/azds.yaml @@ -0,0 +1,54 @@ +kind: helm-release +apiVersion: 1.1 +build: + context: ..\..\..\.. + dockerfile: Dockerfile +install: + chart: ../../../../k8s/helm/catalog-api + set: + image: + tag: $(tag) + pullPolicy: Never + ingress: + annotations: + kubernetes.io/ingress.class: traefik-azds + hosts: + - $(spacePrefix)eshop$(hostSuffix) + inf: + k8s: + dns: $(spacePrefix)eshop$(hostSuffix) + values: + - values.dev.yaml? + - secrets.dev.yaml? + - inf.yaml + - app.yaml +configurations: + develop: + build: + useGitIgnore: true + dockerfile: Dockerfile.develop + container: + syncTarget: /src + sync: + - '**/Pages/**' + - '**/Views/**' + - '**/wwwroot/**' + - '!**/*.{sln,csproj}' + command: + - dotnet + - run + - --no-restore + - --no-build + - --no-launch-profile + - -c + - ${Configuration:-Debug} + iterate: + processesToKill: + - dotnet + - vsdbg + buildCommands: + - - dotnet + - build + - --no-restore + - -c + - ${Configuration:-Debug} diff --git a/src/Services/Catalog/Catalog.API/values.dev.yaml b/src/Services/Catalog/Catalog.API/values.dev.yaml new file mode 100644 index 000000000..eaed45149 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/values.dev.yaml @@ -0,0 +1,3 @@ +ingress: + enabled: true + tls: [] \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj b/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj index 07e9e2991..455dfb0bc 100644 --- a/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj +++ b/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj @@ -33,6 +33,8 @@ + + diff --git a/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj b/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj index 6a9a2bf99..efa9d56a4 100644 --- a/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj +++ b/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj @@ -7,6 +7,8 @@ + + diff --git a/src/Services/Identity/Identity.API/.dockerignore b/src/Services/Identity/Identity.API/.dockerignore new file mode 100644 index 000000000..04f7b133d --- /dev/null +++ b/src/Services/Identity/Identity.API/.dockerignore @@ -0,0 +1,14 @@ +.dockerignore +.git +.gitignore +.vs +.vscode +**/*.*proj.user +**/azds.yaml +**/bin +**/charts +**/Dockerfile +**/Dockerfile.develop +**/obj +**/secrets.dev.yaml +**/values.dev.yaml \ No newline at end of file diff --git a/src/Services/Identity/Identity.API/Controllers/AccountController.cs b/src/Services/Identity/Identity.API/Controllers/AccountController.cs index 6e9bbce16..ccb19a66d 100644 --- a/src/Services/Identity/Identity.API/Controllers/AccountController.cs +++ b/src/Services/Identity/Identity.API/Controllers/AccountController.cs @@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.eShopOnContainers.Services.Identity.API.Models; using Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels; using Microsoft.eShopOnContainers.Services.Identity.API.Services; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers @@ -32,6 +33,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers private readonly IClientStore _clientStore; private readonly ILogger _logger; private readonly UserManager _userManager; + private readonly IConfiguration _configuration; public AccountController( @@ -40,13 +42,15 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers IIdentityServerInteractionService interaction, IClientStore clientStore, ILogger logger, - UserManager userManager) + UserManager userManager, + IConfiguration configuration) { _loginService = loginService; _interaction = interaction; _clientStore = clientStore; _logger = logger; _userManager = userManager; + _configuration = configuration; } /// @@ -81,20 +85,21 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers if (await _loginService.ValidateCredentials(user, model.Password)) { + var tokenLifetime = _configuration.GetValue("TokenLifetimeMinutes", 120); + var props = new AuthenticationProperties { - ExpiresUtc = DateTimeOffset.UtcNow.AddHours(2), + ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(tokenLifetime), AllowRefresh = true, RedirectUri = model.ReturnUrl }; if (model.RememberMe) { - props = new AuthenticationProperties - { - IsPersistent = true, - ExpiresUtc = DateTimeOffset.UtcNow.AddYears(10) - }; + var permanentTokenLifetime = _configuration.GetValue("PermanentTokenLifetimeDays", 365); + + props.ExpiresUtc = DateTimeOffset.UtcNow.AddDays(permanentTokenLifetime); + props.IsPersistent = true; }; await _loginService.SignInAsync(user, props); diff --git a/src/Services/Identity/Identity.API/Devspaces/DevspacesRedirectUriValidator.cs b/src/Services/Identity/Identity.API/Devspaces/DevspacesRedirectUriValidator.cs new file mode 100644 index 000000000..53e497b59 --- /dev/null +++ b/src/Services/Identity/Identity.API/Devspaces/DevspacesRedirectUriValidator.cs @@ -0,0 +1,31 @@ +using IdentityServer4.Models; +using IdentityServer4.Validation; +using Microsoft.Extensions.Logging; +using System.Threading.Tasks; + + +namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces +{ + public class DevspacesRedirectUriValidator : IRedirectUriValidator + { + private readonly ILogger _logger; + public DevspacesRedirectUriValidator(ILogger logger) + { + _logger = logger; + } + + public Task IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client) + { + + _logger.LogInformation($"Client {client.ClientName} used post logout uri {requestedUri}."); + return Task.FromResult(true); + } + + public Task IsRedirectUriValidAsync(string requestedUri, Client client) + { + _logger.LogInformation($"Client {client.ClientName} used redirect uri {requestedUri}."); + return Task.FromResult(true); + } + + } +} \ No newline at end of file diff --git a/src/Services/Identity/Identity.API/Devspaces/IdentityDevspacesBuilderExtensions.cs b/src/Services/Identity/Identity.API/Devspaces/IdentityDevspacesBuilderExtensions.cs new file mode 100644 index 000000000..4dadb0e54 --- /dev/null +++ b/src/Services/Identity/Identity.API/Devspaces/IdentityDevspacesBuilderExtensions.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces +{ + static class IdentityDevspacesBuilderExtensions + { + public static IIdentityServerBuilder AddDevspacesIfNeeded(this IIdentityServerBuilder builder, bool useDevspaces) + { + if (useDevspaces) + { + builder.AddRedirectUriValidator(); + } + return builder; + } + } +} diff --git a/src/Services/Identity/Identity.API/Dockerfile b/src/Services/Identity/Identity.API/Dockerfile index af45d8da8..8196b077a 100644 --- a/src/Services/Identity/Identity.API/Dockerfile +++ b/src/Services/Identity/Identity.API/Dockerfile @@ -4,13 +4,20 @@ EXPOSE 80 FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build WORKDIR /src + +COPY scripts scripts/ + +COPY src/ApiGateways/*/*.csproj /src/csproj-files/ +COPY src/ApiGateways/*/*/*.csproj /src/csproj-files/ +COPY src/BuildingBlocks/*/*/*.csproj /src/csproj-files/ +COPY src/Services/*/*/*.csproj /src/csproj-files/ +COPY src/Web/*/*.csproj /src/csproj-files/ + COPY . . WORKDIR /src/src/Services/Identity/Identity.API -RUN dotnet restore -nowarn:msb3202,nu1503 -RUN dotnet build --no-restore -c Release -o /app +RUN dotnet publish -c Release -o /app FROM build AS publish -RUN dotnet publish --no-restore -c Release -o /app FROM base AS final WORKDIR /app diff --git a/src/Services/Identity/Identity.API/Dockerfile.develop b/src/Services/Identity/Identity.API/Dockerfile.develop new file mode 100644 index 000000000..3ab1fbe7c --- /dev/null +++ b/src/Services/Identity/Identity.API/Dockerfile.develop @@ -0,0 +1,15 @@ +FROM microsoft/dotnet:2.2-sdk +ARG BUILD_CONFIGURATION=Debug +ENV ASPNETCORE_ENVIRONMENT=Development +ENV DOTNET_USE_POLLING_FILE_WATCHER=true +EXPOSE 80 + +WORKDIR /src +COPY ["src/Services/Identity/Identity.API/Identity.API.csproj", "src/Services/Identity/Identity.API/"] +COPY ["src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj", "src/BuildingBlocks/WebHostCustomization/WebHost.Customization/"] +RUN dotnet restore src/Services/Identity/Identity.API/Identity.API.csproj -nowarn:msb3202,nu1503 +COPY . . +WORKDIR "/src/src/Services/Identity/Identity.API" +RUN dotnet build --no-restore -c $BUILD_CONFIGURATION + +ENTRYPOINT ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"] diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj index e8a2c7bd8..728843f71 100644 --- a/src/Services/Identity/Identity.API/Identity.API.csproj +++ b/src/Services/Identity/Identity.API/Identity.API.csproj @@ -34,6 +34,7 @@ + diff --git a/src/Services/Identity/Identity.API/Program.cs b/src/Services/Identity/Identity.API/Program.cs index 8204a1ebf..784f63a1e 100644 --- a/src/Services/Identity/Identity.API/Program.cs +++ b/src/Services/Identity/Identity.API/Program.cs @@ -76,13 +76,14 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://localhost:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Identity/Identity.API/README.md b/src/Services/Identity/Identity.API/README.md index 76e599dea..ffaaed531 100644 --- a/src/Services/Identity/Identity.API/README.md +++ b/src/Services/Identity/Identity.API/README.md @@ -2,10 +2,10 @@ Sample reference containerized application, cross-platform and microservices architecture. Powered by Microsoft -#Overview +## Overview This sample runs a microservices oriented application and a .net core Mvc application that consumes this services. You can find more information about how to set up docker in your machine in the global directory solution. -#Setup +## Setup This service is a identity provider or STS (Security Token Service) currently implemented with IdentityServer 4 wrapping ASP.NET Identity underneath. Check procedures on how to get the sample app started at the Wiki: diff --git a/src/Services/Identity/Identity.API/Startup.cs b/src/Services/Identity/Identity.API/Startup.cs index e672bab60..6ea7e3888 100644 --- a/src/Services/Identity/Identity.API/Startup.cs +++ b/src/Services/Identity/Identity.API/Startup.cs @@ -13,6 +13,7 @@ using Microsoft.eShopOnContainers.Services.Identity.API.Certificates; using Microsoft.eShopOnContainers.Services.Identity.API.Data; using Microsoft.eShopOnContainers.Services.Identity.API.Models; using Microsoft.eShopOnContainers.Services.Identity.API.Services; +using Microsoft.eShopOnContainers.Services.Identity.API.Devspaces; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -85,6 +86,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API x.IssuerUri = "null"; x.Authentication.CookieLifetime = TimeSpan.FromHours(2); }) + .AddDevspacesIfNeeded(Configuration.GetValue("EnableDevspaces", false)) .AddSigningCredential(Certificate.Get()) .AddAspNetIdentity() .AddConfigurationStore(options => diff --git a/src/Services/Identity/Identity.API/Views/Consent/Index.cshtml b/src/Services/Identity/Identity.API/Views/Consent/Index.cshtml index 03f026bda..08c316553 100644 --- a/src/Services/Identity/Identity.API/Views/Consent/Index.cshtml +++ b/src/Services/Identity/Identity.API/Views/Consent/Index.cshtml @@ -16,7 +16,7 @@
- @Html.Partial("_ValidationSummary") +
@@ -49,7 +49,7 @@
    @foreach (var scope in Model.ResourceScopes) { - @Html.Partial("_ScopeListItem", scope) + }
diff --git a/src/Services/Identity/Identity.API/Views/Shared/_LoginPartial.cshtml b/src/Services/Identity/Identity.API/Views/Shared/_LoginPartial.cshtml index 3d0a461f5..e110e459c 100644 --- a/src/Services/Identity/Identity.API/Views/Shared/_LoginPartial.cshtml +++ b/src/Services/Identity/Identity.API/Views/Shared/_LoginPartial.cshtml @@ -7,7 +7,7 @@ @if (SignInManager.IsSignedIn(User)) { - +