From 98552b778568eeada95e2d24d115c9e6e852300f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borja=20Garc=C3=ADa=20Rodr=C3=ADguez?= Date: Mon, 21 Dec 2020 16:44:02 +0100 Subject: [PATCH] delete marketing and locations references --- README.md | 2 - build/acr-build/queue-all.ps1 | 2 - .../multiarch-manifests/create-manifests.ps1 | 2 +- deploy/azure/az/servicebus/sbusdeploy.json | 42 -- deploy/azure/az/sql/sqldeploy.json | 17 +- deploy/azure/az/sql/sqldeploy.parameters.json | 3 +- .../az/storage/marketing/deploystorage.json | 94 ----- .../marketing/deploystorage.parameters.json | 15 - deploy/azure/az/storage/marketing/readme.md | 37 -- deploy/azure/readme.md | 2 - deploy/k8s/archived/helm/apigwmm/.helmignore | 21 - deploy/k8s/archived/helm/apigwmm/Chart.yaml | 5 - deploy/k8s/archived/helm/apigwmm/envoy.yaml | 75 ---- .../archived/helm/apigwmm/templates/NOTES.txt | 2 - .../helm/apigwmm/templates/_helpers.tpl | 32 -- .../helm/apigwmm/templates/_names.tpl | 52 --- .../helm/apigwmm/templates/deployment.yaml | 110 ------ .../helm/apigwmm/templates/envoy-cm.yaml | 14 - .../helm/apigwmm/templates/ingress.yaml | 46 --- .../helm/apigwmm/templates/service.yaml | 23 -- deploy/k8s/archived/helm/apigwmm/values.yaml | 45 --- deploy/k8s/archived/helm/apigwwm/.helmignore | 21 - deploy/k8s/archived/helm/apigwwm/Chart.yaml | 5 - deploy/k8s/archived/helm/apigwwm/envoy.yaml | 75 ---- .../archived/helm/apigwwm/templates/NOTES.txt | 2 - .../helm/apigwwm/templates/_helpers.tpl | 32 -- .../helm/apigwwm/templates/_names.tpl | 52 --- .../helm/apigwwm/templates/deployment.yaml | 110 ------ .../helm/apigwwm/templates/envoy-cm.yaml | 14 - .../helm/apigwwm/templates/ingress.yaml | 47 --- .../helm/apigwwm/templates/service.yaml | 23 -- deploy/k8s/archived/helm/apigwwm/values.yaml | 46 --- deploy/k8s/archived/helm/app.yaml | 8 - deploy/k8s/archived/helm/deploy-all.ps1 | 2 +- deploy/k8s/archived/helm/deploy-all.sh | 4 +- .../identity-api/templates/configmap.yaml | 4 - .../archived/helm/identity-api/values.yaml | 4 - deploy/k8s/archived/helm/inf.yaml | 8 - .../archived/helm/locations-api/.helmignore | 21 - .../archived/helm/locations-api/Chart.yaml | 5 - .../helm/locations-api/templates/NOTES.txt | 9 - .../helm/locations-api/templates/_helpers.tpl | 32 -- .../helm/locations-api/templates/_names.tpl | 52 --- .../locations-api/templates/configmap.yaml | 22 -- .../locations-api/templates/deployment.yaml | 96 ----- .../helm/locations-api/templates/service.yaml | 19 - .../archived/helm/locations-api/values.yaml | 66 ---- .../archived/helm/marketing-api/.helmignore | 21 - .../archived/helm/marketing-api/Chart.yaml | 5 - .../helm/marketing-api/templates/NOTES.txt | 9 - .../helm/marketing-api/templates/_helpers.tpl | 32 -- .../helm/marketing-api/templates/_names.tpl | 60 --- .../marketing-api/templates/configmap.yaml | 27 -- .../marketing-api/templates/deployment.yaml | 96 ----- .../helm/marketing-api/templates/service.yaml | 19 - .../archived/helm/marketing-api/values.yaml | 70 ---- .../mobileshoppingagg/templates/NOTES.txt | 2 +- .../templates/configmap.yaml | 2 - .../helm/mobileshoppingagg/values.yaml | 4 - .../helm/webmvc/templates/configmap.yaml | 1 - deploy/k8s/archived/helm/webmvc/values.yaml | 2 - .../webshoppingagg/templates/configmap.yaml | 2 - .../archived/helm/webshoppingagg/values.yaml | 4 - .../helm/webspa/templates/configmap.yaml | 4 +- deploy/k8s/archived/helm/webspa/values.yaml | 2 - .../helm/webstatus/templates/configmap.yaml | 8 - .../k8s/archived/helm/webstatus/values.yaml | 18 +- deploy/k8s/helm/app.yaml | 8 - deploy/k8s/helm/deploy-all-mac.ps1 | 4 +- deploy/k8s/helm/deploy-all.ps1 | 4 +- deploy/k8s/helm/deploy-all.sh | 4 +- .../identity-api/templates/configmap.yaml | 4 - deploy/k8s/helm/identity-api/values.yaml | 4 - deploy/k8s/helm/inf.yaml | 8 - .../mobileshoppingagg/templates/NOTES.txt | 2 +- .../templates/configmap.yaml | 2 - deploy/k8s/helm/mobileshoppingagg/values.yaml | 4 - .../k8s/helm/webmvc/templates/configmap.yaml | 1 - deploy/k8s/helm/webmvc/values.yaml | 2 - .../webshoppingagg/templates/configmap.yaml | 2 - deploy/k8s/helm/webshoppingagg/values.yaml | 4 - .../k8s/helm/webspa/templates/configmap.yaml | 4 +- deploy/k8s/helm/webspa/values.yaml | 2 - .../helm/webstatus/templates/configmap.yaml | 8 - deploy/k8s/helm/webstatus/values.yaml | 18 +- obsolete/readme/README.ENV.md | 14 +- obsolete/readme/readme-docker-compose.md | 1 - src/.dockerignore | 3 +- src/.env | 7 - src/DockerfileSolutionRestore.txt | Bin 9084 -> 7956 bytes .../Identity.API/Configuration/Config.cs | 40 -- .../Data/ConfigurationDbContextSeed.cs | 2 - .../Controllers/HomeController.cs | 15 - .../Controllers/LocationsController.cs | 72 ---- .../Location/Locations.API/Dockerfile | 64 ---- .../Location/Locations.API/Dockerfile.develop | 17 - .../InternalServerErrorObjectResult.cs | 14 - .../Exceptions/LocationDomainException.cs | 21 - .../Filters/AuthorizeCheckOperationFilter.cs | 37 -- .../Filters/HttpGlobalExceptionFilter.cs | 68 ---- .../Infrastructure/LocationsContext.cs | 34 -- .../Infrastructure/LocationsContextSeed.cs | 354 ----------------- .../Middlewares/ByPassAuthMiddleware.cs | 79 ---- .../Repositories/ILocationsRepository.cs | 23 -- .../Repositories/LocationsRepository.cs | 65 ---- .../Services/IIdentityService.cs | 7 - .../Services/ILocationsService.cs | 18 - .../Services/IdentityService.cs | 20 - .../Services/LocationsService.cs | 97 ----- .../UserLocationUpdatedIntegrationEvent.cs | 18 - .../Locations.API/LocationSettings.cs | 15 - .../Locations.API/Locations.API.csproj | 45 --- .../Locations.API/Model/Core/LocationPoint.cs | 24 -- .../Model/Core/LocationPolygon.cs | 25 -- .../Location/Locations.API/Model/Locations.cs | 42 -- .../Locations.API/Model/UserLocation.cs | 16 - .../Model/UserLocationDetails.cs | 9 - .../Location/Locations.API/Program.cs | 88 ----- .../Properties/launchSettings.json | 29 -- .../Location/Locations.API/Startup.cs | 312 --------------- .../ViewModel/LocationRequest.cs | 8 - .../Location/Locations.API/appsettings.json | 29 -- src/Services/Location/Locations.API/azds.yaml | 56 --- .../Location/Locations.API/values.dev.yaml | 3 - .../LocationTestsStartup.cs | 56 --- .../Locations.FunctionalTests.csproj | 34 -- .../LocationsScenarioBase.cs | 47 --- .../LocationsScenarios.cs | 140 ------- .../appsettings.json | 10 - .../MarketingDetailsHttpTrigger/function.json | 16 - .../MarketingDetailsHttpTrigger/project.json | 21 - .../MarketingDetailsHttpTrigger/run.csx | 91 ----- .../Infrastructure/AzureFunctions/host.json | 1 - .../AzureFunctions/local.settings.json | 17 - .../AzureFunctions/marketing-functions.csproj | 35 -- .../Controllers/CampaignsController.cs | 232 ----------- .../Controllers/HomeController.cs | 13 - .../Controllers/LocationsController.cs | 151 -------- .../Controllers/PicController.cs | 28 -- .../Marketing/Marketing.API/Dockerfile | 64 ---- .../Marketing.API/Dockerfile.develop | 18 - .../Marketing.API/Dto/CampaignDTO.cs | 20 - .../Marketing.API/Dto/UserLocationDTO.cs | 11 - .../Marketing.API/Dto/UserLocationRuleDTO.cs | 11 - .../InternalServerErrorObjectResult.cs | 14 - .../CampaignEntityTypeConfiguration.cs | 46 --- .../RuleEntityTypeConfiguration.cs | 30 -- ...UserLocationRuleEntityTypeConfiguration.cs | 17 - .../Exceptions/MarketingDomainException.cs | 21 - .../Filters/AuthorizeCheckOperationFilter.cs | 36 -- .../Filters/HttpGlobalExceptionFilter.cs | 68 ---- .../Infrastructure/MarketingContext.cs | 45 --- .../Infrastructure/MarketingContextSeed.cs | 85 ---- .../20170615163431_Init.Designer.cs | 117 ------ .../20170615163431_Init.cs | 76 ---- ...9102516_added-campaign-details.Designer.cs | 121 ------ .../20170629102516_added-campaign-details.cs | 31 -- .../MarketingContextModelSnapshot.cs | 118 ------ .../MarketingReadDataContext.cs | 29 -- .../Middlewares/ByPassAuthMiddleware.cs | 78 ---- .../Repositories/IMarketingDataRepository.cs | 11 - .../Repositories/MarketingDataRepository.cs | 37 -- .../Services/IIdentityService.cs | 7 - .../Services/IdentityService.cs | 20 - .../UserLocationUpdatedIntegrationEvent.cs | 19 - ...rLocationUpdatedIntegrationEventHandler.cs | 57 --- .../Marketing.API/Marketing.API.csproj | 70 ---- .../Marketing.API/MarketingSettings.cs | 13 - .../Marketing/Marketing.API/Model/Campaign.cs | 32 -- .../Marketing/Marketing.API/Model/Location.cs | 9 - .../Marketing.API/Model/MarketingData.cs | 17 - .../Marketing/Marketing.API/Model/Rule.cs | 27 -- .../Marketing/Marketing.API/Model/RuleType.cs | 51 --- .../Model/UserLocationDetails.cs | 9 - .../Marketing/Marketing.API/Pics/1.png | Bin 139617 -> 0 bytes .../Marketing/Marketing.API/Pics/2.png | Bin 170303 -> 0 bytes .../Marketing/Marketing.API/Program.cs | 100 ----- .../Properties/launchSettings.json | 29 -- .../Marketing/Marketing.API/Startup.cs | 362 ------------------ .../ViewModel/PaginatedItemsViewModel.cs | 23 -- .../Marketing/Marketing.API/appsettings.json | 32 -- .../Marketing/Marketing.API/azds.yaml | 56 --- .../Marketing/Marketing.API/values.dev.yaml | 3 - .../AutoAuthorizeMiddleware.cs | 26 -- .../CampaignScenarioBase.cs | 30 -- .../CampaignScenarios.cs | 129 ------- .../Marketing.FunctionalTests.csproj | 34 -- .../MarketingScenarioBase.cs | 51 --- .../MarketingTestStartup.cs | 36 -- .../Properties/launchSettings.json | 27 -- .../UserLocationRoleScenarioBase.cs | 44 --- .../UserLocationRoleScenarios.cs | 80 ---- .../appsettings.json | 11 - src/Web/WebMVC/Startup.cs | 2 - src/Web/WebSPA/AppSettings.cs | 1 - .../shared/models/configuration.model.ts | 1 - .../shared/services/configuration.service.ts | 1 - .../shared/services/security.service.ts | 2 +- src/Web/WebSPA/appsettings.json | 2 - src/docker-compose-tests.override.yml | 53 --- src/docker-compose-tests.yml | 27 +- src/docker-compose-windows.prod.yml | 41 +- src/docker-compose.override.yml | 12 +- src/prepare-devspaces.ps1 | 15 - 204 files changed, 40 insertions(+), 7201 deletions(-) delete mode 100644 deploy/azure/az/storage/marketing/deploystorage.json delete mode 100644 deploy/azure/az/storage/marketing/deploystorage.parameters.json delete mode 100644 deploy/azure/az/storage/marketing/readme.md delete mode 100644 deploy/k8s/archived/helm/apigwmm/.helmignore delete mode 100644 deploy/k8s/archived/helm/apigwmm/Chart.yaml delete mode 100644 deploy/k8s/archived/helm/apigwmm/envoy.yaml delete mode 100644 deploy/k8s/archived/helm/apigwmm/templates/NOTES.txt delete mode 100644 deploy/k8s/archived/helm/apigwmm/templates/_helpers.tpl delete mode 100644 deploy/k8s/archived/helm/apigwmm/templates/_names.tpl delete mode 100644 deploy/k8s/archived/helm/apigwmm/templates/deployment.yaml delete mode 100644 deploy/k8s/archived/helm/apigwmm/templates/envoy-cm.yaml delete mode 100644 deploy/k8s/archived/helm/apigwmm/templates/ingress.yaml delete mode 100644 deploy/k8s/archived/helm/apigwmm/templates/service.yaml delete mode 100644 deploy/k8s/archived/helm/apigwmm/values.yaml delete mode 100644 deploy/k8s/archived/helm/apigwwm/.helmignore delete mode 100644 deploy/k8s/archived/helm/apigwwm/Chart.yaml delete mode 100644 deploy/k8s/archived/helm/apigwwm/envoy.yaml delete mode 100644 deploy/k8s/archived/helm/apigwwm/templates/NOTES.txt delete mode 100644 deploy/k8s/archived/helm/apigwwm/templates/_helpers.tpl delete mode 100644 deploy/k8s/archived/helm/apigwwm/templates/_names.tpl delete mode 100644 deploy/k8s/archived/helm/apigwwm/templates/deployment.yaml delete mode 100644 deploy/k8s/archived/helm/apigwwm/templates/envoy-cm.yaml delete mode 100644 deploy/k8s/archived/helm/apigwwm/templates/ingress.yaml delete mode 100644 deploy/k8s/archived/helm/apigwwm/templates/service.yaml delete mode 100644 deploy/k8s/archived/helm/apigwwm/values.yaml delete mode 100644 deploy/k8s/archived/helm/locations-api/.helmignore delete mode 100644 deploy/k8s/archived/helm/locations-api/Chart.yaml delete mode 100644 deploy/k8s/archived/helm/locations-api/templates/NOTES.txt delete mode 100644 deploy/k8s/archived/helm/locations-api/templates/_helpers.tpl delete mode 100644 deploy/k8s/archived/helm/locations-api/templates/_names.tpl delete mode 100644 deploy/k8s/archived/helm/locations-api/templates/configmap.yaml delete mode 100644 deploy/k8s/archived/helm/locations-api/templates/deployment.yaml delete mode 100644 deploy/k8s/archived/helm/locations-api/templates/service.yaml delete mode 100644 deploy/k8s/archived/helm/locations-api/values.yaml delete mode 100644 deploy/k8s/archived/helm/marketing-api/.helmignore delete mode 100644 deploy/k8s/archived/helm/marketing-api/Chart.yaml delete mode 100644 deploy/k8s/archived/helm/marketing-api/templates/NOTES.txt delete mode 100644 deploy/k8s/archived/helm/marketing-api/templates/_helpers.tpl delete mode 100644 deploy/k8s/archived/helm/marketing-api/templates/_names.tpl delete mode 100644 deploy/k8s/archived/helm/marketing-api/templates/configmap.yaml delete mode 100644 deploy/k8s/archived/helm/marketing-api/templates/deployment.yaml delete mode 100644 deploy/k8s/archived/helm/marketing-api/templates/service.yaml delete mode 100644 deploy/k8s/archived/helm/marketing-api/values.yaml delete mode 100644 src/Services/Location/Locations.API/Controllers/HomeController.cs delete mode 100644 src/Services/Location/Locations.API/Controllers/LocationsController.cs delete mode 100644 src/Services/Location/Locations.API/Dockerfile delete mode 100644 src/Services/Location/Locations.API/Dockerfile.develop delete mode 100644 src/Services/Location/Locations.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Exceptions/LocationDomainException.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Repositories/ILocationsRepository.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Services/ILocationsService.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs delete mode 100644 src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs delete mode 100644 src/Services/Location/Locations.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs delete mode 100644 src/Services/Location/Locations.API/LocationSettings.cs delete mode 100644 src/Services/Location/Locations.API/Locations.API.csproj delete mode 100644 src/Services/Location/Locations.API/Model/Core/LocationPoint.cs delete mode 100644 src/Services/Location/Locations.API/Model/Core/LocationPolygon.cs delete mode 100644 src/Services/Location/Locations.API/Model/Locations.cs delete mode 100644 src/Services/Location/Locations.API/Model/UserLocation.cs delete mode 100644 src/Services/Location/Locations.API/Model/UserLocationDetails.cs delete mode 100644 src/Services/Location/Locations.API/Program.cs delete mode 100644 src/Services/Location/Locations.API/Properties/launchSettings.json delete mode 100644 src/Services/Location/Locations.API/Startup.cs delete mode 100644 src/Services/Location/Locations.API/ViewModel/LocationRequest.cs delete mode 100644 src/Services/Location/Locations.API/appsettings.json delete mode 100644 src/Services/Location/Locations.API/azds.yaml delete mode 100644 src/Services/Location/Locations.API/values.dev.yaml delete mode 100644 src/Services/Location/Locations.FunctionalTests/LocationTestsStartup.cs delete mode 100644 src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj delete mode 100644 src/Services/Location/Locations.FunctionalTests/LocationsScenarioBase.cs delete mode 100644 src/Services/Location/Locations.FunctionalTests/LocationsScenarios.cs delete mode 100644 src/Services/Location/Locations.FunctionalTests/appsettings.json delete mode 100644 src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/function.json delete mode 100644 src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/project.json delete mode 100644 src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/run.csx delete mode 100644 src/Services/Marketing/Infrastructure/AzureFunctions/host.json delete mode 100644 src/Services/Marketing/Infrastructure/AzureFunctions/local.settings.json delete mode 100644 src/Services/Marketing/Infrastructure/AzureFunctions/marketing-functions.csproj delete mode 100644 src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs delete mode 100644 src/Services/Marketing/Marketing.API/Controllers/HomeController.cs delete mode 100644 src/Services/Marketing/Marketing.API/Controllers/LocationsController.cs delete mode 100644 src/Services/Marketing/Marketing.API/Controllers/PicController.cs delete mode 100644 src/Services/Marketing/Marketing.API/Dockerfile delete mode 100644 src/Services/Marketing/Marketing.API/Dockerfile.develop delete mode 100644 src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs delete mode 100644 src/Services/Marketing/Marketing.API/Dto/UserLocationDTO.cs delete mode 100644 src/Services/Marketing/Marketing.API/Dto/UserLocationRuleDTO.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/ActionResult/InternalServerErrorObjectResult.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/CampaignEntityTypeConfiguration.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/RuleEntityTypeConfiguration.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/UserLocationRuleEntityTypeConfiguration.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/Exceptions/MarketingDomainException.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/MarketingContext.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170615163431_Init.Designer.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170615163431_Init.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.Designer.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/MarketingContextModelSnapshot.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/MarketingReadDataContext.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/Repositories/IMarketingDataRepository.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/Repositories/MarketingDataRepository.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/Services/IIdentityService.cs delete mode 100644 src/Services/Marketing/Marketing.API/Infrastructure/Services/IdentityService.cs delete mode 100644 src/Services/Marketing/Marketing.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs delete mode 100644 src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs delete mode 100644 src/Services/Marketing/Marketing.API/Marketing.API.csproj delete mode 100644 src/Services/Marketing/Marketing.API/MarketingSettings.cs delete mode 100644 src/Services/Marketing/Marketing.API/Model/Campaign.cs delete mode 100644 src/Services/Marketing/Marketing.API/Model/Location.cs delete mode 100644 src/Services/Marketing/Marketing.API/Model/MarketingData.cs delete mode 100644 src/Services/Marketing/Marketing.API/Model/Rule.cs delete mode 100644 src/Services/Marketing/Marketing.API/Model/RuleType.cs delete mode 100644 src/Services/Marketing/Marketing.API/Model/UserLocationDetails.cs delete mode 100644 src/Services/Marketing/Marketing.API/Pics/1.png delete mode 100644 src/Services/Marketing/Marketing.API/Pics/2.png delete mode 100644 src/Services/Marketing/Marketing.API/Program.cs delete mode 100644 src/Services/Marketing/Marketing.API/Properties/launchSettings.json delete mode 100644 src/Services/Marketing/Marketing.API/Startup.cs delete mode 100644 src/Services/Marketing/Marketing.API/ViewModel/PaginatedItemsViewModel.cs delete mode 100644 src/Services/Marketing/Marketing.API/appsettings.json delete mode 100644 src/Services/Marketing/Marketing.API/azds.yaml delete mode 100644 src/Services/Marketing/Marketing.API/values.dev.yaml delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/AutoAuthorizeMiddleware.cs delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/CampaignScenarioBase.cs delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/CampaignScenarios.cs delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/MarketingScenarioBase.cs delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/MarketingTestStartup.cs delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/Properties/launchSettings.json delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/UserLocationRoleScenarioBase.cs delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/UserLocationRoleScenarios.cs delete mode 100644 src/Services/Marketing/Marketing.FunctionalTests/appsettings.json diff --git a/README.md b/README.md index e457ff9ea..d09cc2fb3 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,6 @@ Sample .NET Core reference application, powered by Microsoft, based on a simplif | 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) | | | diff --git a/build/acr-build/queue-all.ps1 b/build/acr-build/queue-all.ps1 index 69448f9a2..d160abfc1 100644 --- a/build/acr-build/queue-all.ps1 +++ b/build/acr-build/queue-all.ps1 @@ -14,12 +14,10 @@ $services = @( @{ Name="eshopidentity"; Image="eshop/identity.api"; File="src/Services/Identity/Identity.API/Dockerfile" }, @{ Name="eshopordering"; Image="eshop/ordering.api"; File="src/Services/Ordering/Ordering.API/Dockerfile" }, @{ Name="eshoporderingbg"; Image="eshop/ordering.backgroundtasks"; File="src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile" }, - @{ Name="eshopmarketing"; Image="eshop/marketing.api"; File="src/Services/Marketing/Marketing.API/Dockerfile" }, @{ Name="eshopwebspa"; Image="eshop/webspa"; File="src/Web/WebSPA/Dockerfile" }, @{ Name="eshopwebmvc"; Image="eshop/webmvc"; File="src/Web/WebMVC/Dockerfile" }, @{ Name="eshopwebstatus"; Image="eshop/webstatus"; File="src/Web/WebStatus/Dockerfile" }, @{ Name="eshoppayment"; Image="eshop/payment.api"; File="src/Services/Payment/Payment.API/Dockerfile" }, - @{ Name="eshoplocations"; Image="eshop/locations.api"; File="src/Services/Location/Locations.API/Dockerfile" }, @{ Name="eshopocelotapigw"; Image="eshop/ocelotapigw"; File="src/ApiGateways/ApiGw-Base/Dockerfile" }, @{ Name="eshopmobileshoppingagg"; Image="eshop/mobileshoppingagg"; File="src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile" }, @{ Name="eshopwebshoppingagg"; Image="eshop/webshoppingagg"; File="src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile" }, diff --git a/build/multiarch-manifests/create-manifests.ps1 b/build/multiarch-manifests/create-manifests.ps1 index cc7f05194..6fc67b065 100644 --- a/build/multiarch-manifests/create-manifests.ps1 +++ b/build/multiarch-manifests/create-manifests.ps1 @@ -12,7 +12,7 @@ Write-Host "Tags used are linux-master, win-master, linux-dev, win-dev, linux-la Write-Host "Multiarch images tags will be master, dev, latest" -ForegroundColor Yellow -$services = "identity.api", "basket.api", "catalog.api", "ordering.api", "ordering.backgroundtasks", "marketing.api", "payment.api", "locations.api", "webhooks.api", "ocelotapigw", "mobileshoppingagg", "webshoppingagg", "ordering.signalrhub", "webstatus", "webspa", "webmvc", "webhooks.client" +$services = "identity.api", "basket.api", "catalog.api", "ordering.api", "ordering.backgroundtasks", "payment.api", "webhooks.api", "ocelotapigw", "mobileshoppingagg", "webshoppingagg", "ordering.signalrhub", "webstatus", "webspa", "webmvc", "webhooks.client" foreach ($svc in $services) { Write-Host "Creating manifest for $svc and tags :latest, :master, and :dev" diff --git a/deploy/azure/az/servicebus/sbusdeploy.json b/deploy/azure/az/servicebus/sbusdeploy.json index 50c1c6c54..46ac930aa 100644 --- a/deploy/azure/az/servicebus/sbusdeploy.json +++ b/deploy/azure/az/servicebus/sbusdeploy.json @@ -14,8 +14,6 @@ "BasketSubscriptionName": "Basket", "CatalogSubscriptionName": "Catalog", "OrderingSubscriptionName": "Ordering", - "LocationsSubscriptionName": "Locations", - "MarketingSubscriptionName": "Marketing", "GracePeriodSubscriptionName": "GracePeriod", "PaymentSubscriptionName": "Payment", "location": "[resourceGroup().location]", @@ -135,46 +133,6 @@ "entityAvailabilityStatus": "Available" } }, - { - "apiVersion": "[variables('sbVersion')]", - "name": "[variables('LocationsSubscriptionName')]", - "type": "Subscriptions", - "dependsOn": [ - "[variables('serviceBusTopicName')]" - ], - "properties": { - "lockDuration": "00:00:30", - "requiresSession": false, - "defaultMessageTimeToLive": "14.00:00:00", - "deadLetteringOnMessageExpiration": true, - "deadLetteringOnFilterEvaluationExceptions": true, - "maxDeliveryCount": 10, - "enableBatchedOperations": false, - "status": "Active", - "autoDeleteOnIdle": "10675199.02:48:05.4775807", - "entityAvailabilityStatus": "Available" - } - }, - { - "apiVersion": "[variables('sbVersion')]", - "name": "[variables('MarketingSubscriptionName')]", - "type": "Subscriptions", - "dependsOn": [ - "[variables('serviceBusTopicName')]" - ], - "properties": { - "lockDuration": "00:00:30", - "requiresSession": false, - "defaultMessageTimeToLive": "14.00:00:00", - "deadLetteringOnMessageExpiration": true, - "deadLetteringOnFilterEvaluationExceptions": true, - "maxDeliveryCount": 10, - "enableBatchedOperations": false, - "status": "Active", - "autoDeleteOnIdle": "10675199.02:48:05.4775807", - "entityAvailabilityStatus": "Available" - } - }, { "apiVersion": "[variables('sbVersion')]", "name": "[variables('GracePeriodSubscriptionName')]", diff --git a/deploy/azure/az/sql/sqldeploy.json b/deploy/azure/az/sql/sqldeploy.json index 397c94ad6..2bc8eeac3 100644 --- a/deploy/azure/az/sql/sqldeploy.json +++ b/deploy/azure/az/sql/sqldeploy.json @@ -73,22 +73,7 @@ "dependsOn": [ "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" ] - }, - { - "type": "databases", - "name": "[parameters('sql_server').dbs.marketing]", - "apiVersion": "2014-04-01-preview", - "location": "[resourceGroup().location]", - "properties": { - "edition": "Standard", - "collation": "SQL_Latin1_General_CP1_CI_AS", - "maxSizeBytes": "1073741824", - "requestedServiceObjectiveName": "S1" - }, - "dependsOn": [ - "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" - ] - }, + }, { "type": "firewallrules", "name": "AllowAllWindowsAzureIps", diff --git a/deploy/azure/az/sql/sqldeploy.parameters.json b/deploy/azure/az/sql/sqldeploy.parameters.json index 982e78f4c..473cf08cd 100644 --- a/deploy/azure/az/sql/sqldeploy.parameters.json +++ b/deploy/azure/az/sql/sqldeploy.parameters.json @@ -8,8 +8,7 @@ "dbs": { "ordering": "orderingdb", "identity": "identitydb", - "catalog": "catalogdb", - "marketing": "marketingdb" + "catalog": "catalogdb" } } }, diff --git a/deploy/azure/az/storage/marketing/deploystorage.json b/deploy/azure/az/storage/marketing/deploystorage.json deleted file mode 100644 index 632e0d09a..000000000 --- a/deploy/azure/az/storage/marketing/deploystorage.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "marketingstorage": { - "type": "string" - }, - "profileName" : { - "type": "string" - }, - "endpointName" : { - "type": "string" - } - }, - "variables": { - "marketingstorage": "[concat(parameters('marketingstorage'), uniqueString(resourceGroup().id))]", - "endpointName": "[concat(parameters('endpointName'), uniqueString(resourceGroup().id))]", - "profileName": "[parameters('profileName')]" - }, - "resources": [ - { - "type": "Microsoft.Storage/storageAccounts", - "name": "[variables('marketingstorage')]", - "apiVersion": "2016-01-01", - "location": "[resourceGroup().location]", - "tags": { - "displayName": "[variables('marketingstorage')]" - }, - "sku": { - "name": "Standard_LRS" - }, - "kind": "Storage" - }, - { - "name": "[variables('profileName')]", - "type": "Microsoft.Cdn/profiles", - "location": "[resourceGroup().location]", - "apiVersion": "2016-04-02", - "tags": { - "displayName": "[variables('profileName')]" - }, - "sku": { - "name": "Standard_Verizon" - }, - "resources": [ - { - "apiVersion": "2016-04-02", - "name": "[variables('endpointName')]", - "type": "endpoints", - "dependsOn": [ - "[variables('profileName')]", - "[variables('marketingstorage')]" - ], - "location": "[resourceGroup().location]", - "tags": { - "displayName": "[variables('endpointName')]" - }, - "properties": { - "originHostHeader": "[replace(replace(reference(resourceId('Microsoft.Storage/storageAccounts', variables('marketingstorage')),'2015-06-15' ).primaryEndpoints.blob,'https://',''),'/','')]", - "isHttpAllowed": true, - "isHttpsAllowed": true, - "queryStringCachingBehavior": "IgnoreQueryString", - "contentTypesToCompress": [ - "text/plain", - "text/html", - "text/css", - "application/x-javascript", - "text/javascript" - ], - "isCompressionEnabled": "True", - "origins": [ - { - "name": "origin1", - "properties": { - "hostName": "[replace(replace(reference(resourceId('Microsoft.Storage/storageAccounts', variables('marketingstorage')),'2015-06-15' ).primaryEndpoints.blob,'https://',''),'/','')]" - } - } - ] - } - } - ] - } - ], - "outputs": { - "hostName": { - "type": "string", - "value": "[reference(resourceId('Microsoft.cdn/profiles/endpoints', variables('profileName'), variables('endpointName'))).hostName]" - }, - "originHostHeader": { - "type": "string", - "value": "[reference(resourceId('Microsoft.cdn/profiles/endpoints', variables('profileName'), variables('endpointName'))).originHostHeader]" - } - } -} \ No newline at end of file diff --git a/deploy/azure/az/storage/marketing/deploystorage.parameters.json b/deploy/azure/az/storage/marketing/deploystorage.parameters.json deleted file mode 100644 index 40f7b3a1b..000000000 --- a/deploy/azure/az/storage/marketing/deploystorage.parameters.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "marketingstorage": { - "value": "marketing" - }, - "profileName":{ - "value": "eshopmarketing" - }, - "endpointName":{ - "value": "marketing-endpoint" - } - } -} \ No newline at end of file diff --git a/deploy/azure/az/storage/marketing/readme.md b/deploy/azure/az/storage/marketing/readme.md deleted file mode 100644 index c0ec2be7a..000000000 --- a/deploy/azure/az/storage/marketing/readme.md +++ /dev/null @@ -1,37 +0,0 @@ -# Deploying Marketing Storage - -The ARM template `deploystorage.json` and its parameter file (`deploystorage.parameters.json`) are used to deploy following resources: - -1. One Storage Account -2. One CDN profile -3. One Endpoint - -## Editing deploystorage.parameters.json file - -You can edit the `deploystorage.parameters.json` file to set your values, but is not needed. The only parameters that can -be set are: - -1. `marketingstorage` is a string that is used to create the storage account name. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. - -2. `profileName` is a string that is used to create the CDN profile name. - -3. `endpointName` is a string that is used to create the storage endpoint name. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. - -## Deploy the template - -Once parameter file is edited you can deploy it using [create-resources script](../../readme.md). - -i. e. if you are in windows, to deploy a Storage account in a new resourcegroup located in westus, go to `deploy\az` folder and type: - -``` -create-resources.cmd storage\marketing\deploystorage newResourceGroup -c westus -``` - - - - - - - - - diff --git a/deploy/azure/readme.md b/deploy/azure/readme.md index 27b168713..cc35bb001 100644 --- a/deploy/azure/readme.md +++ b/deploy/azure/readme.md @@ -22,8 +22,6 @@ Using `docker-machine` is the recommended way to create a VM with docker install 3. [Deploying Redis Cache](az/redis/readme.md) 4. [Deploying Cosmosdb](az/cosmos/readme.md) 5. [Deploying Catalog Storage](az/storage/catalog/readme.md) -6. [Deploying Marketing Storage](az/storage/marketing/readme.md) -7. [Deploying Marketing Azure functions](az/azurefunctions/readme.md) diff --git a/deploy/k8s/archived/helm/apigwmm/.helmignore b/deploy/k8s/archived/helm/apigwmm/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/apigwmm/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# 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 diff --git a/deploy/k8s/archived/helm/apigwmm/Chart.yaml b/deploy/k8s/archived/helm/apigwmm/Chart.yaml deleted file mode 100644 index 50b3d07c6..000000000 --- a/deploy/k8s/archived/helm/apigwmm/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: apigwmm -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/apigwmm/envoy.yaml b/deploy/k8s/archived/helm/apigwmm/envoy.yaml deleted file mode 100644 index 54b1afa06..000000000 --- a/deploy/k8s/archived/helm/apigwmm/envoy.yaml +++ /dev/null @@ -1,75 +0,0 @@ -admin: - access_log_path: "/dev/null" - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 -static_resources: - listeners: - - address: - socket_address: - address: 0.0.0.0 - port_value: 80 - filter_chains: - - filters: - - name: envoy.http_connection_manager - config: - codec_type: auto - stat_prefix: ingress_http - route_config: - name: eshop_backend_route - virtual_hosts: - - name: eshop_backend - domains: - - "*" - routes: - - name: "m-short" - match: - prefix: "/m/" - route: - auto_host_rewrite: true - prefix_rewrite: "/marketing-api/" - cluster: marketing - - name: "m-long" - match: - prefix: "/marketing-api/" - route: - auto_host_rewrite: true - cluster: marketing - http_filters: - - name: envoy.router - access_log: - - name: envoy.file_access_log - 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)%" - 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" - clusters: - - name: marketing - connect_timeout: 0.25s - type: logical_dns - lb_policy: round_robin - hosts: - - socket_address: - address: marketing-api - port_value: 80 - - name: locations - connect_timeout: 0.25s - type: logical_dns - lb_policy: round_robin - hosts: - - socket_address: - address: locations-api - port_value: 80 diff --git a/deploy/k8s/archived/helm/apigwmm/templates/NOTES.txt b/deploy/k8s/archived/helm/apigwmm/templates/NOTES.txt deleted file mode 100644 index 30ef33447..000000000 --- a/deploy/k8s/archived/helm/apigwmm/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -eShop API Gateway for Mobile Marketing services installed ----------------------------------------------------------- \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwmm/templates/_helpers.tpl b/deploy/k8s/archived/helm/apigwmm/templates/_helpers.tpl deleted file mode 100644 index fd3d89212..000000000 --- a/deploy/k8s/archived/helm/apigwmm/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "apigwmm.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 "apigwmm.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 "apigwmm.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/apigwmm/templates/_names.tpl b/deploy/k8s/archived/helm/apigwmm/templates/_names.tpl deleted file mode 100644 index d44859fea..000000000 --- a/deploy/k8s/archived/helm/apigwmm/templates/_names.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwmm/templates/deployment.yaml b/deploy/k8s/archived/helm/apigwmm/templates/deployment.yaml deleted file mode 100644 index f93706bb9..000000000 --- a/deploy/k8s/archived/helm/apigwmm/templates/deployment.yaml +++ /dev/null @@ -1,110 +0,0 @@ -{{- $name := include "apigwmm.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -{{- $envoycfgname := printf "%s-%s" "envoy" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "apigwmm.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "apigwmm.name" . }} - chart: {{ template "apigwmm.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "apigwmm.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "apigwmm.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - volumes: - - name: config - configMap: - name: {{ $envoycfgname }} - items: - - key: envoy.yaml - path: envoy.yaml - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: IfNotPresent - volumeMounts: - - name: config - mountPath: {{ .Values.envoy.configPath }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: admin - containerPort: 8001 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/apigwmm/templates/envoy-cm.yaml b/deploy/k8s/archived/helm/apigwmm/templates/envoy-cm.yaml deleted file mode 100644 index 71728d084..000000000 --- a/deploy/k8s/archived/helm/apigwmm/templates/envoy-cm.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- $name := include "apigwmm.fullname" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "envoy-{{ $name }}" - labels: - app: {{ template "apigwmm.name" . }} - chart: {{ template "apigwmm.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - {{ (.Files.Glob "envoy.yaml").AsConfig | indent 2 }} - diff --git a/deploy/k8s/archived/helm/apigwmm/templates/ingress.yaml b/deploy/k8s/archived/helm/apigwmm/templates/ingress.yaml deleted file mode 100644 index 44e9a90fc..000000000 --- a/deploy/k8s/archived/helm/apigwmm/templates/ingress.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.mobilemarketingapigw -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "apigwmm.fullname" . }} - labels: - app: {{ template "apigwmm.name" . }} - chart: {{ template "apigwmm.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - 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: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $serviceName }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/apigwmm/templates/service.yaml b/deploy/k8s/archived/helm/apigwmm/templates/service.yaml deleted file mode 100644 index 286277c7d..000000000 --- a/deploy/k8s/archived/helm/apigwmm/templates/service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.mobilemarketingapigw }} - labels: - app: {{ template "apigwmm.name" . }} - chart: {{ template "apigwmm.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - - port: {{ .Values.service.adminPort }} - targetPort: admin - protocol: TCP - name: admin - selector: - app: {{ template "apigwmm.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/apigwmm/values.yaml b/deploy/k8s/archived/helm/apigwmm/values.yaml deleted file mode 100644 index 21f12f27a..000000000 --- a/deploy/k8s/archived/helm/apigwmm/values.yaml +++ /dev/null @@ -1,45 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /mobilemarketingapigw - -image: - repository: envoyproxy/envoy - tag: v1.11.1 - -service: - type: ClusterIP - port: 80 - adminPort: 8001 - -ingress: - enabled: true - annotations: - nginx.ingress.kubernetes.io/rewrite-target: "/" - ingress.kubernetes.io/rewrite-target: "/" - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -env: {} - -envoy: - configPath: /etc/envoy - -probes: - liveness: - path: /ready - initialDelaySeconds: 5 - periodSeconds: 15 - port: 8001 - readiness: - path: /ready - initialDelaySeconds: 5 - periodSeconds: 60 - port: 8001 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwwm/.helmignore b/deploy/k8s/archived/helm/apigwwm/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/apigwwm/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# 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 diff --git a/deploy/k8s/archived/helm/apigwwm/Chart.yaml b/deploy/k8s/archived/helm/apigwwm/Chart.yaml deleted file mode 100644 index 4c2082969..000000000 --- a/deploy/k8s/archived/helm/apigwwm/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: apigwwm -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/apigwwm/envoy.yaml b/deploy/k8s/archived/helm/apigwwm/envoy.yaml deleted file mode 100644 index c6f3421de..000000000 --- a/deploy/k8s/archived/helm/apigwwm/envoy.yaml +++ /dev/null @@ -1,75 +0,0 @@ -admin: - access_log_path: "/dev/null" - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 -static_resources: - listeners: - - address: - socket_address: - address: 0.0.0.0 - port_value: 80 - filter_chains: - - filters: - - name: envoy.http_connection_manager - config: - codec_type: auto - stat_prefix: ingress_http - route_config: - name: eshop_backend_route - virtual_hosts: - - name: eshop_backend - domains: - - "*" - routes: - - name: "m-short" - match: - prefix: "/m/" - route: - auto_host_rewrite: true - prefix_rewrite: "/marketing-api/" - cluster: marketing - - name: "m-long" - match: - prefix: "/marketing-api/" - route: - auto_host_rewrite: true - cluster: marketing - http_filters: - - name: envoy.router - access_log: - - name: envoy.file_access_log - 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)%" - 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" - clusters: - - name: marketing - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: marketing-api - port_value: 80 - - name: locations - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: locations-api - port_value: 80 diff --git a/deploy/k8s/archived/helm/apigwwm/templates/NOTES.txt b/deploy/k8s/archived/helm/apigwwm/templates/NOTES.txt deleted file mode 100644 index 3420c97c8..000000000 --- a/deploy/k8s/archived/helm/apigwwm/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -eShop API Gateway for Web Marketing services installed ------------------------------------------------------- \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwwm/templates/_helpers.tpl b/deploy/k8s/archived/helm/apigwwm/templates/_helpers.tpl deleted file mode 100644 index 194cf96ca..000000000 --- a/deploy/k8s/archived/helm/apigwwm/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "apigwwm.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 "apigwwm.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 "apigwwm.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/apigwwm/templates/_names.tpl b/deploy/k8s/archived/helm/apigwwm/templates/_names.tpl deleted file mode 100644 index d44859fea..000000000 --- a/deploy/k8s/archived/helm/apigwwm/templates/_names.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwwm/templates/deployment.yaml b/deploy/k8s/archived/helm/apigwwm/templates/deployment.yaml deleted file mode 100644 index 6ceb1fa1b..000000000 --- a/deploy/k8s/archived/helm/apigwwm/templates/deployment.yaml +++ /dev/null @@ -1,110 +0,0 @@ -{{- $name := include "apigwwm.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -{{- $envoycfgname := printf "%s-%s" "envoy" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "apigwwm.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "apigwwm.name" . }} - chart: {{ template "apigwwm.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "apigwwm.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "apigwwm.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - volumes: - - name: config - configMap: - name: {{ $envoycfgname }} - items: - - key: envoy.yaml - path: envoy.yaml - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: IfNotPresent - volumeMounts: - - name: config - mountPath: {{ .Values.envoy.configPath }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: admin - containerPort: 8001 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/apigwwm/templates/envoy-cm.yaml b/deploy/k8s/archived/helm/apigwwm/templates/envoy-cm.yaml deleted file mode 100644 index 4d6307e36..000000000 --- a/deploy/k8s/archived/helm/apigwwm/templates/envoy-cm.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- $name := include "apigwwm.fullname" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "envoy-{{ $name }}" - labels: - app: {{ template "apigwwm.name" . }} - chart: {{ template "apigwwm.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - {{ (.Files.Glob "envoy.yaml").AsConfig | indent 2 -}} - diff --git a/deploy/k8s/archived/helm/apigwwm/templates/ingress.yaml b/deploy/k8s/archived/helm/apigwwm/templates/ingress.yaml deleted file mode 100644 index 00d54c226..000000000 --- a/deploy/k8s/archived/helm/apigwwm/templates/ingress.yaml +++ /dev/null @@ -1,47 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.webmarketingapigw -}} - -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "apigwwm.fullname" . }} - labels: - app: {{ template "apigwwm.name" . }} - chart: {{ template "apigwwm.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - 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: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $serviceName }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/apigwwm/templates/service.yaml b/deploy/k8s/archived/helm/apigwwm/templates/service.yaml deleted file mode 100644 index cb11cc665..000000000 --- a/deploy/k8s/archived/helm/apigwwm/templates/service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.webmarketingapigw }} - labels: - app: {{ template "apigwwm.name" . }} - chart: {{ template "apigwwm.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - - port: {{ .Values.service.adminPort }} - targetPort: admin - protocol: TCP - name: admin - selector: - app: {{ template "apigwwm.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/apigwwm/values.yaml b/deploy/k8s/archived/helm/apigwwm/values.yaml deleted file mode 100644 index d866c2d3c..000000000 --- a/deploy/k8s/archived/helm/apigwwm/values.yaml +++ /dev/null @@ -1,46 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /webmarketingapigw - -image: - repository: envoyproxy/envoy - tag: v1.11.1 - -service: - type: ClusterIP - port: 80 - adminPort: 8001 - -ingress: - enabled: true - annotations: - nginx.ingress.kubernetes.io/rewrite-target: "/" - ingress.kubernetes.io/rewrite-target: "/" - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: {} - -envoy: - configPath: /etc/envoy - -probes: - liveness: - path: /ready - initialDelaySeconds: 5 - periodSeconds: 15 - port: 8001 - readiness: - path: /ready - initialDelaySeconds: 5 - periodSeconds: 60 - port: 8001 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/app.yaml b/deploy/k8s/archived/helm/app.yaml index e83ea2823..acea31ef1 100644 --- a/deploy/k8s/archived/helm/app.yaml +++ b/deploy/k8s/archived/helm/app.yaml @@ -13,14 +13,10 @@ app: # app global settings spa: "" # ingress entry for web spa status: webstatus # ingress entry for web status webshoppingapigw: webshoppingapigw # ingress entry for web shopping Agw - webmarketingapigw: webmarketingapigw # ingress entry for web mkg Agw - mobilemarketingapigw: mobilemarketingapigw # ingress entry for mobile mkg Agw mobileshoppingapigw: mobileshoppingapigw # ingress entry for mobile shopping Agw webshoppingagg: webshoppingagg # ingress entry for web shopping aggregator mobileshoppingagg: mobileshoppingagg # ingress entry for mobile shopping aggregator payment: payment-api # ingress entry for payment api - locations: locations-api # ingress entry for locations api - marketing: marketing-api # ingress entry for marketing api webhooks: webhooks-api # ingress entry for webhooks api webhooksweb: webhooks-web # ingress entry for webhooks web demo client svc: @@ -34,13 +30,9 @@ app: # app global settings spa: webspa # service name for web spa status: webstatus # service name for web status webshoppingapigw: webshoppingapigw # service name for web shopping Agw - webmarketingapigw: webmarketingapigw # service name for web mkg Agw - mobilemarketingapigw: mobilemarketingapigw # service name for mobile mkg Agw mobileshoppingapigw: mobileshoppingapigw # service name for mobile shopping Agw webshoppingagg: webshoppingagg # service name for web shopping aggregator mobileshoppingagg: mobileshoppingagg # service name for mobile shopping aggregator payment: payment-api # service name for payment api - locations: locations-api # service name for locations api - marketing: marketing-api # service name for marketing ap webhooks: webhooks-api # service name for webhooks api webhooksweb: webhooks-client # service name for webhooks web diff --git a/deploy/k8s/archived/helm/deploy-all.ps1 b/deploy/k8s/archived/helm/deploy-all.ps1 index 1711c0c2c..51d87e720 100644 --- a/deploy/k8s/archived/helm/deploy-all.ps1 +++ b/deploy/k8s/archived/helm/deploy-all.ps1 @@ -113,7 +113,7 @@ if (-not [string]::IsNullOrEmpty($registry)) { Write-Host "Begin eShopOnContainers installation using Helm" -ForegroundColor Green $infras = ("sql-data", "nosql-data", "rabbitmq", "keystore-data", "basket-data") -$charts = ("eshop-common", "basket-api","catalog-api", "identity-api", "locations-api", "marketing-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web") +$charts = ("eshop-common", "basket-api","catalog-api", "identity-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web") $gateways = ("apigwmm", "apigwms", "apigwwm", "apigwws") if ($deployInfrastructure) { diff --git a/deploy/k8s/archived/helm/deploy-all.sh b/deploy/k8s/archived/helm/deploy-all.sh index 6f6d868aa..ad76bd54c 100644 --- a/deploy/k8s/archived/helm/deploy-all.sh +++ b/deploy/k8s/archived/helm/deploy-all.sh @@ -142,7 +142,7 @@ fi if [[ $push_images ]]; then echo "#################### Pushing images to the container registry ####################" - services=(basket.api catalog.api identity.api ordering.api marketing.api payment.api locations.api webmvc webspa webstatus) + services=(basket.api catalog.api identity.api ordering.api payment.api webmvc webspa webstatus) if [[ -z "$(docker image ls -q --filter=reference=eshop/$service:$image_tag)" ]]; then image_tag=linux-$image_tag @@ -209,7 +209,7 @@ fi echo "#################### Begin $app_name installation using Helm ####################" infras=(sql-data nosql-data rabbitmq keystore-data basket-data) -charts=(eshop-common apigwmm apigwms apigwwm apigwws basket-api catalog-api identity-api locations-api marketing-api mobileshoppingagg ordering-api ordering-backgroundtasks ordering-signalrhub payment-api webmvc webshoppingagg webspa webstatus webhooks-api webhooks-web) +charts=(eshop-common apigwms apigwws basket-api catalog-api identity-api mobileshoppingagg ordering-api ordering-backgroundtasks ordering-signalrhub payment-api webmvc webshoppingagg webspa webstatus webhooks-api webhooks-web) if [[ !$skip_infrastructure ]]; then for infra in "${infras[@]}" diff --git a/deploy/k8s/archived/helm/identity-api/templates/configmap.yaml b/deploy/k8s/archived/helm/identity-api/templates/configmap.yaml index 264ceb745..7c670f646 100644 --- a/deploy/k8s/archived/helm/identity-api/templates/configmap.yaml +++ b/deploy/k8s/archived/helm/identity-api/templates/configmap.yaml @@ -2,8 +2,6 @@ {{- $sqlsrv := include "sql-name" . -}} {{- $mvc_url := include "url-of" (list .Values.app.ingress.entries.mvc .) -}} {{- $spa_url := include "url-of" (list .Values.app.ingress.entries.spa .) -}} -{{- $locations_url := include "url-of" (list .Values.app.ingress.entries.locations .) -}} -{{- $marketing_url := include "url-of" (list .Values.app.ingress.entries.marketing .) -}} {{- $basket_url := include "url-of" (list .Values.app.ingress.entries.basket .) -}} {{- $ordering_url := include "url-of" (list .Values.app.ingress.entries.ordering .) -}} {{- $mobileshoppingagg := include "url-of" (list .Values.app.ingress.entries.mobileshoppingagg .) -}} @@ -27,8 +25,6 @@ data: all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" mvc_e: http://{{ $mvc_url }} spa_e: http://{{ $spa_url }} - locations_e: http://{{ $locations_url }} - marketing_e: http://{{ $marketing_url }} basket_e: http://{{ $basket_url }} ordering_e: http://{{ $ordering_url }} mobileshoppingagg_e: http://{{ $mobileshoppingagg }} diff --git a/deploy/k8s/archived/helm/identity-api/values.yaml b/deploy/k8s/archived/helm/identity-api/values.yaml index 7b57dfde1..92fd57283 100644 --- a/deploy/k8s/archived/helm/identity-api/values.yaml +++ b/deploy/k8s/archived/helm/identity-api/values.yaml @@ -40,10 +40,6 @@ env: key: mvc_e - name: SpaClient key: spa_e - - name: LocationApiClient - key: locations_e - - name: MarketingApiClient - key: marketing_e - name: BasketApiClient key: basket_e - name: OrderingApiClient diff --git a/deploy/k8s/archived/helm/inf.yaml b/deploy/k8s/archived/helm/inf.yaml index 938be3d45..e73b37ee8 100644 --- a/deploy/k8s/archived/helm/inf.yaml +++ b/deploy/k8s/archived/helm/inf.yaml @@ -19,16 +19,8 @@ inf: db: OrderingDb # Ordering API SQL db name identity: db: IdentityDb # Ordering API SQL db name - marketing: - db: MarketingDb # Marketing API SQL db name webhooks: db: WebhooksDb # Webhooks DB - mongo: -# host: my-nosql-data # Uncomment to use specify custom mongo host. By default nosql-data is used - locations: - database: LocationsDb - marketing: - database: MarketingDb redis: # inf.redis defines the redis' connection strings basket: svc: basket-data # Name of k8s svc for basket redis diff --git a/deploy/k8s/archived/helm/locations-api/.helmignore b/deploy/k8s/archived/helm/locations-api/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/locations-api/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# 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 diff --git a/deploy/k8s/archived/helm/locations-api/Chart.yaml b/deploy/k8s/archived/helm/locations-api/Chart.yaml deleted file mode 100644 index 5126fe847..000000000 --- a/deploy/k8s/archived/helm/locations-api/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: locations-api -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/locations-api/templates/NOTES.txt b/deploy/k8s/archived/helm/locations-api/templates/NOTES.txt deleted file mode 100644 index 3b48889bf..000000000 --- a/deploy/k8s/archived/helm/locations-api/templates/NOTES.txt +++ /dev/null @@ -1,9 +0,0 @@ -eShop Locations API installed. ------------------------------- - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "locations-api.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 - diff --git a/deploy/k8s/archived/helm/locations-api/templates/_helpers.tpl b/deploy/k8s/archived/helm/locations-api/templates/_helpers.tpl deleted file mode 100644 index 086a461ba..000000000 --- a/deploy/k8s/archived/helm/locations-api/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "locations-api.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 "locations-api.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 "locations-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/locations-api/templates/_names.tpl b/deploy/k8s/archived/helm/locations-api/templates/_names.tpl deleted file mode 100644 index d44859fea..000000000 --- a/deploy/k8s/archived/helm/locations-api/templates/_names.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/locations-api/templates/configmap.yaml b/deploy/k8s/archived/helm/locations-api/templates/configmap.yaml deleted file mode 100644 index c5d752509..000000000 --- a/deploy/k8s/archived/helm/locations-api/templates/configmap.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- $name := include "locations-api.fullname" . -}} -{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} -{{- $mongo := include "mongo-name" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "locations-api.name" . }} - chart: {{ template "locations-api.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" - all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" - internalurls__IdentityUrl: http://{{ .Values.app.svc.identity }} - urls__IdentityUrl: {{ $identity }} - locations__ConnectionString: mongodb://{{ $mongo }} - locations__Database: {{ .Values.inf.mongo.locations.database }} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/locations-api/templates/deployment.yaml b/deploy/k8s/archived/helm/locations-api/templates/deployment.yaml deleted file mode 100644 index 9a5bb608c..000000000 --- a/deploy/k8s/archived/helm/locations-api/templates/deployment.yaml +++ /dev/null @@ -1,96 +0,0 @@ -{{- $name := include "locations-api.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "locations-api.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "locations-api.name" . }} - chart: {{ template "locations-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "locations-api.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "locations-api.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/locations-api/templates/service.yaml b/deploy/k8s/archived/helm/locations-api/templates/service.yaml deleted file mode 100644 index abd628beb..000000000 --- a/deploy/k8s/archived/helm/locations-api/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.locations }} - labels: - app: {{ template "locations-api.name" . }} - chart: {{ template "locations-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "locations-api.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/locations-api/values.yaml b/deploy/k8s/archived/helm/locations-api/values.yaml deleted file mode 100644 index 4718f2a0b..000000000 --- a/deploy/k8s/archived/helm/locations-api/values.yaml +++ /dev/null @@ -1,66 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /locations-api - -image: - repository: eshop/locations.api - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: false - annotations: {} - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: EventBusConnection - key: all__EventBusConnection - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - - name: UseLoadTest - key: all_EnableLoadTest - - name: IdentityUrl - key: internalurls__IdentityUrl - - name: IdentityUrlExternal - key: urls__IdentityUrl - - name: ConnectionString - key: locations__ConnectionString - - name: Database - key: locations__Database - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 diff --git a/deploy/k8s/archived/helm/marketing-api/.helmignore b/deploy/k8s/archived/helm/marketing-api/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/marketing-api/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# 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 diff --git a/deploy/k8s/archived/helm/marketing-api/Chart.yaml b/deploy/k8s/archived/helm/marketing-api/Chart.yaml deleted file mode 100644 index 173f94fd6..000000000 --- a/deploy/k8s/archived/helm/marketing-api/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: marketing-api -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/marketing-api/templates/NOTES.txt b/deploy/k8s/archived/helm/marketing-api/templates/NOTES.txt deleted file mode 100644 index 7fa66ed47..000000000 --- a/deploy/k8s/archived/helm/marketing-api/templates/NOTES.txt +++ /dev/null @@ -1,9 +0,0 @@ -eShop Marketing API installed. ------------------------------- - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "marketing-api.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 - diff --git a/deploy/k8s/archived/helm/marketing-api/templates/_helpers.tpl b/deploy/k8s/archived/helm/marketing-api/templates/_helpers.tpl deleted file mode 100644 index c252aeeac..000000000 --- a/deploy/k8s/archived/helm/marketing-api/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "marketing-api.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 "marketing-api.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 "marketing-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/marketing-api/templates/_names.tpl b/deploy/k8s/archived/helm/marketing-api/templates/_names.tpl deleted file mode 100644 index 605e92e7e..000000000 --- a/deploy/k8s/archived/helm/marketing-api/templates/_names.tpl +++ /dev/null @@ -1,60 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} - -{{- define "protocol" -}} -{{- if .Values.inf.tls.enabled -}} -{{- printf "%s" "https" -}} -{{- else -}} -{{- printf "%s" "http" -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/marketing-api/templates/configmap.yaml b/deploy/k8s/archived/helm/marketing-api/templates/configmap.yaml deleted file mode 100644 index e6b495a7a..000000000 --- a/deploy/k8s/archived/helm/marketing-api/templates/configmap.yaml +++ /dev/null @@ -1,27 +0,0 @@ -{{- $name := include "marketing-api.fullname" . -}} -{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} -{{- $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 -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "marketing-api.name" . }} - chart: {{ template "marketing-api.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" - all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" - internalurls__IdentityUrl: http://{{ .Values.app.svc.identity }} - 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: {{ $protocol }}://{{ $webshoppingapigw }}/c/api/v1/catalog/items/[0]/pic/ \ No newline at end of file diff --git a/deploy/k8s/archived/helm/marketing-api/templates/deployment.yaml b/deploy/k8s/archived/helm/marketing-api/templates/deployment.yaml deleted file mode 100644 index 60d4cd1a3..000000000 --- a/deploy/k8s/archived/helm/marketing-api/templates/deployment.yaml +++ /dev/null @@ -1,96 +0,0 @@ -{{- $name := include "marketing-api.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "marketing-api.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "marketing-api.name" . }} - chart: {{ template "marketing-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "marketing-api.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "marketing-api.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/marketing-api/templates/service.yaml b/deploy/k8s/archived/helm/marketing-api/templates/service.yaml deleted file mode 100644 index 0e9bfbea2..000000000 --- a/deploy/k8s/archived/helm/marketing-api/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.marketing }} - labels: - app: {{ template "marketing-api.name" . }} - chart: {{ template "marketing-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "marketing-api.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/marketing-api/values.yaml b/deploy/k8s/archived/helm/marketing-api/values.yaml deleted file mode 100644 index 00bebf27f..000000000 --- a/deploy/k8s/archived/helm/marketing-api/values.yaml +++ /dev/null @@ -1,70 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /marketing-api - -image: - repository: eshop/marketing.api - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: false - annotations: {} - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: EventBusConnection - key: all__EventBusConnection - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - - name: UseLoadTest - key: all_EnableLoadTest - - name: IdentityUrl - key: internalurls__IdentityUrl - - name: IdentityUrlExternal - key: urls__IdentityUrl - - name: ConnectionString - key: marketing__ConnectionString - - name: MongoConnectionString - key: marketing__MongoConnectionString - - name: MongoDatabase - key: marketing__MongoDatabase - - name: PicBaseUrl - key: marketing__PicBaseUrl - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/templates/NOTES.txt b/deploy/k8s/archived/helm/mobileshoppingagg/templates/NOTES.txt index 61971f717..e7e5081ea 100644 --- a/deploy/k8s/archived/helm/mobileshoppingagg/templates/NOTES.txt +++ b/deploy/k8s/archived/helm/mobileshoppingagg/templates/NOTES.txt @@ -1,4 +1,4 @@ -eShop Mobile Marketing Aggregator is installed +eShop Mobile Shopping Aggregator is installed ---------------------------------------------- This API is not directly exposed outside cluster. If need to access it use: diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/templates/configmap.yaml b/deploy/k8s/archived/helm/mobileshoppingagg/templates/configmap.yaml index 1ca69509f..6d3eeef4b 100644 --- a/deploy/k8s/archived/helm/mobileshoppingagg/templates/configmap.yaml +++ b/deploy/k8s/archived/helm/mobileshoppingagg/templates/configmap.yaml @@ -21,9 +21,7 @@ data: internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc - internalurls__marketing__hc: http://{{ .Values.app.svc.marketing }}/hc internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc - internalurls__location__hc: http://{{ .Values.app.svc.locations }}/hc internalurls__grpcBasket: "http://{{ .Values.app.svc.basket }}:{{ .Values.service.grpcPort }}" internalurls__grpcCatalog: "http://{{ .Values.app.svc.catalog }}:{{ .Values.service.grpcPort }}" internalurls__grpcOrdering: "http://{{ .Values.app.svc.ordering }}:{{ .Values.service.grpcPort }}" diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/values.yaml b/deploy/k8s/archived/helm/mobileshoppingagg/values.yaml index 844a59441..fc7ce7a38 100644 --- a/deploy/k8s/archived/helm/mobileshoppingagg/values.yaml +++ b/deploy/k8s/archived/helm/mobileshoppingagg/values.yaml @@ -49,12 +49,8 @@ env: key: internalurls__identity__hc - name: OrderingUrlHC key: internalurls__ordering__hc - - name: MarketingUrlHC - key: internalurls__marketing__hc - name: PaymentUrlHC key: internalurls__payment__hc - - name: LocationUrlHC - key: internalurls__location__hc - name: urls__grpcBasket key: internalurls__grpcBasket - name: urls__grpcCatalog diff --git a/deploy/k8s/archived/helm/webmvc/templates/configmap.yaml b/deploy/k8s/archived/helm/webmvc/templates/configmap.yaml index 2aa06fc7f..89b9faae0 100644 --- a/deploy/k8s/archived/helm/webmvc/templates/configmap.yaml +++ b/deploy/k8s/archived/helm/webmvc/templates/configmap.yaml @@ -19,7 +19,6 @@ data: all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" webmvc__keystore: {{ .Values.inf.redis.keystore.constr }} 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: {{ $protocol }}://{{ $webshoppingapigw }} urls__mvc: {{ $protocol }}://{{ $mvc }} diff --git a/deploy/k8s/archived/helm/webmvc/values.yaml b/deploy/k8s/archived/helm/webmvc/values.yaml index 973f187f5..5db29dd01 100644 --- a/deploy/k8s/archived/helm/webmvc/values.yaml +++ b/deploy/k8s/archived/helm/webmvc/values.yaml @@ -44,8 +44,6 @@ env: key: urls__mvc - name: IdentityUrl key: urls__IdentityUrl - - name: MarketingUrl - key: internalurls__apigwwm - name: IdentityUrlHC key: internalurls__identity__hc - name: SignalrHubUrl diff --git a/deploy/k8s/archived/helm/webshoppingagg/templates/configmap.yaml b/deploy/k8s/archived/helm/webshoppingagg/templates/configmap.yaml index d01de8dcd..b1b07ffee 100644 --- a/deploy/k8s/archived/helm/webshoppingagg/templates/configmap.yaml +++ b/deploy/k8s/archived/helm/webshoppingagg/templates/configmap.yaml @@ -21,9 +21,7 @@ data: internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc - internalurls__marketing__hc: http://{{ .Values.app.svc.marketing }}/hc internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc - internalurls__location__hc: http://{{ .Values.app.svc.locations }}/hc internalurls__grpcBasket: "http://{{ .Values.app.svc.basket }}:{{ .Values.service.grpcPort }}" internalurls__grpcCatalog: "http://{{ .Values.app.svc.catalog }}:{{ .Values.service.grpcPort }}" internalurls__grpcOrdering: "http://{{ .Values.app.svc.ordering }}:{{ .Values.service.grpcPort }}" diff --git a/deploy/k8s/archived/helm/webshoppingagg/values.yaml b/deploy/k8s/archived/helm/webshoppingagg/values.yaml index 15501c727..602dcf93a 100644 --- a/deploy/k8s/archived/helm/webshoppingagg/values.yaml +++ b/deploy/k8s/archived/helm/webshoppingagg/values.yaml @@ -49,12 +49,8 @@ env: key: internalurls__identity__hc - name: OrderingUrlHC key: internalurls__ordering__hc - - name: MarketingUrlHC - key: internalurls__marketing__hc - name: PaymentUrlHC key: internalurls__payment__hc - - name: LocationUrlHC - key: internalurls__location__hc - name: urls__grpcBasket key: internalurls__grpcBasket - name: urls__grpcCatalog diff --git a/deploy/k8s/archived/helm/webspa/templates/configmap.yaml b/deploy/k8s/archived/helm/webspa/templates/configmap.yaml index ecdbf8b63..353ff638f 100644 --- a/deploy/k8s/archived/helm/webspa/templates/configmap.yaml +++ b/deploy/k8s/archived/helm/webspa/templates/configmap.yaml @@ -1,7 +1,6 @@ {{- $name := include "webspa.fullname" . -}} {{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} {{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}} -{{- $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" . -}} @@ -23,5 +22,4 @@ data: internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc urls__apigwws: {{ $protocol }}://{{ $webshoppingapigw }} urls__spa: {{ $protocol }}://{{ $spa }} - urls__IdentityUrl: {{ $protocol }}://{{ $identity }} - urls__apigwwm: {{ $protocol }}://{{ $webmarketingapigw }} \ No newline at end of file + urls__IdentityUrl: {{ $protocol }}://{{ $identity }} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webspa/values.yaml b/deploy/k8s/archived/helm/webspa/values.yaml index e1547ed39..4a7eea52b 100644 --- a/deploy/k8s/archived/helm/webspa/values.yaml +++ b/deploy/k8s/archived/helm/webspa/values.yaml @@ -42,8 +42,6 @@ env: key: urls__spa - name: IdentityUrl key: urls__IdentityUrl - - name: MarketingUrl - key: urls__apigwwm - name: IdentityUrlHC key: internalurls__identity__hc - name: SignalrHubUrl diff --git a/deploy/k8s/archived/helm/webstatus/templates/configmap.yaml b/deploy/k8s/archived/helm/webstatus/templates/configmap.yaml index bf40d2a7d..b53864602 100644 --- a/deploy/k8s/archived/helm/webstatus/templates/configmap.yaml +++ b/deploy/k8s/archived/helm/webstatus/templates/configmap.yaml @@ -24,12 +24,8 @@ data: internalurls__spa__hc: http://{{ .Values.app.svc.spa }}/hc name__apigwws__hc: Web Shopping API GW HTTP Check internalurls__apigwws__hc: http://{{ .Values.app.svc.webshoppingapigw }}:8001/ready - name__apigwwm__hc: Web Marketing API GW HTTP Check - internalurls__apigwwm__hc: http://{{ .Values.app.svc.webmarketingapigw }}:8001/ready name__apigwms__hc: Mobile Shopping API GW HTTP Check internalurls__apigwms__hc: http://{{ .Values.app.svc.mobileshoppingapigw }}:8001/ready - name__apigwmm__hc: Mobile Marketing API GW HTTP Check - internalurls__apigwmm__hc: http://{{ .Values.app.svc.mobilemarketingapigw }}:8001/ready name__apigwwsagg__hc: Web Shopping Aggregator GW HTTP Check internalurls__apigwwsagg__hc: http://{{ .Values.app.svc.webshoppingagg }}/hc name__apigwmsagg__hc: Mobile Shopping Aggregator HTTP Check @@ -44,10 +40,6 @@ data: internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc name__identity__hc: Identity HTTP Check internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc - name__marketing__hc: Marketing HTTP Check - internalurls__marketing__hc: http://{{ .Values.app.svc.marketing }}/hc - name__locations__hc: Locations HTTP Check - internalurls__locations__hc: http://{{ .Values.app.svc.locations }}/hc name__payment__hc: Payment HTTP Check internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc name__signalrhub__hc: Ordering SignalR Hub HTTP Check diff --git a/deploy/k8s/archived/helm/webstatus/values.yaml b/deploy/k8s/archived/helm/webstatus/values.yaml index e5a23ec85..1ce23fec3 100644 --- a/deploy/k8s/archived/helm/webstatus/values.yaml +++ b/deploy/k8s/archived/helm/webstatus/values.yaml @@ -67,24 +67,16 @@ env: - name: HealthChecks-UI__HealthChecks__7__Uri key: internalurls__identity__hc - name: HealthChecks-UI__HealthChecks__8__Name - key: name__marketing__hc - - name: HealthChecks-UI__HealthChecks__8__Uri - key: internalurls__marketing__hc - - name: HealthChecks-UI__HealthChecks__9__Name - key: name__locations__hc - - name: HealthChecks-UI__HealthChecks__9__Uri - key: internalurls__locations__hc - - name: HealthChecks-UI__HealthChecks__10__Name key: name__payment__hc - - name: HealthChecks-UI__HealthChecks__10__Uri + - name: HealthChecks-UI__HealthChecks__8__Uri key: internalurls__payment__hc - - name: HealthChecks-UI__HealthChecks__11__Name + - name: HealthChecks-UI__HealthChecks__9__Name key: name__signalrhub__hc - - name: HealthChecks-UI__HealthChecks__11__Uri + - name: HealthChecks-UI__HealthChecks__9__Uri key: internalurls__signalrhub__hc - - name: HealthChecks-UI__HealthChecks__12__Name + - name: HealthChecks-UI__HealthChecks__10__Name key: name__orderingbackground__hc - - name: HealthChecks-UI__HealthChecks__12__Uri + - name: HealthChecks-UI__HealthChecks__10__Uri 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) diff --git a/deploy/k8s/helm/app.yaml b/deploy/k8s/helm/app.yaml index e83ea2823..acea31ef1 100644 --- a/deploy/k8s/helm/app.yaml +++ b/deploy/k8s/helm/app.yaml @@ -13,14 +13,10 @@ app: # app global settings spa: "" # ingress entry for web spa status: webstatus # ingress entry for web status webshoppingapigw: webshoppingapigw # ingress entry for web shopping Agw - webmarketingapigw: webmarketingapigw # ingress entry for web mkg Agw - mobilemarketingapigw: mobilemarketingapigw # ingress entry for mobile mkg Agw mobileshoppingapigw: mobileshoppingapigw # ingress entry for mobile shopping Agw webshoppingagg: webshoppingagg # ingress entry for web shopping aggregator mobileshoppingagg: mobileshoppingagg # ingress entry for mobile shopping aggregator payment: payment-api # ingress entry for payment api - locations: locations-api # ingress entry for locations api - marketing: marketing-api # ingress entry for marketing api webhooks: webhooks-api # ingress entry for webhooks api webhooksweb: webhooks-web # ingress entry for webhooks web demo client svc: @@ -34,13 +30,9 @@ app: # app global settings spa: webspa # service name for web spa status: webstatus # service name for web status webshoppingapigw: webshoppingapigw # service name for web shopping Agw - webmarketingapigw: webmarketingapigw # service name for web mkg Agw - mobilemarketingapigw: mobilemarketingapigw # service name for mobile mkg Agw mobileshoppingapigw: mobileshoppingapigw # service name for mobile shopping Agw webshoppingagg: webshoppingagg # service name for web shopping aggregator mobileshoppingagg: mobileshoppingagg # service name for mobile shopping aggregator payment: payment-api # service name for payment api - locations: locations-api # service name for locations api - marketing: marketing-api # service name for marketing ap webhooks: webhooks-api # service name for webhooks api webhooksweb: webhooks-client # service name for webhooks web diff --git a/deploy/k8s/helm/deploy-all-mac.ps1 b/deploy/k8s/helm/deploy-all-mac.ps1 index c74b7e05e..3de7dc6c6 100644 --- a/deploy/k8s/helm/deploy-all-mac.ps1 +++ b/deploy/k8s/helm/deploy-all-mac.ps1 @@ -120,8 +120,8 @@ if (-not [string]::IsNullOrEmpty($registry)) { Write-Host "Begin eShopOnContainers installation using Helm" -ForegroundColor Green $infras = ("sql-data", "nosql-data", "rabbitmq", "keystore-data", "basket-data") -$charts = ("eshop-common", "basket-api","catalog-api", "identity-api", "locations-api", "marketing-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web") -$gateways = ("apigwmm", "apigwms", "apigwwm", "apigwws") +$charts = ("eshop-common", "basket-api","catalog-api", "identity-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web") +$gateways = ("apigwms", "apigwws") if ($deployInfrastructure) { foreach ($infra in $infras) { diff --git a/deploy/k8s/helm/deploy-all.ps1 b/deploy/k8s/helm/deploy-all.ps1 index da0424195..213e60fb7 100644 --- a/deploy/k8s/helm/deploy-all.ps1 +++ b/deploy/k8s/helm/deploy-all.ps1 @@ -119,8 +119,8 @@ if (-not [string]::IsNullOrEmpty($registry)) { Write-Host "Begin eShopOnContainers installation using Helm" -ForegroundColor Green $infras = ("sql-data", "nosql-data", "rabbitmq", "keystore-data", "basket-data") -$charts = ("eshop-common", "basket-api","catalog-api", "identity-api", "locations-api", "marketing-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web") -$gateways = ("apigwmm", "apigwms", "apigwwm", "apigwws") +$charts = ("eshop-common", "basket-api","catalog-api", "identity-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web") +$gateways = ("apigwms", "apigwws") if ($deployInfrastructure) { foreach ($infra in $infras) { diff --git a/deploy/k8s/helm/deploy-all.sh b/deploy/k8s/helm/deploy-all.sh index bf07105ef..4b4c8eafd 100644 --- a/deploy/k8s/helm/deploy-all.sh +++ b/deploy/k8s/helm/deploy-all.sh @@ -142,7 +142,7 @@ fi if [[ $push_images ]]; then echo "#################### Pushing images to the container registry ####################" - services=(basket.api catalog.api identity.api ordering.api marketing.api payment.api locations.api webmvc webspa webstatus) + services=(basket.api catalog.api identity.api ordering.api payment.api webmvc webspa webstatus) if [[ -z "$(docker image ls -q --filter=reference=eshop/$service:$image_tag)" ]]; then image_tag=linux-$image_tag @@ -209,7 +209,7 @@ fi echo "#################### Begin $app_name installation using Helm ####################" infras=(sql-data nosql-data rabbitmq keystore-data basket-data) -charts=(eshop-common apigwmm apigwms apigwwm apigwws basket-api catalog-api identity-api locations-api marketing-api mobileshoppingagg ordering-api ordering-backgroundtasks ordering-signalrhub payment-api webmvc webshoppingagg webspa webstatus webhooks-api webhooks-web) +charts=(eshop-common apigwms apigwws basket-api catalog-api identity-api mobileshoppingagg ordering-api ordering-backgroundtasks ordering-signalrhub payment-api webmvc webshoppingagg webspa webstatus webhooks-api webhooks-web) if [[ !$skip_infrastructure ]]; then for infra in "${infras[@]}" diff --git a/deploy/k8s/helm/identity-api/templates/configmap.yaml b/deploy/k8s/helm/identity-api/templates/configmap.yaml index 264ceb745..7c670f646 100644 --- a/deploy/k8s/helm/identity-api/templates/configmap.yaml +++ b/deploy/k8s/helm/identity-api/templates/configmap.yaml @@ -2,8 +2,6 @@ {{- $sqlsrv := include "sql-name" . -}} {{- $mvc_url := include "url-of" (list .Values.app.ingress.entries.mvc .) -}} {{- $spa_url := include "url-of" (list .Values.app.ingress.entries.spa .) -}} -{{- $locations_url := include "url-of" (list .Values.app.ingress.entries.locations .) -}} -{{- $marketing_url := include "url-of" (list .Values.app.ingress.entries.marketing .) -}} {{- $basket_url := include "url-of" (list .Values.app.ingress.entries.basket .) -}} {{- $ordering_url := include "url-of" (list .Values.app.ingress.entries.ordering .) -}} {{- $mobileshoppingagg := include "url-of" (list .Values.app.ingress.entries.mobileshoppingagg .) -}} @@ -27,8 +25,6 @@ data: all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" mvc_e: http://{{ $mvc_url }} spa_e: http://{{ $spa_url }} - locations_e: http://{{ $locations_url }} - marketing_e: http://{{ $marketing_url }} basket_e: http://{{ $basket_url }} ordering_e: http://{{ $ordering_url }} mobileshoppingagg_e: http://{{ $mobileshoppingagg }} diff --git a/deploy/k8s/helm/identity-api/values.yaml b/deploy/k8s/helm/identity-api/values.yaml index 7b57dfde1..92fd57283 100644 --- a/deploy/k8s/helm/identity-api/values.yaml +++ b/deploy/k8s/helm/identity-api/values.yaml @@ -40,10 +40,6 @@ env: key: mvc_e - name: SpaClient key: spa_e - - name: LocationApiClient - key: locations_e - - name: MarketingApiClient - key: marketing_e - name: BasketApiClient key: basket_e - name: OrderingApiClient diff --git a/deploy/k8s/helm/inf.yaml b/deploy/k8s/helm/inf.yaml index 938be3d45..e73b37ee8 100644 --- a/deploy/k8s/helm/inf.yaml +++ b/deploy/k8s/helm/inf.yaml @@ -19,16 +19,8 @@ inf: db: OrderingDb # Ordering API SQL db name identity: db: IdentityDb # Ordering API SQL db name - marketing: - db: MarketingDb # Marketing API SQL db name webhooks: db: WebhooksDb # Webhooks DB - mongo: -# host: my-nosql-data # Uncomment to use specify custom mongo host. By default nosql-data is used - locations: - database: LocationsDb - marketing: - database: MarketingDb redis: # inf.redis defines the redis' connection strings basket: svc: basket-data # Name of k8s svc for basket redis diff --git a/deploy/k8s/helm/mobileshoppingagg/templates/NOTES.txt b/deploy/k8s/helm/mobileshoppingagg/templates/NOTES.txt index 61971f717..e7e5081ea 100644 --- a/deploy/k8s/helm/mobileshoppingagg/templates/NOTES.txt +++ b/deploy/k8s/helm/mobileshoppingagg/templates/NOTES.txt @@ -1,4 +1,4 @@ -eShop Mobile Marketing Aggregator is installed +eShop Mobile Shopping Aggregator is installed ---------------------------------------------- This API is not directly exposed outside cluster. If need to access it use: diff --git a/deploy/k8s/helm/mobileshoppingagg/templates/configmap.yaml b/deploy/k8s/helm/mobileshoppingagg/templates/configmap.yaml index 1ca69509f..6d3eeef4b 100644 --- a/deploy/k8s/helm/mobileshoppingagg/templates/configmap.yaml +++ b/deploy/k8s/helm/mobileshoppingagg/templates/configmap.yaml @@ -21,9 +21,7 @@ data: internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc - internalurls__marketing__hc: http://{{ .Values.app.svc.marketing }}/hc internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc - internalurls__location__hc: http://{{ .Values.app.svc.locations }}/hc internalurls__grpcBasket: "http://{{ .Values.app.svc.basket }}:{{ .Values.service.grpcPort }}" internalurls__grpcCatalog: "http://{{ .Values.app.svc.catalog }}:{{ .Values.service.grpcPort }}" internalurls__grpcOrdering: "http://{{ .Values.app.svc.ordering }}:{{ .Values.service.grpcPort }}" diff --git a/deploy/k8s/helm/mobileshoppingagg/values.yaml b/deploy/k8s/helm/mobileshoppingagg/values.yaml index 844a59441..fc7ce7a38 100644 --- a/deploy/k8s/helm/mobileshoppingagg/values.yaml +++ b/deploy/k8s/helm/mobileshoppingagg/values.yaml @@ -49,12 +49,8 @@ env: key: internalurls__identity__hc - name: OrderingUrlHC key: internalurls__ordering__hc - - name: MarketingUrlHC - key: internalurls__marketing__hc - name: PaymentUrlHC key: internalurls__payment__hc - - name: LocationUrlHC - key: internalurls__location__hc - name: urls__grpcBasket key: internalurls__grpcBasket - name: urls__grpcCatalog diff --git a/deploy/k8s/helm/webmvc/templates/configmap.yaml b/deploy/k8s/helm/webmvc/templates/configmap.yaml index 2aa06fc7f..89b9faae0 100644 --- a/deploy/k8s/helm/webmvc/templates/configmap.yaml +++ b/deploy/k8s/helm/webmvc/templates/configmap.yaml @@ -19,7 +19,6 @@ data: all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" webmvc__keystore: {{ .Values.inf.redis.keystore.constr }} 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: {{ $protocol }}://{{ $webshoppingapigw }} urls__mvc: {{ $protocol }}://{{ $mvc }} diff --git a/deploy/k8s/helm/webmvc/values.yaml b/deploy/k8s/helm/webmvc/values.yaml index 973f187f5..5db29dd01 100644 --- a/deploy/k8s/helm/webmvc/values.yaml +++ b/deploy/k8s/helm/webmvc/values.yaml @@ -44,8 +44,6 @@ env: key: urls__mvc - name: IdentityUrl key: urls__IdentityUrl - - name: MarketingUrl - key: internalurls__apigwwm - name: IdentityUrlHC key: internalurls__identity__hc - name: SignalrHubUrl diff --git a/deploy/k8s/helm/webshoppingagg/templates/configmap.yaml b/deploy/k8s/helm/webshoppingagg/templates/configmap.yaml index d01de8dcd..b1b07ffee 100644 --- a/deploy/k8s/helm/webshoppingagg/templates/configmap.yaml +++ b/deploy/k8s/helm/webshoppingagg/templates/configmap.yaml @@ -21,9 +21,7 @@ data: internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc - internalurls__marketing__hc: http://{{ .Values.app.svc.marketing }}/hc internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc - internalurls__location__hc: http://{{ .Values.app.svc.locations }}/hc internalurls__grpcBasket: "http://{{ .Values.app.svc.basket }}:{{ .Values.service.grpcPort }}" internalurls__grpcCatalog: "http://{{ .Values.app.svc.catalog }}:{{ .Values.service.grpcPort }}" internalurls__grpcOrdering: "http://{{ .Values.app.svc.ordering }}:{{ .Values.service.grpcPort }}" diff --git a/deploy/k8s/helm/webshoppingagg/values.yaml b/deploy/k8s/helm/webshoppingagg/values.yaml index 15501c727..602dcf93a 100644 --- a/deploy/k8s/helm/webshoppingagg/values.yaml +++ b/deploy/k8s/helm/webshoppingagg/values.yaml @@ -49,12 +49,8 @@ env: key: internalurls__identity__hc - name: OrderingUrlHC key: internalurls__ordering__hc - - name: MarketingUrlHC - key: internalurls__marketing__hc - name: PaymentUrlHC key: internalurls__payment__hc - - name: LocationUrlHC - key: internalurls__location__hc - name: urls__grpcBasket key: internalurls__grpcBasket - name: urls__grpcCatalog diff --git a/deploy/k8s/helm/webspa/templates/configmap.yaml b/deploy/k8s/helm/webspa/templates/configmap.yaml index ecdbf8b63..353ff638f 100644 --- a/deploy/k8s/helm/webspa/templates/configmap.yaml +++ b/deploy/k8s/helm/webspa/templates/configmap.yaml @@ -1,7 +1,6 @@ {{- $name := include "webspa.fullname" . -}} {{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} {{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}} -{{- $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" . -}} @@ -23,5 +22,4 @@ data: internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc urls__apigwws: {{ $protocol }}://{{ $webshoppingapigw }} urls__spa: {{ $protocol }}://{{ $spa }} - urls__IdentityUrl: {{ $protocol }}://{{ $identity }} - urls__apigwwm: {{ $protocol }}://{{ $webmarketingapigw }} \ No newline at end of file + urls__IdentityUrl: {{ $protocol }}://{{ $identity }} \ No newline at end of file diff --git a/deploy/k8s/helm/webspa/values.yaml b/deploy/k8s/helm/webspa/values.yaml index e1547ed39..4a7eea52b 100644 --- a/deploy/k8s/helm/webspa/values.yaml +++ b/deploy/k8s/helm/webspa/values.yaml @@ -42,8 +42,6 @@ env: key: urls__spa - name: IdentityUrl key: urls__IdentityUrl - - name: MarketingUrl - key: urls__apigwwm - name: IdentityUrlHC key: internalurls__identity__hc - name: SignalrHubUrl diff --git a/deploy/k8s/helm/webstatus/templates/configmap.yaml b/deploy/k8s/helm/webstatus/templates/configmap.yaml index bf40d2a7d..b53864602 100644 --- a/deploy/k8s/helm/webstatus/templates/configmap.yaml +++ b/deploy/k8s/helm/webstatus/templates/configmap.yaml @@ -24,12 +24,8 @@ data: internalurls__spa__hc: http://{{ .Values.app.svc.spa }}/hc name__apigwws__hc: Web Shopping API GW HTTP Check internalurls__apigwws__hc: http://{{ .Values.app.svc.webshoppingapigw }}:8001/ready - name__apigwwm__hc: Web Marketing API GW HTTP Check - internalurls__apigwwm__hc: http://{{ .Values.app.svc.webmarketingapigw }}:8001/ready name__apigwms__hc: Mobile Shopping API GW HTTP Check internalurls__apigwms__hc: http://{{ .Values.app.svc.mobileshoppingapigw }}:8001/ready - name__apigwmm__hc: Mobile Marketing API GW HTTP Check - internalurls__apigwmm__hc: http://{{ .Values.app.svc.mobilemarketingapigw }}:8001/ready name__apigwwsagg__hc: Web Shopping Aggregator GW HTTP Check internalurls__apigwwsagg__hc: http://{{ .Values.app.svc.webshoppingagg }}/hc name__apigwmsagg__hc: Mobile Shopping Aggregator HTTP Check @@ -44,10 +40,6 @@ data: internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc name__identity__hc: Identity HTTP Check internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc - name__marketing__hc: Marketing HTTP Check - internalurls__marketing__hc: http://{{ .Values.app.svc.marketing }}/hc - name__locations__hc: Locations HTTP Check - internalurls__locations__hc: http://{{ .Values.app.svc.locations }}/hc name__payment__hc: Payment HTTP Check internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc name__signalrhub__hc: Ordering SignalR Hub HTTP Check diff --git a/deploy/k8s/helm/webstatus/values.yaml b/deploy/k8s/helm/webstatus/values.yaml index e5a23ec85..1ce23fec3 100644 --- a/deploy/k8s/helm/webstatus/values.yaml +++ b/deploy/k8s/helm/webstatus/values.yaml @@ -67,24 +67,16 @@ env: - name: HealthChecks-UI__HealthChecks__7__Uri key: internalurls__identity__hc - name: HealthChecks-UI__HealthChecks__8__Name - key: name__marketing__hc - - name: HealthChecks-UI__HealthChecks__8__Uri - key: internalurls__marketing__hc - - name: HealthChecks-UI__HealthChecks__9__Name - key: name__locations__hc - - name: HealthChecks-UI__HealthChecks__9__Uri - key: internalurls__locations__hc - - name: HealthChecks-UI__HealthChecks__10__Name key: name__payment__hc - - name: HealthChecks-UI__HealthChecks__10__Uri + - name: HealthChecks-UI__HealthChecks__8__Uri key: internalurls__payment__hc - - name: HealthChecks-UI__HealthChecks__11__Name + - name: HealthChecks-UI__HealthChecks__9__Name key: name__signalrhub__hc - - name: HealthChecks-UI__HealthChecks__11__Uri + - name: HealthChecks-UI__HealthChecks__9__Uri key: internalurls__signalrhub__hc - - name: HealthChecks-UI__HealthChecks__12__Name + - name: HealthChecks-UI__HealthChecks__10__Name key: name__orderingbackground__hc - - name: HealthChecks-UI__HealthChecks__12__Uri + - name: HealthChecks-UI__HealthChecks__10__Uri 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) diff --git a/obsolete/readme/README.ENV.md b/obsolete/readme/README.ENV.md index bdb436a1a..037a01ebc 100644 --- a/obsolete/readme/README.ENV.md +++ b/obsolete/readme/README.ENV.md @@ -16,39 +16,35 @@ To enable the service bus of Azure in eShop solution it is necessary having crea For example: >ESHOP_AZURE_SERVICE_BUS=Endpoint=sb://yourservicebusservice.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=yourtopicpolicykey=;EntityPath=eshop_event_bus -Once the service bus service is created, it is necessary to set to true the "AzureServiceBusEnabled" environment variable from `settings.json` file on Catalog.API, Ordering.API, Basket.API, Payment.API, GracePeriodManager, Marketing.API and Locations.API. +Once the service bus service is created, it is necessary to set to true the "AzureServiceBusEnabled" environment variable from `settings.json` file on Catalog.API, Ordering.API, Basket.API, Payment.API and GracePeriodManager. With the steps explained in the next section, you will be able to run the application with Azure Storage Account instead of the local container storage. # Azure Storage Account service -To enable Azure storage of Azure in eShopOnAzure solution it is necessary having created previously the storage service through ARM file or manually through Azure portal. You can use the ARM files find under **deploy/az/storage** folder already created in eShop. Once the storage account is created, it is very important to create a new container(blob kind) and upload the solution catalog pics files before to continue.Later, it is necessary to set to true the "AzureStorageEnabled" environment variable from `settings.json` in Catalog.API and Marketing.API.Finally, it is necessary to get the container endpoint url from information service in the Azure portal, This url must be declared on .env file located in the solution root folder with `ESHOP_AZURE_STORAGE_CATALOG` for the Catalog.API content and `ESHOP_AZURE_STORAGE_MARKETING` for the Marketing.API content. +To enable Azure storage of Azure in eShopOnAzure solution it is necessary having created previously the storage service through ARM file or manually through Azure portal. You can use the ARM files find under **deploy/az/storage** folder already created in eShop. Once the storage account is created, it is very important to create a new container(blob kind) and upload the solution catalog pics files before to continue.Later, it is necessary to set to true the "AzureStorageEnabled" environment variable from `settings.json` in Catalog.API.Finally, it is necessary to get the container endpoint url from information service in the Azure portal, This url must be declared on .env file located in the solution root folder with `ESHOP_AZURE_STORAGE_CATALOG` for the Catalog.API content. Do not forget to put a slash character '/' in the end of the url. For example: >ESHOP_AZURE_STORAGE_CATALOG=https://yourcatalogstorageaccountservice.blob.core.windows.net/yourcontainername/ ->ESHOP_AZURE_STORAGE_MARKETING=https://yourmarketingstorageaccountservice.blob.core.windows.net/yourcontainername/ ## Check status of Azure Storage Account with Health Checks -It is possible to add status check for the Azure Storage Account inside the Catalog Web Status. In case that the status check is enabled, for the Catalog and/or Marketing section in the WebStatus page, Azure Storage will be checked as one of the dependencies for theses APIs. To enable this check add the account name and key to the .env file for your account. +It is possible to add status check for the Azure Storage Account inside the Catalog Web Status. In case that the status check is enabled, for the Catalog section in the WebStatus page, Azure Storage will be checked as one of the dependencies for theses APIs. To enable this check add the account name and key to the .env file for your account. For example: >ESHOP_AZURE_STORAGE_CATALOG_NAME=storageaccountname >ESHOP_AZURE_STORAGE_CATALOG_KEY=storageaccountkey ->ESHOP_AZURE_STORAGE_MARKETING_NAME=storageaccountname ->ESHOP_AZURE_STORAGE_MARKETING_KEY=storageaccountkey With the steps explained in the next section, you will be able to run the application with Azure SQL Database instead of local storage. # Azure SQL Database -To enable Azure SQL Database in eShop is required to have a Azure SQL with the databases for Ordering.API, Identity.API, Catalaog.API and Marketing.API. You can use the [ARM files](deploy/az/sql/readme.md) already created in this project or do it manually. Once the databases are created, it is necessary to get the connection string for each service and set the corresponding variable in the .env file. +To enable Azure SQL Database in eShop is required to have a Azure SQL with the databases for Ordering.API, Identity.API, Catalaog.API. You can use the [ARM files](deploy/az/sql/readme.md) already created in this project or do it manually. Once the databases are created, it is necessary to get the connection string for each service and set the corresponding variable in the .env file. For example: >ESHOP_AZURE_CATALOG_DB=catalogazureconnectionstring >ESHOP_AZURE_IDENTITY_DB=identityazureconnectionstring >ESHOP_AZURE_ORDERING_DB=orderingazureconnectionstring ->ESHOP_AZURE_MARKETING_DB=marketingazureconnectionstring With the steps explained in the next section, you will be able to run the application with Azure Cosmos DB Database instead of local storage. @@ -61,7 +57,5 @@ For example: # Azure Functions To enable the Azure Functions in eShop you can add the URI where the functions have been deployed. You can use the ARM files under **deploy/az/azurefunctions** to create the resources in Azure. Once created and available, it is necessary to add to the .env file the `ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI` variable. -For example: - >ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI=https://marketing-functions.azurewebsites.net/api/MarketingDetailsHttpTrigger?code=AzureFunctioncode See Azure Functions deployment Files and Readme for more details [ARM files](deploy/az/azurefunctions/readme.md) \ No newline at end of file diff --git a/obsolete/readme/readme-docker-compose.md b/obsolete/readme/readme-docker-compose.md index 882630682..c9f48b52c 100644 --- a/obsolete/readme/readme-docker-compose.md +++ b/obsolete/readme/readme-docker-compose.md @@ -27,7 +27,6 @@ When using this file the following environments variables must be set: * `ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP` with the IP or DNS name of the docker host that runs the services (can use `localhost` if needed). * `ESHOP_AZURE_STORAGE_CATALOG` with the URL of the Azure Storage that will host the catalog images -* `ESHOP_AZURE_STORAGE_MARKETING` with the URL of the Azure Storage that will host the marketing campaign images You might wonder why an external image resource (storage) is needed when using `docker-compose.prod.yml` instead of `docker-compose.override.yml`. Answer to this is related to a limitation of Docker Compose file format. This is how we set the environment configuration of Catalog microservice in `docker-compose.override.yml`: diff --git a/src/.dockerignore b/src/.dockerignore index 2cec0e7b0..dc9d4af2c 100644 --- a/src/.dockerignore +++ b/src/.dockerignore @@ -20,5 +20,4 @@ Web/WebSPA/wwwroot/ packages/ test-results/ TestResults/ -Mobile/ -Services/Marketing/Infrastructure/ \ No newline at end of file +Mobile/ \ No newline at end of file diff --git a/src/.env b/src/.env index 96b801650..d65bdbbf6 100644 --- a/src/.env +++ b/src/.env @@ -7,21 +7,17 @@ # Use this values to run the app locally in Windows ESHOP_EXTERNAL_DNS_NAME_OR_IP=host.docker.internal ESHOP_STORAGE_CATALOG_URL=http://host.docker.internal:5202/c/api/v1/catalog/items/[0]/pic/ -ESHOP_STORAGE_MARKETING_URL=http://host.docker.internal:5110/api/v1/campaigns/[0]/pic/ # Use this values to run the app locally in Mac # ESHOP_EXTERNAL_DNS_NAME_OR_IP=docker.for.mac.localhost # ESHOP_STORAGE_CATALOG_URL=http://docker.for.mac.localhost:5202/c/api/v1/catalog/items/[0]/pic/ -# ESHOP_STORAGE_MARKETING_URL=http://docker.for.mac.localhost:5110/api/v1/campaigns/[0]/pic/ # Use this values to run the app locally in Linux # ESHOP_EXTERNAL_DNS_NAME_OR_IP=docker.for.linux.localhost # ESHOP_STORAGE_CATALOG_URL=http://docker.for.linux.localhost:5202/c/api/v1/catalog/items/[0]/pic/ -# ESHOP_STORAGE_MARKETING_URL=http://docker.for.linux.localhost:5110/api/v1/campaigns/[0]/pic/ # Configure this values to the cloud storage locations # ESHOP_STORAGE_CATALOG_URL= -# ESHOP_STORAGE_MARKETING_URL= ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.162 @@ -31,12 +27,9 @@ ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.162 #ESHOP_AZURE_CATALOG_DB= #ESHOP_AZURE_IDENTITY_DB= #ESHOP_AZURE_ORDERING_DB= -#ESHOP_AZURE_MARKETING_DB= #ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI= #ESHOP_AZURE_STORAGE_CATALOG_NAME= #ESHOP_AZURE_STORAGE_CATALOG_KEY= -#ESHOP_AZURE_STORAGE_MARKETING_NAME= -#ESHOP_AZURE_STORAGE_MARKETING_KEY= #ESHOP_SERVICE_BUS_USERNAME= #ESHOP_SERVICE_BUS_PASSWORD= #INSTRUMENTATION_KEY= diff --git a/src/DockerfileSolutionRestore.txt b/src/DockerfileSolutionRestore.txt index 006f664d87e72d6ca8af9e919471f54cbb415ce1..040bf761ec79bfb95f559c13baa31f518c2a399f 100644 GIT binary patch delta 40 tcmez4HpOlOkKp8cq9Kz7B&{aT5H*;5k4tItJFylpf0dZrW&?2_9soq74wC=? delta 520 zcmbPY_s4AmkD#p&Lq07Lne@w$Dq%EE>g^($Kc2iz~G4~H~FHZA;l(0Prk>c zq>OGW7I#b*("MvcClient")); clientUrls.Add("Spa", configuration.GetValue("SpaClient")); clientUrls.Add("Xamarin", configuration.GetValue("XamarinCallback")); - clientUrls.Add("LocationsApi", configuration.GetValue("LocationApiClient")); - clientUrls.Add("MarketingApi", configuration.GetValue("MarketingApiClient")); clientUrls.Add("BasketApi", configuration.GetValue("BasketApiClient")); clientUrls.Add("OrderingApi", configuration.GetValue("OrderingApiClient")); clientUrls.Add("MobileShoppingAgg", configuration.GetValue("MobileShoppingAggClient")); diff --git a/src/Services/Location/Locations.API/Controllers/HomeController.cs b/src/Services/Location/Locations.API/Controllers/HomeController.cs deleted file mode 100644 index 15cb07404..000000000 --- a/src/Services/Location/Locations.API/Controllers/HomeController.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Controllers -{ - public class HomeController : Controller - { - // GET: // - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } - } -} diff --git a/src/Services/Location/Locations.API/Controllers/LocationsController.cs b/src/Services/Location/Locations.API/Controllers/LocationsController.cs deleted file mode 100644 index a9cbae1c2..000000000 --- a/src/Services/Location/Locations.API/Controllers/LocationsController.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services; -using Microsoft.eShopOnContainers.Services.Locations.API.Model; -using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; -using System; -using System.Collections.Generic; -using System.Net; -using System.Threading.Tasks; - -namespace Locations.API.Controllers -{ - [Route("api/v1/[controller]")] - [Authorize] - [ApiController] - public class LocationsController : ControllerBase - { - private readonly ILocationsService _locationsService; - private readonly IIdentityService _identityService; - - public LocationsController(ILocationsService locationsService, IIdentityService identityService) - { - _locationsService = locationsService ?? throw new ArgumentNullException(nameof(locationsService)); - _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); - } - - //GET api/v1/[controller]/user/1 - [Route("user/{userId:guid}")] - [HttpGet] - [ProducesResponseType(typeof(UserLocation), (int)HttpStatusCode.OK)] - public async Task> GetUserLocationAsync(Guid userId) - { - return await _locationsService.GetUserLocationAsync(userId.ToString()); - } - - //GET api/v1/[controller]/ - [Route("")] - [HttpGet] - [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] - public async Task>> GetAllLocationsAsync() - { - return await _locationsService.GetAllLocationAsync(); - } - - //GET api/v1/[controller]/1 - [Route("{locationId}")] - [HttpGet] - [ProducesResponseType(typeof(Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations), (int)HttpStatusCode.OK)] - public async Task> GetLocationAsync(int locationId) - { - return await _locationsService.GetLocationAsync(locationId); - } - - //POST api/v1/[controller]/ - [Route("")] - [HttpPost] - [ProducesResponseType((int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - public async Task CreateOrUpdateUserLocationAsync([FromBody]LocationRequest newLocReq) - { - var userId = _identityService.GetUserIdentity(); - var result = await _locationsService.AddOrUpdateUserLocationAsync(userId, newLocReq); - - if (!result) - { - return BadRequest(); - } - - return Ok(); - } - } -} diff --git a/src/Services/Location/Locations.API/Dockerfile b/src/Services/Location/Locations.API/Dockerfile deleted file mode 100644 index 0c5fabfe4..000000000 --- a/src/Services/Location/Locations.API/Dockerfile +++ /dev/null @@ -1,64 +0,0 @@ -FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base -WORKDIR /app -EXPOSE 80 - -FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build -WORKDIR /src - -# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles -# to take advantage of Docker's build cache, to speed up local container builds -COPY "eShopOnContainers-ServicesAndWebApps.sln" "eShopOnContainers-ServicesAndWebApps.sln" - -COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj" "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj" -COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" -COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" -COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" -COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" -COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" -COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" -COPY "BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj" "BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj" -COPY "Services/Basket/Basket.API/Basket.API.csproj" "Services/Basket/Basket.API/Basket.API.csproj" -COPY "Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj" "Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj" -COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" -COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" -COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" -COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" -COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" -COPY "Services/Location/Locations.API/Locations.API.csproj" "Services/Location/Locations.API/Locations.API.csproj" -COPY "Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj" "Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj" -COPY "Services/Marketing/Marketing.API/Marketing.API.csproj" "Services/Marketing/Marketing.API/Marketing.API.csproj" -COPY "Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj" "Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj" -COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" -COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" -COPY "Services/Ordering/Ordering.Domain/Ordering.Domain.csproj" "Services/Ordering/Ordering.Domain/Ordering.Domain.csproj" -COPY "Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj" "Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj" -COPY "Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj" "Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj" -COPY "Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj" "Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj" -COPY "Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj" "Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj" -COPY "Services/Payment/Payment.API/Payment.API.csproj" "Services/Payment/Payment.API/Payment.API.csproj" -COPY "Services/Webhooks/Webhooks.API/Webhooks.API.csproj" "Services/Webhooks/Webhooks.API/Webhooks.API.csproj" -COPY "Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj" "Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj" -COPY "Web/WebhookClient/WebhookClient.csproj" "Web/WebhookClient/WebhookClient.csproj" -COPY "Web/WebMVC/WebMVC.csproj" "Web/WebMVC/WebMVC.csproj" -COPY "Web/WebSPA/WebSPA.csproj" "Web/WebSPA/WebSPA.csproj" -COPY "Web/WebStatus/WebStatus.csproj" "Web/WebStatus/WebStatus.csproj" - -COPY "docker-compose.dcproj" "docker-compose.dcproj" - -COPY "NuGet.config" "NuGet.config" - -RUN dotnet restore "eShopOnContainers-ServicesAndWebApps.sln" - -COPY . . -WORKDIR /src/Services/Location/Locations.API -RUN dotnet publish --no-restore -c Release -o /app - -FROM build as functionaltest -WORKDIR /src/Services/Location/Locations.FunctionalTests - -FROM build AS publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app . -ENTRYPOINT ["dotnet", "Locations.API.dll"] diff --git a/src/Services/Location/Locations.API/Dockerfile.develop b/src/Services/Location/Locations.API/Dockerfile.develop deleted file mode 100644 index ab1f7bfb8..000000000 --- a/src/Services/Location/Locations.API/Dockerfile.develop +++ /dev/null @@ -1,17 +0,0 @@ -FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster -ARG BUILD_CONFIGURATION=Debug -ENV ASPNETCORE_ENVIRONMENT=Development -ENV DOTNET_USE_POLLING_FILE_WATCHER=true -EXPOSE 80 - -WORKDIR /src -COPY ["Services/Location/Locations.API/Locations.API.csproj", "Services/Location/Locations.API/"] -COPY ["BuildingBlocks/EventBus/EventBus/EventBus.csproj", "BuildingBlocks/EventBus/EventBus/"] -COPY ["BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj", "BuildingBlocks/EventBus/EventBusRabbitMQ/"] -COPY ["BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj", "BuildingBlocks/EventBus/EventBusServiceBus/"] -RUN dotnet restore Services/Location/Locations.API/Locations.API.csproj -nowarn:msb3202,nu1503 -COPY . . -WORKDIR "/src/Services/Location/Locations.API" -RUN dotnet build --no-restore -c $BUILD_CONFIGURATION - -ENTRYPOINT ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"] diff --git a/src/Services/Location/Locations.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs b/src/Services/Location/Locations.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs deleted file mode 100644 index 772129da9..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.ActionResults -{ - public class InternalServerErrorObjectResult : ObjectResult - { - public InternalServerErrorObjectResult(object error) - : base(error) - { - StatusCode = StatusCodes.Status500InternalServerError; - } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Exceptions/LocationDomainException.cs b/src/Services/Location/Locations.API/Infrastructure/Exceptions/LocationDomainException.cs deleted file mode 100644 index 53016fcb2..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Exceptions/LocationDomainException.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions -{ - using System; - - /// - /// Exception type for app exceptions - /// - public class LocationDomainException : Exception - { - public LocationDomainException() - { } - - public LocationDomainException(string message) - : base(message) - { } - - public LocationDomainException(string message, Exception innerException) - : base(message, innerException) - { } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs b/src/Services/Location/Locations.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs deleted file mode 100644 index e2d4c9aed..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs +++ /dev/null @@ -1,37 +0,0 @@ - -using Microsoft.AspNetCore.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters -{ - internal class AuthorizeCheckOperationFilter : IOperationFilter - { - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - // Check for authorize attribute - var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || - context.MethodInfo.GetCustomAttributes(true).OfType().Any(); - - if (!hasAuthorize) return; - - operation.Responses.TryAdd("401", new OpenApiResponse() { Description = "Unauthorized" }); - operation.Responses.TryAdd("403", new OpenApiResponse() { Description = "Forbidden" }); - - var oAuthScheme = new OpenApiSecurityScheme - { - Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } - }; - - operation.Security = new List - { - new OpenApiSecurityRequirement - { - [ oAuthScheme ] = new [] { "locationsapi" } - } - }; - } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Location/Locations.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs deleted file mode 100644 index 12cffe878..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters -{ - using AspNetCore.Mvc; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Mvc.Filters; - using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.ActionResults; - using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions; - using Microsoft.Extensions.Hosting; - using Microsoft.Extensions.Logging; - using System.Net; - - public class HttpGlobalExceptionFilter : IExceptionFilter - { - private readonly IHostEnvironment env; - private readonly ILogger logger; - - public HttpGlobalExceptionFilter(IHostEnvironment env, ILogger logger) - { - this.env = env; - this.logger = logger; - } - - public void OnException(ExceptionContext context) - { - logger.LogError(new EventId(context.Exception.HResult), - context.Exception, - context.Exception.Message); - - if (context.Exception.GetType() == typeof(LocationDomainException)) - { - var json = new JsonErrorResponse - { - Messages = new[] { context.Exception.Message } - }; - - // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1 - //It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information - context.Result = new BadRequestObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - else - { - var json = new JsonErrorResponse - { - Messages = new[] { "An error occur.Try it again." } - }; - - if (env.IsDevelopment()) - { - json.DeveloperMessage = context.Exception; - } - - // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1 - // It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information - context.Result = new InternalServerErrorObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; - } - context.ExceptionHandled = true; - } - - private class JsonErrorResponse - { - public string[] Messages { get; set; } - - public object DeveloperMessage { get; set; } - } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs deleted file mode 100644 index 4289ffe68..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure -{ - using Microsoft.eShopOnContainers.Services.Locations.API.Model; - using Microsoft.Extensions.Options; - using MongoDB.Driver; - - public class LocationsContext - { - private readonly IMongoDatabase _database = null; - - public LocationsContext(IOptions settings) - { - var client = new MongoClient(settings.Value.ConnectionString); - if (client != null) - _database = client.GetDatabase(settings.Value.Database); - } - - public IMongoCollection UserLocation - { - get - { - return _database.GetCollection("UserLocation"); - } - } - - public IMongoCollection Locations - { - get - { - return _database.GetCollection("Locations"); - } - } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs deleted file mode 100644 index 91d00a4f3..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs +++ /dev/null @@ -1,354 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure -{ - using Microsoft.AspNetCore.Builder; - using Microsoft.eShopOnContainers.Services.Locations.API.Model; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - using MongoDB.Driver; - using MongoDB.Driver.GeoJsonObjectModel; - using System.Collections.Generic; - using System.Threading.Tasks; - - public class LocationsContextSeed - { - private static LocationsContext ctx; - public static async Task SeedAsync(IApplicationBuilder applicationBuilder, ILoggerFactory loggerFactory) - { - var config = applicationBuilder - .ApplicationServices.GetRequiredService>(); - - ctx = new LocationsContext(config); - - if (!ctx.Locations.Database.GetCollection(nameof(Locations)).AsQueryable().Any()) - { - await SetIndexes(); - await SetNorthAmerica(); - await SetSouthAmerica(); - await SetAfrica(); - await SetEurope(); - await SetAsia(); - await SetAustralia(); - await SetBarcelonaLocations(); - } - } - - static async Task SetNorthAmerica() - { - var us = new Locations() - { - Code = "NA", - Description = "North America", - LocationId = 1 - }; - us.SetLocation(-103.219329, 48.803281); - us.SetArea(GetNorthAmericaPoligon()); - await ctx.Locations.InsertOneAsync(us); - await SetUSLocations(us.Id); - } - - static async Task SetUSLocations(string parentId) - { - var us = new Locations() - { - Parent_Id = parentId, - Code = "US", - Description = "United States", - LocationId = 2 - }; - us.SetLocation(-101.357386, 41.650455); - us.SetArea(GetUSPoligon()); - await ctx.Locations.InsertOneAsync(us); - await SetWashingtonLocations(us.Id); - } - - static async Task SetWashingtonLocations(string parentId) - { - var wht = new Locations() - { - Parent_Id = parentId, - Code = "WHT", - Description = "Washington", - LocationId = 3 - }; - wht.SetLocation(-119.542781, 47.223652); - wht.SetArea(GetWashingtonPoligon()); - await ctx.Locations.InsertOneAsync(wht); - await SetSeattleLocations(wht.Id); - await SetRedmondLocations(wht.Id); - } - - static async Task SetSeattleLocations(string parentId) - { - var stl = new Locations() - { - Parent_Id = parentId, - Code = "SEAT", - Description = "Seattle", - LocationId = 4 - }; - stl.SetArea(GetSeattlePoligon()); - stl.SetLocation(-122.330747, 47.603111); - await ctx.Locations.InsertOneAsync(stl); - } - - static async Task SetRedmondLocations(string parentId) - { - var rdm = new Locations() - { - Parent_Id = parentId, - Code = "REDM", - Description = "Redmond", - LocationId = 5 - }; - rdm.SetLocation(-122.122887, 47.674961); - rdm.SetArea(GetRedmondPoligon()); - await ctx.Locations.InsertOneAsync(rdm); - } - - static async Task SetBarcelonaLocations() - { - var bcn = new Locations() - { - Code = "BCN", - Description = "Barcelona", - LocationId = 6 - }; - bcn.SetLocation(2.156453, 41.395226); - bcn.SetArea(GetBarcelonaPoligon()); - await ctx.Locations.InsertOneAsync(bcn); - } - - static async Task SetSouthAmerica() - { - var sa = new Locations() - { - Code = "SA", - Description = "South America", - LocationId = 7 - }; - sa.SetLocation(-60.328704, -16.809748); - sa.SetArea(GetSouthAmericaPoligon()); - await ctx.Locations.InsertOneAsync(sa); - } - - static async Task SetAfrica() - { - var afc = new Locations() - { - Code = "AFC", - Description = "Africa", - LocationId = 8 - }; - afc.SetLocation(19.475383, 13.063667); - afc.SetArea(GetAfricaPoligon()); - await ctx.Locations.InsertOneAsync(afc); - } - - static async Task SetEurope() - { - var eu = new Locations() - { - Code = "EU", - Description = "Europe", - LocationId = 9 - }; - eu.SetLocation(13.147258, 49.947844); - eu.SetArea(GetEuropePoligon()); - await ctx.Locations.InsertOneAsync(eu); - } - - static async Task SetAsia() - { - var asa = new Locations() - { - Code = "AS", - Description = "Asia", - LocationId = 10 - }; - asa.SetLocation(97.522257, 56.069107); - asa.SetArea(GetAsiaPoligon()); - await ctx.Locations.InsertOneAsync(asa); - } - - static async Task SetAustralia() - { - var aus = new Locations() - { - Code = "AUS", - Description = "Australia", - LocationId = 11 - }; - aus.SetLocation(133.733195, -25.010726); - aus.SetArea(GetAustraliaPoligon()); - await ctx.Locations.InsertOneAsync(aus); - } - - static async Task SetIndexes() - { - // Set location indexes - var builder = Builders.IndexKeys; - var keys = builder.Geo2DSphere(prop => prop.Location); - await ctx.Locations.Indexes.CreateOneAsync(keys); - } - - static List GetNorthAmericaPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(-168.07786, 68.80277), - new GeoJson2DGeographicCoordinates(-119.60378, 32.7561), - new GeoJson2DGeographicCoordinates(-116.01966, 28.94642), - new GeoJson2DGeographicCoordinates(-98.52265, 14.49378), - new GeoJson2DGeographicCoordinates(-71.18188, 34.96278), - new GeoJson2DGeographicCoordinates(-51.97606, 48.24377), - new GeoJson2DGeographicCoordinates(-75.39806, 72.93141), - new GeoJson2DGeographicCoordinates(-168.07786, 68.80277) - }; - } - - static List GetSouthAmericaPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(-91.43724, 13.29007), - new GeoJson2DGeographicCoordinates(-87.96315, -27.15081), - new GeoJson2DGeographicCoordinates(-78.75404, -50.71852), - new GeoJson2DGeographicCoordinates(-59.14765, -58.50773), - new GeoJson2DGeographicCoordinates(-50.08813, -42.22419), - new GeoJson2DGeographicCoordinates(-37.21044, -22.56725), - new GeoJson2DGeographicCoordinates(-36.61675, -0.38594), - new GeoJson2DGeographicCoordinates(-44.46056, -16.6746), - new GeoJson2DGeographicCoordinates(-91.43724, 13.29007), - }; - } - - static List GetAfricaPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(-12.68724, 34.05892), - new GeoJson2DGeographicCoordinates(-18.33301, 20.77313), - new GeoJson2DGeographicCoordinates(-14.13503, 6.21292), - new GeoJson2DGeographicCoordinates(1.40221, -14.23693), - new GeoJson2DGeographicCoordinates(22.41485, -35.55408), - new GeoJson2DGeographicCoordinates(51.86499, -25.39831), - new GeoJson2DGeographicCoordinates(53.49269, 4.59405), - new GeoJson2DGeographicCoordinates(35.102, 26.14685), - new GeoJson2DGeographicCoordinates(21.63319, 33.75767), - new GeoJson2DGeographicCoordinates(6.58235, 37.05665), - new GeoJson2DGeographicCoordinates(-12.68724, 34.05892), - }; - } - - static List GetEuropePoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(-11.73143, 35.27646), - new GeoJson2DGeographicCoordinates(-10.84462, 35.25123), - new GeoJson2DGeographicCoordinates(-10.09927, 35.26833), - new GeoJson2DGeographicCoordinates(49.00838, 36.56984), - new GeoJson2DGeographicCoordinates(36.63837, 71.69807), - new GeoJson2DGeographicCoordinates(-10.88788, 61.13851), - new GeoJson2DGeographicCoordinates(-11.73143, 35.27646), - }; - } - - static List GetAsiaPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(31.1592, 45.91629), - new GeoJson2DGeographicCoordinates(32.046, 45.89479), - new GeoJson2DGeographicCoordinates(62.32261, -4.45013), - new GeoJson2DGeographicCoordinates(154.47713, 35.14525), - new GeoJson2DGeographicCoordinates(-166.70788, 68.62211), - new GeoJson2DGeographicCoordinates(70.38837, 75.89335), - new GeoJson2DGeographicCoordinates(32.00274, 67.23428), - new GeoJson2DGeographicCoordinates(31.1592, 45.91629), - }; - } - - static List GetAustraliaPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(100.76857, -45.74117), - new GeoJson2DGeographicCoordinates(101.65538, -45.76273), - new GeoJson2DGeographicCoordinates(167.08823, -50.66317), - new GeoJson2DGeographicCoordinates(174.16463, -34.62579), - new GeoJson2DGeographicCoordinates(160.94837, -5.01004), - new GeoJson2DGeographicCoordinates(139.29462, -7.86376), - new GeoJson2DGeographicCoordinates(101.61212, -11.44654), - new GeoJson2DGeographicCoordinates(100.76857, -45.74117), - }; - } - - static List GetUSPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(-62.88205, 48.7985), - new GeoJson2DGeographicCoordinates(-129.3132, 48.76513), - new GeoJson2DGeographicCoordinates(-120.9496, 30.12256), - new GeoJson2DGeographicCoordinates(-111.3944, 30.87114), - new GeoJson2DGeographicCoordinates(-78.11975, 24.24979), - new GeoJson2DGeographicCoordinates(-62.88205, 48.7985) - }; - } - - static List GetSeattlePoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(-122.36238,47.82929), - new GeoJson2DGeographicCoordinates(-122.42091,47.6337), - new GeoJson2DGeographicCoordinates(-122.37371,47.45224), - new GeoJson2DGeographicCoordinates(-122.20788,47.50259), - new GeoJson2DGeographicCoordinates(-122.26934,47.73644), - new GeoJson2DGeographicCoordinates(-122.36238,47.82929) - }; - } - - static List GetRedmondPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(-122.15432, 47.73148), - new GeoJson2DGeographicCoordinates(-122.17673, 47.72559), - new GeoJson2DGeographicCoordinates(-122.16904, 47.67851), - new GeoJson2DGeographicCoordinates(-122.16136, 47.65036), - new GeoJson2DGeographicCoordinates(-122.15604, 47.62746), - new GeoJson2DGeographicCoordinates(-122.01562, 47.63463), - new GeoJson2DGeographicCoordinates(-122.04961, 47.74244), - new GeoJson2DGeographicCoordinates(-122.15432, 47.73148) - }; - } - - static List GetWashingtonPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(-124.68633, 48.8943), - new GeoJson2DGeographicCoordinates(-124.32962, 45.66613), - new GeoJson2DGeographicCoordinates(-116.73824, 45.93384), - new GeoJson2DGeographicCoordinates(-116.96912, 49.04282), - new GeoJson2DGeographicCoordinates(-124.68633, 48.8943) - }; - } - - static List GetBarcelonaPoligon() - { - return new List() - { - new GeoJson2DGeographicCoordinates(2.033879, 41.383858), - new GeoJson2DGeographicCoordinates(2.113741, 41.419068), - new GeoJson2DGeographicCoordinates(2.188778, 41.451153), - new GeoJson2DGeographicCoordinates(2.235266, 41.418033), - new GeoJson2DGeographicCoordinates(2.137101, 41.299536), - new GeoJson2DGeographicCoordinates(2.033879, 41.383858) - }; - } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs b/src/Services/Location/Locations.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs deleted file mode 100644 index e6b43d109..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Middlewares -{ - class ByPassAuthMiddleware - { - private readonly RequestDelegate _next; - private string _currentUserId; - public ByPassAuthMiddleware(RequestDelegate next) - { - _next = next; - _currentUserId = null; - } - - - public async Task Invoke(HttpContext context) - { - var path = context.Request.Path; - if (path == "/noauth") - { - var userid = context.Request.Query["userid"]; - if (!string.IsNullOrEmpty(userid)) - { - _currentUserId = userid; - } - context.Response.StatusCode = 200; - context.Response.ContentType = "text/string"; - await context.Response.WriteAsync($"User set to {_currentUserId}"); - } - - else if (path == "/noauth/reset") - { - _currentUserId = null; - context.Response.StatusCode = 200; - context.Response.ContentType = "text/string"; - await context.Response.WriteAsync($"User set to none. Token required for protected endpoints."); - } - else - { - var currentUserId = _currentUserId; - - var authHeader = context.Request.Headers["Authorization"]; - if (authHeader != StringValues.Empty) - { - var header = authHeader.FirstOrDefault(); - if (!string.IsNullOrEmpty(header) && header.StartsWith("Email ") && header.Length > "Email ".Length) - { - currentUserId = header.Substring("Email ".Length); - } - } - - - if (!string.IsNullOrEmpty(currentUserId)) - { - var user = new ClaimsIdentity(new[] { - new Claim("emails", currentUserId), - new Claim("name", "Test user"), - new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "Test user"), - new Claim("nonce", Guid.NewGuid().ToString()), - new Claim("http://schemas.microsoft.com/identity/claims/identityprovider", "ByPassAuthMiddleware"), - new Claim("sub", currentUserId), - new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","User"), - new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Microsoft")} - , "ByPassAuth"); - - context.User = new ClaimsPrincipal(user); - } - - await _next.Invoke(context); - } - } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Repositories/ILocationsRepository.cs b/src/Services/Location/Locations.API/Infrastructure/Repositories/ILocationsRepository.cs deleted file mode 100644 index cd50fa987..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Repositories/ILocationsRepository.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories -{ - using Microsoft.eShopOnContainers.Services.Locations.API.Model; - using System.Collections.Generic; - using System.Threading.Tasks; - using ViewModel; - - public interface ILocationsRepository - { - Task GetAsync(int locationId); - - Task> GetLocationListAsync(); - - Task GetUserLocationAsync(string userId); - - Task> GetCurrentUserRegionsListAsync(LocationRequest currentPosition); - - Task AddUserLocationAsync(UserLocation location); - - Task UpdateUserLocationAsync(UserLocation userLocation); - - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs b/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs deleted file mode 100644 index 9f8d42ad4..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories -{ - using Microsoft.eShopOnContainers.Services.Locations.API.Model; - using Microsoft.Extensions.Options; - using MongoDB.Bson; - using MongoDB.Driver; - using MongoDB.Driver.GeoJsonObjectModel; - using System.Collections.Generic; - using System.Threading.Tasks; - using ViewModel; - - public class LocationsRepository - : ILocationsRepository - { - private readonly LocationsContext _context; - - public LocationsRepository(IOptions settings) - { - _context = new LocationsContext(settings); - } - - public async Task GetAsync(int locationId) - { - var filter = Builders.Filter.Eq("LocationId", locationId); - return await _context.Locations - .Find(filter) - .FirstOrDefaultAsync(); - } - - public async Task GetUserLocationAsync(string userId) - { - var filter = Builders.Filter.Eq("UserId", userId); - return await _context.UserLocation - .Find(filter) - .FirstOrDefaultAsync(); - } - - public async Task> GetLocationListAsync() - { - return await _context.Locations.Find(new BsonDocument()).ToListAsync(); - } - - public async Task> GetCurrentUserRegionsListAsync(LocationRequest currentPosition) - { - var point = GeoJson.Point(GeoJson.Geographic(currentPosition.Longitude, currentPosition.Latitude)); - var orderByDistanceQuery = new FilterDefinitionBuilder().Near(x => x.Location, point); - var withinAreaQuery = new FilterDefinitionBuilder().GeoIntersects("Polygon", point); - var filter = Builders.Filter.And(orderByDistanceQuery, withinAreaQuery); - return await _context.Locations.Find(filter).ToListAsync(); - } - - public async Task AddUserLocationAsync(UserLocation location) - { - await _context.UserLocation.InsertOneAsync(location); - } - - public async Task UpdateUserLocationAsync(UserLocation userLocation) - { - await _context.UserLocation.ReplaceOneAsync( - doc => doc.UserId == userLocation.UserId, - userLocation, - new UpdateOptions { IsUpsert = true }); - } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs deleted file mode 100644 index a2b79d8d1..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services -{ - public interface IIdentityService - { - string GetUserIdentity(); - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/ILocationsService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/ILocationsService.cs deleted file mode 100644 index 11459492a..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Services/ILocationsService.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services -{ - using Microsoft.eShopOnContainers.Services.Locations.API.Model; - using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; - using System.Collections.Generic; - using System.Threading.Tasks; - - public interface ILocationsService - { - Task GetLocationAsync(int locationId); - - Task GetUserLocationAsync(string id); - - Task> GetAllLocationAsync(); - - Task AddOrUpdateUserLocationAsync(string userId, LocationRequest locRequest); - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs deleted file mode 100644 index d06b44a4f..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.AspNetCore.Http; -using System; - -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services -{ - public class IdentityService : IIdentityService - { - private readonly IHttpContextAccessor _context; - - public IdentityService(IHttpContextAccessor context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } - - public string GetUserIdentity() - { - return _context.HttpContext.User.FindFirst("sub").Value; - } - } -} diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs deleted file mode 100644 index f6b9ed708..000000000 --- a/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs +++ /dev/null @@ -1,97 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services -{ - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions; - using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories; - using Microsoft.eShopOnContainers.Services.Locations.API.IntegrationEvents.Events; - using Microsoft.eShopOnContainers.Services.Locations.API.Model; - using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; - using Microsoft.Extensions.Logging; - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - - public class LocationsService : ILocationsService - { - private readonly ILocationsRepository _locationsRepository; - private readonly IEventBus _eventBus; - private readonly ILogger _logger; - - public LocationsService( - ILocationsRepository locationsRepository, - IEventBus eventBus, - ILogger logger) - { - _locationsRepository = locationsRepository ?? throw new ArgumentNullException(nameof(locationsRepository)); - _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } - - public async Task GetLocationAsync(int locationId) - { - return await _locationsRepository.GetAsync(locationId); - } - - public async Task GetUserLocationAsync(string userId) - { - return await _locationsRepository.GetUserLocationAsync(userId); - } - - public async Task> GetAllLocationAsync() - { - return await _locationsRepository.GetLocationListAsync(); - } - - public async Task AddOrUpdateUserLocationAsync(string userId, LocationRequest currentPosition) - { - // Get the list of ordered regions the user currently is within - var currentUserAreaLocationList = await _locationsRepository.GetCurrentUserRegionsListAsync(currentPosition); - - if (currentUserAreaLocationList is null) - { - throw new LocationDomainException("User current area not found"); - } - - // If current area found, then update user location - var locationAncestors = new List(); - var userLocation = await _locationsRepository.GetUserLocationAsync(userId); - userLocation = userLocation ?? new UserLocation(); - userLocation.UserId = userId; - userLocation.LocationId = currentUserAreaLocationList[0].LocationId; - userLocation.UpdateDate = DateTime.UtcNow; - await _locationsRepository.UpdateUserLocationAsync(userLocation); - - // Publish integration event to update marketing read data model - // with the new locations updated - PublishNewUserLocationPositionIntegrationEvent(userId, currentUserAreaLocationList); - - return true; - } - - private void PublishNewUserLocationPositionIntegrationEvent(string userId, List newLocations) - { - var newUserLocations = MapUserLocationDetails(newLocations); - var @event = new UserLocationUpdatedIntegrationEvent(userId, newUserLocations); - - _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - - _eventBus.Publish(@event); - } - - private List MapUserLocationDetails(List newLocations) - { - var result = new List(); - newLocations.ForEach(location => - { - result.Add(new UserLocationDetails() - { - LocationId = location.LocationId, - Code = location.Code, - Description = location.Description - }); - }); - - return result; - } - } -} diff --git a/src/Services/Location/Locations.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs b/src/Services/Location/Locations.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs deleted file mode 100644 index 7c3e72769..000000000 --- a/src/Services/Location/Locations.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.IntegrationEvents.Events -{ - using Locations.API.Model; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using System.Collections.Generic; - - public class UserLocationUpdatedIntegrationEvent : IntegrationEvent - { - public string UserId { get; set; } - public List LocationList { get; set; } - - public UserLocationUpdatedIntegrationEvent(string userId, List locationList) - { - UserId = userId; - LocationList = locationList; - } - } -} diff --git a/src/Services/Location/Locations.API/LocationSettings.cs b/src/Services/Location/Locations.API/LocationSettings.cs deleted file mode 100644 index b3972239c..000000000 --- a/src/Services/Location/Locations.API/LocationSettings.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Locations.API -{ - public class LocationSettings - { - public string ExternalCatalogBaseUrl { get; set; } - public string EventBusConnection { get; set; } - public string ConnectionString { get; set; } - public string Database { get; set; } - } -} diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj deleted file mode 100644 index d4899becb..000000000 --- a/src/Services/Location/Locations.API/Locations.API.csproj +++ /dev/null @@ -1,45 +0,0 @@ - - - - netcoreapp3.1 - ..\..\..\..\docker-compose.dcproj - aspnet-Locations.API-20161122013619 - false - true - preview - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Services/Location/Locations.API/Model/Core/LocationPoint.cs b/src/Services/Location/Locations.API/Model/Core/LocationPoint.cs deleted file mode 100644 index 48b6e32a7..000000000 --- a/src/Services/Location/Locations.API/Model/Core/LocationPoint.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Locations.API.Model.Core -{ - public class LocationPoint - { - public LocationPoint() - { - } - - public LocationPoint(double longitude, double latitude) - { - this.coordinates.Add(longitude); - this.coordinates.Add(latitude); - } - - public string type { get; private set; } = "Point"; - - public List coordinates { get; private set; } = new List(); - } -} diff --git a/src/Services/Location/Locations.API/Model/Core/LocationPolygon.cs b/src/Services/Location/Locations.API/Model/Core/LocationPolygon.cs deleted file mode 100644 index 18380cc79..000000000 --- a/src/Services/Location/Locations.API/Model/Core/LocationPolygon.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MongoDB.Driver.GeoJsonObjectModel; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Locations.API.Model.Core -{ - public class LocationPolygon - { - public LocationPolygon() - { - } - - public LocationPolygon(List coordinatesList) - { - var coordinatesMapped = coordinatesList.Select(x => new List() { x.Longitude, x.Latitude }).ToList(); - this.coordinates.Add(coordinatesMapped); - } - - public string type { get; private set; } = "Polygon"; - - public List>> coordinates { get; private set; } = new List>>(); - } -} diff --git a/src/Services/Location/Locations.API/Model/Locations.cs b/src/Services/Location/Locations.API/Model/Locations.cs deleted file mode 100644 index ba3dbe62c..000000000 --- a/src/Services/Location/Locations.API/Model/Locations.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Model -{ - using global::Locations.API.Model.Core; - using MongoDB.Bson; - using MongoDB.Bson.Serialization.Attributes; - using MongoDB.Driver.GeoJsonObjectModel; - using System.Collections.Generic; - - public class Locations - { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] - public string Id { get; set; } - public int LocationId { get; set; } - public string Code { get; set; } - [BsonRepresentation(BsonType.ObjectId)] - public string Parent_Id { get; set; } - public string Description { get; set; } - public double Latitude { get; set; } - public double Longitude { get; set; } - public LocationPoint Location { get; private set; } - public LocationPolygon Polygon { get; private set; } - - // Temporal commented in previewVersion7 of netcore and 2.9.0-beta2 of Mongo packages, review in next versions - // public GeoJsonPoint Location { get; private set; } - // public GeoJsonPolygon Polygon { get; private set; } - public void SetLocation(double lon, double lat) => SetPosition(lon, lat); - public void SetArea(List coordinatesList) => SetPolygon(coordinatesList); - - private void SetPosition(double lon, double lat) - { - Latitude = lat; - Longitude = lon; - Location = new LocationPoint(lon, lat); - } - - private void SetPolygon(List coordinatesList) - { - Polygon = new LocationPolygon(coordinatesList); - } - } -} diff --git a/src/Services/Location/Locations.API/Model/UserLocation.cs b/src/Services/Location/Locations.API/Model/UserLocation.cs deleted file mode 100644 index 4686bd006..000000000 --- a/src/Services/Location/Locations.API/Model/UserLocation.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Model -{ - using MongoDB.Bson; - using MongoDB.Bson.Serialization.Attributes; - using System; - - public class UserLocation - { - [BsonIgnoreIfDefault] - [BsonRepresentation(BsonType.ObjectId)] - public string Id { get; set; } - public string UserId { get; set; } - public int LocationId { get; set; } - public DateTime UpdateDate { get; set; } - } -} diff --git a/src/Services/Location/Locations.API/Model/UserLocationDetails.cs b/src/Services/Location/Locations.API/Model/UserLocationDetails.cs deleted file mode 100644 index 7983e8e59..000000000 --- a/src/Services/Location/Locations.API/Model/UserLocationDetails.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.Model -{ - public class UserLocationDetails - { - public int LocationId { get; set; } - public string Code { get; set; } - public string Description { get; set; } - } -} \ No newline at end of file diff --git a/src/Services/Location/Locations.API/Program.cs b/src/Services/Location/Locations.API/Program.cs deleted file mode 100644 index f9e21a8a4..000000000 --- a/src/Services/Location/Locations.API/Program.cs +++ /dev/null @@ -1,88 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Serilog; -using System; -using System.IO; - -namespace Microsoft.eShopOnContainers.Services.Locations.API -{ - public class Program - { - public static readonly string Namespace = typeof(Program).Namespace; - public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); - - public static int Main(string[] args) - { - var configuration = GetConfiguration(); - - Log.Logger = CreateSerilogLogger(configuration); - - try - { - Log.Information("Configuring web host ({ApplicationContext})...", AppName); - var host = BuildWebHost(configuration, args); - - Log.Information("Starting web host ({ApplicationContext})...", AppName); - host.Run(); - - return 0; - } - catch (Exception ex) - { - Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName); - return 1; - } - finally - { - Log.CloseAndFlush(); - } - } - - private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) => - WebHost.CreateDefaultBuilder(args) - .CaptureStartupErrors(false) - .ConfigureAppConfiguration(x => x.AddConfiguration(configuration)) - .UseStartup() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseSerilog() - .Build(); - - private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) - { - var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - var logstashUrl = configuration["Serilog:LogstashgUrl"]; - return new LoggerConfiguration() - .MinimumLevel.Verbose() - .Enrich.WithProperty("ApplicationContext", AppName) - .Enrich.FromLogContext() - .WriteTo.Console() - .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) - .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) - .ReadFrom.Configuration(configuration) - .CreateLogger(); - } - - private static IConfiguration GetConfiguration() - { - var builder = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) - .AddEnvironmentVariables(); - - var config = builder.Build(); - - if (config.GetValue("UseVault", false)) - { - builder.AddAzureKeyVault( - $"https://{config["Vault:Name"]}.vault.azure.net/", - config["Vault:ClientId"], - config["Vault:ClientSecret"]); - } - - return builder.Build(); - } - } -} \ No newline at end of file diff --git a/src/Services/Location/Locations.API/Properties/launchSettings.json b/src/Services/Location/Locations.API/Properties/launchSettings.json deleted file mode 100644 index 1c86a33b1..000000000 --- a/src/Services/Location/Locations.API/Properties/launchSettings.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:54020/", - "sslPort": 0 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "api/values", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Locations.API": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "api/values", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "http://localhost:3279" - } - } -} \ No newline at end of file diff --git a/src/Services/Location/Locations.API/Startup.cs b/src/Services/Location/Locations.API/Startup.cs deleted file mode 100644 index ca6a57e6e..000000000 --- a/src/Services/Location/Locations.API/Startup.cs +++ /dev/null @@ -1,312 +0,0 @@ -using Autofac; -using Autofac.Extensions.DependencyInjection; -using HealthChecks.UI.Client; -using Locations.API.Controllers; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.Azure.ServiceBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; -using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure; -using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters; -using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Middlewares; -using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories; -using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Models; -using RabbitMQ.Client; -using System; -using System.Collections.Generic; -using System.IdentityModel.Tokens.Jwt; - -namespace Microsoft.eShopOnContainers.Services.Locations.API -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public virtual IServiceProvider ConfigureServices(IServiceCollection services) - { - RegisterAppInsights(services); - - services.AddCustomHealthCheck(Configuration); - - services.AddControllers(options => - { - options.Filters.Add(typeof(HttpGlobalExceptionFilter)); - }) - // Added for functional tests - .AddApplicationPart(typeof(LocationsController).Assembly) - .AddNewtonsoftJson(); - - ConfigureAuthService(services); - - services.Configure(Configuration); - - if (Configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); - - var serviceBusConnectionString = Configuration["EventBusConnection"]; - var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - - return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); - }); - } - else - { - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); - - var factory = new ConnectionFactory() - { - HostName = Configuration["EventBusConnection"], - DispatchConsumersAsync = true - }; - - if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) - { - factory.UserName = Configuration["EventBusUserName"]; - } - - if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) - { - factory.Password = Configuration["EventBusPassword"]; - } - - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } - - return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); - }); - } - - RegisterEventBus(services); - - // Add framework services. - services.AddSwaggerGen(options => - { - options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new OpenApiInfo - { - Title = "eShopOnContainers - Location HTTP API", - Version = "v1", - Description = "The Location Microservice HTTP API. This is a Data-Driven/CRUD microservice sample", - }); - - options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme - { - Type = SecuritySchemeType.OAuth2, - Flows = new OpenApiOAuthFlows() - { - Implicit = new OpenApiOAuthFlow() - { - AuthorizationUrl = new Uri($"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), - TokenUrl = new Uri($"{Configuration.GetValue("IdentityUrlExternal")}/connect/token"), - Scopes = new Dictionary() - { - { "locations", "Locations API" } - } - } - } - }); - - options.OperationFilter(); - - }); - - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder - .SetIsOriginAllowed((host) => true) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); - }); - - services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - //configure autofac - var container = new ContainerBuilder(); - container.Populate(services); - - return new AutofacServiceProvider(container.Build()); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) - { - //loggerFactory.AddAzureWebAppDiagnostics(); - //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); - - var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) - { - app.UsePathBase(pathBase); - } - - app.UseRouting(); - app.UseCors("CorsPolicy"); - ConfigureAuth(app); - - app.UseEndpoints(endpoints => - { - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); - }); - - app.UseSwagger() - .UseSwaggerUI(c => - { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Locations.API V1"); - c.OAuthClientId("locationsswaggerui"); - c.OAuthAppName("Locations Swagger UI"); - }); - - LocationsContextSeed.SeedAsync(app, loggerFactory) - .Wait(); - } - - private void RegisterAppInsights(IServiceCollection services) - { - services.AddApplicationInsightsTelemetry(Configuration); - services.AddApplicationInsightsKubernetesEnricher(); - } - - private void ConfigureAuthService(IServiceCollection services) - { - // prevent from mapping "sub" claim to nameidentifier. - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(options => - { - options.Authority = Configuration.GetValue("IdentityUrl"); - options.Audience = "locations"; - options.RequireHttpsMetadata = false; - }); - } - - protected virtual void ConfigureAuth(IApplicationBuilder app) - { - if (Configuration.GetValue("UseLoadTest")) - { - app.UseMiddleware(); - } - - app.UseAuthentication(); - app.UseAuthorization(); - } - - private void RegisterEventBus(IServiceCollection services) - { - var subscriptionClientName = Configuration["SubscriptionClientName"]; - - if (Configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var serviceBusPersisterConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); - }); - } - else - { - services.AddSingleton(sp => - { - var rabbitMQPersistentConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } - - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); - }); - } - - services.AddSingleton(); - } - } - - public static class CustomExtensionMethods - { - public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) - { - var hcBuilder = services.AddHealthChecks(); - - hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); - - hcBuilder - .AddMongoDb( - configuration["ConnectionString"], - name: "locations-mongodb-check", - tags: new string[] { "mongodb" }); - - if (configuration.GetValue("AzureServiceBusEnabled")) - { - hcBuilder - .AddAzureServiceBusTopic( - configuration["EventBusConnection"], - topicName: "eshop_event_bus", - name: "locations-servicebus-check", - tags: new string[] { "servicebus" }); - } - else - { - hcBuilder - .AddRabbitMQ( - $"amqp://{configuration["EventBusConnection"]}", - name: "locations-rabbitmqbus-check", - tags: new string[] { "rabbitmqbus" }); - } - - return services; - } - } -} diff --git a/src/Services/Location/Locations.API/ViewModel/LocationRequest.cs b/src/Services/Location/Locations.API/ViewModel/LocationRequest.cs deleted file mode 100644 index 5301cee87..000000000 --- a/src/Services/Location/Locations.API/ViewModel/LocationRequest.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Locations.API.ViewModel -{ - public class LocationRequest - { - public double Longitude { get; set; } - public double Latitude { get; set; } - } -} diff --git a/src/Services/Location/Locations.API/appsettings.json b/src/Services/Location/Locations.API/appsettings.json deleted file mode 100644 index 3ee24b242..000000000 --- a/src/Services/Location/Locations.API/appsettings.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "ConnectionString": "mongodb://nosql.data", - "Database": "LocationsDb", - "IdentityUrl": "http://localhost:5105", - "Serilog": { - "SeqServerUrl": null, - "LogstashgUrl": null, - "MinimumLevel": { - "Default": "Information", - "Override": { - "Microsoft": "Warning", - "Microsoft.eShopOnContainers": "Information", - "System": "Warning" - } - } - }, - "AzureServiceBusEnabled": false, - "SubscriptionClientName": "Locations", - "ApplicationInsights": { - "InstrumentationKey": "" - }, - "EventBusRetryCount": 5, - "UseVault": false, - "Vault": { - "Name": "eshop", - "ClientId": "your-client-id", - "ClientSecret": "your-client-secret" - } -} diff --git a/src/Services/Location/Locations.API/azds.yaml b/src/Services/Location/Locations.API/azds.yaml deleted file mode 100644 index e86a09927..000000000 --- a/src/Services/Location/Locations.API/azds.yaml +++ /dev/null @@ -1,56 +0,0 @@ -kind: helm-release -apiVersion: 1.1 -build: - context: ..\..\..\.. - dockerfile: Dockerfile -install: - chart: ../../../../k8s/helm/locations-api - set: - replicaCount: 1 - image: - tag: $(tag) - pullPolicy: Never - ingress: - annotations: - kubernetes.io/ingress.class: traefik-azds - hosts: - - $(spacePrefix)eshop$(hostSuffix) - inf: - k8s: - dns: $(spacePrefix)eshop$(hostSuffix) - values: - - values.dev.yaml? - - secrets.dev.yaml? - - inf.yaml - - app.yaml -configurations: - develop: - build: - useGitIgnore: true - dockerfile: Dockerfile.develop - args: - BUILD_CONFIGURATION: ${BUILD_CONFIGURATION:-Debug} - container: - sync: - - '**/Pages/**' - - '**/Views/**' - - '**/wwwroot/**' - - '!**/*.{sln,csproj}' - command: - - dotnet - - run - - --no-restore - - --no-build - - --no-launch-profile - - -c - - ${BUILD_CONFIGURATION:-Debug} - iterate: - processesToKill: - - dotnet - - vsdbg - buildCommands: - - - dotnet - - build - - --no-restore - - -c - - ${BUILD_CONFIGURATION:-Debug} diff --git a/src/Services/Location/Locations.API/values.dev.yaml b/src/Services/Location/Locations.API/values.dev.yaml deleted file mode 100644 index eaed45149..000000000 --- a/src/Services/Location/Locations.API/values.dev.yaml +++ /dev/null @@ -1,3 +0,0 @@ -ingress: - enabled: true - tls: [] \ No newline at end of file diff --git a/src/Services/Location/Locations.FunctionalTests/LocationTestsStartup.cs b/src/Services/Location/Locations.FunctionalTests/LocationTestsStartup.cs deleted file mode 100644 index 08bf2ffa5..000000000 --- a/src/Services/Location/Locations.FunctionalTests/LocationTestsStartup.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Routing; -using Microsoft.eShopOnContainers.Services.Locations.API; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace Locations.FunctionalTests -{ - public class LocationsTestsStartup : Startup - { - public LocationsTestsStartup(IConfiguration env) : base(env) - { - } - - public override IServiceProvider ConfigureServices(IServiceCollection services) - { - // Added to avoid the Authorize data annotation in test environment. - // Property "SuppressCheckForUnhandledSecurityMetadata" in appsettings.json - services.Configure(Configuration); - return base.ConfigureServices(services); - } - protected override void ConfigureAuth(IApplicationBuilder app) - { - if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) - { - app.UseMiddleware(); - } - else - { - base.ConfigureAuth(app); - } - } - - class LocationAuthorizeMiddleware - { - private readonly RequestDelegate _next; - public LocationAuthorizeMiddleware(RequestDelegate rd) - { - _next = rd; - } - - public async Task Invoke(HttpContext httpContext) - { - var identity = new ClaimsIdentity("cookies"); - identity.AddClaim(new Claim("sub", "4611ce3f-380d-4db5-8d76-87a8689058ed")); - httpContext.User.AddIdentity(identity); - await _next.Invoke(httpContext); - } - } - } -} diff --git a/src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj b/src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj deleted file mode 100644 index 0b6f4f1fa..000000000 --- a/src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - netcoreapp3.1 - false - false - - - - - - - - - Always - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - - diff --git a/src/Services/Location/Locations.FunctionalTests/LocationsScenarioBase.cs b/src/Services/Location/Locations.FunctionalTests/LocationsScenarioBase.cs deleted file mode 100644 index 8c68fa3f6..000000000 --- a/src/Services/Location/Locations.FunctionalTests/LocationsScenarioBase.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.Configuration; -using System.IO; -using System.Reflection; - -namespace Locations.FunctionalTests -{ - public class LocationsScenarioBase - { - public TestServer CreateServer() - { - var path = Assembly.GetAssembly(typeof(LocationsScenarioBase)) - .Location; - - var hostBuilder = new WebHostBuilder() - .UseContentRoot(Path.GetDirectoryName(path)) - .ConfigureAppConfiguration(cb => - { - cb.AddJsonFile("appsettings.json", optional: false) - .AddEnvironmentVariables(); - }).UseStartup(); - - return new TestServer(hostBuilder); - } - - public static class Get - { - public static string Locations = "api/v1/locations"; - - public static string LocationBy(int id) - { - return $"api/v1/locations/{id}"; - } - - public static string UserLocationBy(string id) - { - return $"api/v1/locations/user/{id}"; - } - } - - public static class Post - { - public static string AddNewLocation = "api/v1/locations/"; - } - } -} diff --git a/src/Services/Location/Locations.FunctionalTests/LocationsScenarios.cs b/src/Services/Location/Locations.FunctionalTests/LocationsScenarios.cs deleted file mode 100644 index 5f8c90dfd..000000000 --- a/src/Services/Location/Locations.FunctionalTests/LocationsScenarios.cs +++ /dev/null @@ -1,140 +0,0 @@ -using Microsoft.eShopOnContainers.Services.Locations.API.Model; -using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; -using Newtonsoft.Json; -using System.Collections.Generic; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Xunit; - -namespace Locations.FunctionalTests -{ - public class LocationsScenarios - : LocationsScenarioBase - { - [Fact] - public async Task Set_new_user_seattle_location_response_ok_status_code() - { - using (var server = CreateServer()) - { - var userId = "4611ce3f-380d-4db5-8d76-87a8689058ed"; - var content = new StringContent(BuildLocationsRequest(-122.315752, 47.604610), UTF8Encoding.UTF8, "application/json"); - - // Expected result - var expectedLocation = "SEAT"; - - // Act - var response = await server.CreateClient() - .PostAsync(Post.AddNewLocation, content); - - var userLocationResponse = await server.CreateClient() - .GetAsync(Get.UserLocationBy(userId)); - - var responseBody = await userLocationResponse.Content.ReadAsStringAsync(); - var userLocation = JsonConvert.DeserializeObject(responseBody); - - var locationResponse = await server.CreateClient() - .GetAsync(Get.LocationBy(userLocation.LocationId)); - - responseBody = await locationResponse.Content.ReadAsStringAsync(); - var location = JsonConvert.DeserializeObject(responseBody); - - // Assert - Assert.Equal(expectedLocation, location.Code); - } - } - - [Fact] - public async Task Set_new_user_readmond_location_response_ok_status_code() - { - using (var server = CreateServer()) - { - var userId = "4611ce3f-380d-4db5-8d76-87a8689058ed"; - var content = new StringContent(BuildLocationsRequest(-122.119998, 47.690876), UTF8Encoding.UTF8, "application/json"); - - var client = server.CreateClient(); - - // Expected result - var expectedLocation = "REDM"; - - // Act - - var response = await client.PostAsync(Post.AddNewLocation, content); - - var userLocationResponse = await client.GetAsync(Get.UserLocationBy(userId)); - userLocationResponse.EnsureSuccessStatusCode(); - - var responseBody = await userLocationResponse.Content.ReadAsStringAsync(); - var userLocation = JsonConvert.DeserializeObject(responseBody); - - Assert.NotNull(userLocation); - - var locationResponse = await client.GetAsync(Get.LocationBy(userLocation.LocationId)); - - responseBody = await locationResponse.Content.ReadAsStringAsync(); - var location = JsonConvert.DeserializeObject(responseBody); - - // Assert - Assert.Equal(expectedLocation, location.Code); - } - } - - [Fact] - public async Task Set_new_user_Washington_location_response_ok_status_code() - { - using (var server = CreateServer()) - { - var userId = "4611ce3f-380d-4db5-8d76-87a8689058ed"; - var content = new StringContent(BuildLocationsRequest(-121.040360, 48.091631), UTF8Encoding.UTF8, "application/json"); - - // Expected result - var expectedLocation = "WHT"; - - // Act - var response = await server.CreateClient() - .PostAsync(Post.AddNewLocation, content); - - var userLocationResponse = await server.CreateClient() - .GetAsync(Get.UserLocationBy(userId)); - - var responseBody = await userLocationResponse.Content.ReadAsStringAsync(); - var userLocation = JsonConvert.DeserializeObject(responseBody); - - var locationResponse = await server.CreateClient() - .GetAsync(Get.LocationBy(userLocation.LocationId)); - - responseBody = await locationResponse.Content.ReadAsStringAsync(); - var location = JsonConvert.DeserializeObject(responseBody); - - // Assert - Assert.Equal(expectedLocation, location.Code); - } - } - - [Fact] - public async Task Get_all_locations_response_ok_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Locations); - - var responseBody = await response.Content.ReadAsStringAsync(); - var locations = JsonConvert.DeserializeObject>(responseBody); - - // Assert - Assert.NotEmpty(locations); - } - } - - string BuildLocationsRequest(double lon, double lat) - { - var location = new LocationRequest() - { - Longitude = lon, - Latitude = lat - }; - return JsonConvert.SerializeObject(location); - } - } -} diff --git a/src/Services/Location/Locations.FunctionalTests/appsettings.json b/src/Services/Location/Locations.FunctionalTests/appsettings.json deleted file mode 100644 index 6880b2ee1..000000000 --- a/src/Services/Location/Locations.FunctionalTests/appsettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ConnectionString": "mongodb://localhost:27017", - "Database": "LocationsDb", - "ExternalCatalogBaseUrl": "http://localhost:5101", - "IdentityUrl": "http://localhost:5105", - "isTest": "true", - "EventBusConnection": "localhost", - "SubscriptionClientName": "Locations", - "SuppressCheckForUnhandledSecurityMetadata":true -} diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/function.json b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/function.json deleted file mode 100644 index 70b31994a..000000000 --- a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/function.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "bindings": [ - { - "authLevel": "function", - "name": "req", - "type": "httpTrigger", - "direction": "in" - }, - { - "name": "$return", - "type": "http", - "direction": "out" - } - ], - "disabled": false -} \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/project.json b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/project.json deleted file mode 100644 index 97c3bba09..000000000 --- a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/project.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - - "frameworks": { - - "net46":{ - - "dependencies": { - - "Dapper": "1.50.2", - - "System.Data.SqlClient":"4.1.0", - - "Microsoft.WindowsAzure.ConfigurationManager":"3.2.1" - - } - - } - - } - -} \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/run.csx b/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/run.csx deleted file mode 100644 index 9ca9b5a3b..000000000 --- a/src/Services/Marketing/Infrastructure/AzureFunctions/MarketingDetailsHttpTrigger/run.csx +++ /dev/null @@ -1,91 +0,0 @@ -using System.Net; -using System.Net.Http.Headers; -using System.Configuration; -using Dapper; -using System.Data.SqlClient; - -public static async Task Run(HttpRequestMessage req, TraceWriter log) -{ - log.Info($"Campaign HTTP trigger function processed a request. RequestUri={req.RequestUri}"); - - string htmlResponse = string.Empty; - - // parse query parameter - string campaignId = req.GetQueryNameValuePairs() - .FirstOrDefault(q => string.Compare(q.Key, "campaignId", true) == 0) - .Value; - - string userId = req.GetQueryNameValuePairs() - .FirstOrDefault(q => string.Compare(q.Key, "userId", true) == 0) - .Value; - - var cnnString = ConfigurationManager.ConnectionStrings["SqlConnection"].ConnectionString; - - using (var conn = new SqlConnection(cnnString)) - { - await conn.OpenAsync(); - var sql = "SELECT * FROM [dbo].[Campaign] WHERE Id = @CampaignId;"; - var campaign = (await conn.QueryAsync(sql, new { CampaignId = campaignId })).FirstOrDefault(); - htmlResponse = BuildHtmlResponse(campaign); - } - - var response = new HttpResponseMessage(HttpStatusCode.OK); - response.Content = new ByteArrayContent(System.Text.Encoding.UTF8.GetBytes(htmlResponse)); - response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html"); - - return response; -} - -private static string BuildHtmlResponse(Campaign campaign) -{ - var marketingStorageUri = ConfigurationManager.AppSettings["MarketingStorageUri"]; - - return string.Format(@" - - - - -
- Campaign Details -
- -
-
-
-
- Card image cap -
-

{1}

-

{2}

- -
-
-
-
- - ", - $"{marketingStorageUri}{campaign.PictureName}", - campaign.Name, - campaign.Description, - campaign.From.ToString("MMMM dd, yyyy"), - campaign.From.ToString("MMMM dd, yyyy")); -} - -public class Campaign -{ - public int Id { get; set; } - - public string Name { get; set; } - - public string Description { get; set; } - - public DateTime From { get; set; } - - public DateTime To { get; set; } - - public string PictureUri { get; set; } - - public string PictureName { get; set; } -} diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/host.json b/src/Services/Marketing/Infrastructure/AzureFunctions/host.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/src/Services/Marketing/Infrastructure/AzureFunctions/host.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/local.settings.json b/src/Services/Marketing/Infrastructure/AzureFunctions/local.settings.json deleted file mode 100644 index 92d59f7e2..000000000 --- a/src/Services/Marketing/Infrastructure/AzureFunctions/local.settings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "IsEncrypted": false, - "Value": { - "APPSETTING_FUNCTIONS_EXTENSION_VERSION": "~1", - "APPSETTING_ScmType": "None", - "APPSETTING_WEBSITE_AUTH_ENABLED": "False", - "APPSETTING_REMOTEDEBUGGINGVERSION": "11.0.611103.400", - "APPSETTING_AzureWebJobsDashboard": "", - "APPSETTING_MarketingStorageUri": "", - "APPSETTING_WEBSITE_NODE_DEFAULT_VERSION": "6.5.0", - "APPSETTING_WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "", - "APPSETTING_WEBSITE_CONTENTSHARE": "", - "APPSETTING_WEBSITE_SLOT_NAME": "", - "APPSETTING_AzureWebJobsStorage": "", - "APPSETTING_WEBSITE_SITE_NAME": "" - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Infrastructure/AzureFunctions/marketing-functions.csproj b/src/Services/Marketing/Infrastructure/AzureFunctions/marketing-functions.csproj deleted file mode 100644 index 33e93b625..000000000 --- a/src/Services/Marketing/Infrastructure/AzureFunctions/marketing-functions.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - net461 - - - - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - diff --git a/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs b/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs deleted file mode 100644 index 67ac1bca5..000000000 --- a/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs +++ /dev/null @@ -1,232 +0,0 @@ -using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Services; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers -{ - using System; - using System.Linq; - using System.Collections.Generic; - using Infrastructure.Repositories; - using AspNetCore.Mvc; - using Infrastructure; - using System.Threading.Tasks; - using Model; - using EntityFrameworkCore; - using Dto; - using AspNetCore.Authorization; - using Extensions.Options; - using Microsoft.eShopOnContainers.Services.Marketing.API.ViewModel; - using Microsoft.AspNetCore.Http; - using System.Net; - - [Route("api/v1/[controller]")] - [Authorize] - [ApiController] - public class CampaignsController : ControllerBase - { - private readonly MarketingContext _context; - private readonly MarketingSettings _settings; - private readonly IMarketingDataRepository _marketingDataRepository; - private readonly IIdentityService _identityService; - - public CampaignsController(MarketingContext context, - IMarketingDataRepository marketingDataRepository, - IOptionsSnapshot settings, - IIdentityService identityService) - { - _context = context; - _marketingDataRepository = marketingDataRepository; - _settings = settings.Value; - _identityService = identityService; - } - - [HttpGet] - [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] - public async Task>> GetAllCampaignsAsync() - { - var campaignList = await _context.Campaigns.ToListAsync(); - - if (campaignList is null) - { - return Ok(); - } - - return MapCampaignModelListToDtoList(campaignList); - } - - [HttpGet("{id:int}")] - [ProducesResponseType(typeof(CampaignDTO), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task> GetCampaignByIdAsync(int id) - { - var campaign = await _context.Campaigns.SingleOrDefaultAsync(c => c.Id == id); - - if (campaign is null) - { - return NotFound(); - } - - return MapCampaignModelToDto(campaign); - } - - [HttpPost] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.Created)] - public async Task CreateCampaignAsync([FromBody] CampaignDTO campaignDto) - { - if (campaignDto is null) - { - return BadRequest(); - } - - var campaign = MapCampaignDtoToModel(campaignDto); - - await _context.Campaigns.AddAsync(campaign); - await _context.SaveChangesAsync(); - - return CreatedAtAction(nameof(GetCampaignByIdAsync), new { id = campaign.Id }, null); - } - - [HttpPut("{id:int}")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - [ProducesResponseType((int)HttpStatusCode.Created)] - public async Task UpdateCampaignAsync(int id, [FromBody] CampaignDTO campaignDto) - { - if (id < 1 || campaignDto is null) - { - return BadRequest(); - } - - var campaignToUpdate = await _context.Campaigns.FindAsync(id); - if (campaignToUpdate is null) - { - return NotFound(); - } - - campaignToUpdate.Name = campaignDto.Name; - campaignToUpdate.Description = campaignDto.Description; - campaignToUpdate.From = campaignDto.From; - campaignToUpdate.To = campaignDto.To; - campaignToUpdate.PictureUri = campaignDto.PictureUri; - - await _context.SaveChangesAsync(); - - return CreatedAtAction(nameof(GetCampaignByIdAsync), new { id = campaignToUpdate.Id }, null); - } - - [HttpDelete("{id:int}")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - [ProducesResponseType((int)HttpStatusCode.NoContent)] - public async Task DeleteCampaignByIdAsync(int id) - { - if (id < 1) - { - return BadRequest(); - } - - var campaignToDelete = await _context.Campaigns.FindAsync(id); - - if (campaignToDelete is null) - { - return NotFound(); - } - - _context.Campaigns.Remove(campaignToDelete); - await _context.SaveChangesAsync(); - - return NoContent(); - } - - [HttpGet("user")] - [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] - public async Task>> GetCampaignsByUserIdAsync( int pageSize = 10, int pageIndex = 0) - { - var userId = _identityService.GetUserIdentity(); - - var marketingData = await _marketingDataRepository.GetAsync(userId.ToString()); - - var campaignDtoList = new List(); - - if (marketingData != null) - { - var locationIdCandidateList = marketingData.Locations.Select(x => x.LocationId); - var userCampaignList = await _context.Rules - .OfType() - .Include(c => c.Campaign) - .Where(c => c.Campaign.From <= DateTime.Now - && c.Campaign.To >= DateTime.Now - && locationIdCandidateList.Contains(c.LocationId)) - .Select(c => c.Campaign) - .ToListAsync(); - - if (userCampaignList != null && userCampaignList.Any()) - { - var userCampaignDtoList = MapCampaignModelListToDtoList(userCampaignList); - campaignDtoList.AddRange(userCampaignDtoList); - } - } - - var totalItems = campaignDtoList.Count(); - - campaignDtoList = campaignDtoList - .Skip(pageSize * pageIndex) - .Take(pageSize).ToList(); - - return new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, campaignDtoList); - } - - private List MapCampaignModelListToDtoList(List campaignList) - { - var campaignDtoList = new List(); - - campaignList.ForEach(campaign => campaignDtoList - .Add(MapCampaignModelToDto(campaign))); - - return campaignDtoList; - } - - private CampaignDTO MapCampaignModelToDto(Campaign campaign) - { - var userId = _identityService.GetUserIdentity(); - var dto = new CampaignDTO - { - Id = campaign.Id, - Name = campaign.Name, - Description = campaign.Description, - From = campaign.From, - To = campaign.To, - PictureUri = GetUriPlaceholder(campaign), - }; - - if (!string.IsNullOrEmpty(_settings.CampaignDetailFunctionUri)) - { - dto.DetailsUri = $"{_settings.CampaignDetailFunctionUri}&campaignId={campaign.Id}&userId={userId}"; - } - - return dto; - } - - private Campaign MapCampaignDtoToModel(CampaignDTO campaignDto) - { - return new Campaign - { - Id = campaignDto.Id, - Name = campaignDto.Name, - Description = campaignDto.Description, - From = campaignDto.From, - To = campaignDto.To, - PictureUri = campaignDto.PictureUri - }; - } - - private string GetUriPlaceholder(Campaign campaign) - { - var baseUri = _settings.PicBaseUrl; - - return _settings.AzureStorageEnabled - ? baseUri + campaign.PictureName - : baseUri.Replace("[0]", campaign.Id.ToString()); - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Controllers/HomeController.cs b/src/Services/Marketing/Marketing.API/Controllers/HomeController.cs deleted file mode 100644 index d37386b9a..000000000 --- a/src/Services/Marketing/Marketing.API/Controllers/HomeController.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers -{ - using Microsoft.AspNetCore.Mvc; - - // GET: // - public class HomeController : Controller - { - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Controllers/LocationsController.cs b/src/Services/Marketing/Marketing.API/Controllers/LocationsController.cs deleted file mode 100644 index 7d5959cb5..000000000 --- a/src/Services/Marketing/Marketing.API/Controllers/LocationsController.cs +++ /dev/null @@ -1,151 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers -{ - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Mvc; - using Microsoft.eShopOnContainers.Services.Marketing.API.Dto; - using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure; - using Microsoft.eShopOnContainers.Services.Marketing.API.Model; - using System.Collections.Generic; - using System.Linq; - using System.Net; - using System.Threading.Tasks; - - [Authorize] - [ApiController] - public class LocationsController : ControllerBase - { - private readonly MarketingContext _context; - - public LocationsController(MarketingContext context) - { - _context = context; - } - - [HttpGet] - [Route("api/v1/campaigns/{campaignId:int}/locations/{userLocationRuleId:int}")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - [ProducesResponseType(typeof(UserLocationRuleDTO),(int)HttpStatusCode.OK)] - public ActionResult GetLocationByCampaignAndLocationRuleId(int campaignId, - int userLocationRuleId) - { - if (campaignId < 1 || userLocationRuleId < 1) - { - return BadRequest(); - } - - var location = _context.Rules - .OfType() - .SingleOrDefault(c => c.CampaignId == campaignId && c.Id == userLocationRuleId); - - if (location is null) - { - return NotFound(); - } - - return MapUserLocationRuleModelToDto(location); - } - - [HttpGet] - [Route("api/v1/campaigns/{campaignId:int}/locations")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] - public ActionResult> GetAllLocationsByCampaignId(int campaignId) - { - if (campaignId < 1) - { - return BadRequest(); - } - - var locationList = _context.Rules - .OfType() - .Where(c => c.CampaignId == campaignId) - .ToList(); - - if(locationList is null) - { - return Ok(); - } - - return MapUserLocationRuleModelListToDtoList(locationList); - } - - [HttpPost] - [Route("api/v1/campaigns/{campaignId:int}/locations")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.Created)] - public async Task CreateLocationAsync(int campaignId, [FromBody] UserLocationRuleDTO locationRuleDto) - { - if (campaignId < 1 || locationRuleDto is null) - { - return BadRequest(); - } - - var locationRule = MapUserLocationRuleDtoToModel(locationRuleDto); - locationRule.CampaignId = campaignId; - - await _context.Rules.AddAsync(locationRule); - await _context.SaveChangesAsync(); - - return CreatedAtAction(nameof(GetLocationByCampaignAndLocationRuleId), - new { campaignId = campaignId, userLocationRuleId = locationRule.Id }, null); - } - - [HttpDelete] - [Route("api/v1/campaigns/{campaignId:int}/locations/{userLocationRuleId:int}")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task DeleteLocationByIdAsync(int campaignId, int userLocationRuleId) - { - if (campaignId < 1 || userLocationRuleId < 1) - { - return BadRequest(); - } - - var locationToDelete = _context.Rules - .OfType() - .SingleOrDefault(c => c.CampaignId == campaignId && c.Id == userLocationRuleId); - - if (locationToDelete is null) - { - return NotFound(); - } - - _context.Rules.Remove(locationToDelete); - await _context.SaveChangesAsync(); - - return NoContent(); - } - - private List MapUserLocationRuleModelListToDtoList(List userLocationRuleList) - { - var userLocationRuleDtoList = new List(); - - userLocationRuleList.ForEach(userLocationRule => userLocationRuleDtoList - .Add(MapUserLocationRuleModelToDto(userLocationRule))); - - return userLocationRuleDtoList; - } - - private UserLocationRuleDTO MapUserLocationRuleModelToDto(UserLocationRule userLocationRule) - { - return new UserLocationRuleDTO - { - Id = userLocationRule.Id, - Description = userLocationRule.Description, - LocationId = userLocationRule.LocationId - }; - } - - private UserLocationRule MapUserLocationRuleDtoToModel(UserLocationRuleDTO userLocationRuleDto) - { - return new UserLocationRule - { - Id = userLocationRuleDto.Id, - Description = userLocationRuleDto.Description, - LocationId = userLocationRuleDto.LocationId - }; - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Controllers/PicController.cs b/src/Services/Marketing/Marketing.API/Controllers/PicController.cs deleted file mode 100644 index 740f4975b..000000000 --- a/src/Services/Marketing/Marketing.API/Controllers/PicController.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers -{ - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Mvc; - using System.IO; - - [ApiController] - public class PicController : ControllerBase - { - private readonly IWebHostEnvironment _env; - public PicController(IWebHostEnvironment env) - { - _env = env; - } - - [HttpGet] - [Route("api/v1/campaigns/{campaignId:int}/pic")] - public ActionResult GetImage(int campaignId) - { - var webRoot = _env.WebRootPath; - var path = Path.Combine(webRoot, campaignId + ".png"); - - var buffer = System.IO.File.ReadAllBytes(path); - - return File(buffer, "image/png"); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Dockerfile b/src/Services/Marketing/Marketing.API/Dockerfile deleted file mode 100644 index e7a3f120b..000000000 --- a/src/Services/Marketing/Marketing.API/Dockerfile +++ /dev/null @@ -1,64 +0,0 @@ -FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base -WORKDIR /app -EXPOSE 80 - -FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build -WORKDIR /src - -# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles -# to take advantage of Docker's build cache, to speed up local container builds -COPY "eShopOnContainers-ServicesAndWebApps.sln" "eShopOnContainers-ServicesAndWebApps.sln" - -COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj" "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj" -COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" -COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" -COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" -COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" -COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" -COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" -COPY "BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj" "BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj" -COPY "Services/Basket/Basket.API/Basket.API.csproj" "Services/Basket/Basket.API/Basket.API.csproj" -COPY "Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj" "Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj" -COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" -COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" -COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" -COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" -COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" -COPY "Services/Location/Locations.API/Locations.API.csproj" "Services/Location/Locations.API/Locations.API.csproj" -COPY "Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj" "Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj" -COPY "Services/Marketing/Marketing.API/Marketing.API.csproj" "Services/Marketing/Marketing.API/Marketing.API.csproj" -COPY "Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj" "Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj" -COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" -COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" -COPY "Services/Ordering/Ordering.Domain/Ordering.Domain.csproj" "Services/Ordering/Ordering.Domain/Ordering.Domain.csproj" -COPY "Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj" "Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj" -COPY "Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj" "Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj" -COPY "Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj" "Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj" -COPY "Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj" "Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj" -COPY "Services/Payment/Payment.API/Payment.API.csproj" "Services/Payment/Payment.API/Payment.API.csproj" -COPY "Services/Webhooks/Webhooks.API/Webhooks.API.csproj" "Services/Webhooks/Webhooks.API/Webhooks.API.csproj" -COPY "Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj" "Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj" -COPY "Web/WebhookClient/WebhookClient.csproj" "Web/WebhookClient/WebhookClient.csproj" -COPY "Web/WebMVC/WebMVC.csproj" "Web/WebMVC/WebMVC.csproj" -COPY "Web/WebSPA/WebSPA.csproj" "Web/WebSPA/WebSPA.csproj" -COPY "Web/WebStatus/WebStatus.csproj" "Web/WebStatus/WebStatus.csproj" - -COPY "docker-compose.dcproj" "docker-compose.dcproj" - -COPY "NuGet.config" "NuGet.config" - -RUN dotnet restore "eShopOnContainers-ServicesAndWebApps.sln" - -COPY . . -WORKDIR /src/Services/Marketing/Marketing.API -RUN dotnet publish --no-restore -c Release -o /app - -FROM build as functionaltest -WORKDIR /src/Services/Marketing/Marketing.FunctionalTests - -FROM build AS publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app . -ENTRYPOINT ["dotnet", "Marketing.API.dll"] diff --git a/src/Services/Marketing/Marketing.API/Dockerfile.develop b/src/Services/Marketing/Marketing.API/Dockerfile.develop deleted file mode 100644 index 8425f47c1..000000000 --- a/src/Services/Marketing/Marketing.API/Dockerfile.develop +++ /dev/null @@ -1,18 +0,0 @@ -FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster -ARG BUILD_CONFIGURATION=Debug -ENV ASPNETCORE_ENVIRONMENT=Development -ENV DOTNET_USE_POLLING_FILE_WATCHER=true -EXPOSE 80 - -WORKDIR /src -COPY [Services/Marketing/Marketing.API/Marketing.API.csproj", "Services/Marketing/Marketing.API/"] -COPY [BuildingBlocks/EventBus/EventBus/EventBus.csproj", "BuildingBlocks/EventBus/EventBus/"] -COPY [BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj", "BuildingBlocks/EventBus/EventBusRabbitMQ/"] -COPY [BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj", "BuildingBlocks/EventBus/EventBusServiceBus/"] -COPY [BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj", "BuildingBlocks/WebHostCustomization/WebHost.Customization/"] -RUN dotnet restore Services/Marketing/Marketing.API/Marketing.API.csproj -nowarn:msb3202,nu1503 -COPY . . -WORKDIR "/src/Services/Marketing/Marketing.API" -RUN dotnet build --no-restore -c $BUILD_CONFIGURATION - -ENTRYPOINT ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"] diff --git a/src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs b/src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs deleted file mode 100644 index 3c409c8a9..000000000 --- a/src/Services/Marketing/Marketing.API/Dto/CampaignDTO.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Dto -{ - using System; - - public class CampaignDTO - { - public int Id { get; set; } - - public string Name { get; set; } - - public string Description { get; set; } - - public DateTime From { get; set; } - - public DateTime To { get; set; } - - public string PictureUri { get; set; } - public string DetailsUri { get; set; } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Dto/UserLocationDTO.cs b/src/Services/Marketing/Marketing.API/Dto/UserLocationDTO.cs deleted file mode 100644 index 3400b0dda..000000000 --- a/src/Services/Marketing/Marketing.API/Dto/UserLocationDTO.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Dto -{ - public class UserLocationDTO - { - public string Id { get; set; } - public Guid UserId { get; set; } - public int LocationId { get; set; } - public DateTime UpdateDate { get; set; } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Dto/UserLocationRuleDTO.cs b/src/Services/Marketing/Marketing.API/Dto/UserLocationRuleDTO.cs deleted file mode 100644 index a76eb90a0..000000000 --- a/src/Services/Marketing/Marketing.API/Dto/UserLocationRuleDTO.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Dto -{ - public class UserLocationRuleDTO - { - public int Id { get; set; } - - public int LocationId { get; set; } - - public string Description { get; set; } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/ActionResult/InternalServerErrorObjectResult.cs b/src/Services/Marketing/Marketing.API/Infrastructure/ActionResult/InternalServerErrorObjectResult.cs deleted file mode 100644 index 5975d92af..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/ActionResult/InternalServerErrorObjectResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.ActionResults -{ - using AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - - public class InternalServerErrorObjectResult : ObjectResult - { - public InternalServerErrorObjectResult(object error) - : base(error) - { - StatusCode = StatusCodes.Status500InternalServerError; - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/CampaignEntityTypeConfiguration.cs b/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/CampaignEntityTypeConfiguration.cs deleted file mode 100644 index 22292e53f..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/CampaignEntityTypeConfiguration.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Marketing.API.Model; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.EntityConfigurations -{ - class CampaignEntityTypeConfiguration - : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Campaign"); - - builder.HasKey(m => m.Id); - - builder.Property(m => m.Id) - .UseHiLo("campaign_hilo") - .IsRequired(); - - builder.Property(m => m.Name) - .HasColumnName("Name") - .IsRequired(); - - builder.Property(m => m.From) - .HasColumnName("From") - .IsRequired(); - - builder.Property(m => m.To) - .HasColumnName("To") - .IsRequired(); - - builder.Property(m => m.Description) - .HasColumnName("Description") - .IsRequired(); - - builder.Property(m => m.PictureUri) - .HasColumnName("PictureUri") - .IsRequired(); - - builder.HasMany(m => m.Rules) - .WithOne(r => r.Campaign) - .HasForeignKey(r => r.CampaignId) - .IsRequired(); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/RuleEntityTypeConfiguration.cs b/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/RuleEntityTypeConfiguration.cs deleted file mode 100644 index ebf1d1b3a..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/RuleEntityTypeConfiguration.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Marketing.API.Model; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.EntityConfigurations -{ - class RuleEntityTypeConfiguration - : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Rule"); - - builder.HasKey(r => r.Id); - - builder.Property(r => r.Id) - .UseHiLo("rule_hilo") - .IsRequired(); - - builder.HasDiscriminator("RuleTypeId") - .HasValue(RuleType.UserProfileRule.Id) - .HasValue(RuleType.PurchaseHistoryRule.Id) - .HasValue(RuleType.UserLocationRule.Id); - - builder.Property(r => r.Description) - .HasColumnName("Description") - .IsRequired(); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/UserLocationRuleEntityTypeConfiguration.cs b/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/UserLocationRuleEntityTypeConfiguration.cs deleted file mode 100644 index 84840d3a5..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/EntityConfigurations/UserLocationRuleEntityTypeConfiguration.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Marketing.API.Model; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.EntityConfigurations -{ - class UserLocationRuleEntityTypeConfiguration - : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.Property(r => r.LocationId) - .HasColumnName("LocationId") - .IsRequired(); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Exceptions/MarketingDomainException.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Exceptions/MarketingDomainException.cs deleted file mode 100644 index 68ccd9e52..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Exceptions/MarketingDomainException.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Exceptions -{ - using System; - - /// - /// Exception type for app exceptions - /// - public class MarketingDomainException : Exception - { - public MarketingDomainException() - { } - - public MarketingDomainException(string message) - : base(message) - { } - - public MarketingDomainException(string message, Exception innerException) - : base(message, innerException) - { } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs deleted file mode 100644 index d013597d9..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Filters -{ - public class AuthorizeCheckOperationFilter : IOperationFilter - { - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - // Check for authorize attribute - var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || - context.MethodInfo.GetCustomAttributes(true).OfType().Any(); - - if (!hasAuthorize) return; - - operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); - operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); - - var oAuthScheme = new OpenApiSecurityScheme - { - Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } - }; - - operation.Security = new List - { - new OpenApiSecurityRequirement - { - [ oAuthScheme ] = new [] { "marketingapi" } - } - }; - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs deleted file mode 100644 index 19c5ab038..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Filters -{ - using AspNetCore.Mvc; - using global::Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Exceptions; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Mvc.Filters; - using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.ActionResults; - using Microsoft.Extensions.Hosting; - using Microsoft.Extensions.Logging; - using System.Net; - - public class HttpGlobalExceptionFilter : IExceptionFilter - { - private readonly IWebHostEnvironment env; - private readonly ILogger logger; - - public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) - { - this.env = env; - this.logger = logger; - } - - public void OnException(ExceptionContext context) - { - logger.LogError(new EventId(context.Exception.HResult), - context.Exception, - context.Exception.Message); - - if (context.Exception.GetType() == typeof(MarketingDomainException)) - { - var json = new JsonErrorResponse - { - Messages = new[] { context.Exception.Message } - }; - - // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1 - //It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information - context.Result = new BadRequestObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - else - { - var json = new JsonErrorResponse - { - Messages = new[] { "An error occur.Try it again." } - }; - - if (env.IsDevelopment()) - { - json.DeveloperMessage = context.Exception; - } - - // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1 - // It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information - context.Result = new InternalServerErrorObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; - } - context.ExceptionHandled = true; - } - - private class JsonErrorResponse - { - public string[] Messages { get; set; } - - public object DeveloperMessage { get; set; } - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContext.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContext.cs deleted file mode 100644 index e06106b5e..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContext.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure -{ - using System; - using System.IO; - using EntityConfigurations; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Design; - using Microsoft.eShopOnContainers.Services.Marketing.API.Model; - using Microsoft.Extensions.Configuration; - - public class MarketingContext : DbContext - { - public MarketingContext(DbContextOptions options) : base(options) - { - } - - public DbSet Campaigns { get; set; } - - public DbSet Rules { get; set; } - - protected override void OnModelCreating(ModelBuilder builder) - { - builder.ApplyConfiguration(new CampaignEntityTypeConfiguration()); - builder.ApplyConfiguration(new RuleEntityTypeConfiguration()); - builder.ApplyConfiguration(new UserLocationRuleEntityTypeConfiguration()); - } - } - - public class MarketingContextDesignFactory : IDesignTimeDbContextFactory - { - public MarketingContext CreateDbContext(string[] args) - { - IConfigurationRoot configuration = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) - .AddEnvironmentVariables() - .Build(); - - var connectionString = configuration["ConnectionString"]; - var optionsBuilder = new DbContextOptionsBuilder() - .UseSqlServer(connectionString); - return new MarketingContext(optionsBuilder.Options); - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs deleted file mode 100644 index ac800909e..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs +++ /dev/null @@ -1,85 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure -{ - using Microsoft.eShopOnContainers.Services.Marketing.API.Model; - using Microsoft.Extensions.Logging; - using Polly; - using Polly.Retry; - using System; - using System.Collections.Generic; - using System.Data.SqlClient; - using System.Linq; - using System.Threading.Tasks; - - public class MarketingContextSeed - { - public async Task SeedAsync(MarketingContext context,ILogger logger,int retries = 3) - { - var policy = CreatePolicy(retries, logger, nameof(MarketingContextSeed)); - - await policy.ExecuteAsync(async () => - { - if (!context.Campaigns.Any()) - { - await context.Campaigns.AddRangeAsync( - GetPreconfiguredMarketings()); - - await context.SaveChangesAsync(); - } - }); - } - - private List GetPreconfiguredMarketings() - { - return new List - { - new Campaign - { - Name = ".NET Bot Black Hoodie 50% OFF", - Description = "Campaign Description 1", - From = DateTime.Now, - To = DateTime.Now.AddDays(7), - PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/campaigns/1/pic", - PictureName = "1.png", - Rules = new List - { - new UserLocationRule - { - Description = "Campaign is only for United States users.", - LocationId = 1 - } - } - }, - new Campaign - { - Name = "Roslyn Red T-Shirt 3x2", - Description = "Campaign Description 2", - From = DateTime.Now.AddDays(-7), - To = DateTime.Now.AddDays(14), - PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/campaigns/2/pic", - PictureName = "2.png", - Rules = new List - { - new UserLocationRule - { - Description = "Campaign is only for Seattle users.", - LocationId = 3 - } - } - } - }; - } - - private AsyncRetryPolicy CreatePolicy(int retries, ILogger logger, string prefix) - { - return Policy.Handle(). - WaitAndRetryAsync( - retryCount: retries, - sleepDurationProvider: retry => TimeSpan.FromSeconds(5), - onRetry: (exception, timeSpan, retry, ctx) => - { - logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", prefix, exception.GetType().Name, exception.Message, retry, retries); - } - ); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170615163431_Init.Designer.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170615163431_Init.Designer.cs deleted file mode 100644 index b4696a8f3..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170615163431_Init.Designer.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations -{ - [DbContext(typeof(MarketingContext))] - [Migration("20170615163431_Init")] - partial class Init - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.2") - .HasAnnotation("SqlServer:Sequence:.campaign_hilo", "'campaign_hilo', '', '1', '10', '', '', 'Int64', 'False'") - .HasAnnotation("SqlServer:Sequence:.rule_hilo", "'rule_hilo', '', '1', '10', '', '', 'Int64', 'False'") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:HiLoSequenceName", "campaign_hilo") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); - - b.Property("Description") - .IsRequired() - .HasColumnName("Description"); - - b.Property("From") - .HasColumnName("From"); - - b.Property("Name") - .IsRequired() - .HasColumnName("Name"); - - b.Property("PictureUri") - .IsRequired() - .HasColumnName("PictureUri"); - - b.Property("To") - .HasColumnName("To"); - - b.HasKey("Id"); - - b.ToTable("Campaign"); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:HiLoSequenceName", "rule_hilo") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); - - b.Property("CampaignId"); - - b.Property("Description") - .IsRequired() - .HasColumnName("Description"); - - b.Property("RuleTypeId"); - - b.HasKey("Id"); - - b.HasIndex("CampaignId"); - - b.ToTable("Rule"); - - b.HasDiscriminator("RuleTypeId"); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.PurchaseHistoryRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - - b.ToTable("PurchaseHistoryRule"); - - b.HasDiscriminator().HasValue(2); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserLocationRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - b.Property("LocationId") - .HasColumnName("LocationId"); - - b.ToTable("UserLocationRule"); - - b.HasDiscriminator().HasValue(3); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserProfileRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - - b.ToTable("UserProfileRule"); - - b.HasDiscriminator().HasValue(1); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b => - { - b.HasOne("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", "Campaign") - .WithMany("Rules") - .HasForeignKey("CampaignId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170615163431_Init.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170615163431_Init.cs deleted file mode 100644 index 92398f1a8..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170615163431_Init.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations -{ - public partial class Init : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateSequence( - name: "campaign_hilo", - incrementBy: 10); - - migrationBuilder.CreateSequence( - name: "rule_hilo", - incrementBy: 10); - - migrationBuilder.CreateTable( - name: "Campaign", - columns: table => new - { - Id = table.Column(nullable: false), - Description = table.Column(nullable: false), - From = table.Column(nullable: false), - Name = table.Column(nullable: false), - PictureUri = table.Column(nullable: false), - To = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Campaign", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Rule", - columns: table => new - { - Id = table.Column(nullable: false), - CampaignId = table.Column(nullable: false), - Description = table.Column(nullable: false), - RuleTypeId = table.Column(nullable: false), - LocationId = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Rule", x => x.Id); - table.ForeignKey( - name: "FK_Rule_Campaign_CampaignId", - column: x => x.CampaignId, - principalTable: "Campaign", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_Rule_CampaignId", - table: "Rule", - column: "CampaignId"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Rule"); - - migrationBuilder.DropTable( - name: "Campaign"); - - migrationBuilder.DropSequence( - name: "campaign_hilo"); - - migrationBuilder.DropSequence( - name: "rule_hilo"); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.Designer.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.Designer.cs deleted file mode 100644 index 342d1d02f..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.Designer.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations -{ - [DbContext(typeof(MarketingContext))] - [Migration("20170629102516_added-campaign-details")] - partial class addedcampaigndetails - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.2") - .HasAnnotation("SqlServer:Sequence:.campaign_hilo", "'campaign_hilo', '', '1', '10', '', '', 'Int64', 'False'") - .HasAnnotation("SqlServer:Sequence:.rule_hilo", "'rule_hilo', '', '1', '10', '', '', 'Int64', 'False'") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:HiLoSequenceName", "campaign_hilo") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); - - b.Property("Description") - .IsRequired() - .HasColumnName("Description"); - - b.Property("DetailsUri"); - - b.Property("From") - .HasColumnName("From"); - - b.Property("Name") - .IsRequired() - .HasColumnName("Name"); - - b.Property("PictureName"); - - b.Property("PictureUri") - .IsRequired() - .HasColumnName("PictureUri"); - - b.Property("To") - .HasColumnName("To"); - - b.HasKey("Id"); - - b.ToTable("Campaign"); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:HiLoSequenceName", "rule_hilo") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); - - b.Property("CampaignId"); - - b.Property("Description") - .IsRequired() - .HasColumnName("Description"); - - b.Property("RuleTypeId"); - - b.HasKey("Id"); - - b.HasIndex("CampaignId"); - - b.ToTable("Rule"); - - b.HasDiscriminator("RuleTypeId"); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.PurchaseHistoryRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - - b.ToTable("PurchaseHistoryRule"); - - b.HasDiscriminator().HasValue(2); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserLocationRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - b.Property("LocationId") - .HasColumnName("LocationId"); - - b.ToTable("UserLocationRule"); - - b.HasDiscriminator().HasValue(3); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserProfileRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - - b.ToTable("UserProfileRule"); - - b.HasDiscriminator().HasValue(1); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b => - { - b.HasOne("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", "Campaign") - .WithMany("Rules") - .HasForeignKey("CampaignId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.cs deleted file mode 100644 index 5b7c7ef6c..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/20170629102516_added-campaign-details.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations -{ - public partial class addedcampaigndetails : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "DetailsUri", - table: "Campaign", - nullable: true); - - migrationBuilder.AddColumn( - name: "PictureName", - table: "Campaign", - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "DetailsUri", - table: "Campaign"); - - migrationBuilder.DropColumn( - name: "PictureName", - table: "Campaign"); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/MarketingContextModelSnapshot.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/MarketingContextModelSnapshot.cs deleted file mode 100644 index a79055954..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingMigrations/MarketingContextModelSnapshot.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.MarketingMigrations -{ - [DbContext(typeof(MarketingContext))] - partial class MarketingContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.2") - .HasAnnotation("SqlServer:Sequence:.campaign_hilo", "'campaign_hilo', '', '1', '10', '', '', 'Int64', 'False'") - .HasAnnotation("SqlServer:Sequence:.rule_hilo", "'rule_hilo', '', '1', '10', '', '', 'Int64', 'False'") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:HiLoSequenceName", "campaign_hilo") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); - - b.Property("Description") - .IsRequired() - .HasColumnName("Description"); - - b.Property("DetailsUri"); - - b.Property("From") - .HasColumnName("From"); - - b.Property("Name") - .IsRequired() - .HasColumnName("Name"); - - b.Property("PictureName"); - - b.Property("PictureUri") - .IsRequired() - .HasColumnName("PictureUri"); - - b.Property("To") - .HasColumnName("To"); - - b.HasKey("Id"); - - b.ToTable("Campaign"); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:HiLoSequenceName", "rule_hilo") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); - - b.Property("CampaignId"); - - b.Property("Description") - .IsRequired() - .HasColumnName("Description"); - - b.Property("RuleTypeId"); - - b.HasKey("Id"); - - b.HasIndex("CampaignId"); - - b.ToTable("Rule"); - - b.HasDiscriminator("RuleTypeId"); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.PurchaseHistoryRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - - b.ToTable("PurchaseHistoryRule"); - - b.HasDiscriminator().HasValue(2); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserLocationRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - b.Property("LocationId") - .HasColumnName("LocationId"); - - b.ToTable("UserLocationRule"); - - b.HasDiscriminator().HasValue(3); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.UserProfileRule", b => - { - b.HasBaseType("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule"); - - - b.ToTable("UserProfileRule"); - - b.HasDiscriminator().HasValue(1); - }); - - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Rule", b => - { - b.HasOne("Microsoft.eShopOnContainers.Services.Marketing.API.Model.Campaign", "Campaign") - .WithMany("Rules") - .HasForeignKey("CampaignId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingReadDataContext.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingReadDataContext.cs deleted file mode 100644 index b16968617..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingReadDataContext.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure -{ - using Microsoft.eShopOnContainers.Services.Marketing.API.Model; - using Microsoft.Extensions.Options; - using MongoDB.Driver; - - public class MarketingReadDataContext - { - private readonly IMongoDatabase _database = null; - - public MarketingReadDataContext(IOptions settings) - { - var client = new MongoClient(settings.Value.MongoConnectionString); - - if (client != null) - { - _database = client.GetDatabase(settings.Value.MongoDatabase); - } - } - - public IMongoCollection MarketingData - { - get - { - return _database.GetCollection("MarketingReadDataModel"); - } - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs deleted file mode 100644 index 6f4ff16e2..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; -using System; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Middlewares -{ - class ByPassAuthMiddleware - { - private readonly RequestDelegate _next; - private string _currentUserId; - public ByPassAuthMiddleware(RequestDelegate next) - { - _next = next; - _currentUserId = null; - } - - - public async Task Invoke(HttpContext context) - { - var path = context.Request.Path; - if (path == "/noauth") - { - var userid = context.Request.Query["userid"]; - if (!string.IsNullOrEmpty(userid)) - { - _currentUserId = userid; - } - context.Response.StatusCode = 200; - context.Response.ContentType = "text/string"; - await context.Response.WriteAsync($"User set to {_currentUserId}"); - } - - else if (path == "/noauth/reset") - { - _currentUserId = null; - context.Response.StatusCode = 200; - context.Response.ContentType = "text/string"; - await context.Response.WriteAsync($"User set to none. Token required for protected endpoints."); - } - else - { - var currentUserId = _currentUserId; - - var authHeader = context.Request.Headers["Authorization"]; - if (authHeader != StringValues.Empty) - { - var header = authHeader.FirstOrDefault(); - if (!string.IsNullOrEmpty(header) && header.StartsWith("Email ") && header.Length > "Email ".Length) - { - currentUserId = header.Substring("Email ".Length); - } - } - - - if (!string.IsNullOrEmpty(currentUserId)) - { - var user = new ClaimsIdentity(new[] { - new Claim("emails", currentUserId), - new Claim("name", "Test user"), - new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "Test user"), - new Claim("nonce", Guid.NewGuid().ToString()), - new Claim("http://schemas.microsoft.com/identity/claims/identityprovider", "ByPassAuthMiddleware"), - new Claim("sub", currentUserId), - new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","User"), - new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Microsoft")} - , "ByPassAuth"); - - context.User = new ClaimsPrincipal(user); - } - - await _next.Invoke(context); - } - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Repositories/IMarketingDataRepository.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Repositories/IMarketingDataRepository.cs deleted file mode 100644 index 12a4bf2f8..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Repositories/IMarketingDataRepository.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Repositories -{ - using Model; - using System.Threading.Tasks; - - public interface IMarketingDataRepository - { - Task GetAsync(string userId); - Task UpdateLocationAsync(MarketingData marketingData); - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Repositories/MarketingDataRepository.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Repositories/MarketingDataRepository.cs deleted file mode 100644 index 4e531a84c..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Repositories/MarketingDataRepository.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Microsoft.eShopOnContainers.Services.Marketing.API.Model; -using Microsoft.Extensions.Options; -using MongoDB.Driver; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Repositories -{ - public class MarketingDataRepository - : IMarketingDataRepository - { - private readonly MarketingReadDataContext _context; - - public MarketingDataRepository(IOptions settings) - { - _context = new MarketingReadDataContext(settings); - } - - public async Task GetAsync(string userId) - { - var filter = Builders.Filter.Eq("UserId", userId); - return await _context.MarketingData - .Find(filter) - .FirstOrDefaultAsync(); - } - - public async Task UpdateLocationAsync(MarketingData marketingData) - { - var filter = Builders.Filter.Eq("UserId", marketingData.UserId); - var update = Builders.Update - .Set("Locations", marketingData.Locations) - .CurrentDate("UpdateDate"); - - await _context.MarketingData - .UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = true }); - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Services/IIdentityService.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Services/IIdentityService.cs deleted file mode 100644 index 42df49ebc..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Services/IIdentityService.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Services -{ - public interface IIdentityService - { - string GetUserIdentity(); - } -} diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Services/IdentityService.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Services/IdentityService.cs deleted file mode 100644 index 82ce214be..000000000 --- a/src/Services/Marketing/Marketing.API/Infrastructure/Services/IdentityService.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Services -{ - using AspNetCore.Http; - using System; - - public class IdentityService : IIdentityService - { - private IHttpContextAccessor _context; - - public IdentityService(IHttpContextAccessor context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } - - public string GetUserIdentity() - { - return _context.HttpContext.User.FindFirst("sub").Value; - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs b/src/Services/Marketing/Marketing.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs deleted file mode 100644 index b73e7b659..000000000 --- a/src/Services/Marketing/Marketing.API/IntegrationEvents/Events/UserLocationUpdatedIntegrationEvent.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.IntegrationEvents.Events -{ - using Marketing.API.Model; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using System.Collections.Generic; - - public class UserLocationUpdatedIntegrationEvent : IntegrationEvent - { - public string UserId { get; set; } - - public List LocationList { get; set; } - - public UserLocationUpdatedIntegrationEvent(string userId, List locationList) - { - UserId = userId; - LocationList = locationList; - } - } -} diff --git a/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs b/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs deleted file mode 100644 index 3d5e62e45..000000000 --- a/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.IntegrationEvents.Handlers -{ - using Marketing.API.IntegrationEvents.Events; - using Marketing.API.Model; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Repositories; - using Microsoft.Extensions.Logging; - using Serilog.Context; - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - - public class UserLocationUpdatedIntegrationEventHandler - : IIntegrationEventHandler - { - private readonly IMarketingDataRepository _marketingDataRepository; - private readonly ILogger _logger; - - public UserLocationUpdatedIntegrationEventHandler( - IMarketingDataRepository repository, - ILogger logger) - { - _marketingDataRepository = repository ?? throw new ArgumentNullException(nameof(repository)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } - - public async Task Handle(UserLocationUpdatedIntegrationEvent @event) - { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - - var userMarketingData = await _marketingDataRepository.GetAsync(@event.UserId); - userMarketingData = userMarketingData ?? - new MarketingData() { UserId = @event.UserId }; - - userMarketingData.Locations = MapUpdatedUserLocations(@event.LocationList); - await _marketingDataRepository.UpdateLocationAsync(userMarketingData); - } - } - - private List MapUpdatedUserLocations(List newUserLocations) - { - var result = new List(); - newUserLocations.ForEach(location => { - result.Add(new Location() - { - LocationId = location.LocationId, - Code = location.Code, - Description = location.Description - }); - }); - - return result; - } - } -} diff --git a/src/Services/Marketing/Marketing.API/Marketing.API.csproj b/src/Services/Marketing/Marketing.API/Marketing.API.csproj deleted file mode 100644 index bc3116fc3..000000000 --- a/src/Services/Marketing/Marketing.API/Marketing.API.csproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - netcoreapp3.1 - ..\..\..\..\docker-compose.dcproj - Microsoft.eShopOnContainers.Services.Marketing.API - $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; - false - true - aspnet-Marketing.API-20161122013619 - - /subscriptions/6c22bb55-0221-4ce4-9bf1-3c4a10a7294c/resourcegroups/eshop-log/providers/microsoft.insights/components/eshopappinsights - /subscriptions/6c22bb55-0221-4ce4-9bf1-3c4a10a7294c/resourcegroups/eshop-log/providers/microsoft.insights/components/eshopappinsights - preview - - - - - - - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - - - - diff --git a/src/Services/Marketing/Marketing.API/MarketingSettings.cs b/src/Services/Marketing/Marketing.API/MarketingSettings.cs deleted file mode 100644 index 20e5d9c44..000000000 --- a/src/Services/Marketing/Marketing.API/MarketingSettings.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API -{ - public class MarketingSettings - { - public string ConnectionString { get; set; } - public string MongoConnectionString { get; set; } - public string MongoDatabase { get; set; } - public string ExternalCatalogBaseUrl { get; set; } - public string CampaignDetailFunctionUri { get; set; } - public string PicBaseUrl { get; set; } - public bool AzureStorageEnabled { get; set; } - } -} diff --git a/src/Services/Marketing/Marketing.API/Model/Campaign.cs b/src/Services/Marketing/Marketing.API/Model/Campaign.cs deleted file mode 100644 index 841580427..000000000 --- a/src/Services/Marketing/Marketing.API/Model/Campaign.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model -{ - using System; - using System.Collections.Generic; - - public class Campaign - { - public int Id { get; set; } - - public string Name { get; set; } - - public string Description { get; set; } - - public DateTime From { get; set; } - - public DateTime To { get; set; } - - public string PictureName { get; set; } - - public string PictureUri { get; set; } - - public string DetailsUri { get; set; } - - public List Rules { get; set; } - - - public Campaign() - { - Rules = new List(); - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Model/Location.cs b/src/Services/Marketing/Marketing.API/Model/Location.cs deleted file mode 100644 index 6738e1dcf..000000000 --- a/src/Services/Marketing/Marketing.API/Model/Location.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model -{ - public class Location - { - public int LocationId { get; set; } - public string Code { get; set; } - public string Description { get; set; } - } -} diff --git a/src/Services/Marketing/Marketing.API/Model/MarketingData.cs b/src/Services/Marketing/Marketing.API/Model/MarketingData.cs deleted file mode 100644 index 638bffac6..000000000 --- a/src/Services/Marketing/Marketing.API/Model/MarketingData.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MongoDB.Bson; -using MongoDB.Bson.Serialization.Attributes; -using System; -using System.Collections.Generic; - -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model -{ - public class MarketingData - { - [BsonIgnoreIfDefault] - [BsonRepresentation(BsonType.ObjectId)] - public string Id { get; set; } - public string UserId { get; set; } - public List Locations { get; set; } - public DateTime UpdateDate { get; set; } - } -} diff --git a/src/Services/Marketing/Marketing.API/Model/Rule.cs b/src/Services/Marketing/Marketing.API/Model/Rule.cs deleted file mode 100644 index 6f9f23ef5..000000000 --- a/src/Services/Marketing/Marketing.API/Model/Rule.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model -{ - public abstract class Rule - { - public int Id { get; set; } - - public int CampaignId { get; set; } - - public Campaign Campaign { get; set; } - - public string Description { get; set; } - } - - - public class UserProfileRule : Rule - { - } - - public class PurchaseHistoryRule : Rule - { - } - - public class UserLocationRule : Rule - { - public int LocationId { get; set; } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Model/RuleType.cs b/src/Services/Marketing/Marketing.API/Model/RuleType.cs deleted file mode 100644 index 1fa569cbb..000000000 --- a/src/Services/Marketing/Marketing.API/Model/RuleType.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model -{ - using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Exceptions; - using System; - using System.Collections.Generic; - using System.Linq; - - public sealed class RuleType - { - public static readonly RuleType UserProfileRule = new RuleType(1, nameof(UserProfileRule)); - public static readonly RuleType PurchaseHistoryRule = new RuleType(2, nameof(UserProfileRule)); - public static readonly RuleType UserLocationRule = new RuleType(3, nameof(UserProfileRule)); - - public readonly int Id; - public readonly string Name; - - private RuleType(int id, string name) - { - Id = id; - Name = name; - } - - public static IEnumerable List() => - new[] { UserProfileRule, PurchaseHistoryRule, UserLocationRule }; - - public static RuleType FromName(string name) - { - var state = List() - .SingleOrDefault(s => String.Equals(s.Name, name, StringComparison.CurrentCultureIgnoreCase)); - - if (state == null) - { - throw new MarketingDomainException($"Possible values for RuleType: {String.Join(",", List().Select(s => s.Name))}"); - } - - return state; - } - - public static RuleType From(int id) - { - var state = List().SingleOrDefault(s => s.Id == id); - - if (state == null) - { - throw new MarketingDomainException($"Possible values for RuleType: {String.Join(",", List().Select(s => s.Name))}"); - } - - return state; - } - } -} \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Model/UserLocationDetails.cs b/src/Services/Marketing/Marketing.API/Model/UserLocationDetails.cs deleted file mode 100644 index e6d7fe305..000000000 --- a/src/Services/Marketing/Marketing.API/Model/UserLocationDetails.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model -{ - public class UserLocationDetails - { - public int LocationId { get; set; } - public string Code { get; set; } - public string Description { get; set; } - } -} diff --git a/src/Services/Marketing/Marketing.API/Pics/1.png b/src/Services/Marketing/Marketing.API/Pics/1.png deleted file mode 100644 index 22a6a946f8e8ba387c041bab215e4a842d897a10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139617 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