Merge Netcore2.2 branch
This commit is contained in:
commit
b9dcc80acd
3
.gitignore
vendored
3
.gitignore
vendored
@ -263,3 +263,6 @@ pub/
|
|||||||
/src/Web/WebMVC/wwwroot/css/site.min.css
|
/src/Web/WebMVC/wwwroot/css/site.min.css
|
||||||
**/.kube/**
|
**/.kube/**
|
||||||
.mfractor
|
.mfractor
|
||||||
|
|
||||||
|
# Ignore HealthCheckdb
|
||||||
|
*healthchecksdb*
|
@ -4,6 +4,9 @@
|
|||||||
<add key="repositoryPath" value="packages" />
|
<add key="repositoryPath" value="packages" />
|
||||||
</config>
|
</config>
|
||||||
<packageSources>
|
<packageSources>
|
||||||
|
<add key="Preview-aspnetcore-tools" value="https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json"/>
|
||||||
|
<add key="Preview-aspnetcore-dev" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json"/>
|
||||||
|
<add key="Preview-aspnetcore" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json"/>
|
||||||
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnet-feb2017-patch/api/v3/index.json" />
|
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnet-feb2017-patch/api/v3/index.json" />
|
||||||
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
||||||
</packageSources>
|
</packageSources>
|
||||||
|
@ -187,6 +187,17 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||||
|
- urls__basket=http://basket.api
|
||||||
|
- urls__catalog=http://catalog.api
|
||||||
|
- urls__orders=http://ordering.api
|
||||||
|
- urls__identity=http://identity.api
|
||||||
|
- CatalogUrlHC=http://catalog.api/hc
|
||||||
|
- OrderingUrlHC=http://ordering.api/hc
|
||||||
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
|
- BasketUrlHC=http://basket.api/hc
|
||||||
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
|
- LocationUrlHC=http://locations.api/hc
|
||||||
ports:
|
ports:
|
||||||
- "5200:80"
|
- "5200:80"
|
||||||
volumes:
|
volumes:
|
||||||
@ -196,6 +207,13 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||||
|
- CatalogUrlHC=http://catalog.api/hc
|
||||||
|
- OrderingUrlHC=http://ordering.api/hc
|
||||||
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
|
- BasketUrlHC=http://basket.api/hc
|
||||||
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
|
- LocationUrlHC=http://locations.api/hc
|
||||||
ports:
|
ports:
|
||||||
- "5201:80"
|
- "5201:80"
|
||||||
volumes:
|
volumes:
|
||||||
@ -205,6 +223,13 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||||
|
- CatalogUrlHC=http://catalog.api/hc
|
||||||
|
- OrderingUrlHC=http://ordering.api/hc
|
||||||
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
|
- BasketUrlHC=http://basket.api/hc
|
||||||
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
|
- LocationUrlHC=http://locations.api/hc
|
||||||
ports:
|
ports:
|
||||||
- "5202:80"
|
- "5202:80"
|
||||||
volumes:
|
volumes:
|
||||||
@ -214,6 +239,13 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||||
|
- CatalogUrlHC=http://catalog.api/hc
|
||||||
|
- OrderingUrlHC=http://ordering.api/hc
|
||||||
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
|
- BasketUrlHC=http://basket.api/hc
|
||||||
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
|
- LocationUrlHC=http://locations.api/hc
|
||||||
ports:
|
ports:
|
||||||
- "5203:80"
|
- "5203:80"
|
||||||
volumes:
|
volumes:
|
||||||
@ -226,6 +258,13 @@ services:
|
|||||||
- urls__catalog=http://catalog.api
|
- urls__catalog=http://catalog.api
|
||||||
- urls__orders=http://ordering.api
|
- urls__orders=http://ordering.api
|
||||||
- urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
- urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||||
|
- CatalogUrlHC=http://catalog.api/hc
|
||||||
|
- OrderingUrlHC=http://ordering.api/hc
|
||||||
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
|
- BasketUrlHC=http://basket.api/hc
|
||||||
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
|
- LocationUrlHC=http://locations.api/hc
|
||||||
ports:
|
ports:
|
||||||
- "5120:80" # Important: In a production environment your should remove the external port (5120) kept here for microservice debugging purposes.
|
- "5120:80" # Important: In a production environment your should remove the external port (5120) kept here for microservice debugging purposes.
|
||||||
# The API Gateway redirects and access through the internal port (80).
|
# The API Gateway redirects and access through the internal port (80).
|
||||||
@ -237,6 +276,13 @@ services:
|
|||||||
- urls__catalog=http://catalog.api
|
- urls__catalog=http://catalog.api
|
||||||
- urls__orders=http://ordering.api
|
- urls__orders=http://ordering.api
|
||||||
- urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
- urls__identity=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
|
||||||
|
- CatalogUrlHC=http://catalog.api/hc
|
||||||
|
- OrderingUrlHC=http://ordering.api/hc
|
||||||
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
|
- BasketUrlHC=http://basket.api/hc
|
||||||
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
|
- LocationUrlHC=http://locations.api/hc
|
||||||
ports:
|
ports:
|
||||||
- "5121:80" # Important: In a production environment your should remove the external port (5121) kept here for microservice debugging purposes.
|
- "5121:80" # Important: In a production environment your should remove the external port (5121) kept here for microservice debugging purposes.
|
||||||
# The API Gateway redirects and access through the internal port (80).
|
# The API Gateway redirects and access through the internal port (80).
|
||||||
@ -259,16 +305,41 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- ASPNETCORE_URLS=http://0.0.0.0:80
|
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||||
- CatalogUrl=http://catalog.api/hc
|
- HealthChecks-UI__HealthChecks__1__Name=WebMVC HTTP Check
|
||||||
- OrderingUrl=http://ordering.api/hc
|
- HealthChecks-UI__HealthChecks__1__Uri=http://webmvc/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__2__Name=WebSPA HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__2__Uri=http://webspa/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__3__Name=Web Shopping Aggregator GW HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__3__Uri=http://webshoppingagg/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__4__Name=Mobile Shopping Aggregator HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__4__Uri=http://mobileshoppingagg/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__5__Name=Mobile Shopping API GW HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__5__Uri=http://mobileshoppingapigw/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__6__Name=Mobile Marketing API GW HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__6__Uri=http://mobilemarketingapigw/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__7__Name=Web Shopping API GW HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__7__Uri=http://webshoppingapigw/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__8__Name=Web Marketing API GW HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__8__Uri=http://webmarketingapigw/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__9__Name=Ordering HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__9__Uri=http://ordering.api/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__10__Name=Ordering HTTP Background Check
|
||||||
|
- HealthChecks-UI__HealthChecks__10__Uri=http://ordering.backgroundtasks/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__11__Name=Basket HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__11__Uri=http://basket.api/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__12__Name=Catalog HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__12__Uri=http://catalog.api/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__13__Name=Identity HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__13__Uri=http://identity.api/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__14__Name=Marketing HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__14__Uri=http://marketing.api/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__15__Name=Locations HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__15__Uri=http://locations.api/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__16__Name=Payments HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__16__Uri=http://payment.api/hc
|
||||||
|
- HealthChecks-UI__HealthChecks__17__Name=Ordering SignalRHub HTTP Check
|
||||||
|
- HealthChecks-UI__HealthChecks__17__Uri=http://ordering.signalrhub/hc
|
||||||
- OrderingBackgroundTasksUrl=http://ordering.backgroundtasks/hc
|
- OrderingBackgroundTasksUrl=http://ordering.backgroundtasks/hc
|
||||||
- BasketUrl=http://basket.api/hc
|
|
||||||
- IdentityUrl=http://identity.api/hc
|
|
||||||
- LocationsUrl=http://locations.api/hc
|
|
||||||
- MarketingUrl=http://marketing.api/hc
|
|
||||||
- PaymentUrl=http://payment.api/hc
|
|
||||||
- mvc=http://webmvc/hc
|
|
||||||
- spa=http://webspa/hc
|
|
||||||
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
||||||
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
||||||
ports:
|
ports:
|
||||||
@ -281,12 +352,9 @@ services:
|
|||||||
- IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
- IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
- PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
|
- PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
|
||||||
- MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5203
|
- MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5203
|
||||||
- CatalogUrlHC=http://catalog.api/hc
|
- PurchaseUrlHC=http://webshoppingapigw/hc
|
||||||
- OrderingUrlHC=http://ordering.api/hc
|
- MarketingUrlHC=http://webmarketingapigw/hc
|
||||||
- IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser.
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
- BasketUrlHC=http://basket.api/hc
|
|
||||||
- MarketingUrlHC=http://marketing.api/hc
|
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
|
||||||
- UseCustomizationData=True
|
- UseCustomizationData=True
|
||||||
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
||||||
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
||||||
@ -300,14 +368,11 @@ services:
|
|||||||
- ASPNETCORE_URLS=http://0.0.0.0:80
|
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||||
- PurchaseUrl=http://webshoppingapigw
|
- PurchaseUrl=http://webshoppingapigw
|
||||||
- IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser.
|
- IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser.
|
||||||
- MarketingUrl=http://webmarketingapigw
|
- MarketingUrl=http://webmarketingapigw
|
||||||
- CatalogUrlHC=http://catalog.api/hc
|
|
||||||
- OrderingUrlHC=http://ordering.api/hc
|
|
||||||
- IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser.
|
|
||||||
- BasketUrlHC=http://basket.api/hc
|
|
||||||
- MarketingUrlHC=http://marketing.api/hc
|
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
|
||||||
- SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
|
- SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
|
||||||
|
- IdentityUrlHC=http://identity.api/hc
|
||||||
|
- PurchaseUrlHC=http://webshoppingapigw/hc
|
||||||
|
- MarketingUrlHC=http://webmarketingapigw/hc
|
||||||
- UseCustomizationData=True
|
- UseCustomizationData=True
|
||||||
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
||||||
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
||||||
|
@ -56,16 +56,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBusRabbitMQ", "src\Bui
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationEventLogEF", "src\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj", "{9EE28E45-1533-472B-8267-56C48855BA0E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationEventLogEF", "src\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj", "{9EE28E45-1533-472B-8267-56C48855BA0E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HealthChecks", "HealthChecks", "{A81ECBC2-6B00-4DCD-8388-469174033379}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj", "{942ED6E8-0050-495F-A0EA-01E97F63760C}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebStatus", "src\Web\WebStatus\WebStatus.csproj", "{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebStatus", "src\Web\WebStatus\WebStatus.csproj", "{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HealthChecks", "src\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj", "{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.SqlServer", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj", "{4BD76717-3102-4969-8C2C-BAAA3F0263B6}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41139F64-4046-4F16-96B7-D941D96FA9C6}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41139F64-4046-4F16-96B7-D941D96FA9C6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}"
|
||||||
@ -76,8 +68,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marketing.API", "src\Servic
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBusServiceBus", "src\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj", "{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBusServiceBus", "src\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj", "{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.AzureStorage", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj", "{768C887F-C229-4B94-ACD8-0C7F65686524}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{1815B651-941C-466B-AE33-D1D7EEB8F77F}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{1815B651-941C-466B-AE33-D1D7EEB8F77F}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{15F4B3AA-89B6-4A0D-9051-414305974781}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{15F4B3AA-89B6-4A0D-9051-414305974781}"
|
||||||
@ -644,54 +634,6 @@ Global
|
|||||||
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x64.Build.0 = Release|Any CPU
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.ActiveCfg = Release|Any CPU
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.Build.0 = Release|Any CPU
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x64.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.AppStore|x86.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|ARM.ActiveCfg = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|ARM.Build.0 = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhone.ActiveCfg = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhone.Build.0 = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
@ -740,102 +682,6 @@ Global
|
|||||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x64.Build.0 = Release|Any CPU
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.ActiveCfg = Release|Any CPU
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.Build.0 = Release|Any CPU
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|x64.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.AppStore|x86.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|ARM.ActiveCfg = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|ARM.Build.0 = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|iPhone.ActiveCfg = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|iPhone.Build.0 = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|x64.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.AppStore|x86.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|ARM.ActiveCfg = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|ARM.Build.0 = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|iPhone.ActiveCfg = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|iPhone.Build.0 = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
{E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
@ -980,54 +826,6 @@ Global
|
|||||||
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x64.Build.0 = Release|Any CPU
|
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x86.ActiveCfg = Release|Any CPU
|
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x86.Build.0 = Release|Any CPU
|
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|x64.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.AppStore|x86.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|ARM.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|iPhone.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|ARM.ActiveCfg = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|ARM.Build.0 = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|iPhone.ActiveCfg = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|iPhone.Build.0 = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
{15F4B3AA-89B6-4A0D-9051-414305974781}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
@ -1869,17 +1667,12 @@ Global
|
|||||||
{0044B293-1DCC-4224-B948-00CF6DC7F510} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
{0044B293-1DCC-4224-B948-00CF6DC7F510} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
{8088F3FC-6787-45FA-A924-816EC81CBFAC} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
{9EE28E45-1533-472B-8267-56C48855BA0E} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
{9EE28E45-1533-472B-8267-56C48855BA0E} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
{A81ECBC2-6B00-4DCD-8388-469174033379} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
|
||||||
{942ED6E8-0050-495F-A0EA-01E97F63760C} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
|
||||||
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
|
{C0A7918D-B4F2-4E7F-8DE2-1E5279EF079F} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
|
||||||
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
|
||||||
{4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
|
||||||
{41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
|
{41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
|
||||||
{E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6}
|
{E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6}
|
||||||
{A5260DE0-1FDD-467E-9CC1-A028AB081CEE} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
|
{A5260DE0-1FDD-467E-9CC1-A028AB081CEE} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
|
||||||
{DF395F85-B010-465D-857A-7EBCC512C0C2} = {A5260DE0-1FDD-467E-9CC1-A028AB081CEE}
|
{DF395F85-B010-465D-857A-7EBCC512C0C2} = {A5260DE0-1FDD-467E-9CC1-A028AB081CEE}
|
||||||
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
{768C887F-C229-4B94-ACD8-0C7F65686524} = {A81ECBC2-6B00-4DCD-8388-469174033379}
|
|
||||||
{1815B651-941C-466B-AE33-D1D7EEB8F77F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
{1815B651-941C-466B-AE33-D1D7EEB8F77F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
||||||
{15F4B3AA-89B6-4A0D-9051-414305974781} = {1815B651-941C-466B-AE33-D1D7EEB8F77F}
|
{15F4B3AA-89B6-4A0D-9051-414305974781} = {1815B651-941C-466B-AE33-D1D7EEB8F77F}
|
||||||
{77849D35-37D4-4802-81DC-9477B2775A40} = {932D8224-11F6-4D07-B109-DA28AD288A63}
|
{77849D35-37D4-4802-81DC-9477B2775A40} = {932D8224-11F6-4D07-B109-DA28AD288A63}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"sdk": {
|
"sdk": {
|
||||||
"version": "2.1.401"
|
"version": "2.2.100"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,4 +11,11 @@ metadata:
|
|||||||
heritage: {{ .Release.Service }}
|
heritage: {{ .Release.Service }}
|
||||||
data:
|
data:
|
||||||
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
||||||
|
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
||||||
|
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
|
||||||
|
|
||||||
|
@ -32,6 +32,20 @@ env:
|
|||||||
configmap:
|
configmap:
|
||||||
- name: IdentityUrl
|
- name: IdentityUrl
|
||||||
key: internalurls__identity
|
key: internalurls__identity
|
||||||
|
- name: CatalogUrlHC
|
||||||
|
key: internalurls__catalog__hc
|
||||||
|
- name: BasketUrlHC
|
||||||
|
key: internalurls__basket__hc
|
||||||
|
- name: IdentityUrlHC
|
||||||
|
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
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
values:
|
values:
|
||||||
- name: ASPNETCORE_ENVIRONMENT
|
- name: ASPNETCORE_ENVIRONMENT
|
||||||
|
@ -11,4 +11,11 @@ metadata:
|
|||||||
heritage: {{ .Release.Service }}
|
heritage: {{ .Release.Service }}
|
||||||
data:
|
data:
|
||||||
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
||||||
|
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
||||||
|
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
|
||||||
|
|
||||||
|
@ -32,6 +32,20 @@ env:
|
|||||||
configmap:
|
configmap:
|
||||||
- name: IdentityUrl
|
- name: IdentityUrl
|
||||||
key: internalurls__identity
|
key: internalurls__identity
|
||||||
|
- name: CatalogUrlHC
|
||||||
|
key: internalurls__catalog__hc
|
||||||
|
- name: BasketUrlHC
|
||||||
|
key: internalurls__basket__hc
|
||||||
|
- name: IdentityUrlHC
|
||||||
|
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
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
values:
|
values:
|
||||||
- name: ASPNETCORE_ENVIRONMENT
|
- name: ASPNETCORE_ENVIRONMENT
|
||||||
|
@ -11,4 +11,11 @@ metadata:
|
|||||||
heritage: {{ .Release.Service }}
|
heritage: {{ .Release.Service }}
|
||||||
data:
|
data:
|
||||||
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
||||||
|
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
||||||
|
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
|
||||||
|
|
||||||
|
@ -32,6 +32,20 @@ env:
|
|||||||
configmap:
|
configmap:
|
||||||
- name: IdentityUrl
|
- name: IdentityUrl
|
||||||
key: internalurls__identity
|
key: internalurls__identity
|
||||||
|
- name: CatalogUrlHC
|
||||||
|
key: internalurls__catalog__hc
|
||||||
|
- name: BasketUrlHC
|
||||||
|
key: internalurls__basket__hc
|
||||||
|
- name: IdentityUrlHC
|
||||||
|
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
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
values:
|
values:
|
||||||
- name: ASPNETCORE_ENVIRONMENT
|
- name: ASPNETCORE_ENVIRONMENT
|
||||||
|
@ -11,4 +11,11 @@ metadata:
|
|||||||
heritage: {{ .Release.Service }}
|
heritage: {{ .Release.Service }}
|
||||||
data:
|
data:
|
||||||
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
||||||
|
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
||||||
|
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
|
||||||
|
|
||||||
|
@ -32,6 +32,20 @@ env:
|
|||||||
configmap:
|
configmap:
|
||||||
- name: IdentityUrl
|
- name: IdentityUrl
|
||||||
key: internalurls__identity
|
key: internalurls__identity
|
||||||
|
- name: CatalogUrlHC
|
||||||
|
key: internalurls__catalog__hc
|
||||||
|
- name: BasketUrlHC
|
||||||
|
key: internalurls__basket__hc
|
||||||
|
- name: IdentityUrlHC
|
||||||
|
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
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
values:
|
values:
|
||||||
- name: ASPNETCORE_ENVIRONMENT
|
- name: ASPNETCORE_ENVIRONMENT
|
||||||
|
@ -14,6 +14,8 @@ inf:
|
|||||||
db: OrderingDb # Ordering API SQL db name
|
db: OrderingDb # Ordering API SQL db name
|
||||||
identity:
|
identity:
|
||||||
db: IdentityDb # Ordering API SQL db name
|
db: IdentityDb # Ordering API SQL db name
|
||||||
|
marketing:
|
||||||
|
db: MarketingDb # Marketing API SQL db name
|
||||||
mongo:
|
mongo:
|
||||||
# host: my-nosql-data # Uncomment to use specify custom mongo host. By default nosql-data is used
|
# host: my-nosql-data # Uncomment to use specify custom mongo host. By default nosql-data is used
|
||||||
locations:
|
locations:
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}}
|
{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}}
|
||||||
{{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}}
|
{{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}}
|
||||||
{{- $mongo := include "mongo-name" . -}}
|
{{- $mongo := include "mongo-name" . -}}
|
||||||
|
{{- $sqlsrv := include "sql-name" . -}}
|
||||||
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
@ -19,6 +20,7 @@ data:
|
|||||||
all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}"
|
all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}"
|
||||||
internalurls__IdentityUrl: http://{{ .Values.app.svc.identity }}
|
internalurls__IdentityUrl: http://{{ .Values.app.svc.identity }}
|
||||||
urls__IdentityUrl: {{ $identity }}
|
urls__IdentityUrl: {{ $identity }}
|
||||||
marketing__ConnectionString: mongodb://{{ $mongo }}
|
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__Database: {{ .Values.inf.mongo.marketing.database }}
|
marketing__MongoConnectionString: mongodb://{{ $mongo }}
|
||||||
|
marketing__MongoDatabase: {{ .Values.inf.mongo.marketing.database }}
|
||||||
marketing__PicBaseUrl: http://{{ $webshoppingapigw }}/api/v1/c/catalog/items/[0]/pic/
|
marketing__PicBaseUrl: http://{{ $webshoppingapigw }}/api/v1/c/catalog/items/[0]/pic/
|
@ -44,8 +44,10 @@ env:
|
|||||||
key: urls__IdentityUrl
|
key: urls__IdentityUrl
|
||||||
- name: ConnectionString
|
- name: ConnectionString
|
||||||
key: marketing__ConnectionString
|
key: marketing__ConnectionString
|
||||||
- name: Database
|
- name: MongoConnectionString
|
||||||
key: marketing__Database
|
key: marketing__MongoConnectionString
|
||||||
|
- name: MongoDatabase
|
||||||
|
key: marketing__MongoDatabase
|
||||||
- name: PicBaseUrl
|
- name: PicBaseUrl
|
||||||
key: marketing__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 define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
|
@ -17,3 +17,10 @@ data:
|
|||||||
internalurls__catalog: http://{{ .Values.app.svc.catalog }}
|
internalurls__catalog: http://{{ .Values.app.svc.catalog }}
|
||||||
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
||||||
internalurls__ordering: http://{{ .Values.app.svc.ordering }}
|
internalurls__ordering: http://{{ .Values.app.svc.ordering }}
|
||||||
|
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
||||||
|
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
|
||||||
|
@ -40,6 +40,20 @@ env:
|
|||||||
key: internalurls__ordering
|
key: internalurls__ordering
|
||||||
- name: urls__identity
|
- name: urls__identity
|
||||||
key: internalurls__identity
|
key: internalurls__identity
|
||||||
|
- name: CatalogUrlHC
|
||||||
|
key: internalurls__catalog__hc
|
||||||
|
- name: BasketUrlHC
|
||||||
|
key: internalurls__basket__hc
|
||||||
|
- name: IdentityUrlHC
|
||||||
|
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
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
values:
|
values:
|
||||||
- name: ASPNETCORE_ENVIRONMENT
|
- name: ASPNETCORE_ENVIRONMENT
|
||||||
|
@ -21,12 +21,9 @@ data:
|
|||||||
webmvc__keystore: {{ .Values.inf.redis.keystore.constr }}
|
webmvc__keystore: {{ .Values.inf.redis.keystore.constr }}
|
||||||
internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }}
|
internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }}
|
||||||
internalurls__apigwwm: http://{{ .Values.app.svc.webmarketingapigw }}
|
internalurls__apigwwm: http://{{ .Values.app.svc.webmarketingapigw }}
|
||||||
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
internalurls__apigwws__hc: http://{{ .Values.app.svc.webshoppingapigw }}/hc
|
||||||
internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc
|
|
||||||
internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc
|
internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc
|
||||||
internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc
|
internalurls__apigwwm__hc: http://{{ .Values.app.svc.webmarketingapigw }}/hc
|
||||||
internalurls__marketing__hc: http://{{ .Values.app.svc.marketing }}/hc
|
|
||||||
internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc
|
|
||||||
urls__apigwws: http://{{ $webshoppingapigw }}
|
urls__apigwws: http://{{ $webshoppingapigw }}
|
||||||
urls__mvc: http://{{ $mvc }}
|
urls__mvc: http://{{ $mvc }}
|
||||||
urls__IdentityUrl: http://{{ $identity }}
|
urls__IdentityUrl: http://{{ $identity }}
|
||||||
|
@ -46,18 +46,12 @@ env:
|
|||||||
key: urls__IdentityUrl
|
key: urls__IdentityUrl
|
||||||
- name: MarketingUrl
|
- name: MarketingUrl
|
||||||
key: internalurls__apigwwm
|
key: internalurls__apigwwm
|
||||||
- name: BasketUrlHC
|
- name: PurchaseUrlHC
|
||||||
key: internalurls__basket__hc
|
key: internalurls__apigwws__hc
|
||||||
- name: CatalogUrlHC
|
|
||||||
key: internalurls__catalog__hc
|
|
||||||
- name: IdentityUrlHC
|
- name: IdentityUrlHC
|
||||||
key: internalurls__identity__hc
|
key: internalurls__identity__hc
|
||||||
- name: OrderingUrlHC
|
|
||||||
key: internalurls__ordering__hc
|
|
||||||
- name: MarketingUrlHC
|
- name: MarketingUrlHC
|
||||||
key: internalurls__marketing__hc
|
key: internalurls__apigwwm__hc
|
||||||
- name: PaymentUrlHC
|
|
||||||
key: internalurls__payment__hc
|
|
||||||
- name: SignalrHubUrl
|
- name: SignalrHubUrl
|
||||||
key: urls__apigwws
|
key: urls__apigwws
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
|
@ -17,3 +17,10 @@ data:
|
|||||||
internalurls__catalog: http://{{ .Values.app.svc.catalog }}
|
internalurls__catalog: http://{{ .Values.app.svc.catalog }}
|
||||||
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
internalurls__identity: http://{{ .Values.app.svc.identity }}
|
||||||
internalurls__ordering: http://{{ .Values.app.svc.ordering }}
|
internalurls__ordering: http://{{ .Values.app.svc.ordering }}
|
||||||
|
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
||||||
|
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
|
||||||
|
@ -40,6 +40,20 @@ env:
|
|||||||
key: internalurls__ordering
|
key: internalurls__ordering
|
||||||
- name: urls__identity
|
- name: urls__identity
|
||||||
key: internalurls__identity
|
key: internalurls__identity
|
||||||
|
- name: CatalogUrlHC
|
||||||
|
key: internalurls__catalog__hc
|
||||||
|
- name: BasketUrlHC
|
||||||
|
key: internalurls__basket__hc
|
||||||
|
- name: IdentityUrlHC
|
||||||
|
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
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
values:
|
values:
|
||||||
- name: ASPNETCORE_ENVIRONMENT
|
- name: ASPNETCORE_ENVIRONMENT
|
||||||
|
@ -20,12 +20,9 @@ data:
|
|||||||
all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}"
|
all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}"
|
||||||
webspa__keystore: {{ .Values.inf.redis.keystore.constr }}
|
webspa__keystore: {{ .Values.inf.redis.keystore.constr }}
|
||||||
internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }}
|
internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }}
|
||||||
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
internalurls__apigwws__hc: http://{{ .Values.app.svc.webshoppingapigw }}/hc
|
||||||
internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc
|
|
||||||
internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc
|
internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc
|
||||||
internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc
|
internalurls__apigwwm__hc: http://{{ .Values.app.svc.webmarketingapigw }}/hc
|
||||||
internalurls__marketing__hc: http://{{ .Values.app.svc.marketing }}/hc
|
|
||||||
internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc
|
|
||||||
urls__apigwws: http://{{ $webshoppingapigw }}
|
urls__apigwws: http://{{ $webshoppingapigw }}
|
||||||
urls__spa: http://{{ $spa }}
|
urls__spa: http://{{ $spa }}
|
||||||
urls__IdentityUrl: http://{{ $identity }}
|
urls__IdentityUrl: http://{{ $identity }}
|
||||||
|
@ -44,18 +44,12 @@ env:
|
|||||||
key: urls__IdentityUrl
|
key: urls__IdentityUrl
|
||||||
- name: MarketingUrl
|
- name: MarketingUrl
|
||||||
key: urls__apigwwm
|
key: urls__apigwwm
|
||||||
- name: BasketUrlHC
|
- name: PurchaseUrlHC
|
||||||
key: internalurls__basket__hc
|
key: internalurls__apigwws__hc
|
||||||
- name: CatalogUrlHC
|
|
||||||
key: internalurls__catalog__hc
|
|
||||||
- name: IdentityUrlHC
|
- name: IdentityUrlHC
|
||||||
key: internalurls__identity__hc
|
key: internalurls__identity__hc
|
||||||
- name: OrderingUrlHC
|
|
||||||
key: internalurls__ordering__hc
|
|
||||||
- name: MarketingUrlHC
|
- name: MarketingUrlHC
|
||||||
key: internalurls__marketing__hc
|
key: internalurls__apigwwm__hc
|
||||||
- name: PaymentUrlHC
|
|
||||||
key: internalurls__payment__hc
|
|
||||||
- name: SignalrHubUrl
|
- name: SignalrHubUrl
|
||||||
key: urls__apigwws
|
key: urls__apigwws
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
|
@ -19,18 +19,37 @@ data:
|
|||||||
all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}"
|
all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}"
|
||||||
all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}"
|
all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}"
|
||||||
webstatus__keystore: {{ .Values.inf.redis.keystore.constr }}
|
webstatus__keystore: {{ .Values.inf.redis.keystore.constr }}
|
||||||
internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }}
|
name__mvc__hc: WebMVC HTTP Check
|
||||||
internalurls__apigwwm: http://{{ .Values.app.svc.webmarketingapigw }}
|
|
||||||
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
|
||||||
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__locations__hc: http://{{ .Values.app.svc.locations }}/hc
|
|
||||||
internalurls__orderingbackground__hc: http://{{ .Values.app.svc.orderingbackgroundtasks }}/hc
|
|
||||||
internalurls__mvc__hc: http://{{ .Values.app.svc.mvc }}/hc
|
internalurls__mvc__hc: http://{{ .Values.app.svc.mvc }}/hc
|
||||||
|
name__spa__hc: WebSPA HTTP Check
|
||||||
internalurls__spa__hc: http://{{ .Values.app.svc.spa }}/hc
|
internalurls__spa__hc: http://{{ .Values.app.svc.spa }}/hc
|
||||||
urls__apigwws: http://{{ $webshoppingapigw }}
|
name__apigwws__hc: Web Shopping API GW HTTP Check
|
||||||
urls__mvc: http://{{ $mvc }}
|
internalurls__apigwws__hc: http://{{ .Values.app.svc.webshoppingapigw }}/hc
|
||||||
urls__IdentityUrl: http://{{ $identity }}
|
name__apigwwm__hc: Web Marketing API GW HTTP Check
|
||||||
|
internalurls__apigwwm__hc: http://{{ .Values.app.svc.webmarketingapigw }}/hc
|
||||||
|
name__apigwms__hc: Mobile Shopping API GW HTTP Check
|
||||||
|
internalurls__apigwms__hc: http://{{ .Values.app.svc.mobileshoppingapigw }}/hc
|
||||||
|
name__apigwmm__hc: Mobile Marketing API GW HTTP Check
|
||||||
|
internalurls__apigwmm__hc: http://{{ .Values.app.svc.mobilemarketingapigw }}/hc
|
||||||
|
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
|
||||||
|
internalurls__apigwmsagg__hc: http://{{ .Values.app.svc.mobileshoppingagg }}/hc
|
||||||
|
name__ordering__hc: Ordering HTTP Check
|
||||||
|
internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc
|
||||||
|
name__orderingbackground__hc: Ordering HTTP Background Check
|
||||||
|
internalurls__orderingbackground__hc: http://{{ .Values.app.svc.orderingbackgroundtasks }}/hc
|
||||||
|
name__basket__hc: Basket HTTP Check
|
||||||
|
internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc
|
||||||
|
name__catalog__hc: Catalog HTTP Check
|
||||||
|
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
|
||||||
|
internalurls__signalrhub__hc: http://{{ .Values.app.svc.orderingsignalrhub }}/hc
|
||||||
|
@ -13,7 +13,9 @@ service:
|
|||||||
|
|
||||||
ingress:
|
ingress:
|
||||||
enabled: true
|
enabled: true
|
||||||
annotations: {}
|
annotations: {
|
||||||
|
|
||||||
|
}
|
||||||
tls: []
|
tls: []
|
||||||
|
|
||||||
resources: {}
|
resources: {}
|
||||||
@ -32,27 +34,73 @@ env:
|
|||||||
configmap:
|
configmap:
|
||||||
- name: ApplicationInsights__InstrumentationKey
|
- name: ApplicationInsights__InstrumentationKey
|
||||||
key: all__InstrumentationKey
|
key: all__InstrumentationKey
|
||||||
- name: BasketUrl
|
- name: HealthChecks-UI__HealthChecks__0__Name
|
||||||
key: internalurls__basket__hc
|
key: name__mvc__hc
|
||||||
- name: CatalogUrl
|
- name: HealthChecks-UI__HealthChecks__0__Uri
|
||||||
key: internalurls__catalog__hc
|
|
||||||
- name: IdentityUrl
|
|
||||||
key: internalurls__identity__hc
|
|
||||||
- name: OrderingUrl
|
|
||||||
key: internalurls__ordering__hc
|
|
||||||
- name: OrderingBackgroundTasksUrl
|
|
||||||
key: internalurls__orderingbackground__hc
|
|
||||||
- name: LocationsUrl
|
|
||||||
key: internalurls__locations__hc
|
|
||||||
- name: MarketingUrl
|
|
||||||
key: internalurls__marketing__hc
|
|
||||||
- name: IdentityUrlHC
|
|
||||||
key: internalurls__identity__hc
|
|
||||||
- name: mvc
|
|
||||||
key: internalurls__mvc__hc
|
key: internalurls__mvc__hc
|
||||||
- name: spa
|
- name: HealthChecks-UI__HealthChecks__1__Name
|
||||||
|
key: name__spa__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__1__Uri
|
||||||
key: internalurls__spa__hc
|
key: internalurls__spa__hc
|
||||||
- name: PaymentUrl
|
- name: HealthChecks-UI__HealthChecks__2__Name
|
||||||
|
key: name__apigwws__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__2__Uri
|
||||||
|
key: internalurls__apigwws__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__3__Name
|
||||||
|
key: name__apigwwm__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__3__Uri
|
||||||
|
key: internalurls__apigwwm__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__4__Name
|
||||||
|
key: name__apigwms__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__4__Uri
|
||||||
|
key: internalurls__apigwms__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__5__Name
|
||||||
|
key: name__apigwmm__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__5__Uri
|
||||||
|
key: internalurls__apigwmm__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__6__Name
|
||||||
|
key: name__apigwwsagg__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__6__Uri
|
||||||
|
key: internalurls__apigwwsagg__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__7__Name
|
||||||
|
key: name__apigwmsagg__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__7__Uri
|
||||||
|
key: internalurls__apigwmsagg__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__8__Name
|
||||||
|
key: name__ordering__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__8__Uri
|
||||||
|
key: internalurls__ordering__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__9__Name
|
||||||
|
key: name__orderingbackground__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__9__Uri
|
||||||
|
key: internalurls__orderingbackground__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__10__Name
|
||||||
|
key: name__signalrhub__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__10__Uri
|
||||||
|
key: internalurls__signalrhub__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__11__Name
|
||||||
|
key: name__basket__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__11__Uri
|
||||||
|
key: internalurls__basket__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__12__Name
|
||||||
|
key: name__catalog__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__12__Uri
|
||||||
|
key: internalurls__catalog__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__13__Name
|
||||||
|
key: name__identity__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__13__Uri
|
||||||
|
key: internalurls__identity__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__14__Name
|
||||||
|
key: name__marketing__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__14__Uri
|
||||||
|
key: internalurls__marketing__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__15__Name
|
||||||
|
key: name__locations__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__15__Uri
|
||||||
|
key: internalurls__locations__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__16__Name
|
||||||
|
key: name__payment__hc
|
||||||
|
- name: HealthChecks-UI__HealthChecks__16__Uri
|
||||||
key: internalurls__payment__hc
|
key: internalurls__payment__hc
|
||||||
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
# values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
|
||||||
values:
|
values:
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
|
FROM microsoft/dotnet:2.2.0-aspnetcore-runtime AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
FROM microsoft/dotnet:2.1-sdk AS build
|
FROM microsoft/dotnet:2.2.100-sdk AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj src/ApiGateways/ApiGw-Base/
|
|
||||||
RUN dotnet restore src/ApiGateways/ApiGw-Base/
|
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR /src/src/ApiGateways/ApiGw-Base/
|
WORKDIR /src/src/ApiGateways/ApiGw-Base/
|
||||||
|
RUN dotnet restore -nowarn:msb3202,nu1503
|
||||||
RUN dotnet build -c Release -o /app
|
RUN dotnet build -c Release -o /app
|
||||||
|
|
||||||
FROM build AS publish
|
FROM build AS publish
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -9,7 +9,11 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||||
<PackageReference Include="Ocelot" Version="12.0.1" />
|
<PackageReference Include="Ocelot" Version="12.0.1" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Ocelot.DependencyInjection;
|
using Ocelot.DependencyInjection;
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
|
using System;
|
||||||
|
using HealthChecks.UI.Client;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
namespace OcelotApiGw
|
namespace OcelotApiGw
|
||||||
{
|
{
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly IConfiguration _cfg;
|
private readonly IConfiguration _cfg;
|
||||||
|
|
||||||
public Startup(IConfiguration configuration)
|
public Startup(IConfiguration configuration)
|
||||||
@ -23,6 +26,16 @@ namespace OcelotApiGw
|
|||||||
var identityUrl = _cfg.GetValue<string>("IdentityUrl");
|
var identityUrl = _cfg.GetValue<string>("IdentityUrl");
|
||||||
var authenticationProviderKey = "IdentityApiKey";
|
var authenticationProviderKey = "IdentityApiKey";
|
||||||
|
|
||||||
|
services.AddHealthChecks()
|
||||||
|
.AddCheck("self", () => HealthCheckResult.Healthy())
|
||||||
|
.AddUrlGroup(new Uri(_cfg["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
|
||||||
|
.AddUrlGroup(new Uri(_cfg["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
|
||||||
|
.AddUrlGroup(new Uri(_cfg["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
|
||||||
|
.AddUrlGroup(new Uri(_cfg["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
|
||||||
|
.AddUrlGroup(new Uri(_cfg["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
|
||||||
|
.AddUrlGroup(new Uri(_cfg["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
|
||||||
|
.AddUrlGroup(new Uri(_cfg["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
|
||||||
|
|
||||||
services.AddCors(options =>
|
services.AddCors(options =>
|
||||||
{
|
{
|
||||||
options.AddPolicy("CorsPolicy",
|
options.AddPolicy("CorsPolicy",
|
||||||
@ -65,6 +78,7 @@ namespace OcelotApiGw
|
|||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
var pathBase = _cfg["PATH_BASE"];
|
var pathBase = _cfg["PATH_BASE"];
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(pathBase))
|
if (!string.IsNullOrEmpty(pathBase))
|
||||||
{
|
{
|
||||||
app.UsePathBase(pathBase);
|
app.UsePathBase(pathBase);
|
||||||
@ -75,6 +89,17 @@ namespace OcelotApiGw
|
|||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
Predicate = _ => true,
|
||||||
|
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseHealthChecks("/liveness", new HealthCheckOptions
|
||||||
|
{
|
||||||
|
Predicate = r => r.Name.Contains("self")
|
||||||
|
});
|
||||||
|
|
||||||
loggerFactory.AddConsole(_cfg.GetSection("Logging"));
|
loggerFactory.AddConsole(_cfg.GetSection("Logging"));
|
||||||
|
|
||||||
app.UseCors("CorsPolicy");
|
app.UseCors("CorsPolicy");
|
||||||
|
@ -5,16 +5,19 @@ using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class BasketController : Controller
|
[ApiController]
|
||||||
|
public class BasketController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ICatalogService _catalog;
|
private readonly ICatalogService _catalog;
|
||||||
private readonly IBasketService _basket;
|
private readonly IBasketService _basket;
|
||||||
|
|
||||||
public BasketController(ICatalogService catalogService, IBasketService basketService)
|
public BasketController(ICatalogService catalogService, IBasketService basketService)
|
||||||
{
|
{
|
||||||
_catalog = catalogService;
|
_catalog = catalogService;
|
||||||
@ -23,22 +26,24 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[HttpPut]
|
[HttpPut]
|
||||||
public async Task<IActionResult> UpdateAllBasket([FromBody] UpdateBasketRequest data)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
[ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<ActionResult<BasketData>> UpdateAllBasketAsync([FromBody] UpdateBasketRequest data)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (data.Items == null || !data.Items.Any())
|
if (data.Items == null || !data.Items.Any())
|
||||||
{
|
{
|
||||||
return BadRequest("Need to pass at least one basket line");
|
return BadRequest("Need to pass at least one basket line");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the current basket
|
// Retrieve the current basket
|
||||||
var currentBasket = await _basket.GetById(data.BuyerId);
|
var currentBasket = await _basket.GetByIdAsync(data.BuyerId);
|
||||||
|
|
||||||
if (currentBasket == null)
|
if (currentBasket == null)
|
||||||
{
|
{
|
||||||
currentBasket = new BasketData(data.BuyerId);
|
currentBasket = new BasketData(data.BuyerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var catalogItems = await _catalog.GetCatalogItems(data.Items.Select(x => x.ProductId));
|
var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId));
|
||||||
var newBasket = new BasketData(data.BuyerId);
|
var newBasket = new BasketData(data.BuyerId);
|
||||||
|
|
||||||
foreach (var bitem in data.Items)
|
foreach (var bitem in data.Items)
|
||||||
@ -60,13 +65,16 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await _basket.Update(newBasket);
|
await _basket.UpdateAsync(newBasket);
|
||||||
return Ok(newBasket);
|
|
||||||
|
return newBasket;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut]
|
[HttpPut]
|
||||||
[Route("items")]
|
[Route("items")]
|
||||||
public async Task<IActionResult> UpdateQuantities([FromBody] UpdateBasketItemsRequest data)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
[ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<ActionResult<BasketData>> UpdateQuantitiesAsync([FromBody] UpdateBasketItemsRequest data)
|
||||||
{
|
{
|
||||||
if (!data.Updates.Any())
|
if (!data.Updates.Any())
|
||||||
{
|
{
|
||||||
@ -74,7 +82,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the current basket
|
// Retrieve the current basket
|
||||||
var currentBasket = await _basket.GetById(data.BasketId);
|
var currentBasket = await _basket.GetByIdAsync(data.BasketId);
|
||||||
if (currentBasket == null)
|
if (currentBasket == null)
|
||||||
{
|
{
|
||||||
return BadRequest($"Basket with id {data.BasketId} not found.");
|
return BadRequest($"Basket with id {data.BasketId} not found.");
|
||||||
@ -84,21 +92,26 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
foreach (var update in data.Updates)
|
foreach (var update in data.Updates)
|
||||||
{
|
{
|
||||||
var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId);
|
var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId);
|
||||||
|
|
||||||
if (basketItem == null)
|
if (basketItem == null)
|
||||||
{
|
{
|
||||||
return BadRequest($"Basket item with id {update.BasketItemId} not found");
|
return BadRequest($"Basket item with id {update.BasketItemId} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
basketItem.Quantity = update.NewQty;
|
basketItem.Quantity = update.NewQty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the updated basket
|
// Save the updated basket
|
||||||
await _basket.Update(currentBasket);
|
await _basket.UpdateAsync(currentBasket);
|
||||||
return Ok(currentBasket);
|
|
||||||
|
return currentBasket;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("items")]
|
[Route("items")]
|
||||||
public async Task<IActionResult> AddBasketItem([FromBody] AddBasketItemRequest data)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||||
|
public async Task<ActionResult> AddBasketItemAsync([FromBody] AddBasketItemRequest data)
|
||||||
{
|
{
|
||||||
if (data == null || data.Quantity == 0)
|
if (data == null || data.Quantity == 0)
|
||||||
{
|
{
|
||||||
@ -106,12 +119,12 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Step 1: Get the item from catalog
|
// Step 1: Get the item from catalog
|
||||||
var item = await _catalog.GetCatalogItem(data.CatalogItemId);
|
var item = await _catalog.GetCatalogItemAsync(data.CatalogItemId);
|
||||||
|
|
||||||
//item.PictureUri =
|
//item.PictureUri =
|
||||||
|
|
||||||
// Step 2: Get current basket status
|
// Step 2: Get current basket status
|
||||||
var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId);
|
var currentBasket = (await _basket.GetByIdAsync(data.BasketId)) ?? new BasketData(data.BasketId);
|
||||||
// Step 3: Merge current status with new product
|
// Step 3: Merge current status with new product
|
||||||
currentBasket.Items.Add(new BasketDataItem()
|
currentBasket.Items.Add(new BasketDataItem()
|
||||||
{
|
{
|
||||||
@ -124,8 +137,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Step 4: Update basket
|
// Step 4: Update basket
|
||||||
await _basket.Update(currentBasket);
|
await _basket.UpdateAsync(currentBasket);
|
||||||
|
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
|
||||||
using System;
|
using System.Net;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class OrderController : Controller
|
[ApiController]
|
||||||
|
public class OrderController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IBasketService _basketService;
|
private readonly IBasketService _basketService;
|
||||||
private readonly IOrderApiClient _orderClient;
|
private readonly IOrderApiClient _orderClient;
|
||||||
|
|
||||||
public OrderController(IBasketService basketService, IOrderApiClient orderClient)
|
public OrderController(IBasketService basketService, IOrderApiClient orderClient)
|
||||||
{
|
{
|
||||||
_basketService = basketService;
|
_basketService = basketService;
|
||||||
@ -22,21 +23,23 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
|
|
||||||
[Route("draft/{basketId}")]
|
[Route("draft/{basketId}")]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> GetOrderDraft(string basketId)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
[ProducesResponseType(typeof(OrderData), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<ActionResult<OrderData>> GetOrderDraftAsync(string basketId)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(basketId))
|
if (string.IsNullOrEmpty(basketId))
|
||||||
{
|
{
|
||||||
return BadRequest("Need a valid basketid");
|
return BadRequest("Need a valid basketid");
|
||||||
}
|
}
|
||||||
// Get the basket data and build a order draft based on it
|
// Get the basket data and build a order draft based on it
|
||||||
var basket = await _basketService.GetById(basketId);
|
var basket = await _basketService.GetByIdAsync(basketId);
|
||||||
|
|
||||||
if (basket == null)
|
if (basket == null)
|
||||||
{
|
{
|
||||||
return BadRequest($"No basket found for id {basketId}");
|
return BadRequest($"No basket found for id {basketId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var orderDraft = await _orderClient.GetOrderDraftFromBasket(basket);
|
return await _orderClient.GetOrderDraftFromBasketAsync(basket);
|
||||||
return Ok(orderDraft);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
|
FROM microsoft/dotnet:2.2.0-aspnetcore-runtime AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
FROM microsoft/dotnet:2.1-sdk AS build
|
FROM microsoft/dotnet:2.2.100-sdk AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR /src/src/ApiGateways/Mobile.Bff.Shopping/aggregator
|
WORKDIR /src/src/ApiGateways/Mobile.Bff.Shopping/aggregator
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
<AssemblyName>Mobile.Shopping.HttpAggregator</AssemblyName>
|
<AssemblyName>Mobile.Shopping.HttpAggregator</AssemblyName>
|
||||||
<RootNamespace>Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator</RootNamespace>
|
<RootNamespace>Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator</RootNamespace>
|
||||||
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||||
@ -12,11 +12,15 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="2.2.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.2.0-preview3-35497" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -22,7 +22,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
_urls = config.Value;
|
_urls = config.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<BasketData> GetById(string id)
|
public async Task<BasketData> GetByIdAsync(string id)
|
||||||
{
|
{
|
||||||
var data = await _httpClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
|
var data = await _httpClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
return basket;
|
return basket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Update(BasketData currentBasket)
|
public async Task UpdateAsync(BasketData currentBasket)
|
||||||
{
|
{
|
||||||
var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json");
|
var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
_urls = config.Value;
|
_urls = config.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CatalogItem> GetCatalogItem(int id)
|
public async Task<CatalogItem> GetCatalogItemAsync(int id)
|
||||||
{
|
{
|
||||||
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
|
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
|
||||||
var catalogItem = JsonConvert.DeserializeObject<CatalogItem>(stringContent);
|
var catalogItem = JsonConvert.DeserializeObject<CatalogItem>(stringContent);
|
||||||
@ -30,7 +30,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
return catalogItem;
|
return catalogItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<CatalogItem>> GetCatalogItems(IEnumerable<int> ids)
|
public async Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids)
|
||||||
{
|
{
|
||||||
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
|
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
|
||||||
var catalogItems = JsonConvert.DeserializeObject<CatalogItem[]>(stringContent);
|
var catalogItems = JsonConvert.DeserializeObject<CatalogItem[]>(stringContent);
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||||
{
|
{
|
||||||
public interface IBasketService
|
public interface IBasketService
|
||||||
{
|
{
|
||||||
Task<BasketData> GetById(string id);
|
Task<BasketData> GetByIdAsync(string id);
|
||||||
Task Update(BasketData currentBasket);
|
|
||||||
|
Task UpdateAsync(BasketData currentBasket);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||||
{
|
{
|
||||||
public interface ICatalogService
|
public interface ICatalogService
|
||||||
{
|
{
|
||||||
Task<CatalogItem> GetCatalogItem(int id);
|
Task<CatalogItem> GetCatalogItemAsync(int id);
|
||||||
Task<IEnumerable<CatalogItem>> GetCatalogItems(IEnumerable<int> ids);
|
|
||||||
|
Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||||
{
|
{
|
||||||
public interface IOrderApiClient
|
public interface IOrderApiClient
|
||||||
{
|
{
|
||||||
Task<OrderData> GetOrderDraftFromBasket(BasketData basket);
|
Task<OrderData> GetOrderDraftFromBasketAsync(BasketData basket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
_urls = config.Value;
|
_urls = config.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<OrderData> GetOrderDraftFromBasket(BasketData basket)
|
public async Task<OrderData> GetOrderDraftFromBasketAsync(BasketData basket)
|
||||||
{
|
{
|
||||||
var uri = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft();
|
var uri = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft();
|
||||||
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
|
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
|
||||||
|
@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure;
|
||||||
@ -16,6 +17,9 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Polly;
|
using Polly;
|
||||||
using Polly.Extensions.Http;
|
using Polly.Extensions.Http;
|
||||||
using Swashbuckle.AspNetCore.Swagger;
|
using Swashbuckle.AspNetCore.Swagger;
|
||||||
|
using HealthChecks.UI.Client;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
||||||
{
|
{
|
||||||
@ -31,6 +35,16 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
services.AddHealthChecks()
|
||||||
|
.AddCheck("self", () => HealthCheckResult.Healthy())
|
||||||
|
.AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
|
||||||
|
|
||||||
services.AddCustomMvc(Configuration)
|
services.AddCustomMvc(Configuration)
|
||||||
.AddCustomAuthentication(Configuration)
|
.AddCustomAuthentication(Configuration)
|
||||||
.AddHttpServices();
|
.AddHttpServices();
|
||||||
@ -47,15 +61,31 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
app.UsePathBase(pathBase);
|
app.UsePathBase(pathBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
Predicate = _ => true,
|
||||||
|
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseHealthChecks("/liveness", new HealthCheckOptions
|
||||||
|
{
|
||||||
|
Predicate = r => r.Name.Contains("self")
|
||||||
|
});
|
||||||
|
|
||||||
app.UseCors("CorsPolicy");
|
app.UseCors("CorsPolicy");
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||||
|
app.UseHsts();
|
||||||
|
}
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
app.UseHttpsRedirection();
|
||||||
app.UseMvc();
|
app.UseMvc();
|
||||||
|
|
||||||
app.UseSwagger().UseSwaggerUI(c =>
|
app.UseSwagger().UseSwaggerUI(c =>
|
||||||
@ -77,7 +107,8 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
services.AddOptions();
|
services.AddOptions();
|
||||||
services.Configure<UrlsConfig>(configuration.GetSection("urls"));
|
services.Configure<UrlsConfig>(configuration.GetSection("urls"));
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc()
|
||||||
|
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
||||||
|
|
||||||
services.AddSwaggerGen(options =>
|
services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
@ -120,12 +151,14 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
{
|
{
|
||||||
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
|
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
|
||||||
var identityUrl = configuration.GetValue<string>("urls:identity");
|
var identityUrl = configuration.GetValue<string>("urls:identity");
|
||||||
|
|
||||||
services.AddAuthentication(options =>
|
services.AddAuthentication(options =>
|
||||||
{
|
{
|
||||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
|
||||||
}).AddJwtBearer(options =>
|
})
|
||||||
|
.AddJwtBearer(options =>
|
||||||
{
|
{
|
||||||
options.Authority = identityUrl;
|
options.Authority = identityUrl;
|
||||||
options.RequireHttpsMetadata = false;
|
options.RequireHttpsMetadata = false;
|
||||||
@ -143,6 +176,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddHttpServices(this IServiceCollection services)
|
public static IServiceCollection AddHttpServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
//register delegating handlers
|
//register delegating handlers
|
||||||
@ -163,8 +197,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
.AddPolicyHandler(GetRetryPolicy())
|
.AddPolicyHandler(GetRetryPolicy())
|
||||||
.AddPolicyHandler(GetCircuitBreakerPolicy());
|
.AddPolicyHandler(GetCircuitBreakerPolicy());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +206,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
.HandleTransientHttpError()
|
.HandleTransientHttpError()
|
||||||
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
|
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||||
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
|
private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
|
||||||
|
@ -5,16 +5,19 @@ using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class BasketController : Controller
|
[ApiController]
|
||||||
|
public class BasketController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ICatalogService _catalog;
|
private readonly ICatalogService _catalog;
|
||||||
private readonly IBasketService _basket;
|
private readonly IBasketService _basket;
|
||||||
|
|
||||||
public BasketController(ICatalogService catalogService, IBasketService basketService)
|
public BasketController(ICatalogService catalogService, IBasketService basketService)
|
||||||
{
|
{
|
||||||
_catalog = catalogService;
|
_catalog = catalogService;
|
||||||
@ -23,22 +26,23 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
|||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[HttpPut]
|
[HttpPut]
|
||||||
public async Task<IActionResult> UpdateAllBasket([FromBody] UpdateBasketRequest data)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
[ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<ActionResult<BasketData>> UpdateAllBasketAsync([FromBody] UpdateBasketRequest data)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (data.Items == null || !data.Items.Any())
|
if (data.Items == null || !data.Items.Any())
|
||||||
{
|
{
|
||||||
return BadRequest("Need to pass at least one basket line");
|
return BadRequest("Need to pass at least one basket line");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the current basket
|
// Retrieve the current basket
|
||||||
var currentBasket = await _basket.GetById(data.BuyerId);
|
var currentBasket = await _basket.GetByIdAsync(data.BuyerId);
|
||||||
if (currentBasket == null)
|
if (currentBasket == null)
|
||||||
{
|
{
|
||||||
currentBasket = new BasketData(data.BuyerId);
|
currentBasket = new BasketData(data.BuyerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var catalogItems = await _catalog.GetCatalogItems(data.Items.Select(x => x.ProductId));
|
var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId));
|
||||||
var newBasket = new BasketData(data.BuyerId);
|
var newBasket = new BasketData(data.BuyerId);
|
||||||
|
|
||||||
foreach (var bitem in data.Items)
|
foreach (var bitem in data.Items)
|
||||||
@ -60,13 +64,16 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await _basket.Update(newBasket);
|
await _basket.UpdateAsync(newBasket);
|
||||||
return Ok(newBasket);
|
|
||||||
|
return newBasket;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut]
|
[HttpPut]
|
||||||
[Route("items")]
|
[Route("items")]
|
||||||
public async Task<IActionResult> UpdateQuantities([FromBody] UpdateBasketItemsRequest data)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
[ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<ActionResult<BasketData>> UpdateQuantitiesAsync([FromBody] UpdateBasketItemsRequest data)
|
||||||
{
|
{
|
||||||
if (!data.Updates.Any())
|
if (!data.Updates.Any())
|
||||||
{
|
{
|
||||||
@ -74,7 +81,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the current basket
|
// Retrieve the current basket
|
||||||
var currentBasket = await _basket.GetById(data.BasketId);
|
var currentBasket = await _basket.GetByIdAsync(data.BasketId);
|
||||||
if (currentBasket == null)
|
if (currentBasket == null)
|
||||||
{
|
{
|
||||||
return BadRequest($"Basket with id {data.BasketId} not found.");
|
return BadRequest($"Basket with id {data.BasketId} not found.");
|
||||||
@ -92,13 +99,16 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save the updated basket
|
// Save the updated basket
|
||||||
await _basket.Update(currentBasket);
|
await _basket.UpdateAsync(currentBasket);
|
||||||
return Ok(currentBasket);
|
|
||||||
|
return currentBasket;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("items")]
|
[Route("items")]
|
||||||
public async Task<IActionResult> AddBasketItem([FromBody] AddBasketItemRequest data)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||||
|
public async Task<ActionResult> AddBasketItemAsync([FromBody] AddBasketItemRequest data)
|
||||||
{
|
{
|
||||||
if (data == null || data.Quantity == 0)
|
if (data == null || data.Quantity == 0)
|
||||||
{
|
{
|
||||||
@ -106,12 +116,12 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Step 1: Get the item from catalog
|
// Step 1: Get the item from catalog
|
||||||
var item = await _catalog.GetCatalogItem(data.CatalogItemId);
|
var item = await _catalog.GetCatalogItemAsync(data.CatalogItemId);
|
||||||
|
|
||||||
//item.PictureUri =
|
//item.PictureUri =
|
||||||
|
|
||||||
// Step 2: Get current basket status
|
// Step 2: Get current basket status
|
||||||
var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId);
|
var currentBasket = (await _basket.GetByIdAsync(data.BasketId)) ?? new BasketData(data.BasketId);
|
||||||
// Step 3: Merge current status with new product
|
// Step 3: Merge current status with new product
|
||||||
currentBasket.Items.Add(new BasketDataItem()
|
currentBasket.Items.Add(new BasketDataItem()
|
||||||
{
|
{
|
||||||
@ -124,8 +134,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Step 4: Update basket
|
// Step 4: Update basket
|
||||||
await _basket.Update(currentBasket);
|
await _basket.UpdateAsync(currentBasket);
|
||||||
|
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
|
||||||
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services;
|
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class OrderController : Controller
|
[ApiController]
|
||||||
|
public class OrderController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IBasketService _basketService;
|
private readonly IBasketService _basketService;
|
||||||
private readonly IOrderApiClient _orderClient;
|
private readonly IOrderApiClient _orderClient;
|
||||||
@ -22,21 +25,23 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers
|
|||||||
|
|
||||||
[Route("draft/{basketId}")]
|
[Route("draft/{basketId}")]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> GetOrderDraft(string basketId)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
[ProducesResponseType(typeof(OrderData), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<ActionResult<OrderData>> GetOrderDraftAsync(string basketId)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(basketId))
|
if (string.IsNullOrEmpty(basketId))
|
||||||
{
|
{
|
||||||
return BadRequest("Need a valid basketid");
|
return BadRequest("Need a valid basketid");
|
||||||
}
|
}
|
||||||
// Get the basket data and build a order draft based on it
|
// Get the basket data and build a order draft based on it
|
||||||
var basket = await _basketService.GetById(basketId);
|
var basket = await _basketService.GetByIdAsync(basketId);
|
||||||
|
|
||||||
if (basket == null)
|
if (basket == null)
|
||||||
{
|
{
|
||||||
return BadRequest($"No basket found for id {basketId}");
|
return BadRequest($"No basket found for id {basketId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var orderDraft = await _orderClient.GetOrderDraftFromBasket(basket);
|
return await _orderClient.GetOrderDraftFromBasketAsync(basket);
|
||||||
return Ok(orderDraft);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
|
FROM microsoft/dotnet:2.2.0-aspnetcore-runtime AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
FROM microsoft/dotnet:2.1-sdk AS build
|
FROM microsoft/dotnet:2.2.100-sdk AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR /src/src/ApiGateways/Web.Bff.Shopping/aggregator
|
WORKDIR /src/src/ApiGateways/Web.Bff.Shopping/aggregator
|
||||||
|
@ -10,7 +10,6 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
|||||||
{
|
{
|
||||||
public class BasketService : IBasketService
|
public class BasketService : IBasketService
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly HttpClient _apiClient;
|
private readonly HttpClient _apiClient;
|
||||||
private readonly ILogger<BasketService> _logger;
|
private readonly ILogger<BasketService> _logger;
|
||||||
private readonly UrlsConfig _urls;
|
private readonly UrlsConfig _urls;
|
||||||
@ -22,18 +21,19 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
|||||||
_urls = config.Value;
|
_urls = config.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<BasketData> GetById(string id)
|
public async Task<BasketData> GetByIdAsync(string id)
|
||||||
{
|
{
|
||||||
var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
|
var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
|
||||||
var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject<BasketData>(data) : null;
|
var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject<BasketData>(data) : null;
|
||||||
|
|
||||||
return basket;
|
return basket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Update(BasketData currentBasket)
|
public async Task UpdateAsync(BasketData currentBasket)
|
||||||
{
|
{
|
||||||
var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json");
|
var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
var data = await _apiClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), basketContent);
|
await _apiClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), basketContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
|||||||
{
|
{
|
||||||
public class CatalogService : ICatalogService
|
public class CatalogService : ICatalogService
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly ILogger<CatalogService> _logger;
|
private readonly ILogger<CatalogService> _logger;
|
||||||
private readonly UrlsConfig _urls;
|
private readonly UrlsConfig _urls;
|
||||||
@ -23,20 +22,18 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
|||||||
_urls = config.Value;
|
_urls = config.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CatalogItem> GetCatalogItem(int id)
|
public async Task<CatalogItem> GetCatalogItemAsync(int id)
|
||||||
{
|
{
|
||||||
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
|
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
|
||||||
var catalogItem = JsonConvert.DeserializeObject<CatalogItem>(stringContent);
|
|
||||||
|
|
||||||
return catalogItem;
|
return JsonConvert.DeserializeObject<CatalogItem>(stringContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<CatalogItem>> GetCatalogItems(IEnumerable<int> ids)
|
public async Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids)
|
||||||
{
|
{
|
||||||
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
|
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
|
||||||
var catalogItems = JsonConvert.DeserializeObject<CatalogItem[]>(stringContent);
|
|
||||||
|
|
||||||
return catalogItems;
|
return JsonConvert.DeserializeObject<CatalogItem[]>(stringContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
||||||
{
|
{
|
||||||
public interface IBasketService
|
public interface IBasketService
|
||||||
{
|
{
|
||||||
Task<BasketData> GetById(string id);
|
Task<BasketData> GetByIdAsync(string id);
|
||||||
Task Update(BasketData currentBasket);
|
|
||||||
|
|
||||||
|
Task UpdateAsync(BasketData currentBasket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
||||||
{
|
{
|
||||||
public interface ICatalogService
|
public interface ICatalogService
|
||||||
{
|
{
|
||||||
Task<CatalogItem> GetCatalogItem(int id);
|
Task<CatalogItem> GetCatalogItemAsync(int id);
|
||||||
Task<IEnumerable<CatalogItem>> GetCatalogItems(IEnumerable<int> ids);
|
|
||||||
|
Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
||||||
{
|
{
|
||||||
public interface IOrderApiClient
|
public interface IOrderApiClient
|
||||||
{
|
{
|
||||||
Task<OrderData> GetOrderDraftFromBasket(BasketData basket);
|
Task<OrderData> GetOrderDraftFromBasketAsync(BasketData basket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
|||||||
{
|
{
|
||||||
public class OrderApiClient : IOrderApiClient
|
public class OrderApiClient : IOrderApiClient
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly HttpClient _apiClient;
|
private readonly HttpClient _apiClient;
|
||||||
private readonly ILogger<OrderApiClient> _logger;
|
private readonly ILogger<OrderApiClient> _logger;
|
||||||
private readonly UrlsConfig _urls;
|
private readonly UrlsConfig _urls;
|
||||||
@ -22,7 +21,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
|||||||
_urls = config.Value;
|
_urls = config.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<OrderData> GetOrderDraftFromBasket(BasketData basket)
|
public async Task<OrderData> GetOrderDraftFromBasketAsync(BasketData basket)
|
||||||
{
|
{
|
||||||
var url = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft();
|
var url = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft();
|
||||||
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
|
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
|
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config;
|
||||||
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
|
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
|
||||||
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure;
|
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure;
|
||||||
@ -17,6 +18,9 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using HealthChecks.UI.Client;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
||||||
{
|
{
|
||||||
@ -32,6 +36,16 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
|||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
services.AddHealthChecks()
|
||||||
|
.AddCheck("self", () => HealthCheckResult.Healthy())
|
||||||
|
.AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
|
||||||
|
.AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
|
||||||
|
|
||||||
services.AddCustomMvc(Configuration)
|
services.AddCustomMvc(Configuration)
|
||||||
.AddCustomAuthentication(Configuration)
|
.AddCustomAuthentication(Configuration)
|
||||||
.AddApplicationServices();
|
.AddApplicationServices();
|
||||||
@ -47,24 +61,39 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
|||||||
app.UsePathBase(pathBase);
|
app.UsePathBase(pathBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
Predicate = _ => true,
|
||||||
|
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseHealthChecks("/liveness", new HealthCheckOptions
|
||||||
|
{
|
||||||
|
Predicate = r => r.Name.Contains("self")
|
||||||
|
});
|
||||||
|
|
||||||
app.UseCors("CorsPolicy");
|
app.UseCors("CorsPolicy");
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||||
|
app.UseHsts();
|
||||||
|
}
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
app.UseHttpsRedirection();
|
||||||
app.UseMvc();
|
app.UseMvc();
|
||||||
|
|
||||||
app.UseSwagger().UseSwaggerUI(c =>
|
app.UseSwagger()
|
||||||
{
|
.UseSwaggerUI(c =>
|
||||||
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1");
|
{
|
||||||
//c.ConfigureOAuth2("Microsoft.eShopOnContainers.Web.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI");
|
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1");
|
||||||
});
|
//c.ConfigureOAuth2("Microsoft.eShopOnContainers.Web.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI");
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,12 +128,14 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
|||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
services.AddOptions();
|
services.AddOptions();
|
||||||
services.Configure<UrlsConfig>(configuration.GetSection("urls"));
|
services.Configure<UrlsConfig>(configuration.GetSection("urls"));
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc()
|
||||||
|
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
||||||
|
|
||||||
services.AddSwaggerGen(options =>
|
services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
@ -177,6 +208,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
|||||||
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
|
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
|
||||||
{
|
{
|
||||||
return HttpPolicyExtensions
|
return HttpPolicyExtensions
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
<AssemblyName>Web.Shopping.HttpAggregator</AssemblyName>
|
<AssemblyName>Web.Shopping.HttpAggregator</AssemblyName>
|
||||||
<RootNamespace>Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator</RootNamespace>
|
<RootNamespace>Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator</RootNamespace>
|
||||||
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||||
@ -12,11 +12,14 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" />
|
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.2.0-preview3-35497" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autofac" Version="4.6.2" />
|
<PackageReference Include="Autofac" Version="4.6.2" />
|
||||||
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
|
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0-preview3-35497" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="Polly" Version="6.0.1" />
|
<PackageReference Include="Polly" Version="6.0.1" />
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="5.0.1" />
|
<PackageReference Include="RabbitMQ.Client" Version="5.0.1" />
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<PackageReference Include="Autofac" Version="4.6.2" />
|
<PackageReference Include="Autofac" Version="4.6.2" />
|
||||||
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="3.0.0" />
|
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="3.0.0" />
|
||||||
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
|
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0-preview3-35497" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.0-preview3-35497" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.0-preview3-35497" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.1.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.0-preview3-35497" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.0-preview3-35497" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
|
||||||
using Microsoft.Extensions.HealthChecks;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.HealthChecks
|
|
||||||
{
|
|
||||||
public class HealthCheckMiddleware
|
|
||||||
{
|
|
||||||
private readonly RequestDelegate _next;
|
|
||||||
private readonly string _path;
|
|
||||||
private readonly int? _port;
|
|
||||||
private readonly IHealthCheckService _service;
|
|
||||||
private readonly TimeSpan _timeout;
|
|
||||||
|
|
||||||
public HealthCheckMiddleware(RequestDelegate next, IHealthCheckService service, int port, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
_port = port;
|
|
||||||
_service = service;
|
|
||||||
_next = next;
|
|
||||||
_timeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HealthCheckMiddleware(RequestDelegate next, IHealthCheckService service, string path, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
_path = path;
|
|
||||||
_service = service;
|
|
||||||
_next = next;
|
|
||||||
_timeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
|
||||||
{
|
|
||||||
if (IsHealthCheckRequest(context))
|
|
||||||
{
|
|
||||||
var timeoutTokenSource = new CancellationTokenSource(_timeout);
|
|
||||||
var result = await _service.CheckHealthAsync(timeoutTokenSource.Token);
|
|
||||||
var status = result.CheckStatus;
|
|
||||||
|
|
||||||
if (status != CheckStatus.Healthy)
|
|
||||||
context.Response.StatusCode = 503;
|
|
||||||
|
|
||||||
context.Response.Headers.Add("content-type", "application/json");
|
|
||||||
await context.Response.WriteAsync(JsonConvert.SerializeObject(new { status = status.ToString() }));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await _next.Invoke(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsHealthCheckRequest(HttpContext context)
|
|
||||||
{
|
|
||||||
if (_port.HasValue)
|
|
||||||
{
|
|
||||||
var connInfo = context.Features.Get<IHttpConnectionFeature>();
|
|
||||||
if (connInfo.LocalPort == _port)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.Request.Path == _path)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.HealthChecks
|
|
||||||
{
|
|
||||||
public class HealthCheckStartupFilter : IStartupFilter
|
|
||||||
{
|
|
||||||
private string _path;
|
|
||||||
private int? _port;
|
|
||||||
private TimeSpan _timeout;
|
|
||||||
|
|
||||||
public HealthCheckStartupFilter(int port, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
_port = port;
|
|
||||||
_timeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HealthCheckStartupFilter(string path, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
_path = path;
|
|
||||||
_timeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
|
|
||||||
{
|
|
||||||
return app =>
|
|
||||||
{
|
|
||||||
if (_port.HasValue)
|
|
||||||
{
|
|
||||||
app.UseMiddleware<HealthCheckMiddleware>(_port, _timeout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
app.UseMiddleware<HealthCheckMiddleware>(_path, _timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
next(app);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNetCore.HealthChecks;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Hosting
|
|
||||||
{
|
|
||||||
public static class HealthCheckWebHostBuilderExtension
|
|
||||||
{
|
|
||||||
public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(10);
|
|
||||||
|
|
||||||
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, int port)
|
|
||||||
=> UseHealthChecks(builder, port, DefaultTimeout);
|
|
||||||
|
|
||||||
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, int port, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
Guard.ArgumentValid(port > 0 && port < 65536, nameof(port), "Port must be a value between 1 and 65535.");
|
|
||||||
Guard.ArgumentValid(timeout > TimeSpan.Zero, nameof(timeout), "Health check timeout must be a positive time span.");
|
|
||||||
|
|
||||||
builder.ConfigureServices(services =>
|
|
||||||
{
|
|
||||||
var existingUrl = builder.GetSetting(WebHostDefaults.ServerUrlsKey);
|
|
||||||
builder.UseSetting(WebHostDefaults.ServerUrlsKey, $"{existingUrl};http://localhost:{port}");
|
|
||||||
|
|
||||||
services.AddSingleton<IStartupFilter>(new HealthCheckStartupFilter(port, timeout));
|
|
||||||
});
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, string path)
|
|
||||||
=> UseHealthChecks(builder, path, DefaultTimeout);
|
|
||||||
|
|
||||||
public static IWebHostBuilder UseHealthChecks(this IWebHostBuilder builder, string path, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(path), path);
|
|
||||||
// REVIEW: Is there a better URL path validator somewhere?
|
|
||||||
Guard.ArgumentValid(!path.Contains("?"), nameof(path), "Path cannot contain query string values.");
|
|
||||||
Guard.ArgumentValid(path.StartsWith("/"), nameof(path), "Path should start with '/'.");
|
|
||||||
Guard.ArgumentValid(timeout > TimeSpan.Zero, nameof(timeout), "Health check timeout must be a positive time span.");
|
|
||||||
|
|
||||||
builder.ConfigureServices(services => services.AddSingleton<IStartupFilter>(new HealthCheckStartupFilter(path, timeout)));
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.Extensions.HealthChecks;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Hosting
|
|
||||||
{
|
|
||||||
public static class HealthCheckWebHostExtensions
|
|
||||||
{
|
|
||||||
private const int DEFAULT_TIMEOUT_SECONDS = 300;
|
|
||||||
|
|
||||||
public static void RunWhenHealthy(this IWebHost webHost)
|
|
||||||
{
|
|
||||||
webHost.RunWhenHealthy(TimeSpan.FromSeconds(DEFAULT_TIMEOUT_SECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RunWhenHealthy(this IWebHost webHost, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
var healthChecks = webHost.Services.GetService(typeof(IHealthCheckService)) as IHealthCheckService;
|
|
||||||
|
|
||||||
var loops = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
var checkResult = healthChecks.CheckHealthAsync().Result;
|
|
||||||
if (checkResult.CheckStatus == CheckStatus.Healthy)
|
|
||||||
{
|
|
||||||
webHost.Run();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
System.Threading.Thread.Sleep(1000);
|
|
||||||
loops++;
|
|
||||||
|
|
||||||
} while (loops < timeout.TotalSeconds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,175 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.WindowsAzure.Storage;
|
|
||||||
using Microsoft.WindowsAzure.Storage.Auth;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
// REVIEW: Do we want these to continue to use default parameters?
|
|
||||||
// REVIEW: What are the appropriate guards for these functions?
|
|
||||||
|
|
||||||
public static class AzureHealthCheckBuilderExtensions
|
|
||||||
{
|
|
||||||
public static HealthCheckBuilder AddAzureBlobStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string containerName = null, TimeSpan? cacheDuration = null)
|
|
||||||
{
|
|
||||||
var credentials = new StorageCredentials(accountName, accountKey);
|
|
||||||
var storageAccount = new CloudStorageAccount(credentials, true);
|
|
||||||
return AddAzureBlobStorageCheck(builder, storageAccount, containerName, cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddAzureBlobStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string containerName = null, TimeSpan? cacheDuration = null)
|
|
||||||
{
|
|
||||||
builder.AddCheck($"AzureBlobStorageCheck {storageAccount.BlobStorageUri} {containerName}", async () =>
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var blobClient = storageAccount.CreateCloudBlobClient();
|
|
||||||
|
|
||||||
var properties = await blobClient.GetServicePropertiesAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(containerName))
|
|
||||||
{
|
|
||||||
var container = blobClient.GetContainerReference(containerName);
|
|
||||||
|
|
||||||
result = await container.ExistsAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
? HealthCheckResult.Healthy($"AzureBlobStorage {storageAccount.BlobStorageUri} is available")
|
|
||||||
: HealthCheckResult.Unhealthy($"AzureBlobStorage {storageAccount.BlobStorageUri} is unavailable");
|
|
||||||
}, cacheDuration ?? builder.DefaultCacheDuration);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddAzureTableStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string tableName = null, TimeSpan? cacheDuration = null)
|
|
||||||
{
|
|
||||||
var credentials = new StorageCredentials(accountName, accountKey);
|
|
||||||
var storageAccount = new CloudStorageAccount(credentials, true);
|
|
||||||
return AddAzureTableStorageCheck(builder, storageAccount, tableName, cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddAzureTableStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string tableName = null, TimeSpan? cacheDuration = null)
|
|
||||||
{
|
|
||||||
builder.AddCheck($"AzureTableStorageCheck {storageAccount.TableStorageUri} {tableName}", async () =>
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var tableClient = storageAccount.CreateCloudTableClient();
|
|
||||||
|
|
||||||
var properties = await tableClient.GetServicePropertiesAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(tableName))
|
|
||||||
{
|
|
||||||
var table = tableClient.GetTableReference(tableName);
|
|
||||||
|
|
||||||
result = await table.ExistsAsync();
|
|
||||||
}
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
? HealthCheckResult.Healthy($"AzureTableStorage {storageAccount.BlobStorageUri} is available")
|
|
||||||
: HealthCheckResult.Unhealthy($"AzureTableStorage {storageAccount.BlobStorageUri} is unavailable");
|
|
||||||
|
|
||||||
}, cacheDuration ?? builder.DefaultCacheDuration);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddAzureFileStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string shareName = null, TimeSpan? cacheDuration = null)
|
|
||||||
{
|
|
||||||
var credentials = new StorageCredentials(accountName, accountKey);
|
|
||||||
var storageAccount = new CloudStorageAccount(credentials, true);
|
|
||||||
return AddAzureFileStorageCheck(builder, storageAccount, shareName, cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddAzureFileStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string shareName = null, TimeSpan? cacheDuration = null)
|
|
||||||
{
|
|
||||||
builder.AddCheck($"AzureFileStorageCheck {storageAccount.FileStorageUri} {shareName}", async () =>
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var fileClient = storageAccount.CreateCloudFileClient();
|
|
||||||
|
|
||||||
var properties = await fileClient.GetServicePropertiesAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(shareName))
|
|
||||||
{
|
|
||||||
var share = fileClient.GetShareReference(shareName);
|
|
||||||
|
|
||||||
result = await share.ExistsAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
? HealthCheckResult.Healthy($"AzureFileStorage {storageAccount.BlobStorageUri} is available")
|
|
||||||
: HealthCheckResult.Unhealthy($"AzureFileStorage {storageAccount.BlobStorageUri} is unavailable");
|
|
||||||
}, cacheDuration ?? builder.DefaultCacheDuration);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddAzureQueueStorageCheck(this HealthCheckBuilder builder, string accountName, string accountKey, string queueName = null, TimeSpan? cacheDuration = null)
|
|
||||||
{
|
|
||||||
var credentials = new StorageCredentials(accountName, accountKey);
|
|
||||||
var storageAccount = new CloudStorageAccount(credentials, true);
|
|
||||||
return AddAzureQueueStorageCheck(builder, storageAccount, queueName, cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddAzureQueueStorageCheck(HealthCheckBuilder builder, CloudStorageAccount storageAccount, string queueName = null, TimeSpan? cacheDuration = null)
|
|
||||||
{
|
|
||||||
builder.AddCheck($"AzureQueueStorageCheck {storageAccount.QueueStorageUri} {queueName}", async () =>
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var queueClient = storageAccount.CreateCloudQueueClient();
|
|
||||||
|
|
||||||
var properties = await queueClient.GetServicePropertiesAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(queueName))
|
|
||||||
{
|
|
||||||
var queue = queueClient.GetQueueReference(queueName);
|
|
||||||
|
|
||||||
result = await queue.ExistsAsync();
|
|
||||||
}
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
? HealthCheckResult.Healthy($"AzureFileStorage {storageAccount.BlobStorageUri} is available")
|
|
||||||
: HealthCheckResult.Unhealthy($"AzureFileStorage {storageAccount.BlobStorageUri} is unavailable");
|
|
||||||
|
|
||||||
}, cacheDuration ?? builder.DefaultCacheDuration);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
|
||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
|
||||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
|
||||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.0" />
|
|
||||||
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
|
|
||||||
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
|
|
||||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.0" />
|
|
||||||
<PackageReference Include="WindowsAzure.Storage" Version="9.1.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,22 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("HealthChecks.Azure")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
[assembly: Guid("0c4158b7-7153-4d2e-abfa-4ce07d44f75f")]
|
|
@ -1,54 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Data;
|
|
||||||
using System.Data.SqlClient;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
// REVIEW: What are the appropriate guards for these functions?
|
|
||||||
|
|
||||||
public static class HealthCheckBuilderSqlServerExtensions
|
|
||||||
{
|
|
||||||
public static HealthCheckBuilder AddSqlCheck(this HealthCheckBuilder builder, string name, string connectionString)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return AddSqlCheck(builder, name, connectionString, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddSqlCheck(this HealthCheckBuilder builder, string name, string connectionString, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
builder.AddCheck($"SqlCheck({name})", async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//TODO: There is probably a much better way to do this.
|
|
||||||
using (var connection = new SqlConnection(connectionString))
|
|
||||||
{
|
|
||||||
connection.Open();
|
|
||||||
using (var command = connection.CreateCommand())
|
|
||||||
{
|
|
||||||
command.CommandType = CommandType.Text;
|
|
||||||
command.CommandText = "SELECT 1";
|
|
||||||
var result = (int)await command.ExecuteScalarAsync().ConfigureAwait(false);
|
|
||||||
if (result == 1)
|
|
||||||
{
|
|
||||||
return HealthCheckResult.Healthy($"SqlCheck({name}): Healthy");
|
|
||||||
}
|
|
||||||
|
|
||||||
return HealthCheckResult.Unhealthy($"SqlCheck({name}): Unhealthy");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return HealthCheckResult.Unhealthy($"SqlCheck({name}): Exception during check: {ex.GetType().FullName}");
|
|
||||||
}
|
|
||||||
}, cacheDuration);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.5.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,109 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public abstract class CachedHealthCheck
|
|
||||||
{
|
|
||||||
private static readonly TypeInfo HealthCheckTypeInfo = typeof(IHealthCheck).GetTypeInfo();
|
|
||||||
|
|
||||||
private volatile int _writerCount;
|
|
||||||
|
|
||||||
public CachedHealthCheck(string name, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
|
||||||
Guard.ArgumentValid(cacheDuration.TotalMilliseconds >= 0, nameof(cacheDuration), "Cache duration must be zero (disabled) or greater than zero.");
|
|
||||||
|
|
||||||
Name = name;
|
|
||||||
CacheDuration = cacheDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IHealthCheckResult CachedResult { get; internal set; }
|
|
||||||
|
|
||||||
public TimeSpan CacheDuration { get; }
|
|
||||||
|
|
||||||
public DateTimeOffset CacheExpiration { get; internal set; }
|
|
||||||
|
|
||||||
public string Name { get; }
|
|
||||||
|
|
||||||
protected virtual DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
|
|
||||||
|
|
||||||
protected abstract IHealthCheck Resolve(IServiceProvider serviceProvider);
|
|
||||||
|
|
||||||
public async ValueTask<IHealthCheckResult> RunAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken = default(CancellationToken))
|
|
||||||
{
|
|
||||||
while (CacheExpiration <= UtcNow)
|
|
||||||
{
|
|
||||||
// Can't use a standard lock here because of async, so we'll use this flag to determine when we should write a value,
|
|
||||||
// and the waiters who aren't allowed to write will just spin wait for the new value.
|
|
||||||
if (Interlocked.Exchange(ref _writerCount, 1) != 0)
|
|
||||||
{
|
|
||||||
await Task.Delay(5, cancellationToken).ConfigureAwait(false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var check = Resolve(serviceProvider);
|
|
||||||
CachedResult = await check.CheckAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
CachedResult = HealthCheckResult.Unhealthy("The health check operation timed out");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
CachedResult = HealthCheckResult.Unhealthy($"Exception during check: {ex.GetType().FullName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheExpiration = UtcNow + CacheDuration;
|
|
||||||
_writerCount = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CachedResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CachedHealthCheck FromHealthCheck(string name, TimeSpan cacheDuration, IHealthCheck healthCheck)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(healthCheck), healthCheck);
|
|
||||||
|
|
||||||
return new TypeOrHealthCheck_HealthCheck(name, cacheDuration, healthCheck);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CachedHealthCheck FromType(string name, TimeSpan cacheDuration, Type healthCheckType)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(healthCheckType), healthCheckType);
|
|
||||||
Guard.ArgumentValid(HealthCheckTypeInfo.IsAssignableFrom(healthCheckType.GetTypeInfo()), nameof(healthCheckType), $"Health check must implement '{typeof(IHealthCheck).FullName}'.");
|
|
||||||
|
|
||||||
return new TypeOrHealthCheck_Type(name, cacheDuration, healthCheckType);
|
|
||||||
}
|
|
||||||
|
|
||||||
class TypeOrHealthCheck_HealthCheck : CachedHealthCheck
|
|
||||||
{
|
|
||||||
private readonly IHealthCheck _healthCheck;
|
|
||||||
|
|
||||||
public TypeOrHealthCheck_HealthCheck(string name, TimeSpan cacheDuration, IHealthCheck healthCheck) : base(name, cacheDuration)
|
|
||||||
=> _healthCheck = healthCheck;
|
|
||||||
|
|
||||||
protected override IHealthCheck Resolve(IServiceProvider serviceProvider) => _healthCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TypeOrHealthCheck_Type : CachedHealthCheck
|
|
||||||
{
|
|
||||||
private readonly Type _healthCheckType;
|
|
||||||
|
|
||||||
public TypeOrHealthCheck_Type(string name, TimeSpan cacheDuration, Type healthCheckType) : base(name, cacheDuration)
|
|
||||||
=> _healthCheckType = healthCheckType;
|
|
||||||
|
|
||||||
protected override IHealthCheck Resolve(IServiceProvider serviceProvider)
|
|
||||||
=> (IHealthCheck)serviceProvider.GetRequiredService(_healthCheckType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public static class CachedHealthCheckExtensions
|
|
||||||
{
|
|
||||||
public static ValueTask<IHealthCheckResult> RunAsync(this CachedHealthCheck check, IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(check), check);
|
|
||||||
|
|
||||||
return check.RunAsync(serviceProvider, CancellationToken.None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public enum CheckStatus
|
|
||||||
{
|
|
||||||
Unknown,
|
|
||||||
Unhealthy,
|
|
||||||
Healthy,
|
|
||||||
Warning
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public static partial class HealthCheckBuilderExtensions
|
|
||||||
{
|
|
||||||
// Lambda versions of AddCheck for Func/Func<Task>/Func<ValueTask>
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<IHealthCheckResult> check)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromCheck(check), builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, IHealthCheckResult> check)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromCheck(check), builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<IHealthCheckResult> check, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromCheck(check), cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, IHealthCheckResult> check, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromCheck(check), cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<Task<IHealthCheckResult>> check)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromTaskCheck(check), builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, Task<IHealthCheckResult>> check)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromTaskCheck(check), builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromTaskCheck(check), cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, Task<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromTaskCheck(check), cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<ValueTask<IHealthCheckResult>> check)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check), builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check), builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check), cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddValueTaskCheck(this HealthCheckBuilder builder, string name, Func<CancellationToken, ValueTask<IHealthCheckResult>> check, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(name, HealthCheck.FromValueTaskCheck(check), cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IHealthCheck versions of AddCheck
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck(this HealthCheckBuilder builder, string checkName, IHealthCheck check)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck(checkName, check, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type versions of AddCheck
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddCheck<TCheck>(this HealthCheckBuilder builder, string name) where TCheck : class, IHealthCheck
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return builder.AddCheck<TCheck>(name, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public static partial class HealthCheckBuilderExtensions
|
|
||||||
{
|
|
||||||
// Numeric checks
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddMinValueCheck<T>(this HealthCheckBuilder builder, string name, T minValue, Func<T> currentValueFunc) where T : IComparable<T>
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return AddMinValueCheck(builder, name, minValue, currentValueFunc, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddMinValueCheck<T>(this HealthCheckBuilder builder, string name, T minValue, Func<T> currentValueFunc, TimeSpan cacheDuration)
|
|
||||||
where T : IComparable<T>
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
|
||||||
Guard.ArgumentNotNull(nameof(currentValueFunc), currentValueFunc);
|
|
||||||
|
|
||||||
builder.AddCheck(name, () =>
|
|
||||||
{
|
|
||||||
var currentValue = currentValueFunc();
|
|
||||||
var status = currentValue.CompareTo(minValue) >= 0 ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
|
||||||
return HealthCheckResult.FromStatus(
|
|
||||||
status,
|
|
||||||
$"min={minValue}, current={currentValue}",
|
|
||||||
new Dictionary<string, object> { { "min", minValue }, { "current", currentValue } }
|
|
||||||
);
|
|
||||||
}, cacheDuration);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddMaxValueCheck<T>(this HealthCheckBuilder builder, string name, T maxValue, Func<T> currentValueFunc) where T : IComparable<T>
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return AddMaxValueCheck(builder, name, maxValue, currentValueFunc, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddMaxValueCheck<T>(this HealthCheckBuilder builder, string name, T maxValue, Func<T> currentValueFunc, TimeSpan cacheDuration)
|
|
||||||
where T : IComparable<T>
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
|
||||||
Guard.ArgumentNotNull(nameof(currentValueFunc), currentValueFunc);
|
|
||||||
|
|
||||||
builder.AddCheck(name, () =>
|
|
||||||
{
|
|
||||||
var currentValue = currentValueFunc();
|
|
||||||
var status = currentValue.CompareTo(maxValue) <= 0 ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
|
||||||
return HealthCheckResult.FromStatus(
|
|
||||||
status,
|
|
||||||
$"max={maxValue}, current={currentValue}",
|
|
||||||
new Dictionary<string, object> { { "max", maxValue }, { "current", currentValue } }
|
|
||||||
);
|
|
||||||
}, cacheDuration);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public static partial class HealthCheckBuilderExtensions
|
|
||||||
{
|
|
||||||
// System checks
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddPrivateMemorySizeCheck(this HealthCheckBuilder builder, long maxSize)
|
|
||||||
=> AddMaxValueCheck(builder, $"PrivateMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().PrivateMemorySize64);
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddPrivateMemorySizeCheck(this HealthCheckBuilder builder, long maxSize, TimeSpan cacheDuration)
|
|
||||||
=> AddMaxValueCheck(builder, $"PrivateMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().PrivateMemorySize64, cacheDuration);
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddVirtualMemorySizeCheck(this HealthCheckBuilder builder, long maxSize)
|
|
||||||
=> AddMaxValueCheck(builder, $"VirtualMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().VirtualMemorySize64);
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddVirtualMemorySizeCheck(this HealthCheckBuilder builder, long maxSize, TimeSpan cacheDuration)
|
|
||||||
=> AddMaxValueCheck(builder, $"VirtualMemorySize({maxSize})", maxSize, () => Process.GetCurrentProcess().VirtualMemorySize64, cacheDuration);
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddWorkingSetCheck(this HealthCheckBuilder builder, long maxSize)
|
|
||||||
=> AddMaxValueCheck(builder, $"WorkingSet({maxSize})", maxSize, () => Process.GetCurrentProcess().WorkingSet64);
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddWorkingSetCheck(this HealthCheckBuilder builder, long maxSize, TimeSpan cacheDuration)
|
|
||||||
=> AddMaxValueCheck(builder, $"WorkingSet({maxSize})", maxSize, () => Process.GetCurrentProcess().WorkingSet64, cacheDuration);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Extensions.HealthChecks.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public static partial class HealthCheckBuilderExtensions
|
|
||||||
{
|
|
||||||
// Default URL check
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return AddUrlCheck(builder, url, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url, TimeSpan cacheDuration)
|
|
||||||
=> AddUrlCheck(builder, url, response => UrlChecker.DefaultUrlCheck(response), cacheDuration);
|
|
||||||
|
|
||||||
// Func returning IHealthCheckResult
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url, Func<HttpResponseMessage, IHealthCheckResult> checkFunc)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return AddUrlCheck(builder, url, checkFunc, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
|
||||||
Func<HttpResponseMessage, IHealthCheckResult> checkFunc,
|
|
||||||
TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
|
||||||
|
|
||||||
return AddUrlCheck(builder, url, response => new ValueTask<IHealthCheckResult>(checkFunc(response)), cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Func returning Task<IHealthCheckResult>
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url, Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return AddUrlCheck(builder, url, checkFunc, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
|
||||||
Func<HttpResponseMessage, Task<IHealthCheckResult>> checkFunc,
|
|
||||||
TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
|
||||||
|
|
||||||
return AddUrlCheck(builder, url, response => new ValueTask<IHealthCheckResult>(checkFunc(response)), cacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Func returning ValueTask<IHealthCheckResult>
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url, Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
|
|
||||||
return AddUrlCheck(builder, url, checkFunc, builder.DefaultCacheDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckBuilder AddUrlCheck(this HealthCheckBuilder builder, string url,
|
|
||||||
Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc,
|
|
||||||
TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(builder), builder);
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(url), url);
|
|
||||||
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
|
||||||
|
|
||||||
var urlCheck = new UrlChecker(checkFunc, url);
|
|
||||||
builder.AddCheck($"UrlCheck({url})", () => urlCheck.CheckAsync(), cacheDuration);
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a composite health check result built from several results.
|
|
||||||
/// </summary>
|
|
||||||
public class CompositeHealthCheckResult : IHealthCheckResult
|
|
||||||
{
|
|
||||||
private static readonly IReadOnlyDictionary<string, object> _emptyData = new Dictionary<string, object>();
|
|
||||||
private readonly CheckStatus _initialStatus;
|
|
||||||
private readonly CheckStatus _partiallyHealthyStatus;
|
|
||||||
private readonly Dictionary<string, IHealthCheckResult> _results = new Dictionary<string, IHealthCheckResult>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
public CompositeHealthCheckResult(CheckStatus partiallyHealthyStatus = CheckStatus.Warning,
|
|
||||||
CheckStatus initialStatus = CheckStatus.Unknown)
|
|
||||||
{
|
|
||||||
_partiallyHealthyStatus = partiallyHealthyStatus;
|
|
||||||
_initialStatus = initialStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CheckStatus CheckStatus
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var checkStatuses = new HashSet<CheckStatus>(_results.Select(x => x.Value.CheckStatus));
|
|
||||||
if (checkStatuses.Count == 0)
|
|
||||||
{
|
|
||||||
return _initialStatus;
|
|
||||||
}
|
|
||||||
if (checkStatuses.Count == 1)
|
|
||||||
{
|
|
||||||
return checkStatuses.First();
|
|
||||||
}
|
|
||||||
if (checkStatuses.Contains(CheckStatus.Healthy))
|
|
||||||
{
|
|
||||||
return _partiallyHealthyStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CheckStatus.Unhealthy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Description => string.Join(Environment.NewLine, _results.Select(r => $"{r.Key}: {r.Value.Description}"));
|
|
||||||
|
|
||||||
public IReadOnlyDictionary<string, object> Data
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var result = new Dictionary<string, object>();
|
|
||||||
|
|
||||||
foreach (var kvp in _results)
|
|
||||||
result.Add(kvp.Key, kvp.Value.Data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyDictionary<string, IHealthCheckResult> Results => _results;
|
|
||||||
|
|
||||||
public void Add(string name, CheckStatus status, string description)
|
|
||||||
=> Add(name, status, description, null);
|
|
||||||
|
|
||||||
public void Add(string name, CheckStatus status, string description, Dictionary<string, object> data)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
|
||||||
Guard.ArgumentValid(status != CheckStatus.Unknown, nameof(status), "Cannot add 'Unknown' status to composite health check result.");
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(description), description);
|
|
||||||
|
|
||||||
_results.Add(name, HealthCheckResult.FromStatus(status, description, data));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(string name, IHealthCheckResult checkResult)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(name), name);
|
|
||||||
Guard.ArgumentNotNull(nameof(checkResult), checkResult);
|
|
||||||
|
|
||||||
_results.Add(name, checkResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public class HealthCheck : IHealthCheck
|
|
||||||
{
|
|
||||||
protected HealthCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(check), check);
|
|
||||||
|
|
||||||
Check = check;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Func<CancellationToken, ValueTask<IHealthCheckResult>> Check { get; }
|
|
||||||
|
|
||||||
public ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken = default(CancellationToken))
|
|
||||||
=> Check(cancellationToken);
|
|
||||||
|
|
||||||
public static HealthCheck FromCheck(Func<IHealthCheckResult> check)
|
|
||||||
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()));
|
|
||||||
|
|
||||||
public static HealthCheck FromCheck(Func<CancellationToken, IHealthCheckResult> check)
|
|
||||||
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)));
|
|
||||||
|
|
||||||
public static HealthCheck FromTaskCheck(Func<Task<IHealthCheckResult>> check)
|
|
||||||
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check()));
|
|
||||||
|
|
||||||
public static HealthCheck FromTaskCheck(Func<CancellationToken, Task<IHealthCheckResult>> check)
|
|
||||||
=> new HealthCheck(token => new ValueTask<IHealthCheckResult>(check(token)));
|
|
||||||
|
|
||||||
public static HealthCheck FromValueTaskCheck(Func<ValueTask<IHealthCheckResult>> check)
|
|
||||||
=> new HealthCheck(token => check());
|
|
||||||
|
|
||||||
public static HealthCheck FromValueTaskCheck(Func<CancellationToken, ValueTask<IHealthCheckResult>> check)
|
|
||||||
=> new HealthCheck(check);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,135 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public class HealthCheckBuilder
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, CachedHealthCheck> _checksByName;
|
|
||||||
private readonly HealthCheckGroup _currentGroup;
|
|
||||||
private readonly Dictionary<string, HealthCheckGroup> _groups;
|
|
||||||
|
|
||||||
public HealthCheckBuilder()
|
|
||||||
{
|
|
||||||
_checksByName = new Dictionary<string, CachedHealthCheck>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
_currentGroup = new HealthCheckGroup(string.Empty, CheckStatus.Unhealthy);
|
|
||||||
_groups = new Dictionary<string, HealthCheckGroup>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
[string.Empty] = _currentGroup
|
|
||||||
};
|
|
||||||
|
|
||||||
DefaultCacheDuration = TimeSpan.FromMinutes(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This constructor should only be used when creating a grouped health check builder.
|
|
||||||
/// </summary>
|
|
||||||
public HealthCheckBuilder(HealthCheckBuilder rootBuilder, HealthCheckGroup currentGroup)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(rootBuilder), rootBuilder);
|
|
||||||
Guard.ArgumentNotNull(nameof(currentGroup), currentGroup);
|
|
||||||
|
|
||||||
_checksByName = rootBuilder._checksByName;
|
|
||||||
_currentGroup = currentGroup;
|
|
||||||
_groups = rootBuilder._groups;
|
|
||||||
|
|
||||||
DefaultCacheDuration = rootBuilder.DefaultCacheDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the registered checks, indexed by check name.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyDictionary<string, CachedHealthCheck> ChecksByName => _checksByName;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current default cache duration used when registering checks.
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan DefaultCacheDuration { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the registered groups, indexed by group name. The root group's name is <see cref="string.Empty"/>.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyDictionary<string, HealthCheckGroup> Groups => _groups;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers a health check type that will later be resolved via dependency
|
|
||||||
/// injection.
|
|
||||||
/// </summary>
|
|
||||||
public HealthCheckBuilder AddCheck<TCheck>(string checkName, TimeSpan cacheDuration) where TCheck : class, IHealthCheck
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(checkName), checkName);
|
|
||||||
Guard.ArgumentValid(!_checksByName.ContainsKey(checkName), nameof(checkName), $"A check with name '{checkName}' has already been registered.");
|
|
||||||
|
|
||||||
var namedCheck = CachedHealthCheck.FromType(checkName, cacheDuration, typeof(TCheck));
|
|
||||||
|
|
||||||
_checksByName.Add(checkName, namedCheck);
|
|
||||||
_currentGroup.ChecksInternal.Add(namedCheck);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers a concrete health check to the builder.
|
|
||||||
/// </summary>
|
|
||||||
public HealthCheckBuilder AddCheck(string checkName, IHealthCheck check, TimeSpan cacheDuration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(checkName), checkName);
|
|
||||||
Guard.ArgumentNotNull(nameof(check), check);
|
|
||||||
Guard.ArgumentValid(!_checksByName.ContainsKey(checkName), nameof(checkName), $"A check with name '{checkName}' has already been registered.");
|
|
||||||
|
|
||||||
var namedCheck = CachedHealthCheck.FromHealthCheck(checkName, cacheDuration, check);
|
|
||||||
|
|
||||||
_checksByName.Add(checkName, namedCheck);
|
|
||||||
_currentGroup.ChecksInternal.Add(namedCheck);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new health check group, to which you can add one or more health
|
|
||||||
/// checks. Uses <see cref="CheckStatus.Unhealthy"/> when the group is
|
|
||||||
/// partially successful.
|
|
||||||
/// </summary>
|
|
||||||
public HealthCheckBuilder AddHealthCheckGroup(string groupName, Action<HealthCheckBuilder> groupChecks)
|
|
||||||
=> AddHealthCheckGroup(groupName, groupChecks, CheckStatus.Unhealthy);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new health check group, to which you can add one or more health
|
|
||||||
/// checks.
|
|
||||||
/// </summary>
|
|
||||||
public HealthCheckBuilder AddHealthCheckGroup(string groupName, Action<HealthCheckBuilder> groupChecks, CheckStatus partialSuccessStatus)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(groupName), groupName);
|
|
||||||
Guard.ArgumentNotNull(nameof(groupChecks), groupChecks);
|
|
||||||
Guard.ArgumentValid(partialSuccessStatus != CheckStatus.Unknown, nameof(partialSuccessStatus), "Check status 'Unknown' is not valid for partial success.");
|
|
||||||
Guard.ArgumentValid(!_groups.ContainsKey(groupName), nameof(groupName), $"A group with name '{groupName}' has already been registered.");
|
|
||||||
Guard.OperationValid(_currentGroup.GroupName == string.Empty, "Nested groups are not supported by HealthCheckBuilder.");
|
|
||||||
|
|
||||||
var group = new HealthCheckGroup(groupName, partialSuccessStatus);
|
|
||||||
_groups.Add(groupName, group);
|
|
||||||
|
|
||||||
var innerBuilder = new HealthCheckBuilder(this, group);
|
|
||||||
groupChecks(innerBuilder);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HealthCheckBuilder WithDefaultCacheDuration(TimeSpan duration)
|
|
||||||
{
|
|
||||||
Guard.ArgumentValid(duration >= TimeSpan.Zero, nameof(duration), "Duration must be zero (disabled) or a positive duration.");
|
|
||||||
|
|
||||||
DefaultCacheDuration = duration;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HealthCheckBuilder WithPartialSuccessStatus(CheckStatus partiallyHealthyStatus)
|
|
||||||
{
|
|
||||||
_currentGroup.PartiallyHealthyStatus = partiallyHealthyStatus;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public class HealthCheckGroup
|
|
||||||
{
|
|
||||||
private CheckStatus _partialSuccessStatus;
|
|
||||||
|
|
||||||
public HealthCheckGroup(string groupName, CheckStatus partialSuccessStatus)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(groupName), groupName);
|
|
||||||
|
|
||||||
GroupName = groupName;
|
|
||||||
PartiallyHealthyStatus = partialSuccessStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<CachedHealthCheck> Checks => ChecksInternal.AsReadOnly();
|
|
||||||
|
|
||||||
internal List<CachedHealthCheck> ChecksInternal { get; } = new List<CachedHealthCheck>();
|
|
||||||
|
|
||||||
public string GroupName { get; }
|
|
||||||
|
|
||||||
public CheckStatus PartiallyHealthyStatus
|
|
||||||
{
|
|
||||||
get => _partialSuccessStatus;
|
|
||||||
internal set
|
|
||||||
{
|
|
||||||
Guard.ArgumentValid(value != CheckStatus.Unknown, nameof(value), "Check status 'Unknown' is not valid for partial success.");
|
|
||||||
|
|
||||||
_partialSuccessStatus = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public class HealthCheckResult : IHealthCheckResult
|
|
||||||
{
|
|
||||||
private static readonly IReadOnlyDictionary<string, object> _emptyData = new Dictionary<string, object>();
|
|
||||||
|
|
||||||
public CheckStatus CheckStatus { get; }
|
|
||||||
public IReadOnlyDictionary<string, object> Data { get; }
|
|
||||||
public string Description { get; }
|
|
||||||
|
|
||||||
private HealthCheckResult(CheckStatus checkStatus, string description, IReadOnlyDictionary<string, object> data)
|
|
||||||
{
|
|
||||||
CheckStatus = checkStatus;
|
|
||||||
Description = description;
|
|
||||||
Data = data ?? _emptyData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HealthCheckResult Unhealthy(string description)
|
|
||||||
=> new HealthCheckResult(CheckStatus.Unhealthy, description, null);
|
|
||||||
|
|
||||||
public static HealthCheckResult Unhealthy(string description, IReadOnlyDictionary<string, object> data)
|
|
||||||
=> new HealthCheckResult(CheckStatus.Unhealthy, description, data);
|
|
||||||
|
|
||||||
public static HealthCheckResult Healthy(string description)
|
|
||||||
=> new HealthCheckResult(CheckStatus.Healthy, description, null);
|
|
||||||
|
|
||||||
public static HealthCheckResult Healthy(string description, IReadOnlyDictionary<string, object> data)
|
|
||||||
=> new HealthCheckResult(CheckStatus.Healthy, description, data);
|
|
||||||
|
|
||||||
public static HealthCheckResult Warning(string description)
|
|
||||||
=> new HealthCheckResult(CheckStatus.Warning, description, null);
|
|
||||||
|
|
||||||
public static HealthCheckResult Warning(string description, IReadOnlyDictionary<string, object> data)
|
|
||||||
=> new HealthCheckResult(CheckStatus.Warning, description, data);
|
|
||||||
|
|
||||||
public static HealthCheckResult Unknown(string description)
|
|
||||||
=> new HealthCheckResult(CheckStatus.Unknown, description, null);
|
|
||||||
|
|
||||||
public static HealthCheckResult Unknown(string description, IReadOnlyDictionary<string, object> data)
|
|
||||||
=> new HealthCheckResult(CheckStatus.Unknown, description, data);
|
|
||||||
|
|
||||||
public static HealthCheckResult FromStatus(CheckStatus status, string description)
|
|
||||||
=> new HealthCheckResult(status, description, null);
|
|
||||||
|
|
||||||
public static HealthCheckResult FromStatus(CheckStatus status, string description, IReadOnlyDictionary<string, object> data)
|
|
||||||
=> new HealthCheckResult(status, description, data);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public class HealthCheckResults
|
|
||||||
{
|
|
||||||
public IList<IHealthCheckResult> CheckResults { get; } = new List<IHealthCheckResult>();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,119 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public class HealthCheckService : IHealthCheckService
|
|
||||||
{
|
|
||||||
private readonly HealthCheckBuilder _builder;
|
|
||||||
private readonly IReadOnlyList<HealthCheckGroup> _groups;
|
|
||||||
private readonly HealthCheckGroup _root;
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
|
||||||
|
|
||||||
public HealthCheckService(HealthCheckBuilder builder, IServiceProvider serviceProvider, IServiceScopeFactory serviceScopeFactory)
|
|
||||||
{
|
|
||||||
_builder = builder;
|
|
||||||
_groups = GetGroups().Where(group => group.GroupName != string.Empty).ToList();
|
|
||||||
_root = GetGroup(string.Empty);
|
|
||||||
_serviceProvider = serviceProvider;
|
|
||||||
_serviceScopeFactory = serviceScopeFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<CompositeHealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken))
|
|
||||||
{
|
|
||||||
using (var scope = GetServiceScope())
|
|
||||||
{
|
|
||||||
var scopeServiceProvider = scope.ServiceProvider;
|
|
||||||
var groupTasks = _groups.Select(group => new { Group = group, Task = RunGroupAsync(scopeServiceProvider, group, cancellationToken) }).ToList();
|
|
||||||
var result = await RunGroupAsync(scopeServiceProvider, _root, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
await Task.WhenAll(groupTasks.Select(x => x.Task));
|
|
||||||
|
|
||||||
foreach (var groupTask in groupTasks)
|
|
||||||
{
|
|
||||||
result.Add($"Group({groupTask.Group.GroupName})", groupTask.Task.Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<CachedHealthCheck> GetAllChecks()
|
|
||||||
=> _builder.ChecksByName.Values.ToList().AsReadOnly();
|
|
||||||
|
|
||||||
public CachedHealthCheck GetCheck(string checkName)
|
|
||||||
=> _builder.ChecksByName[checkName];
|
|
||||||
|
|
||||||
public HealthCheckGroup GetGroup(string groupName)
|
|
||||||
=> _builder.Groups[groupName];
|
|
||||||
|
|
||||||
public IReadOnlyList<HealthCheckGroup> GetGroups()
|
|
||||||
=> _builder.Groups.Values.ToList().AsReadOnly();
|
|
||||||
|
|
||||||
private IServiceScope GetServiceScope()
|
|
||||||
=> _serviceScopeFactory == null ? new UnscopedServiceProvider(_serviceProvider) : _serviceScopeFactory.CreateScope();
|
|
||||||
|
|
||||||
public async ValueTask<IHealthCheckResult> RunCheckAsync(CachedHealthCheck healthCheck, CancellationToken cancellationToken = default(CancellationToken))
|
|
||||||
{
|
|
||||||
using (var scope = GetServiceScope())
|
|
||||||
{
|
|
||||||
return await RunCheckAsync(scope.ServiceProvider, healthCheck, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses the provided service provider and executes the provided check.
|
|
||||||
/// </summary>
|
|
||||||
public ValueTask<IHealthCheckResult> RunCheckAsync(IServiceProvider serviceProvider, CachedHealthCheck healthCheck, CancellationToken cancellationToken = default(CancellationToken))
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(serviceProvider), serviceProvider);
|
|
||||||
Guard.ArgumentNotNull(nameof(healthCheck), healthCheck);
|
|
||||||
|
|
||||||
return healthCheck.RunAsync(serviceProvider, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new resolution scope from the default service provider and executes the checks in the given group.
|
|
||||||
/// </summary>
|
|
||||||
public async Task<CompositeHealthCheckResult> RunGroupAsync(HealthCheckGroup group, CancellationToken cancellationToken = default(CancellationToken))
|
|
||||||
{
|
|
||||||
using (var scope = GetServiceScope())
|
|
||||||
return await RunGroupAsync(scope.ServiceProvider, group, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses the provided service provider and executes the checks in the given group.
|
|
||||||
/// </summary>
|
|
||||||
public async Task<CompositeHealthCheckResult> RunGroupAsync(IServiceProvider serviceProvider, HealthCheckGroup group, CancellationToken cancellationToken = default(CancellationToken))
|
|
||||||
{
|
|
||||||
var result = new CompositeHealthCheckResult(group.PartiallyHealthyStatus);
|
|
||||||
var checkTasks = group.Checks.Select(check => new { Check = check, Task = check.RunAsync(serviceProvider, cancellationToken).AsTask() }).ToList();
|
|
||||||
await Task.WhenAll(checkTasks.Select(checkTask => checkTask.Task));
|
|
||||||
|
|
||||||
foreach (var checkTask in checkTasks)
|
|
||||||
{
|
|
||||||
result.Add(checkTask.Check.Name, checkTask.Task.Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class UnscopedServiceProvider : IServiceScope
|
|
||||||
{
|
|
||||||
public UnscopedServiceProvider(IServiceProvider serviceProvider)
|
|
||||||
=> ServiceProvider = serviceProvider;
|
|
||||||
|
|
||||||
public IServiceProvider ServiceProvider { get; }
|
|
||||||
|
|
||||||
public void Dispose() { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Extensions.HealthChecks;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyInjection
|
|
||||||
{
|
|
||||||
public static class HealthCheckServiceCollectionExtensions
|
|
||||||
{
|
|
||||||
private static readonly Type HealthCheckServiceInterface = typeof(IHealthCheckService);
|
|
||||||
|
|
||||||
public static IServiceCollection AddHealthChecks(this IServiceCollection services, Action<HealthCheckBuilder> checks)
|
|
||||||
{
|
|
||||||
Guard.OperationValid(!services.Any(descriptor => descriptor.ServiceType == HealthCheckServiceInterface), "AddHealthChecks may only be called once.");
|
|
||||||
|
|
||||||
var builder = new HealthCheckBuilder();
|
|
||||||
|
|
||||||
services.AddSingleton<IHealthCheckService, HealthCheckService>(serviceProvider =>
|
|
||||||
{
|
|
||||||
var serviceScopeFactory = serviceProvider.GetService<IServiceScopeFactory>();
|
|
||||||
return new HealthCheckService(builder, serviceProvider, serviceScopeFactory);
|
|
||||||
});
|
|
||||||
|
|
||||||
checks(builder);
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public interface IHealthCheck
|
|
||||||
{
|
|
||||||
ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken = default(CancellationToken));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public interface IHealthCheckResult
|
|
||||||
{
|
|
||||||
CheckStatus CheckStatus { get; }
|
|
||||||
string Description { get; }
|
|
||||||
IReadOnlyDictionary<string, object> Data { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks
|
|
||||||
{
|
|
||||||
public interface IHealthCheckService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Runs all registered health checks.
|
|
||||||
/// </summary>
|
|
||||||
Task<CompositeHealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all registered health checks as a flat list.
|
|
||||||
/// </summary>
|
|
||||||
IReadOnlyList<CachedHealthCheck> GetAllChecks();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a health check by name.
|
|
||||||
/// </summary>
|
|
||||||
CachedHealthCheck GetCheck(string checkName);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all health checks in a group.
|
|
||||||
/// </summary>
|
|
||||||
HealthCheckGroup GetGroup(string groupName);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all the health check groups.
|
|
||||||
/// </summary>
|
|
||||||
IReadOnlyList<HealthCheckGroup> GetGroups();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new resolution scope from the default service provider and executes the provided check.
|
|
||||||
/// </summary>
|
|
||||||
ValueTask<IHealthCheckResult> RunCheckAsync(CachedHealthCheck healthCheck, CancellationToken cancellationToken = default(CancellationToken));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses the provided service provider and executes the provided check.
|
|
||||||
/// </summary>
|
|
||||||
ValueTask<IHealthCheckResult> RunCheckAsync(IServiceProvider serviceProvider, CachedHealthCheck healthCheck, CancellationToken cancellationToken = default(CancellationToken));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new resolution scope from the default service provider and executes the checks in the given group.
|
|
||||||
/// </summary>
|
|
||||||
Task<CompositeHealthCheckResult> RunGroupAsync(HealthCheckGroup group, CancellationToken cancellationToken = default(CancellationToken));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses the provided service provider and executes the checks in the given group.
|
|
||||||
/// </summary>
|
|
||||||
Task<CompositeHealthCheckResult> RunGroupAsync(IServiceProvider serviceProvider, HealthCheckGroup group, CancellationToken cancellationToken = default(CancellationToken));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.HealthChecks.Internal
|
|
||||||
{
|
|
||||||
public class UrlChecker
|
|
||||||
{
|
|
||||||
private readonly Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> _checkFunc;
|
|
||||||
private readonly string _url;
|
|
||||||
|
|
||||||
public UrlChecker(Func<HttpResponseMessage, ValueTask<IHealthCheckResult>> checkFunc, string url)
|
|
||||||
{
|
|
||||||
Guard.ArgumentNotNull(nameof(checkFunc), checkFunc);
|
|
||||||
Guard.ArgumentNotNullOrEmpty(nameof(url), url);
|
|
||||||
|
|
||||||
_checkFunc = checkFunc;
|
|
||||||
_url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CheckStatus PartiallyHealthyStatus { get; set; } = CheckStatus.Warning;
|
|
||||||
|
|
||||||
public async Task<IHealthCheckResult> CheckAsync()
|
|
||||||
{
|
|
||||||
using (var httpClient = CreateHttpClient())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await httpClient.GetAsync(_url).ConfigureAwait(false);
|
|
||||||
return await _checkFunc(response);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
var data = new Dictionary<string, object> { { "url", _url } };
|
|
||||||
return HealthCheckResult.Unhealthy($"Exception during check: {ex.GetType().FullName}", data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpClient CreateHttpClient()
|
|
||||||
{
|
|
||||||
var httpClient = GetHttpClient();
|
|
||||||
httpClient.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true };
|
|
||||||
return httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async ValueTask<IHealthCheckResult> DefaultUrlCheck(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
var status = response.IsSuccessStatusCode ? CheckStatus.Healthy : CheckStatus.Unhealthy;
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "url", response.RequestMessage.RequestUri.ToString() },
|
|
||||||
{ "status", (int)response.StatusCode },
|
|
||||||
{ "reason", response.ReasonPhrase },
|
|
||||||
{ "body", await response.Content?.ReadAsStringAsync() }
|
|
||||||
};
|
|
||||||
return HealthCheckResult.FromStatus(status, $"status code {response.StatusCode} ({(int)response.StatusCode})", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual HttpClient GetHttpClient()
|
|
||||||
=> new HttpClient();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\common\Guard.cs" Link="Internal\Guard.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
|
||||||
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
|
||||||
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
|
|
||||||
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
|
|
||||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,57 +0,0 @@
|
|||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
static class Guard
|
|
||||||
{
|
|
||||||
public static void ArgumentNotNull(string argumentName, object value)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(argumentName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ArgumentNotNullOrEmpty(string argumentName, string value)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(argumentName);
|
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Value cannot be an empty string.", argumentName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use IReadOnlyCollection<T> instead of IEnumerable<T> to discourage double enumeration
|
|
||||||
public static void ArgumentNotNullOrEmpty<T>(string argumentName, IReadOnlyCollection<T> items)
|
|
||||||
{
|
|
||||||
if (items == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(argumentName);
|
|
||||||
}
|
|
||||||
if (items.Count == 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Collection must contain at least one item.", argumentName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ArgumentValid(bool valid, string argumentName, string exceptionMessage)
|
|
||||||
{
|
|
||||||
if (!valid)
|
|
||||||
{
|
|
||||||
throw new ArgumentException(exceptionMessage, argumentName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void OperationValid(bool valid, string exceptionMessage)
|
|
||||||
{
|
|
||||||
if (!valid)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(exceptionMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Polly" Version="6.0.1" />
|
<PackageReference Include="Polly" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
|
||||||
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
<DockerComposeProjectPath>..\..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -13,26 +13,32 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0" />
|
||||||
|
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.6" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||||
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.4" />
|
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.4" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -13,54 +13,44 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
|
|||||||
{
|
{
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class BasketController : Controller
|
[ApiController]
|
||||||
|
public class BasketController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IBasketRepository _repository;
|
private readonly IBasketRepository _repository;
|
||||||
private readonly IIdentityService _identitySvc;
|
private readonly IIdentityService _identityService;
|
||||||
private readonly IEventBus _eventBus;
|
private readonly IEventBus _eventBus;
|
||||||
|
|
||||||
public BasketController(IBasketRepository repository,
|
public BasketController(IBasketRepository repository, IIdentityService identityService, IEventBus eventBus)
|
||||||
IIdentityService identityService,
|
|
||||||
IEventBus eventBus)
|
|
||||||
{
|
{
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
_identitySvc = identityService;
|
_identityService = identityService;
|
||||||
_eventBus = eventBus;
|
_eventBus = eventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET /id
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> Get(string id)
|
public async Task<ActionResult<CustomerBasket>> GetBasketByIdAsync(string id)
|
||||||
{
|
{
|
||||||
var basket = await _repository.GetBasketAsync(id);
|
var basket = await _repository.GetBasketAsync(id);
|
||||||
if (basket == null)
|
|
||||||
{
|
|
||||||
return Ok(new CustomerBasket(id) { });
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(basket);
|
return basket ?? new CustomerBasket(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST /value
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> Post([FromBody]CustomerBasket value)
|
public async Task<ActionResult<CustomerBasket>> UpdateBasketAsync([FromBody]CustomerBasket value)
|
||||||
{
|
{
|
||||||
var basket = await _repository.UpdateBasketAsync(value);
|
return await _repository.UpdateBasketAsync(value);
|
||||||
|
|
||||||
return Ok(basket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("checkout")]
|
[Route("checkout")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ProducesResponseType((int)HttpStatusCode.Accepted)]
|
[ProducesResponseType((int)HttpStatusCode.Accepted)]
|
||||||
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
public async Task<IActionResult> Checkout([FromBody]BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId)
|
public async Task<ActionResult> CheckoutAsync([FromBody]BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId)
|
||||||
{
|
{
|
||||||
var userId = _identitySvc.GetUserIdentity();
|
var userId = _identityService.GetUserIdentity();
|
||||||
|
|
||||||
|
|
||||||
basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ?
|
basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ?
|
||||||
guid : basketCheckout.RequestId;
|
guid : basketCheckout.RequestId;
|
||||||
|
|
||||||
@ -80,17 +70,17 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
|
|||||||
// Once basket is checkout, sends an integration event to
|
// Once basket is checkout, sends an integration event to
|
||||||
// ordering.api to convert basket to order and proceeds with
|
// ordering.api to convert basket to order and proceeds with
|
||||||
// order creation process
|
// order creation process
|
||||||
_eventBus.Publish(eventMessage);
|
_eventBus.Publish(eventMessage);
|
||||||
|
|
||||||
return Accepted();
|
return Accepted();
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE api/values/5
|
// DELETE api/values/5
|
||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
public void Delete(string id)
|
[ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task DeleteBasketByIdAsync(string id)
|
||||||
{
|
{
|
||||||
_repository.DeleteBasketAsync(id);
|
await _repository.DeleteBasketAsync(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
|
FROM microsoft/dotnet:2.2.0-aspnetcore-runtime AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
FROM microsoft/dotnet:2.1-sdk AS build
|
FROM microsoft/dotnet:2.2.100-sdk AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR /src/src/Services/Basket/Basket.API
|
WORKDIR /src/src/Services/Basket/Basket.API
|
||||||
|
@ -10,7 +10,6 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
public class RedisBasketRepository : IBasketRepository
|
public class RedisBasketRepository : IBasketRepository
|
||||||
{
|
{
|
||||||
private readonly ILogger<RedisBasketRepository> _logger;
|
private readonly ILogger<RedisBasketRepository> _logger;
|
||||||
|
|
||||||
private readonly ConnectionMultiplexer _redis;
|
private readonly ConnectionMultiplexer _redis;
|
||||||
private readonly IDatabase _database;
|
private readonly IDatabase _database;
|
||||||
|
|
||||||
@ -30,12 +29,14 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
{
|
{
|
||||||
var server = GetServer();
|
var server = GetServer();
|
||||||
var data = server.Keys();
|
var data = server.Keys();
|
||||||
|
|
||||||
return data?.Select(k => k.ToString());
|
return data?.Select(k => k.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CustomerBasket> GetBasketAsync(string customerId)
|
public async Task<CustomerBasket> GetBasketAsync(string customerId)
|
||||||
{
|
{
|
||||||
var data = await _database.StringGetAsync(customerId);
|
var data = await _database.StringGetAsync(customerId);
|
||||||
|
|
||||||
if (data.IsNullOrEmpty)
|
if (data.IsNullOrEmpty)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@ -47,6 +48,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
public async Task<CustomerBasket> UpdateBasketAsync(CustomerBasket basket)
|
public async Task<CustomerBasket> UpdateBasketAsync(CustomerBasket basket)
|
||||||
{
|
{
|
||||||
var created = await _database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket));
|
var created = await _database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket));
|
||||||
|
|
||||||
if (!created)
|
if (!created)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Problem occur persisting the item.");
|
_logger.LogInformation("Problem occur persisting the item.");
|
||||||
|
@ -23,7 +23,6 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
{
|
{
|
||||||
options.ConfigPath = "/Failing";
|
options.ConfigPath = "/Failing";
|
||||||
})
|
})
|
||||||
.UseHealthChecks("/hc")
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.ConfigureAppConfiguration((builderContext, config) =>
|
.ConfigureAppConfiguration((builderContext, config) =>
|
||||||
|
@ -4,12 +4,16 @@ using Basket.API.Infrastructure.Filters;
|
|||||||
using Basket.API.Infrastructure.Middlewares;
|
using Basket.API.Infrastructure.Middlewares;
|
||||||
using Basket.API.IntegrationEvents.EventHandling;
|
using Basket.API.IntegrationEvents.EventHandling;
|
||||||
using Basket.API.IntegrationEvents.Events;
|
using Basket.API.IntegrationEvents.Events;
|
||||||
|
using HealthChecks.UI.Client;
|
||||||
|
|
||||||
using Microsoft.ApplicationInsights.Extensibility;
|
using Microsoft.ApplicationInsights.Extensibility;
|
||||||
using Microsoft.ApplicationInsights.ServiceFabric;
|
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Azure.ServiceBus;
|
using Microsoft.Azure.ServiceBus;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
@ -21,7 +25,7 @@ using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
|||||||
using Microsoft.eShopOnContainers.Services.Basket.API.Services;
|
using Microsoft.eShopOnContainers.Services.Basket.API.Services;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.HealthChecks;
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
@ -30,7 +34,6 @@ using Swashbuckle.AspNetCore.Swagger;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||||
{
|
{
|
||||||
@ -51,20 +54,17 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddMvc(options =>
|
services.AddMvc(options =>
|
||||||
{
|
{
|
||||||
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||||
options.Filters.Add(typeof(ValidateModelStateFilter));
|
options.Filters.Add(typeof(ValidateModelStateFilter));
|
||||||
|
|
||||||
}).AddControllersAsServices();
|
})
|
||||||
|
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
|
||||||
|
.AddControllersAsServices();
|
||||||
|
|
||||||
ConfigureAuthService(services);
|
ConfigureAuthService(services);
|
||||||
|
|
||||||
services.AddHealthChecks(checks =>
|
services.AddCustomHealthCheck(Configuration);
|
||||||
{
|
|
||||||
checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask<IHealthCheckResult>(HealthCheckResult.Healthy("Ok")),
|
|
||||||
TimeSpan.Zero //No cache for this HealthCheck, better just for demos
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
services.Configure<BasketSettings>(Configuration);
|
services.Configure<BasketSettings>(Configuration);
|
||||||
|
|
||||||
@ -189,10 +189,16 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
app.UsePathBase(pathBase);
|
app.UsePathBase(pathBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
Predicate = _ => true,
|
||||||
|
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||||
|
});
|
||||||
|
|
||||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
app.UseHealthChecks("/liveness", new HealthCheckOptions
|
||||||
app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200));
|
{
|
||||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
Predicate = r => r.Name.Contains("self")
|
||||||
|
});
|
||||||
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
app.UseCors("CorsPolicy");
|
app.UseCors("CorsPolicy");
|
||||||
@ -309,6 +315,42 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
|
|
||||||
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
|
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
|
||||||
eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>();
|
eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CustomExtensionMethods
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
var hcBuilder = services.AddHealthChecks();
|
||||||
|
|
||||||
|
hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy());
|
||||||
|
|
||||||
|
hcBuilder
|
||||||
|
.AddRedis(
|
||||||
|
configuration["ConnectionString"],
|
||||||
|
name: "redis-check",
|
||||||
|
tags: new string[] { "redis" });
|
||||||
|
|
||||||
|
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||||
|
{
|
||||||
|
hcBuilder
|
||||||
|
.AddAzureServiceBusTopic(
|
||||||
|
configuration["EventBusConnection"],
|
||||||
|
topicName: "eshop_event_bus",
|
||||||
|
name: "basket-servicebus-check",
|
||||||
|
tags: new string[] { "servicebus" });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hcBuilder
|
||||||
|
.AddRabbitMQ(
|
||||||
|
$"amqp://{configuration["EventBusConnection"]}",
|
||||||
|
name: "basket-rabbitmqbus-check",
|
||||||
|
tags: new string[] { "rabbitmqbus" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.2.0" />
|
||||||
<PackageReference Include="xunit" Version="2.3.1" />
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||||
|
@ -44,10 +44,10 @@ namespace UnitTest.Basket.Application
|
|||||||
//Act
|
//Act
|
||||||
var basketController = new BasketController(
|
var basketController = new BasketController(
|
||||||
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
|
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
|
||||||
var actionResult = await basketController.Get(fakeCustomerId) as OkObjectResult;
|
var actionResult = await basketController.GetBasketByIdAsync(fakeCustomerId);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK);
|
Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK);
|
||||||
Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId);
|
Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,10 +67,10 @@ namespace UnitTest.Basket.Application
|
|||||||
var basketController = new BasketController(
|
var basketController = new BasketController(
|
||||||
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
|
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
|
||||||
|
|
||||||
var actionResult = await basketController.Post(fakeCustomerBasket) as OkObjectResult;
|
var actionResult = await basketController.UpdateBasketAsync(fakeCustomerBasket);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK);
|
Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK);
|
||||||
Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId);
|
Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ namespace UnitTest.Basket.Application
|
|||||||
var basketController = new BasketController(
|
var basketController = new BasketController(
|
||||||
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
|
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
|
||||||
|
|
||||||
var result = await basketController.Checkout(new BasketCheckout(), Guid.NewGuid().ToString()) as BadRequestResult;
|
var result = await basketController.CheckoutAsync(new BasketCheckout(), Guid.NewGuid().ToString()) as BadRequestResult;
|
||||||
Assert.NotNull(result);
|
Assert.NotNull(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ namespace UnitTest.Basket.Application
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
var result = await basketController.Checkout(new BasketCheckout(), Guid.NewGuid().ToString()) as AcceptedResult;
|
var result = await basketController.CheckoutAsync(new BasketCheckout(), Guid.NewGuid().ToString()) as AcceptedResult;
|
||||||
|
|
||||||
_serviceBusMock.Verify(mock => mock.Publish(It.IsAny<UserCheckoutAcceptedIntegrationEvent>()), Times.Once);
|
_serviceBusMock.Verify(mock => mock.Publish(It.IsAny<UserCheckoutAcceptedIntegrationEvent>()), Times.Once);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||||
<AssemblyName>Catalog.API</AssemblyName>
|
<AssemblyName>Catalog.API</AssemblyName>
|
||||||
@ -34,14 +34,22 @@
|
|||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.AzureStorage" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="2.2.0" />
|
||||||
|
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.1.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" />
|
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
||||||
@ -52,10 +60,6 @@
|
|||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -28,7 +28,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
_catalogIntegrationEventService = catalogIntegrationEventService ?? throw new ArgumentNullException(nameof(catalogIntegrationEventService));
|
_catalogIntegrationEventService = catalogIntegrationEventService ?? throw new ArgumentNullException(nameof(catalogIntegrationEventService));
|
||||||
_settings = settings.Value;
|
_settings = settings.Value;
|
||||||
|
|
||||||
((DbContext)context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/v1/[controller]/items[?pageSize=3&pageIndex=10]
|
// GET api/v1/[controller]/items[?pageSize=3&pageIndex=10]
|
||||||
@ -36,11 +36,19 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[Route("items")]
|
[Route("items")]
|
||||||
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
||||||
[ProducesResponseType(typeof(IEnumerable<CatalogItem>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(IEnumerable<CatalogItem>), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0, [FromQuery] string ids = null)
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
|
public async Task<IActionResult> ItemsAsync([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0, string ids = null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(ids))
|
if (!string.IsNullOrEmpty(ids))
|
||||||
{
|
{
|
||||||
return GetItemsByIds(ids);
|
var items = await GetItemsByIdsAsync(ids);
|
||||||
|
|
||||||
|
if (!items.Any())
|
||||||
|
{
|
||||||
|
return BadRequest("ids value invalid. Must be comma-separated list of numbers");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalItems = await _catalogContext.CatalogItems
|
var totalItems = await _catalogContext.CatalogItems
|
||||||
@ -54,37 +62,36 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
|
|
||||||
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
|
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
|
||||||
|
|
||||||
var model = new PaginatedItemsViewModel<CatalogItem>(
|
var model = new PaginatedItemsViewModel<CatalogItem>(pageIndex, pageSize, totalItems, itemsOnPage);
|
||||||
pageIndex, pageSize, totalItems, itemsOnPage);
|
|
||||||
|
|
||||||
return Ok(model);
|
return Ok(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IActionResult GetItemsByIds(string ids)
|
private async Task<List<CatalogItem>> GetItemsByIdsAsync(string ids)
|
||||||
{
|
{
|
||||||
var numIds = ids.Split(',')
|
var numIds = ids.Split(',').Select(id => (Ok: int.TryParse(id, out int x), Value: x));
|
||||||
.Select(id => (Ok: int.TryParse(id, out int x), Value: x));
|
|
||||||
|
|
||||||
if (!numIds.All(nid => nid.Ok))
|
if (!numIds.All(nid => nid.Ok))
|
||||||
{
|
{
|
||||||
return BadRequest("ids value invalid. Must be comma-separated list of numbers");
|
return new List<CatalogItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var idsToSelect = numIds
|
var idsToSelect = numIds
|
||||||
.Select(id => id.Value);
|
.Select(id => id.Value);
|
||||||
|
|
||||||
var items = _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToList();
|
var items = await _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToListAsync();
|
||||||
|
|
||||||
items = ChangeUriPlaceholder(items);
|
items = ChangeUriPlaceholder(items);
|
||||||
|
|
||||||
return Ok(items);
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("items/{id:int}")]
|
[Route("items/{id:int}")]
|
||||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
[ProducesResponseType(typeof(CatalogItem), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(CatalogItem), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> GetItemById(int id)
|
public async Task<ActionResult<CatalogItem>> ItemByIdAsync(int id)
|
||||||
{
|
{
|
||||||
if (id <= 0)
|
if (id <= 0)
|
||||||
{
|
{
|
||||||
@ -95,11 +102,12 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
|
|
||||||
var baseUri = _settings.PicBaseUrl;
|
var baseUri = _settings.PicBaseUrl;
|
||||||
var azureStorageEnabled = _settings.AzureStorageEnabled;
|
var azureStorageEnabled = _settings.AzureStorageEnabled;
|
||||||
|
|
||||||
item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled);
|
item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled);
|
||||||
|
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
return Ok(item);
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NotFound();
|
return NotFound();
|
||||||
@ -107,11 +115,10 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
|
|
||||||
// GET api/v1/[controller]/items/withname/samplename[?pageSize=3&pageIndex=10]
|
// GET api/v1/[controller]/items/withname/samplename[?pageSize=3&pageIndex=10]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("[action]/withname/{name:minlength(1)}")]
|
[Route("items/withname/{name:minlength(1)}")]
|
||||||
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> Items(string name, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<ActionResult<PaginatedItemsViewModel<CatalogItem>>> ItemsWithNameAsync(string name, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
var totalItems = await _catalogContext.CatalogItems
|
var totalItems = await _catalogContext.CatalogItems
|
||||||
.Where(c => c.Name.StartsWith(name))
|
.Where(c => c.Name.StartsWith(name))
|
||||||
.LongCountAsync();
|
.LongCountAsync();
|
||||||
@ -124,17 +131,14 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
|
|
||||||
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
|
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
|
||||||
|
|
||||||
var model = new PaginatedItemsViewModel<CatalogItem>(
|
return new PaginatedItemsViewModel<CatalogItem>(pageIndex, pageSize, totalItems, itemsOnPage);
|
||||||
pageIndex, pageSize, totalItems, itemsOnPage);
|
|
||||||
|
|
||||||
return Ok(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/v1/[controller]/items/type/1/brand[?pageSize=3&pageIndex=10]
|
// GET api/v1/[controller]/items/type/1/brand[?pageSize=3&pageIndex=10]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("[action]/type/{catalogTypeId}/brand/{catalogBrandId:int?}")]
|
[Route("items/type/{catalogTypeId}/brand/{catalogBrandId:int?}")]
|
||||||
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> Items(int catalogTypeId, int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<ActionResult<PaginatedItemsViewModel<CatalogItem>>> ItemsByTypeIdAndBrandIdAsync(int catalogTypeId, int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
{
|
{
|
||||||
var root = (IQueryable<CatalogItem>)_catalogContext.CatalogItems;
|
var root = (IQueryable<CatalogItem>)_catalogContext.CatalogItems;
|
||||||
|
|
||||||
@ -155,16 +159,14 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
|
|
||||||
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
|
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
|
||||||
|
|
||||||
var model = new PaginatedItemsViewModel<CatalogItem>(
|
return new PaginatedItemsViewModel<CatalogItem>(pageIndex, pageSize, totalItems, itemsOnPage);
|
||||||
pageIndex, pageSize, totalItems, itemsOnPage);
|
|
||||||
|
|
||||||
return Ok(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/v1/[controller]/items/type/all/brand[?pageSize=3&pageIndex=10]
|
// GET api/v1/[controller]/items/type/all/brand[?pageSize=3&pageIndex=10]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("[action]/type/all/brand/{catalogBrandId:int?}")]
|
[Route("items/type/all/brand/{catalogBrandId:int?}")]
|
||||||
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> Items(int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<ActionResult<PaginatedItemsViewModel<CatalogItem>>> ItemsByBrandIdAsync(int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
{
|
{
|
||||||
var root = (IQueryable<CatalogItem>)_catalogContext.CatalogItems;
|
var root = (IQueryable<CatalogItem>)_catalogContext.CatalogItems;
|
||||||
|
|
||||||
@ -183,34 +185,25 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
|
|
||||||
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
|
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
|
||||||
|
|
||||||
var model = new PaginatedItemsViewModel<CatalogItem>(
|
return new PaginatedItemsViewModel<CatalogItem>(pageIndex, pageSize, totalItems, itemsOnPage);
|
||||||
pageIndex, pageSize, totalItems, itemsOnPage);
|
|
||||||
|
|
||||||
return Ok(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/v1/[controller]/CatalogTypes
|
// GET api/v1/[controller]/CatalogTypes
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("[action]")]
|
[Route("catalogtypes")]
|
||||||
[ProducesResponseType(typeof(List<CatalogItem>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(List<CatalogType>), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> CatalogTypes()
|
public async Task<ActionResult<List<CatalogType>>> CatalogTypesAsync()
|
||||||
{
|
{
|
||||||
var items = await _catalogContext.CatalogTypes
|
return await _catalogContext.CatalogTypes.ToListAsync();
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Ok(items);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/v1/[controller]/CatalogBrands
|
// GET api/v1/[controller]/CatalogBrands
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("[action]")]
|
[Route("catalogbrands")]
|
||||||
[ProducesResponseType(typeof(List<CatalogItem>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(List<CatalogBrand>), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> CatalogBrands()
|
public async Task<ActionResult<List<CatalogBrand>>> CatalogBrandsAsync()
|
||||||
{
|
{
|
||||||
var items = await _catalogContext.CatalogBrands
|
return await _catalogContext.CatalogBrands.ToListAsync();
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Ok(items);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//PUT api/v1/[controller]/items
|
//PUT api/v1/[controller]/items
|
||||||
@ -218,10 +211,9 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[HttpPut]
|
[HttpPut]
|
||||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||||
[ProducesResponseType((int)HttpStatusCode.Created)]
|
[ProducesResponseType((int)HttpStatusCode.Created)]
|
||||||
public async Task<IActionResult> UpdateProduct([FromBody]CatalogItem productToUpdate)
|
public async Task<ActionResult> UpdateProductAsync([FromBody]CatalogItem productToUpdate)
|
||||||
{
|
{
|
||||||
var catalogItem = await _catalogContext.CatalogItems
|
var catalogItem = await _catalogContext.CatalogItems.SingleOrDefaultAsync(i => i.Id == productToUpdate.Id);
|
||||||
.SingleOrDefaultAsync(i => i.Id == productToUpdate.Id);
|
|
||||||
|
|
||||||
if (catalogItem == null)
|
if (catalogItem == null)
|
||||||
{
|
{
|
||||||
@ -231,7 +223,6 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
var oldPrice = catalogItem.Price;
|
var oldPrice = catalogItem.Price;
|
||||||
var raiseProductPriceChangedEvent = oldPrice != productToUpdate.Price;
|
var raiseProductPriceChangedEvent = oldPrice != productToUpdate.Price;
|
||||||
|
|
||||||
|
|
||||||
// Update current product
|
// Update current product
|
||||||
catalogItem = productToUpdate;
|
catalogItem = productToUpdate;
|
||||||
_catalogContext.CatalogItems.Update(catalogItem);
|
_catalogContext.CatalogItems.Update(catalogItem);
|
||||||
@ -252,14 +243,14 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
await _catalogContext.SaveChangesAsync();
|
await _catalogContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreatedAtAction(nameof(GetItemById), new { id = productToUpdate.Id }, null);
|
return CreatedAtAction(nameof(ItemByIdAsync), new { id = productToUpdate.Id }, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//POST api/v1/[controller]/items
|
//POST api/v1/[controller]/items
|
||||||
[Route("items")]
|
[Route("items")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ProducesResponseType((int)HttpStatusCode.Created)]
|
[ProducesResponseType((int)HttpStatusCode.Created)]
|
||||||
public async Task<IActionResult> CreateProduct([FromBody]CatalogItem product)
|
public async Task<ActionResult> CreateProductAsync([FromBody]CatalogItem product)
|
||||||
{
|
{
|
||||||
var item = new CatalogItem
|
var item = new CatalogItem
|
||||||
{
|
{
|
||||||
@ -270,18 +261,20 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
PictureFileName = product.PictureFileName,
|
PictureFileName = product.PictureFileName,
|
||||||
Price = product.Price
|
Price = product.Price
|
||||||
};
|
};
|
||||||
|
|
||||||
_catalogContext.CatalogItems.Add(item);
|
_catalogContext.CatalogItems.Add(item);
|
||||||
|
|
||||||
await _catalogContext.SaveChangesAsync();
|
await _catalogContext.SaveChangesAsync();
|
||||||
|
|
||||||
return CreatedAtAction(nameof(GetItemById), new { id = item.Id }, null);
|
return CreatedAtAction(nameof(ItemByIdAsync), new { id = item.Id }, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//DELETE api/v1/[controller]/id
|
//DELETE api/v1/[controller]/id
|
||||||
[Route("{id}")]
|
[Route("{id}")]
|
||||||
[HttpDelete]
|
[HttpDelete]
|
||||||
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
||||||
public async Task<IActionResult> DeleteProduct(int id)
|
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||||
|
public async Task<ActionResult> DeleteProductAsync(int id)
|
||||||
{
|
{
|
||||||
var product = _catalogContext.CatalogItems.SingleOrDefault(x => x.Id == id);
|
var product = _catalogContext.CatalogItems.SingleOrDefault(x => x.Id == id);
|
||||||
|
|
||||||
|
@ -9,8 +9,9 @@ using System.Threading.Tasks;
|
|||||||
// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
|
// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
||||||
{
|
{
|
||||||
public class PicController : Controller
|
[ApiController]
|
||||||
|
public class PicController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IHostingEnvironment _env;
|
private readonly IHostingEnvironment _env;
|
||||||
private readonly CatalogContext _catalogContext;
|
private readonly CatalogContext _catalogContext;
|
||||||
@ -27,7 +28,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||||
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
|
||||||
// GET: /<controller>/
|
// GET: /<controller>/
|
||||||
public async Task<IActionResult> GetImage(int catalogItemId)
|
public async Task<ActionResult> GetImageAsync(int catalogItemId)
|
||||||
{
|
{
|
||||||
if (catalogItemId <= 0)
|
if (catalogItemId <= 0)
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
|
FROM microsoft/dotnet:2.2.0-aspnetcore-runtime AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
FROM microsoft/dotnet:2.1-sdk AS build
|
FROM microsoft/dotnet:2.2.100-sdk AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR /src/src/Services/Catalog/Catalog.API
|
WORKDIR /src/src/Services/Catalog/Catalog.API
|
||||||
|
@ -35,7 +35,6 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
|||||||
WebHost.CreateDefaultBuilder(args)
|
WebHost.CreateDefaultBuilder(args)
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.UseApplicationInsights()
|
.UseApplicationInsights()
|
||||||
.UseHealthChecks("/hc")
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.UseWebRoot("Pics")
|
.UseWebRoot("Pics")
|
||||||
.ConfigureAppConfiguration((builderContext, config) =>
|
.ConfigureAppConfiguration((builderContext, config) =>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user