diff --git a/.gitignore b/.gitignore index d7f16d65c..0fb1c0ab0 100644 --- a/.gitignore +++ b/.gitignore @@ -259,3 +259,4 @@ pub/ #Ignore marker-file used to know which docker files we have. .eshopdocker_* /src/Web/WebMVC/wwwroot/lib +/src/Web/WebMVC/wwwroot/css/site.min.css diff --git a/cli-windows/build-images.ps1 b/cli-windows/build-images.ps1 new file mode 100644 index 000000000..d454f3a14 --- /dev/null +++ b/cli-windows/build-images.ps1 @@ -0,0 +1,11 @@ +Param([string] $imageTag) + +$scriptPath = Split-Path $script:MyInvocation.MyCommand.Path + +if ([string]::IsNullOrEmpty($imageTag)) { + $imageTag = $(git rev-parse --abbrev-ref HEAD) +} + +Write-Host "Building images with tag $imageTag" -ForegroundColor Yellow +$env:TAG=$imageTag +docker-compose -f "$scriptPath\..\docker-compose.yml" build \ No newline at end of file diff --git a/docker-compose-windows.yml b/docker-compose-windows.yml index f281d855a..5a7e3ff16 100644 --- a/docker-compose-windows.yml +++ b/docker-compose-windows.yml @@ -2,7 +2,7 @@ version: '2.1' services: basket.api: - image: eshop/basket.api-win + image: eshop/basket.api-win:${TAG:-latest} build: context: ./src/Services/Basket/Basket.API dockerfile: Dockerfile.nanowin @@ -11,7 +11,7 @@ services: - identity.api catalog.api: - image: eshop/catalog.api-win + image: eshop/catalog.api-win:${TAG:-latest} build: context: ./src/Services/Catalog/Catalog.API dockerfile: Dockerfile.nanowin @@ -19,7 +19,7 @@ services: - sql.data identity.api: - image: eshop/identity.api-win + image: eshop/identity.api-win:${TAG:-latest} build: context: ./src/Services/Identity/Identity.API dockerfile: Dockerfile.nanowin @@ -27,7 +27,7 @@ services: - sql.data ordering.api: - image: eshop/ordering.api-win + image: eshop/ordering.api-win:${TAG:-latest} build: context: ./src/Services/Ordering/Ordering.API dockerfile: Dockerfile.nanowin @@ -35,7 +35,7 @@ services: - sql.data webspa: - image: eshop/webspa-win + image: eshop/webspa-win:${TAG:-latest} build: context: ./src/Web/WebSPA dockerfile: Dockerfile.nanowin @@ -44,7 +44,7 @@ services: - basket.api webmvc: - image: eshop/webmvc-win + image: eshop/webmvc-win:${TAG:-latest} build: context: ./src/Web/WebMVC dockerfile: Dockerfile.nanowin @@ -55,7 +55,7 @@ services: - basket.api locations.api: - image: locations.api + image: eshop/locations.api:${TAG:-latest} build: context: ./src/Services/Location/Locations.API dockerfile: Dockerfile @@ -64,7 +64,7 @@ services: - rabbitmq marketing.api: - image: eshop/marketing.api + image: eshop/marketing.api:${TAG:-latest} build: context: ./src/Services/Marketing/Marketing.API dockerfile: Dockerfile diff --git a/docker-compose.ci.build.yml b/docker-compose.ci.build.yml index 86c32ccfb..b76d26fb8 100644 --- a/docker-compose.ci.build.yml +++ b/docker-compose.ci.build.yml @@ -1,4 +1,4 @@ -version: '2' +version: '3' services: ci-build: diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 8520197f5..b840bda61 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,4 +1,4 @@ -version: '2' +version: '3' # The default docker-compose.override file can use the "localhost" as the external name for testing web apps within the same dev machine. # The ESHOP_EXTERNAL_DNS_NAME_OR_IP environment variable is taken, by default, from the ".env" file defined like: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 634253d8a..8b9762cf5 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,4 +1,4 @@ -version: '2' +version: '3' # The Production docker-compose file has to have the external/real IPs or DNS names for the services # The ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP environment variable is taken, by default, from the ".env" file defined like: diff --git a/docker-compose.vs.debug.yml b/docker-compose.vs.debug.yml index 04799273d..b0c792d32 100644 --- a/docker-compose.vs.debug.yml +++ b/docker-compose.vs.debug.yml @@ -1,4 +1,4 @@ -version: '2' +version: '3' services: basket.api: diff --git a/docker-compose.vs.release.yml b/docker-compose.vs.release.yml index 15bd7e5be..6aac3f799 100644 --- a/docker-compose.vs.release.yml +++ b/docker-compose.vs.release.yml @@ -1,4 +1,4 @@ -version: '2' +version: '3' services: basket.api: diff --git a/docker-compose.yml b/docker-compose.yml index e728e125d..66b8ba49e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,8 @@ -version: '2' - +version: '3' services: graceperiodmanager: - image: eshop/graceperiodmanager + image: eshop/graceperiodmanager:${TAG:-latest} build: context: ./src/Services/GracePeriod/GracePeriodManager dockerfile: Dockerfile @@ -12,7 +11,7 @@ services: - rabbitmq basket.api: - image: eshop/basket.api + image: eshop/basket.api:${TAG:-latest} build: context: ./src/Services/Basket/Basket.API dockerfile: Dockerfile @@ -21,7 +20,7 @@ services: - identity.api catalog.api: - image: eshop/catalog.api + image: eshop/catalog.api:${TAG:-latest} build: context: ./src/Services/Catalog/Catalog.API dockerfile: Dockerfile @@ -30,7 +29,7 @@ services: - rabbitmq identity.api: - image: eshop/identity.api + image: eshop/identity.api:${TAG:-latest} build: context: ./src/Services/Identity/Identity.API dockerfile: Dockerfile @@ -38,7 +37,7 @@ services: - sql.data ordering.api: - image: eshop/ordering.api + image: eshop/ordering.api:${TAG:-latest} build: context: ./src/Services/Ordering/Ordering.API dockerfile: Dockerfile @@ -47,7 +46,7 @@ services: - rabbitmq marketing.api: - image: eshop/marketing.api + image: eshop/marketing.api:${TAG:-latest} build: context: ./src/Services/Marketing/Marketing.API dockerfile: Dockerfile @@ -58,7 +57,7 @@ services: - rabbitmq webspa: - image: eshop/webspa + image: eshop/webspa:${TAG:-latest} build: context: ./src/Web/WebSPA dockerfile: Dockerfile @@ -67,7 +66,7 @@ services: - basket.api webmvc: - image: eshop/webmvc + image: eshop/webmvc:${TAG:-latest} build: context: ./src/Web/WebMVC dockerfile: Dockerfile @@ -95,13 +94,13 @@ services: - "5672:5672" webstatus: - image: eshop/webstatus + image: eshop/webstatus:${TAG:-latest} build: context: ./src/Web/WebStatus dockerfile: Dockerfile payment.api: - image: eshop/payment.api + image: eshop/payment.api:${TAG:-latest} build: context: ./src/Services/Payment/Payment.API dockerfile: Dockerfile @@ -109,7 +108,7 @@ services: - rabbitmq locations.api: - image: eshop/locations.api + image: eshop/locations.api:${TAG:-latest} build: context: ./src/Services/Location/Locations.API dockerfile: Dockerfile diff --git a/global.json b/global.json new file mode 100644 index 000000000..38fed7db6 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version":"1.0.4" + } +} \ No newline at end of file diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index 9930474ba..5b6c5732f 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -2,10 +2,14 @@ Param( [parameter(Mandatory=$false)][string]$registry, [parameter(Mandatory=$false)][string]$dockerUser, [parameter(Mandatory=$false)][string]$dockerPassword, - [parameter(Mandatory=$false)][bool]$deployCI, - [parameter(Mandatory=$false)][bool]$useDockerHub, [parameter(Mandatory=$false)][string]$execPath, - [parameter(Mandatory=$false)][string]$kubeconfigPath + [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=$false, + [parameter(Mandatory=$false)][bool]$deployInfrastructure=$true ) function ExecKube($cmd) { @@ -20,7 +24,11 @@ function ExecKube($cmd) { } } -# Not used when deploying through CI VSTS +# Initialization +$debugMode = $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent +$useDockerHub = [string]::IsNullOrEmpty($registry) + +# Check required commands (only if not in CI environment) if(-not $deployCI) { $requiredCommands = ("docker", "docker-compose", "kubectl") foreach ($command in $requiredCommands) { @@ -30,6 +38,45 @@ if(-not $deployCI) { } } } +else { + $buildImages = false; # Never build images through CI, as they previously built +} + +# Get tag to use from current branch if no tag is passed +if ([string]::IsNullOrEmpty($imageTag)) { + $imageTag = $(git rev-parse --abbrev-ref HEAD) +} +Write-Host "Docker image Tag: $imageTag" -ForegroundColor Yellow + +# Read config to use +$config = Get-Content -Raw -Path $configFile | ConvertFrom-Json +if ($debugMode) { + Write-Host "[DEBUG]: Using following JSON config: " -ForegroundColor Yellow + $json = ConvertTo-Json $config -Depth 5 + Write-Host $json + if (-not $deployCI) { + Write-Host "[DEBUG]: Press a key " -ForegroundColor Yellow + [System.Console]::Read() + } +} + +# building and publishing docker images if needed +if($buildImages) { + Write-Host "Building and publishing eShopOnContainers..." -ForegroundColor Yellow + dotnet restore ../eShopOnContainers-ServicesAndWebApps.sln + dotnet publish -c Release -o obj/Docker/publish ../eShopOnContainers-ServicesAndWebApps.sln + + 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..." -ForegroundColor Yellow + $services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "marketing.api","payment.api","locations.api", "webmvc", "webspa", "webstatus") + foreach ($service in $services) { + docker tag eshop/${service}:$imageTag $registry/eshop/${service}:$imageTag + docker push $registry/eshop/${service}:$imageTag + } +} # Use ACR instead of DockerHub as image repository if(-not $useDockerHub) { @@ -54,38 +101,34 @@ 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 deploymentsExecKube -cmd 'delete configmap config-files' ExecKube -cmd 'create configmap config-files --from-file=nginx-conf=nginx.conf' ExecKube -cmd 'label configmap config-files app=eshop' -ExecKube -cmd 'create -f sql-data.yaml -f basket-data.yaml -f keystore-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml' -# building and publishing docker images not necessary when deploying through CI VSTS -if(-not $deployCI) { - Write-Host "Building and publishing eShopOnContainers..." -ForegroundColor Yellow - dotnet restore ../eShopOnContainers-ServicesAndWebApps.sln - dotnet publish -c Release -o obj/Docker/publish ../eShopOnContainers-ServicesAndWebApps.sln - - Write-Host "Building Docker images..." -ForegroundColor Yellow - docker-compose -p .. -f ../docker-compose.yml build - - Write-Host "Pushing images to $registry..." -ForegroundColor Yellow - $services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "webmvc", "webspa", "webstatus") - foreach ($service in $services) { - docker tag eshop/$service $registry/eshop/$service - docker push $registry/eshop/$service - } +if ($deployInfrastructure) { + Write-Host 'Deploying infrastructure deployments (databases, redis, ...)' -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 "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 +Write-Host 'Deploying code deployments (databases, redis, ...)' -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" + ExecKube -cmd 'create configmap urls ` --from-literal=BasketUrl=http://basket ` --from-literal=BasketHealthCheckUrl=http://basket/hc ` @@ -101,37 +144,65 @@ ExecKube -cmd 'create configmap urls ` --from-literal=MvcClientCatalogUrl=http://catalog ` --from-literal=MvcClientBasketUrl=http://basket ` --from-literal=WebSpaHealthCheckUrl=http://webspa/hc ` - --from-literal=SpaClientOrderingExternalUrl=http://$($frontendUrl)/ordering-api ` - --from-literal=SpaClientCatalogExternalUrl=http://$($frontendUrl)/catalog-api ` - --from-literal=SpaClientBasketExternalUrl=http://$($frontendUrl)/basket-api ` - --from-literal=SpaClientIdentityExternalUrl=http://$($frontendUrl)/identity ` - --from-literal=SpaClientExternalUrl=http://$($frontendUrl)' + --from-literal=SpaClientOrderingExternalUrl=http://$($externalDns)/ordering-api ` + --from-literal=SpaClientCatalogExternalUrl=http://$($externalDns)/catalog-api ` + --from-literal=SpaClientBasketExternalUrl=http://$($externalDns)/basket-api ` + --from-literal=SpaClientIdentityExternalUrl=http://$($externalDns)/identity ` + --from-literal=SpaClientExternalUrl=http://$($externalDns)' ExecKube -cmd 'label configmap urls app=eshop' -Write-Host "Creating deployments..." -ForegroundColor Yellow +Write-Host "Applying external configuration from json" -ForegroundColor Yellow + +ExecKube -cmd 'create configmap externalcfg ` + --from-literal=CatalogSqlDb=$($config.sql.catalog) ` + --from-literal=IdentitySqlDb=$($config.sql.identity) ` + --from-literal=OrderingSqlDb=$($config.sql.ordering) ` + --from-literal=MarketingSqlDb=$($config.sql.marketing) ` + --from-literal=LocationsNoSqlDb=$($config.nosql.locations.constr) ` + --from-literal=LocationsNoSqlDbName=$($config.nosql.locations.db) ` + --from-literal=MarketingNoSqlDb=$($config.nosql.marketing.constr) ` + --from-literal=MarketingNoSqlDbName=$($config.nosql.marketing.db) ` + --from-literal=BasketRedisConStr=$($config.redis.basket) ` + --from-literal=LocationsBus=$($config.servicebus.locations) ` + --from-literal=MarketingBus=$($config.servicebus.marketing) ` + --from-literal=BasketBus=$($config.servicebus.basket) ` + --from-literal=OrderingBus=$($config.servicebus.ordering) ` + --from-literal=CatalogBus=$($config.servicebus.catalog) ` + --from-literal=PaymentBus=$($config.servicebus.payment) ` + --from-literal=UseAzureServiceBus=$($config.servicebus.use_azure) ` + --from-literal=keystore=$($config.redis.keystore) ' +ExecKube -cmd 'label configmap externalcfg app=eshop' +Write-Host "Creating deployments..." -ForegroundColor Yellow ExecKube -cmd 'create -f deployments.yaml' -# not using ACR for pulling images when deploying through CI VSTS -if(-not $deployCI) { - # update deployments with the private registry before k8s tries to pull images - # (deployment templating, or Helm, would obviate this) - Write-Host "Update Image containers..." -ForegroundColor Yellow - ExecKube -cmd 'set image deployments/basket basket=$registry/eshop/basket.api' - ExecKube -cmd 'set image deployments/catalog catalog=$registry/eshop/catalog.api' - ExecKube -cmd 'set image deployments/identity identity=$registry/eshop/identity.api' - ExecKube -cmd 'set image deployments/ordering ordering=$registry/eshop/ordering.api' - ExecKube -cmd 'set image deployments/webmvc webmvc=$registry/eshop/webmvc' - ExecKube -cmd 'set image deployments/webstatus webstatus=$registry/eshop/webstatus' - ExecKube -cmd 'set image deployments/webspa webspa=$registry/eshop/webspa' +# update deployments with the correct image (with tag and/or registry) +Write-Host "Update Image containers to use prefix '$registry' and tag '$imageTag'" -ForegroundColor Yellow +$registryPath = "" +if (-not [string]::IsNullOrEmpty($registry)) { + $registryPath = "$registry/" } +ExecKube -cmd 'set image deployments/basket basket=${registryPath}eshop/basket.api:$imageTag' +ExecKube -cmd 'set image deployments/catalog catalog=${registryPath}eshop/catalog.api:$imageTag' +ExecKube -cmd 'set image deployments/identity identity=${registryPath}eshop/identity.api:$imageTag' +ExecKube -cmd 'set image deployments/ordering ordering=${registryPath}eshop/ordering.api:$imageTag' +ExecKube -cmd 'set image deployments/marketing marketing=${registryPath}eshop/marketing.api:$imageTag' +ExecKube -cmd 'set image deployments/locations locations=${registryPath}eshop/locations.api:$imageTag' +ExecKube -cmd 'set image deployments/payment payment=${registryPath}eshop/payment.api:$imageTag' +ExecKube -cmd 'set image deployments/webmvc webmvc=${registryPath}eshop/webmvc:$imageTag' +ExecKube -cmd 'set image deployments/webstatus webstatus=${registryPath}eshop/webstatus:$imageTag' +ExecKube -cmd 'set image deployments/webspa webspa=${registryPath}eshop/webspa:$imageTag' + Write-Host "Execute rollout..." -ForegroundColor Yellow ExecKube -cmd 'rollout resume deployments/basket' ExecKube -cmd 'rollout resume deployments/catalog' ExecKube -cmd 'rollout resume deployments/identity' ExecKube -cmd 'rollout resume deployments/ordering' +ExecKube -cmd 'rollout resume deployments/marketing' +ExecKube -cmd 'rollout resume deployments/locations' +ExecKube -cmd 'rollout resume deployments/payment' ExecKube -cmd 'rollout resume deployments/webmvc' ExecKube -cmd 'rollout resume deployments/webstatus' ExecKube -cmd 'rollout resume deployments/webspa' diff --git a/k8s/deployments.yaml b/k8s/deployments.yaml index 62352e2ef..0a42f573d 100644 --- a/k8s/deployments.yaml +++ b/k8s/deployments.yaml @@ -18,9 +18,20 @@ spec: - name: ASPNETCORE_URLS value: http://0.0.0.0:80/basket-api - name: ConnectionString - value: basket-data + valueFrom: + configMapKeyRef: + name: externalcfg + key: BasketRedisConStr - name: EventBusConnection - value: rabbitmq + valueFrom: + configMapKeyRef: + name: externalcfg + key: BasketBus + - name: AzureServiceBusEnabled + valueFrom: + configMapKeyRef: + name: externalcfg + key: UseAzureServiceBus - name: IdentityUrl valueFrom: configMapKeyRef: @@ -51,14 +62,20 @@ spec: - name: ASPNETCORE_URLS value: http://0.0.0.0:80/catalog-api - name: ConnectionString - value: "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word" - - name: EventBusConnection - value: rabbitmq + valueFrom: + configMapKeyRef: + name: externalcfg + key: CatalogSqlDb - name: ExternalCatalogBaseUrl valueFrom: configMapKeyRef: name: urls key: CatalogUrl + - name: EventBusConnection + valueFrom: + configMapKeyRef: + name: externalcfg + key: CatalogBus ports: - containerPort: 80 imagePullSecrets: @@ -84,9 +101,15 @@ spec: - name: ASPNETCORE_URLS value: http://0.0.0.0:80/identity - name: ConnectionStrings__DefaultConnection - value: "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word" + valueFrom: + configMapKeyRef: + name: externalcfg + key: IdentitySqlDb - name: DPConnectionString - value: keystore-data + valueFrom: + configMapKeyRef: + name: externalcfg + key: keystore - name: IsClusterEnv value: 'True' - name: MvcClient @@ -124,9 +147,69 @@ spec: - name: ASPNETCORE_URLS value: http://0.0.0.0:80/ordering-api - name: ConnectionString - value: "Server=sql-data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;" + valueFrom: + configMapKeyRef: + name: externalcfg + key: OrderingSqlDb + - name: EventBusConnection + valueFrom: + configMapKeyRef: + name: externalcfg + key: OrderingBus + - name: AzureServiceBusEnabled + valueFrom: + configMapKeyRef: + name: externalcfg + key: UseAzureServiceBus + - name: IdentityUrl + valueFrom: + configMapKeyRef: + name: urls + key: IdentityUrl + ports: + - containerPort: 80 + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: locations +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: locations + spec: + containers: + - name: locations + image: eshop/locations.api + imagePullPolicy: Always + env: + - name: ASPNETCORE_URLS + value: http://0.0.0.0:80/locations-api + - name: ConnectionString + valueFrom: + configMapKeyRef: + name: externalcfg + key: LocationsNoSqlDb + - name: Database + valueFrom: + configMapKeyRef: + name: externalcfg + key: LocationsNoSqlDbName + - name: AzureServiceBusEnabled + valueFrom: + configMapKeyRef: + name: externalcfg + key: UseAzureServiceBus - name: EventBusConnection - value: rabbitmq + valueFrom: + configMapKeyRef: + name: externalcfg + key: LocationsBus - name: IdentityUrl valueFrom: configMapKeyRef: @@ -139,6 +222,94 @@ spec: --- apiVersion: extensions/v1beta1 kind: Deployment +metadata: + name: marketing +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: marketing + spec: + containers: + - name: marketing + image: eshop/marketing.api + imagePullPolicy: Always + env: + - name: ASPNETCORE_URLS + value: http://0.0.0.0:80/marketing-api + - name: ConnectionString + valueFrom: + configMapKeyRef: + name: externalcfg + key: MarketingSqlDb + - name: MongoConnectionString + valueFrom: + configMapKeyRef: + name: externalcfg + key: MarketingNoSqlDb + - name: MongoDatabase + valueFrom: + configMapKeyRef: + name: externalcfg + key: MarketingNoSqlDbName + - name: AzureServiceBusEnabled + valueFrom: + configMapKeyRef: + name: externalcfg + key: UseAzureServiceBus + - name: EventBusConnection + valueFrom: + configMapKeyRef: + name: externalcfg + key: MarketingBus + - name: IdentityUrl + valueFrom: + configMapKeyRef: + name: urls + key: IdentityUrl + ports: + - containerPort: 80 + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: payment +spec: + paused: true + template: + metadata: + labels: + app: eshop + component: payment + spec: + containers: + - name: payment + image: eshop/payment.api + imagePullPolicy: Always + env: + - name: ASPNETCORE_URLS + value: http://0.0.0.0:80/payment-api + - name: AzureServiceBusEnabled + valueFrom: + configMapKeyRef: + name: externalcfg + key: UseAzureServiceBus + - name: EventBusConnection + valueFrom: + configMapKeyRef: + name: externalcfg + key: PaymentBus + ports: + - containerPort: 80 + imagePullSecrets: + - name: registry-key +--- +apiVersion: extensions/v1beta1 +kind: Deployment metadata: name: webmvc spec: @@ -157,7 +328,10 @@ spec: - name: ASPNETCORE_URLS value: http://0.0.0.0:80/webmvc - name: DPConnectionString - value: keystore-data + valueFrom: + configMapKeyRef: + name: externalcfg + key: keystore - name: IsClusterEnv value: 'True' - name: BasketUrl @@ -264,7 +438,10 @@ spec: - name: ASPNETCORE_URLS value: http://0.0.0.0:80 - name: DPConnectionString - value: keystore-data + valueFrom: + configMapKeyRef: + name: externalcfg + key: keystore - name: IsClusterEnv value: 'True' - name: BasketUrl diff --git a/k8s/local.json b/k8s/local.json new file mode 100644 index 000000000..9f3fef102 --- /dev/null +++ b/k8s/local.json @@ -0,0 +1,31 @@ +{ + "sql": { + "catalog": "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word;", + "identity":"Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word;", + "ordering":"Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;", + "marketing":"Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word;" + }, + "nosql": { + "locations": { + "constr": "mongodb://nosql-data", + "db": "LocationsDb" + }, + "marketing": { + "constr": "mongodb://nosql-data", + "db": "MarketingDb" + } + }, + "redis": { + "basket" : "basket-data", + "keystore": "keystore-data" + }, + "servicebus": { + "use_azure": false, + "ordering": "rabbitmq", + "marketing": "rabbitmq", + "locations": "rabbitmq", + "payment": "rabbitmq", + "basket": "rabbitmq", + "catalog": "rabbitmq" + } +} \ No newline at end of file diff --git a/k8s/nginx.conf b/k8s/nginx.conf index 1f754a8cd..22c3414a1 100644 --- a/k8s/nginx.conf +++ b/k8s/nginx.conf @@ -71,6 +71,24 @@ http { 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; diff --git a/k8s/nosql-data.yaml b/k8s/nosql-data.yaml new file mode 100644 index 000000000..5dfb67c6e --- /dev/null +++ b/k8s/nosql-data.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: eshop + component: nosql-data + name: nosql-data +spec: + ports: + - port: 27017 + selector: + app: eshop + component: nosql-data +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: nosql-data +spec: + template: + metadata: + labels: + app: eshop + component: nosql-data + spec: + containers: + - name: nosql-data + image: mongo + ports: + - containerPort: 27017 diff --git a/k8s/services.yaml b/k8s/services.yaml index 3c45806d3..02b73448a 100644 --- a/k8s/services.yaml +++ b/k8s/services.yaml @@ -56,6 +56,48 @@ spec: --- apiVersion: v1 kind: Service +metadata: + labels: + app: eshop + component: locations + name: locations +spec: + ports: + - port: 80 + selector: + app: eshop + component: locations +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: eshop + component: payment + name: payment +spec: + ports: + - port: 80 + selector: + app: eshop + component: payment +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: eshop + component: marketing + name: marketing +spec: + ports: + - port: 80 + selector: + app: eshop + component: marketing +--- +apiVersion: v1 +kind: Service metadata: labels: app: eshop @@ -94,4 +136,4 @@ spec: - port: 80 selector: app: eshop - component: webspa \ No newline at end of file + component: webspa diff --git a/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs index 6f519f6b1..0c53582e3 100644 --- a/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs +++ b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs @@ -24,6 +24,7 @@ { await SetIndexes(); await SetUSLocations(); + await SetBarcelonaLocations(); } } @@ -85,6 +86,20 @@ await ctx.Locations.InsertOneAsync(rdm); } + static async Task SetBarcelonaLocations() + { + var bcn = new Locations() + { + Code = "BCN", + Description = "Barcelona", + LocationId = 5 + }; + bcn.SetLocation(2.156453, 41.395226); + bcn.SetArea(GetBarcelonaPoligon()); + await ctx.Locations.InsertOneAsync(bcn); + } + + static async Task SetIndexes() { // Set location indexes @@ -145,5 +160,18 @@ new GeoJson2DGeographicCoordinates(-124.68633, 48.8943) }; } + + static List GetBarcelonaPoligon() + { + return new List() + { + new GeoJson2DGeographicCoordinates(2.033879, 41.383858), + new GeoJson2DGeographicCoordinates(2.113741, 41.419068), + new GeoJson2DGeographicCoordinates(2.188778, 41.451153), + new GeoJson2DGeographicCoordinates(2.235266, 41.418033), + new GeoJson2DGeographicCoordinates(2.137101, 41.299536), + new GeoJson2DGeographicCoordinates(2.033879, 41.383858) + }; + } } } diff --git a/src/Web/WebMVC/wwwroot/css/site.min.css b/src/Web/WebMVC/wwwroot/css/site.min.css deleted file mode 100644 index 4d03fa783..000000000 --- a/src/Web/WebMVC/wwwroot/css/site.min.css +++ /dev/null @@ -1 +0,0 @@ -.esh-app-footer{background-color:#000;border-top:1px solid #eee;margin-top:2.5rem;padding-bottom:2.5rem;padding-top:2.5rem;width:100%}.esh-app-footer-brand{height:50px;width:230px}.esh-app-footer-text{color:#83d01b;line-height:50px;text-align:right;width:100%}@font-face{font-family:Montserrat;font-weight:400;src:url("../fonts/Montserrat-Regular.eot?") format("eot"),url("../fonts/Montserrat-Regular.woff") format("woff"),url("../fonts/Montserrat-Regular.ttf") format("truetype"),url("../fonts/Montserrat-Regular.svg#Montserrat") format("svg")}@font-face{font-family:Montserrat;font-weight:700;src:url("../fonts/Montserrat-Bold.eot?") format("eot"),url("../fonts/Montserrat-Bold.woff") format("woff"),url("../fonts/Montserrat-Bold.ttf") format("truetype"),url("../fonts/Montserrat-Bold.svg#Montserrat") format("svg")}html,body{font-family:Montserrat,sans-serif;font-size:16px;font-weight:400;z-index:10}*,*::after,*::before{box-sizing:border-box}.preloading{color:#00a69c;display:block;font-size:1.5rem;left:50%;position:fixed;top:50%;transform:translate(-50%,-50%)}select::-ms-expand{display:none}@media screen and (min-width:992px){.form-input{max-width:360px;width:360px}}.form-input{border-radius:0;height:45px;padding:10px}.form-input-small{max-width:100px !important}.form-input-medium{width:150px !important}.alert{padding-left:0}.alert-danger{background-color:transparent;border:0;color:#fb0d0d;font-size:12px}a,a:active,a:hover,a:visited{color:#000;text-decoration:none;transition:color .35s}a:hover,a:active{color:#75b918;transition:color .35s}.esh-basket{min-height:80vh}.esh-basket-titles{padding-bottom:1rem;padding-top:2rem}.esh-basket-titles--clean{padding-bottom:0;padding-top:0}.esh-basket-title{text-transform:uppercase}.esh-basket-items--border{border-bottom:1px solid #eee;padding:.5rem 0}.esh-basket-items--border:last-of-type{border-color:transparent}.esh-basket-item{font-size:1rem;font-weight:300}.esh-basket-item--middle{line-height:8rem}@media screen and (max-width:1024px){.esh-basket-item--middle{line-height:1rem}}.esh-basket-item--mark{color:#00a69c}.esh-basket-image{height:8rem}.esh-basket-input{line-height:1rem;width:100%}.esh-basket-checkout{border:none;border-radius:0;background-color:#83d01b;color:#fff;display:inline-block;font-size:1rem;font-weight:400;margin-top:1rem;padding:1rem 1.5rem;text-align:center;text-transform:uppercase;transition:all .35s}.esh-basket-checkout:hover{background-color:#4a760f;transition:all .35s}.esh-basket-margin12{margin-left:12px}.esh-basketstatus{cursor:pointer;display:inline-block;float:right;position:relative;transition:all .35s}.esh-basketstatus.is-disabled{opacity:.5;pointer-events:none}.esh-basketstatus-image{height:36px;margin-top:.5rem}.esh-basketstatus-badge{background-color:#83d01b;border-radius:50%;color:#fff;display:block;height:1.5rem;left:50%;position:absolute;text-align:center;top:0;transform:translateX(-38%);transition:all .35s;width:1.5rem}.esh-basketstatus:hover .esh-basketstatus-badge{background-color:transparent;color:#75b918;transition:all .35s}.esh-catalog-hero{background-image:url("../images/main_banner.png");background-size:cover;height:260px;width:100%}.esh-catalog-title{position:relative;top:74.28571px}.esh-catalog-filters{background-color:#00a69c;height:65px}.esh-catalog-filter{background-color:transparent;border-color:#00d9cc;color:#fff;cursor:pointer;margin-right:1rem;margin-top:.5rem;outline-color:#83d01b;padding-bottom:0;padding-left:.5rem;padding-right:.5rem;padding-top:1.5rem;min-width:140px;-webkit-appearance:none}.esh-catalog-filter option{background-color:#00a69c}.esh-catalog-label{display:inline-block;position:relative;z-index:0}.esh-catalog-label::before{color:rgba(255,255,255,.5);content:attr(data-title);font-size:.65rem;margin-top:.65rem;margin-left:.5rem;position:absolute;text-transform:uppercase;z-index:1}.esh-catalog-label::after{background-image:url("../images/arrow-down.png");height:7px;content:'';position:absolute;right:1.5rem;top:2.5rem;width:10px;z-index:1}.esh-catalog-send{background-color:#83d01b;color:#fff;cursor:pointer;font-size:1rem;transform:translateY(.5rem);padding:.5rem;transition:all .35s}.esh-catalog-send:hover{background-color:#4a760f;transition:all .35s}.esh-catalog-items{margin-top:1rem}.esh-catalog-item{text-align:center;margin-bottom:1.5rem;width:33%;display:inline-block;float:none !important}@media screen and (max-width:1024px){.esh-catalog-item{width:50%}}@media screen and (max-width:768px){.esh-catalog-item{width:100%}}.esh-catalog-thumbnail{max-width:370px;width:100%}.esh-catalog-button{background-color:#83d01b;border:none;color:#fff;cursor:pointer;font-size:1rem;height:3rem;margin-top:1rem;transition:all .35s;width:80%}.esh-catalog-button.is-disabled{opacity:.5;pointer-events:none}.esh-catalog-button:hover{background-color:#4a760f;transition:all .35s}.esh-catalog-name{font-size:1rem;font-weight:300;margin-top:.5rem;text-align:center;text-transform:uppercase}.esh-catalog-price{text-align:center;font-weight:900;font-size:28px}.esh-catalog-price::before{content:'$'}.esh-orders{min-height:80vh;overflow-x:hidden}.esh-orders-header{background-color:#00a69c;height:4rem}.esh-orders-back{color:rgba(255,255,255,.4);line-height:4rem;text-transform:uppercase;text-decoration:none;transition:color .35s}.esh-orders-back:hover{color:#fff;transition:color .35s}.esh-orders-titles{padding-bottom:1rem;padding-top:2rem}.esh-orders-title{text-transform:uppercase}.esh-orders-items{height:2rem;line-height:2rem;position:relative}.esh-orders-items:nth-of-type(2n+1):before{background-color:#eef;content:'';height:100%;left:0;margin-left:-100vw;position:absolute;top:0;width:200vw;z-index:-1}.esh-orders-item{font-weight:300}.esh-orders-item--hover{opacity:0;pointer-events:none}.esh-orders-items:hover .esh-orders-item--hover{opacity:1;pointer-events:all}.esh-orders-link{color:#83d01b;text-decoration:none;transition:color .35s}.esh-orders-link:hover{color:#75b918;transition:color .35s}.esh-orders_detail{min-height:80vh}.esh-orders_detail-section{padding:1rem 0}.esh-orders_detail-section--right{text-align:right}.esh-orders_detail-titles{padding-bottom:1rem;padding-top:2rem}.esh-orders_detail-title{text-transform:uppercase}.esh-orders_detail-items--border{border-bottom:1px solid #eee;padding:.5rem 0}.esh-orders_detail-items--border:last-of-type{border-color:transparent}.esh-orders_detail-item{font-size:1rem;font-weight:300}.esh-orders_detail-item--middle{line-height:8rem}@media screen and (max-width:768px){.esh-orders_detail-item--middle{line-height:1rem}}.esh-orders_detail-item--mark{color:#83d01b}.esh-orders_detail-image{height:8rem}.esh-orders_new{min-height:80vh}.esh-orders_new-header{background-color:#00a69c;height:4rem}.esh-orders_new-back{color:rgba(255,255,255,.4);line-height:4rem;text-decoration:none;text-transform:uppercase;transition:color .35s}.esh-orders_new-back:hover{color:#fff;transition:color .35s}.esh-orders_new-section{padding:1rem 0}.esh-orders_new-section--right{text-align:right}.esh-orders_new-placeOrder{background-color:#83d01b;border:0;border-radius:0;color:#fff;display:inline-block;font-size:1rem;font-weight:400;margin-top:1rem;padding:1rem 1.5rem;text-align:center;text-transform:uppercase;transition:all .35s}.esh-orders_new-placeOrder:hover{background-color:#4a760f;transition:all .35s}.esh-orders_new-titles{padding-bottom:1rem;padding-top:2rem}.esh-orders_new-title{font-size:1.25rem;text-transform:uppercase}.esh-orders_new-items--border{border-bottom:1px solid #eee;padding:.5rem 0}.esh-orders_new-items--border:last-of-type{border-color:transparent}.esh-orders_new-item{font-size:1rem;font-weight:300}.esh-orders_new-item--middle{line-height:8rem}@media screen and (max-width:768px){.esh-orders_new-item--middle{line-height:1rem}}.esh-orders_new-item--mark{color:#83d01b}.esh-orders_new-image{height:8rem}.esh-header{background-color:#00a69c;height:4rem}.esh-header-back{color:rgba(255,255,255,.5) !important;line-height:4rem;text-transform:uppercase;text-decoration:none;transition:color .35s}.esh-header-back:hover{color:#fff !important;transition:color .35s}.esh-identity{line-height:3rem;position:relative;text-align:right}.esh-identity-section{display:inline-block;width:100%}.esh-identity-name{display:inline-block}.esh-identity-name--upper{text-transform:uppercase}@media screen and (max-width:768px){.esh-identity-name{font-size:.85rem}}.esh-identity-image{display:inline-block}.esh-identity-drop{background:#fff;height:0;min-width:14rem;right:0;overflow:hidden;padding:.5rem;position:absolute;top:2.5rem;transition:height .35s}.esh-identity:hover .esh-identity-drop{border:1px solid #eee;height:7rem;transition:height .35s}.esh-identity-item{cursor:pointer;display:block;transition:color .35s}.esh-identity-item:hover{color:#75b918;transition:color .35s}.esh-pager-wrapper{padding-top:1rem;text-align:center}.esh-pager-item{margin:0 5vw}.esh-pager-item--navigable{display:inline-block;cursor:pointer}.esh-pager-item--navigable.is-disabled{opacity:0;pointer-events:none}.esh-pager-item--navigable:hover{color:#83d01b}@media screen and (max-width:1280px){.esh-pager-item{font-size:.85rem}}@media screen and (max-width:1024px){.esh-pager-item{margin:0 4vw}} \ No newline at end of file