diff --git a/README.md b/README.md index e421903a6..b9b28ca81 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ You can download them and start reviewing these Guides/eBooks here: | | | | | **Download .PDF** (2nd Edition) | **Download** | **Download** | -Download in other formats (**eReaders** like **MOBI**, **EPUB**) and other eBooks at the [.NET Architecture center](dot.net/architecture). +Download in other formats (**eReaders** like **MOBI**, **EPUB**) and other eBooks at the [.NET Architecture center](http://dot.net/architecture). Send feedback to [dotnet-architecture-ebooks-feedback@service.microsoft.com](dotnet-architecture-ebooks-feedback@service.microsoft.com) diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml index 6cffab120..43aa95660 100644 --- a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml @@ -5,6 +5,7 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + @@ -19,6 +20,18 @@ + + + + + + + + + + + + @@ -99,6 +112,11 @@ ServiceFabric PowerShell module. The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. --> + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml index 035005544..16c67d3a8 100644 --- a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml @@ -28,8 +28,6 @@ - - diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/ServiceManifest.xml new file mode 100644 index 000000000..248eb72d3 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/ServiceManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + eshop/ordering.backgroundtasks + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Cloud.xml index bf87a8296..48b8b6b33 100644 --- a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Cloud.xml +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Cloud.xml @@ -1,6 +1,7 @@  + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/eShopOnServiceFabric.sfproj b/ServiceFabric/Linux/eShopOnServiceFabric/eShopOnServiceFabric.sfproj index 405e7bb4c..e345590fb 100644 --- a/ServiceFabric/Linux/eShopOnServiceFabric/eShopOnServiceFabric.sfproj +++ b/ServiceFabric/Linux/eShopOnServiceFabric/eShopOnServiceFabric.sfproj @@ -38,6 +38,8 @@ + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml index 29679fbaa..05704ada8 100644 --- a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml @@ -5,6 +5,7 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + @@ -19,6 +20,18 @@ + + + + + + + + + + + + @@ -99,6 +112,11 @@ ServiceFabric PowerShell module. The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. --> + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml index 3ef5408a5..2e7aae7a5 100644 --- a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml @@ -28,8 +28,6 @@ - - diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/ServiceManifest.xml new file mode 100644 index 000000000..c963ce512 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingBackgroundPkg/ServiceManifest.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + eshop/ordering.backgroundtasks-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Cloud.xml index bf87a8296..48b8b6b33 100644 --- a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Cloud.xml +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Cloud.xml @@ -1,6 +1,7 @@  + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/eShopOnServiceFabric.sfproj b/ServiceFabric/Windows/eShopOnServiceFabric/eShopOnServiceFabric.sfproj index 405e7bb4c..e345590fb 100644 --- a/ServiceFabric/Windows/eShopOnServiceFabric/eShopOnServiceFabric.sfproj +++ b/ServiceFabric/Windows/eShopOnServiceFabric/eShopOnServiceFabric.sfproj @@ -38,6 +38,8 @@ + + diff --git a/ServiceFabric/Windows/sfwin.sln b/ServiceFabric/Windows/sfwin.sln new file mode 100644 index 000000000..989ad6080 --- /dev/null +++ b/ServiceFabric/Windows/sfwin.sln @@ -0,0 +1,13 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27323.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Global + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {04B6E659-060F-4550-A5CA-70B9E9D8F010} + EndGlobalSection +EndGlobal diff --git a/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.json b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.json index 073dc9653..b33d939ed 100644 --- a/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.json +++ b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.json @@ -2,6 +2,9 @@ "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", "contentVersion": "1.0.0.0", "parameters": { + "prefix": { + "type": "string" + }, "clusterLocation": { "type": "string", "metadata": { @@ -233,13 +236,16 @@ "publicIPApiVersion": "2015-06-15", "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]", "subnet0Ref": "[concat(variables('vnetID'),'/subnets/',parameters('subnet0Name'))]", - "lbID0": "[resourceId('Microsoft.Network/loadBalancers', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "lbID0": "[resourceId('Microsoft.Network/loadBalancers', concat('LB','-', variables('clusterName'),'-',parameters('vmNodeType0Name')))]", "lbIPConfig0": "[concat(variables('lbID0'),'/frontendIPConfigurations/LoadBalancerIPConfig')]", "lbPoolID0": "[concat(variables('lbID0'),'/backendAddressPools/LoadBalancerBEAddressPool')]", "lbProbeID0": "[concat(variables('lbID0'),'/probes/FabricGatewayProbe')]", "lbHttpProbeID0": "[concat(variables('lbID0'),'/probes/FabricHttpGatewayProbe')]", "lbNatPoolID0": "[concat(variables('lbID0'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]", "vmStorageAccountName0": "[toLower(concat(uniqueString(resourceGroup().id), '1', '0' ))]", + "supportLogStorageAccountName": "[take(concat(parameters('prefix'), parameters('supportLogStorageAccountName')),22)]", + "applicationDiagnosticsStorageAccountName" : "[take(concat(parameters('prefix'), parameters('applicationDiagnosticsStorageAccountName')),22)]", + "clusterName": "[concat(parameters('prefix'), parameters('clusterName'))]", "uniqueStringArray0": [ "[concat(variables('vmStorageAccountName0'), '0')]", "[concat(variables('vmStorageAccountName0'), '1')]", @@ -252,7 +258,7 @@ { "apiVersion": "[variables('storageApiVersion')]", "type": "Microsoft.Storage/storageAccounts", - "name": "[parameters('supportLogStorageAccountName')]", + "name": "[variables('supportLogStorageAccountName')]", "location": "[parameters('computeLocation')]", "dependsOn": [], "properties": {}, @@ -262,13 +268,13 @@ }, "tags": { "resourceType": "Service Fabric", - "clusterName": "[parameters('clusterName')]" + "clusterName": "[variables('clusterName')]" } }, { "apiVersion": "[variables('storageApiVersion')]", "type": "Microsoft.Storage/storageAccounts", - "name": "[parameters('applicationDiagnosticsStorageAccountName')]", + "name": "[variables('applicationDiagnosticsStorageAccountName')]", "location": "[parameters('computeLocation')]", "dependsOn": [], "properties": {}, @@ -278,7 +284,7 @@ }, "tags": { "resourceType": "Service Fabric", - "clusterName": "[parameters('clusterName')]" + "clusterName": "[variables('clusterName')]" } }, { @@ -304,7 +310,7 @@ }, "tags": { "resourceType": "Service Fabric", - "clusterName": "[parameters('clusterName')]" + "clusterName": "[variables('clusterName')]" } }, { @@ -320,13 +326,13 @@ }, "tags": { "resourceType": "Service Fabric", - "clusterName": "[parameters('clusterName')]" + "clusterName": "[variables('clusterName')]" } }, { "apiVersion": "[variables('lbApiVersion')]", "type": "Microsoft.Network/loadBalancers", - "name": "[concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name'))]", + "name": "[concat('LB','-', variables('clusterName'),'-',parameters('vmNodeType0Name'))]", "location": "[parameters('computeLocation')]", "dependsOn": [ "[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]" @@ -600,7 +606,7 @@ }, "tags": { "resourceType": "Service Fabric", - "clusterName": "[parameters('clusterName')]" + "clusterName": "[variables('clusterName')]" } }, { @@ -620,7 +626,7 @@ }, "tags": { "resourceType": "Service Fabric", - "clusterName": "[parameters('clusterName')]" + "clusterName": "[variables('clusterName')]" } }, { @@ -635,9 +641,9 @@ "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2])]", "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3])]", "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4])]", - "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", - "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', parameters('applicationDiagnosticsStorageAccountName'))]" + "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', variables('clusterName'),'-',parameters('vmNodeType0Name')))]", + "[concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName'))]", + "[concat('Microsoft.Storage/storageAccounts/', variables('applicationDiagnosticsStorageAccountName'))]" ], "properties": { "overprovision": "[parameters('overProvision')]", @@ -653,12 +659,12 @@ "type": "ServiceFabricNode", "autoUpgradeMinorVersion": true, "protectedSettings": { - "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key1]", - "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key2]" + "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('supportLogStorageAccountName')),'2015-05-01-preview').key1]", + "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('supportLogStorageAccountName')),'2015-05-01-preview').key2]" }, "publisher": "Microsoft.Azure.ServiceFabric", "settings": { - "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]", + "clusterEndpoint": "[reference(variables('clusterName')).clusterEndpoint]", "nodeTypeRef": "[parameters('vmNodeType0Name')]", "dataPath": "D:\\\\SvcFab", "durabilityLevel": "Bronze", @@ -674,8 +680,8 @@ "type": "IaaSDiagnostics", "autoUpgradeMinorVersion": true, "protectedSettings": { - "storageAccountName": "[parameters('applicationDiagnosticsStorageAccountName')]", - "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]", + "storageAccountName": "[variables('applicationDiagnosticsStorageAccountName')]", + "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]", "storageAccountEndPoint": "https://core.windows.net/" }, "publisher": "Microsoft.Azure.Diagnostics", @@ -715,7 +721,7 @@ } } }, - "StorageAccount": "[parameters('applicationDiagnosticsStorageAccountName')]" + "StorageAccount": "[variables('applicationDiagnosticsStorageAccountName')]" }, "typeHandlerVersion": "1.5" } @@ -786,16 +792,16 @@ }, "tags": { "resourceType": "Service Fabric", - "clusterName": "[parameters('clusterName')]" + "clusterName": "[variables('clusterName')]" } }, { "apiVersion": "2017-07-01-preview", "type": "Microsoft.ServiceFabric/clusters", - "name": "[parameters('clusterName')]", + "name": "[variables('clusterName')]", "location": "[parameters('clusterLocation')]", "dependsOn": [ - "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]" + "[concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName'))]" ], "properties": { "addonFeatures": [ @@ -803,14 +809,14 @@ ], "clientCertificateCommonNames": [], "clientCertificateThumbprints": [], - "clusterCodeVersion": "5.7.207.9494", + "clusterCodeVersion": "6.0.232.9494", "clusterState": "Default", "diagnosticsStorageAccountConfig": { - "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]", + "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]", "protectedAccountKeyName": "StorageAccountKey1", - "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]", - "storageAccountName": "[parameters('supportLogStorageAccountName')]", - "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]" + "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]", + "storageAccountName": "[variables('supportLogStorageAccountName')]", + "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]" }, "fabricSettings": [], "managementEndpoint": "[concat('http://',reference(concat(parameters('lbIPName'),'-','0')).dnsSettings.fqdn,':',parameters('nt0fabricHttpGatewayPort'))]", @@ -840,13 +846,13 @@ }, "tags": { "resourceType": "Service Fabric", - "clusterName": "[parameters('clusterName')]" + "clusterName": "[variables('clusterName')]" } } ], "outputs": { "clusterProperties": { - "value": "[reference(parameters('clusterName'))]", + "value": "[reference(variables('clusterName'))]", "type": "object" } } diff --git a/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.parameters.json b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.parameters.json index 2c214b754..af7e1a6ee 100644 --- a/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.parameters.json +++ b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.parameters.json @@ -2,8 +2,11 @@ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { + "prefix": { + "value": "qa" + }, "clusterName": { - "value": "qa-eshop-sfwin-cluster" + "value": "-eshop-sfwin-cluster" }, "clusterLocation": { "value": "westus" @@ -12,10 +15,10 @@ "value": "westus" }, "adminUserName": { - "value": "eshop" + "value": "testedu" }, "adminPassword": { - "value": "Your_complex_Pass@word1" + "value": "testedu1234!" }, "nicName": { "value": "NIC-eshopsfwin" @@ -24,7 +27,7 @@ "value": "eshopsfwin-PubIP" }, "dnsName": { - "value": "qa-eshop-sfwin-cluster" + "value": "testedu-eshop-sfwin-cluster" }, "virtualNetworkName": { "value": "VNet-eshopsfwin" @@ -36,10 +39,10 @@ "value": "LBIP-eshopsfwin" }, "applicationDiagnosticsStorageAccountName": { - "value": "sfdgqaeshopsfwin" + "value": "sfdiageshopw" }, "supportLogStorageAccountName": { - "value": "sflogsqaeshopsfwin" + "value": "sflogeshopw" }, "vmImageSku": { "value": "2016-Datacenter-with-Containers" diff --git a/docker-compose-windows.prod.yml b/docker-compose-windows.prod.yml index b99fed472..c9e9825e3 100644 --- a/docker-compose-windows.prod.yml +++ b/docker-compose-windows.prod.yml @@ -68,6 +68,17 @@ services: - AzureServiceBusEnabled=False ports: - "5102:80" + + ordering.backgroundtasks: + environment: + - ASPNETCORE_ENVIRONMENT=Production + - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word} + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - UseCustomizationData=True + - AzureServiceBusEnabled=False + ports: + - "5111:80" webspa: environment: diff --git a/docker-compose-windows.yml b/docker-compose-windows.yml index de01c2ba7..35f3ff7be 100644 --- a/docker-compose-windows.yml +++ b/docker-compose-windows.yml @@ -37,6 +37,15 @@ services: - sql.data - rabbitmq + ordering.backgroundtasks: + image: eshop/ordering.backgroundtasks-win:${TAG:-latest} + build: + context: . + dockerfile: src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile + depends_on: + - sql.data + - rabbitmq + marketing.api: image: eshop/marketing.api-win:${TAG:-latest} build: diff --git a/docker-compose.override.windows.yml b/docker-compose.override.windows.yml index 448e0dc7f..b4828607a 100644 --- a/docker-compose.override.windows.yml +++ b/docker-compose.override.windows.yml @@ -37,7 +37,12 @@ services: - EventBusUserName=admin - EventBusPassword=password - marketing.api: + ordering.api: + environment: + - EventBusUserName=admin + - EventBusPassword=password + + ordering.backgroundtasks: environment: - EventBusUserName=admin - EventBusPassword=password diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 96e34bcf2..4f2e31123 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -83,6 +83,24 @@ services: ports: - "5102:80" + ordering.backgroundtasks: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word} + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} + - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} + - UseCustomizationData=True + - AzureServiceBusEnabled=False + - CheckUpdateTime=30000 + - GracePeriodTime=1 + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} + - UseLoadTest=${USE_LOADTEST:-False} + ports: + - "5111:80" + marketing.api: environment: - ASPNETCORE_ENVIRONMENT=Development @@ -219,4 +237,5 @@ services: rabbitmq: ports: - "15672:15672" - - "5672:5672" \ No newline at end of file + - "5672:5672" + diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 552350251..fac480f2e 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -90,6 +90,24 @@ services: ports: - "5102:80" + ordering.backgroundtasks: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=${ESHOP_AZURE_ORDERING_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word} + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} + - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} + - UseCustomizationData=True + - AzureServiceBusEnabled=False + - CheckUpdateTime=30000 + - GracePeriodTime=1 + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} + - UseLoadTest=${USE_LOADTEST:-False} + ports: + - "5111:80" + marketing.api: environment: - ASPNETCORE_ENVIRONMENT=Development diff --git a/docker-compose.yml b/docker-compose.yml index d8b7318ce..b237ad04f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,6 +38,15 @@ services: - sql.data - rabbitmq + ordering.backgroundtasks: + image: eshop/ordering.backgroundtasks:${TAG:-latest} + build: + context: . + dockerfile: src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile + depends_on: + - sql.data + - rabbitmq + marketing.api: image: eshop/marketing.api:${TAG:-latest} build: @@ -106,4 +115,4 @@ services: image: redis:alpine rabbitmq: - image: rabbitmq:3-management-alpine + image: rabbitmq:3-management-alpine \ No newline at end of file diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index e4ddff1c2..353952ff0 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2009 +VisualStudioVersion = 15.0.27130.2024 MinimumVisualStudioVersion = 10.0.40219.1 Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" EndProject @@ -97,6 +97,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{1815 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{15F4B3AA-89B6-4A0D-9051-414305974781}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.BackgroundTasks", "src\Services\Ordering\Ordering.BackgroundTasks\Ordering.BackgroundTasks.csproj", "{2FF56999-0266-48B2-ACC1-FEBC482A5105}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -1311,6 +1313,54 @@ Global {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x64.Build.0 = Release|Any CPU {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.ActiveCfg = Release|Any CPU {15F4B3AA-89B6-4A0D-9051-414305974781}.Release|x86.Build.0 = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|ARM.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhone.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x64.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x64.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x86.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.AppStore|x86.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|ARM.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|ARM.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhone.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x64.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x64.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x86.ActiveCfg = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Debug|x86.Build.0 = Debug|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|Any CPU.Build.0 = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|ARM.ActiveCfg = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|ARM.Build.0 = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhone.ActiveCfg = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhone.Build.0 = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x64.ActiveCfg = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x64.Build.0 = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x86.ActiveCfg = Release|Any CPU + {2FF56999-0266-48B2-ACC1-FEBC482A5105}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1357,6 +1407,7 @@ Global {969E793C-C413-490E-9C9D-B2B46DA5AF32} = {EF0337F2-ED00-4643-89FD-EE10863F1870} {1815B651-941C-466B-AE33-D1D7EEB8F77F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25} {15F4B3AA-89B6-4A0D-9051-414305974781} = {1815B651-941C-466B-AE33-D1D7EEB8F77F} + {2FF56999-0266-48B2-ACC1-FEBC482A5105} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} diff --git a/eShopOnContainers.sln b/eShopOnContainers.sln index 708fd1b84..ebee1f162 100644 --- a/eShopOnContainers.sln +++ b/eShopOnContainers.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27130.2010 +VisualStudioVersion = 15.0.27130.2024 MinimumVisualStudioVersion = 10.0.40219.1 Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" EndProject @@ -103,7 +103,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared Code", "Shared Code" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{2BB81612-8D04-49CD-B17F-38DAB176E583}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.Core", "src\Mobile\eShopOnContainers\eShopOnContainers.Core\eShopOnContainers.Core.csproj", "{BA96A12C-4EE3-46C4-BB3F-F811B554CD01}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "eShopOnContainers.Core", "src\Mobile\eShopOnContainers\eShopOnContainers.Core\eShopOnContainers.Core.csproj", "{BA96A12C-4EE3-46C4-BB3F-F811B554CD01}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.Droid", "src\Mobile\eShopOnContainers\eShopOnContainers.Droid\eShopOnContainers.Droid.csproj", "{62DBB163-9CA9-4818-B48B-13233DF37C24}" EndProject @@ -113,7 +113,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.Windows", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile Apps", "Mobile Apps", "{0AAED9FF-3260-43BB-B586-9AAF1E010A90}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.UnitTests", "src\Mobile\eShopOnContainers\eShopOnContainers.UnitTests\eShopOnContainers.UnitTests.csproj", "{6E4285E7-7611-4440-A1B5-3513EBB13807}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "eShopOnContainers.UnitTests", "src\Mobile\eShopOnContainers\eShopOnContainers.UnitTests\eShopOnContainers.UnitTests.csproj", "{6E4285E7-7611-4440-A1B5-3513EBB13807}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.TestRunner.Droid", "src\Mobile\eShopOnContainers\eShopOnContainers.TestRunner.Droid\eShopOnContainers.TestRunner.Droid.csproj", "{A289A7F0-ACD8-42AE-87B6-AB1AFD310BF1}" EndProject @@ -121,6 +121,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.TestRunne EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.TestRunner.Windows", "src\Mobile\eShopOnContainers\eShopOnContainers.TestRunner.Windows\eShopOnContainers.TestRunner.Windows.csproj", "{A7337243-33B8-463A-87AD-944B75EFD820}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.BackgroundTasks", "src\Services\Ordering\Ordering.BackgroundTasks\Ordering.BackgroundTasks.csproj", "{16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -1759,6 +1761,54 @@ Global {A7337243-33B8-463A-87AD-944B75EFD820}.Release|x86.ActiveCfg = Release|x86 {A7337243-33B8-463A-87AD-944B75EFD820}.Release|x86.Build.0 = Release|x86 {A7337243-33B8-463A-87AD-944B75EFD820}.Release|x86.Deploy.0 = Release|x86 + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|ARM.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|iPhone.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|x64.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|x64.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|x86.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.AppStore|x86.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|ARM.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|ARM.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|iPhone.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|x64.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|x64.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|x86.ActiveCfg = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Debug|x86.Build.0 = Debug|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|Any CPU.Build.0 = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|ARM.ActiveCfg = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|ARM.Build.0 = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|iPhone.ActiveCfg = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|iPhone.Build.0 = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|x64.ActiveCfg = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|x64.Build.0 = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|x86.ActiveCfg = Release|Any CPU + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1817,6 +1867,7 @@ Global {A289A7F0-ACD8-42AE-87B6-AB1AFD310BF1} = {0AAED9FF-3260-43BB-B586-9AAF1E010A90} {B68C2B56-7581-46AE-B55D-D25DDFD3BFE3} = {0AAED9FF-3260-43BB-B586-9AAF1E010A90} {A7337243-33B8-463A-87AD-944B75EFD820} = {0AAED9FF-3260-43BB-B586-9AAF1E010A90} + {16CDE5D2-2DDE-4AF2-B902-AD9CC42DE480} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} diff --git a/k8s/deploy-ingress-azure.ps1 b/k8s/deploy-ingress-azure.ps1 new file mode 100644 index 000000000..f93cf437b --- /dev/null +++ b/k8s/deploy-ingress-azure.ps1 @@ -0,0 +1,3 @@ +kubectl patch deployment -n ingress-nginx nginx-ingress-controller --type=json --patch="$(cat nginx-ingress\publish-service-patch.yaml)" +kubectl apply -f nginx-ingress\azure\service.yaml +kubectl apply -f nginx-ingress\patch-service-without-rbac.yaml \ No newline at end of file diff --git a/k8s/deploy-ingress.ps1 b/k8s/deploy-ingress.ps1 new file mode 100644 index 000000000..694361bfa --- /dev/null +++ b/k8s/deploy-ingress.ps1 @@ -0,0 +1,12 @@ +kubectl apply -f ingress.yaml + +# Deploy nginx-ingress core files +kubectl apply -f nginx-ingress\namespace.yaml +kubectl apply -f nginx-ingress\default-backend.yaml +kubectl apply -f nginx-ingress\configmap.yaml +kubectl apply -f nginx-ingress\tcp-services-configmap.yaml +kubectl apply -f nginx-ingress\udp-services-configmap.yaml +kubectl apply -f nginx-ingress\without-rbac.yaml + + + diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index bcb2d7393..eed45ee62 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -6,10 +6,8 @@ Param( [parameter(Mandatory=$false)][string]$kubeconfigPath, [parameter(Mandatory=$true)][string]$configFile, [parameter(Mandatory=$false)][string]$imageTag, - [parameter(Mandatory=$false)][string]$externalDns, [parameter(Mandatory=$false)][bool]$deployCI=$false, [parameter(Mandatory=$false)][bool]$buildImages=$true, - [parameter(Mandatory=$false)][bool]$buildBits=$false, [parameter(Mandatory=$false)][bool]$deployInfrastructure=$true, [parameter(Mandatory=$false)][string]$dockerOrg="eshop" ) @@ -30,6 +28,16 @@ function ExecKube($cmd) { $debugMode = $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent $useDockerHub = [string]::IsNullOrEmpty($registry) +$externalDns = & ExecKube -cmd 'get svc ingress-nginx -n ingress-nginx -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"' +Write-Host "Ingress ip detected: $externalDns" -ForegroundColor Yellow + +if (-not [bool]($externalDns -as [ipaddress])) { + Write-Host "Must install ingress first" -ForegroundColor Red + Write-Host "Run deploy-ingress.ps1 and deploy-ingress-azure.ps1" -ForegroundColor Red + exit +} + + # Check required commands (only if not in CI environment) if(-not $deployCI) { $requiredCommands = ("docker", "docker-compose", "kubectl") @@ -41,7 +49,6 @@ if(-not $deployCI) { } } else { - $buildBits = false; $buildImages = false; # Never build images through CI, as they previously built } @@ -51,18 +58,14 @@ if ([string]::IsNullOrEmpty($imageTag)) { } Write-Host "Docker image Tag: $imageTag" -ForegroundColor Yellow -# building and publishing docker images if needed -if($buildBits) { - Write-Host "Building and publishing eShopOnContainers..." -ForegroundColor Yellow - dotnet publish -c Release -o obj/Docker/publish ../eShopOnContainers-ServicesAndWebApps.sln -} +# building docker images if needed if ($buildImages) { Write-Host "Building Docker images tagged with '$imageTag'" -ForegroundColor Yellow $env:TAG=$imageTag docker-compose -p .. -f ../docker-compose.yml build Write-Host "Pushing images to $registry/$dockerOrg..." -ForegroundColor Yellow - $services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "marketing.api","payment.api","locations.api", "webmvc", "webspa", "webstatus") + $services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "ordering.backgroundtasks", "marketing.api","payment.api","locations.api", "webmvc", "webspa", "webstatus") foreach ($service in $services) { $imageFqdn = if ($useDockerHub) {"$dockerOrg/${service}"} else {"$registry/$dockerOrg/${service}"} @@ -100,35 +103,18 @@ if (-not [string]::IsNullOrEmpty($dockerUser)) { Write-Host "Removing existing services & deployments.." -ForegroundColor Yellow ExecKube -cmd 'delete deployments --all' ExecKube -cmd 'delete services --all' -ExecKube -cmd 'delete configmap config-files' ExecKube -cmd 'delete configmap urls' ExecKube -cmd 'delete configmap externalcfg' # start sql, rabbitmq, frontend deployments -ExecKube -cmd 'create configmap config-files --from-file=nginx-conf=nginx.conf' -ExecKube -cmd 'label configmap config-files app=eshop' - if ($deployInfrastructure) { Write-Host 'Deploying infrastructure deployments (databases, redis, RabbitMQ...)' -ForegroundColor Yellow ExecKube -cmd 'create -f sql-data.yaml -f basket-data.yaml -f keystore-data.yaml -f rabbitmq.yaml -f nosql-data.yaml' } -Write-Host 'Deploying code deployments (Web APIs, Web apps, ...)' -ForegroundColor Yellow -ExecKube -cmd 'create -f services.yaml -f frontend.yaml' - -if ([string]::IsNullOrEmpty($externalDns)) { - Write-Host "Waiting for frontend's external ip..." -ForegroundColor Yellow - while ($true) { - $frontendUrl = & ExecKube -cmd 'get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"' - if ([bool]($frontendUrl -as [ipaddress])) { - break - } - Start-Sleep -s 15 - } - $externalDns = $frontendUrl -} -Write-Host "Using $externalDns as the external DNS/IP of the k8s cluster" +Write-Host 'Deploying code deployments (Web APIs, Web apps, ...)' -ForegroundColor Yellow +ExecKube -cmd 'create -f services.yaml' ExecKube -cmd 'create configmap urls ` --from-literal=BasketUrl=http://basket ` @@ -192,6 +178,8 @@ ExecKube -cmd 'set image deployments/payment payment=${registryPath}${dockerOrg} ExecKube -cmd 'set image deployments/webmvc webmvc=${registryPath}${dockerOrg}/webmvc:$imageTag' ExecKube -cmd 'set image deployments/webstatus webstatus=${registryPath}${dockerOrg}/webstatus:$imageTag' ExecKube -cmd 'set image deployments/webspa webspa=${registryPath}${dockerOrg}/webspa:$imageTag' +ExecKube -cmd 'set image deployments/orderingbackground orderingbackground=${registryPath}${dockerOrg}/ordering.backgroundtasks:$imageTag' + Write-Host "Execute rollout..." -ForegroundColor Yellow ExecKube -cmd 'rollout resume deployments/basket' @@ -204,6 +192,7 @@ ExecKube -cmd 'rollout resume deployments/payment' ExecKube -cmd 'rollout resume deployments/webmvc' ExecKube -cmd 'rollout resume deployments/webstatus' ExecKube -cmd 'rollout resume deployments/webspa' +ExecKube -cmd 'rollout resume deployments/orderingbackground' Write-Host "WebSPA is exposed at http://$externalDns, WebMVC at http://$externalDns/webmvc, WebStatus at http://$externalDns/webstatus" -ForegroundColor Yellow diff --git a/k8s/deployments.yaml b/k8s/deployments.yaml index 9935b83d7..034842f8c 100644 --- a/k8s/deployments.yaml +++ b/k8s/deployments.yaml @@ -56,15 +56,15 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 60 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key --- @@ -121,15 +121,15 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 60 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key --- @@ -208,15 +208,15 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 60 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key --- @@ -259,6 +259,71 @@ spec: configMapKeyRef: name: urls key: IdentityUrl + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: UseLoadTest + valueFrom: + configMapKeyRef: + name: externalcfg + key: EnableLoadTest + - name: OrchestratorType + value: 'K8S' + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 60 + livenessProbe: + httpGet: + path: /liveness + port: 80 + scheme: HTTP + initialDelaySeconds: 120 + periodSeconds: 60 + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: orderingbackground +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: orderingbackground + spec: + containers: + - name: orderingbackground + image: eshop/ordering.backgroundtasks + imagePullPolicy: Always + env: + - name: PATH_BASE + value: /ordering-backgroundtasks + - name: ConnectionString + valueFrom: + configMapKeyRef: + name: externalcfg + key: OrderingSqlDb + - name: EventBusConnection + valueFrom: + configMapKeyRef: + name: externalcfg + key: OrderingBus + - name: AzureServiceBusEnabled + valueFrom: + configMapKeyRef: + name: externalcfg + key: UseAzureServiceBus - name: CheckUpdateTime valueFrom: configMapKeyRef: @@ -288,15 +353,15 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 60 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key --- @@ -368,15 +433,15 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 50 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key --- @@ -458,15 +523,15 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 60 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key --- @@ -513,15 +578,15 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 60 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key --- @@ -635,15 +700,15 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 60 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key --- @@ -828,14 +893,14 @@ spec: path: /hc port: 80 scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 10 + initialDelaySeconds: 60 + periodSeconds: 60 livenessProbe: httpGet: - path: /hc + path: /liveness port: 80 scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 + initialDelaySeconds: 120 + periodSeconds: 60 imagePullSecrets: - name: registry-key diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 000000000..3c2fe8bad --- /dev/null +++ b/k8s/ingress.yaml @@ -0,0 +1,55 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + labels: + app: eshop + component: frontend + name: eshop-ingress + annotations: + ingress.kubernetes.io/ssl-redirect: "false" +spec: + rules: + - http: + paths: + - path: /basket-api + backend: + serviceName: basket + servicePort: 80 + - path: /catalog-api + backend: + serviceName: catalog + servicePort: 80 + - path: /identity + backend: + serviceName: identity + servicePort: 80 + - path: /ordering-api + backend: + serviceName: ordering + servicePort: 80 + - path: /webmvc + backend: + serviceName: webmvc + servicePort: 80 + - path: /webstatus + backend: + serviceName: webstatus + servicePort: 80 + - path: /marketing-api + backend: + serviceName: marketing + servicePort: 80 + - path: /payment-api + backend: + serviceName: payment + servicePort: 80 + - path: /locations-api + backend: + serviceName: locations + servicePort: 80 + - path: / + backend: + serviceName: webspa + servicePort: 80 + + diff --git a/k8s/nginx-ingress/azure/service.yaml b/k8s/nginx-ingress/azure/service.yaml new file mode 100644 index 000000000..8d2f71505 --- /dev/null +++ b/k8s/nginx-ingress/azure/service.yaml @@ -0,0 +1,19 @@ +kind: Service +apiVersion: v1 +metadata: + name: ingress-nginx + namespace: ingress-nginx + labels: + app: ingress-nginx +spec: + externalTrafficPolicy: Local + type: LoadBalancer + selector: + app: ingress-nginx + ports: + - name: http + port: 80 + targetPort: http + - name: https + port: 443 + targetPort: https diff --git a/k8s/nginx-ingress/configmap.yaml b/k8s/nginx-ingress/configmap.yaml new file mode 100644 index 000000000..6703fc38e --- /dev/null +++ b/k8s/nginx-ingress/configmap.yaml @@ -0,0 +1,11 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: nginx-configuration + namespace: ingress-nginx + labels: + app: ingress-nginx +data: + ssl-redirect: "false" + proxy-buffer-size: "128k" + proxy-buffers: "4 256k" diff --git a/k8s/nginx-ingress/default-backend.yaml b/k8s/nginx-ingress/default-backend.yaml new file mode 100644 index 000000000..64f6f58ad --- /dev/null +++ b/k8s/nginx-ingress/default-backend.yaml @@ -0,0 +1,52 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: default-http-backend + labels: + app: default-http-backend + namespace: ingress-nginx +spec: + replicas: 1 + template: + metadata: + labels: + app: default-http-backend + spec: + terminationGracePeriodSeconds: 60 + containers: + - name: default-http-backend + # Any image is permissable as long as: + # 1. It serves a 404 page at / + # 2. It serves 200 on a /healthz endpoint + image: gcr.io/google_containers/defaultbackend:1.4 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + scheme: HTTP + initialDelaySeconds: 30 + timeoutSeconds: 5 + ports: + - containerPort: 8080 + resources: + limits: + cpu: 10m + memory: 20Mi + requests: + cpu: 10m + memory: 20Mi +--- + +apiVersion: v1 +kind: Service +metadata: + name: default-http-backend + namespace: ingress-nginx + labels: + app: default-http-backend +spec: + ports: + - port: 80 + targetPort: 8080 + selector: + app: default-http-backend diff --git a/k8s/nginx-ingress/namespace.yaml b/k8s/nginx-ingress/namespace.yaml new file mode 100644 index 000000000..6878f0be8 --- /dev/null +++ b/k8s/nginx-ingress/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ingress-nginx diff --git a/k8s/nginx-ingress/patch-service-without-rbac.yaml b/k8s/nginx-ingress/patch-service-without-rbac.yaml new file mode 100644 index 000000000..919efc389 --- /dev/null +++ b/k8s/nginx-ingress/patch-service-without-rbac.yaml @@ -0,0 +1,40 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: nginx-ingress-controller + namespace: ingress-nginx +spec: + replicas: 1 + selector: + matchLabels: + app: ingress-nginx + template: + metadata: + labels: + app: ingress-nginx + spec: + containers: + - name: nginx-ingress-controller + image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.9.0 + args: + - /nginx-ingress-controller + - --default-backend-service=$(POD_NAMESPACE)/default-http-backend + - --configmap=$(POD_NAMESPACE)/nginx-configuration + - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services + - --udp-services-configmap=$(POD_NAMESPACE)/udp-services + - --publish-service=$(POD_NAMESPACE)/ingress-nginx + - --annotations-prefix=nginx.ingress.kubernetes.io + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 diff --git a/k8s/nginx-ingress/publish-service-patch.yaml b/k8s/nginx-ingress/publish-service-patch.yaml new file mode 100644 index 000000000..f8f52f772 --- /dev/null +++ b/k8s/nginx-ingress/publish-service-patch.yaml @@ -0,0 +1,7 @@ +[ + { + 'op': 'add', + 'path': '/spec/template/spec/containers/0/args/-', + 'value': '--publish-service=$(POD_NAMESPACE)/ingress-nginx' + } +] diff --git a/k8s/nginx-ingress/tcp-services-configmap.yaml b/k8s/nginx-ingress/tcp-services-configmap.yaml new file mode 100644 index 000000000..a963085d3 --- /dev/null +++ b/k8s/nginx-ingress/tcp-services-configmap.yaml @@ -0,0 +1,5 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: tcp-services + namespace: ingress-nginx diff --git a/k8s/nginx-ingress/udp-services-configmap.yaml b/k8s/nginx-ingress/udp-services-configmap.yaml new file mode 100644 index 000000000..1870931a2 --- /dev/null +++ b/k8s/nginx-ingress/udp-services-configmap.yaml @@ -0,0 +1,5 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: udp-services + namespace: ingress-nginx diff --git a/k8s/nginx-ingress/without-rbac.yaml b/k8s/nginx-ingress/without-rbac.yaml new file mode 100644 index 000000000..1c46b73eb --- /dev/null +++ b/k8s/nginx-ingress/without-rbac.yaml @@ -0,0 +1,61 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: nginx-ingress-controller + namespace: ingress-nginx +spec: + replicas: 1 + selector: + matchLabels: + app: ingress-nginx + template: + metadata: + labels: + app: ingress-nginx + annotations: + prometheus.io/port: '10254' + prometheus.io/scrape: 'true' + spec: + containers: + - name: nginx-ingress-controller + image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.9.0 + args: + - /nginx-ingress-controller + - --default-backend-service=$(POD_NAMESPACE)/default-http-backend + - --configmap=$(POD_NAMESPACE)/nginx-configuration + - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services + - --udp-services-configmap=$(POD_NAMESPACE)/udp-services + - --annotations-prefix=nginx.ingress.kubernetes.io + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 diff --git a/k8s/nginx.conf b/k8s/nginx.conf deleted file mode 100644 index 22c3414a1..000000000 --- a/k8s/nginx.conf +++ /dev/null @@ -1,98 +0,0 @@ -pid /tmp/nginx.pid; - -worker_processes 1; - -events { - worker_connections 1024; -} - -http { - server_tokens off; - - add_header X-Frame-Options SAMEORIGIN; - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - - client_body_temp_path /tmp/client_body; - fastcgi_temp_path /tmp/fastcgi_temp; - proxy_temp_path /tmp/proxy_temp; - scgi_temp_path /tmp/scgi_temp; - uwsgi_temp_path /tmp/uwsgi_temp; - - gzip on; - gzip_comp_level 6; - gzip_min_length 1024; - gzip_buffers 4 32k; - gzip_types text/plain application/javascript text/css; - gzip_vary on; - - keepalive_timeout 65; - - proxy_buffer_size 128k; - proxy_buffers 4 256k; - proxy_busy_buffers_size 256k; - - server { - listen 8080; - - location /basket-api { - proxy_pass http://basket; - proxy_redirect off; - proxy_set_header Host $host; - } - - location /catalog-api { - proxy_pass http://catalog; - proxy_redirect off; - proxy_set_header Host $host; - } - - location /identity { - proxy_pass http://identity; - proxy_redirect off; - proxy_set_header Host $host; - } - - location /ordering-api { - proxy_pass http://ordering; - proxy_redirect off; - proxy_set_header Host $host; - } - - location /webmvc { - proxy_pass http://webmvc; - proxy_redirect off; - proxy_set_header Host $host; - } - - location /webstatus { - proxy_pass http://webstatus; - proxy_redirect off; - proxy_set_header Host $host; - } - - location /marketing-api { - proxy_pass http://marketing; - proxy_redirect off; - proxy_set_header Host $host; - } - - location /payment-api { - proxy_pass http://payment; - proxy_redirect off; - proxy_set_header Host $host; - } - - location /locations-api { - proxy_pass http://locations; - proxy_redirect off; - proxy_set_header Host $host; - } - - location / { - proxy_pass http://webspa; - proxy_redirect off; - proxy_set_header Host $host; - } - } -} \ No newline at end of file diff --git a/k8s/services.yaml b/k8s/services.yaml index 02b73448a..805d3dc85 100644 --- a/k8s/services.yaml +++ b/k8s/services.yaml @@ -56,6 +56,20 @@ spec: --- apiVersion: v1 kind: Service +metadata: + labels: + app: eshop + component: orderingbackground + name: orderingbackground +spec: + ports: + - port: 80 + selector: + app: eshop + component: orderingbackground +--- +apiVersion: v1 +kind: Service metadata: labels: app: eshop diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index f2129be69..49a417635 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -92,9 +92,13 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ policy.Execute(() => { + var properties = channel.CreateBasicProperties(); + properties.DeliveryMode = 2; // persistent + channel.BasicPublish(exchange: BROKER_NAME, routingKey: eventName, - basicProperties: null, + mandatory:true, + basicProperties: properties, body: body); }); } @@ -184,6 +188,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var message = Encoding.UTF8.GetString(ea.Body); await ProcessEvent(eventName, message); + + channel.BasicAck(ea.DeliveryTag,multiple:false); }; channel.BasicConsume(queue: _queueName, diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 1b698a339..86b57c0cd 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -188,7 +188,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API { app.UsePathBase(pathBase); } - + + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 + app.UseStaticFiles(); app.UseCors("CorsPolicy"); diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index 41dee0069..5eec48959 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -191,6 +191,10 @@ app.UsePathBase(pathBase); } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 + app.UseCors("CorsPolicy"); app.UseMvcWithDefaultRoute(); diff --git a/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs b/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs index bb41f0d0a..b109bf896 100644 --- a/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs +++ b/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs @@ -1,6 +1,7 @@ using IdentityServer4.EntityFramework.DbContexts; using IdentityServer4.EntityFramework.Mappers; using Microsoft.eShopOnContainers.Services.Identity.API.Configuration; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Linq; @@ -10,47 +11,36 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data { public class ConfigurationDbContextSeed { - public async Task SeedAsync(ConfigurationDbContext context,IConfiguration configuration) + public async Task SeedAsync(ConfigurationDbContext context, IConfiguration configuration) { - //callbacks urls from config: - var clientUrls = new Dictionary(); - - clientUrls.Add("Mvc", configuration.GetValue("MvcClient")); - clientUrls.Add("Spa", configuration.GetValue("SpaClient")); - clientUrls.Add("Xamarin", configuration.GetValue("XamarinCallback")); - clientUrls.Add("LocationsApi", configuration.GetValue("LocationApiClient")); - clientUrls.Add("MarketingApi", configuration.GetValue("MarketingApiClient")); - clientUrls.Add("BasketApi", configuration.GetValue("BasketApiClient")); - clientUrls.Add("OrderingApi", configuration.GetValue("OrderingApiClient")); + var clientUrls = new Dictionary + { + {"Mvc", configuration.GetValue("MvcClient")}, + {"Spa", configuration.GetValue("SpaClient")}, + {"Xamarin", configuration.GetValue("XamarinCallback")}, + {"LocationsApi", configuration.GetValue("LocationApiClient")}, + {"MarketingApi", configuration.GetValue("MarketingApiClient")}, + {"BasketApi", configuration.GetValue("BasketApiClient")}, + {"OrderingApi", configuration.GetValue("OrderingApiClient")} + }; - if (!context.Clients.Any()) + if (!await context.Clients.AnyAsync()) { - foreach (var client in Config.GetClients(clientUrls)) - { - await context.Clients.AddAsync(client.ToEntity()); - } - await context.SaveChangesAsync(); + context.Clients.AddRange(Config.GetClients(clientUrls).Select(client => client.ToEntity())); } - if (!context.IdentityResources.Any()) + if (!await context.IdentityResources.AnyAsync()) { - foreach (var resource in Config.GetResources()) - { - await context.IdentityResources.AddAsync(resource.ToEntity()); - } - await context.SaveChangesAsync(); + context.IdentityResources.AddRange(Config.GetResources().Select(resource => resource.ToEntity())); } - if (!context.ApiResources.Any()) + if (!await context.ApiResources.AnyAsync()) { - foreach (var api in Config.GetApis()) - { - await context.ApiResources.AddAsync(api.ToEntity()); - } - - await context.SaveChangesAsync(); + context.ApiResources.AddRange(Config.GetApis().Select(api => api.ToEntity())); } + + await context.SaveChangesAsync(); } } } diff --git a/src/Services/Identity/Identity.API/Startup.cs b/src/Services/Identity/Identity.API/Startup.cs index 58ac0bd10..f16f90965 100644 --- a/src/Services/Identity/Identity.API/Startup.cs +++ b/src/Services/Identity/Identity.API/Startup.cs @@ -136,7 +136,12 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API { loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); app.UsePathBase(pathBase); - } + } + + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 app.UseStaticFiles(); diff --git a/src/Services/Identity/Identity.API/Views/Home/About.cshtml b/src/Services/Identity/Identity.API/Views/Home/About.cshtml deleted file mode 100644 index 50476d1fb..000000000 --- a/src/Services/Identity/Identity.API/Views/Home/About.cshtml +++ /dev/null @@ -1,7 +0,0 @@ -@{ - ViewData["Title"] = "About"; -} -

@ViewData["Title"].

-

@ViewData["Message"]

- -

Use this area to provide additional information.

diff --git a/src/Services/Identity/Identity.API/Views/Home/Contact.cshtml b/src/Services/Identity/Identity.API/Views/Home/Contact.cshtml deleted file mode 100644 index 15c12c6d1..000000000 --- a/src/Services/Identity/Identity.API/Views/Home/Contact.cshtml +++ /dev/null @@ -1,17 +0,0 @@ -@{ - ViewData["Title"] = "Contact"; -} -

@ViewData["Title"].

-

@ViewData["Message"]

- -
- One Microsoft Way
- Redmond, WA 98052-6399
- P: - 425.555.0100 -
- -
- Support: Support@example.com
- Marketing: Marketing@example.com -
diff --git a/src/Services/Location/Locations.API/Startup.cs b/src/Services/Location/Locations.API/Startup.cs index 55e9d52c0..e69180e61 100644 --- a/src/Services/Location/Locations.API/Startup.cs +++ b/src/Services/Location/Locations.API/Startup.cs @@ -162,6 +162,10 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API app.UsePathBase(pathBase); } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 + app.UseCors("CorsPolicy"); ConfigureAuth(app); diff --git a/src/Services/Marketing/Marketing.API/Startup.cs b/src/Services/Marketing/Marketing.API/Startup.cs index a5f12b54e..f2dcd1578 100644 --- a/src/Services/Marketing/Marketing.API/Startup.cs +++ b/src/Services/Marketing/Marketing.API/Startup.cs @@ -192,8 +192,12 @@ if (!string.IsNullOrEmpty(pathBase)) { app.UsePathBase(pathBase); - } - + } + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 + app.UseCors("CorsPolicy"); ConfigureAuth(app); diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 0c7272f6b..1879175c9 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -6,7 +6,6 @@ using global::Ordering.API.Application.IntegrationEvents; using global::Ordering.API.Application.IntegrationEvents.Events; using global::Ordering.API.Infrastructure.Filters; - using global::Ordering.API.Infrastructure.HostedServices; using global::Ordering.API.Infrastructure.Middlewares; using Infrastructure.AutofacModules; using Infrastructure.Filters; @@ -58,9 +57,6 @@ }).AddControllersAsServices(); //Injecting Controllers themselves thru DI //For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services - // Configure GracePeriodManager Hosted Service - services.AddSingleton(); - services.AddTransient(); services.AddHealthChecks(checks => @@ -215,8 +211,12 @@ { loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); app.UsePathBase(pathBase); - } - + } + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 + app.UseCors("CorsPolicy"); ConfigureAuth(app); diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Configuration/BackgroundTaskSettings.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Configuration/BackgroundTaskSettings.cs new file mode 100644 index 000000000..2b42f6084 --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Configuration/BackgroundTaskSettings.cs @@ -0,0 +1,13 @@ +namespace Ordering.BackgroundTasks.Configuration +{ + public class BackgroundTaskSettings + { + public string ConnectionString { get; set; } + + public string EventBusConnection { get; set; } + + public int GracePeriodTime { get; set; } + + public int CheckUpdateTime { get; set; } + } +} diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile b/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile new file mode 100644 index 000000000..391d8c17b --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile @@ -0,0 +1,18 @@ +FROM microsoft/aspnetcore:2.0.3 AS base +WORKDIR /app +EXPOSE 80 + +FROM microsoft/aspnetcore-build:2.0 AS build +WORKDIR /src +COPY . . +RUN dotnet restore -nowarn:msb3202,nu1503 +WORKDIR /src/src/Services/Ordering/Ordering.BackgroundTasks +RUN dotnet build --no-restore -c Release -o /app + +FROM build AS publish +RUN dotnet publish --no-restore -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "Ordering.BackgroundTasks.dll"] \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/IntegrationEvents/GracePeriodConfirmedIntegrationEvent.cs b/src/Services/Ordering/Ordering.BackgroundTasks/IntegrationEvents/GracePeriodConfirmedIntegrationEvent.cs new file mode 100644 index 000000000..df008ad90 --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/IntegrationEvents/GracePeriodConfirmedIntegrationEvent.cs @@ -0,0 +1,12 @@ +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + +namespace Ordering.BackgroundTasks.IntegrationEvents +{ + public class GracePeriodConfirmedIntegrationEvent : IntegrationEvent + { + public int OrderId { get; } + + public GracePeriodConfirmedIntegrationEvent(int orderId) => + OrderId = orderId; + } +} diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj new file mode 100644 index 000000000..731d6df06 --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj @@ -0,0 +1,32 @@ + + + + netcoreapp2.0 + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + ..\..\..\..\docker-compose.dcproj + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs new file mode 100644 index 000000000..23d0a5e42 --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Logging; + +namespace Ordering.BackgroundTasks +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup() + .UseHealthChecks("/hc") + .ConfigureLogging((hostingContext, builder) => + { + builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); + builder.AddDebug(); + builder.AddConsole(); + }).Build(); + } +} diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Properties/launchSettings.json b/src/Services/Ordering/Ordering.BackgroundTasks/Properties/launchSettings.json new file mode 100644 index 000000000..6d60a7d28 --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:5161/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Ordering.BackgroundTasks": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5162/" + } + } +} diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Startup.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Startup.cs new file mode 100644 index 000000000..bb7ae0902 --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Startup.cs @@ -0,0 +1,161 @@ +using Autofac; +using Autofac.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Azure.ServiceBus; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.HealthChecks; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Ordering.BackgroundTasks.Configuration; +using Ordering.BackgroundTasks.Tasks; +using RabbitMQ.Client; +using System; + +namespace Ordering.BackgroundTasks +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public IServiceProvider ConfigureServices(IServiceCollection services) + { + //add health check for this service + services.AddHealthChecks(checks => + { + var minutes = 1; + + if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed)) + { + minutes = minutesParsed; + } + checks.AddSqlCheck("OrderingDb", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes)); + }); + + //configure settings + + services.Configure(Configuration); + services.AddOptions(); + + //configure background task + + services.AddSingleton(); + + //configure event bus related services + + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + + var serviceBusConnectionString = Configuration["EventBusConnection"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); + + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); + }); + } + else + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + + + var factory = new ConnectionFactory() + { + HostName = Configuration["EventBusConnection"] + }; + + if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) + { + factory.UserName = Configuration["EventBusUserName"]; + } + + if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) + { + factory.Password = Configuration["EventBusPassword"]; + } + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); + }); + } + + RegisterEventBus(services); + + //create autofac based service provider + var container = new ContainerBuilder(); + container.Populate(services); + + + return new AutofacServiceProvider(container.Build()); + } + + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 + } + + + private void RegisterEventBus(IServiceCollection services) + { + var subscriptionClientName = Configuration["SubscriptionClientName"]; + + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); + }); + } + else + { + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); + } + + services.AddSingleton(); + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/BackgroundService.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/Base/BackgroundTask.cs similarity index 95% rename from src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/BackgroundService.cs rename to src/Services/Ordering/Ordering.BackgroundTasks/Tasks/Base/BackgroundTask.cs index 205b3c75a..6611fc3ab 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/BackgroundService.cs +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/Base/BackgroundTask.cs @@ -1,12 +1,11 @@ -using System; +using Microsoft.Extensions.Hosting; +using System; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Hosting; - -namespace Ordering.API.Infrastructure.HostedServices +namespace Ordering.BackgroundTasks.Tasks.Base { - // Copyright (c) .NET Foundation. All rights reserved. + // 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. /// @@ -19,6 +18,7 @@ namespace Ordering.API.Infrastructure.HostedServices public abstract class BackgroundService : IHostedService, IDisposable { private Task _executingTask; + private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource(); /// @@ -78,6 +78,4 @@ namespace Ordering.API.Infrastructure.HostedServices _stoppingCts.Cancel(); } } - - } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/GracePeriodManagerService.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs similarity index 59% rename from src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/GracePeriodManagerService.cs rename to src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs index 52b1b2da7..c89b8cbf3 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/GracePeriodManagerService.cs +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs @@ -1,51 +1,53 @@ -namespace Ordering.API.Infrastructure.HostedServices +using Dapper; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Ordering.BackgroundTasks.Configuration; +using Ordering.BackgroundTasks.IntegrationEvents; +using Ordering.BackgroundTasks.Tasks.Base; +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Threading; +using System.Threading.Tasks; + +namespace Ordering.BackgroundTasks.Tasks { - using Dapper; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.Services.Ordering.API; - using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - using Ordering.API.Application.IntegrationEvents.Events; - using System; - using System.Collections.Generic; - using System.Data.SqlClient; - using System.Threading; - using System.Threading.Tasks; - - public class GracePeriodManagerService : BackgroundService + public class GracePeriodManagerService + : BackgroundService { - private readonly OrderingSettings _settings; private readonly ILogger _logger; + private readonly BackgroundTaskSettings _settings; private readonly IEventBus _eventBus; - public GracePeriodManagerService(IOptions settings, - IEventBus eventBus, - ILogger logger) + public GracePeriodManagerService(IOptions settings, + IEventBus eventBus, + ILogger logger) { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); _settings = settings?.Value ?? throw new ArgumentNullException(nameof(settings)); + _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - _logger.LogDebug($"GracePeriod background task is starting."); + _logger.LogDebug($"GracePeriodManagerService is starting."); - stoppingToken.Register(() => _logger.LogDebug($"#1 GracePeriod background task is stopping.")); + stoppingToken.Register(() => _logger.LogDebug($"#1 GracePeriodManagerService background task is stopping.")); while (!stoppingToken.IsCancellationRequested) { - _logger.LogDebug($"GracePeriod background task is doing background work."); + _logger.LogDebug($"GracePeriodManagerService background task is doing background work."); CheckConfirmedGracePeriodOrders(); await Task.Delay(_settings.CheckUpdateTime, stoppingToken); - - continue; } - _logger.LogDebug($"GracePeriod background task is stopping."); - + _logger.LogDebug($"GracePeriodManagerService background task is stopping."); + + await Task.CompletedTask; } private void CheckConfirmedGracePeriodOrders() @@ -54,11 +56,11 @@ var orderIds = GetConfirmedGracePeriodOrders(); - _logger.LogDebug($"GracePeriod sent a ."); foreach (var orderId in orderIds) { - var gracePeriodConfirmedEvent = new GracePeriodConfirmedIntegrationEvent(orderId); - _eventBus.Publish(gracePeriodConfirmedEvent); + var confirmGracePeriodEvent = new GracePeriodConfirmedIntegrationEvent(orderId); + + _eventBus.Publish(confirmGracePeriodEvent); } } diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.Development.json b/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.Development.json new file mode 100644 index 000000000..fa8ce71a9 --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json b/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json new file mode 100644 index 000000000..fd26645ab --- /dev/null +++ b/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json @@ -0,0 +1,27 @@ +{ + "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;", + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Debug" + } + }, + "Console": { + "LogLevel": { + "Default": "Debug" + } + } + }, + "SubscriptionClientName": "BackgroundTasks", + "GracePeriodTime": "1", + "CheckUpdateTime": "1000", + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "AzureServiceBusEnabled": false, + "EventBusRetryCount": 5, + "EventBusConnection": "", + "EventBusUserName": "", + "EventBusPassword": "" +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs index d2e742b33..428d97580 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs @@ -95,8 +95,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O { if (_orderStatusId == OrderStatus.Submitted.Id) { - AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems)); _orderStatusId = OrderStatus.AwaitingValidation.Id; + + AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems)); } } @@ -104,10 +105,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O { if (_orderStatusId == OrderStatus.AwaitingValidation.Id) { - AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id)); - _orderStatusId = OrderStatus.StockConfirmed.Id; _description = "All the items were confirmed with available stock."; + + AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id)); } } @@ -115,10 +116,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O { if (_orderStatusId == OrderStatus.StockConfirmed.Id) { - AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems)); - _orderStatusId = OrderStatus.Paid.Id; _description = "The payment was performed at a simulated \"American Bank checking bank account endinf on XX35071\""; + + AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems)); } } diff --git a/src/Services/Payment/Payment.API/Startup.cs b/src/Services/Payment/Payment.API/Startup.cs index e06c7c7f2..02cd4c70e 100644 --- a/src/Services/Payment/Payment.API/Startup.cs +++ b/src/Services/Payment/Payment.API/Startup.cs @@ -103,6 +103,10 @@ namespace Payment.API app.UsePathBase(pathBase); } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 + ConfigureEventBus(app); } diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs index ced47ea67..105b1ed9e 100644 --- a/src/Web/WebMVC/Startup.cs +++ b/src/Web/WebMVC/Startup.cs @@ -160,6 +160,11 @@ namespace Microsoft.eShopOnContainers.WebMVC app.UsePathBase(pathBase); } + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 + app.UseSession(); app.UseStaticFiles(); diff --git a/src/Web/WebSPA/Startup.cs b/src/Web/WebSPA/Startup.cs index 3f2354b97..f49eba772 100644 --- a/src/Web/WebSPA/Startup.cs +++ b/src/Web/WebSPA/Startup.cs @@ -110,7 +110,12 @@ namespace eShopConContainers.WebSPA { loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); app.UsePathBase(pathBase); - } + } + + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 app.Use(async (context, next) => { diff --git a/src/Web/WebStatus/Startup.cs b/src/Web/WebStatus/Startup.cs index 19aedc449..6f32ce5a8 100644 --- a/src/Web/WebStatus/Startup.cs +++ b/src/Web/WebStatus/Startup.cs @@ -72,7 +72,12 @@ namespace WebStatus if (!string.IsNullOrEmpty(pathBase)) { app.UsePathBase(pathBase); - } + } + + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + 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 app.UseStaticFiles();