Browse Source

Merged from dev

pull/1207/head
Vijay Bikka 5 years ago
parent
commit
48b9fdf3da
147 changed files with 1146 additions and 1566 deletions
  1. +34
    -159
      README.md
  2. +17
    -17
      build/azure-devops/apigws/azure-pipelines.yml
  3. +4
    -4
      build/azure-devops/basket-api/azure-pipelines.yml
  4. +8
    -6
      build/azure-devops/buildimages.yaml
  5. +4
    -4
      build/azure-devops/catalog-api/azure-pipelines.yml
  6. +4
    -4
      build/azure-devops/identity-api/azure-pipelines.yml
  7. +8
    -8
      build/azure-devops/infrastructure/azure-pipelines.yml
  8. +4
    -4
      build/azure-devops/location-api/azure-pipelines.yml
  9. +4
    -4
      build/azure-devops/marketing-api/azure-pipelines.yml
  10. +3
    -3
      build/azure-devops/mobile-shopping-agg/azure-pipelines.yml
  11. +6
    -6
      build/azure-devops/ordering-api/azure-pipelines.yml
  12. +5
    -5
      build/azure-devops/payment-api/azure-pipelines.yml
  13. +3
    -3
      build/azure-devops/readme.md
  14. +4
    -4
      build/azure-devops/web-shopping-agg/azure-pipelines.yml
  15. +5
    -5
      build/azure-devops/webhooks-api/azure-pipelines.yml
  16. +5
    -5
      build/azure-devops/webhooks-client/azure-pipelines.yml
  17. +4
    -4
      build/azure-devops/webmvc/azure-pipelines.yml
  18. +4
    -4
      build/azure-devops/webspa/azure-pipelines.yml
  19. +4
    -4
      build/azure-devops/webstatus/azure-pipelines.yml
  20. +18
    -0
      deploy/k8s/dashboard-adminuser.yaml
  21. +0
    -2
      deploy/k8s/deploy-ingress-dockerlocal.ps1
  22. +0
    -2
      deploy/k8s/deploy-ingress.ps1
  23. +20
    -0
      deploy/k8s/enable-tls.ps1
  24. +7
    -2
      deploy/k8s/helm/apigwmm/templates/ingress.yaml
  25. +27
    -12
      deploy/k8s/helm/apigwms/envoy.yaml
  26. +7
    -2
      deploy/k8s/helm/apigwms/templates/ingress.yaml
  27. +6
    -1
      deploy/k8s/helm/apigwwm/templates/ingress.yaml
  28. +25
    -10
      deploy/k8s/helm/apigwws/envoy.yaml
  29. +6
    -1
      deploy/k8s/helm/apigwws/templates/ingress.yaml
  30. +0
    -42
      deploy/k8s/helm/basket-api/templates/ingress.yaml
  31. +8
    -0
      deploy/k8s/helm/catalog-api/templates/_names.tpl
  32. +2
    -1
      deploy/k8s/helm/catalog-api/templates/configmap.yaml
  33. +0
    -42
      deploy/k8s/helm/catalog-api/templates/ingress.yaml
  34. +50
    -9
      deploy/k8s/helm/deploy-all.ps1
  35. +6
    -1
      deploy/k8s/helm/identity-api/templates/ingress.yaml
  36. +4
    -1
      deploy/k8s/helm/inf.yaml
  37. +0
    -325
      deploy/k8s/helm/istio/doc.md
  38. +0
    -15
      deploy/k8s/helm/istio/gateway.yml
  39. +0
    -59
      deploy/k8s/helm/istio/virtualservices.yml
  40. +0
    -41
      deploy/k8s/helm/locations-api/templates/ingress.yaml
  41. +8
    -0
      deploy/k8s/helm/marketing-api/templates/_names.tpl
  42. +3
    -2
      deploy/k8s/helm/marketing-api/templates/configmap.yaml
  43. +0
    -41
      deploy/k8s/helm/marketing-api/templates/ingress.yaml
  44. +0
    -41
      deploy/k8s/helm/mobileshoppingagg/templates/ingress.yaml
  45. +21
    -0
      deploy/k8s/helm/tls-support/.helmignore
  46. +5
    -0
      deploy/k8s/helm/tls-support/Chart.yaml
  47. +32
    -0
      deploy/k8s/helm/tls-support/templates/_helpers.tpl
  48. +17
    -0
      deploy/k8s/helm/tls-support/templates/issuer.yaml
  49. +8
    -0
      deploy/k8s/helm/tls-support/values-prod.yaml
  50. +8
    -0
      deploy/k8s/helm/tls-support/values-staging.yaml
  51. +9
    -0
      deploy/k8s/helm/webhooks-api/templates/_names.tpl
  52. +2
    -1
      deploy/k8s/helm/webhooks-api/templates/configmap.yaml
  53. +7
    -2
      deploy/k8s/helm/webhooks-api/templates/ingress.yaml
  54. +9
    -0
      deploy/k8s/helm/webhooks-web/templates/_names.tpl
  55. +4
    -3
      deploy/k8s/helm/webhooks-web/templates/configmap.yaml
  56. +15
    -3
      deploy/k8s/helm/webhooks-web/templates/ingress.yaml
  57. +8
    -0
      deploy/k8s/helm/webmvc/templates/_names.tpl
  58. +4
    -3
      deploy/k8s/helm/webmvc/templates/configmap.yaml
  59. +6
    -1
      deploy/k8s/helm/webmvc/templates/ingress.yaml
  60. +0
    -41
      deploy/k8s/helm/webshoppingagg/templates/ingress.yaml
  61. +8
    -0
      deploy/k8s/helm/webspa/templates/_names.tpl
  62. +5
    -5
      deploy/k8s/helm/webspa/templates/configmap.yaml
  63. +10
    -3
      deploy/k8s/helm/webspa/templates/ingress.yaml
  64. +0
    -2
      deploy/k8s/helm/webstatus/templates/_names.tpl
  65. +0
    -1
      deploy/k8s/helm/webstatus/templates/configmap.yaml
  66. +10
    -3
      deploy/k8s/helm/webstatus/templates/ingress.yaml
  67. +16
    -33
      deploy/k8s/helm/webstatus/values.yaml
  68. BIN
      deploy/k8s/nginx-ingress/cm.yaml
  69. +11
    -0
      deploy/k8s/nginx-ingress/local-cm.yaml
  70. +0
    -0
      deploy/k8s/nginx-ingress/local-svc.yaml
  71. +0
    -0
      deploy/windows/add-firewall-rules-for-sts-auth-thru-docker.ps1
  72. +0
    -0
      deploy/windows/set-dockernat-networkategory-to-private.ps1
  73. BIN
      img/eShopOnContainers-Architecture-With-Azure-API-Management.png
  74. BIN
      img/eShopOnContainers-architecture.png
  75. BIN
      img/eShopOnContainers_Types_Of_Microservices.png
  76. BIN
      img/eshop-webspa-app-screenshot.png
  77. BIN
      img/new-folder-structure.png
  78. BIN
      img/vs-solution-structure.png
  79. BIN
      img/xamarin-mobile-App.png
  80. +27
    -12
      src/ApiGateways/Envoy/config/mobileshopping/envoy.yaml
  81. +25
    -10
      src/ApiGateways/Envoy/config/webshopping/envoy.yaml
  82. +2
    -2
      src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile
  83. +13
    -13
      src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
  84. +1
    -1
      src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs
  85. +2
    -2
      src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile
  86. +15
    -14
      src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj
  87. +2
    -2
      src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj
  88. +1
    -1
      src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
  89. +5
    -5
      src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj
  90. +3
    -3
      src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj
  91. +5
    -5
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj
  92. +8
    -8
      src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj
  93. +19
    -18
      src/Services/Basket/Basket.API/Basket.API.csproj
  94. +2
    -2
      src/Services/Basket/Basket.API/Dockerfile
  95. +5
    -5
      src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj
  96. +6
    -8
      src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj
  97. +20
    -19
      src/Services/Catalog/Catalog.API/Catalog.API.csproj
  98. +2
    -2
      src/Services/Catalog/Catalog.API/Dockerfile
  99. +4
    -4
      src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj
  100. +100
    -58
      src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs

+ 34
- 159
README.md View File

@ -1,48 +1,46 @@
# eShopOnContainers - Microservices Architecture and Containers based Reference Application (**BETA state** - Visual Studio and CLI environments compatible)
<a href="https://dot.net/architecture">
<img src="https://github.com/dotnet-architecture/eShopOnContainers/raw/dev/img/eshop_logo.png" alt="eShop logo" title="eShopOnContainers" align="right" height="60" />
</a>
Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers.
## Linux Build Status for 'dev' branch
# .NET Microservices Sample Reference Application
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):
Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers.
| 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) |
![](img/eshop-webmvc-app-screenshot.png)
| 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)
## Azure DevOps - Build Status
| Web Shopping Aggregator | Mobile Shopping Aggregator | WebMVC Client | WebSPA Client |
| Image | Status | Image | Status |
| ------------- | ------------- | ------------- | ------------- |
| [![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) |
| Api Gateway (base) | [![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) | Shopping Aggregator (Web) | [![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) |
| 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) | Shopping Aggregator (Mobile) | [![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) |
| 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) | Web Client (MVC) | [![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) |
|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) | Web Client (SPA) | [![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) |
| 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) | Web Status (Health) | [![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) |
| 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) | 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) |
| 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) | Webhooks 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) |
| 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) | | |
| Web Status | Webhooks API | Webhooks 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) |
_**Dev** branch contains the latest **beta** code and their images are tagged with `:dev` in our [Docker Hub](https://hub.docker.com/u/eshop)_
## Getting Started
eShopOnContainers is provided in "two flavors":
- Basic scenario: Can be run locally using docker compose, and also deployed to a local Kubernetes cluster
- Production scenario: Can only be deployed on a Kubernetes cluster (local or in the cloud like AKS), and enable production features like the use of a Service Mesh.
eShopOnContainers is provided in two flavors: Basic and Advanced.
### Basic scenario
You can run eShop locally:
The basic scenario can be run locally using docker compose, and also deployed to a local Kubernetes cluster. Refer these Wiki pages to Get Started:
- [Using Visual Studio](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Windows-setup)
- Using CLI or Visual Studio Code
- Using docker compose
- Using local Kubernetes
- [CLI or Visual Studio Code](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Windows-setup)
- [Visual Studio (F5 experience)](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Windows-setup#optional---use-visual-studio)
- [Docker compose](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Docker-compose-deployment-files)
- [Local Kubernetes](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Deploy-to-Local-Kubernetes)
### Advanced scenario
The Advanced scenario can be run only in a Kubernetes cluster. Currently this scenario is the same as basic scenario with the following differences:
- Use of a Service Mesh for Resiliency
- [Deploy to AKS with a Service Mesh for resiliency](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Deploy-to-Azure-Kubernetes-Service-(AKS))
In the future more features will be implemented in the advanced scenario.
@ -57,72 +55,15 @@ Do you want to be up-to-date on .NET Architecture guidance and reference apps li
## Updated for .NET Core 3.0
eShopOnContainers is updated to .NET Core 3.0 "wave" of technologies. Not just compilation but also new recommended code in EF Core, ASP.NET Core, and other new related versions.
### Details on the latest mayor release
- Migrate solution from ASP.NET Core 2.2 to 3.0 and update all projects to use the latest .NET Core 3.0 templates.
- Implement the new .NET Core 3.0 WorkerService in Ordering.API and other background processes.
- Improve Ordering.API
- Group order items
- apply discounts from Marketing.API
- Handle two deployment scenarios
- Basic deployment, better for learning:
- Docker compose
- Local Kubernetes
- Visual Studio F5 experience
- Advanced deployment, complex but more real-life:
- Sidecar implementation with Envoy/Linkerd
- Improved API Gateway and resilience
- gRPC for inter-service communications
- Test and Support Azure Dev Spaces
eShopOnContainers is updated to .NET Core 3.0 "wave" of technologies. Not just compilation but also new recommended code in EF Core, ASP.NET Core, and other new related versions and a several significant changes.
### New folder structure
The repo also has a new, simpler, folder structure, as shown in the following image:
![](img/new-folder-structure.png)
In the above image you can see that the first folder level contains, basically:
- **build**: Scripts for building Docker images.
- **deploy**: Scripts for deployment.
- **src**: All source projects, including tests.
- **ApiGateways**: Envoy configuration and Aggregators source code.
- **BuildBlocks**: Common components used by several projects.
- **Mobile**: Mobile apps projects.
- **Services**: Backend for all services. Including unit and functional tests for some projects.
- Basket
- Catalog
- Identity
- Location
- Marketing
- Ordering
- Payment
- Webhooks
- **Tests**: General functional application tests.
- **test-results**: Test results
- **Web**: Web applications
**See more details in the [Release notes](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Release-notes) wiki page**.
>**PLEASE** Read our [branch guide](./branch-guide.md) to know about our branching policy
>
> ### DISCLAIMER
>
> **IMPORTANT:** The current state of this sample application is **BETA**, because we are constantly evolving towards newly released technologies. Therefore, many areas could be improved and change significantly while refactoring the current code and implementing new features. Feedback with improvements and pull requests from the community will be highly appreciated and accepted.
>
> This reference application proposes a simplified microservice oriented architecture implementation to introduce technologies like .NET Core with Docker containers through a comprehensive application. The chosen domain is eShop/eCommerce but simply because it is a well-known domain by most people/developers.
However, this sample application should not be considered as an "eCommerce reference model" at all. The implemented business domain might not be ideal from an eCommerce business point of view. It is neither trying to solve all the problems in a large, scalable and mission-critical distributed system. It is just a bootstrap for developers to easily get started in the world of Docker containers and microservices with .NET Core.
>
> For example, the next step after running the solution in the local dev PC and understanding Docker containers and microservices development with .NET Core, is to select a microservice cluster/orchestrator like Kubernetes in Azure (AKS) or Azure Service Fabric, both environments tested and supported by this solution.
> Additional steps would be to move your databases to HA cloud services (like Azure SQL Database) or switch your EventBus to use Azure Service Bus (instead of bare-bone RabbitMQ) or any other production-ready Service Bus in the market.
![image](https://user-images.githubusercontent.com/1712635/40397331-059a7ec6-5de7-11e8-8542-a597eca16fef.png)
> Read the planned [Roadmap](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Roadmap) within the Wiki for further info about possible new implementations and provide feedback at the [ISSUES section](https://github.com/dotnet/eShopOnContainers/issues) if you'd like to see any specific scenario implemented or improved. Also, feel free to discuss on any current issue.
### Architecture overview
@ -130,38 +71,7 @@ This reference application is cross-platform at the server and client side, than
The architecture proposes a microservice oriented architecture implementation with multiple autonomous microservices (each one owning its own data/db) and implementing different approaches within each microservice (simple CRUD vs. DDD/CQRS patterns) using Http as the communication protocol between the client apps and the microservices and supports asynchronous communication for data updates propagation across multiple services based on Integration Events and an Event Bus (a light message broker, to choose between RabbitMQ or Azure Service Bus, underneath) plus other features defined at the [roadmap](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Roadmap).
![](img/eshop_logo.png)
![](https://user-images.githubusercontent.com/1712635/38758862-d4b42498-3f27-11e8-8dad-db60b0fa05d3.png)
> ### Important Note on API Gateways and published APIs
>
> Since April 2018, we have introduced the implementation of the [API Gateway pattern](http://microservices.io/patterns/apigateway.html) and [Backend-For-Front-End (BFF) pattern](https://samnewman.io/patterns/architectural/bff/) in eShopOnContainers architecture, so you can filter and publish simplified APIs and URIs and apply additional security in that tier while hiding/securing the internal microservices to the client apps or outside consumers. These sample API Gateways in eShopOnContainers are based on [Envoy](https://www.envoyproxy.io/), an OSS, production-grade API Gateway and proxy [described in the official documentation page](https://www.envoyproxy.io/docs/envoy/latest/). The deployed API Gateways are autonomous and can be deployed as your own custom microservices/containers, as it is currently done in eShopOnContainers, so you can test it even in a simple development environment with just Docker engine or deploy it into orchestrators like Kubernetes in AKS or Service Fabric.
>
> For your production-ready architecture you can either keep using Envoy or, if you need further functionality and a much richer set of features suitable for commercial APIs, you can also substitute those API Gateways and use [Azure API Management](https://azure.microsoft.com/services/api-management/) or any other commercial API Gateway.
![](img/eShopOnContainers-Architecture-With-Azure-API-Management.png)
> The sample code in this repo is NOT making use of Azure API Management in order to be able to provide an "F5 experience" in Visual Studio (or CLI) of the sample with no up-front dependencies in Azure. But you could evaluate API Gateways alternatives when building for production.
>
> ### Internal architecture and design of the microservices
>
> The microservices are different in type, meaning different internal architecture pattern approaches depending on its purpose, as shown in the image below.
![](img/eShopOnContainers_Types_Of_Microservices.png)
> ### Important Note on Database Servers/Containers
>
> In this solution's current configuration for a development environment, the SQL databases are automatically deployed with sample data into a single SQL Server container (a single shared Docker container for SQL databases) so the whole solution can be up and running without any dependency to any cloud or a specific server. Each database could also be deployed as a single Docker container, but then you'd need more than 8GB of RAM assigned to Docker in your development machine in order to be able to run 3 SQL Server Docker containers in your Docker Linux host in "Docker for Windows" or "Docker for Mac" development environments.
>
> A similar case is defined in regard to Redis cache running as a container for the development environment. Or a No-SQL database (MongoDB) running as a container.
>
> However, in a real production environment it is recommended to have your databases (SQL Server, Redis, and the NO-SQL database, in this case) in HA (High Available) services like Azure SQL Database, Redis as a service and Azure CosmosDB instead the MongoDB container (as both systems share the same access protocol). If you want to change to a production configuration, you'll just need to change the connection strings once you have set up the servers in an HA cloud or on-premises.
>
> ### Important Note on EventBus
>
> In this solution's current EventBus is a simplified implementation, mainly used for learning purposes (development and testing), so it doesn't handle all production scenarios, most notably on error handling.
> The following fork provides production environment level implementation examples with eShopOnContainers:
>
> - Implementation with [NServiceBus](https://github.com/Particular/NServiceBus) : <https://github.com/Particular/eShopOnContainers>
![](img/eShopOnContainers-architecture.png)
## Related documentation and guidance
@ -172,55 +82,20 @@ You can download them and start reviewing these Guides/eBooks here:
| Architecting & Developing | Containers Lifecycle & CI/CD | App patterns with Xamarin.Forms |
| ------------ | ------------| ------------|
| <a href='https://aka.ms/microservicesebook'><img src="img/Microservices-cover-small.png"> </a> | <a href='https://aka.ms/dockerlifecycleebook'> <img src="img/DevOps-Cover-small.png"> </a> | <a href='https://aka.ms/xamarinpatternsebook'> <img src="img/xamarin-enterprise-patterns-ebook-cover-small.png"> </a> |
| [![](img/Microservices-cover-small.png)](https://aka.ms/microservicesebook) | [![](img/DevOps-Cover-small.png)](https://aka.ms/dockerlifecycleebook) | [![](img/xamarin-enterprise-patterns-ebook-cover-small.png)](https://aka.ms/xamarinpatternsebook) |
| <sup> <a href='https://aka.ms/microservicesebook'>**Download .PDF**</a> </sup> | <sup> <a href='https://aka.ms/dockerlifecycleebook'>**Download** </a> </sup> | <sup> <a href='https://aka.ms/xamarinpatternsebook'>**Download** </a> </sup> |
Download in other formats (**eReaders** like **MOBI**, **EPUB**) and other eBooks at the [.NET Architecture center](http://dot.net/architecture).
Send feedback to [dotnet-architecture-ebooks-feedback@service.microsoft.com](dotnet-architecture-ebooks-feedback@service.microsoft.com)
However, we encourage you to download and review the [Architecting and Developing Microservices eBook](https://aka.ms/microservicesebook) because the architectural styles and architectural patterns and technologies explained in the guide are using this reference application when explaining many pattern implementations, so you'll understand the context, design and decisions taken in the current architecture and internal designs much better.
## Overview of the application code
In this repo you can find a sample reference application that will help you to understand how to implement a microservice architecture based application using **.NET Core** and **Docker**.
The example business domain or scenario is based on an eShop or eCommerce which is implemented as a multi-container application. Each container is a microservice deployment (like the basket-microservice, catalog-microservice, ordering-microservice and the identity-microservice) which is developed using ASP.NET Core running on .NET Core so they can run either on Linux Containers and Windows Containers.
The screenshot below shows the VS Solution structure for those microservices/containers and client apps.
- (*Recommended when getting started*) Open **eShopOnContainers-ServicesAndWebApps.sln** for a solution containing just the server-side projects related to the microservices and web applications.
- Open <b>eShopOnContainers-MobileApps.sln</b> for a solution containing just the client mobile app projects (Xamarin mobile apps only). It works independently based on mocks, too.
- Open <b>eShopOnContainers.sln</b> for a solution containing all the projects (All client apps and services).
<img src="img/vs-solution-structure.png">
Finally, those microservices are consumed by multiple client web and mobile apps, as described below.
<br>
<b>*MVC Application (ASP.NET Core)*</b>: It's an MVC application where you can find interesting scenarios on how to consume HTTP-based microservices from C# running in the server side, as it is a typical ASP.NET Core MVC application. Since it is a server-side application, access to other containers/microservices is done within the internal Docker Host network with its internal name resolution.
<img src="img/eshop-webmvc-app-screenshot.png">
<br>
<b>*SPA (Single Page Application)*</b>: Providing similar "eShop business functionality" but developed with Angular, Typescript and slightly using ASP.NET Core MVC. This is another approach for client web applications to be used when you want to have a more modern client behavior which is not behaving with the typical browser round-trip on every action but behaving like a Single-Page-Application which is more similar to a desktop app usage experience. The consumption of the HTTP-based microservices is done from TypeScript/JavaScript in the client browser, so the client calls to the microservices come from out of the Docker Host internal network (Like from your network or even from the Internet).
<img src="img/eshop-webspa-app-screenshot.png">
<br>
<b>*Xamarin Mobile App (For iOS, Android and Windows/UWP)*</b>: It is a client mobile app supporting the most common mobile OS platforms (iOS, Android and Windows/UWP). In this case, the consumption of the microservices is done from C# but running on the client devices, so out of the Docker Host internal network (Like from your network or even the Internet).
<img src="img/xamarin-mobile-App.png">
## Setting up your development environment for eShopOnContainers
### Windows based (CLI and Visual Studio)
<https://github.com/dotnet-architecture/eShopOnContainers/wiki/Windows-setup>
### Mac based (CLI and Visual Studio for Mac)
If you have an e-book feedback, create a new issue here: <https://github.com/dotnet-architecture/ebooks/issues>
<https://github.com/dotnet-architecture/eShopOnContainers/wiki/Mac-setup>
However, we encourage you to download and review the [.NET Microservices: Architecture for Containerized .NET Applications e-book](https://aka.ms/microservicesebook) because the architectural styles, patterns, and technologies explained in the guide use this reference application when explaining most implementations, so you'll understand the context, design and decisions taken in the current architecture and internal designs much better.
## Orchestrators: Kubernetes and Service Fabric
## Read further
See at the [Wiki](https://github.com/dotnet-architecture/eShopOnContainers/wiki) the posts on setup/instructions about how to deploy to Kubernetes or Service Fabric in Azure (although you could also deploy to any other cloud or on-premises).
- [Explore the application](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Explore-the-application)
- [Explore the code](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Explore-the-code)
## Sending feedback and pull requests
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**
Read the planned [Roadmap](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Roadmap) within the Wiki for further info about possible new implementations and provide feedback at the [ISSUES section](https://github.com/dotnet/eShopOnContainers/issues) if you'd like to see any specific scenario implemented or improved. Also, feel free to discuss on any current issue.

+ 17
- 17
build/azure-devops/apigws/azure-pipelines.yml View File

@ -1,5 +1,3 @@
variables:
registryEndpoint: eshop-registry
trigger:
branches:
include:
@ -8,22 +6,24 @@ trigger:
paths:
include:
- src/ApiGateways/*
- k8s/helm/apigwmm/*
- k8s/helm/apigwms/*
- k8s/helm/apigwwm/*
- k8s/helm/apigwws/*
- deploy/k8s/helm/apigwmm/*
- deploy/k8s/helm/apigwms/*
- deploy/k8s/helm/apigwwm/*
- deploy/k8s/helm/apigwws/*
exclude:
- src/ApiGateways/Mobile.Bff.Shopping/aggregator/*
- src/ApiGateways/Web.Bff.Shopping/aggregator/*
jobs:
- template: ../buildimages.yaml
parameters:
services: mobileshoppingapigw mobilemarketingapigw webshoppingapigw webmarketingapigw
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
- template: ../multiarch.yaml
parameters:
image: ocelotapigw
branch: $(Build.SourceBranchName)
registryEndpoint: $(registryEndpoint)
- job: PublishCharts
condition: ne('$(Build.Reason)', 'PullRequest')
pool:
vmImage: 'ubuntu-16.04'
steps:
- task: CopyFiles@2
inputs:
sourceFolder: $(Build.SourcesDirectory)/deploy/k8s/helm
targetFolder: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
artifactName: helm

+ 4
- 4
build/azure-devops/basket-api/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Services/Basket/*
- k8s/helm/basket-api/*
- deploy/k8s/helm/basket-api/*
jobs:
- template: ../buildimages.yaml
parameters:
services: basket.api
services: basket-api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: basket.api


+ 8
- 6
build/azure-devops/buildimages.yaml View File

@ -13,16 +13,17 @@ jobs:
- bash: docker-compose build ${{ parameters.services }}
displayName: Create multiarch manifest
env:
TAG: ${{ variables['Build.SourceBranchName'] }}
TAG: ${{ variables['Build.SourceBranchName'] }}
- job: BuildContainersForPR_Windows
condition: eq('${{ variables['Build.Reason'] }}', 'PullRequest')
condition: False
# condition: eq('${{ variables['Build.Reason'] }}', 'PullRequest')
pool:
vmImage: 'windows-2019'
steps:
- bash: docker-compose build ${{ parameters.services }}
displayName: Create multiarch manifest
env:
TAG: ${{ variables['Build.SourceBranchName'] }}
TAG: ${{ variables['Build.SourceBranchName'] }}
PLATFORM: win
NODE_IMAGE: stefanscherer/node-windows:10
- job: BuildLinux
@ -51,7 +52,7 @@ jobs:
qualifyImageNames: true
projectName: ""
dockerComposeFileArgs: |
TAG=${{ variables['Build.SourceBranchName'] }}
TAG=${{ variables['Build.SourceBranchName'] }}
- task: CopyFiles@2
inputs:
sourceFolder: ${{ parameters.helmfrom }}
@ -61,7 +62,8 @@ jobs:
pathtoPublish: ${{ parameters.helmto }}
artifactName: helm
- job: BuildWindows
condition: ne('${{ variables['Build.Reason'] }}', 'PullRequest')
condition: False
# condition: ne('${{ variables['Build.Reason'] }}', 'PullRequest')
pool:
vmImage: 'windows-2019'
steps:
@ -89,4 +91,4 @@ jobs:
projectName: ""
dockerComposeFileArgs: |
TAG=${{ variables['Build.SourceBranchName'] }}
PLATFORM=win
PLATFORM=win

+ 4
- 4
build/azure-devops/catalog-api/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Services/Catalog/*
- k8s/helm/catalog-api/*
- deploy/k8s/helm/catalog-api/*
jobs:
- template: ../buildimages.yaml
parameters:
services: catalog.api
services: catalog-api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: catalog.api


+ 4
- 4
build/azure-devops/identity-api/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Services/Identity/*
- k8s/helm/identity-api/*
- deploy/k8s/helm/identity-api/*
jobs:
- template: ../buildimages.yaml
parameters:
services: identity.api
services: identity-api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: identity.api


+ 8
- 8
build/azure-devops/infrastructure/azure-pipelines.yml View File

@ -9,17 +9,17 @@ trigger:
- dev
paths:
include:
- k8s/helm/basket-data/*
- k8s/helm/keystore-data/*
- k8s/helm/nosql-data/*
- k8s/helm/rabbitmq/*
- k8s/helm/sql-data/*
- deploy/k8s/helm/basket-data/*
- deploy/k8s/helm/keystore-data/*
- deploy/k8s/helm/nosql-data/*
- deploy/k8s/helm/rabbitmq/*
- deploy/k8s/helm/sql-data/*
steps:
- task: CopyFiles@2
inputs:
sourceFolder: $(Build.SourcesDirectory)/k8s/helm
targetFolder: $(Build.ArtifactStagingDirectory)/k8s/helm
sourceFolder: $(Build.SourcesDirectory)/deploy/k8s/helm
targetFolder: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: $(Build.ArtifactStagingDirectory)/k8s/helm
pathtoPublish: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
artifactName: helm

+ 4
- 4
build/azure-devops/location-api/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Services/Location/*
- k8s/helm/locations-api/*
- deploy/k8s/helm/locations-api/*
jobs:
- template: ../buildimages.yaml
parameters:
services: locations.api
services: locations-api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: locations.api


+ 4
- 4
build/azure-devops/marketing-api/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Services/Marketing/*
- k8s/helm/marketing-api/*
- deploy/k8s/helm/marketing-api/*
jobs:
- template: ../buildimages.yaml
parameters:
services: marketing.api
services: marketing-api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: marketing.api


+ 3
- 3
build/azure-devops/mobile-shopping-agg/azure-pipelines.yml View File

@ -8,14 +8,14 @@ trigger:
paths:
include:
- src/ApiGateways/Mobile.Bff.Shopping/aggregator/*
- k8s/helm/mobileshoppingagg/*
- deploy/k8s/helm/mobileshoppingagg/*
jobs:
- template: ../buildimages.yaml
parameters:
services: mobileshoppingagg
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: mobileshoppingagg


+ 6
- 6
build/azure-devops/ordering-api/azure-pipelines.yml View File

@ -9,16 +9,16 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Services/Ordering/*
- k8s/helm/ordering-api/*
- k8s/helm/ordering-backgroundtasks/*
- k8s/helm/ordering-signalrhub/*
- deploy/k8s/helm/ordering-api/*
- deploy/k8s/helm/ordering-backgroundtasks/*
- deploy/k8s/helm/ordering-signalrhub/*
jobs:
- template: ../buildimages.yaml
parameters:
services: ordering.api
services: ordering-api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: ordering.api


+ 5
- 5
build/azure-devops/payment-api/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Services/Payment/*
- k8s/helm/payment-api/*
- deploy/k8s/helm/payment-api/*
jobs:
- template: ../buildimages.yaml
parameters:
services: payment.api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
services: payment-api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: payment.api


+ 3
- 3
build/azure-devops/readme.md View File

@ -1,5 +1,5 @@
# Azure Devops build definitions
# Azure DevOps build definitions
This folder contains the Azure Devops build definitions in YAML format. Each folder contains one `azure-pipelines.yml` that contains the build definition for one microservice (usually a Docker image, but some microservices generates more than one Docker image).
This folder contains the Azure DevOps build definitions in YAML format. Each folder contains one `azure-pipelines.yml` that contains the build definition for one microservice (usually a Docker image, but some microservices generates more than one Docker image).
For more information about YAML builds read the [Azure DevOps documentation](https://docs.microsoft.com/en-us/azure/devops/pipelines/get-started-yaml?view=azure-devops).
For more information about YAML builds read the [Azure DevOps documentation](https://docs.microsoft.com/azure/devops/pipelines/get-started-yaml?view=azure-devops).

+ 4
- 4
build/azure-devops/web-shopping-agg/azure-pipelines.yml View File

@ -8,14 +8,14 @@ trigger:
paths:
include:
- src/ApiGateways/Web.Bff.Shopping/aggregator/*
- k8s/helm/webshoppingagg/*
- deploy/k8s/helm/webshoppingagg/*
jobs:
- template: ../buildimages.yaml
parameters:
services: webshoppingagg
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: webshoppingagg


+ 5
- 5
build/azure-devops/webhooks-api/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Services/Webhooks/*
- k8s/helm/webhooks-api/*
- deploy/k8s/helm/webhooks-api/*
jobs:
- template: ../buildimages.yaml
parameters:
services: webhooks.api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
services: webhooks-api
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: webhooks.api


+ 5
- 5
build/azure-devops/webhooks-client/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Web/WebhookClient/*
- k8s/helm/webhooks-web/*
- deploy/k8s/helm/webhooks-web/*
jobs:
- template: ../buildimages.yaml
parameters:
services: webhooks.client
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
services: webhooks-client
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: webhooks.client


+ 4
- 4
build/azure-devops/webmvc/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Web/WebMVC/*
- k8s/helm/webmvc/*
- deploy/k8s/helm/webmvc/*
jobs:
- template: ../buildimages.yaml
parameters:
services: webmvc
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: webmvc


+ 4
- 4
build/azure-devops/webspa/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Web/WebSPA/*
- k8s/helm/webspa/*
- deploy/k8s/helm/webspa/*
jobs:
- template: ../buildimages.yaml
parameters:
services: webspa
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: webspa


+ 4
- 4
build/azure-devops/webstatus/azure-pipelines.yml View File

@ -9,14 +9,14 @@ trigger:
include:
- src/BuildingBlocks/*
- src/Web/WebStatus/*
- k8s/helm/webstatus/*
- deploy/k8s/helm/webstatus/*
jobs:
- template: ../buildimages.yaml
parameters:
services: webstatus
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/k8s/helm
registryEndpoint: $(registryEndpoint)
helmfrom: $(Build.SourcesDirectory)/deploy/k8s/helm
helmto: $(Build.ArtifactStagingDirectory)/deploy/k8s/helm
- template: ../multiarch.yaml
parameters:
image: webstatus


+ 18
- 0
deploy/k8s/dashboard-adminuser.yaml View File

@ -0,0 +1,18 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard

+ 0
- 2
deploy/k8s/deploy-ingress-dockerlocal.ps1 View File

@ -1,2 +0,0 @@
kubectl apply -f nginx-ingress\cm.yaml
kubectl apply -f nginx-ingress\cloud-generic.yaml

+ 0
- 2
deploy/k8s/deploy-ingress.ps1 View File

@ -1,2 +0,0 @@
# Deploy nginx-ingress core files
kubectl apply -f nginx-ingress\mandatory.yaml

+ 20
- 0
deploy/k8s/enable-tls.ps1 View File

@ -0,0 +1,20 @@
Param (
[parameter(Mandatory=$false)][string]$aksName="",
[parameter(Mandatory=$false)][string]$aksRg=""
)
if ($aksName -and $aksRg) {
$aks=$(az aks show -n $aksName -g $aksRg -o json | ConvertFrom-Json)
if (-not $aks) {
Write-Host "AKS $aksName not found in RG $aksRg" -ForegroundColor Red
exit 1
}
Write-Host "Switching kubectl context to $aksRg/$aksName" -ForegroundColor Yellow
az aks get-credentials -g $aksRg -n $aksName
}
Write-Host "Installing cert-manager on current cluster"
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.11.0/cert-manager.yaml --validate=false

+ 7
- 2
deploy/k8s/helm/apigwmm/templates/ingress.yaml View File

@ -14,6 +14,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -24,12 +27,14 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:


+ 27
- 12
deploy/k8s/helm/apigwms/envoy.yaml View File

@ -42,13 +42,20 @@ static_resources:
route:
auto_host_rewrite: true
prefix_rewrite: "/ordering-api/"
cluster: ordering
cluster: ordering
- name: "o-long"
match:
prefix: "/ordering-api/"
route:
auto_host_rewrite: true
cluster: ordering
cluster: ordering
- name: "h-long"
match:
prefix: "/hub/notificationhub"
route:
auto_host_rewrite: true
cluster: signalr-hub
timeout: 300s
- name: "b-short"
match:
prefix: "/b/"
@ -61,7 +68,7 @@ static_resources:
prefix: "/basket-api/"
route:
auto_host_rewrite: true
cluster: basket
cluster: basket
- name: "agg"
match:
prefix: "/"
@ -70,25 +77,25 @@ static_resources:
prefix_rewrite: "/"
cluster: shoppingagg
http_filters:
- name: envoy.router
- name: envoy.router
access_log:
- name: envoy.file_access_log
filter:
not_health_check_filter: {}
not_health_check_filter: {}
config:
json_format:
time: "%START_TIME%"
protocol: "%PROTOCOL%"
duration: "%DURATION%"
request_method: "%REQ(:METHOD)%"
request_host: "%REQ(HOST)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
request_method: "%REQ(:METHOD)%"
request_host: "%REQ(HOST)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
response_flags: "%RESPONSE_FLAGS%"
route_name: "%ROUTE_NAME%"
upstream_host: "%UPSTREAM_HOST%"
upstream_cluster: "%UPSTREAM_CLUSTER%"
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
path: "/tmp/access.log"
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
path: "/tmp/access.log"
clusters:
- name: shoppingagg
connect_timeout: 0.25s
@ -113,7 +120,7 @@ static_resources:
hosts:
- socket_address:
address: basket-api
port_value: 80
port_value: 80
- name: ordering
connect_timeout: 0.25s
type: strict_dns
@ -121,4 +128,12 @@ static_resources:
hosts:
- socket_address:
address: ordering-api
port_value: 80
port_value: 80
- name: signalr-hub
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
hosts:
- socket_address:
address: ordering-signalrhub
port_value: 80

+ 7
- 2
deploy/k8s/helm/apigwms/templates/ingress.yaml View File

@ -15,6 +15,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -25,12 +28,14 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:


+ 6
- 1
deploy/k8s/helm/apigwwm/templates/ingress.yaml View File

@ -15,6 +15,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -25,7 +28,9 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}


+ 25
- 10
deploy/k8s/helm/apigwws/envoy.yaml View File

@ -42,13 +42,20 @@ static_resources:
route:
auto_host_rewrite: true
prefix_rewrite: "/ordering-api/"
cluster: ordering
cluster: ordering
- name: "o-long"
match:
prefix: "/ordering-api/"
route:
auto_host_rewrite: true
cluster: ordering
cluster: ordering
- name: "h-long"
match:
prefix: "/hub/notificationhub"
route:
auto_host_rewrite: true
cluster: signalr-hub
timeout: 300s
- name: "b-short"
match:
prefix: "/b/"
@ -61,7 +68,7 @@ static_resources:
prefix: "/basket-api/"
route:
auto_host_rewrite: true
cluster: basket
cluster: basket
- name: "agg"
match:
prefix: "/"
@ -70,7 +77,7 @@ static_resources:
prefix_rewrite: "/"
cluster: shoppingagg
http_filters:
- name: envoy.router
- name: envoy.router
access_log:
- name: envoy.file_access_log
filter:
@ -80,15 +87,15 @@ static_resources:
time: "%START_TIME%"
protocol: "%PROTOCOL%"
duration: "%DURATION%"
request_method: "%REQ(:METHOD)%"
request_host: "%REQ(HOST)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
request_method: "%REQ(:METHOD)%"
request_host: "%REQ(HOST)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
response_flags: "%RESPONSE_FLAGS%"
route_name: "%ROUTE_NAME%"
upstream_host: "%UPSTREAM_HOST%"
upstream_cluster: "%UPSTREAM_CLUSTER%"
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
path: "/tmp/access.log"
path: "/tmp/access.log"
clusters:
- name: shoppingagg
connect_timeout: 0.25s
@ -113,7 +120,7 @@ static_resources:
hosts:
- socket_address:
address: basket-api
port_value: 80
port_value: 80
- name: ordering
connect_timeout: 0.25s
type: strict_dns
@ -121,4 +128,12 @@ static_resources:
hosts:
- socket_address:
address: ordering-api
port_value: 80
port_value: 80
- name: signalr-hub
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
hosts:
- socket_address:
address: ordering-signalrhub
port_value: 80

+ 6
- 1
deploy/k8s/helm/apigwws/templates/ingress.yaml View File

@ -14,6 +14,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -24,7 +27,9 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}


+ 0
- 42
deploy/k8s/helm/basket-api/templates/ingress.yaml View File

@ -1,42 +0,0 @@
{{- 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 }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- 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 }}

+ 8
- 0
deploy/k8s/helm/catalog-api/templates/_names.tpl View File

@ -49,4 +49,12 @@
{{- else -}}
{{- .Values.image.repository -}}
{{- end -}}
{{- end -}}
{{- define "protocol" -}}
{{- if .Values.inf.tls.enabled -}}
{{- printf "%s" "https" -}}
{{- else -}}
{{- printf "%s" "http" -}}
{{- end -}}
{{- end -}}

+ 2
- 1
deploy/k8s/helm/catalog-api/templates/configmap.yaml View File

@ -1,6 +1,7 @@
{{- $name := include "catalog-api.fullname" . -}}
{{- $sqlsrv := include "sql-name" . -}}
{{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}}
{{- $protocol := include "protocol" . -}}
apiVersion: v1
kind: ConfigMap
@ -13,7 +14,7 @@ metadata:
heritage: {{ .Release.Service }}
data:
catalog__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.catalog.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }};
catalog__PicBaseUrl: http://{{ $webshoppingapigw }}/c/api/v1/catalog/items/[0]/pic/
catalog__PicBaseUrl: {{ $protocol }}://{{ $webshoppingapigw }}/c/api/v1/catalog/items/[0]/pic/
catalog__AzureStorageEnabled: "{{ .Values.inf.misc.useAzureStorage }}"
all__EventBusConnection: {{ .Values.inf.eventbus.constr }}
all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}"

+ 0
- 42
deploy/k8s/helm/catalog-api/templates/ingress.yaml View File

@ -1,42 +0,0 @@
{{- 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 }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- 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 }}

+ 50
- 9
deploy/k8s/helm/deploy-all.ps1 View File

@ -13,11 +13,49 @@ Param(
[parameter(Mandatory=$false)][bool]$useLocalk8s=$false,
[parameter(Mandatory=$false)][bool]$useMesh=$false,
[parameter(Mandatory=$false)][string][ValidateSet('Always','IfNotPresent','Never', IgnoreCase=$false)]$imagePullPolicy="Always",
[parameter(Mandatory=$false)][string][ValidateSet('prod','staging','none','custom', IgnoreCase=$false)]$sslSupport = "none",
[parameter(Mandatory=$false)][string]$tlsSecretName = "eshop-tls-custom",
[parameter(Mandatory=$false)][string]$chartsToDeploy="*",
[parameter(Mandatory=$false)][string]$ingressMeshAnnotationsFile="ingress_values_linkerd.yaml"
)
function Install-Chart {
Param([string]$chart,[string]$initialOptions, [bool]$customRegistry)
$options=$initialOptions
if ($sslEnabled) {
$options = "$options --set ingress.tls[0].secretName=$tlsSecretName --set ingress.tls[0].hosts={$dns}"
if ($sslSupport -ne "custom") {
$options = "$options --set inf.tls.issuer=$sslIssuer"
}
}
if ($customRegistry) {
$options = "$options --set inf.registry.server=$registry --set inf.registry.login=$dockerUser --set inf.registry.pwd=$dockerPassword --set inf.registry.secretName=eshop-docker-scret"
}
if ($chart -ne "eshop-common" -or $customRegistry) { # eshop-common is ignored when no secret must be deployed
$command = "install $options --name=$appName-$chart $chart"
Write-Host "Helm Command: helm $command" -ForegroundColor Gray
Invoke-Expression 'cmd /c "helm $command"'
}
}
$dns = $externalDns
$sslEnabled=$false
$sslIssuer=""
if ($sslSupport -eq "staging") {
$sslEnabled=$true
$tlsSecretName="eshop-letsencrypt-staging"
$sslIssuer="letsencrypt-staging"
}
elseif ($sslSupport -eq "prod") {
$sslEnabled=$true
$tlsSecretName="eshop-letsencrypt-prod"
$sslIssuer="letsencrypt-prod"
}
elseif ($sslSupport -eq "custom") {
$sslEnabled=$true
}
$ingressValuesFile="ingress_values.yaml"
@ -45,6 +83,15 @@ if ($externalDns -eq "aks") {
# Initialization & check commands
if ([string]::IsNullOrEmpty($dns)) {
Write-Host "No DNS specified. Ingress resources will be bound to public ip" -ForegroundColor Yellow
if ($sslEnabled) {
Write-Host "Can't bound SSL to public IP. DNS is mandatory when using TLS" -ForegroundColor Red
exit 1
}
}
if ($useLocalk8s -and $sslEnabled) {
Write-Host "SSL can'be enabled on local K8s." -ForegroundColor Red
exit 1
}
if ($clean) {
@ -83,21 +130,15 @@ if ($deployCharts) {
foreach ($chart in $charts) {
if ($chartsToDeploy -eq "*" -or $chartsToDeploy.Contains($chart)) {
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 --values $ingressMeshAnnotationsFile --set app.name=$appName --set inf.k8s.dns=$dns --set "ingress.hosts={$dns}" --set image.tag=$imageTag --set image.pullPolicy=$imagePullPolicy --set inf.mesh.enabled=$useMesh --set inf.k8s.local=$useLocalk8s --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 --values $ingressMeshAnnotationsFile --set app.name=$appName --set inf.k8s.dns=$dns --set "ingress.hosts={$dns}" --set image.tag=$imageTag --set image.pullPolicy=$imagePullPolicy --set inf.mesh.enabled=$useMesh --set inf.k8s.local=$useLocalk8s --name="$appName-$chart" $chart
}
}
Install-Chart $chart "-f app.yaml --values inf.yaml -f $ingressValuesFile -f $ingressMeshAnnotationsFile --set app.name=$appName --set inf.k8s.dns=$dns --set ingress.hosts={$dns} --set image.tag=$imageTag --set image.pullPolicy=$imagePullPolicy --set inf.tls.enabled=$sslEnabled --set inf.mesh.enabled=$useMesh --set inf.k8s.local=$useLocalk8s" $useCustomRegistry
}
}
foreach ($chart in $gateways) {
if ($chartsToDeploy -eq "*" -or $chartsToDeploy.Contains($chart)) {
Write-Host "Installing Api Gateway Chart: $chart" -ForegroundColor Green
helm install --values app.yaml --values inf.yaml --values $ingressValuesFile --values $ingressMeshAnnotationsFile --set app.name=$appName --set inf.k8s.dns=$dns --set "ingress.hosts={$dns}" --set image.pullPolicy=$imagePullPolicy --set inf.mesh.enabled=$useMesh --name="$appName-$chart" $chart
Install-Chart $chart "-f app.yaml -f inf.yaml -f $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set image.pullPolicy=$imagePullPolicy --set inf.mesh.enabled=$useMesh --set ingress.hosts={$dns} --set inf.tls.enabled=$sslEnabled" $false
}
}
}


+ 6
- 1
deploy/k8s/helm/identity-api/templates/ingress.yaml View File

@ -14,6 +14,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -24,7 +27,9 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}


+ 4
- 1
deploy/k8s/helm/inf.yaml View File

@ -3,7 +3,10 @@
inf:
mesh:
enabled: true
enabled: false # True to enable Linkerd (set by deploy-all.ps1)
tls:
enabled: false # True to enable TLS (set by deploy-all.ps1)
issuer: "" # cert-manager issuer to use for retrieving certs (set by deploy-all.ps1)
sql: # inf.sql defines the sql server databases & logins
# host: my-sql-server # Uncomment to specify a custom sql-server to be used. By default "sql-data-<appname>" will be used
common:


+ 0
- 325
deploy/k8s/helm/istio/doc.md View File

@ -1,325 +0,0 @@
# Using Helm Charts to deploy eShopOnContainers to AKS with ISTIO
It is possible to deploy eShopOnContainers on a AKS using [Helm](https://helm.sh/) instead of custom scripts (that will be deprecated soon).
## Create Kubernetes cluster in AKS
You can create the AKS cluster by using two ways:
- A. Use Azure CLI: Follow a procedure suing [Azure CLI like here](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough), but make sure you **enable RBAC** with `--enable-rbac` in `az aks create` command.
- B. Use Azure's portal
The following steps are using the Azure portal to create the AKS cluster:
- Start the process by providing the general data, like in the following screenshot:
![image](https://user-images.githubusercontent.com/1712635/45787360-c59ecd80-bc29-11e8-9565-c989ad6ad57b.png)
- Then, very important, in the next step, enable RBAC:
![image](https://user-images.githubusercontent.com/1712635/45780917-8bc2cc80-bc13-11e8-87ac-2942b3c7496d.png)
You can use **basic network** settings since for a test you don't need integration into any existing VNET.
![image](https://user-images.githubusercontent.com/1712635/45780991-b745b700-bc13-11e8-926b-afac57229d0a.png)
- You can also enable monitoring:
![image](https://user-images.githubusercontent.com/1712635/45781148-1277a980-bc14-11e8-8614-f7a239731bec.png)
- Finally, create the cluster. It'll take a few minutes for it to be ready.
### Configure RBAC security for K8s dashboard service-account
In order NOT to get errors in the Kubernetes dashboard, you'll need to set the following service-account steps.
Here you can see the errors you might see:
![image](https://user-images.githubusercontent.com/1712635/45784384-5622e100-bc1d-11e8-8d33-e22fd955150a.png)
Now, just run the Azure CLI command to browse the Kubernetes Dashboard:
`az aks browse --resource-group pro-eshop-aks-helm-linux-resgrp --name pro-eshop-aks-helm-linux`
![image](https://user-images.githubusercontent.com/1712635/45786406-2d9ee500-bc25-11e8-83e9-bdfc302e80f1.png)
## Additional pre-requisites
In addition to having an AKS cluster created in Azure and having kubectl and Azure CLI installed in your local machine and configured to use your Azure subscription, you also need the following pre-requisites:
### Install Helm
You need to have helm installed on your machine, and Tiller must be installed on the AKS. Follow these instructions on how to ['Install applications with Helm in Azure Kubernetes Service (AKS)'](https://docs.microsoft.com/en-us/azure/aks/kubernetes-helm) to setup Helm and Tiller for AKS.
**Note**: If your ASK cluster is not RBAC-enabled (default option in portal) you may receive following error when running a helm command:
```
Error: Get http://localhost:8080/api/v1/namespaces/kube-system/configmaps?labelSelector=OWNER%!D(MISSING)TILLER: dial tcp [::1]:8080: connect: connection refused
```
If so, type:
```
kubectl --namespace=kube-system edit deployment/tiller-deploy
```
Your default text editor will popup with the YAML definition of the tiller deploy. Search for:
```
automountServiceAccountToken: false
```
And change it to:
```
automountServiceAccountToken: true
```
Save the file and close the editor. This should reapply the deployment in the cluster. Now Helm commands should work.
## Install eShopOnContainers with Istio using Helm
All steps need to be performed on `/k8s/helm` folder. The easiest way is to use the `deploy-all-istio.ps1` script from a Powershell window:
```
.\deploy-all-istio.ps1 -dnsname eshoptestistio -externalDns aks -aksName eshoptest -aksRg eshoptest -imageTag dev
```
This will install all the [eShopOnContainers public images](https://hub.docker.com/u/eshop/) with tag `dev` on the AKS named `eshoptest` in the resource group `eshoptest` and with the dns url: http://**eshoptestistio**.westus.cloudapp.azure.com/ . By default all infrastructure (sql, mongo, rabbit and redis) is installed also in the cluster.
Once the script is run, you should see following output when using `kubectl get deployment`:
```
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
eshop-apigwmm 1 1 1 1 4d
eshop-apigwms 1 1 1 1 4d
eshop-apigwwm 1 1 1 1 4d
eshop-apigwws 1 1 1 1 4d
eshop-basket-api 1 1 1 1 4d
eshop-basket-data 1 1 1 1 4d
eshop-catalog-api 1 1 1 1 4d
eshop-identity-api 1 1 1 1 4d
eshop-keystore-data 1 1 1 1 4d
eshop-locations-api 1 1 1 1 4d
eshop-marketing-api 1 1 1 1 4d
eshop-mobileshoppingagg 1 1 1 1 4d
eshop-nosql-data 1 1 1 1 4d
eshop-ordering-api 1 1 1 1 4d
eshop-ordering-backgroundtasks 1 1 1 1 4d
eshop-ordering-signalrhub 1 1 1 1 4d
eshop-payment-api 1 1 1 1 4d
eshop-rabbitmq 1 1 1 1 4d
eshop-sql-data 1 1 1 1 4d
eshop-webmvc 1 1 1 1 4d
eshop-webshoppingagg 1 1 1 1 4d
eshop-webspa 1 1 1 1 4d
eshop-webstatus 1 1 1 1 4d
```
Every public service is exposed through the istio ingress gateway.
Yo can see the ingress gateway public ip doing `kubectl get services -n istio-system`
```
grafana ClusterIP 10.0.204.87 <none> 3000/TCP 1h
istio-citadel ClusterIP 10.0.23.86 <none> 8060/TCP,9093/TCP 1h
istio-egressgateway ClusterIP 10.0.136.169 <none> 80/TCP,443/TCP 1h
istio-galley ClusterIP 10.0.113.51 <none> 443/TCP,9093/TCP 1h
istio-ingressgateway LoadBalancer 10.0.76.80 40.118.189.161 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:31276/TCP,8060:30519/TCP,853:31698/TCP,15030:31453/TCP,15031:32362/TCP 1h
istio-pilot ClusterIP 10.0.164.253 <none> 15010/TCP,15011/TCP,8080/TCP,9093/TCP 1h
istio-policy ClusterIP 10.0.170.49 <none> 9091/TCP,15004/TCP,9093/TCP 1h
istio-sidecar-injector ClusterIP 10.0.251.12 <none> 443/TCP 1h
istio-telemetry ClusterIP 10.0.195.112 <none> 9091/TCP,15004/TCP,9093/TCP,42422/TCP 1h
jaeger-agent ClusterIP None <none> 5775/UDP,6831/UDP,6832/UDP 1h
jaeger-collector ClusterIP 10.0.123.98 <none> 14267/TCP,14268/TCP 1h
jaeger-query ClusterIP 10.0.244.146 <none> 16686/TCP 1h
kiali ClusterIP 10.0.182.12 <none> 20001/TCP 1h
prometheus ClusterIP 10.0.136.223 <none> 9090/TCP 1h
tracing ClusterIP 10.0.57.236 <none> 80/TCP 1h
zipkin ClusterIP 10.0.30.57 <none> 9411/TCP 1h
```
You can view the MVC client at http://[dns]/
## Customizing the deployment
### Using your own images
To use your own images instead of the public ones, you have to pass following additional parameters to the `deploy-all-istio.ps1` script:
* `registry`: Login server for the Docker registry
* `dockerUser`: User login for the Docker registry
* `dockerPassword`: User password for the Docker registry
This will deploy a secret on the cluster to connect to the specified server, and all image names deployed will be prepended with `registry/` value.
### Not deploying infrastructure containers
If you want to use external resources, use `-deployInfrastructure $false` to not deploy infrastructure containers. However **you still have to manually update the scripts to provide your own configuration** (see next section).
### Providing your own configuration
The file `inf.yaml` contains the description of the infrastructure used. File is docummented so take a look on it to understand all of its entries. If using external resources you need to edit this file according to your needs. You'll need to edit:
* `inf.sql.host` with the host name of the SQL Server
* `inf.sql.common` entries to provide your SQL user, password. `Pid` is not used when using external resources (it is used to set specific product id for the SQL Server container).
* `inf.sql.catalog`, `inf.sql.ordering`, `inf.sql.identity`: To provide the database names for catalog, ordering and identity services
* `mongo.host`: With the host name of the Mongo DB
* `mongo.locations`, `mongo.marketing` with the database names for locations and marketing services
* `redis.basket.constr` with the connection string to Redis for Basket Service. Note that `redis.basket.svc` is not used when using external services
* `redis.keystore.constr` with the connection string to Redis for Keystore Service. Note that `redis.keystore.svc` is not used when using external services
* `eventbus.constr` with the connection string to Azure Service Bus and `eventbus.useAzure` to `true` to use Azure service bus. Note that `eventbus.svc` is not used when using external services
### Using Azure storage for Catalog Photos
Using Azure storage for catalog (and marketing) photos is not directly supported, but you can accomplish it by editing the file `k8s/helm/catalog-api/templates/configmap.yaml`. Search for lines:
```
catalog__PicBaseUrl: http://{{ $webshoppingapigw }}/c/api/v1/catalog/items/[0]/pic/
```
And replace it for:
```
catalog__PicBaseUrl: http://<url-of-the-storage>/
```
In the same way, to use Azure storage for the marketing service, have to edit the file `k8s/helm/marketing-api/templates/configmap.yaml` and replacing the line:
```
marketing__PicBaseUrl: http://{{ $webshoppingapigw }}/c/api/v1/catalog/items/[0]/pic/
```
by:
```
marketing__PicBaseUrl: http://<url-of-the-storage>/
```
# Using Helm Charts to deploy eShopOnContainers to a local Kubernetes in Windows with 'Docker for Windows'
## Additional pre-requisites
In addition to having Docker for Windows/Mac with Kubernetes enabled and having kubectl ayou also need the following pre-requisites:
### Install Helm
You need to have helm installed on your machine, and Tiller must be installed on the local Docker Kubernetes cluster. Once you have [Helm downloaded](https://helm.sh/) and installed on your machine you must:
1. Create the tiller service account, by running `kubectl apply -f helm-rbac.yaml` from `/k8s` folder
2. Install tiller and configure it to use the tiller service account by typing `helm init --service-account tiller`
## Install eShopOnContainers with Istio using Helm
All steps need to be performed on `/k8s/helm` folder. The easiest way is to use the `deploy-all-istio.ps1` script from a Powershell window:
```
.\deploy-all-istio.ps1 -imageTag dev -useLocalk8s $true
```
The parameter `useLocalk8s` to $true, forces the script to use `localhost` as the DNS for all Helm charts.
This will install all the [eShopOnContainers public images](https://hub.docker.com/u/eshop/) with tag `dev` on the Docker local Kubernetes cluster. By default all infrastructure (sql, mongo, rabbit and redis) is installed also in the cluster.
Once the script is run, you should see following output when using `kubectl get deployment`:
```
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
eshop-apigwmm 1 1 1 1 2h
eshop-apigwms 1 1 1 1 2h
eshop-apigwwm 1 1 1 1 2h
eshop-apigwws 1 1 1 1 2h
eshop-basket-api 1 1 1 1 2h
eshop-basket-data 1 1 1 1 2h
eshop-catalog-api 1 1 1 1 2h
eshop-identity-api 1 1 1 1 2h
eshop-keystore-data 1 1 1 1 2h
eshop-locations-api 1 1 1 1 2h
eshop-marketing-api 1 1 1 1 2h
eshop-mobileshoppingagg 1 1 1 1 2h
eshop-nosql-data 1 1 1 1 2h
eshop-ordering-api 1 1 1 1 2h
eshop-ordering-backgroundtasks 1 1 1 1 2h
eshop-ordering-signalrhub 1 1 1 1 2h
eshop-payment-api 1 1 1 1 2h
eshop-rabbitmq 1 1 1 1 2h
eshop-sql-data 1 1 1 1 2h
eshop-webmvc 1 1 1 1 2h
eshop-webshoppingagg 1 1 1 1 2h
eshop-webspa 1 1 1 1 2h
eshop-webstatus 1 1 1 1 2h
```
Note that istio ingress gateway is bound to DNS localhost and the host is also "localhost". So, you can access the webspa by typing `http://localhost` and the MVC by typing `http://localhost/`
As this is the Docker local K8s cluster, you can see also the containers running on your machine. If you type `docker ps` you'll see all them:
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fec1e3499416 a3f21ec4bd11 "/entrypoint.sh /ngi…" 9 minutes ago Up 9 minutes k8s_nginx-ingress-controller_nginx-ingress-controller-f88c75bc6-5xs2n_ingress-nginx_f1cc7094-e68f-11e8-b4b6-00155d016146_0
76485867f032 eshop/payment.api "dotnet Payment.API.…" 2 hours ago Up 2 hours k8s_payment-api_eshop-payment-api-75d5f9bdf6-6zx2v_default_4a3cdab4-e67f-11e8-b4b6-00155d016146_1
c2c4640ed610 eshop/marketing.api "dotnet Marketing.AP…" 2 hours ago Up 2 hours k8s_marketing-api_eshop-marketing-api-6b8c5989fd-jpxqv_default_45780626-e67f-11e8-b4b6-00155d016146_1
85301d538574 eshop/ordering.signalrhub "dotnet Ordering.Sig…" 2 hours ago Up 2 hours k8s_ordering-signalrhub_eshop-ordering-signalrhub-58cf5ff6-cnlm8_default_4932c344-e67f-11e8-b4b6-00155d016146_1
7a408a98000e eshop/ordering.backgroundtasks "dotnet Ordering.Bac…" 2 hours ago Up 2 hours k8s_ordering-backgroundtasks_eshop-ordering-backgroundtasks-cc8f6d4d8-ztfk7_default_47f9cf10-e67f-11e8-b4b6-00155d016146_1
12c64b3a13e0 eshop/basket.api "dotnet Basket.API.d…" 2 hours ago Up 2 hours k8s_basket-api_eshop-basket-api-658546684d-6hlvd_default_4262d022-e67f-11e8-b4b6-00155d016146_1
133fccfeeff3 eshop/webstatus "dotnet WebStatus.dll" 2 hours ago Up 2 hours k8s_webstatus_eshop-webstatus-7f46479dc4-bqnq7_default_4dc13eb2-e67f-11e8-b4b6-00155d016146_0
00c6e4c52135 eshop/webspa "dotnet WebSPA.dll" 2 hours ago Up 2 hours k8s_webspa_eshop-webspa-64cb8df9cb-dcbwg_default_4cd47376-e67f-11e8-b4b6-00155d016146_0
d4507f1f6b1a eshop/webshoppingagg "dotnet Web.Shopping…" 2 hours ago Up 2 hours k8s_webshoppingagg_eshop-webshoppingagg-cc94fc86-sxd2v_default_4be6cdb9-e67f-11e8-b4b6-00155d016146_0
9178e26703da eshop/webmvc "dotnet WebMVC.dll" 2 hours ago Up 2 hours k8s_webmvc_eshop-webmvc-985779684-4br5z_default_4addd4d6-e67f-11e8-b4b6-00155d016146_0
1088c281c710 eshop/ordering.api "dotnet Ordering.API…" 2 hours ago Up 2 hours k8s_ordering-api_eshop-ordering-api-fb8c548cb-k68x9_default_4740958a-e67f-11e8-b4b6-00155d016146_0
12424156d5c9 eshop/mobileshoppingagg "dotnet Mobile.Shopp…" 2 hours ago Up 2 hours k8s_mobileshoppingagg_eshop-mobileshoppingagg-b54645d7b-rlrgh_default_46c00017-e67f-11e8-b4b6-00155d016146_0
65463ffd437d eshop/locations.api "dotnet Locations.AP…" 2 hours ago Up 2 hours k8s_locations-api_eshop-locations-api-577fc94696-dfhq8_default_44929c4b-e67f-11e8-b4b6-00155d016146_0
5b3431873763 eshop/identity.api "dotnet Identity.API…" 2 hours ago Up 2 hours k8s_identity-api_eshop-identity-api-85d9b79f4-s5ks7_default_43d6eb7c-e67f-11e8-b4b6-00155d016146_0
7c8e77252459 eshop/catalog.api "dotnet Catalog.API.…" 2 hours ago Up 2 hours k8s_catalog-api_eshop-catalog-api-59fd444fb-ztvhz_default_4356705a-e67f-11e8-b4b6-00155d016146_0
94d95d0d3653 eshop/ocelotapigw "dotnet OcelotApiGw.…" 2 hours ago Up 2 hours k8s_apigwws_eshop-apigwws-65474b979d-n99jw_default_41395473-e67f-11e8-b4b6-00155d016146_0
bc4bbce71d5f eshop/ocelotapigw "dotnet OcelotApiGw.…" 2 hours ago Up 2 hours k8s_apigwwm_eshop-apigwwm-857c549dd8-8w5gv_default_4098d770-e67f-11e8-b4b6-00155d016146_0
840aabcceaa9 eshop/ocelotapigw "dotnet OcelotApiGw.…" 2 hours ago Up 2 hours k8s_apigwms_eshop-apigwms-5b94dfb54b-dnmr9_default_401fc611-e67f-11e8-b4b6-00155d016146_0
aabed7646f5b eshop/ocelotapigw "dotnet OcelotApiGw.…" 2 hours ago Up 2 hours k8s_apigwmm_eshop-apigwmm-85f96cbdb4-dhfwr_default_3ed7967a-e67f-11e8-b4b6-00155d016146_0
49c5700def5a f06a5773f01e "docker-entrypoint.s…" 2 hours ago Up 2 hours k8s_basket-data_eshop-basket-data-66fbc788cc-csnlw_default_3e0c45fe-e67f-11e8-b4b6-00155d016146_0
a5db4c521807 f06a5773f01e "docker-entrypoint.s…" 2 hours ago Up 2 hours k8s_keystore-data_eshop-keystore-data-5c9c85cb99-8k56s_default_3ce1a273-e67f-11e8-b4b6-00155d016146_0
aae88fd2d810 d69a5113ceae "docker-entrypoint.s…" 2 hours ago Up 2 hours k8s_rabbitmq_eshop-rabbitmq-6b68647bc4-gr565_default_3c37ee6a-e67f-11e8-b4b6-00155d016146_0
65d49ca9589d bbed8d0e01c1 "docker-entrypoint.s…" 2 hours ago Up 2 hours k8s_nosql-data_eshop-nosql-data-579c9d89f8-mtt95_default_3b9c1f89-e67f-11e8-b4b6-00155d016146_0
090e0dde2ec4 bbe2822dfe38 "/opt/mssql/bin/sqls…" 2 hours ago Up 2 hours k8s_sql-data_eshop-sql-data-5c4fdcccf4-bscdb_default_3afd29b8-e67f-11e8-b4b6-00155d016146_0
```
## Known issues
Login from the webmvc results in following error: HttpRequestException: Response status code does not indicate success: 404 (Not Found).
The reason is because MVC needs to access the Identity Server from both outside the container (browser) and inside the container (C# code). Thus, the configuration uses always the *external url* of the Identity Server, which in this case is just `http://localhost/identity-api`. But this external url is incorrect when used from C# code, and the web mvc can't access the identity api. This is the only case when this issue happens (and is the reason why we use 10.0.75.1 for local address in web mvc in local development mode)
Solving this requires some manual steps:
Update the configmap of Web MVC by typing (**line breaks are mandatory**) and your cluster dns name has to be the same of your environment:
```
kubectl patch cm cfg-eshop-webmvc --type strategic --patch @'
data:
urls__IdentityUrl: http://**eshoptest**.westus.cloudapp.azure.com/identity
urls__mvc: http://**eshoptest**.westus.cloudapp.azure.com/webmvc
'@
```
Update the configmap of Identity API by typing (**line breaks are mandatory**):
```
kubectl patch cm cfg-eshop-identity-api --type strategic --patch @'
data:
mvc_e: http://**eshoptest**.westus.cloudapp.azure.com/webmvc
'@
```
Restart the SQL Server pod to ensure the database is recreated again:
```
kubectl delete pod --selector app=sql-data
```
Wait until SQL Server pod is ready to accept connections and then restart all other pods:
```
kubectl delete pod --selector="app!=sql-data"
```
**Note:** Pods are deleted to ensure the databases are recreated again, as identity api stores its client names and urls in the database.
Now, you can access the MVC app using: `http://**eshoptest**.westus.cloudapp.azure.com/`.

+ 0
- 15
deploy/k8s/helm/istio/gateway.yml View File

@ -1,15 +0,0 @@
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-ingressgateway
#namespace: istio-system
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"

+ 0
- 59
deploy/k8s/helm/istio/virtualservices.yml View File

@ -1,59 +0,0 @@
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: webmvcvs
namespace: default
spec:
hosts:
- "*"
gateways:
- istio-ingressgateway
http:
- match:
- uri:
prefix: /
route:
- destination:
port:
number: 80
host: webmvc
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: webshoppingapigwvs
namespace: default
spec:
hosts:
- "*"
gateways:
- istio-ingressgateway
http:
- match:
- uri:
prefix: /webshoppingapigw
route:
- destination:
port:
number: 80
host: webshoppingapigw
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: identityvs
namespace: default
spec:
hosts:
- "*"
gateways:
- istio-ingressgateway
http:
- match:
- uri:
prefix: /identity
route:
- destination:
port:
number: 80
host: identity

+ 0
- 41
deploy/k8s/helm/locations-api/templates/ingress.yaml View File

@ -1,41 +0,0 @@
{{- 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 }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- 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 }}

+ 8
- 0
deploy/k8s/helm/marketing-api/templates/_names.tpl View File

@ -49,4 +49,12 @@
{{- else -}}
{{- .Values.image.repository -}}
{{- end -}}
{{- end -}}
{{- define "protocol" -}}
{{- if .Values.inf.tls.enabled -}}
{{- printf "%s" "https" -}}
{{- else -}}
{{- printf "%s" "http" -}}
{{- end -}}
{{- end -}}

+ 3
- 2
deploy/k8s/helm/marketing-api/templates/configmap.yaml View File

@ -3,6 +3,7 @@
{{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}}
{{- $mongo := include "mongo-name" . -}}
{{- $sqlsrv := include "sql-name" . -}}
{{- $protocol := include "protocol" . -}}
apiVersion: v1
kind: ConfigMap
@ -19,8 +20,8 @@ data:
all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}"
all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}"
internalurls__IdentityUrl: http://{{ .Values.app.svc.identity }}
urls__IdentityUrl: {{ $identity }}
urls__IdentityUrl: {{ $protocol }}://{{ $identity }}
marketing__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.marketing.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }};
marketing__MongoConnectionString: mongodb://{{ $mongo }}
marketing__MongoDatabase: {{ .Values.inf.mongo.marketing.database }}
marketing__PicBaseUrl: http://{{ $webshoppingapigw }}/c/api/v1/catalog/items/[0]/pic/
marketing__PicBaseUrl: {{ $protocol }}://{{ $webshoppingapigw }}/c/api/v1/catalog/items/[0]/pic/

+ 0
- 41
deploy/k8s/helm/marketing-api/templates/ingress.yaml View File

@ -1,41 +0,0 @@
{{- 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 }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- 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 }}

+ 0
- 41
deploy/k8s/helm/mobileshoppingagg/templates/ingress.yaml View File

@ -1,41 +0,0 @@
{{- 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 }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- 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 }}

+ 21
- 0
deploy/k8s/helm/tls-support/.helmignore View File

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

+ 5
- 0
deploy/k8s/helm/tls-support/Chart.yaml View File

@ -0,0 +1,5 @@
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: tt-ssl
version: 0.1.0

+ 32
- 0
deploy/k8s/helm/tls-support/templates/_helpers.tpl View File

@ -0,0 +1,32 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "tt-tls.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "tt-tls.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "tt-tls.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

+ 17
- 0
deploy/k8s/helm/tls-support/templates/issuer.yaml View File

@ -0,0 +1,17 @@
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: {{ .Values.issuerName }}
namespace: default
environment: {{ .Values.environment }}
app: {{ .Values.applicationName }}
spec:
acme:
server: {{ .Values.server }}
email: not@used.com
privateKeySecretRef:
name: {{ .Values.issuerSecretName }}
solvers:
- http01:
ingress:
class: {{ .Values.ingressClass }}

+ 8
- 0
deploy/k8s/helm/tls-support/values-prod.yaml View File

@ -0,0 +1,8 @@
applicationName: eshop
issuerName: letsencrypt-prod
certName: eshop-cert-prod
environment: prod
server: https://acme-v02.api.letsencrypt.org/directory
certSecretName: eshop-letsencrypt-prod
issuerSecretName: letsencrypt-prod
ingressClass: addon-http-application-routing

+ 8
- 0
deploy/k8s/helm/tls-support/values-staging.yaml View File

@ -0,0 +1,8 @@
applicationName: eshop
issuerName: letsencrypt-staging
certName: eshop-cert-staging
environment: staging
server: https://acme-staging-v02.api.letsencrypt.org/directory
certSecretName: eshop-letsencrypt-staging
issuerSecretName: letsencrypt-staging
ingressClass: addon-http-application-routing

+ 9
- 0
deploy/k8s/helm/webhooks-api/templates/_names.tpl View File

@ -48,4 +48,13 @@
{{- else -}}
{{- .Values.image.repository -}}
{{- end -}}
{{- end -}}
{{- define "protocol" -}}
{{- if .Values.inf.tls.enabled -}}
{{- printf "%s" "https" -}}
{{- else -}}
{{- printf "%s" "http" -}}
{{- end -}}
{{- end -}}

+ 2
- 1
deploy/k8s/helm/webhooks-api/templates/configmap.yaml View File

@ -1,6 +1,7 @@
{{- $name := include "webhooks-api.fullname" . -}}
{{- $sqlsrv := include "sql-name" . -}}
{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}}
{{- $protocol := include "protocol" . -}}
apiVersion: v1
kind: ConfigMap
@ -14,7 +15,7 @@ metadata:
data:
webhooks__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.webhooks.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }};
urls__IdentityUrl: http://{{ $identity }}
urls__IdentityUrlExternal: http://{{ $identity }}
urls__IdentityUrlExternal: {{ $protocol }}://{{ $identity }}
all__EventBusConnection: {{ .Values.inf.eventbus.constr }}
all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}"
all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}"

+ 7
- 2
deploy/k8s/helm/webhooks-api/templates/ingress.yaml View File

@ -14,6 +14,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -24,12 +27,14 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:


+ 9
- 0
deploy/k8s/helm/webhooks-web/templates/_names.tpl View File

@ -48,4 +48,13 @@
{{- else -}}
{{- .Values.image.repository -}}
{{- end -}}
{{- end -}}
{{- define "protocol" -}}
{{- if .Values.inf.tls.enabled -}}
{{- printf "%s" "https" -}}
{{- else -}}
{{- printf "%s" "http" -}}
{{- end -}}
{{- end -}}

+ 4
- 3
deploy/k8s/helm/webhooks-web/templates/configmap.yaml View File

@ -2,6 +2,7 @@
{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}}
{{- $webhooksweb := include "url-of" (list .Values.app.ingress.entries.webhooksweb .) -}}
{{- $webhooks := include "url-of" (list .Values.app.ingress.entries.webhooks .) -}}
{{- $protocol := include "protocol" . -}}
apiVersion: v1
kind: ConfigMap
@ -13,7 +14,7 @@ metadata:
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
data:
urls__webhooks: http://{{ $webhooks }}
identity_e: http://{{ $identity }}
webhooksweb_e: http://{{ $webhooksweb }}
urls__webhooks: {{ $protocol }}://{{ $webhooks }}
identity_e: {{ $protocol }}://{{ $identity }}
webhooksweb_e: {{ $protocol }}://{{ $webhooksweb }}
urls_webhooksweb: http://{{ .Values.app.svc.webhooksweb }}

+ 15
- 3
deploy/k8s/helm/webhooks-web/templates/ingress.yaml View File

@ -13,21 +13,33 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
- host: {{ .Values.inf.k8s.dns }}
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
backend:
serviceName: {{ .Values.app.svc.webhooksweb }}
serviceName: {{ $.Values.app.svc.webhooksweb }}
servicePort: http
{{- end }}
{{- end }}

+ 8
- 0
deploy/k8s/helm/webmvc/templates/_names.tpl View File

@ -49,4 +49,12 @@
{{- else -}}
{{- .Values.image.repository -}}
{{- end -}}
{{- end -}}
{{- define "protocol" -}}
{{- if .Values.inf.tls.enabled -}}
{{- printf "%s" "https" -}}
{{- else -}}
{{- printf "%s" "http" -}}
{{- end -}}
{{- end -}}

+ 4
- 3
deploy/k8s/helm/webmvc/templates/configmap.yaml View File

@ -2,6 +2,7 @@
{{- $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 .) -}}
{{- $protocol := include "protocol" . -}}
apiVersion: v1
kind: ConfigMap
@ -20,6 +21,6 @@ data:
internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }}
internalurls__apigwwm: http://{{ .Values.app.svc.webmarketingapigw }}
internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc
urls__apigwws: http://{{ $webshoppingapigw }}
urls__mvc: http://{{ $mvc }}
urls__IdentityUrl: http://{{ $identity }}
urls__apigwws: {{ $protocol }}://{{ $webshoppingapigw }}
urls__mvc: {{ $protocol }}://{{ $mvc }}
urls__IdentityUrl: {{ $protocol }}://{{ $identity }}

+ 6
- 1
deploy/k8s/helm/webmvc/templates/ingress.yaml View File

@ -14,6 +14,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -24,7 +27,9 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}


+ 0
- 41
deploy/k8s/helm/webshoppingagg/templates/ingress.yaml View File

@ -1,41 +0,0 @@
{{- 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 }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- 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 }}

+ 8
- 0
deploy/k8s/helm/webspa/templates/_names.tpl View File

@ -49,4 +49,12 @@
{{- else -}}
{{- .Values.image.repository -}}
{{- end -}}
{{- end -}}
{{- define "protocol" -}}
{{- if .Values.inf.tls.enabled -}}
{{- printf "%s" "https" -}}
{{- else -}}
{{- printf "%s" "http" -}}
{{- end -}}
{{- end -}}

+ 5
- 5
deploy/k8s/helm/webspa/templates/configmap.yaml View File

@ -4,7 +4,7 @@
{{- $webmarketingapigw := include "url-of" (list .Values.app.ingress.entries.webmarketingapigw .) -}}
{{- $spa := include "url-of" (list .Values.app.ingress.entries.spa .) -}}
{{- $mongo := include "mongo-name" . -}}
{{- $protocol := include "protocol" . -}}
apiVersion: v1
kind: ConfigMap
@ -21,7 +21,7 @@ data:
webspa__keystore: {{ .Values.inf.redis.keystore.constr }}
internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }}
internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc
urls__apigwws: http://{{ $webshoppingapigw }}
urls__spa: http://{{ $spa }}
urls__IdentityUrl: http://{{ $identity }}
urls__apigwwm: http://{{ $webmarketingapigw }}
urls__apigwws: {{ $protocol }}://{{ $webshoppingapigw }}
urls__spa: {{ $protocol }}://{{ $spa }}
urls__IdentityUrl: {{ $protocol }}://{{ $identity }}
urls__apigwwm: {{ $protocol }}://{{ $webmarketingapigw }}

+ 10
- 3
deploy/k8s/helm/webspa/templates/ingress.yaml View File

@ -13,6 +13,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -23,16 +26,20 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
- host: {{ .Values.inf.k8s.dns }}
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
backend:
serviceName: {{ .Values.app.svc.spa }}
serviceName: {{ $.Values.app.svc.spa }}
servicePort: http
{{- end }}
{{- end }}

+ 0
- 2
deploy/k8s/helm/webstatus/templates/_names.tpl View File

@ -32,8 +32,6 @@
{{- end -}}
{{- end -}}
{{- define "pathBase" -}}
{{- if .Values.inf.k8s.suffix -}}
{{- $suffix := include "suffix-name" . -}}


+ 0
- 1
deploy/k8s/helm/webstatus/templates/configmap.yaml View File

@ -4,7 +4,6 @@
{{- $mvc := include "url-of" (list .Values.app.ingress.entries.mvc .) -}}
{{- $mongo := include "mongo-name" . -}}
apiVersion: v1
kind: ConfigMap
metadata:


+ 10
- 3
deploy/k8s/helm/webstatus/templates/ingress.yaml View File

@ -14,6 +14,9 @@ metadata:
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }}
cert-manager.io/issuer: {{ .Values.inf.tls.issuer }}
{{- end }}
{{- if .Values.inf.mesh.enabled }}
{{- with .Values.ingress.mesh.annotations }}
{{ toYaml . | indent 4 }}
@ -24,16 +27,20 @@ spec:
tls:
{{- range .Values.ingress.tls }}
- hosts:
- {{ .Values.inf.k8s.dns }}
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
- host: {{ .Values.inf.k8s.dns }}
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
backend:
serviceName: {{ .Values.app.svc.status }}
serviceName: {{ $.Values.app.svc.status }}
servicePort: http
{{- end }}
{{- end }}

+ 16
- 33
deploy/k8s/helm/webstatus/values.yaml View File

@ -55,54 +55,37 @@ env:
- name: HealthChecks-UI__HealthChecks__4__Uri
key: internalurls__ordering__hc
- name: HealthChecks-UI__HealthChecks__5__Name
key: name__orderingbackground__hc
key: name__basket__hc
- name: HealthChecks-UI__HealthChecks__5__Uri
key: internalurls__orderingbackground__hc
key: internalurls__basket__hc
- name: HealthChecks-UI__HealthChecks__6__Name
key: name__signalrhub__hc
key: name__catalog__hc
- name: HealthChecks-UI__HealthChecks__6__Uri
key: internalurls__signalrhub__hc
key: internalurls__catalog__hc
- name: HealthChecks-UI__HealthChecks__7__Name
key: name__basket__hc
key: name__identity__hc
- name: HealthChecks-UI__HealthChecks__7__Uri
key: internalurls__basket__hc
key: internalurls__identity__hc
- name: HealthChecks-UI__HealthChecks__8__Name
key: name__catalog__hc
key: name__marketing__hc
- name: HealthChecks-UI__HealthChecks__8__Uri
key: internalurls__catalog__hc
key: internalurls__marketing__hc
- name: HealthChecks-UI__HealthChecks__9__Name
key: name__identity__hc
key: name__locations__hc
- name: HealthChecks-UI__HealthChecks__9__Uri
key: internalurls__identity__hc
key: internalurls__locations__hc
- name: HealthChecks-UI__HealthChecks__10__Name
key: name__marketing__hc
key: name__payment__hc
- name: HealthChecks-UI__HealthChecks__10__Uri
key: internalurls__marketing__hc
key: internalurls__payment__hc
- name: HealthChecks-UI__HealthChecks__11__Name
key: name__locations__hc
key: name__signalrhub__hc
- name: HealthChecks-UI__HealthChecks__11__Uri
key: internalurls__locations__hc
key: internalurls__signalrhub__hc
- name: HealthChecks-UI__HealthChecks__12__Name
key: name__payment__hc
key: name__orderingbackground__hc
- name: HealthChecks-UI__HealthChecks__12__Uri
key: internalurls__payment__hc
- name: HealthChecks-UI__HealthChecks__13__Name
key: name__apigwws__hc
- name: HealthChecks-UI__HealthChecks__13__Uri
key: internalurls__apigwws__hc
- name: HealthChecks-UI__HealthChecks__14__Name
key: name__apigwwm__hc
- name: HealthChecks-UI__HealthChecks__14__Uri
key: internalurls__apigwwm__hc
- name: HealthChecks-UI__HealthChecks__15__Name
key: name__apigwms__hc
- name: HealthChecks-UI__HealthChecks__15__Uri
key: internalurls__apigwms__hc
- name: HealthChecks-UI__HealthChecks__16__Name
key: name__apigwmm__hc
- name: HealthChecks-UI__HealthChecks__16__Uri
key: internalurls__apigwmm__hc
key: internalurls__orderingbackground__hc
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
values:


BIN
deploy/k8s/nginx-ingress/cm.yaml View File


+ 11
- 0
deploy/k8s/nginx-ingress/local-cm.yaml View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
name: nginx-configuration
namespace: ingress-nginx
data:
proxy-buffer-size: "128k"
proxy-buffers: "4 256k"

deploy/k8s/nginx-ingress/cloud-generic.yaml → deploy/k8s/nginx-ingress/local-svc.yaml View File


obsolete/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 → deploy/windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 View File


obsolete/cli-windows/set-dockernat-networkategory-to-private.ps1 → deploy/windows/set-dockernat-networkategory-to-private.ps1 View File


BIN
img/eShopOnContainers-Architecture-With-Azure-API-Management.png View File

Before After
Width: 1791  |  Height: 1029  |  Size: 347 KiB

BIN
img/eShopOnContainers-architecture.png View File

Before After
Width: 1511  |  Height: 802  |  Size: 204 KiB

BIN
img/eShopOnContainers_Types_Of_Microservices.png View File

Before After
Width: 1249  |  Height: 581  |  Size: 156 KiB

BIN
img/eshop-webspa-app-screenshot.png View File

Before After
Width: 2196  |  Height: 1845  |  Size: 1.7 MiB

BIN
img/new-folder-structure.png View File

Before After
Width: 546  |  Height: 204  |  Size: 11 KiB

BIN
img/vs-solution-structure.png View File

Before After
Width: 1995  |  Height: 1081  |  Size: 383 KiB

BIN
img/xamarin-mobile-App.png View File

Before After
Width: 320  |  Height: 571  |  Size: 189 KiB

+ 27
- 12
src/ApiGateways/Envoy/config/mobileshopping/envoy.yaml View File

@ -42,13 +42,20 @@ static_resources:
route:
auto_host_rewrite: true
prefix_rewrite: "/ordering-api/"
cluster: ordering
cluster: ordering
- name: "o-long"
match:
prefix: "/ordering-api/"
route:
auto_host_rewrite: true
cluster: ordering
cluster: ordering
- name: "h-long"
match:
prefix: "/hub/notificationhub"
route:
auto_host_rewrite: true
cluster: signalr-hub
timeout: 300s
- name: "b-short"
match:
prefix: "/b/"
@ -61,7 +68,7 @@ static_resources:
prefix: "/basket-api/"
route:
auto_host_rewrite: true
cluster: basket
cluster: basket
- name: "agg"
match:
prefix: "/"
@ -70,25 +77,25 @@ static_resources:
prefix_rewrite: "/"
cluster: shoppingagg
http_filters:
- name: envoy.router
- name: envoy.router
access_log:
- name: envoy.file_access_log
filter:
not_health_check_filter: {}
not_health_check_filter: {}
config:
json_format:
time: "%START_TIME%"
protocol: "%PROTOCOL%"
duration: "%DURATION%"
request_method: "%REQ(:METHOD)%"
request_host: "%REQ(HOST)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
request_method: "%REQ(:METHOD)%"
request_host: "%REQ(HOST)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
response_flags: "%RESPONSE_FLAGS%"
route_name: "%ROUTE_NAME%"
upstream_host: "%UPSTREAM_HOST%"
upstream_cluster: "%UPSTREAM_CLUSTER%"
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
path: "/tmp/access.log"
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
path: "/tmp/access.log"
clusters:
- name: shoppingagg
connect_timeout: 0.25s
@ -113,7 +120,7 @@ static_resources:
hosts:
- socket_address:
address: basket-api
port_value: 80
port_value: 80
- name: ordering
connect_timeout: 0.25s
type: strict_dns
@ -121,4 +128,12 @@ static_resources:
hosts:
- socket_address:
address: ordering-api
port_value: 80
port_value: 80
- name: signalr-hub
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
hosts:
- socket_address:
address: ordering-signalrhub
port_value: 80

+ 25
- 10
src/ApiGateways/Envoy/config/webshopping/envoy.yaml View File

@ -42,13 +42,20 @@ static_resources:
route:
auto_host_rewrite: true
prefix_rewrite: "/ordering-api/"
cluster: ordering
cluster: ordering
- name: "o-long"
match:
prefix: "/ordering-api/"
route:
auto_host_rewrite: true
cluster: ordering
cluster: ordering
- name: "h-long"
match:
prefix: "/hub/notificationhub"
route:
auto_host_rewrite: true
cluster: signalr-hub
timeout: 300s
- name: "b-short"
match:
prefix: "/b/"
@ -61,7 +68,7 @@ static_resources:
prefix: "/basket-api/"
route:
auto_host_rewrite: true
cluster: basket
cluster: basket
- name: "agg"
match:
prefix: "/"
@ -70,7 +77,7 @@ static_resources:
prefix_rewrite: "/"
cluster: shoppingagg
http_filters:
- name: envoy.router
- name: envoy.router
access_log:
- name: envoy.file_access_log
filter:
@ -80,15 +87,15 @@ static_resources:
time: "%START_TIME%"
protocol: "%PROTOCOL%"
duration: "%DURATION%"
request_method: "%REQ(:METHOD)%"
request_host: "%REQ(HOST)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
request_method: "%REQ(:METHOD)%"
request_host: "%REQ(HOST)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
response_flags: "%RESPONSE_FLAGS%"
route_name: "%ROUTE_NAME%"
upstream_host: "%UPSTREAM_HOST%"
upstream_cluster: "%UPSTREAM_CLUSTER%"
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
path: "/tmp/access.log"
path: "/tmp/access.log"
clusters:
- name: shoppingagg
connect_timeout: 0.25s
@ -113,7 +120,7 @@ static_resources:
hosts:
- socket_address:
address: basket-api
port_value: 80
port_value: 80
- name: ordering
connect_timeout: 0.25s
type: strict_dns
@ -121,4 +128,12 @@ static_resources:
hosts:
- socket_address:
address: ordering-api
port_value: 80
port_value: 80
- name: signalr-hub
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
hosts:
- socket_address:
address: ordering-signalrhub
port_value: 80

+ 2
- 2
src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY "eShopOnContainers-ServicesAndWebApps.sln" "eShopOnContainers-ServicesAndWebApps.sln"


+ 13
- 13
src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>Mobile.Shopping.HttpAggregator</AssemblyName>
<RootNamespace>Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator</RootNamespace>
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
@ -15,19 +15,19 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.4" />
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.3" />
<PackageReference Include="Google.Protobuf" Version="3.10.0-rc1" />
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="0.2.23-pre2" />
<PackageReference Include="Grpc.Core" Version="2.24.0-pre1" />
<PackageReference Include="Grpc.Tools" Version="2.24.0-pre1" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="3.0.0" />
<PackageReference Include="Google.Protobuf" Version="3.11.2" />
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="2.25.0" />
<PackageReference Include="Grpc.Core" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Serilog.AspNetCore" Version="3.0.1-dev-00099" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.2-dev-00824" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc2" />
<PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.6.0-rc1.19456.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00834" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc5" />
</ItemGroup>
<ItemGroup>


+ 1
- 1
src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs View File

@ -49,7 +49,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
var request = MapToCustomerBasketRequest(currentBasket);
_logger.LogDebug("Grpc update basket request {@request}", request);
return client.UpdateBasketAsync(request);
return await client.UpdateBasketAsync(request);
});
}


+ 2
- 2
src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY "eShopOnContainers-ServicesAndWebApps.sln" "eShopOnContainers-ServicesAndWebApps.sln"


+ 15
- 14
src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>Web.Shopping.HttpAggregator</AssemblyName>
<RootNamespace>Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator</RootNamespace>
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
@ -15,20 +15,21 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.4" />
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.3" />
<PackageReference Include="Google.Protobuf" Version="3.10.0-rc1" />
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="0.2.23-pre2" />
<PackageReference Include="Grpc.Core" Version="2.24.0-pre1" />
<PackageReference Include="Grpc.Net.Client" Version="0.2.23-pre2" />
<PackageReference Include="Grpc.Tools" Version="2.24.0-pre1" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="3.0.0" />
<PackageReference Include="Google.Protobuf" Version="3.11.2" />
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="2.25.0" />
<PackageReference Include="Grpc.Core" Version="2.25.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Serilog.AspNetCore" Version="3.0.1-dev-00099" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.2-dev-00824" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc2" />
<PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.6.0-rc1.19456.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00834" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc5" />
<!--<PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.6.0-rc1.19456.4" />-->
</ItemGroup>
<ItemGroup>


+ 2
- 2
src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj View File

@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Microsoft.Extensions.Http" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.0" />
</ItemGroup>
</Project>

+ 1
- 1
src/BuildingBlocks/EventBus/EventBus/EventBus.csproj View File

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3-beta1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
</Project>

+ 5
- 5
src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj View File

@ -7,11 +7,11 @@
<ItemGroup>
<PackageReference Include="Autofac" Version="4.9.4" />
<PackageReference Include="Microsoft.CSharp" Version="4.6.0-rc1.19456.4" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3-beta1" />
<PackageReference Include="Polly" Version="7.1.1" />
<PackageReference Include="RabbitMQ.Client" Version="6.0.0-pre3" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Polly" Version="7.2.0" />
<PackageReference Include="RabbitMQ.Client" Version="6.0.0-rc1" />
<PackageReference Include="System.ValueTuple" Version="4.6.0-preview1-26829-04" />
</ItemGroup>


+ 3
- 3
src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj View File

@ -7,9 +7,9 @@
<ItemGroup>
<PackageReference Include="Autofac" Version="4.9.4" />
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="4.0.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.6.0-rc1.19456.4" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="4.1.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.0" />
</ItemGroup>
<ItemGroup>


+ 5
- 5
src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj View File

@ -6,14 +6,14 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0-rc1.19456.14">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-rc1.19456.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-rc1.19456.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0-rc1.19456.14" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3-beta1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>


+ 8
- 8
src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj View File

@ -1,22 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="3.0.0-preview4-19123-01" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0-rc1.19456.14">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-rc1.19456.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-rc1.19456.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0-rc1.19456.14" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="3.0.0-rc1.19456.4" />
<PackageReference Include="Polly" Version="7.1.1" />
<PackageReference Include="System.Data.SqlClient" Version="4.7.0-rc1.19456.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="3.1.0" />
<PackageReference Include="Polly" Version="7.2.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.0" />
</ItemGroup>
</Project>

+ 19
- 18
src/Services/Basket/Basket.API/Basket.API.csproj View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
<GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks>
@ -16,29 +16,30 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.5" />
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.1" />
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="2.2.4" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.4" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="5.0.0-rc1" />
<PackageReference Include="Google.Protobuf" Version="3.10.0-rc1" />
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="3.0.3" />
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Google.Protobuf" Version="3.11.2" />
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.24.0-pre1" PrivateAssets="All" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.8.0-beta3" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.11.0-beta2" />
<PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.12.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.12.0" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Serilog.AspNetCore" Version="3.0.1-dev-00099" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.1-dev-00209" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.2-dev-00824" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.1-dev-00216" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00834" />
<PackageReference Include="Serilog.Sinks.Http" Version="5.2.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="4.0.1-dev-00159" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc2" />
<PackageReference Include="Serilog.Sinks.Seq" Version="4.1.0-dev-00166" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc5" />
</ItemGroup>
<ItemGroup>


+ 2
- 2
src/Services/Basket/Basket.API/Dockerfile View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY "eShopOnContainers-ServicesAndWebApps.sln" "eShopOnContainers-ServicesAndWebApps.sln"


+ 5
- 5
src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
@ -16,10 +16,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0-preview-20190828-03" />
<PackageReference Include="Moq" Version="4.13.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>


+ 6
- 8
src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj View File

@ -1,20 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MediatR" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="3.0.0-preview4-19123-01" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="3.0.0-preview4-19123-01" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0-preview-20190828-03" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="3.0.0-rc1.19456.4" />
<PackageReference Include="Moq" Version="4.13.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="3.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="3.1.0" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>


+ 20
- 19
src/Services/Catalog/Catalog.API/Catalog.API.csproj View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<DebugType>portable</DebugType>
<PreserveCompilationContext>true</PreserveCompilationContext>
<AssemblyName>Catalog.API</AssemblyName>
@ -42,28 +42,29 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.5" />
<PackageReference Include="AspNetCore.HealthChecks.AzureStorage" Version="2.2.2" />
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.1" />
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.1" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.4" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="5.0.0-rc1" />
<PackageReference Include="Google.Protobuf" Version="3.10.0-rc1" />
<PackageReference Include="Grpc.AspNetCore.Server" Version="0.2.23-pre2" />
<PackageReference Include="Grpc.Tools" Version="2.24.0-pre1" PrivateAssets="All" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.8.0-beta3" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.11.0-beta2" />
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.AzureStorage" Version="3.0.1" />
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="3.0.3" />
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Google.Protobuf" Version="3.11.2" />
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.12.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.12.0" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-rc1.19456.10" />
<PackageReference Include="Serilog.AspNetCore" Version="3.0.1-dev-00099" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.1-dev-00209" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.2-dev-00824" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.1-dev-00216" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00834" />
<PackageReference Include="Serilog.Sinks.Http" Version="5.2.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="4.0.1-dev-00159" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc2" />
<PackageReference Include="Serilog.Sinks.Seq" Version="4.1.0-dev-00166" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc5" />
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.4.0-beta-24913-02" />
</ItemGroup>


+ 2
- 2
src/Services/Catalog/Catalog.API/Dockerfile View File

@ -1,9 +1,9 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY "eShopOnContainers-ServicesAndWebApps.sln" "eShopOnContainers-ServicesAndWebApps.sln"


+ 4
- 4
src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
@ -33,9 +33,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.0.0-rc1.19457.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0-preview-20190828-03" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>


+ 100
- 58
src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs View File

@ -1,90 +1,132 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.WebMVC.Controllers;
using Microsoft.eShopOnContainers.WebMVC.Services;
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
using Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels;
using Catalog.API.IntegrationEvents;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.Services.Catalog.API;
using Microsoft.eShopOnContainers.Services.Catalog.API.Controllers;
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
using Microsoft.eShopOnContainers.Services.Catalog.API.Model;
using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel;
using Microsoft.Extensions.Options;
using Moq;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using CatalogModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Catalog;
namespace UnitTest.Catalog.Application
{
public class CatalogControllerTest
{
private readonly Mock<ICatalogService> _catalogServiceMock;
private readonly DbContextOptions<CatalogContext> _dbOptions;
public CatalogControllerTest()
{
_catalogServiceMock = new Mock<ICatalogService>();
_dbOptions = new DbContextOptionsBuilder<CatalogContext>()
.UseInMemoryDatabase(databaseName: "in-memory")
.Options;
using (var dbContext = new CatalogContext(_dbOptions))
{
dbContext.AddRange(GetFakeCatalog());
dbContext.SaveChanges();
}
}
[Fact]
public async Task Get_catalog_items_success()
{
//Arrange
var fakeBrandFilterApplied = 1;
var fakeTypesFilterApplied = 2;
var fakePage = 2;
var fakeCatalog = GetFakeCatalog();
var brandFilterApplied = 1;
var typesFilterApplied = 2;
var pageSize = 4;
var pageIndex = 1;
var expectedNumberOfPages = 5;
var expectedTotalPages = 50;
var expectedCurrentPage = 2;
var expectedItemsInPage = 2;
var expectedTotalItems = 6;
_catalogServiceMock.Setup(x => x.GetCatalogItems
(
It.Is<int>(y => y == fakePage),
It.IsAny<int>(),
It.Is<int?>(y => y == fakeBrandFilterApplied),
It.Is<int?>(y => y == fakeTypesFilterApplied)
))
.Returns(Task.FromResult(fakeCatalog));
var catalogContext = new CatalogContext(_dbOptions);
var catalogSettings = new TestCatalogSettings();
var integrationServicesMock = new Mock<ICatalogIntegrationEventService>();
//Act
var orderController = new CatalogController(_catalogServiceMock.Object);
var actionResult = await orderController.Index(fakeBrandFilterApplied, fakeTypesFilterApplied, fakePage, null);
var orderController = new CatalogController(catalogContext, catalogSettings, integrationServicesMock.Object);
var actionResult = await orderController.ItemsByTypeIdAndBrandIdAsync(typesFilterApplied, brandFilterApplied, pageSize, pageIndex);
//Assert
var viewResult = Assert.IsType<ViewResult>(actionResult);
var model = Assert.IsAssignableFrom<IndexViewModel>(viewResult.ViewData.Model);
Assert.Equal(model.PaginationInfo.TotalPages, expectedNumberOfPages);
Assert.Equal(model.PaginationInfo.TotalItems, expectedTotalPages);
Assert.Equal(model.PaginationInfo.ActualPage, expectedCurrentPage);
Assert.Empty(model.PaginationInfo.Next);
Assert.Empty(model.PaginationInfo.Previous);
}
private CatalogModel GetFakeCatalog()
Assert.IsType<ActionResult<PaginatedItemsViewModel<CatalogItem>>>(actionResult);
var page = Assert.IsAssignableFrom<PaginatedItemsViewModel<CatalogItem>>(actionResult.Value);
Assert.Equal(expectedTotalItems, page.Count);
Assert.Equal(pageIndex, page.PageIndex);
Assert.Equal(pageSize, page.PageSize);
Assert.Equal(expectedItemsInPage, page.Data.Count());
}
private List<CatalogItem> GetFakeCatalog()
{
return new CatalogModel()
return new List<CatalogItem>()
{
PageSize = 10,
Count = 50,
PageIndex = 2,
Data = new List<CatalogItem>()
new CatalogItem()
{
Id = 1,
Name = "fakeItemA",
CatalogTypeId = 2,
CatalogBrandId = 1,
PictureFileName = "fakeItemA.png"
},
new CatalogItem()
{
Id = 2,
Name = "fakeItemB",
CatalogTypeId = 2,
CatalogBrandId = 1,
PictureFileName = "fakeItemB.png"
},
new CatalogItem()
{
Id = 3,
Name = "fakeItemC",
CatalogTypeId = 2,
CatalogBrandId = 1,
PictureFileName = "fakeItemC.png"
},
new CatalogItem()
{
new CatalogItem()
{
Id = 1,
Name = "fakeItemA",
CatalogTypeId = 1
},
new CatalogItem()
{
Id = 2,
Name = "fakeItemB",
CatalogTypeId = 1
},
new CatalogItem()
{
Id = 3,
Name = "fakeItemC",
CatalogTypeId = 1
}
Id = 4,
Name = "fakeItemD",
CatalogTypeId = 2,
CatalogBrandId = 1,
PictureFileName = "fakeItemD.png"
},
new CatalogItem()
{
Id = 5,
Name = "fakeItemE",
CatalogTypeId = 2,
CatalogBrandId = 1,
PictureFileName = "fakeItemE.png"
},
new CatalogItem()
{
Id = 6,
Name = "fakeItemF",
CatalogTypeId = 2,
CatalogBrandId = 1,
PictureFileName = "fakeItemF.png"
}
};
}
}
public class TestCatalogSettings : IOptionsSnapshot<CatalogSettings>
{
public CatalogSettings Value => new CatalogSettings
{
PicBaseUrl = "http://image-server.com/",
AzureStorageEnabled = true
};
public CatalogSettings Get(string name) => Value;
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save