diff --git a/docker-compose.elk.yml b/docker-compose.elk.yml new file mode 100644 index 000000000..04e6c8a05 --- /dev/null +++ b/docker-compose.elk.yml @@ -0,0 +1,37 @@ +version: '3.4' + +services: + + elasticsearch: + build: + context: elk/elasticsearch/ + volumes: + - ./elk/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro + ports: + - "9200:9200" + - "9300:9300" + environment: + ES_JAVA_OPTS: "-Xmx256m -Xms256m" + + logstash: + build: + context: elk/logstash/ + volumes: + - ./elk/logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro + - ./elk/logstash/pipeline:/usr/share/logstash/pipeline:ro + ports: + - "8080:8080" + environment: + LS_JAVA_OPTS: "-Xmx256m -Xms256m" + depends_on: + - elasticsearch + + kibana: + build: + context: elk/kibana/ + volumes: + - ./elk/kibana/config/:/usr/share/kibana/config:ro + ports: + - "5601:5601" + depends_on: + - elasticsearch \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 55d5b10e6..2a0448bad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,7 @@ version: '3.4' services: + seq: image: datalust/seq:latest diff --git a/elk/Readme.md b/elk/Readme.md new file mode 100644 index 000000000..dddeab3fd --- /dev/null +++ b/elk/Readme.md @@ -0,0 +1,88 @@ +This article contains a brief introduction to centralized structured logging with [Serilog](https://serilog.net/) and event viewing with [ELK](https://www.elastic.co/elk-stack) in eShopOnContainers. ELK is an acronym of ElasticSearch, LogStash and Kibana. This is one of the most used tools in the industry standards. + +![](img/elk/kibana-working.png) + +## Wiring eshopOnContainers with ELK in Localhost + +eshopOnContainers is ready for work with ELK, you only need to setup the configuration parameter **LogstashUrl**, in **Serilog** Section, for achieve this, you can do it modifing this parameter in every appsettings.json of every service, or via Environment Variable **Serilog:LogstashUrl**. + +There is another option, a zero-configuration environment for testing the integration launching via ```docker-compose``` command, on the root directory of eshopOnContainers: + +```sh +docker-compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.elk.yml build + +docker-compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.elk.yml up +``` + +### Configuring Logstash index on Kibana + +Once time you have started and configured your application, you only need to configure the logstash index on kibana. +You can address to Kibana, with docker-compose setup is at [http://localhost:5601](http://localhost:5601) + +If you have accessed to kibana too early, you can see this error. It's normal, depending of your machine the kibana stack needs a bit of time to startup. +![](img/elk/kibana_startup.png) + +You can wait a bit and refresh the page, the first time you enter, you need to configure and index pattern, in the ```docker-compose``` configuration, the index pattern name is **eshops-\***. +![](img/elk/kibana_eshops_index.png) + +With the index pattern configured, you can enter in the discover section and start viewing how the tool is recollecting the logging information. + +![](img/elk/kibana_result.png) + +## Configuring ELK on Azure VM +Another option is to use a preconfigured virtual machine with Logstash, ElasticSearch and Kibana and point the configuration parameter **LogstashUrl**. For doing this you can address to Microsoft Azure, and start searching a Certified ELK Virtual Machine + +![](img/elk/create-vm-elk-azure.png) + +This options it have a certified preconfigured options (Network, VirtualMachine type, OS, RAM, Disks) for having a good starting point of ELK with good performance. + +![](img/elk/create-vm-elk-azure-summary.png) + +When you have configured the main aspects of your virtual machine, you will have a "review & create" last step like this: +![](img/elk/create-vm-elk-azure-last-step.png) + +### Configuring the bitnami environment + + This virtual machine has a lot of configuration pipeing done. If you want to change something of the default configuration you can address this documentation: + [https://docs.bitnami.com/virtual-machine/apps/elk/get-started/](https://docs.bitnami.com/virtual-machine/apps/elk/get-started/) + + The only thing you have to change is the logstash configuration inside the machine. This configuration is at the file ```/opt/bitnami/logstash/conf/logstash.conf``` + You must edit the file and overwrite with this configuration: + ```conf + input { + http { + #default host 0.0.0.0:8080 + codec => json + } +} + +## Add your filters / logstash plugins configuration here +filter { + split { + field => "events" + target => "e" + remove_field => "events" + } +} + +output { + elasticsearch { + hosts => "elasticsearch:9200" + index=>"eshops-%{+xxxx.ww}" + } +} +``` + +For doing this you can connect via ssh to the vm and edit the file using the vi editor for example. +When the file will be edited, check there are Inbound Port Rules created for the logstash service. You can do it going to Networking Menu on your ELK Virtual Machine Resource in Azure. + +![](img/elk/azure-nsg-inboundportsConfig.png) + +The only thing that remains is to connect to your vm vía browser. And check the bitnami splash page is showing. + +![](img/elk/bitnami_splash.png) + +You can get the password for accessing going to your virtual machine in azure and check the boot diagnostics, theres a message that shows to you which is your password. + +When you have the user and password you can access to the kibana tool, and create the ```eshops-*``` index pattern that is well documented at the beggining of this documentation and then start to discover. +![](img/elk/) \ No newline at end of file diff --git a/elk/elasticsearch/Dockerfile b/elk/elasticsearch/Dockerfile new file mode 100644 index 000000000..0ad46d887 --- /dev/null +++ b/elk/elasticsearch/Dockerfile @@ -0,0 +1,5 @@ +# https://github.com/elastic/elasticsearch-docker +FROM docker.elastic.co/elasticsearch/elasticsearch-oss:6.0.0 + +# Add your elasticsearch plugins setup here +# Example: RUN elasticsearch-plugin install analysis-icu diff --git a/elk/elasticsearch/config/elasticsearch.yml b/elk/elasticsearch/config/elasticsearch.yml new file mode 100644 index 000000000..e97577084 --- /dev/null +++ b/elk/elasticsearch/config/elasticsearch.yml @@ -0,0 +1,16 @@ +--- +## Default Elasticsearch configuration from elasticsearch-docker. +## from https://github.com/elastic/elasticsearch-docker/blob/master/build/elasticsearch/elasticsearch.yml +# +cluster.name: "docker-cluster" +network.host: 0.0.0.0 + +# minimum_master_nodes need to be explicitly set when bound on a public IP +# set to 1 to allow single node clusters +# Details: https://github.com/elastic/elasticsearch/pull/17288 +discovery.zen.minimum_master_nodes: 1 + +## Use single node discovery in order to disable production mode and avoid bootstrap checks +## see https://www.elastic.co/guide/en/elasticsearch/reference/current/bootstrap-checks.html +# +discovery.type: single-node diff --git a/elk/kibana/Dockerfile b/elk/kibana/Dockerfile new file mode 100644 index 000000000..1785734aa --- /dev/null +++ b/elk/kibana/Dockerfile @@ -0,0 +1,5 @@ +# https://github.com/elastic/kibana-docker +FROM docker.elastic.co/kibana/kibana-oss:6.0.0 + +# Add your kibana plugins setup here +# Example: RUN kibana-plugin install diff --git a/elk/kibana/config/kibana.yml b/elk/kibana/config/kibana.yml new file mode 100644 index 000000000..4b34a1606 --- /dev/null +++ b/elk/kibana/config/kibana.yml @@ -0,0 +1,7 @@ +--- +## Default Kibana configuration from kibana-docker. +## from https://github.com/elastic/kibana-docker/blob/master/build/kibana/config/kibana.yml +# +server.name: kibana +server.host: "0" +elasticsearch.url: http://elasticsearch:9200 diff --git a/elk/logstash/Dockerfile b/elk/logstash/Dockerfile new file mode 100644 index 000000000..d8bb475a5 --- /dev/null +++ b/elk/logstash/Dockerfile @@ -0,0 +1,6 @@ +# https://github.com/elastic/logstash-docker +FROM docker.elastic.co/logstash/logstash-oss:6.0.0 + +# Add your logstash plugins setup here +# Example: RUN logstash-plugin install logstash-filter-json +RUN logstash-plugin install logstash-input-http \ No newline at end of file diff --git a/elk/logstash/config/logstash.yml b/elk/logstash/config/logstash.yml new file mode 100644 index 000000000..d4f28f778 --- /dev/null +++ b/elk/logstash/config/logstash.yml @@ -0,0 +1,6 @@ +--- +## Default Logstash configuration from logstash-docker. +## from https://github.com/elastic/logstash-docker/blob/master/build/logstash/config/logstash-oss.yml +# +http.host: "0.0.0.0" +path.config: /usr/share/logstash/pipeline \ No newline at end of file diff --git a/elk/logstash/pipeline/logstash.conf b/elk/logstash/pipeline/logstash.conf new file mode 100644 index 000000000..b38a681d7 --- /dev/null +++ b/elk/logstash/pipeline/logstash.conf @@ -0,0 +1,22 @@ +input { + http { + #default host 0.0.0.0:8080 + codec => json + } +} + +## Add your filters / logstash plugins configuration here +filter { + split { + field => "events" + target => "e" + remove_field => "events" + } +} + +output { + elasticsearch { + hosts => "elasticsearch:9200" + index=>"eshops-%{+xxxx.ww}" + } +} diff --git a/img/elk/azure-nsg-inboundportsConfig.png b/img/elk/azure-nsg-inboundportsConfig.png new file mode 100644 index 000000000..5a0371e66 Binary files /dev/null and b/img/elk/azure-nsg-inboundportsConfig.png differ diff --git a/img/elk/bitnami_splash.png b/img/elk/bitnami_splash.png new file mode 100644 index 000000000..a34643864 Binary files /dev/null and b/img/elk/bitnami_splash.png differ diff --git a/img/elk/create-vm-elk-azure-last-step.png b/img/elk/create-vm-elk-azure-last-step.png new file mode 100644 index 000000000..348f8843c Binary files /dev/null and b/img/elk/create-vm-elk-azure-last-step.png differ diff --git a/img/elk/create-vm-elk-azure-summary.png b/img/elk/create-vm-elk-azure-summary.png new file mode 100644 index 000000000..b56ae5af3 Binary files /dev/null and b/img/elk/create-vm-elk-azure-summary.png differ diff --git a/img/elk/create-vm-elk-azure.png b/img/elk/create-vm-elk-azure.png new file mode 100644 index 000000000..b7d98bb95 Binary files /dev/null and b/img/elk/create-vm-elk-azure.png differ diff --git a/img/elk/discover-kibana.png b/img/elk/discover-kibana.png new file mode 100644 index 000000000..3977042c7 Binary files /dev/null and b/img/elk/discover-kibana.png differ diff --git a/img/elk/kibana_eshops_index.png b/img/elk/kibana_eshops_index.png new file mode 100644 index 000000000..5a4be8ec3 Binary files /dev/null and b/img/elk/kibana_eshops_index.png differ diff --git a/img/elk/kibana_result.png b/img/elk/kibana_result.png new file mode 100644 index 000000000..55b7fd3ff Binary files /dev/null and b/img/elk/kibana_result.png differ diff --git a/img/elk/kibana_startup.png b/img/elk/kibana_startup.png new file mode 100644 index 000000000..e283d7de8 Binary files /dev/null and b/img/elk/kibana_startup.png differ diff --git a/img/elk/kibana_working.png b/img/elk/kibana_working.png new file mode 100644 index 000000000..e310e2710 Binary files /dev/null and b/img/elk/kibana_working.png differ diff --git a/k8s/README.k8s.md b/k8s/README.k8s.md index 62841aba1..84d9a72f0 100644 --- a/k8s/README.k8s.md +++ b/k8s/README.k8s.md @@ -20,7 +20,7 @@ For AKS: For ACS: >``` ->./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -createAcr true -orchestratorName k8s-cluster -dnsName k8s-dns +>./gen-k8s-env-aks -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -serviceName k8s-cluster -createAcr true -nodeCount 3 -nodeVMSize Standard_D2_v2 >``` * A Docker development environment with `docker` and `docker-compose`. diff --git a/k8s/helm/deploy-all-istio.ps1 b/k8s/helm/deploy-all-istio.ps1 new file mode 100644 index 000000000..5e05c6dbb --- /dev/null +++ b/k8s/helm/deploy-all-istio.ps1 @@ -0,0 +1,116 @@ +Param( + [parameter(Mandatory=$false)][string]$registry, + [parameter(Mandatory=$false)][bool]$installIstioOnSystem=$false, + [parameter(Mandatory=$false)][string]$dockerUser, + [parameter(Mandatory=$false)][string]$dockerPassword, + [parameter(Mandatory=$false)][string]$externalDns="aks", + [parameter(Mandatory=$false)][string]$dnsname="eshoptestistio", + [parameter(Mandatory=$false)][string]$appName="eshop", + [parameter(Mandatory=$false)][bool]$deployInfrastructure=$true, + [parameter(Mandatory=$false)][string]$kialiuser="admin", + [parameter(Mandatory=$false)][string]$kialipasswrd="admin", + [parameter(Mandatory=$false)][bool]$clean=$true, + [parameter(Mandatory=$false)][string]$aksName="", + [parameter(Mandatory=$false)][string]$aksRg="", + [parameter(Mandatory=$false)][string]$imageTag="latest", + [parameter(Mandatory=$false)][bool]$useLocalk8s=$false + ) + +$dns = $externalDns + +# Instalamos Istio +# Specify the Istio version that will be leveraged throughout these instructions +$ISTIO_VERSION="1.0.6" + +# Windows +$ProgressPreference = 'SilentlyContinue'; +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +Invoke-WebRequest -URI "https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istio-$ISTIO_VERSION-win.zip" -OutFile "istio-$ISTIO_VERSION.zip" +Remove-Item istio-$ISTIO_VERSION -Recurse -ErrorAction Ignore +Expand-Archive -Path "istio-$ISTIO_VERSION.zip" -DestinationPath . + +if($installIstioOnSystem -eq $true) { + New-Item -ItemType Directory -Force -Path "C:\Program Files\Istio" + mv ./istio-$ISTIO_VERSION/bin/istioctl.exe "C:\Program Files/Istio/" + $PATH = [environment]::GetEnvironmentVariable("PATH", "User") + [environment]::SetEnvironmentVariable("PATH", $PATH + "; C:\Program Files\Istio", "User") +} +# Primero Desinstalamos cualquier cosa que haya en el cluster +if ($clean -eq $true) { + Write-Host "Cleaning previous helm releases..." -ForegroundColor Green + helm delete --purge $(helm ls -q) + kubectl delete -f istio-$ISTIO_VERSION/install/kubernetes/helm/istio/templates/crds.yaml -n istio-system + Write-Host "Previous releases deleted" -ForegroundColor Green +} + +Write-Host "Generating Kiali Credentials" -ForegroundColor Green +#generamos la credenciales para que kiali arranque sin problemas +kubectl -n istio-system create secret generic kiali --from-literal=username=$kialiuser --from-literal=passphrase=$kialipasswrd + + +Write-Host "Deploying Istio in the cluster" -ForegroundColor Green +helm install istio-$ISTIO_VERSION/install/kubernetes/helm/istio --wait --name istio --namespace istio-system --set global.controlPlaneSecurityEnabled=true --set grafana.enabled=true --set tracing.enabled=true --set kiali.enabled=true + +Write-Host "Setting Up Gateway" +kubectl delete gateway istio-autogenerated-k8s-ingress -n istio-system +kubectl apply -f ./istio/gateway.yml + +if ($useLocalk8s -eq $true) { + $dns="localhost" + $externalDns="localhost" +} +else { + Write-Host "Resolving DNS to Gateway public IP" -ForegroundColor Green + $ipaddress = $(kubectl get service istio-ingressgateway -n istio-system)[1] | %{ $_.Split(' ')[9];} + $query = "[?ipAddress!=null]|[?contains([ipAddress], '$ipaddress')].[id]" + $resid = az network public-ip list --query $query --output tsv + $jsonresponse = az network public-ip update --ids $resid --dns-name $dnsname + $externalDns = ($jsonresponse | ConvertFrom-Json).dnsSettings.fqdn + Write-Host "$externalDns is pointing to Cluster public ip $ipaddress" +} + +$useCustomRegistry=$false +if (-not [string]::IsNullOrEmpty($registry)) { + $useCustomRegistry=$true + if ([string]::IsNullOrEmpty($dockerUser) -or [string]::IsNullOrEmpty($dockerPassword)) { + Write-Host "Error: Must use -dockerUser AND -dockerPassword if specifying custom registry" -ForegroundColor Red + exit 1 + } +} +Write-Host "Begin eShopOnContainers installation using Helm" -ForegroundColor Green + +$infras = ("sql-data", "nosql-data", "rabbitmq", "keystore-data", "basket-data") +$charts = ("eshop-common", "apigwmm", "apigwms", "apigwwm", "apigwws", "basket-api","catalog-api", "identity-api", "locations-api", "marketing-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web") + +if ($deployInfrastructure) { + foreach ($infra in $infras) { + Write-Host "Installing infrastructure: $infra" -ForegroundColor Green + helm install --values app.yaml --values inf.yaml --set app.name=$appName --set inf.k8s.dns=$externalDns --name="$appName-$infra" $infra + } +} + +foreach ($chart in $charts) { + Write-Host "Installing: $chart" -ForegroundColor Green + if ($useCustomRegistry) { + helm install --set inf.registry.server=$registry --set inf.registry.login=$dockerUser --set inf.registry.pwd=$dockerPassword --set inf.registry.secretName=eshop-docker-scret --values app.yaml --values inf.yaml --values $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set image.tag=$imageTag --set image.pullPolicy=Always --name="$appName-$chart" $chart + } + else { + if ($chart -ne "eshop-common") { # eshop-common is ignored when no secret must be deployed + helm install --values app.yaml --values inf.yaml --set app.name=$appName --set inf.k8s.dns=$externalDns --set image.tag=$imageTag --set image.pullPolicy=Always --name="$appName-$chart" $chart + } + } +} + +Write-Host "helm charts installed." -ForegroundColor Green +Write-Host "Appling Virtual Services for routing." -ForegroundColor Green +kubectl apply -f ./istio/virtualservices.yml + +Remove-Item istio-$ISTIO_VERSION -Recurse -ErrorAction Ignore +Remove-Item istio-$ISTIO_VERSION.zip -Recurse -ErrorAction Ignore + + + + + + + diff --git a/k8s/helm/deploy-all.ps1 b/k8s/helm/deploy-all.ps1 index 1819c9a67..42ba3ab27 100644 --- a/k8s/helm/deploy-all.ps1 +++ b/k8s/helm/deploy-all.ps1 @@ -82,8 +82,4 @@ foreach ($chart in $charts) { } } -Write-Host "helm charts installed." -ForegroundColor Green - - - - +Write-Host "helm charts installed." -ForegroundColor Green \ No newline at end of file diff --git a/k8s/helm/istio/doc.md b/k8s/helm/istio/doc.md new file mode 100644 index 000000000..b8c0a0257 --- /dev/null +++ b/k8s/helm/istio/doc.md @@ -0,0 +1,325 @@ +# Using Helm Charts to deploy eShopOnContainers to AKS with ISTIO + +It is possible to deploy eShopOnContainers on a AKS using [Helm](https://helm.sh/) instead of custom scripts (that will be deprecated soon). + +## Create Kubernetes cluster in AKS +You can create the AKS cluster by using two ways: + +- A. Use Azure CLI: Follow a procedure suing [Azure CLI like here](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough), but make sure you **enable RBAC** with `--enable-rbac` in `az aks create` command. + +- B. Use Azure's portal + +The following steps are using the Azure portal to create the AKS cluster: + +- Start the process by providing the general data, like in the following screenshot: + +![image](https://user-images.githubusercontent.com/1712635/45787360-c59ecd80-bc29-11e8-9565-c989ad6ad57b.png) + +- Then, very important, in the next step, enable RBAC: + +![image](https://user-images.githubusercontent.com/1712635/45780917-8bc2cc80-bc13-11e8-87ac-2942b3c7496d.png) + + You can use **basic network** settings since for a test you don't need integration into any existing VNET. + +![image](https://user-images.githubusercontent.com/1712635/45780991-b745b700-bc13-11e8-926b-afac57229d0a.png) + +- You can also enable monitoring: + +![image](https://user-images.githubusercontent.com/1712635/45781148-1277a980-bc14-11e8-8614-f7a239731bec.png) + +- Finally, create the cluster. It'll take a few minutes for it to be ready. + +### Configure RBAC security for K8s dashboard service-account + +In order NOT to get errors in the Kubernetes dashboard, you'll need to set the following service-account steps. + +Here you can see the errors you might see: +![image](https://user-images.githubusercontent.com/1712635/45784384-5622e100-bc1d-11e8-8d33-e22fd955150a.png) + +Now, just run the Azure CLI command to browse the Kubernetes Dashboard: + +`az aks browse --resource-group pro-eshop-aks-helm-linux-resgrp --name pro-eshop-aks-helm-linux` + +![image](https://user-images.githubusercontent.com/1712635/45786406-2d9ee500-bc25-11e8-83e9-bdfc302e80f1.png) + + +## Additional pre-requisites + +In addition to having an AKS cluster created in Azure and having kubectl and Azure CLI installed in your local machine and configured to use your Azure subscription, you also need the following pre-requisites: + +### Install Helm + +You need to have helm installed on your machine, and Tiller must be installed on the AKS. Follow these instructions on how to ['Install applications with Helm in Azure Kubernetes Service (AKS)'](https://docs.microsoft.com/en-us/azure/aks/kubernetes-helm) to setup Helm and Tiller for AKS. + +**Note**: If your ASK cluster is not RBAC-enabled (default option in portal) you may receive following error when running a helm command: + +``` +Error: Get http://localhost:8080/api/v1/namespaces/kube-system/configmaps?labelSelector=OWNER%!D(MISSING)TILLER: dial tcp [::1]:8080: connect: connection refused +``` + +If so, type: + +``` +kubectl --namespace=kube-system edit deployment/tiller-deploy +``` + +Your default text editor will popup with the YAML definition of the tiller deploy. Search for: + +``` +automountServiceAccountToken: false +``` + +And change it to: + +``` +automountServiceAccountToken: true +``` + +Save the file and close the editor. This should reapply the deployment in the cluster. Now Helm commands should work. + +## Install eShopOnContainers with Istio using Helm + +All steps need to be performed on `/k8s/helm` folder. The easiest way is to use the `deploy-all-istio.ps1` script from a Powershell window: + +``` +.\deploy-all-istio.ps1 -dnsname eshoptestistio -externalDns aks -aksName eshoptest -aksRg eshoptest -imageTag dev +``` + +This will install all the [eShopOnContainers public images](https://hub.docker.com/u/eshop/) with tag `dev` on the AKS named `eshoptest` in the resource group `eshoptest` and with the dns url: http://**eshoptestistio**.westus.cloudapp.azure.com/ . By default all infrastructure (sql, mongo, rabbit and redis) is installed also in the cluster. + +Once the script is run, you should see following output when using `kubectl get deployment`: + +``` +NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE +eshop-apigwmm 1 1 1 1 4d +eshop-apigwms 1 1 1 1 4d +eshop-apigwwm 1 1 1 1 4d +eshop-apigwws 1 1 1 1 4d +eshop-basket-api 1 1 1 1 4d +eshop-basket-data 1 1 1 1 4d +eshop-catalog-api 1 1 1 1 4d +eshop-identity-api 1 1 1 1 4d +eshop-keystore-data 1 1 1 1 4d +eshop-locations-api 1 1 1 1 4d +eshop-marketing-api 1 1 1 1 4d +eshop-mobileshoppingagg 1 1 1 1 4d +eshop-nosql-data 1 1 1 1 4d +eshop-ordering-api 1 1 1 1 4d +eshop-ordering-backgroundtasks 1 1 1 1 4d +eshop-ordering-signalrhub 1 1 1 1 4d +eshop-payment-api 1 1 1 1 4d +eshop-rabbitmq 1 1 1 1 4d +eshop-sql-data 1 1 1 1 4d +eshop-webmvc 1 1 1 1 4d +eshop-webshoppingagg 1 1 1 1 4d +eshop-webspa 1 1 1 1 4d +eshop-webstatus 1 1 1 1 4d +``` + +Every public service is exposed through the istio ingress gateway. +Yo can see the ingress gateway public ip doing `kubectl get services -n istio-system` +``` +grafana ClusterIP 10.0.204.87 3000/TCP 1h +istio-citadel ClusterIP 10.0.23.86 8060/TCP,9093/TCP 1h +istio-egressgateway ClusterIP 10.0.136.169 80/TCP,443/TCP 1h +istio-galley ClusterIP 10.0.113.51 443/TCP,9093/TCP 1h +istio-ingressgateway LoadBalancer 10.0.76.80 40.118.189.161 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:31276/TCP,8060:30519/TCP,853:31698/TCP,15030:31453/TCP,15031:32362/TCP 1h +istio-pilot ClusterIP 10.0.164.253 15010/TCP,15011/TCP,8080/TCP,9093/TCP 1h +istio-policy ClusterIP 10.0.170.49 9091/TCP,15004/TCP,9093/TCP 1h +istio-sidecar-injector ClusterIP 10.0.251.12 443/TCP 1h +istio-telemetry ClusterIP 10.0.195.112 9091/TCP,15004/TCP,9093/TCP,42422/TCP 1h +jaeger-agent ClusterIP None 5775/UDP,6831/UDP,6832/UDP 1h +jaeger-collector ClusterIP 10.0.123.98 14267/TCP,14268/TCP 1h +jaeger-query ClusterIP 10.0.244.146 16686/TCP 1h +kiali ClusterIP 10.0.182.12 20001/TCP 1h +prometheus ClusterIP 10.0.136.223 9090/TCP 1h +tracing ClusterIP 10.0.57.236 80/TCP 1h +zipkin ClusterIP 10.0.30.57 9411/TCP 1h +``` + +You can view the MVC client at http://[dns]/ + +## Customizing the deployment + +### Using your own images + +To use your own images instead of the public ones, you have to pass following additional parameters to the `deploy-all-istio.ps1` script: + +* `registry`: Login server for the Docker registry +* `dockerUser`: User login for the Docker registry +* `dockerPassword`: User password for the Docker registry + +This will deploy a secret on the cluster to connect to the specified server, and all image names deployed will be prepended with `registry/` value. + +### Not deploying infrastructure containers + +If you want to use external resources, use `-deployInfrastructure $false` to not deploy infrastructure containers. However **you still have to manually update the scripts to provide your own configuration** (see next section). + +### Providing your own configuration + +The file `inf.yaml` contains the description of the infrastructure used. File is docummented so take a look on it to understand all of its entries. If using external resources you need to edit this file according to your needs. You'll need to edit: + +* `inf.sql.host` with the host name of the SQL Server +* `inf.sql.common` entries to provide your SQL user, password. `Pid` is not used when using external resources (it is used to set specific product id for the SQL Server container). +* `inf.sql.catalog`, `inf.sql.ordering`, `inf.sql.identity`: To provide the database names for catalog, ordering and identity services +* `mongo.host`: With the host name of the Mongo DB +* `mongo.locations`, `mongo.marketing` with the database names for locations and marketing services +* `redis.basket.constr` with the connection string to Redis for Basket Service. Note that `redis.basket.svc` is not used when using external services +* `redis.keystore.constr` with the connection string to Redis for Keystore Service. Note that `redis.keystore.svc` is not used when using external services +* `eventbus.constr` with the connection string to Azure Service Bus and `eventbus.useAzure` to `true` to use Azure service bus. Note that `eventbus.svc` is not used when using external services + +### Using Azure storage for Catalog Photos + +Using Azure storage for catalog (and marketing) photos is not directly supported, but you can accomplish it by editing the file `k8s/helm/catalog-api/templates/configmap.yaml`. Search for lines: + +``` +catalog__PicBaseUrl: http://{{ $webshoppingapigw }}/api/v1/c/catalog/items/[0]/pic/ +``` + +And replace it for: + +``` +catalog__PicBaseUrl: http:/// +``` + +In the same way, to use Azure storage for the marketing service, have to edit the file `k8s/helm/marketing-api/templates/configmap.yaml` and replacing the line: + +``` +marketing__PicBaseUrl: http://{{ $webshoppingapigw }}/api/v1/c/catalog/items/[0]/pic/ +``` + +by: + +``` +marketing__PicBaseUrl: http:/// +``` + +# Using Helm Charts to deploy eShopOnContainers to a local Kubernetes in Windows with 'Docker for Windows' + +## Additional pre-requisites + +In addition to having Docker for Windows/Mac with Kubernetes enabled and having kubectl ayou also need the following pre-requisites: + +### Install Helm + +You need to have helm installed on your machine, and Tiller must be installed on the local Docker Kubernetes cluster. Once you have [Helm downloaded](https://helm.sh/) and installed on your machine you must: + +1. Create the tiller service account, by running `kubectl apply -f helm-rbac.yaml` from `/k8s` folder +2. Install tiller and configure it to use the tiller service account by typing `helm init --service-account tiller` + +## Install eShopOnContainers with Istio using Helm + +All steps need to be performed on `/k8s/helm` folder. The easiest way is to use the `deploy-all-istio.ps1` script from a Powershell window: + +``` +.\deploy-all-istio.ps1 -imageTag dev -useLocalk8s $true +``` + +The parameter `useLocalk8s` to $true, forces the script to use `localhost` as the DNS for all Helm charts. + +This will install all the [eShopOnContainers public images](https://hub.docker.com/u/eshop/) with tag `dev` on the Docker local Kubernetes cluster. By default all infrastructure (sql, mongo, rabbit and redis) is installed also in the cluster. + +Once the script is run, you should see following output when using `kubectl get deployment`: + +``` +NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE +eshop-apigwmm 1 1 1 1 2h +eshop-apigwms 1 1 1 1 2h +eshop-apigwwm 1 1 1 1 2h +eshop-apigwws 1 1 1 1 2h +eshop-basket-api 1 1 1 1 2h +eshop-basket-data 1 1 1 1 2h +eshop-catalog-api 1 1 1 1 2h +eshop-identity-api 1 1 1 1 2h +eshop-keystore-data 1 1 1 1 2h +eshop-locations-api 1 1 1 1 2h +eshop-marketing-api 1 1 1 1 2h +eshop-mobileshoppingagg 1 1 1 1 2h +eshop-nosql-data 1 1 1 1 2h +eshop-ordering-api 1 1 1 1 2h +eshop-ordering-backgroundtasks 1 1 1 1 2h +eshop-ordering-signalrhub 1 1 1 1 2h +eshop-payment-api 1 1 1 1 2h +eshop-rabbitmq 1 1 1 1 2h +eshop-sql-data 1 1 1 1 2h +eshop-webmvc 1 1 1 1 2h +eshop-webshoppingagg 1 1 1 1 2h +eshop-webspa 1 1 1 1 2h +eshop-webstatus 1 1 1 1 2h +``` + +Note that istio ingress gateway is bound to DNS localhost and the host is also "localhost". So, you can access the webspa by typing `http://localhost` and the MVC by typing `http://localhost/` + +As this is the Docker local K8s cluster, you can see also the containers running on your machine. If you type `docker ps` you'll see all them: + +``` +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +fec1e3499416 a3f21ec4bd11 "/entrypoint.sh /ngi…" 9 minutes ago Up 9 minutes k8s_nginx-ingress-controller_nginx-ingress-controller-f88c75bc6-5xs2n_ingress-nginx_f1cc7094-e68f-11e8-b4b6-00155d016146_0 +76485867f032 eshop/payment.api "dotnet Payment.API.…" 2 hours ago Up 2 hours k8s_payment-api_eshop-payment-api-75d5f9bdf6-6zx2v_default_4a3cdab4-e67f-11e8-b4b6-00155d016146_1 +c2c4640ed610 eshop/marketing.api "dotnet Marketing.AP…" 2 hours ago Up 2 hours k8s_marketing-api_eshop-marketing-api-6b8c5989fd-jpxqv_default_45780626-e67f-11e8-b4b6-00155d016146_1 +85301d538574 eshop/ordering.signalrhub "dotnet Ordering.Sig…" 2 hours ago Up 2 hours k8s_ordering-signalrhub_eshop-ordering-signalrhub-58cf5ff6-cnlm8_default_4932c344-e67f-11e8-b4b6-00155d016146_1 +7a408a98000e eshop/ordering.backgroundtasks "dotnet Ordering.Bac…" 2 hours ago Up 2 hours k8s_ordering-backgroundtasks_eshop-ordering-backgroundtasks-cc8f6d4d8-ztfk7_default_47f9cf10-e67f-11e8-b4b6-00155d016146_1 +12c64b3a13e0 eshop/basket.api "dotnet Basket.API.d…" 2 hours ago Up 2 hours k8s_basket-api_eshop-basket-api-658546684d-6hlvd_default_4262d022-e67f-11e8-b4b6-00155d016146_1 +133fccfeeff3 eshop/webstatus "dotnet WebStatus.dll" 2 hours ago Up 2 hours k8s_webstatus_eshop-webstatus-7f46479dc4-bqnq7_default_4dc13eb2-e67f-11e8-b4b6-00155d016146_0 +00c6e4c52135 eshop/webspa "dotnet WebSPA.dll" 2 hours ago Up 2 hours k8s_webspa_eshop-webspa-64cb8df9cb-dcbwg_default_4cd47376-e67f-11e8-b4b6-00155d016146_0 +d4507f1f6b1a eshop/webshoppingagg "dotnet Web.Shopping…" 2 hours ago Up 2 hours k8s_webshoppingagg_eshop-webshoppingagg-cc94fc86-sxd2v_default_4be6cdb9-e67f-11e8-b4b6-00155d016146_0 +9178e26703da eshop/webmvc "dotnet WebMVC.dll" 2 hours ago Up 2 hours k8s_webmvc_eshop-webmvc-985779684-4br5z_default_4addd4d6-e67f-11e8-b4b6-00155d016146_0 +1088c281c710 eshop/ordering.api "dotnet Ordering.API…" 2 hours ago Up 2 hours k8s_ordering-api_eshop-ordering-api-fb8c548cb-k68x9_default_4740958a-e67f-11e8-b4b6-00155d016146_0 +12424156d5c9 eshop/mobileshoppingagg "dotnet Mobile.Shopp…" 2 hours ago Up 2 hours k8s_mobileshoppingagg_eshop-mobileshoppingagg-b54645d7b-rlrgh_default_46c00017-e67f-11e8-b4b6-00155d016146_0 +65463ffd437d eshop/locations.api "dotnet Locations.AP…" 2 hours ago Up 2 hours k8s_locations-api_eshop-locations-api-577fc94696-dfhq8_default_44929c4b-e67f-11e8-b4b6-00155d016146_0 +5b3431873763 eshop/identity.api "dotnet Identity.API…" 2 hours ago Up 2 hours k8s_identity-api_eshop-identity-api-85d9b79f4-s5ks7_default_43d6eb7c-e67f-11e8-b4b6-00155d016146_0 +7c8e77252459 eshop/catalog.api "dotnet Catalog.API.…" 2 hours ago Up 2 hours k8s_catalog-api_eshop-catalog-api-59fd444fb-ztvhz_default_4356705a-e67f-11e8-b4b6-00155d016146_0 +94d95d0d3653 eshop/ocelotapigw "dotnet OcelotApiGw.…" 2 hours ago Up 2 hours k8s_apigwws_eshop-apigwws-65474b979d-n99jw_default_41395473-e67f-11e8-b4b6-00155d016146_0 +bc4bbce71d5f eshop/ocelotapigw "dotnet OcelotApiGw.…" 2 hours ago Up 2 hours k8s_apigwwm_eshop-apigwwm-857c549dd8-8w5gv_default_4098d770-e67f-11e8-b4b6-00155d016146_0 +840aabcceaa9 eshop/ocelotapigw "dotnet OcelotApiGw.…" 2 hours ago Up 2 hours k8s_apigwms_eshop-apigwms-5b94dfb54b-dnmr9_default_401fc611-e67f-11e8-b4b6-00155d016146_0 +aabed7646f5b eshop/ocelotapigw "dotnet OcelotApiGw.…" 2 hours ago Up 2 hours k8s_apigwmm_eshop-apigwmm-85f96cbdb4-dhfwr_default_3ed7967a-e67f-11e8-b4b6-00155d016146_0 +49c5700def5a f06a5773f01e "docker-entrypoint.s…" 2 hours ago Up 2 hours k8s_basket-data_eshop-basket-data-66fbc788cc-csnlw_default_3e0c45fe-e67f-11e8-b4b6-00155d016146_0 +a5db4c521807 f06a5773f01e "docker-entrypoint.s…" 2 hours ago Up 2 hours k8s_keystore-data_eshop-keystore-data-5c9c85cb99-8k56s_default_3ce1a273-e67f-11e8-b4b6-00155d016146_0 +aae88fd2d810 d69a5113ceae "docker-entrypoint.s…" 2 hours ago Up 2 hours k8s_rabbitmq_eshop-rabbitmq-6b68647bc4-gr565_default_3c37ee6a-e67f-11e8-b4b6-00155d016146_0 +65d49ca9589d bbed8d0e01c1 "docker-entrypoint.s…" 2 hours ago Up 2 hours k8s_nosql-data_eshop-nosql-data-579c9d89f8-mtt95_default_3b9c1f89-e67f-11e8-b4b6-00155d016146_0 +090e0dde2ec4 bbe2822dfe38 "/opt/mssql/bin/sqls…" 2 hours ago Up 2 hours k8s_sql-data_eshop-sql-data-5c4fdcccf4-bscdb_default_3afd29b8-e67f-11e8-b4b6-00155d016146_0 +``` + +## Known issues + +Login from the webmvc results in following error: HttpRequestException: Response status code does not indicate success: 404 (Not Found). + +The reason is because MVC needs to access the Identity Server from both outside the container (browser) and inside the container (C# code). Thus, the configuration uses always the *external url* of the Identity Server, which in this case is just `http://localhost/identity-api`. But this external url is incorrect when used from C# code, and the web mvc can't access the identity api. This is the only case when this issue happens (and is the reason why we use 10.0.75.1 for local address in web mvc in local development mode) + +Solving this requires some manual steps: + +Update the configmap of Web MVC by typing (**line breaks are mandatory**) and your cluster dns name has to be the same of your environment: + +``` +kubectl patch cm cfg-eshop-webmvc --type strategic --patch @' +data: + urls__IdentityUrl: http://**eshoptest**.westus.cloudapp.azure.com/identity + urls__mvc: http://**eshoptest**.westus.cloudapp.azure.com/webmvc +'@ +``` + +Update the configmap of Identity API by typing (**line breaks are mandatory**): + +``` +kubectl patch cm cfg-eshop-identity-api --type strategic --patch @' +data: + mvc_e: http://**eshoptest**.westus.cloudapp.azure.com/webmvc +'@ +``` + +Restart the SQL Server pod to ensure the database is recreated again: + +``` +kubectl delete pod --selector app=sql-data +``` + +Wait until SQL Server pod is ready to accept connections and then restart all other pods: + +``` +kubectl delete pod --selector="app!=sql-data" +``` + +**Note:** Pods are deleted to ensure the databases are recreated again, as identity api stores its client names and urls in the database. + +Now, you can access the MVC app using: `http://**eshoptest**.westus.cloudapp.azure.com/`. + diff --git a/k8s/helm/istio/gateway.yml b/k8s/helm/istio/gateway.yml new file mode 100644 index 000000000..fbc61dadd --- /dev/null +++ b/k8s/helm/istio/gateway.yml @@ -0,0 +1,15 @@ +apiVersion: networking.istio.io/v1alpha3 +kind: Gateway +metadata: + name: istio-ingressgateway + #namespace: istio-system +spec: + selector: + istio: ingressgateway # use Istio default gateway implementation + servers: + - port: + number: 80 + name: http + protocol: HTTP + hosts: + - "*" \ No newline at end of file diff --git a/k8s/helm/istio/virtualservices.yml b/k8s/helm/istio/virtualservices.yml new file mode 100644 index 000000000..e01f4678f --- /dev/null +++ b/k8s/helm/istio/virtualservices.yml @@ -0,0 +1,59 @@ +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: webmvcvs + namespace: default +spec: + hosts: + - "*" + gateways: + - istio-ingressgateway + http: + - match: + - uri: + prefix: / + route: + - destination: + port: + number: 80 + host: webmvc +--- +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: webshoppingapigwvs + namespace: default +spec: + hosts: + - "*" + gateways: + - istio-ingressgateway + http: + - match: + - uri: + prefix: /webshoppingapigw + route: + - destination: + port: + number: 80 + host: webshoppingapigw +--- +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: identityvs + namespace: default +spec: + hosts: + - "*" + gateways: + - istio-ingressgateway + http: + - match: + - uri: + prefix: /identity + route: + - destination: + port: + number: 80 + host: identity \ No newline at end of file diff --git a/k8s/nginx-ingress/mandatory-istio.yaml b/k8s/nginx-ingress/mandatory-istio.yaml new file mode 100644 index 000000000..56b1cc3b5 --- /dev/null +++ b/k8s/nginx-ingress/mandatory-istio.yaml @@ -0,0 +1,238 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ingress-nginx + +--- + +kind: ConfigMap +apiVersion: v1 +metadata: + name: nginx-configuration + namespace: ingress-nginx + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: nginx-ingress-serviceaccount + namespace: ingress-nginx + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: nginx-ingress-clusterrole + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - "extensions" + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "extensions" + resources: + - ingresses/status + verbs: + - update + +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role +metadata: + name: nginx-ingress-role + namespace: ingress-nginx + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx +rules: + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + resourceNames: + # Defaults to "-" + # Here: "-" + # This has to be adapted if you change either parameter + # when launching the nginx-ingress-controller. + - "ingress-controller-leader-nginx" + verbs: + - get + - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - apiGroups: + - "" + resources: + - endpoints + verbs: + - get + +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: nginx-ingress-role-nisa-binding + namespace: ingress-nginx + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: nginx-ingress-role +subjects: + - kind: ServiceAccount + name: nginx-ingress-serviceaccount + namespace: ingress-nginx + +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: nginx-ingress-clusterrole-nisa-binding + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: nginx-ingress-clusterrole +subjects: + - kind: ServiceAccount + name: nginx-ingress-serviceaccount + namespace: ingress-nginx + +--- + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: nginx-ingress-controller + namespace: ingress-nginx + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + template: + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + annotations: + prometheus.io/port: "10254" + prometheus.io/scrape: "true" + spec: + serviceAccountName: nginx-ingress-serviceaccount + containers: + - name: nginx-ingress-controller + image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.20.0 + args: + - /nginx-ingress-controller + - --configmap=$(POD_NAMESPACE)/nginx-configuration + - --publish-service=$(POD_NAMESPACE)/ingress-nginx + - --annotations-prefix=nginx.ingress.kubernetes.io + securityContext: + capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE + # www-data -> 33 + runAsUser: 33 + 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/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs b/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs index e789081f3..ea1aca61e 100644 --- a/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs +++ b/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs @@ -115,10 +115,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus private void RaiseOnEventRemoved(string eventName) { var handler = OnEventRemoved; - if (handler != null) - { - OnEventRemoved(this, eventName); - } + handler?.Invoke(this, eventName); } diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj index f7a2943ff..d5fc0a301 100644 --- a/src/Services/Basket/Basket.API/Basket.API.csproj +++ b/src/Services/Basket/Basket.API/Basket.API.csproj @@ -33,6 +33,7 @@ + diff --git a/src/Services/Basket/Basket.API/Program.cs b/src/Services/Basket/Basket.API/Program.cs index 893a52400..40cc0eebc 100644 --- a/src/Services/Basket/Basket.API/Program.cs +++ b/src/Services/Basket/Basket.API/Program.cs @@ -57,13 +57,14 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index 33f1c299f..fc8fc544a 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -1,6 +1,7 @@ { "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj index e5c3945c9..6150179ee 100644 --- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj +++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj @@ -53,6 +53,7 @@ + diff --git a/src/Services/Catalog/Catalog.API/Program.cs b/src/Services/Catalog/Catalog.API/Program.cs index c75b56c39..39b071c46 100644 --- a/src/Services/Catalog/Catalog.API/Program.cs +++ b/src/Services/Catalog/Catalog.API/Program.cs @@ -71,13 +71,14 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json index 8f2cde4db..3aaed933a 100644 --- a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json +++ b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json @@ -16,7 +16,8 @@ "ConnectionString": "server=localhost,5433;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word", "ASPNETCORE_ENVIRONMENT": "Development", "EventBusConnection": "localhost", - "Serilog:SeqServerUrl": "http://locahost:5340" + "Serilog:SeqServerUrl": "http://locahost:5340", + "Serilog:LogstashgUrl":"http://locahost:8080", } }, "Microsoft.eShopOnContainers.Services.Catalog.API": { diff --git a/src/Services/Catalog/Catalog.API/appsettings.json b/src/Services/Catalog/Catalog.API/appsettings.json index b26f63bff..cc7b1b1fb 100644 --- a/src/Services/Catalog/Catalog.API/appsettings.json +++ b/src/Services/Catalog/Catalog.API/appsettings.json @@ -4,6 +4,7 @@ "UseCustomizationData": false, "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj index e8a2c7bd8..728843f71 100644 --- a/src/Services/Identity/Identity.API/Identity.API.csproj +++ b/src/Services/Identity/Identity.API/Identity.API.csproj @@ -34,6 +34,7 @@ + diff --git a/src/Services/Identity/Identity.API/Program.cs b/src/Services/Identity/Identity.API/Program.cs index 8204a1ebf..784f63a1e 100644 --- a/src/Services/Identity/Identity.API/Program.cs +++ b/src/Services/Identity/Identity.API/Program.cs @@ -76,13 +76,14 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://localhost:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Identity/Identity.API/appsettings.json b/src/Services/Identity/Identity.API/appsettings.json index 74d8e826c..2f05c2d1c 100644 --- a/src/Services/Identity/Identity.API/appsettings.json +++ b/src/Services/Identity/Identity.API/appsettings.json @@ -7,6 +7,7 @@ "UseCustomizationData": false, "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj index 455516a91..6c33656e1 100644 --- a/src/Services/Location/Locations.API/Locations.API.csproj +++ b/src/Services/Location/Locations.API/Locations.API.csproj @@ -29,6 +29,7 @@ + diff --git a/src/Services/Location/Locations.API/Program.cs b/src/Services/Location/Locations.API/Program.cs index c13df985f..acadf4a39 100644 --- a/src/Services/Location/Locations.API/Program.cs +++ b/src/Services/Location/Locations.API/Program.cs @@ -54,13 +54,14 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Location/Locations.API/appsettings.json b/src/Services/Location/Locations.API/appsettings.json index 43fe53873..7fbe98b3e 100644 --- a/src/Services/Location/Locations.API/appsettings.json +++ b/src/Services/Location/Locations.API/appsettings.json @@ -4,6 +4,7 @@ "IdentityUrl": "http://localhost:5105", "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Marketing/Marketing.API/Marketing.API.csproj b/src/Services/Marketing/Marketing.API/Marketing.API.csproj index 201f0c519..c47989611 100644 --- a/src/Services/Marketing/Marketing.API/Marketing.API.csproj +++ b/src/Services/Marketing/Marketing.API/Marketing.API.csproj @@ -45,6 +45,7 @@ + diff --git a/src/Services/Marketing/Marketing.API/Program.cs b/src/Services/Marketing/Marketing.API/Program.cs index ae26c9786..4d07e7e0f 100644 --- a/src/Services/Marketing/Marketing.API/Program.cs +++ b/src/Services/Marketing/Marketing.API/Program.cs @@ -66,13 +66,14 @@ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Marketing/Marketing.API/appsettings.json b/src/Services/Marketing/Marketing.API/appsettings.json index c16978dce..d4a58cc8e 100644 --- a/src/Services/Marketing/Marketing.API/appsettings.json +++ b/src/Services/Marketing/Marketing.API/appsettings.json @@ -1,6 +1,7 @@ { "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Ordering/Ordering.API/Ordering.API.csproj b/src/Services/Ordering/Ordering.API/Ordering.API.csproj index 77c173523..e2b25c2a7 100644 --- a/src/Services/Ordering/Ordering.API/Ordering.API.csproj +++ b/src/Services/Ordering/Ordering.API/Ordering.API.csproj @@ -52,6 +52,7 @@ + diff --git a/src/Services/Ordering/Ordering.API/Program.cs b/src/Services/Ordering/Ordering.API/Program.cs index 8fc18c8bb..a0b7dc40e 100644 --- a/src/Services/Ordering/Ordering.API/Program.cs +++ b/src/Services/Ordering/Ordering.API/Program.cs @@ -68,16 +68,17 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API .UseSerilog() .Build(); - private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) + private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Ordering/Ordering.API/appsettings.json b/src/Services/Ordering/Ordering.API/appsettings.json index 64b24a354..f74c312b1 100644 --- a/src/Services/Ordering/Ordering.API/appsettings.json +++ b/src/Services/Ordering/Ordering.API/appsettings.json @@ -4,6 +4,7 @@ "UseCustomizationData": false, "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj index 5f85b74a4..63df5da80 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj @@ -28,6 +28,7 @@ + diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs index 8f8cf41e1..7a429742e 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs @@ -51,13 +51,14 @@ namespace Ordering.BackgroundTasks private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json b/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json index 3697c53a5..51250be9d 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json +++ b/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json @@ -2,6 +2,7 @@ "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;", "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/CardType.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/CardType.cs index d6a92892c..3053cb678 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/CardType.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/CardType.cs @@ -9,31 +9,13 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B public class CardType : Enumeration { - public static CardType Amex = new AmexCardType(); - public static CardType Visa = new VisaCardType(); - public static CardType MasterCard = new MasterCardType(); + public static CardType Amex = new CardType(1, "Amex"); + public static CardType Visa = new CardType(2, "Visa"); + public static CardType MasterCard = new CardType(3, "MasterCard"); public CardType(int id, string name) : base(id, name) { } - - private class AmexCardType : CardType - { - public AmexCardType() : base(1, "Amex") - { } - } - - private class VisaCardType : CardType - { - public VisaCardType() : base(2, "Visa") - { } - } - - private class MasterCardType : CardType - { - public MasterCardType() : base(3, "MasterCard") - { } - } } } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs index 1716cc32d..19e62311a 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs @@ -16,10 +16,6 @@ public static OrderStatus Shipped = new OrderStatus(5, nameof(Shipped).ToLowerInvariant()); public static OrderStatus Cancelled = new OrderStatus(6, nameof(Cancelled).ToLowerInvariant()); - protected OrderStatus() - { - } - public OrderStatus(int id, string name) : base(id, name) { diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs index a1e4c4c7e..d3e415df2 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs @@ -11,9 +11,6 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork public int Id { get; private set; } - protected Enumeration() - { } - protected Enumeration(int id, string name) { Id = id; diff --git a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj index fefc7e94d..00d70cbe6 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj +++ b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj @@ -30,6 +30,7 @@ + diff --git a/src/Services/Ordering/Ordering.SignalrHub/Program.cs b/src/Services/Ordering/Ordering.SignalrHub/Program.cs index fdb3f5f3a..76f131caa 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Program.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/Program.cs @@ -54,13 +54,14 @@ namespace Ordering.SignalrHub private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Ordering/Ordering.SignalrHub/appsettings.json b/src/Services/Ordering/Ordering.SignalrHub/appsettings.json index bd752de48..e43c354a3 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/appsettings.json +++ b/src/Services/Ordering/Ordering.SignalrHub/appsettings.json @@ -2,6 +2,7 @@ "IdentityUrl": "http://localhost:5105", "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Services/Ordering/Ordering.UnitTests/Application/OrderControllerTest.cs b/src/Services/Ordering/Ordering.UnitTests/Application/OrderControllerTest.cs deleted file mode 100644 index a60ce3bb3..000000000 --- a/src/Services/Ordering/Ordering.UnitTests/Application/OrderControllerTest.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Controllers; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Moq; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Xunit; -using BasketModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Basket; - -namespace UnitTest.Ordering.Application -{ - public class OrderControllerTest - { - private readonly Mock _orderServiceMock; - private readonly Mock _basketServiceMock; - private readonly Mock> _identityParserMock; - private readonly Mock _contextMock; - - public OrderControllerTest() - { - _orderServiceMock = new Mock(); - _basketServiceMock = new Mock(); - _identityParserMock = new Mock>(); - _contextMock = new Mock(); - } - - [Fact] - public async Task Get_order_list_success() - { - //Arrange - var expectedTotalResults = 1; - var fakeOrder = GetFakeOrder(); - - _orderServiceMock.Setup(x => x.GetMyOrders(It.IsAny())) - .Returns(Task.FromResult(new List() { fakeOrder })); - - //Act - var orderController = new OrderController(_orderServiceMock.Object, _basketServiceMock.Object, _identityParserMock.Object); - orderController.ControllerContext.HttpContext = _contextMock.Object; - var actionResult = await orderController.Index(fakeOrder); - - //Assert - var viewResult = Assert.IsType(actionResult); - var model = Assert.IsAssignableFrom>(viewResult.ViewData.Model); - Assert.Equal(model.Count, expectedTotalResults); - } - - [Fact] - public async Task Get_order_detail_success() - { - //Arrange - var fakeOrderId = "12"; - var fakeOrder = GetFakeOrder(); - - _orderServiceMock.Setup(x => x.GetOrder(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(fakeOrder)); - - //Act - var orderController = new OrderController(_orderServiceMock.Object, _basketServiceMock.Object, _identityParserMock.Object); - orderController.ControllerContext.HttpContext = _contextMock.Object; - var actionResult = await orderController.Detail(fakeOrderId); - - //Assert - var viewResult = Assert.IsType(actionResult); - Assert.IsAssignableFrom(viewResult.ViewData.Model); - } - - - - private Order GetFakeOrder() - { - return new Order() - { - OrderNumber = "1", - CardNumber = "12", - CardSecurityNumber = "1212", - Status = "Pending", - RequestId = Guid.NewGuid(), - CardExpiration = DateTime.Now.AddYears(1), - }; - } - } -} diff --git a/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj b/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj index 6a3d3c284..e94aae4f1 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj +++ b/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj @@ -19,7 +19,6 @@ - diff --git a/src/Services/Payment/Payment.API/Payment.API.csproj b/src/Services/Payment/Payment.API/Payment.API.csproj index 14aaa598c..efce8b8ab 100644 --- a/src/Services/Payment/Payment.API/Payment.API.csproj +++ b/src/Services/Payment/Payment.API/Payment.API.csproj @@ -24,6 +24,7 @@ + diff --git a/src/Services/Payment/Payment.API/Program.cs b/src/Services/Payment/Payment.API/Program.cs index 9b0aded5c..b03bee3da 100644 --- a/src/Services/Payment/Payment.API/Program.cs +++ b/src/Services/Payment/Payment.API/Program.cs @@ -54,13 +54,14 @@ namespace Payment.API private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Services/Payment/Payment.API/appsettings.json b/src/Services/Payment/Payment.API/appsettings.json index bf6157648..a73471214 100644 --- a/src/Services/Payment/Payment.API/appsettings.json +++ b/src/Services/Payment/Payment.API/appsettings.json @@ -1,6 +1,7 @@ { "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Web/WebMVC/Program.cs b/src/Web/WebMVC/Program.cs index c329237ce..a80d0514b 100644 --- a/src/Web/WebMVC/Program.cs +++ b/src/Web/WebMVC/Program.cs @@ -49,16 +49,17 @@ namespace Microsoft.eShopOnContainers.WebMVC .UseSerilog() .Build(); - private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) + private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Web/WebMVC/WebMVC.csproj b/src/Web/WebMVC/WebMVC.csproj index 739e50506..6f466d730 100644 --- a/src/Web/WebMVC/WebMVC.csproj +++ b/src/Web/WebMVC/WebMVC.csproj @@ -41,6 +41,7 @@ + diff --git a/src/Web/WebMVC/appsettings.json b/src/Web/WebMVC/appsettings.json index 591964725..96c75b932 100644 --- a/src/Web/WebMVC/appsettings.json +++ b/src/Web/WebMVC/appsettings.json @@ -13,6 +13,7 @@ "UseCustomizationData": false, "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { diff --git a/src/Web/WebMVC/package-lock.json b/src/Web/WebMVC/package-lock.json index a94ca154f..785fd8273 100644 --- a/src/Web/WebMVC/package-lock.json +++ b/src/Web/WebMVC/package-lock.json @@ -19,7 +19,7 @@ "resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz", "integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=", "requires": { - "jquery": "3.3.1" + "jquery": ">=1.12.0" } } } diff --git a/src/Web/WebSPA/package-lock.json b/src/Web/WebSPA/package-lock.json index 8386a6cf9..9a1e9af96 100644 --- a/src/Web/WebSPA/package-lock.json +++ b/src/Web/WebSPA/package-lock.json @@ -2887,9 +2887,9 @@ } }, "bootstrap": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz", - "integrity": "sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==" + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz", + "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==" }, "boxen": { "version": "1.3.0", @@ -6959,9 +6959,9 @@ "dev": true }, "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", + "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", "dev": true, "requires": { "argparse": "^1.0.7", diff --git a/src/Web/WebSPA/package.json b/src/Web/WebSPA/package.json index 2adfb5d84..11cb0b882 100644 --- a/src/Web/WebSPA/package.json +++ b/src/Web/WebSPA/package.json @@ -39,7 +39,7 @@ "@angular/router": "^7.2.10", "@aspnet/signalr": "1.0.3", "@ng-bootstrap/ng-bootstrap": "3.3.0", - "bootstrap": "4.1.3", + "bootstrap": "4.3.1", "core-js": "^2.5.0", "file-loader": "2.0.0", "font-awesome": "4.7.0", diff --git a/src/Web/WebStatus/Program.cs b/src/Web/WebStatus/Program.cs index d97ca289f..c8c850cfd 100644 --- a/src/Web/WebStatus/Program.cs +++ b/src/Web/WebStatus/Program.cs @@ -54,16 +54,17 @@ namespace WebStatus .UseSerilog() .Build(); - private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) + private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; - + var logstashUrl = configuration["Serilog:LogstashgUrl"]; return new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("ApplicationContext", AppName) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl) + .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl) .ReadFrom.Configuration(configuration) .CreateLogger(); } diff --git a/src/Web/WebStatus/WebStatus.csproj b/src/Web/WebStatus/WebStatus.csproj index 320780ffa..e66f0a211 100644 --- a/src/Web/WebStatus/WebStatus.csproj +++ b/src/Web/WebStatus/WebStatus.csproj @@ -28,6 +28,7 @@ + diff --git a/src/Web/WebStatus/appsettings.json b/src/Web/WebStatus/appsettings.json index d5589cc5a..da478fe30 100644 --- a/src/Web/WebStatus/appsettings.json +++ b/src/Web/WebStatus/appsettings.json @@ -5,6 +5,7 @@ }, "Serilog": { "SeqServerUrl": null, + "LogstashgUrl": null, "MinimumLevel": { "Default": "Information", "Override": { @@ -13,5 +14,13 @@ "System": "Warning" } } - } + }, + "Webhooks": [ + { + "Name": "", + "Uri": "", + "Payload": "", + "RestoredPayload": "" + } + ] }