diff --git a/.env b/.env index 797e5fc5c..c8fcdfcf2 100644 --- a/.env +++ b/.env @@ -23,3 +23,5 @@ ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92 #ESHOP_AZURE_STORAGE_MARKETING_KEY= #ESHOP_SERVICE_BUS_USERNAME= #ESHOP_SERVICE_BUS_PASSWORD= +#INSTRUMENTATION_KEY= +#USE_LOADTEST= \ No newline at end of file diff --git a/README.md b/README.md index c0218730f..a0d988099 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,53 @@ - # eShopOnContainers - Microservices Architecture and Containers based Reference Application (Visual Studio 2017 and CLI environments compatible) +# eShopOnContainers - Microservices Architecture and Containers based Reference Application (**BETA state** - Visual Studio 2017 and CLI environments compatible) Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers.

-**Note for Pull Requests**: We accept pull request from the community. When doing it, please do it onto the DEV branch which is the consolidated work-in-progress branch. Do not request it onto Master, if possible. - -## Moved to .NET Core 2.0 "wave" -We have moved to .NET Core 2.0! +**Note Visual Studio 2017 version required**: This is important as of Oct. 11th 2017. For working with Docker and docker-compose files (needed with eShopOnContainers), do not migrate to VS 2017 15.4 as it has a bug when using TAGs in the docker-compose files. +Please, either use VS 2017 15.35 or VS 2017 15.5 Preview 1 (bug is fixed here) or later. +VS Preview installs next to your stable Visual Studio IDE, allowing you to use either independently. +Download of Preview here: https://www.visualstudio.com/vs/preview/ -* Branch `dev` is in .NET Core 2.0. -* Branch `master` is *still* in .NET Core 1.1 (but it will be updated soon) +**Note for Pull Requests**: We accept pull request from the community. When doing it, please do it onto the DEV branch which is the consolidated work-in-progress branch. Do not request it onto Master, if possible. -To access the .NET Core 1.1 version you can use the `netcore1.1` tag ([https://github.com/dotnet-architecture/eShopOnContainers/tree/netcore1.1](https://github.com/dotnet-architecture/eShopOnContainers/tree/netcore1.1)) +## Moving to .NET Core 2.0 "wave" +NOTE: During August/September 2017 we'll be moving the solution to .NET Core "wave". Not just compilation but also new recommended code in EF Core 2.0, ASP.NET Core 2.0, and other new related versions. >**PLEASE** Read our [branch guide](./branch-guide.md) to know about our branching policy > ### DISCLAIMER -> **IMPORTANT:** The current state of this sample application is **BETA** for the .NET Core 2.0 version, and v1.0 for the .NET Core 1.1.2 version tagged ([https://github.com/dotnet-architecture/eShopOnContainers/tree/netcore1.1](https://github.com/dotnet-architecture/eShopOnContainers/tree/netcore1.1)) +> **IMPORTANT:** The current state of this sample application is **BETA**, consider it version 0.1, a foundational version. Therefore, many areas could be improved and change significantly while refactoring current code and implementing new features. Feedback with improvements and pull requests from the community will be highly appreciated and accepted. > > This reference application proposes a simplified microservice oriented architecture implementation to introduce technologies like .NET Core with Docker containers through a comprehensive application. The chosen domain is an eShop/eCommerce but simply because it is a well-know domain by most people/developers. However, this sample application should not be considered as an "eCommerce reference model", at all. The implemented business domain might not be ideal from an eCommerce business point of view. It is neither trying to solve all the problems in a large, scalable and mission-critical distributed system. It is just a bootstrap for developers to easily get started in the world of Docker containers and microservices with .NET Core. ->

The next step after understanding Docker containers and microservices development with .NET Core, is to select a microservice cluster/orchestrator like Azure Service Fabric or Kubernetes, DC/OS or Docker Swarm (in Azure Container Service). Kubernetes and Service Fabric are being tested with eShopOnContainer. -> Additional steps already tested in eShopOnContainers are about moving your databases to HA cloud services (like Azure SQL DB), to implement your EventBus with Azure Service Bus or any other production ready Service Bus in the market. +>

For example, the next step (still not covered in eShopOnContainers) after understanding Docker containers and microservices development with .NET Core, is to select a microservice cluster/orchestrator like Docker Swarm, Kubernetes or DC/OS (in Azure Container Service) or Azure Service Fabric which in most of the cases will require additional partial changes to your application's configuration (although the present architecture should work on most orchestrators with small changes). +> Additional steps would be to move your databases to HA cloud services, or to implement your EventBus with Azure Service Bus or any other production ready Service Bus in the market. +>

In the future we might fork this project and make multiple versions targeting specific microservice cluster/orchestrators plus using additional cloud infrastructure.

> > Read the planned Roadmap and Milestones for future releases of eShopOnContainers within the Wiki for further info about possible new implementations and provide feedback at the ISSUES section if you'd like to see any specific scenario implemented or improved. Also, feel free to discuss on any current issue. -**Architecture overview**: This reference application is cross-platform either at the server and client side, thanks to .NET Core services capable of running on Linux or Windows containers depending on your Docker host, and to Xamarin for mobile apps running on Android, iOS or Windows/UWP plus any browser for the client web apps. +**Architecture overview**: This reference application is cross-platform at the server and client side, thanks to .NET Core services capable of running on Linux or Windows containers depending on your Docker host, and to Xamarin for mobile apps running on Android, iOS or Windows/UWP plus any browser for the client web apps. The architecture proposes a simplified microservice oriented architecture implementation with multiple autonomous microservices (each one owning its own data/db) and implementing different approaches within each microservice (simple CRUD vs. DDD/CQRS patterns) using Http as the communication protocol between the client apps and the microservices and supports asynchronous communication for data updates propagation across multiple services based on Integration Events and an Event Bus (a light message broker, to choose between RabbitMQ or Azure Service Bus, underneath) plus other features defined at the roadmap.

-The microservices are different in type, meaning different internal architecture patterns approaches depending on it purpose, as shown in the image below. + +> ### Important Note on API Gateways and published APIs +> Note that the previous architecture diagram shows how you deploy eShopOnContainers in a local Docker development machine. For a production-ready architecture we recommend to keep evolving your architecture with additional features like API Gateways based on AzureAPI Management or any other approach for API Gateways explained in the related documentation/eBook, so you can filter APIs and apply security in a single tier while hiding/securing the internal microservices to the client apps or outside consumers. +

+ +

+ +> The sample code in this repo is NOT making use of Azure API Management in order to be able to provide an "F5 experience" in Visual Studio (or CLI) of the sample with no up-front dependencies in Azure. But you should evaluate API Gateways alternatives when building for production. + +The microservices are different in type, meaning different internal architecture pattern approaches depending on its purpose, as shown in the image below.

-Additional microservice styles with other frameworks and No-SQL databases will be added, eventually. This is a great opportunity for pull requests from the community, like a new microservice using Nancy, or even other languages like Node, Go, Python or data containers with MongoDB with Azure DocDB compatibility, PostgreSQL, RavenDB, Event Store, MySql, etc. You name it! :) > ### Important Note on Database Servers/Containers -> In this solution's current configuration for a development environment, the SQL databases are automatically deployed with sample data into a single SQL Server for Linux container (a single shared Docker container for SQL databases) so the whole solution can be up and running without any dependency to any cloud or specific server. Each database could also be deployed as a single Docker container, but then you'd need more then 8GB or memory RAM assigned to Docker in your development machine in order to be able to run 3 SQL Server Docker containers in your Docker Linux host in "Docker for Windows" or "Docker for Mac" development environments. ->

A similar case is defined in regards Redis cache running as a container for the development environment. ->

However, in a real production environment it is recommended to have your databases (SQL Server and Redis, in this case) in HA (High Available) services like Azure SQL Database, Redis as a service or any other clustering system. If you want to change to a production configuration, you'll just need to change the connection strings once you have set up the servers in a HA cloud or on-premises. +> In this solution's current configuration for a development environment, the SQL databases are automatically deployed with sample data into a single SQL Server for Linux container (a single shared Docker container for SQL databases) so the whole solution can be up and running without any dependency to any cloud or specific server. Each database could also be deployed as a single Docker container, but then you'd need more than 8GB of RAM assigned to Docker in your development machine in order to be able to run 3 SQL Server Docker containers in your Docker Linux host in "Docker for Windows" or "Docker for Mac" development environments. +>

A similar case is defined in regard to Redis cache running as a container for the development environment. Or a No-SQL database (MongoDB) running as a container. +>

However, in a real production environment it is recommended to have your databases (SQL Server, Redis, and the NO-SQL database, in this case) in HA (High Available) services like Azure SQL Database, Redis as a service and Azure CosmosDB instead the MongoDB container (as both systems share the same access protocol). If you want to change to a production configuration, you'll just need to change the connection strings once you have set up the servers in a HA cloud or on-premises. ## Related documentation and guidance While developing this reference application, we've been creating a reference Guide/eBook focusing on architecting and developing containerized and microservice based .NET Applications (download link available below) which explains in detail how to develop this kind of architectural style (microservices, Docker containers, Domain-Driven Design for certain microservices) plus other simpler architectural styles, like monolithic apps that can also live as Docker containers. @@ -70,7 +79,7 @@ The screenshot below shows the VS Solution structure for those microservices/con Finally, those microservices are consumed by multiple client web and mobile apps, as described below.
-*MVC Application (ASP.NET Core)*: Its an MVC application where you can find interesting scenarios on how to consume HTTP-based microservices from C# running in the server side, as it is a typical ASP.NET Core MVC application. Since it is a server-side application, access to other containers/microservices is done within the internal Docker Host network with its internal name resolution. +*MVC Application (ASP.NET Core)*: It's an MVC application where you can find interesting scenarios on how to consume HTTP-based microservices from C# running in the server side, as it is a typical ASP.NET Core MVC application. Since it is a server-side application, access to other containers/microservices is done within the internal Docker Host network with its internal name resolution.
*SPA (Single Page Application)*: Providing similar "eShop business functionality" but developed with Angular 2, Typescript and slightly using ASP.NET Core MVC. This is another approach for client web applications to be used when you want to have a more modern client behavior which is not behaving with the typical browser round-trip on every action but behaving like a Single-Page-Application which is more similar to a desktop app usage experience. The consumption of the HTTP-based microservices is done from TypeScript/JavaScript in the client browser, so the client calls to the microservices come from out of the Docker Host internal network (Like from your network or even from the Internet). @@ -94,33 +103,11 @@ For those who prefer the CLI on a Mac, using dotnet CLI, docker CLI and VS Code (Instructions still TBD, but similar to Windows CLI): https://github.com/dotnet/eShopOnContainers/wiki/04.-Setting-eShopOnContainer-solution-up-in-a-Mac,-VS-Code-and-CLI-environment--(dotnet-CLI,-Docker-CLI-and-VS-Code) -> ### Note on tested Docker Containers/Images -> Most of the development and testing of this project was (as of early March 2017) done on Docker Linux containers running in development machines with "Docker for Windows" and the default Hyper-V Linux VM (MobiLinuxVM) installed by "Docker for Windows". -The Windows Containers scenario is currently being implemented/tested yet. The application should be able to run on Windows Nano Containers based on different Docker base images, as well, as the .NET Core services have also been tested running on plain Windows (with no Docker). -The app was also partially tested on "Docker for Mac" using a development MacOS machine with .NET Core and VS Code installed, which is still a scenario using Linux containers running on the VM setup in the Mac by the "Docker for Windows" setup. But further testing and feedback on Mac environments and Windows Containers, from the community, will be appreciated. - -## Kubernetes -The k8s directory contains Kubernetes configuration for the eShopOnContainers app and a PowerShell script to deploy it to a cluster. Each eShopOnContainers microservice has a deployment configuration in `deployments.yaml`, and is exposed to the cluster by a service in `services.yaml`. The microservices are exposed externally on individual routes (`/basket-api`, `/webmvc`, etc.) by an nginx reverse proxy specified in `frontend.yaml` and `nginx.conf`. - -### Prerequisites -* A Kubernetes cluster. Follow Azure Container Service's [walkthrough](https://docs.microsoft.com/en-us/azure/container-service/container-service-kubernetes-walkthrough) to create one. -* A private Docker registry. Follow Azure Container Registry's [guide](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal) to create one. -* A Docker development environment with `docker` and `docker-compose`. - * Visit [docker.com](https://docker.com) to download the tools and set up the environment. Docker's [installation guide](https://docs.docker.com/engine/getstarted/step_one/#step-3-verify-your-installation) covers verifying your Docker installation. -* The Kubernetes command line client, `kubectl`. - * This can be installed with the `az` tool as described in the Azure Container Service [walkthrough](https://docs.microsoft.com/en-us/azure/container-service/container-service-kubernetes-walkthrough). `az` is also helpful for getting the credentials `kubectl` needs to access your cluster. For other installation options, and information about configuring `kubectl` yourself, see the [Kubernetes documentation](https://kubernetes.io/docs/tasks/kubectl/install/). - -### Deploy the application with the deployment script -1. Open a PowerShell command line at the `k8s` directory of your local eShopOnContainers repository. -1. Ensure `docker`, `docker-compose`, and `kubectl` are on the path, and configured for your Docker machine and Kubernetes cluster. -1. Run `deploy.ps1` with your registry information. The Docker username and password are provided by Azure Container Registry, and can be retrieved from the Azure portal. For example: ->``` ->./deploy.ps1 -registry myregistry.azurecr.io -dockerUser User -dockerPassword SecretPassword ->``` -The script will build the code and corresponding Docker images, push the latter to your registry, and deploy the application to your cluster. You can watch the deployment unfold from the Kubernetes web interface: run `kubectl proxy` and open a browser to [http://localhost:8001/ui](http://localhost:8001/ui) +## Orchestrators: Kubernetes and Service Fabric +See at the Wiki the posts on setup/instructions about how to deploy to Kubernetes or Service Fabric in Azure (although you could also deploy to any other cloud or on-premises). ## Sending feedback and pull requests -As mentioned, we'd appreciate to your feedback, improvements and ideas. +As mentioned, we'd appreciate your feedback, improvements and ideas. You can create new issues at the issues section, do pull requests and/or send emails to **eshop_feedback@service.microsoft.com** ## Questions diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..bb1cf2743 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/Config/Settings.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/ServiceManifest.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/ServiceManifest.xml new file mode 100644 index 000000000..8c2f16691 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/ServiceManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + rabbitmq:3-management + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..5a4c2828d --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Cloud.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..1699b8eaa --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..1699b8eaa --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/Bus.sfproj b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/Bus.sfproj new file mode 100644 index 000000000..0a56c800e --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/Bus.sfproj @@ -0,0 +1,46 @@ + + + + + f29e27c9-0d5e-4a57-adbf-dd651649d2a1 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/packages.config b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricBus/Bus/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..fe031fe95 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/Config/Settings.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/ServiceManifest.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/ServiceManifest.xml new file mode 100644 index 000000000..e7ecf592f --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/ServiceManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + mongo:latest + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..8b48c39d1 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Cloud.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..22363f273 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..22363f273 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/NoSQL.sfproj b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/NoSQL.sfproj new file mode 100644 index 000000000..f07ff03a9 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/NoSQL.sfproj @@ -0,0 +1,46 @@ + + + + + eb070036-ec60-49a6-88e1-562a2043c3d7 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/packages.config b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..11bf47a6a --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/Config/Settings.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/ServiceManifest.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/ServiceManifest.xml new file mode 100644 index 000000000..cfcc10eca --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/ServiceManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + redis:latest + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..951ce24db --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Cloud.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..e2f3876c7 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..e2f3876c7 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/Redis.sfproj b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/Redis.sfproj new file mode 100644 index 000000000..5b28bfdba --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/Redis.sfproj @@ -0,0 +1,46 @@ + + + + + 17acd9ea-8f16-4091-aa29-c67002971eee + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/packages.config b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricRedis/Redis/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..27fa4bfe2 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/Config/Settings.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/ServiceManifest.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/ServiceManifest.xml new file mode 100644 index 000000000..97ff3ded2 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/ServiceManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + microsoft/mssql-server-linux:2017-latest + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..3ad12232a --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Cloud.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..9fc10b0bc --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..9fc10b0bc --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/Sql.sfproj b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/Sql.sfproj new file mode 100644 index 000000000..48447811e --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/Sql.sfproj @@ -0,0 +1,46 @@ + + + + + 65a83188-79c1-47ad-931d-8e8a87247408 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/packages.config b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Linux/Infrastructure/eShopOnServiceFabricSql/Sql/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..6cffab120 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..b73e3d5f7 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/ServiceManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + eshop/basket.api:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..f46e22fc7 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/ServiceManifest.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + eshop/catalog.api:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..b67bb16ee --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/ServiceManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + eshop/locations.api:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..615379176 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/ServiceManifest.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + eshop/marketing.api:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..b6820aa70 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + eshop/ordering.api:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..2a9a4dfd6 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/ServiceManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + eshop/payment.api:latest + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..bf87a8296 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Cloud.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..e579cbf89 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..e579cbf89 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/eShopOnServiceFabric/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/eShopOnServiceFabric.sfproj b/ServiceFabric/Linux/eShopOnServiceFabric/eShopOnServiceFabric.sfproj new file mode 100644 index 000000000..405e7bb4c --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/eShopOnServiceFabric.sfproj @@ -0,0 +1,55 @@ + + + + + 983eab84-65c5-4793-a300-08f97c791a15 + 1.6 + 1.5 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabric/packages.config b/ServiceFabric/Linux/eShopOnServiceFabric/packages.config new file mode 100644 index 000000000..c5f59e48e --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabric/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..638b70194 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..60a6ef71b --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/ServiceManifest.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + eshop/identity.api:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..a1255b6c0 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Cloud.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..e8623180a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..e8623180a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv.sfproj b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv.sfproj new file mode 100644 index 000000000..1d0d025a9 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv.sfproj @@ -0,0 +1,46 @@ + + + + + 39b54901-d57d-416e-b51e-33c4017ca464 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/packages.config b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..158c03905 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/ServiceManifest.xml new file mode 100644 index 000000000..9b6e89cfe --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/ServiceManifest.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + eshop/webmvc:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..d99e1573a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Cloud.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..1d59af5a6 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..1d59af5a6 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC.sfproj b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC.sfproj new file mode 100644 index 000000000..ff4ce2247 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC.sfproj @@ -0,0 +1,46 @@ + + + + + 0cf895ff-3616-4d1f-8d2e-5d856cdf3612 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/packages.config b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..7fca0294e --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/ServiceManifest.xml new file mode 100644 index 000000000..470eb37b4 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/ServiceManifest.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + eshop/webspa:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..fdeb6fd88 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Cloud.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..92fe692c3 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..92fe692c3 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA.sfproj b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA.sfproj new file mode 100644 index 000000000..05ed606be --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA.sfproj @@ -0,0 +1,46 @@ + + + + + 1670de10-5626-429d-a74a-2dd8281cc0c9 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/packages.config b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..da2d7de0b --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/Config/Settings.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/ServiceManifest.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/ServiceManifest.xml new file mode 100644 index 000000000..26e50454b --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/ServiceManifest.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + eshop/webstatus:latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..f49e04e6b --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Cloud.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..9864bd050 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..9864bd050 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Cloud.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.1Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.5Node.xml b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus.sfproj b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus.sfproj new file mode 100644 index 000000000..1d4def7f2 --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus.sfproj @@ -0,0 +1,46 @@ + + + + + 25f73fd9-b32f-401a-80e8-17c72606a7e1 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/packages.config b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Linux/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..bb1cf2743 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/Config/Settings.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/ServiceManifest.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/ServiceManifest.xml new file mode 100644 index 000000000..9415f54f2 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationPackageRoot/RabbitMQPkg/ServiceManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + spring2/rabbitmq:3.6.10 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..5a4c2828d --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Cloud.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..1699b8eaa --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..1699b8eaa --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/Bus.sfproj b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/Bus.sfproj new file mode 100644 index 000000000..0a56c800e --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/Bus.sfproj @@ -0,0 +1,46 @@ + + + + + f29e27c9-0d5e-4a57-adbf-dd651649d2a1 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/packages.config b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricBus/Bus/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..fe031fe95 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/Config/Settings.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/ServiceManifest.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/ServiceManifest.xml new file mode 100644 index 000000000..be47332ca --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationPackageRoot/MongoDBPkg/ServiceManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + mongo:windowsservercore + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..8b48c39d1 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Cloud.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..22363f273 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..22363f273 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/NoSQL.sfproj b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/NoSQL.sfproj new file mode 100644 index 000000000..f07ff03a9 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/NoSQL.sfproj @@ -0,0 +1,46 @@ + + + + + eb070036-ec60-49a6-88e1-562a2043c3d7 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/packages.config b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricNoSql/NoSQL/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..11bf47a6a --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/Config/Settings.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/ServiceManifest.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/ServiceManifest.xml new file mode 100644 index 000000000..ea9deb355 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationPackageRoot/BasketDataPkg/ServiceManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + redis:nanoserver + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..951ce24db --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Cloud.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..e2f3876c7 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..e2f3876c7 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/Redis.sfproj b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/Redis.sfproj new file mode 100644 index 000000000..5b28bfdba --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/Redis.sfproj @@ -0,0 +1,46 @@ + + + + + 17acd9ea-8f16-4091-aa29-c67002971eee + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/packages.config b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricRedis/Redis/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..27fa4bfe2 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/Config/Settings.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/ServiceManifest.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/ServiceManifest.xml new file mode 100644 index 000000000..252c74f21 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationPackageRoot/SqlServerPkg/ServiceManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + microsoft/mssql-server-windows-developer:2017 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..3ad12232a --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Cloud.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..9fc10b0bc --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..9fc10b0bc --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/Sql.sfproj b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/Sql.sfproj new file mode 100644 index 000000000..48447811e --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/Sql.sfproj @@ -0,0 +1,46 @@ + + + + + 65a83188-79c1-47ad-931d-8e8a87247408 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/packages.config b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Windows/Infrastructure/eShopOnServiceFabricSql/Sql/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..29679fbaa --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..4a5574fd6 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/BasketApiPkg/ServiceManifest.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + eshop/basket.api-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..f101ce6b9 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/CatalogApiPkg/ServiceManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + eshop/catalog.api-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..47dbb5a12 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/LocationsApiPkg/ServiceManifest.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + eshop/locations.api-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..db840c274 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/MarketingApiPkg/ServiceManifest.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + eshop/marketing.api-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..d014b3ee8 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/OrderingApiPkg/ServiceManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + eshop/ordering.api-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..fe787521f --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationPackageRoot/PaymentApiPkg/ServiceManifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + eshop/payment.api-win + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..bf87a8296 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Cloud.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..e579cbf89 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..e579cbf89 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/eShopOnServiceFabric/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/eShopOnServiceFabric.sfproj b/ServiceFabric/Windows/eShopOnServiceFabric/eShopOnServiceFabric.sfproj new file mode 100644 index 000000000..405e7bb4c --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/eShopOnServiceFabric.sfproj @@ -0,0 +1,55 @@ + + + + + 983eab84-65c5-4793-a300-08f97c791a15 + 1.6 + 1.5 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabric/packages.config b/ServiceFabric/Windows/eShopOnServiceFabric/packages.config new file mode 100644 index 000000000..c5f59e48e --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabric/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..b39aef66a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/ServiceManifest.xml new file mode 100644 index 000000000..f6de99e73 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationPackageRoot/IdentityApiPkg/ServiceManifest.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + eshop/identity.api-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..207735106 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Cloud.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..e8623180a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..e8623180a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv.sfproj b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv.sfproj new file mode 100644 index 000000000..1d0d025a9 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv.sfproj @@ -0,0 +1,46 @@ + + + + + 39b54901-d57d-416e-b51e-33c4017ca464 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/packages.config b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricIdSrv/eShopOnServiceFabricIdSrv/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..8282adb11 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/ServiceManifest.xml new file mode 100644 index 000000000..927220a15 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationPackageRoot/WebMVCPkg/ServiceManifest.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + eshop/webmvc-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..d99e1573a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Cloud.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..1d59af5a6 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..1d59af5a6 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC.sfproj b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC.sfproj new file mode 100644 index 000000000..ff4ce2247 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC.sfproj @@ -0,0 +1,46 @@ + + + + + 0cf895ff-3616-4d1f-8d2e-5d856cdf3612 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/packages.config b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebMVC/eShopOnServiceFabricWebMVC/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..e7479f239 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/ServiceManifest.xml new file mode 100644 index 000000000..ea6e46d72 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationPackageRoot/WebSPAPkg/ServiceManifest.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + eshop/webspa-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..fdeb6fd88 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Cloud.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..92fe692c3 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..92fe692c3 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA.sfproj b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA.sfproj new file mode 100644 index 000000000..05ed606be --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA.sfproj @@ -0,0 +1,46 @@ + + + + + 1670de10-5626-429d-a74a-2dd8281cc0c9 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/packages.config b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebSPA/eShopOnServiceFabricWebSPA/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/ApplicationManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/ApplicationManifest.xml new file mode 100644 index 000000000..20fb0c3a9 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/ApplicationManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/Config/Settings.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/Config/Settings.xml new file mode 100644 index 000000000..ad84ffd8a --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/ServiceManifest.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/ServiceManifest.xml new file mode 100644 index 000000000..3cbfc87a9 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationPackageRoot/WebStatusPkg/ServiceManifest.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + eshop/webstatus-win + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Cloud.xml new file mode 100644 index 000000000..f49e04e6b --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Cloud.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.1Node.xml new file mode 100644 index 000000000..9864bd050 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.1Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.5Node.xml new file mode 100644 index 000000000..9864bd050 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/ApplicationParameters/Local.5Node.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Cloud.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Cloud.xml new file mode 100644 index 000000000..2ab9df11c --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Cloud.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.1Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.1Node.xml new file mode 100644 index 000000000..6e1403e96 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.1Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.5Node.xml b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.5Node.xml new file mode 100644 index 000000000..f42d759c3 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/PublishProfiles/Local.5Node.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/Scripts/Deploy-FabricApplication.ps1 b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/Scripts/Deploy-FabricApplication.ps1 new file mode 100644 index 000000000..2897b10e8 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/Scripts/Deploy-FabricApplication.ps1 @@ -0,0 +1,258 @@ +<# +.SYNOPSIS +Deploys a Service Fabric application type to a cluster. + +.DESCRIPTION +This script deploys a Service Fabric application type to a cluster. It is invoked by Visual Studio when deploying a Service Fabric Application project. + +.NOTES +WARNING: This script file is invoked by Visual Studio. Its parameters must not be altered but its logic can be customized as necessary. + +.PARAMETER PublishProfileFile +Path to the file containing the publish profile. + +.PARAMETER ApplicationPackagePath +Path to the folder of the packaged Service Fabric application. + +.PARAMETER DeployOnly +Indicates that the Service Fabric application should not be created or upgraded after registering the application type. + +.PARAMETER ApplicationParameter +Hashtable of the Service Fabric application parameters to be used for the application. + +.PARAMETER UnregisterUnusedApplicationVersionsAfterUpgrade +Indicates whether to unregister any unused application versions that exist after an upgrade is finished. + +.PARAMETER OverrideUpgradeBehavior +Indicates the behavior used to override the upgrade settings specified by the publish profile. +'None' indicates that the upgrade settings will not be overridden. +'ForceUpgrade' indicates that an upgrade will occur with default settings, regardless of what is specified in the publish profile. +'VetoUpgrade' indicates that an upgrade will not occur, regardless of what is specified in the publish profile. + +.PARAMETER UseExistingClusterConnection +Indicates that the script should make use of an existing cluster connection that has already been established in the PowerShell session. The cluster connection parameters configured in the publish profile are ignored. + +.PARAMETER OverwriteBehavior +Overwrite Behavior if an application exists in the cluster with the same name. Available Options are Never, Always, SameAppTypeAndVersion. This setting is not applicable when upgrading an application. +'Never' will not remove the existing application. This is the default behavior. +'Always' will remove the existing application even if its Application type and Version is different from the application being created. +'SameAppTypeAndVersion' will remove the existing application only if its Application type and Version is same as the application being created. + +.PARAMETER SkipPackageValidation +Switch signaling whether the package should be validated or not before deployment. + +.PARAMETER SecurityToken +A security token for authentication to cluster management endpoints. Used for silent authentication to clusters that are protected by Azure Active Directory. + +.PARAMETER CopyPackageTimeoutSec +Timeout in seconds for copying application package to image store. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' + +Deploy the application using the default package location for a Debug build. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -DoNotCreateApplication + +Deploy the application but do not create the application instance. + +.EXAMPLE +. Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath 'pkg\Debug' -ApplicationParameter @{CustomParameter1='MyValue'; CustomParameter2='MyValue'} + +Deploy the application by providing values for parameters that are defined in the application manifest. +#> + +Param +( + [String] + $PublishProfileFile, + + [String] + $ApplicationPackagePath, + + [Switch] + $DeployOnly, + + [Hashtable] + $ApplicationParameter, + + [Boolean] + $UnregisterUnusedApplicationVersionsAfterUpgrade, + + [String] + [ValidateSet('None', 'ForceUpgrade', 'VetoUpgrade')] + $OverrideUpgradeBehavior = 'None', + + [Switch] + $UseExistingClusterConnection, + + [String] + [ValidateSet('Never','Always','SameAppTypeAndVersion')] + $OverwriteBehavior = 'Never', + + [Switch] + $SkipPackageValidation, + + [String] + $SecurityToken, + + [int] + $CopyPackageTimeoutSec +) + +function Read-XmlElementAsHashtable +{ + Param ( + [System.Xml.XmlElement] + $Element + ) + + $hashtable = @{} + if ($Element.Attributes) + { + $Element.Attributes | + ForEach-Object { + $boolVal = $null + if ([bool]::TryParse($_.Value, [ref]$boolVal)) { + $hashtable[$_.Name] = $boolVal + } + else { + $hashtable[$_.Name] = $_.Value + } + } + } + + return $hashtable +} + +function Read-PublishProfile +{ + Param ( + [ValidateScript({Test-Path $_ -PathType Leaf})] + [String] + $PublishProfileFile + ) + + $publishProfileXml = [Xml] (Get-Content $PublishProfileFile) + $publishProfile = @{} + + $publishProfile.ClusterConnectionParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("ClusterConnectionParameters") + $publishProfile.UpgradeDeployment = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment") + $publishProfile.CopyPackageParameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("CopyPackageParameters") + + if ($publishProfileXml.PublishProfile.Item("UpgradeDeployment")) + { + $publishProfile.UpgradeDeployment.Parameters = Read-XmlElementAsHashtable $publishProfileXml.PublishProfile.Item("UpgradeDeployment").Item("Parameters") + if ($publishProfile.UpgradeDeployment["Mode"]) + { + $publishProfile.UpgradeDeployment.Parameters[$publishProfile.UpgradeDeployment["Mode"]] = $true + } + } + + $publishProfileFolder = (Split-Path $PublishProfileFile) + $publishProfile.ApplicationParameterFile = [System.IO.Path]::Combine($PublishProfileFolder, $publishProfileXml.PublishProfile.ApplicationParameterFile.Path) + + return $publishProfile +} + +$LocalFolder = (Split-Path $MyInvocation.MyCommand.Path) + +if (!$PublishProfileFile) +{ + $PublishProfileFile = "$LocalFolder\..\PublishProfiles\Local.xml" +} + +if (!$ApplicationPackagePath) +{ + $ApplicationPackagePath = "$LocalFolder\..\pkg\Release" +} + +$ApplicationPackagePath = Resolve-Path $ApplicationPackagePath + +$publishProfile = Read-PublishProfile $PublishProfileFile + +if (-not $UseExistingClusterConnection) +{ + $ClusterConnectionParameters = $publishProfile.ClusterConnectionParameters + if ($SecurityToken) + { + $ClusterConnectionParameters["SecurityToken"] = $SecurityToken + } + + try + { + [void](Connect-ServiceFabricCluster @ClusterConnectionParameters) + } + catch [System.Fabric.FabricObjectClosedException] + { + Write-Warning "Service Fabric cluster may not be connected." + throw + } +} + +$RegKey = "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" +$ModuleFolderPath = (Get-ItemProperty -Path $RegKey -Name FabricSDKPSModulePath).FabricSDKPSModulePath +Import-Module "$ModuleFolderPath\ServiceFabricSDK.psm1" + +$IsUpgrade = ($publishProfile.UpgradeDeployment -and $publishProfile.UpgradeDeployment.Enabled -and $OverrideUpgradeBehavior -ne 'VetoUpgrade') -or $OverrideUpgradeBehavior -eq 'ForceUpgrade' + +$PublishParameters = @{ + 'ApplicationPackagePath' = $ApplicationPackagePath + 'ApplicationParameterFilePath' = $publishProfile.ApplicationParameterFile + 'ApplicationParameter' = $ApplicationParameter + 'ErrorAction' = 'Stop' +} + +if ($publishProfile.CopyPackageParameters.CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $publishProfile.CopyPackageParameters.CopyPackageTimeoutSec +} + +if ($publishProfile.CopyPackageParameters.CompressPackage) +{ + $PublishParameters['CompressPackage'] = $publishProfile.CopyPackageParameters.CompressPackage +} + +# CopyPackageTimeoutSec parameter overrides the value from the publish profile +if ($CopyPackageTimeoutSec) +{ + $PublishParameters['CopyPackageTimeoutSec'] = $CopyPackageTimeoutSec +} + +if ($IsUpgrade) +{ + $Action = "RegisterAndUpgrade" + if ($DeployOnly) + { + $Action = "Register" + } + + $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters + + if ($OverrideUpgradeBehavior -eq 'ForceUpgrade') + { + # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior. + $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true } + } + + $PublishParameters['Action'] = $Action + $PublishParameters['UpgradeParameters'] = $UpgradeParameters + $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade + + Publish-UpgradedServiceFabricApplication @PublishParameters +} +else +{ + $Action = "RegisterAndCreate" + if ($DeployOnly) + { + $Action = "Register" + } + + $PublishParameters['Action'] = $Action + $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior + $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation + + Publish-NewServiceFabricApplication @PublishParameters +} \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus.sfproj b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus.sfproj new file mode 100644 index 000000000..1d4def7f2 --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus.sfproj @@ -0,0 +1,46 @@ + + + + + 25f73fd9-b32f-401a-80e8-17c72606a7e1 + 1.7 + 1.5 + 1.6 + v4.6.1 + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets + + + + + + + + \ No newline at end of file diff --git a/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/packages.config b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/packages.config new file mode 100644 index 000000000..3dc0a332b --- /dev/null +++ b/ServiceFabric/Windows/eShopOnServiceFabricWebStatus/eShopOnServiceFabricWebStatus/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/cli-mac/build-bits.sh b/cli-mac/build-bits.sh index 8548ec72b..a7712b831 100755 --- a/cli-mac/build-bits.sh +++ b/cli-mac/build-bits.sh @@ -1,5 +1,7 @@ #!/bin/sh +# List of microservices here needs to be updated to include all the new microservices (Marketing, etc.) + projectList=( "../src/Services/Catalog/Catalog.API" "../src/Services/Basket/Basket.API" @@ -38,3 +40,5 @@ fi # No need to build the images, docker build or docker compose will # do that using the images and containers defined in the docker-compose.yml file. +# +# diff --git a/cli-windows/vsts/build-bits-no-parallel.ps1 b/cli-windows/vsts/build-bits-no-parallel.ps1 new file mode 100644 index 000000000..4344bdcc8 --- /dev/null +++ b/cli-windows/vsts/build-bits-no-parallel.ps1 @@ -0,0 +1,56 @@ +Param([string] $rootPath) +$scriptPath = Split-Path $script:MyInvocation.MyCommand.Path + +Write-Host "Current script directory is $scriptPath" -ForegroundColor Yellow + +if ([string]::IsNullOrEmpty($rootPath)) { + $rootPath = "$scriptPath\..\.." +} +Write-Host "Root path used is $rootPath" -ForegroundColor Yellow + + +$projectPaths = + @{Path="$rootPath\src\Web\WebMVC";Prj="WebMVC.csproj"}, + @{Path="$rootPath\src\Web\WebSPA";Prj="WebSPA.csproj"}, + @{Path="$rootPath\src\Services\Identity\Identity.API";Prj="Identity.API.csproj"}, + @{Path="$rootPath\src\Services\Catalog\Catalog.API";Prj="Catalog.API.csproj"}, + @{Path="$rootPath\src\Services\Ordering\Ordering.API";Prj="Ordering.API.csproj"}, + @{Path="$rootPath\src\Services\Basket\Basket.API";Prj="Basket.API.csproj"}, + @{Path="$rootPath\src\Services\Location\Locations.API";Prj="Locations.API.csproj"}, + @{Path="$rootPath\src\Services\Marketing\Marketing.API";Prj="Marketing.API.csproj"}, + @{Path="$rootPath\src\Services\Payment\Payment.API";Prj="Payment.API.csproj"}, + @{Path="$rootPath\src\Web\WebStatus";Prj="WebStatus.csproj"} + +$projectPaths | foreach { + $projectPath = $_.Path + $projectFile = $_.Prj + $outPath = $_.Path + "\obj\Docker\publish" + $projectPathAndFile = "$projectPath\$projectFile" + Write-Host "Deleting old publish files in $outPath" -ForegroundColor Yellow + remove-item -path $outPath -Force -Recurse -ErrorAction SilentlyContinue + Write-Host "Publishing $projectPathAndFile to $outPath" -ForegroundColor Yellow + dotnet restore $projectPathAndFile + dotnet build $projectPathAndFile + dotnet publish $projectPathAndFile -o $outPath + } + +######################################################################################## +# Delete old eShop Docker images +######################################################################################## + +$imagesToDelete = docker images --filter=reference="eshop/*" -q + +If (-Not $imagesToDelete) {Write-Host "Not deleting eShop images as there are no eShop images in the current local Docker repo."} +Else +{ + # Delete all containers + Write-Host "Deleting all containers in local Docker Host" + docker rm $(docker ps -a -q) -f + + # Delete all eshop images + Write-Host "Deleting eShop images in local Docker repo" + Write-Host $imagesToDelete + docker rmi $(docker images --filter=reference="eshop/*" -q) -f +} + +# WE DON'T NEED DOCKER BUILD AS WE CAN RUN "DOCKER-COMPOSE BUILD" OR "DOCKER-COMPOSE UP" AND IT WILL BUILD ALL THE IMAGES IN THE .YML FOR US diff --git a/deploy/az/azurefunctions/azurefunctionsdeploy.json b/deploy/az/azurefunctions/azurefunctionsdeploy.json index 7f1b8a445..29625302b 100644 --- a/deploy/az/azurefunctions/azurefunctionsdeploy.json +++ b/deploy/az/azurefunctions/azurefunctionsdeploy.json @@ -6,7 +6,8 @@ "type": "string", "metadata": { "description": "Name of the Azure Functions namespace" - } + }, + "defaultValue": "mktfunctionsdemo" } }, "variables": { @@ -16,7 +17,7 @@ "ServerFarmPlan": "[concat(trim(variables('location')), 'Plan')]", "StorageAccounts": "[concat(variables('SitesEshopfunctionsName'), 'st')]" }, - "resources": [ + "resources": [ { "type": "Microsoft.Storage/storageAccounts", "sku": { diff --git a/deploy/az/servicefabric/LinuxContainers/gen-keyvaultcert.ps1 b/deploy/az/servicefabric/LinuxContainers/gen-keyvaultcert.ps1 new file mode 100644 index 000000000..c6fc34013 --- /dev/null +++ b/deploy/az/servicefabric/LinuxContainers/gen-keyvaultcert.ps1 @@ -0,0 +1,53 @@ +Param( + [parameter(Mandatory=$true)][string]$vaultName, + [parameter(Mandatory=$true)][string]$certName, + [parameter(Mandatory=$true)][string]$certPwd, + [parameter(Mandatory=$true)][string]$subjectName, + [parameter(Mandatory=$false)][string]$ValidityInMonths=12, + [parameter(Mandatory=$true)][string]$saveDir +) + + +#Log in Azure Account +Login-AzureRmAccount + + +# Create Cert in KeyVault +Write-Host "Creating certificate in Azure KeyVault..." -ForegroundColor Yellow +$policy = New-AzureKeyVaultCertificatePolicy -SubjectName $subjectName -IssuerName Self -ValidityInMonths $ValidityInMonths +Add-AzureKeyVaultCertificate -VaultName $vaultName -Name $certName -CertificatePolicy $policy + +# Downloading Certificate +Write-Host "Downloading Certificate from KeyVault..." -ForegroundColor Yellow + +$Stoploop = $false +$Retrycount = 0 + +do { + try { + + $kvSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certName -ErrorAction SilentlyContinue + $kvSecretBytes = [System.Convert]::FromBase64String($kvSecret.SecretValueText) + $certCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection + $certCollection.Import($kvSecretBytes,$null,[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable) + $protectedCertificateBytes = $certCollection.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $certPwd) + [System.IO.File]::WriteAllBytes($saveDir + "\" + $certName + ".pfx", $protectedCertificateBytes) + + $Stoploop = $true + Write-Host "Finished!" -ForegroundColor Yellow + } + catch { + if ($Retrycount -gt 5){ + $Stoploop = $true + Write-Host "Not possible to retrieve the certificate!" -ForegroundColor Yellow + } + else { + Start-Sleep -Seconds 20 + $Retrycount = $Retrycount + 1 + } + } +} +While ($Stoploop -eq $false) + +# Show Certificate Values +Get-AzureKeyVaultCertificate -VaultName $vaultName -Name $certName \ No newline at end of file diff --git a/deploy/az/servicefabric/LinuxContainers/readme.md b/deploy/az/servicefabric/LinuxContainers/readme.md new file mode 100644 index 000000000..98d097b10 --- /dev/null +++ b/deploy/az/servicefabric/LinuxContainers/readme.md @@ -0,0 +1,134 @@ +# Deploying a Service Fabric cluster based on Linux nodes + +## A. Unsecured cluster (SF Linux cluster) +For a secured cluster, see option B. below. + +You can always deploy a SF cluster through the Azure portal, as explained in this article: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-get-started-azure-cluster + +However, when creating a cluster, there are quite a few configurations to take into account, like enabling the internal DNS service or Reverse Proxy service, choosing between Linux/Windows, open/publish your application ports in the load-balancer and most of all (the most complex setup) how to create a secure cluster. + +Because of those reasons, we have created a set of ARM templates and scripts so you can create, re-create and configure the SF clusters much faster, as explained below: + +Within eShopOnContainers root folder, at the folder [..\deploy\az\servicefabric\LinuxContainers](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/az/servicefabric/LinuxContainers), you can find the ARM template `servicefabricdeploy.json` and its parameters file (`servicefabricdeploy.parameters.json`) to create a Service Fabric cluster environment for Linux Containers. + +## Edit the servicefabricdeploy.parameters.json file + +Edit the following params in `servicefabricdeploy.parameters.json` file to set your values: + +- clusterName: Name of your SF cluster +- clusterLocation: Datacenter location, like westus or westeurope +- computeLocation: Datacenter location, like westus or westeurope +- adminUserName: user-name for VMs administration +- adminPassword: user-password for VMs administration +- dnsName: Name assigned to your SF dns + +Optionally, you could modify which ports are opened in the LoadBalancer for the multiple eShopOnContainer apps and API services. +By default, they are setup as: +- webMvcHttpPort: 5100 +- webSpaHttpPort: 5104 +- webStatusHttpPort: 5107 +- IdSrvHttpRule: 5105 +- BasketApiHttpRule: 5103 +- CatalogApiHttpRule: 5101 +- OrderingApiHttpRule: 5102 +- MarketingApiHttpRule: 5110 +- LocationsApiHttpRule: 5109 + +## Deploy the Service Fabric cluster using the script and ARM templates + +Once parameter file is edited you can deploy it using [create-resources script](../readme.md). + +For example, to deploy the cluster to a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd servicefabric\LinuxContainers\servicefabricdeploy qa-eshop-sflinux-resgrp -c westus +``` + +You should see a similar execution to the following: +![image](https://user-images.githubusercontent.com/1712635/31638180-15da9f84-b287-11e7-9d4e-604f33690198.png) + +Now, if you go to your subscription in Azure, you should be able to see the SF cluster already created and available, like in the following image: + +![image](https://user-images.githubusercontent.com/1712635/31638398-3fc08ad8-b288-11e7-879b-fc4df0daad2b.png) + +In this case, this is an unsecured SF cluster with a single Linux node, good for initial tests and getting started with SF. + +## B. Secured cluster (SF Linux cluster) + +Within eShopOnContainers root folder, at the folder [..\deploy\az\servicefabric\LinuxContainers](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/az/servicefabric/LinuxContainers), you can find the ARM template `servicefabricdeploysecured.json` and its parameter file (`servicefabricdeploysecured.parameters.json`) to create a secured Service Fabric cluster environment for Linux Containers (IN THIS CASE, IT IS A SECURED CLUSTER USING A CERTIFICATE). + +The ARM template `servicefabricdeploysecured.json` and its parameter file (`servicefabricdeploysecured.parameters.json`) are used to create a service fabric cluster environment for linux containers secured with a certificate. + +## Create Azure Keyvault service +Go to PortalAzure and create a Keyvault service. Make sure Enable access for deployment checkboxes are selected. + +![image](https://user-images.githubusercontent.com/1712635/31638848-9b266530-b28a-11e7-953b-1e3ec1a54f77.png) + +## Generate a certificate in Azure Keyvault +In a POWER-SHELL window, move to the folder [..\deploy\az\servicefabric\LinuxContainers](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/az/servicefabric/LinuxContainers). + +**Select your Azure subscription** You might have [several Azure subscriptions](https://docs.microsoft.com/en-us/cli/azure/account#set) as shown if you type the following. + + >``` + >az account list + >``` + If you have multiple subscription accounts, you first need to select the Azure subscription account you want to target. Type the following: + >``` + >az account set --subscription "Your Azure Subscription Name or ID" + >``` + +Execute the gen-keyvaultcert.ps1 script to generate and download a certificate from Keyvault. + +``` +.\gen-keyvaultcert.ps1 -vaultName -certName -certPwd -subjectName CN=.westeurope.cloudapp.azure.com -saveDir C:\Users\\Downloads + +``` + +You should see a similar execution to the following: +![image](https://user-images.githubusercontent.com/1712635/31640172-93efcca0-b291-11e7-970e-5b5e6bf07042.png) + +IMPORTANT: At this point, copy/cut the .PFX certificate file saved in the downloads forlder and save it in a secure place. + +## Install the certificate +Install the certificate (by double-clicking on the .PFX file) under 'Current User' store location (by default location) and check it as exportable. + + + +Also, install the same certificate as CA (Certificate Authority) under Current User, too. + +![image](https://user-images.githubusercontent.com/1712635/31642795-c6ffa434-b2a1-11e7-8ff8-2a63549a780e.png) + +## Editing servicefabricdeploysecured.parameters.json file + +Edit the parameters in `servicefabricdeploysecured.parameters.json` in a similar way you can do with the unsecured .json file shown above (clusterName, dnsName, etc.), plus edit the following values: + +- sourceVaultValue: Your Azure Keyvault's RESOURCE ID (check Azure keyvault properties, similar to: /subscriptions/e1234ac1-c09c-3jaf-6767-98b3c5f1f246/resourceGroups/eshop-global-resgrp/providers/Microsoft.KeyVault/vaults/eshopkeyvault") + +- certificateUrlValue: Your certificate Secret Identifier (check Azure Keyvault secret certificate properties, should be in the format of https://.vault.azure.net:443/secrets/, similar to: +https://eshopkeyvault.vault.azure.net/secrets/pro-eshop-sflinux-cluster-cert/fd47684442c04cdj83b3hfe4h8e08123) + +- certificateThumbprint: certificate thumbprint (check azure Keyvault certificate thumbprint, something like 69JK453486D55A6818577Z0699100365HDK70FCE) + +## Deploy the secured SF Linux cluster + +Once parameters file is edited you can deploy it using [create-resources script](../readme.md). +Use a command prompt window positioned into the deploy\az folder. + +``` +create-resources.cmd servicefabric\LinuxContainers\servicefabricdeploysecured pro-eshop-sflinux-resgrp -c westus +``` +The execution should be something like the following: +![image](https://user-images.githubusercontent.com/1712635/31642529-54479704-b2a0-11e7-90ee-2abf32c92205.png) + +Once the cluster is created you can explore it with Azure's portal, like in the following image: + +![image](https://user-images.githubusercontent.com/1712635/31642956-b7cfc8d0-b2a2-11e7-8ede-a141ec190eb4.png) + +## Deploy eShopOnServiceFabric with Visual Studio. + +Modify the cloud.xml file of each Service Fabric application in PublishProfile directory and set your certificate settings to be able to deploy eshopOnContainers in the secured cluster: + + + + + diff --git a/deploy/az/servicefabric/LinuxContainers/servicefabricdeploy.json b/deploy/az/servicefabric/LinuxContainers/servicefabricdeploy.json new file mode 100644 index 000000000..fb28174db --- /dev/null +++ b/deploy/az/servicefabric/LinuxContainers/servicefabricdeploy.json @@ -0,0 +1,751 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterLocation": { + "type": "string", + "metadata": { + "description": "Location of the Cluster" + } + }, + "clusterName": { + "type": "string", + "defaultValue": "Cluster", + "metadata": { + "description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only" + } + }, + "nt0applicationStartPort": { + "type": "int", + "defaultValue": 20000 + }, + "nt0applicationEndPort": { + "type": "int", + "defaultValue": 30000 + }, + "nt0ephemeralStartPort": { + "type": "int", + "defaultValue": 49152 + }, + "nt0ephemeralEndPort": { + "type": "int", + "defaultValue": 65534 + }, + "nt0fabricTcpGatewayPort": { + "type": "int", + "defaultValue": 19000 + }, + "nt0fabricHttpGatewayPort": { + "type": "int", + "defaultValue": 19080 + }, + "webMvcHttpPort": { + "type": "int", + "defaultValue": 5100 + }, + "webSpaHttpPort": { + "type": "int", + "defaultValue": 5104 + }, + "webStatusHttpPort": { + "type": "int", + "defaultValue": 5107 + }, + "IdSrvHttpRule": { + "type": "int", + "defaultValue": 5105 + }, + "BasketApiHttpRule": { + "type": "int", + "defaultValue": 5103 + }, + "CatalogApiHttpRule": { + "type": "int", + "defaultValue": 5101 + }, + "OrderingApiHttpRule": { + "type": "int", + "defaultValue": 5102 + }, + "MarketingApiHttpRule": { + "type": "int", + "defaultValue": 5110 + }, + "LocationsApiHttpRule": { + "type": "int", + "defaultValue": 5109 + }, + "subnet0Name": { + "type": "string", + "defaultValue": "Subnet-0" + }, + "subnet0Prefix": { + "type": "string", + "defaultValue": "10.0.0.0/24" + }, + "computeLocation": { + "type": "string" + }, + "publicIPAddressName": { + "type": "string", + "defaultValue": "PublicIP-VM" + }, + "publicIPAddressType": { + "type": "string", + "allowedValues": [ + "Dynamic" + ], + "defaultValue": "Dynamic" + }, + "vmStorageAccountContainerName": { + "type": "string", + "defaultValue": "vhds" + }, + "adminUserName": { + "type": "string", + "defaultValue": "testadm", + "metadata": { + "description": "Remote desktop user Id" + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Remote desktop user password. Must be a strong password" + } + }, + "virtualNetworkName": { + "type": "string", + "defaultValue": "VNet" + }, + "addressPrefix": { + "type": "string", + "defaultValue": "10.0.0.0/16" + }, + "dnsName": { + "type": "string" + }, + "nicName": { + "type": "string", + "defaultValue": "NIC" + }, + "lbName": { + "type": "string", + "defaultValue": "LoadBalancer" + }, + "lbIPName": { + "type": "string", + "defaultValue": "PublicIP-LB-FE" + }, + "overProvision": { + "type": "string", + "defaultValue": "false" + }, + "vmImagePublisher": { + "type": "string", + "defaultValue": "Microsoft.Azure.ServiceFabric" + }, + "vmImageOffer": { + "type": "string", + "defaultValue": "UbuntuServer" + }, + "vmImageSku": { + "type": "string", + "defaultValue": "16.04" + }, + "vmImageVersion": { + "type": "string", + "defaultValue": "6.0.12" + }, + "storageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the VM image storage account" + } + }, + "supportLogStorageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the support log storage account" + } + }, + "supportLogStorageAccountName": { + "type": "string", + "defaultValue": "[toLower( concat('sflogs', uniqueString(resourceGroup().id),'2'))]", + "metadata": { + "description": "Name for the storage account that contains support logs from the cluster" + } + }, + "applicationDiagnosticsStorageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the application diagnostics storage account" + } + }, + "applicationDiagnosticsStorageAccountName": { + "type": "string", + "defaultValue": "[toLower(concat(uniqueString(resourceGroup().id), '3' ))]", + "metadata": { + "description": "Name for the storage account that contains application diagnostics data from the cluster" + } + }, + "nt0InstanceCount": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "Instance count for node type" + } + }, + "vmNodeType0Name": { + "type": "string", + "defaultValue": "primary", + "maxLength": 9 + }, + "vmNodeType0Size": { + "type": "string", + "defaultValue": "Standard_D1_v2" + } + }, + "variables": { + "vmssApiVersion": "2017-03-30", + "lbApiVersion": "2015-06-15", + "vNetApiVersion": "2015-06-15", + "storageApiVersion": "2016-01-01", + "publicIPApiVersion": "2015-06-15", + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]", + "subnet0Ref": "[concat(variables('vnetID'),'/subnets/',parameters('subnet0Name'))]", + "wadlogs": "", + "wadperfcounters1": "", + "wadperfcounters2": "", + "wadcfgxstart": "[concat(variables('wadlogs'),variables('wadperfcounters1'),variables('wadperfcounters2'),'')]", + "lbID0": "[resourceId('Microsoft.Network/loadBalancers', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "lbIPConfig0": "[concat(variables('lbID0'),'/frontendIPConfigurations/LoadBalancerIPConfig')]", + "lbPoolID0": "[concat(variables('lbID0'),'/backendAddressPools/LoadBalancerBEAddressPool')]", + "lbProbeID0": "[concat(variables('lbID0'),'/probes/FabricGatewayProbe')]", + "lbHttpProbeID0": "[concat(variables('lbID0'),'/probes/FabricHttpGatewayProbe')]", + "lbNatPoolID0": "[concat(variables('lbID0'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]", + "vmStorageAccountName0": "[toLower(concat(uniqueString(resourceGroup().id), '1', '0' ))]", + "wadmetricsresourceid0": "[concat('/subscriptions/',subscription().subscriptionId,'/resourceGroups/',resourceGroup().name ,'/providers/','Microsoft.Compute/virtualMachineScaleSets/', parameters('vmNodeType0Name'))]" + }, + "resources": [ + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('supportLogStorageAccountName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "kind": "Storage", + "sku": { + "name": "[parameters('supportLogStorageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('applicationDiagnosticsStorageAccountName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "kind": "Storage", + "sku": { + "name": "[parameters('applicationDiagnosticsStorageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('vNetApiVersion')]", + "type": "Microsoft.Network/virtualNetworks", + "name": "[parameters('virtualNetworkName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[parameters('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[parameters('subnet0Name')]", + "properties": { + "addressPrefix": "[parameters('subnet0Prefix')]" + } + } + ] + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('publicIPApiVersion')]", + "type": "Microsoft.Network/publicIPAddresses", + "name": "[concat(parameters('lbIPName'),'-','0')]", + "location": "[parameters('computeLocation')]", + "properties": { + "dnsSettings": { + "domainNameLabel": "[parameters('dnsName')]" + }, + "publicIPAllocationMethod": "Dynamic" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('lbApiVersion')]", + "type": "Microsoft.Network/loadBalancers", + "name": "[concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name'))]", + "location": "[parameters('computeLocation')]", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]" + ], + "properties": { + "frontendIPConfigurations": [ + { + "name": "LoadBalancerIPConfig", + "properties": { + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]" + } + } + } + ], + "backendAddressPools": [ + { + "name": "LoadBalancerBEAddressPool", + "properties": {} + } + ], + "loadBalancingRules": [ + { + "name": "LBRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0fabricTcpGatewayPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0fabricTcpGatewayPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "LBHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0fabricHttpGatewayPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0fabricHttpGatewayPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "WebMVCHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webMvcHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webMvcHttpPort')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "WebSPAHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webSpaHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webSpaHttpPort')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "WebStatusHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webStatusHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webStatusHttpPort')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "IdSrvHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('IdSrvHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('IdSrvHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "BasketApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('BasketApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('BasketApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "CatalogApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('CatalogApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('CatalogApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "OrderingApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('OrderingApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('OrderingApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "MarketingApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('MarketingApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('MarketingApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "LocationsApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('LocationsApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('LocationsApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + } + ], + "probes": [ + { + "name": "FabricGatewayProbe", + "properties": { + "intervalInSeconds": 5, + "numberOfProbes": 2, + "port": "[parameters('nt0fabricTcpGatewayPort')]", + "protocol": "tcp" + } + }, + { + "name": "FabricHttpGatewayProbe", + "properties": { + "intervalInSeconds": 5, + "numberOfProbes": 2, + "port": "[parameters('nt0fabricHttpGatewayPort')]", + "protocol": "tcp" + } + } + ], + "inboundNatPools": [ + { + "name": "LoadBalancerBEAddressNatPool", + "properties": { + "backendPort": "22", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPortRangeEnd": "4500", + "frontendPortRangeStart": "3389", + "protocol": "tcp" + } + } + ] + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('vmssApiVersion')]", + "type": "Microsoft.Compute/virtualMachineScaleSets", + "name": "[parameters('vmNodeType0Name')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [ + "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]", + "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('applicationDiagnosticsStorageAccountName'))]" + ], + "properties": { + "overprovision": "[parameters('overProvision')]", + "upgradePolicy": { + "mode": "Automatic" + }, + "virtualMachineProfile": { + "extensionProfile": { + "extensions": [ + { + "name": "[concat(parameters('vmNodeType0Name'),'_ServiceFabricLinuxNode')]", + "properties": { + "type": "ServiceFabricLinuxNode", + "autoUpgradeMinorVersion": true, + "protectedSettings": { + "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key1]", + "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key2]" + }, + "publisher": "Microsoft.Azure.ServiceFabric", + "settings": { + "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]", + "nodeTypeRef": "[parameters('vmNodeType0Name')]", + "durabilityLevel": "Bronze", + "enableParallelJobs": true, + "nicPrefixOverride": "[parameters('subnet0Prefix')]" + }, + "typeHandlerVersion": "1.0" + } + }, + { + "name": "[concat('VMDiagnosticsVmExt','_vmNodeType0Name')]", + "properties": { + "type": "LinuxDiagnostic", + "autoUpgradeMinorVersion": true, + "protectedSettings": { + "storageAccountName": "[parameters('applicationDiagnosticsStorageAccountName')]", + "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]", + "storageAccountEndPoint": "https://core.windows.net/" + }, + "publisher": "Microsoft.OSTCExtensions", + "settings": { + "xmlCfg": "[base64(concat(variables('wadcfgxstart'),variables('wadmetricsresourceid0'),variables('wadcfgxend')))]", + "StorageAccount": "[parameters('applicationDiagnosticsStorageAccountName')]" + }, + "typeHandlerVersion": "2.3" + } + } + ] + }, + "networkProfile": { + "networkInterfaceConfigurations": [ + { + "name": "[concat(parameters('nicName'), '-0')]", + "properties": { + "ipConfigurations": [ + { + "name": "[concat(parameters('nicName'),'-',0)]", + "properties": { + "loadBalancerBackendAddressPools": [ + { + "id": "[variables('lbPoolID0')]" + } + ], + "loadBalancerInboundNatPools": [ + { + "id": "[variables('lbNatPoolID0')]" + } + ], + "subnet": { + "id": "[variables('subnet0Ref')]" + } + } + } + ], + "primary": true + } + } + ] + }, + "osProfile": { + "adminPassword": "[parameters('adminPassword')]", + "adminUsername": "[parameters('adminUsername')]", + "computernamePrefix": "[parameters('vmNodeType0Name')]" + }, + "storageProfile": { + "imageReference": { + "publisher": "[parameters('vmImagePublisher')]", + "offer": "[parameters('vmImageOffer')]", + "sku": "[parameters('vmImageSku')]", + "version": "[parameters('vmImageVersion')]" + }, + "osDisk": { + "caching": "ReadOnly", + "createOption": "FromImage", + "managedDisk": { + "storageAccountType": "[parameters('storageAccountType')]" + } + } + } + } + }, + "sku": { + "name": "[parameters('vmNodeType0Size')]", + "capacity": "[parameters('nt0InstanceCount')]", + "tier": "Standard" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "2017-07-01-preview", + "type": "Microsoft.ServiceFabric/clusters", + "name": "[parameters('clusterName')]", + "location": "[parameters('clusterLocation')]", + "dependsOn": [ + "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]" + ], + "properties": { + "addonFeatures": [ + "DnsService" + ], + "clientCertificateCommonNames": [], + "clientCertificateThumbprints": [], + "clusterCodeVersion": "6.0.120.1", + "clusterState": "Default", + "diagnosticsStorageAccountConfig": { + "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]", + "protectedAccountKeyName": "StorageAccountKey1", + "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]", + "storageAccountName": "[parameters('supportLogStorageAccountName')]", + "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]" + }, + "fabricSettings": [], + "managementEndpoint": "[concat('http://',reference(concat(parameters('lbIPName'),'-','0')).dnsSettings.fqdn,':',parameters('nt0fabricHttpGatewayPort'))]", + "nodeTypes": [ + { + "name": "[parameters('vmNodeType0Name')]", + "applicationPorts": { + "endPort": "[parameters('nt0applicationEndPort')]", + "startPort": "[parameters('nt0applicationStartPort')]" + }, + "clientConnectionEndpointPort": "[parameters('nt0fabricTcpGatewayPort')]", + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": "[parameters('nt0ephemeralEndPort')]", + "startPort": "[parameters('nt0ephemeralStartPort')]" + }, + "httpGatewayEndpointPort": "[parameters('nt0fabricHttpGatewayPort')]", + "isPrimary": true, + "vmInstanceCount": "[parameters('nt0InstanceCount')]" + } + ], + "provisioningState": "Default", + "reliabilityLevel": "None", + "upgradeMode": "Manual", + "vmImage": "Linux" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + } + ], + "outputs": { + "clusterProperties": { + "value": "[reference(parameters('clusterName'))]", + "type": "object" + } + } +} \ No newline at end of file diff --git a/deploy/az/servicefabric/LinuxContainers/servicefabricdeploy.parameters.json b/deploy/az/servicefabric/LinuxContainers/servicefabricdeploy.parameters.json new file mode 100644 index 000000000..0e37d24ec --- /dev/null +++ b/deploy/az/servicefabric/LinuxContainers/servicefabricdeploy.parameters.json @@ -0,0 +1,93 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterName": { + "value": "qa-eshop-sflinux-cluster" + }, + "clusterLocation": { + "value": "westus" + }, + "computeLocation": { + "value": "westus" + }, + "adminUserName": { + "value": "eshop" + }, + "adminPassword": { + "value": "Your_complex_Pass@word1" + }, + "nicName": { + "value": "NIC-eshoponsflin" + }, + "publicIPAddressName": { + "value": "eshoponsflin-PubIP" + }, + "dnsName": { + "value": "qa-eshop-sflinux-cluster" + }, + "virtualNetworkName": { + "value": "VNet-eshoponsflin" + }, + "lbName": { + "value": "LB-eshoponsflin" + }, + "lbIPName": { + "value": "LBIP-eshoponsflin" + }, + "vmImageSku": { + "value": "16.04-LTS" + }, + "vmImageVersion": { + "value": "latest" + }, + "vmImagePublisher": { + "value": "Canonical" + }, + "nt0ephemeralStartPort": { + "value": 49152 + }, + "nt0ephemeralEndPort": { + "value": 65534 + }, + "nt0applicationStartPort": { + "value": 20000 + }, + "nt0applicationEndPort": { + "value": 30000 + }, + "nt0fabricTcpGatewayPort": { + "value": 19000 + }, + "nt0fabricHttpGatewayPort": { + "value": 19080 + }, + "webMvcHttpPort": { + "value": 5100 + }, + "webSpaHttpPort": { + "value": 5104 + }, + "webStatusHttpPort": { + "value": 5107 + }, + "IdSrvHttpRule": { + "value": 5105 + }, + "BasketApiHttpRule": { + "value": 5103 + }, + "CatalogApiHttpRule": { + "value": 5101 + }, + "OrderingApiHttpRule": { + "value": 5102 + }, + "MarketingApiHttpRule": { + "value": 5110 + }, + "LocationsApiHttpRule": { + "value": 5109 + } + } +} \ No newline at end of file diff --git a/deploy/az/servicefabric/LinuxContainers/servicefabricdeploysecured.json b/deploy/az/servicefabric/LinuxContainers/servicefabricdeploysecured.json new file mode 100644 index 000000000..0d6620f32 --- /dev/null +++ b/deploy/az/servicefabric/LinuxContainers/servicefabricdeploysecured.json @@ -0,0 +1,821 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterLocation": { + "type": "string", + "metadata": { + "description": "Location of the Cluster" + } + }, + "clusterName": { + "type": "string", + "defaultValue": "Cluster", + "metadata": { + "description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only" + } + }, + "nt0applicationStartPort": { + "type": "int", + "defaultValue": 20000 + }, + "nt0applicationEndPort": { + "type": "int", + "defaultValue": 30000 + }, + "nt0ephemeralStartPort": { + "type": "int", + "defaultValue": 49152 + }, + "nt0ephemeralEndPort": { + "type": "int", + "defaultValue": 65534 + }, + "nt0fabricTcpGatewayPort": { + "type": "int", + "defaultValue": 19000 + }, + "nt0fabricHttpGatewayPort": { + "type": "int", + "defaultValue": 19080 + }, + "webMvcHttpPort": { + "type": "int", + "defaultValue": 5100 + }, + "webSpaHttpPort": { + "type": "int", + "defaultValue": 5104 + }, + "webStatusHttpPort": { + "type": "int", + "defaultValue": 5107 + }, + "IdSrvHttpRule": { + "type": "int", + "defaultValue": 5105 + }, + "BasketApiHttpRule": { + "type": "int", + "defaultValue": 5103 + }, + "CatalogApiHttpRule": { + "type": "int", + "defaultValue": 5101 + }, + "OrderingApiHttpRule": { + "type": "int", + "defaultValue": 5102 + }, + "MarketingApiHttpRule": { + "type": "int", + "defaultValue": 5110 + }, + "LocationsApiHttpRule": { + "type": "int", + "defaultValue": 5109 + }, + "subnet0Name": { + "type": "string", + "defaultValue": "Subnet-0" + }, + "subnet0Prefix": { + "type": "string", + "defaultValue": "10.0.0.0/24" + }, + "computeLocation": { + "type": "string" + }, + "publicIPAddressName": { + "type": "string", + "defaultValue": "PublicIP-VM" + }, + "publicIPAddressType": { + "type": "string", + "allowedValues": [ + "Dynamic" + ], + "defaultValue": "Dynamic" + }, + "vmStorageAccountContainerName": { + "type": "string", + "defaultValue": "vhds" + }, + "adminUserName": { + "type": "string", + "defaultValue": "testadm", + "metadata": { + "description": "Remote desktop user Id" + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Remote desktop user password. Must be a strong password" + } + }, + "virtualNetworkName": { + "type": "string", + "defaultValue": "VNet" + }, + "addressPrefix": { + "type": "string", + "defaultValue": "10.0.0.0/16" + }, + "dnsName": { + "type": "string" + }, + "nicName": { + "type": "string", + "defaultValue": "NIC" + }, + "lbName": { + "type": "string", + "defaultValue": "LoadBalancer" + }, + "lbIPName": { + "type": "string", + "defaultValue": "PublicIP-LB-FE" + }, + "overProvision": { + "type": "string", + "defaultValue": "false" + }, + "vmImagePublisher": { + "type": "string", + "defaultValue": "Microsoft.Azure.ServiceFabric" + }, + "vmImageOffer": { + "type": "string", + "defaultValue": "UbuntuServer" + }, + "vmImageSku": { + "type": "string", + "defaultValue": "16.04" + }, + "vmImageVersion": { + "type": "string", + "defaultValue": "6.0.12" + }, + "clusterProtectionLevel": { + "type": "string", + "allowedValues": [ + "None", + "Sign", + "EncryptAndSign" + ], + "defaultValue": "EncryptAndSign", + "metadata": { + "description": "Protection level.Three values are allowed - EncryptAndSign, Sign, None. It is best to keep the default of EncryptAndSign, unless you have a need not to" + } + }, + "certificateStoreValue": { + "type": "string", + "allowedValues": [ + "My" + ], + "defaultValue": "My", + "metadata": { + "description": "The store name where the cert will be deployed in the virtual machine" + } + }, + "certificateThumbprint": { + "type": "string", + "metadata": { + "description": "Certificate Thumbprint" + } + }, + "sourceVaultValue": { + "type": "string", + "metadata": { + "description": "Resource Id of the key vault, is should be in the format of /subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/" + } + }, + "certificateUrlValue": { + "type": "string", + "metadata": { + "description": "Refers to the location URL in your key vault where the certificate was uploaded, it is should be in the format of https://.vault.azure.net:443/secrets/" + } + }, + "storageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the VM image storage account" + } + }, + "supportLogStorageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the support log storage account" + } + }, + "supportLogStorageAccountName": { + "type": "string", + "defaultValue": "[toLower( concat('sflogs', uniqueString(resourceGroup().id),'2'))]", + "metadata": { + "description": "Name for the storage account that contains support logs from the cluster" + } + }, + "applicationDiagnosticsStorageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the application diagnostics storage account" + } + }, + "applicationDiagnosticsStorageAccountName": { + "type": "string", + "defaultValue": "[toLower(concat(uniqueString(resourceGroup().id), '3' ))]", + "metadata": { + "description": "Name for the storage account that contains application diagnostics data from the cluster" + } + }, + "nt0InstanceCount": { + "type": "int", + "defaultValue": 5, + "metadata": { + "description": "Instance count for node type" + } + }, + "vmNodeType0Name": { + "type": "string", + "defaultValue": "primary", + "maxLength": 9 + }, + "vmNodeType0Size": { + "type": "string", + "defaultValue": "Standard_D1_v2" + } + }, + "variables": { + "vmssApiVersion": "2017-03-30", + "lbApiVersion": "2015-06-15", + "vNetApiVersion": "2015-06-15", + "storageApiVersion": "2016-01-01", + "publicIPApiVersion": "2015-06-15", + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]", + "subnet0Ref": "[concat(variables('vnetID'),'/subnets/',parameters('subnet0Name'))]", + "wadlogs": "", + "wadperfcounters1": "", + "wadperfcounters2": "", + "wadcfgxstart": "[concat(variables('wadlogs'),variables('wadperfcounters1'),variables('wadperfcounters2'),'')]", + "lbID0": "[resourceId('Microsoft.Network/loadBalancers', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "lbIPConfig0": "[concat(variables('lbID0'),'/frontendIPConfigurations/LoadBalancerIPConfig')]", + "lbPoolID0": "[concat(variables('lbID0'),'/backendAddressPools/LoadBalancerBEAddressPool')]", + "lbProbeID0": "[concat(variables('lbID0'),'/probes/FabricGatewayProbe')]", + "lbHttpProbeID0": "[concat(variables('lbID0'),'/probes/FabricHttpGatewayProbe')]", + "lbNatPoolID0": "[concat(variables('lbID0'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]", + "vmStorageAccountName0": "[toLower(concat(uniqueString(resourceGroup().id), '1', '0' ))]", + "wadmetricsresourceid0": "[concat('/subscriptions/',subscription().subscriptionId,'/resourceGroups/',resourceGroup().name ,'/providers/','Microsoft.Compute/virtualMachineScaleSets/', parameters('vmNodeType0Name'))]" + }, + "resources": [ + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('supportLogStorageAccountName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "kind": "Storage", + "sku": { + "name": "[parameters('supportLogStorageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('applicationDiagnosticsStorageAccountName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "kind": "Storage", + "sku": { + "name": "[parameters('applicationDiagnosticsStorageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('vNetApiVersion')]", + "type": "Microsoft.Network/virtualNetworks", + "name": "[parameters('virtualNetworkName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[parameters('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[parameters('subnet0Name')]", + "properties": { + "addressPrefix": "[parameters('subnet0Prefix')]" + } + } + ] + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('publicIPApiVersion')]", + "type": "Microsoft.Network/publicIPAddresses", + "name": "[concat(parameters('lbIPName'),'-','0')]", + "location": "[parameters('computeLocation')]", + "properties": { + "dnsSettings": { + "domainNameLabel": "[parameters('dnsName')]" + }, + "publicIPAllocationMethod": "Dynamic" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('lbApiVersion')]", + "type": "Microsoft.Network/loadBalancers", + "name": "[concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name'))]", + "location": "[parameters('computeLocation')]", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]" + ], + "properties": { + "frontendIPConfigurations": [ + { + "name": "LoadBalancerIPConfig", + "properties": { + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]" + } + } + } + ], + "backendAddressPools": [ + { + "name": "LoadBalancerBEAddressPool", + "properties": {} + } + ], + "loadBalancingRules": [ + { + "name": "LBRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0fabricTcpGatewayPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0fabricTcpGatewayPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "LBHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0fabricHttpGatewayPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0fabricHttpGatewayPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "WebMVCHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webMvcHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webMvcHttpPort')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "WebSPAHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webSpaHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webSpaHttpPort')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "WebStatusHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webStatusHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webStatusHttpPort')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "IdSrvHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('IdSrvHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('IdSrvHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "BasketApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('BasketApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('BasketApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "CatalogApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('CatalogApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('CatalogApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "OrderingApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('OrderingApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('OrderingApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "MarketingApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('MarketingApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('MarketingApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "LocationsApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('LocationsApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('LocationsApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + } + ], + "probes": [ + { + "name": "FabricGatewayProbe", + "properties": { + "intervalInSeconds": 5, + "numberOfProbes": 2, + "port": "[parameters('nt0fabricTcpGatewayPort')]", + "protocol": "tcp" + } + }, + { + "name": "FabricHttpGatewayProbe", + "properties": { + "intervalInSeconds": 5, + "numberOfProbes": 2, + "port": "[parameters('nt0fabricHttpGatewayPort')]", + "protocol": "tcp" + } + } + ], + "inboundNatPools": [ + { + "name": "LoadBalancerBEAddressNatPool", + "properties": { + "backendPort": "22", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPortRangeEnd": "4500", + "frontendPortRangeStart": "3389", + "protocol": "tcp" + } + } + ] + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('vmssApiVersion')]", + "type": "Microsoft.Compute/virtualMachineScaleSets", + "name": "[parameters('vmNodeType0Name')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [ + "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]", + "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('applicationDiagnosticsStorageAccountName'))]" + ], + "properties": { + "overprovision": "[parameters('overProvision')]", + "upgradePolicy": { + "mode": "Automatic" + }, + "virtualMachineProfile": { + "extensionProfile": { + "extensions": [ + { + "name": "[concat(parameters('vmNodeType0Name'),'_ServiceFabricLinuxNode')]", + "properties": { + "type": "ServiceFabricLinuxNode", + "autoUpgradeMinorVersion": true, + "protectedSettings": { + "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key1]", + "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key2]" + }, + "publisher": "Microsoft.Azure.ServiceFabric", + "settings": { + "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]", + "nodeTypeRef": "[parameters('vmNodeType0Name')]", + "durabilityLevel": "Bronze", + "enableParallelJobs": true, + "nicPrefixOverride": "[parameters('subnet0Prefix')]", + "certificate": { + "thumbprint": "[parameters('certificateThumbprint')]", + "x509StoreName": "[parameters('certificateStoreValue')]" + } + }, + "typeHandlerVersion": "1.0" + } + }, + { + "name": "[concat('VMDiagnosticsVmExt','_vmNodeType0Name')]", + "properties": { + "type": "LinuxDiagnostic", + "autoUpgradeMinorVersion": true, + "protectedSettings": { + "storageAccountName": "[parameters('applicationDiagnosticsStorageAccountName')]", + "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]", + "storageAccountEndPoint": "https://core.windows.net/" + }, + "publisher": "Microsoft.OSTCExtensions", + "settings": { + "xmlCfg": "[base64(concat(variables('wadcfgxstart'),variables('wadmetricsresourceid0'),variables('wadcfgxend')))]", + "StorageAccount": "[parameters('applicationDiagnosticsStorageAccountName')]" + }, + "typeHandlerVersion": "2.3" + } + } + ] + }, + "networkProfile": { + "networkInterfaceConfigurations": [ + { + "name": "[concat(parameters('nicName'), '-0')]", + "properties": { + "ipConfigurations": [ + { + "name": "[concat(parameters('nicName'),'-',0)]", + "properties": { + "loadBalancerBackendAddressPools": [ + { + "id": "[variables('lbPoolID0')]" + } + ], + "loadBalancerInboundNatPools": [ + { + "id": "[variables('lbNatPoolID0')]" + } + ], + "subnet": { + "id": "[variables('subnet0Ref')]" + } + } + } + ], + "primary": true + } + } + ] + }, + "osProfile": { + "adminPassword": "[parameters('adminPassword')]", + "adminUsername": "[parameters('adminUsername')]", + "computernamePrefix": "[parameters('vmNodeType0Name')]", + "secrets": [ + { + "sourceVault": { + "id": "[parameters('sourceVaultValue')]" + }, + "vaultCertificates": [ + { + "certificateUrl": "[parameters('certificateUrlValue')]" + } + ] + } + ] + }, + "storageProfile": { + "imageReference": { + "publisher": "[parameters('vmImagePublisher')]", + "offer": "[parameters('vmImageOffer')]", + "sku": "[parameters('vmImageSku')]", + "version": "[parameters('vmImageVersion')]" + }, + "osDisk": { + "caching": "ReadOnly", + "createOption": "FromImage", + "managedDisk": { + "storageAccountType": "[parameters('storageAccountType')]" + } + } + } + } + }, + "sku": { + "name": "[parameters('vmNodeType0Size')]", + "capacity": "[parameters('nt0InstanceCount')]", + "tier": "Standard" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "2017-07-01-preview", + "type": "Microsoft.ServiceFabric/clusters", + "name": "[parameters('clusterName')]", + "location": "[parameters('clusterLocation')]", + "dependsOn": [ + "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]" + ], + "properties": { + "addonFeatures": [ + "DnsService" + ], + "certificate": { + "thumbprint": "[parameters('certificateThumbprint')]", + "x509StoreName": "[parameters('certificateStoreValue')]" + }, + "clientCertificateCommonNames": [], + "clientCertificateThumbprints": [], + "clusterCodeVersion": "6.0.120.1", + "clusterState": "Default", + "diagnosticsStorageAccountConfig": { + "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]", + "protectedAccountKeyName": "StorageAccountKey1", + "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]", + "storageAccountName": "[parameters('supportLogStorageAccountName')]", + "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]" + }, + "fabricSettings": [ + { + "parameters": [ + { + "name": "ClusterProtectionLevel", + "value": "[parameters('clusterProtectionLevel')]" + } + ], + "name": "Security" + } + ], + "managementEndpoint": "[concat('https://',reference(concat(parameters('lbIPName'),'-','0')).dnsSettings.fqdn,':',parameters('nt0fabricHttpGatewayPort'))]", + "nodeTypes": [ + { + "name": "[parameters('vmNodeType0Name')]", + "applicationPorts": { + "endPort": "[parameters('nt0applicationEndPort')]", + "startPort": "[parameters('nt0applicationStartPort')]" + }, + "clientConnectionEndpointPort": "[parameters('nt0fabricTcpGatewayPort')]", + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": "[parameters('nt0ephemeralEndPort')]", + "startPort": "[parameters('nt0ephemeralStartPort')]" + }, + "httpGatewayEndpointPort": "[parameters('nt0fabricHttpGatewayPort')]", + "isPrimary": true, + "vmInstanceCount": "[parameters('nt0InstanceCount')]" + } + ], + "provisioningState": "Default", + "reliabilityLevel": "Silver", + "upgradeMode": "Manual", + "vmImage": "Linux" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + } + ], + "outputs": { + "clusterProperties": { + "value": "[reference(parameters('clusterName'))]", + "type": "object" + } + } +} \ No newline at end of file diff --git a/deploy/az/servicefabric/LinuxContainers/servicefabricdeploysecured.parameters.json b/deploy/az/servicefabric/LinuxContainers/servicefabricdeploysecured.parameters.json new file mode 100644 index 000000000..65875cb31 --- /dev/null +++ b/deploy/az/servicefabric/LinuxContainers/servicefabricdeploysecured.parameters.json @@ -0,0 +1,102 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterName": { + "value": "pro-eshop-sflinux-cluster" + }, + "clusterLocation": { + "value": "westus" + }, + "computeLocation": { + "value": "westus" + }, + "adminUserName": { + "value": "eshop" + }, + "adminPassword": { + "value": "Pass@word1" + }, + "nicName": { + "value": "NIC-eshopsflinsec" + }, + "publicIPAddressName": { + "value": "eshopsflinsec-PubIP" + }, + "dnsName": { + "value": "pro-eshop-sflinux-cluster" + }, + "virtualNetworkName": { + "value": "VNet-eshopsflin" + }, + "lbName": { + "value": "LB-eshopsflin" + }, + "lbIPName": { + "value": "LBIP-eshopsflin" + }, + "sourceVaultValue": { + "value": "your-value-check-keyvault-at-azure" + }, + "certificateUrlValue": { + "value": "your-value-check-keyvault-at-azure" + }, + "certificateThumbprint": { + "value": "your-value-check-keyvault-at-azure" + }, + "vmImageSku": { + "value": "16.04-LTS" + }, + "vmImageVersion": { + "value": "latest" + }, + "vmImagePublisher": { + "value": "Canonical" + }, + "nt0ephemeralStartPort": { + "value": 49152 + }, + "nt0ephemeralEndPort": { + "value": 65534 + }, + "nt0applicationStartPort": { + "value": 20000 + }, + "nt0applicationEndPort": { + "value": 30000 + }, + "nt0fabricTcpGatewayPort": { + "value": 19000 + }, + "nt0fabricHttpGatewayPort": { + "value": 19080 + }, + "webMvcHttpPort": { + "value": 5100 + }, + "webSpaHttpPort": { + "value": 5104 + }, + "webStatusHttpPort": { + "value": 5107 + }, + "IdSrvHttpRule": { + "value": 5105 + }, + "BasketApiHttpRule": { + "value": 5103 + }, + "CatalogApiHttpRule": { + "value": 5101 + }, + "OrderingApiHttpRule": { + "value": 5102 + }, + "MarketingApiHttpRule": { + "value": 5110 + }, + "LocationsApiHttpRule": { + "value": 5109 + } + } +} \ No newline at end of file diff --git a/deploy/az/servicefabric/WindowsContainers/gen-keyvaultcert.ps1 b/deploy/az/servicefabric/WindowsContainers/gen-keyvaultcert.ps1 new file mode 100644 index 000000000..c6fc34013 --- /dev/null +++ b/deploy/az/servicefabric/WindowsContainers/gen-keyvaultcert.ps1 @@ -0,0 +1,53 @@ +Param( + [parameter(Mandatory=$true)][string]$vaultName, + [parameter(Mandatory=$true)][string]$certName, + [parameter(Mandatory=$true)][string]$certPwd, + [parameter(Mandatory=$true)][string]$subjectName, + [parameter(Mandatory=$false)][string]$ValidityInMonths=12, + [parameter(Mandatory=$true)][string]$saveDir +) + + +#Log in Azure Account +Login-AzureRmAccount + + +# Create Cert in KeyVault +Write-Host "Creating certificate in Azure KeyVault..." -ForegroundColor Yellow +$policy = New-AzureKeyVaultCertificatePolicy -SubjectName $subjectName -IssuerName Self -ValidityInMonths $ValidityInMonths +Add-AzureKeyVaultCertificate -VaultName $vaultName -Name $certName -CertificatePolicy $policy + +# Downloading Certificate +Write-Host "Downloading Certificate from KeyVault..." -ForegroundColor Yellow + +$Stoploop = $false +$Retrycount = 0 + +do { + try { + + $kvSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certName -ErrorAction SilentlyContinue + $kvSecretBytes = [System.Convert]::FromBase64String($kvSecret.SecretValueText) + $certCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection + $certCollection.Import($kvSecretBytes,$null,[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable) + $protectedCertificateBytes = $certCollection.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $certPwd) + [System.IO.File]::WriteAllBytes($saveDir + "\" + $certName + ".pfx", $protectedCertificateBytes) + + $Stoploop = $true + Write-Host "Finished!" -ForegroundColor Yellow + } + catch { + if ($Retrycount -gt 5){ + $Stoploop = $true + Write-Host "Not possible to retrieve the certificate!" -ForegroundColor Yellow + } + else { + Start-Sleep -Seconds 20 + $Retrycount = $Retrycount + 1 + } + } +} +While ($Stoploop -eq $false) + +# Show Certificate Values +Get-AzureKeyVaultCertificate -VaultName $vaultName -Name $certName \ No newline at end of file diff --git a/deploy/az/servicefabric/WindowsContainers/readme.md b/deploy/az/servicefabric/WindowsContainers/readme.md new file mode 100644 index 000000000..18aa8ad78 --- /dev/null +++ b/deploy/az/servicefabric/WindowsContainers/readme.md @@ -0,0 +1,138 @@ +# Deploying a Service Fabric cluster based on Windows nodes + +## A. Unsecured cluster (SF Windows cluster) +For a secured cluster, see option B. below. + +You can always deploy a SF cluster through the Azure portal, as explained in this article: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-get-started-azure-cluster + +However, when creating a cluster, there are quite a few configurations to take into account, like enabling the internal DNS service or Reverse Proxy service, choosing between Linux/Windows, open/publish your application ports in the load-balancer and most of all (the most complex setup) how to create a secure cluster. + +Because of those reasons, we have created a set of ARM templates and scripts so you can create, re-create and configure the SF clusters much faster, as explained below: + +Within eShopOnContainers root folder, at the folder [..\deploy\az\servicefabric\WindowsContainers](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/az/servicefabric/WindowsContainers), you can find the ARM template `servicefabricdeploy.json` and its parameters file (`servicefabricdeploy.parameters.json`) to create a Service Fabric cluster environment for Windows Containers (NOT SECURED CLUSTER). + +## Edit the servicefabricdeploy.parameters.json file + +Edit the following params in `servicefabricdeploy.parameters.json` file to set your values: + +- clusterName: Name of your SF cluster +- clusterLocation: Datacenter location, like westus or westeurope +- computeLocation: Datacenter location, like westus or westeurope +- adminUserName: user-name for VMs administration +- adminPassword: user-password for VMs administration +- dnsName: Name assigned to your SF dns + +Optionally, you could modify which ports are opened in the LoadBalancer for the multiple eShopOnContainer apps and API services. +By default, they are setup as: +- webMvcHttpPort: 5100 +- webSpaHttpPort: 5104 +- webStatusHttpPort: 5107 +- IdSrvHttpRule: 5105 +- BasketApiHttpRule: 5103 +- CatalogApiHttpRule: 5101 +- OrderingApiHttpRule: 5102 +- MarketingApiHttpRule: 5110 +- LocationsApiHttpRule: 5109 + +## Deploy the Service Fabric cluster using the script and ARM templates + +Once parameter file is edited you can deploy it using [create-resources script](../readme.md). + +For example, to deploy the cluster to a new resourcegroup located in westus, using the Command Prompt, go to `deploy\az` folder and type: +``` +create-resources.cmd servicefabric\WindowsContainers\servicefabricdeploy qa-eshop-sfwin-resgrp -c westus +``` + +You should see a similar execution to the following: +![image](https://user-images.githubusercontent.com/1712635/31638979-4881d7aa-b28b-11e7-873c-e1185043a9eb.png) + +Now, if you go to your subscription in Azure, you should be able to see the SF cluster already created and available, like in the following image: + +![image](https://user-images.githubusercontent.com/1712635/31639043-9b26c786-b28b-11e7-8d59-eeea97f74176.png) + +In this case, this is an unsecured SF cluster with a single Windows node, good for initial tests and getting started with SF. + + +## B. Secured cluster (SF Windows cluster) + +Within eShopOnContainers root folder, at the folder [..\deploy\az\servicefabric\WindowsContainers](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/az/servicefabric/WindowsContainers), you can find the ARM template `servicefabricdeploysecured.json` and its parameter file (`servicefabricdeploysecured.parameters.json`) to create a secured Service Fabric cluster environment for Windows Containers (IN THIS CASE, IT IS A SECURED CLUSTER USING A CERTIFICATE). + +## Create Azure Keyvault service +Go to PortalAzure and create a Keyvault service. Make sure Enable access for deployment checkboxes are selected. + +![image](https://user-images.githubusercontent.com/1712635/31638848-9b266530-b28a-11e7-953b-1e3ec1a54f77.png) + +## Generate a certificate in Azure Keyvault +In a POWER-SHELL window, move to the folder [..\deploy\az\servicefabric\WindowsContainers](https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/az/servicefabric/WindowsContainers). + +**Select your Azure subscription** You might have [several Azure subscriptions](https://docs.microsoft.com/en-us/cli/azure/account#set) as shown if you type the following. + + >``` + >az account list + >``` + If you have multiple subscription accounts, you first need to select the Azure subscription account you want to target. Type the following: + >``` + >az account set --subscription "Your Azure Subscription Name or ID" + >``` + +**Execute the gen-keyvaultcert.ps1 script** to generate and download a certificate from Keyvault. +Make sure you're going to run it against the Azure subscription you mean it. + +You might need to authenticate from the browser when running this PowerShell script. + +``` +.\gen-keyvaultcert.ps1 -vaultName -certName -certPwd -subjectName CN=.westus.cloudapp.azure.com -saveDir C:\Users\\Downloads + +``` +You should see a similar execution to the following: +![image](https://user-images.githubusercontent.com/1712635/31640172-93efcca0-b291-11e7-970e-5b5e6bf07042.png) + +IMPORTANT: At this point, copy/cut the .PFX certificate file saved in the downloads forlder and save it in a secure place. + +## Install the certificate +Install the certificate (by double-clicking on the .PFX file) under 'Current User' store location (by default location) and check it as exportable. + + + +Also, install the same certificate as CA (Certificate Authority) under Current User, too. + +![image](https://user-images.githubusercontent.com/1712635/31642795-c6ffa434-b2a1-11e7-8ff8-2a63549a780e.png) + +## Editing servicefabricdeploysecured.parameters.json file + +Edit the parameters in `servicefabricdeploysecured.parameters.json` in a similar way you can do with the unsecured .json file shown above (clusterName, dnsName, etc.), plus edit the following values: + +- sourceVaultValue: Your Azure Keyvault's RESOURCE ID (check Azure keyvault properties, similar to: /subscriptions/e1234ac1-c09c-3jaf-6767-98b3c5f1f246/resourceGroups/eshop-global-resgrp/providers/Microsoft.KeyVault/vaults/eshopkeyvault") + +- certificateUrlValue: Your certificate Secret Identifier (check Azure Keyvault secret certificate properties, should be in the format of https://.vault.azure.net:443/secrets/, similar to: +https://eshopkeyvault.vault.azure.net/secrets/pro-eshop-sfwin-cluster-cert/w647684642cGE2sj83b3hfe4h8e08963) + +- certificateThumbprint: certificate thumbprint (check azure Keyvault certificate thumbprint, something like 88JK453486D55A6818573G0DW9100365HDK70HDK) + +## Deploy the secured SF cluster (Windows nodes) + +Once parameters file is edited you can deploy it using [create-resources script](../readme.md). + +Use a command prompt window positioned into the deploy\az folder. + +``` +create-resources.cmd servicefabric\WindowsContainers\servicefabricdeploysecured pro-eshop-sfwin-resgrp -c westus +``` +The execution should be something like the following: + +![image](https://user-images.githubusercontent.com/1712635/31641955-0bc9d59e-b29d-11e7-9230-5ba02843d98a.png) + +Once the cluster is created you can explore it with Azure's portal, like in the following image: +![image](https://user-images.githubusercontent.com/1712635/31642431-bf1c409e-b29f-11e7-980f-a7685a45108c.png) + +In this case, the ARM template is creating a 5 node cluster when creating a SECURE cluster for "production". + + +# Deploy eShopOnServiceFabric with Visual Studio. + +Modify the cloud.xml file of each Service Fabric application in PublishProfile directory and set your certificate settings to be able to deploy eshopOnContainers in the secured cluster: + + + + + diff --git a/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.json b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.json new file mode 100644 index 000000000..073dc9653 --- /dev/null +++ b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.json @@ -0,0 +1,853 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterLocation": { + "type": "string", + "metadata": { + "description": "Location of the Cluster" + } + }, + "clusterName": { + "type": "string", + "defaultValue": "Cluster", + "metadata": { + "description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only" + } + }, + "nt0applicationStartPort": { + "type": "int", + "defaultValue": 20000 + }, + "nt0applicationEndPort": { + "type": "int", + "defaultValue": 30000 + }, + "nt0ephemeralStartPort": { + "type": "int", + "defaultValue": 49152 + }, + "nt0ephemeralEndPort": { + "type": "int", + "defaultValue": 65534 + }, + "nt0fabricTcpGatewayPort": { + "type": "int", + "defaultValue": 19000 + }, + "nt0fabricHttpGatewayPort": { + "type": "int", + "defaultValue": 19080 + }, + "nt0reverseProxyEndpointPort": { + "type": "int", + "defaultValue": 19081 + }, + "webMvcHttpPort": { + "type": "int", + "defaultValue": 5100 + }, + "webSpaHttpPort": { + "type": "int", + "defaultValue": 5104 + }, + "webStatusHttpPort": { + "type": "int", + "defaultValue": 5107 + }, + "IdSrvHttpRule": { + "type": "int", + "defaultValue": 5105 + }, + "BasketApiHttpRule": { + "type": "int", + "defaultValue": 5103 + }, + "CatalogApiHttpRule": { + "type": "int", + "defaultValue": 5101 + }, + "OrderingApiHttpRule": { + "type": "int", + "defaultValue": 5102 + }, + "MarketingApiHttpRule": { + "type": "int", + "defaultValue": 5110 + }, + "LocationsApiHttpRule": { + "type": "int", + "defaultValue": 5109 + }, + "subnet0Name": { + "type": "string", + "defaultValue": "Subnet-0" + }, + "subnet0Prefix": { + "type": "string", + "defaultValue": "10.0.0.0/24" + }, + "computeLocation": { + "type": "string" + }, + "publicIPAddressName": { + "type": "string", + "defaultValue": "PublicIP-VM" + }, + "publicIPAddressType": { + "type": "string", + "allowedValues": [ + "Dynamic" + ], + "defaultValue": "Dynamic" + }, + "vmStorageAccountContainerName": { + "type": "string", + "defaultValue": "vhds" + }, + "adminUserName": { + "type": "string", + "defaultValue": "testadm", + "metadata": { + "description": "Remote desktop user Id" + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Remote desktop user password. Must be a strong password" + } + }, + "virtualNetworkName": { + "type": "string", + "defaultValue": "VNet" + }, + "addressPrefix": { + "type": "string", + "defaultValue": "10.0.0.0/16" + }, + "dnsName": { + "type": "string" + }, + "nicName": { + "type": "string", + "defaultValue": "NIC" + }, + "lbName": { + "type": "string", + "defaultValue": "LoadBalancer" + }, + "lbIPName": { + "type": "string", + "defaultValue": "PublicIP-LB-FE" + }, + "overProvision": { + "type": "string", + "defaultValue": "false" + }, + "vmImagePublisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsServer" + }, + "vmImageOffer": { + "type": "string", + "defaultValue": "WindowsServer" + }, + "vmImageSku": { + "type": "string", + "defaultValue": "2012-R2-Datacenter" + }, + "vmImageVersion": { + "type": "string", + "defaultValue": "latest" + }, + "storageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the VM image storage account" + } + }, + "supportLogStorageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the support log storage account" + } + }, + "supportLogStorageAccountName": { + "type": "string", + "defaultValue": "[toLower( concat('sflogs', uniqueString(resourceGroup().id),'2'))]", + "metadata": { + "description": "Name for the storage account that contains support logs from the cluster" + } + }, + "applicationDiagnosticsStorageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the application diagnostics storage account" + } + }, + "applicationDiagnosticsStorageAccountName": { + "type": "string", + "defaultValue": "[toLower(concat(uniqueString(resourceGroup().id), '3' ))]", + "metadata": { + "description": "Name for the storage account that contains application diagnostics data from the cluster" + } + }, + "nt0InstanceCount": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "Instance count for node type" + } + }, + "vmNodeType0Name": { + "type": "string", + "defaultValue": "primary", + "maxLength": 9 + }, + "vmNodeType0Size": { + "type": "string", + "defaultValue": "Standard_D2_v2" + } + }, + "variables": { + "vmssApiVersion": "2017-03-30", + "lbApiVersion": "2015-06-15", + "vNetApiVersion": "2015-06-15", + "storageApiVersion": "2016-01-01", + "publicIPApiVersion": "2015-06-15", + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]", + "subnet0Ref": "[concat(variables('vnetID'),'/subnets/',parameters('subnet0Name'))]", + "lbID0": "[resourceId('Microsoft.Network/loadBalancers', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "lbIPConfig0": "[concat(variables('lbID0'),'/frontendIPConfigurations/LoadBalancerIPConfig')]", + "lbPoolID0": "[concat(variables('lbID0'),'/backendAddressPools/LoadBalancerBEAddressPool')]", + "lbProbeID0": "[concat(variables('lbID0'),'/probes/FabricGatewayProbe')]", + "lbHttpProbeID0": "[concat(variables('lbID0'),'/probes/FabricHttpGatewayProbe')]", + "lbNatPoolID0": "[concat(variables('lbID0'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]", + "vmStorageAccountName0": "[toLower(concat(uniqueString(resourceGroup().id), '1', '0' ))]", + "uniqueStringArray0": [ + "[concat(variables('vmStorageAccountName0'), '0')]", + "[concat(variables('vmStorageAccountName0'), '1')]", + "[concat(variables('vmStorageAccountName0'), '2')]", + "[concat(variables('vmStorageAccountName0'), '3')]", + "[concat(variables('vmStorageAccountName0'), '4')]" + ] + }, + "resources": [ + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('supportLogStorageAccountName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "kind": "Storage", + "sku": { + "name": "[parameters('supportLogStorageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('applicationDiagnosticsStorageAccountName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "kind": "Storage", + "sku": { + "name": "[parameters('applicationDiagnosticsStorageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('vNetApiVersion')]", + "type": "Microsoft.Network/virtualNetworks", + "name": "[parameters('virtualNetworkName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[parameters('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[parameters('subnet0Name')]", + "properties": { + "addressPrefix": "[parameters('subnet0Prefix')]" + } + } + ] + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('publicIPApiVersion')]", + "type": "Microsoft.Network/publicIPAddresses", + "name": "[concat(parameters('lbIPName'),'-','0')]", + "location": "[parameters('computeLocation')]", + "properties": { + "dnsSettings": { + "domainNameLabel": "[parameters('dnsName')]" + }, + "publicIPAllocationMethod": "Dynamic" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('lbApiVersion')]", + "type": "Microsoft.Network/loadBalancers", + "name": "[concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name'))]", + "location": "[parameters('computeLocation')]", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]" + ], + "properties": { + "frontendIPConfigurations": [ + { + "name": "LoadBalancerIPConfig", + "properties": { + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]" + } + } + } + ], + "backendAddressPools": [ + { + "name": "LoadBalancerBEAddressPool", + "properties": {} + } + ], + "loadBalancingRules": [ + { + "name": "LBRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0fabricTcpGatewayPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0fabricTcpGatewayPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "LBHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0fabricHttpGatewayPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0fabricHttpGatewayPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "ReverseProxyHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0reverseProxyEndpointPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0reverseProxyEndpointPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "WebMVCHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webMvcHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webMvcHttpPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "WebSPAHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webSpaHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webSpaHttpPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "WebStatusHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webStatusHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webStatusHttpPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "IdSrvHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('IdSrvHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('IdSrvHttpRule')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "BasketApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('BasketApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('BasketApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "CatalogApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('CatalogApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('CatalogApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "OrderingApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('OrderingApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('OrderingApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "MarketingApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('MarketingApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('MarketingApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "LocationsApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('LocationsApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('LocationsApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + } + ], + "probes": [ + { + "name": "FabricGatewayProbe", + "properties": { + "intervalInSeconds": 5, + "numberOfProbes": 2, + "port": "[parameters('nt0fabricTcpGatewayPort')]", + "protocol": "tcp" + } + }, + { + "name": "FabricHttpGatewayProbe", + "properties": { + "intervalInSeconds": 5, + "numberOfProbes": 2, + "port": "[parameters('nt0fabricHttpGatewayPort')]", + "protocol": "tcp" + } + } + ], + "inboundNatPools": [ + { + "name": "LoadBalancerBEAddressNatPool", + "properties": { + "backendPort": "3389", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPortRangeEnd": "4500", + "frontendPortRangeStart": "3389", + "protocol": "tcp" + } + } + ] + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[variables('uniqueStringArray0')[copyIndex()]]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "copy": { + "name": "storageLoop", + "count": 5 + }, + "kind": "Storage", + "sku": { + "name": "[parameters('storageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('vmssApiVersion')]", + "type": "Microsoft.Compute/virtualMachineScaleSets", + "name": "[parameters('vmNodeType0Name')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [ + "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0])]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1])]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2])]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3])]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4])]", + "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('applicationDiagnosticsStorageAccountName'))]" + ], + "properties": { + "overprovision": "[parameters('overProvision')]", + "upgradePolicy": { + "mode": "Automatic" + }, + "virtualMachineProfile": { + "extensionProfile": { + "extensions": [ + { + "name": "[concat(parameters('vmNodeType0Name'),'_ServiceFabricNode')]", + "properties": { + "type": "ServiceFabricNode", + "autoUpgradeMinorVersion": true, + "protectedSettings": { + "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key1]", + "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key2]" + }, + "publisher": "Microsoft.Azure.ServiceFabric", + "settings": { + "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]", + "nodeTypeRef": "[parameters('vmNodeType0Name')]", + "dataPath": "D:\\\\SvcFab", + "durabilityLevel": "Bronze", + "enableParallelJobs": true, + "nicPrefixOverride": "[parameters('subnet0Prefix')]" + }, + "typeHandlerVersion": "1.0" + } + }, + { + "name": "[concat('VMDiagnosticsVmExt','_vmNodeType0Name')]", + "properties": { + "type": "IaaSDiagnostics", + "autoUpgradeMinorVersion": true, + "protectedSettings": { + "storageAccountName": "[parameters('applicationDiagnosticsStorageAccountName')]", + "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]", + "storageAccountEndPoint": "https://core.windows.net/" + }, + "publisher": "Microsoft.Azure.Diagnostics", + "settings": { + "WadCfg": { + "DiagnosticMonitorConfiguration": { + "overallQuotaInMB": "50000", + "EtwProviders": { + "EtwEventSourceProviderConfiguration": [ + { + "provider": "Microsoft-ServiceFabric-Actors", + "scheduledTransferKeywordFilter": "1", + "scheduledTransferPeriod": "PT5M", + "DefaultEvents": { + "eventDestination": "ServiceFabricReliableActorEventTable" + } + }, + { + "provider": "Microsoft-ServiceFabric-Services", + "scheduledTransferPeriod": "PT5M", + "DefaultEvents": { + "eventDestination": "ServiceFabricReliableServiceEventTable" + } + } + ], + "EtwManifestProviderConfiguration": [ + { + "provider": "cbd93bc2-71e5-4566-b3a7-595d8eeca6e8", + "scheduledTransferLogLevelFilter": "Information", + "scheduledTransferKeywordFilter": "4611686018427387904", + "scheduledTransferPeriod": "PT5M", + "DefaultEvents": { + "eventDestination": "ServiceFabricSystemEventTable" + } + } + ] + } + } + }, + "StorageAccount": "[parameters('applicationDiagnosticsStorageAccountName')]" + }, + "typeHandlerVersion": "1.5" + } + } + ] + }, + "networkProfile": { + "networkInterfaceConfigurations": [ + { + "name": "[concat(parameters('nicName'), '-0')]", + "properties": { + "ipConfigurations": [ + { + "name": "[concat(parameters('nicName'),'-',0)]", + "properties": { + "loadBalancerBackendAddressPools": [ + { + "id": "[variables('lbPoolID0')]" + } + ], + "loadBalancerInboundNatPools": [ + { + "id": "[variables('lbNatPoolID0')]" + } + ], + "subnet": { + "id": "[variables('subnet0Ref')]" + } + } + } + ], + "primary": true + } + } + ] + }, + "osProfile": { + "adminPassword": "[parameters('adminPassword')]", + "adminUsername": "[parameters('adminUsername')]", + "computernamePrefix": "[parameters('vmNodeType0Name')]" + }, + "storageProfile": { + "imageReference": { + "publisher": "[parameters('vmImagePublisher')]", + "offer": "[parameters('vmImageOffer')]", + "sku": "[parameters('vmImageSku')]", + "version": "[parameters('vmImageVersion')]" + }, + "osDisk": { + "caching": "ReadOnly", + "createOption": "FromImage", + "vhdContainers": [ + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]", + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]", + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]", + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]", + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]" + ], + "name": "vmssosdisk" + } + } + } + }, + "sku": { + "name": "[parameters('vmNodeType0Size')]", + "capacity": "[parameters('nt0InstanceCount')]", + "tier": "Standard" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "2017-07-01-preview", + "type": "Microsoft.ServiceFabric/clusters", + "name": "[parameters('clusterName')]", + "location": "[parameters('clusterLocation')]", + "dependsOn": [ + "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]" + ], + "properties": { + "addonFeatures": [ + "DnsService" + ], + "clientCertificateCommonNames": [], + "clientCertificateThumbprints": [], + "clusterCodeVersion": "5.7.207.9494", + "clusterState": "Default", + "diagnosticsStorageAccountConfig": { + "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]", + "protectedAccountKeyName": "StorageAccountKey1", + "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]", + "storageAccountName": "[parameters('supportLogStorageAccountName')]", + "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]" + }, + "fabricSettings": [], + "managementEndpoint": "[concat('http://',reference(concat(parameters('lbIPName'),'-','0')).dnsSettings.fqdn,':',parameters('nt0fabricHttpGatewayPort'))]", + "nodeTypes": [ + { + "name": "[parameters('vmNodeType0Name')]", + "applicationPorts": { + "endPort": "[parameters('nt0applicationEndPort')]", + "startPort": "[parameters('nt0applicationStartPort')]" + }, + "clientConnectionEndpointPort": "[parameters('nt0fabricTcpGatewayPort')]", + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": "[parameters('nt0ephemeralEndPort')]", + "startPort": "[parameters('nt0ephemeralStartPort')]" + }, + "httpGatewayEndpointPort": "[parameters('nt0fabricHttpGatewayPort')]", + "isPrimary": true, + "reverseProxyEndpointPort": "[parameters('nt0reverseProxyEndpointPort')]", + "vmInstanceCount": "[parameters('nt0InstanceCount')]" + } + ], + "provisioningState": "Default", + "reliabilityLevel": "None", + "upgradeMode": "Manual", + "vmImage": "Windows" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + } + ], + "outputs": { + "clusterProperties": { + "value": "[reference(parameters('clusterName'))]", + "type": "object" + } + } +} \ No newline at end of file diff --git a/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.parameters.json b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.parameters.json new file mode 100644 index 000000000..2c214b754 --- /dev/null +++ b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploy.parameters.json @@ -0,0 +1,97 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterName": { + "value": "qa-eshop-sfwin-cluster" + }, + "clusterLocation": { + "value": "westus" + }, + "computeLocation": { + "value": "westus" + }, + "adminUserName": { + "value": "eshop" + }, + "adminPassword": { + "value": "Your_complex_Pass@word1" + }, + "nicName": { + "value": "NIC-eshopsfwin" + }, + "publicIPAddressName": { + "value": "eshopsfwin-PubIP" + }, + "dnsName": { + "value": "qa-eshop-sfwin-cluster" + }, + "virtualNetworkName": { + "value": "VNet-eshopsfwin" + }, + "lbName": { + "value": "LB-eshopsfwin" + }, + "lbIPName": { + "value": "LBIP-eshopsfwin" + }, + "applicationDiagnosticsStorageAccountName": { + "value": "sfdgqaeshopsfwin" + }, + "supportLogStorageAccountName": { + "value": "sflogsqaeshopsfwin" + }, + "vmImageSku": { + "value": "2016-Datacenter-with-Containers" + }, + "nt0ephemeralStartPort": { + "value": 49152 + }, + "nt0ephemeralEndPort": { + "value": 65534 + }, + "nt0applicationStartPort": { + "value": 20000 + }, + "nt0applicationEndPort": { + "value": 30000 + }, + "nt0fabricTcpGatewayPort": { + "value": 19000 + }, + "nt0fabricHttpGatewayPort": { + "value": 19080 + }, + "nt0reverseProxyEndpointPort": { + "value": 19081 + }, + "webMvcHttpPort": { + "value": 5100 + }, + "webSpaHttpPort": { + "value": 5104 + }, + "webStatusHttpPort": { + "value": 5107 + }, + "IdSrvHttpRule": { + "value": 5105 + }, + "BasketApiHttpRule": { + "value": 5103 + }, + "CatalogApiHttpRule": { + "value": 5101 + }, + "OrderingApiHttpRule": { + "value": 5102 + }, + "MarketingApiHttpRule": { + "value": 5110 + }, + "LocationsApiHttpRule": { + "value": 5109 + } + } +} + diff --git a/deploy/az/servicefabric/WindowsContainers/servicefabricdeploysecured.json b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploysecured.json new file mode 100644 index 000000000..843f5c0d1 --- /dev/null +++ b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploysecured.json @@ -0,0 +1,924 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterLocation": { + "type": "string", + "metadata": { + "description": "Location of the Cluster" + } + }, + "clusterName": { + "type": "string", + "defaultValue": "Cluster", + "metadata": { + "description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only" + } + }, + "nt0applicationStartPort": { + "type": "int", + "defaultValue": 20000 + }, + "nt0applicationEndPort": { + "type": "int", + "defaultValue": 30000 + }, + "nt0ephemeralStartPort": { + "type": "int", + "defaultValue": 49152 + }, + "nt0ephemeralEndPort": { + "type": "int", + "defaultValue": 65534 + }, + "nt0fabricTcpGatewayPort": { + "type": "int", + "defaultValue": 19000 + }, + "nt0fabricHttpGatewayPort": { + "type": "int", + "defaultValue": 19080 + }, + "nt0reverseProxyEndpointPort": { + "type": "int", + "defaultValue": 19081 + }, + "webMvcHttpPort": { + "type": "int", + "defaultValue": 5100 + }, + "webSpaHttpPort": { + "type": "int", + "defaultValue": 5104 + }, + "webStatusHttpPort": { + "type": "int", + "defaultValue": 5107 + }, + "IdSrvHttpRule": { + "type": "int", + "defaultValue": 5105 + }, + "BasketApiHttpRule": { + "type": "int", + "defaultValue": 5103 + }, + "CatalogApiHttpRule": { + "type": "int", + "defaultValue": 5101 + }, + "OrderingApiHttpRule": { + "type": "int", + "defaultValue": 5102 + }, + "MarketingApiHttpRule": { + "type": "int", + "defaultValue": 5110 + }, + "LocationsApiHttpRule": { + "type": "int", + "defaultValue": 5109 + }, + "subnet0Name": { + "type": "string", + "defaultValue": "Subnet-0" + }, + "subnet0Prefix": { + "type": "string", + "defaultValue": "10.0.0.0/24" + }, + "computeLocation": { + "type": "string" + }, + "publicIPAddressName": { + "type": "string", + "defaultValue": "PublicIP-VM" + }, + "publicIPAddressType": { + "type": "string", + "allowedValues": [ + "Dynamic" + ], + "defaultValue": "Dynamic" + }, + "vmStorageAccountContainerName": { + "type": "string", + "defaultValue": "vhds" + }, + "adminUserName": { + "type": "string", + "defaultValue": "testadm", + "metadata": { + "description": "Remote desktop user Id" + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Remote desktop user password. Must be a strong password" + } + }, + "virtualNetworkName": { + "type": "string", + "defaultValue": "VNet" + }, + "addressPrefix": { + "type": "string", + "defaultValue": "10.0.0.0/16" + }, + "dnsName": { + "type": "string" + }, + "nicName": { + "type": "string", + "defaultValue": "NIC" + }, + "lbName": { + "type": "string", + "defaultValue": "LoadBalancer" + }, + "lbIPName": { + "type": "string", + "defaultValue": "PublicIP-LB-FE" + }, + "overProvision": { + "type": "string", + "defaultValue": "false" + }, + "vmImagePublisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsServer" + }, + "vmImageOffer": { + "type": "string", + "defaultValue": "WindowsServer" + }, + "vmImageSku": { + "type": "string", + "defaultValue": "2012-R2-Datacenter" + }, + "vmImageVersion": { + "type": "string", + "defaultValue": "latest" + }, + "clusterProtectionLevel": { + "type": "string", + "allowedValues": [ + "None", + "Sign", + "EncryptAndSign" + ], + "defaultValue": "EncryptAndSign", + "metadata": { + "description": "Protection level.Three values are allowed - EncryptAndSign, Sign, None. It is best to keep the default of EncryptAndSign, unless you have a need not to" + } + }, + "certificateStoreValue": { + "type": "string", + "allowedValues": [ + "My" + ], + "defaultValue": "My", + "metadata": { + "description": "The store name where the cert will be deployed in the virtual machine" + } + }, + "certificateThumbprint": { + "type": "string", + "metadata": { + "description": "Certificate Thumbprint" + } + }, + "sourceVaultValue": { + "type": "string", + "metadata": { + "description": "Resource Id of the key vault, is should be in the format of /subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/" + } + }, + "certificateUrlValue": { + "type": "string", + "metadata": { + "description": "Refers to the location URL in your key vault where the certificate was uploaded, it is should be in the format of https://.vault.azure.net:443/secrets/" + } + }, + "storageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the VM image storage account" + } + }, + "supportLogStorageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the support log storage account" + } + }, + "supportLogStorageAccountName": { + "type": "string", + "defaultValue": "[toLower( concat('sflogs', uniqueString(resourceGroup().id),'2'))]", + "metadata": { + "description": "Name for the storage account that contains support logs from the cluster" + } + }, + "applicationDiagnosticsStorageAccountType": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS" + ], + "defaultValue": "Standard_LRS", + "metadata": { + "description": "Replication option for the application diagnostics storage account" + } + }, + "applicationDiagnosticsStorageAccountName": { + "type": "string", + "defaultValue": "[toLower(concat(uniqueString(resourceGroup().id), '3' ))]", + "metadata": { + "description": "Name for the storage account that contains application diagnostics data from the cluster" + } + }, + "nt0InstanceCount": { + "type": "int", + "defaultValue": 5, + "metadata": { + "description": "Instance count for node type" + } + }, + "vmNodeType0Name": { + "type": "string", + "defaultValue": "primary", + "maxLength": 9 + }, + "vmNodeType0Size": { + "type": "string", + "defaultValue": "Standard_D2_v2" + } + }, + "variables": { + "vmssApiVersion": "2017-03-30", + "lbApiVersion": "2015-06-15", + "vNetApiVersion": "2015-06-15", + "storageApiVersion": "2016-01-01", + "publicIPApiVersion": "2015-06-15", + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]", + "subnet0Ref": "[concat(variables('vnetID'),'/subnets/',parameters('subnet0Name'))]", + "lbID0": "[resourceId('Microsoft.Network/loadBalancers', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "lbIPConfig0": "[concat(variables('lbID0'),'/frontendIPConfigurations/LoadBalancerIPConfig')]", + "lbPoolID0": "[concat(variables('lbID0'),'/backendAddressPools/LoadBalancerBEAddressPool')]", + "lbProbeID0": "[concat(variables('lbID0'),'/probes/FabricGatewayProbe')]", + "lbHttpProbeID0": "[concat(variables('lbID0'),'/probes/FabricHttpGatewayProbe')]", + "lbNatPoolID0": "[concat(variables('lbID0'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]", + "vmStorageAccountName0": "[toLower(concat(uniqueString(resourceGroup().id), '1', '0' ))]", + "uniqueStringArray0": [ + "[concat(variables('vmStorageAccountName0'), '0')]", + "[concat(variables('vmStorageAccountName0'), '1')]", + "[concat(variables('vmStorageAccountName0'), '2')]", + "[concat(variables('vmStorageAccountName0'), '3')]", + "[concat(variables('vmStorageAccountName0'), '4')]" + ] + }, + "resources": [ + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('supportLogStorageAccountName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "kind": "Storage", + "sku": { + "name": "[parameters('supportLogStorageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('applicationDiagnosticsStorageAccountName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "kind": "Storage", + "sku": { + "name": "[parameters('applicationDiagnosticsStorageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('vNetApiVersion')]", + "type": "Microsoft.Network/virtualNetworks", + "name": "[parameters('virtualNetworkName')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[parameters('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[parameters('subnet0Name')]", + "properties": { + "addressPrefix": "[parameters('subnet0Prefix')]" + } + } + ] + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('publicIPApiVersion')]", + "type": "Microsoft.Network/publicIPAddresses", + "name": "[concat(parameters('lbIPName'),'-','0')]", + "location": "[parameters('computeLocation')]", + "properties": { + "dnsSettings": { + "domainNameLabel": "[parameters('dnsName')]" + }, + "publicIPAllocationMethod": "Dynamic" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('lbApiVersion')]", + "type": "Microsoft.Network/loadBalancers", + "name": "[concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name'))]", + "location": "[parameters('computeLocation')]", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]" + ], + "properties": { + "frontendIPConfigurations": [ + { + "name": "LoadBalancerIPConfig", + "properties": { + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]" + } + } + } + ], + "backendAddressPools": [ + { + "name": "LoadBalancerBEAddressPool", + "properties": {} + } + ], + "loadBalancingRules": [ + { + "name": "LBRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0fabricTcpGatewayPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0fabricTcpGatewayPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "LBHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0fabricHttpGatewayPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0fabricHttpGatewayPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "ReverseProxyHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('nt0reverseProxyEndpointPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('nt0reverseProxyEndpointPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "WebMVCHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webMvcHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webMvcHttpPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "WebSPAHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webSpaHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webSpaHttpPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "WebStatusHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('webStatusHttpPort')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('webStatusHttpPort')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "IdSrvHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('IdSrvHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('IdSrvHttpRule')]", + "idleTimeoutInMinutes": "5", + "probe": { + "id": "[variables('lbHttpProbeID0')]" + }, + "protocol": "tcp" + } + }, + { + "name": "BasketApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('BasketApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('BasketApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "CatalogApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('CatalogApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('CatalogApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "OrderingApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('OrderingApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('OrderingApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "MarketingApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('MarketingApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('MarketingApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + }, + { + "name": "LocationsApiHttpRule", + "properties": { + "backendAddressPool": { + "id": "[variables('lbPoolID0')]" + }, + "backendPort": "[parameters('LocationsApiHttpRule')]", + "enableFloatingIP": "false", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPort": "[parameters('LocationsApiHttpRule')]", + "idleTimeoutInMinutes": "5", + "protocol": "tcp" + } + } + ], + "probes": [ + { + "name": "FabricGatewayProbe", + "properties": { + "intervalInSeconds": 5, + "numberOfProbes": 2, + "port": "[parameters('nt0fabricTcpGatewayPort')]", + "protocol": "tcp" + } + }, + { + "name": "FabricHttpGatewayProbe", + "properties": { + "intervalInSeconds": 5, + "numberOfProbes": 2, + "port": "[parameters('nt0fabricHttpGatewayPort')]", + "protocol": "tcp" + } + } + ], + "inboundNatPools": [ + { + "name": "LoadBalancerBEAddressNatPool", + "properties": { + "backendPort": "3389", + "frontendIPConfiguration": { + "id": "[variables('lbIPConfig0')]" + }, + "frontendPortRangeEnd": "4500", + "frontendPortRangeStart": "3389", + "protocol": "tcp" + } + } + ] + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('storageApiVersion')]", + "type": "Microsoft.Storage/storageAccounts", + "name": "[variables('uniqueStringArray0')[copyIndex()]]", + "location": "[parameters('computeLocation')]", + "dependsOn": [], + "properties": {}, + "copy": { + "name": "storageLoop", + "count": 5 + }, + "kind": "Storage", + "sku": { + "name": "[parameters('storageAccountType')]" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "[variables('vmssApiVersion')]", + "type": "Microsoft.Compute/virtualMachineScaleSets", + "name": "[parameters('vmNodeType0Name')]", + "location": "[parameters('computeLocation')]", + "dependsOn": [ + "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0])]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1])]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2])]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3])]", + "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4])]", + "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',parameters('vmNodeType0Name')))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('applicationDiagnosticsStorageAccountName'))]" + ], + "properties": { + "overprovision": "[parameters('overProvision')]", + "upgradePolicy": { + "mode": "Automatic" + }, + "virtualMachineProfile": { + "extensionProfile": { + "extensions": [ + { + "name": "[concat(parameters('vmNodeType0Name'),'_ServiceFabricNode')]", + "properties": { + "type": "ServiceFabricNode", + "autoUpgradeMinorVersion": true, + "protectedSettings": { + "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key1]", + "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('supportLogStorageAccountName')),'2015-05-01-preview').key2]" + }, + "publisher": "Microsoft.Azure.ServiceFabric", + "settings": { + "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]", + "nodeTypeRef": "[parameters('vmNodeType0Name')]", + "dataPath": "D:\\\\SvcFab", + "durabilityLevel": "Bronze", + "enableParallelJobs": true, + "nicPrefixOverride": "[parameters('subnet0Prefix')]", + "certificate": { + "thumbprint": "[parameters('certificateThumbprint')]", + "x509StoreName": "[parameters('certificateStoreValue')]" + } + }, + "typeHandlerVersion": "1.0" + } + }, + { + "name": "[concat('VMDiagnosticsVmExt','_vmNodeType0Name')]", + "properties": { + "type": "IaaSDiagnostics", + "autoUpgradeMinorVersion": true, + "protectedSettings": { + "storageAccountName": "[parameters('applicationDiagnosticsStorageAccountName')]", + "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]", + "storageAccountEndPoint": "https://core.windows.net/" + }, + "publisher": "Microsoft.Azure.Diagnostics", + "settings": { + "WadCfg": { + "DiagnosticMonitorConfiguration": { + "overallQuotaInMB": "50000", + "EtwProviders": { + "EtwEventSourceProviderConfiguration": [ + { + "provider": "Microsoft-ServiceFabric-Actors", + "scheduledTransferKeywordFilter": "1", + "scheduledTransferPeriod": "PT5M", + "DefaultEvents": { + "eventDestination": "ServiceFabricReliableActorEventTable" + } + }, + { + "provider": "Microsoft-ServiceFabric-Services", + "scheduledTransferPeriod": "PT5M", + "DefaultEvents": { + "eventDestination": "ServiceFabricReliableServiceEventTable" + } + } + ], + "EtwManifestProviderConfiguration": [ + { + "provider": "cbd93bc2-71e5-4566-b3a7-595d8eeca6e8", + "scheduledTransferLogLevelFilter": "Information", + "scheduledTransferKeywordFilter": "4611686018427387904", + "scheduledTransferPeriod": "PT5M", + "DefaultEvents": { + "eventDestination": "ServiceFabricSystemEventTable" + } + } + ] + } + } + }, + "StorageAccount": "[parameters('applicationDiagnosticsStorageAccountName')]" + }, + "typeHandlerVersion": "1.5" + } + } + ] + }, + "networkProfile": { + "networkInterfaceConfigurations": [ + { + "name": "[concat(parameters('nicName'), '-0')]", + "properties": { + "ipConfigurations": [ + { + "name": "[concat(parameters('nicName'),'-',0)]", + "properties": { + "loadBalancerBackendAddressPools": [ + { + "id": "[variables('lbPoolID0')]" + } + ], + "loadBalancerInboundNatPools": [ + { + "id": "[variables('lbNatPoolID0')]" + } + ], + "subnet": { + "id": "[variables('subnet0Ref')]" + } + } + } + ], + "primary": true + } + } + ] + }, + "osProfile": { + "adminPassword": "[parameters('adminPassword')]", + "adminUsername": "[parameters('adminUsername')]", + "computernamePrefix": "[parameters('vmNodeType0Name')]", + "secrets": [ + { + "sourceVault": { + "id": "[parameters('sourceVaultValue')]" + }, + "vaultCertificates": [ + { + "certificateStore": "[parameters('certificateStoreValue')]", + "certificateUrl": "[parameters('certificateUrlValue')]" + } + ] + } + ] + }, + "storageProfile": { + "imageReference": { + "publisher": "[parameters('vmImagePublisher')]", + "offer": "[parameters('vmImageOffer')]", + "sku": "[parameters('vmImageSku')]", + "version": "[parameters('vmImageVersion')]" + }, + "osDisk": { + "caching": "ReadOnly", + "createOption": "FromImage", + "vhdContainers": [ + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]", + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]", + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]", + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]", + "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4]), variables('storageApiVersion')).primaryEndpoints.blob, parameters('vmStorageAccountContainerName'))]" + ], + "name": "vmssosdisk" + } + } + } + }, + "sku": { + "name": "[parameters('vmNodeType0Size')]", + "capacity": "[parameters('nt0InstanceCount')]", + "tier": "Standard" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + }, + { + "apiVersion": "2017-07-01-preview", + "type": "Microsoft.ServiceFabric/clusters", + "name": "[parameters('clusterName')]", + "location": "[parameters('clusterLocation')]", + "dependsOn": [ + "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]" + ], + "properties": { + "addonFeatures": [ + "DnsService" + ], + "certificate": { + "thumbprint": "[parameters('certificateThumbprint')]", + "x509StoreName": "[parameters('certificateStoreValue')]" + }, + "clientCertificateCommonNames": [], + "clientCertificateThumbprints": [], + "clusterCodeVersion": "5.7.207.9494", + "clusterState": "Default", + "diagnosticsStorageAccountConfig": { + "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]", + "protectedAccountKeyName": "StorageAccountKey1", + "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]", + "storageAccountName": "[parameters('supportLogStorageAccountName')]", + "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]" + }, + "fabricSettings": [ + { + "parameters": [ + { + "name": "ClusterProtectionLevel", + "value": "[parameters('clusterProtectionLevel')]" + } + ], + "name": "Security" + } + ], + "managementEndpoint": "[concat('https://',reference(concat(parameters('lbIPName'),'-','0')).dnsSettings.fqdn,':',parameters('nt0fabricHttpGatewayPort'))]", + "nodeTypes": [ + { + "name": "[parameters('vmNodeType0Name')]", + "applicationPorts": { + "endPort": "[parameters('nt0applicationEndPort')]", + "startPort": "[parameters('nt0applicationStartPort')]" + }, + "clientConnectionEndpointPort": "[parameters('nt0fabricTcpGatewayPort')]", + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": "[parameters('nt0ephemeralEndPort')]", + "startPort": "[parameters('nt0ephemeralStartPort')]" + }, + "httpGatewayEndpointPort": "[parameters('nt0fabricHttpGatewayPort')]", + "isPrimary": true, + "reverseProxyEndpointPort": "[parameters('nt0reverseProxyEndpointPort')]", + "vmInstanceCount": "[parameters('nt0InstanceCount')]" + } + ], + "provisioningState": "Default", + "reliabilityLevel": "Silver", + "upgradeMode": "Manual", + "vmImage": "Windows" + }, + "tags": { + "resourceType": "Service Fabric", + "clusterName": "[parameters('clusterName')]" + } + } + ], + "outputs": { + "clusterProperties": { + "value": "[reference(parameters('clusterName'))]", + "type": "object" + } + } +} \ No newline at end of file diff --git a/deploy/az/servicefabric/WindowsContainers/servicefabricdeploysecured.parameters.json b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploysecured.parameters.json new file mode 100644 index 000000000..bbc8eb663 --- /dev/null +++ b/deploy/az/servicefabric/WindowsContainers/servicefabricdeploysecured.parameters.json @@ -0,0 +1,106 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterName": { + "value": "pro-eshop-sfwin-cluster" + }, + "clusterLocation": { + "value": "westus" + }, + "computeLocation": { + "value": "westus" + }, + "adminUserName": { + "value": "eshop" + }, + "adminPassword": { + "value": "Your_complex_Pass@word1" + }, + "nicName": { + "value": "NIC-eshopsfwin" + }, + "publicIPAddressName": { + "value": "eshopsfwin-PubIP" + }, + "dnsName": { + "value": "pro-eshop-sfwin-cluster" + }, + "virtualNetworkName": { + "value": "VNet-eshopsfwin" + }, + "lbName": { + "value": "LB-eshopsfwin" + }, + "lbIPName": { + "value": "LBIP-eshopsfwin" + }, + "applicationDiagnosticsStorageAccountName": { + "value": "sfdgqaeshopsfwinsec" + }, + "supportLogStorageAccountName": { + "value": "sflogsqaeshopsfwinsec" + }, + "sourceVaultValue": { + "value": "your-value-check-keyvault-at-azure" + }, + "certificateUrlValue": { + "value": "your-value-check-keyvault-at-azure" + }, + "certificateThumbprint": { + "value": "your-value-check-keyvault-at-azure" + }, + "vmImageSku": { + "value": "2016-Datacenter-with-Containers" + }, + "nt0ephemeralStartPort": { + "value": 49152 + }, + "nt0ephemeralEndPort": { + "value": 65534 + }, + "nt0applicationStartPort": { + "value": 20000 + }, + "nt0applicationEndPort": { + "value": 30000 + }, + "nt0fabricTcpGatewayPort": { + "value": 19000 + }, + "nt0fabricHttpGatewayPort": { + "value": 19080 + }, + "nt0reverseProxyEndpointPort": { + "value": 19081 + }, + "webMvcHttpPort": { + "value": 5100 + }, + "webSpaHttpPort": { + "value": 5104 + }, + "webStatusHttpPort": { + "value": 5107 + }, + "IdSrvHttpRule": { + "value": 5105 + }, + "BasketApiHttpRule": { + "value": 5103 + }, + "CatalogApiHttpRule": { + "value": 5101 + }, + "OrderingApiHttpRule": { + "value": 5102 + }, + "MarketingApiHttpRule": { + "value": 5110 + }, + "LocationsApiHttpRule": { + "value": 5109 + } + } +} + diff --git a/docker-compose-external.override.yml b/docker-compose-external.override.yml index f20440ad7..60764ca54 100644 --- a/docker-compose-external.override.yml +++ b/docker-compose-external.override.yml @@ -3,7 +3,7 @@ version: '2' services: sql.data: environment: - - SA_PASSWORD=Pass@word + - MSSQL_SA_PASSWORD=Pass@word - ACCEPT_EULA=Y ports: - "5433:1433" \ No newline at end of file diff --git a/docker-compose-external.yml b/docker-compose-external.yml index 8d8d61add..8d8e0e760 100644 --- a/docker-compose-external.yml +++ b/docker-compose-external.yml @@ -1,8 +1,8 @@ -version: '2.1' +version: '3' services: sql.data: - image: microsoft/mssql-server-linux + image: microsoft/mssql-server-linux:2017-latest basket.data: image: redis diff --git a/docker-compose-windows.prod.yml b/docker-compose-windows.prod.yml index d5ea2d1bc..0e7602e8f 100644 --- a/docker-compose-windows.prod.yml +++ b/docker-compose-windows.prod.yml @@ -1,4 +1,4 @@ -version: '2.1' +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: @@ -121,7 +121,7 @@ services: sql.data: environment: - - SA_PASSWORD=Pass@word + - MSSQL_SA_PASSWORD=Pass@word - ACCEPT_EULA=Y ports: - "5433:1433" diff --git a/docker-compose-windows.yml b/docker-compose-windows.yml index 294d5f7f5..08785cff1 100644 --- a/docker-compose-windows.yml +++ b/docker-compose-windows.yml @@ -1,4 +1,4 @@ -version: '2.1' +version: '3' services: basket.api: diff --git a/docker-compose.ci.build.yml b/docker-compose.ci.build.yml index 02fe39637..d4b69f9c5 100644 --- a/docker-compose.ci.build.yml +++ b/docker-compose.ci.build.yml @@ -1,4 +1,4 @@ -version: '2.1' +version: '3' services: ci-build: diff --git a/docker-compose.nobuild.yml b/docker-compose.nobuild.yml index 186ab8639..4f301cd3c 100644 --- a/docker-compose.nobuild.yml +++ b/docker-compose.nobuild.yml @@ -1,4 +1,4 @@ -version: '2.1' +version: '3' services: basket.api: @@ -66,7 +66,7 @@ services: - rabbitmq sql.data: - image: microsoft/mssql-server-linux + image: microsoft/mssql-server-linux:2017-latest nosql.data: image: mongo diff --git a/docker-compose.override.windows.yml b/docker-compose.override.windows.yml index 130405d3b..537b3b098 100644 --- a/docker-compose.override.windows.yml +++ b/docker-compose.override.windows.yml @@ -1,4 +1,4 @@ -version: '2.1' +version: '3' # ONLY NEEDED WHEN RUNNING WINDOWS CONTAINERS # diff --git a/docker-compose.override.yml b/docker-compose.override.yml index b1ce31184..449bc4a74 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,4 +1,4 @@ -version: '2.1' +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: @@ -19,6 +19,10 @@ services: - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} - AzureServiceBusEnabled=False + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} + - UseLoadTest=${USE_LOADTEST:-False} + ports: - "5103:80" @@ -36,6 +40,8 @@ services: - UseCustomizationData=True - AzureServiceBusEnabled=False - AzureStorageEnabled=False + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} ports: - "5101:80" @@ -45,13 +51,15 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104 - XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback #localhost do not work for UWP login, so we have to use "external" IP always - - ConnectionStrings__DefaultConnection=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word} + - ConnectionString=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word} - MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5110. - LocationApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5109 - MarketingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110 - BasketApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103 - OrderingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102 - - UseCustomizationData=True + - UseCustomizationData=True + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} ports: - "5105:80" @@ -69,6 +77,9 @@ services: - AzureServiceBusEnabled=False - CheckUpdateTime=30000 - GracePeriodTime=1 + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} + - UseLoadTest=${USE_LOADTEST:-False} ports: - "5102:80" @@ -90,6 +101,9 @@ services: - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY} - AzureServiceBusEnabled=False - AzureStorageEnabled=False + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} + - UseLoadTest=${USE_LOADTEST:-False} ports: - "5110:80" @@ -110,6 +124,8 @@ services: - MarketingUrlHC=http://marketing.api/hc - PaymentUrlHC=http://payment.api/hc - UseCustomizationData=True + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} ports: - "5104:80" @@ -130,6 +146,9 @@ services: - MarketingUrlHC=http://marketing.api/hc - PaymentUrlHC=http://payment.api/hc - UseCustomizationData=True + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} + - UseLoadTest=${USE_LOADTEST:-False} ports: - "5100:80" @@ -146,6 +165,8 @@ services: - PaymentUrl=http://payment.api/hc - mvc=http://webmvc/hc - spa=http://webspa/hc + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} ports: - "5107:80" @@ -157,6 +178,8 @@ services: - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} - AzureServiceBusEnabled=False + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} ports: - "5108:80" @@ -172,12 +195,15 @@ services: - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} - AzureServiceBusEnabled=False + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} + - UseLoadTest=${USE_LOADTEST:-False} ports: - "5109:80" sql.data: environment: - - SA_PASSWORD=Pass@word + - MSSQL_SA_PASSWORD=Pass@word - ACCEPT_EULA=Y - MSSQL_PID=Developer ports: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 313811f19..a2301c236 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,4 +1,4 @@ -version: '2.1' +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: @@ -124,7 +124,7 @@ services: sql.data: environment: - - SA_PASSWORD=Pass@word + - MSSQL_SA_PASSWORD=Pass@word - ACCEPT_EULA=Y - MSSQL_PID=Developer ports: diff --git a/docker-compose.yml b/docker-compose.yml index 23acd8af7..d05d5f697 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2.1' +version: '3' services: @@ -97,7 +97,7 @@ services: - rabbitmq sql.data: - image: microsoft/mssql-server-linux:latest + image: microsoft/mssql-server-linux:2017-latest nosql.data: image: mongo diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index e633cf2ed..cc63417a3 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26730.12 +VisualStudioVersion = 15.0.27004.2002 MinimumVisualStudioVersion = 10.0.40219.1 Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" EndProject @@ -79,8 +79,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Health EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.HealthChecks.SqlServer", "src\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj", "{4BD76717-3102-4969-8C2C-BAAA3F0263B6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{4A980AC4-7205-46BF-8CCB-09E44D700FD4}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41139F64-4046-4F16-96B7-D941D96FA9C6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}" @@ -1029,54 +1027,6 @@ Global {4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x64.Build.0 = Release|Any CPU {4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x86.ActiveCfg = Release|Any CPU {4BD76717-3102-4969-8C2C-BAAA3F0263B6}.Release|x86.Build.0 = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|ARM.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|iPhone.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|x64.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|x64.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|x86.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.AppStore|x86.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|ARM.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|ARM.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|iPhone.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|x64.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|x64.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|x86.ActiveCfg = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Debug|x86.Build.0 = Debug|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|Any CPU.Build.0 = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|ARM.ActiveCfg = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|ARM.Build.0 = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|iPhone.ActiveCfg = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|iPhone.Build.0 = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|x64.ActiveCfg = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|x64.Build.0 = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|x86.ActiveCfg = Release|Any CPU - {4A980AC4-7205-46BF-8CCB-09E44D700FD4}.Release|x86.Build.0 = Release|Any CPU {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU @@ -1450,7 +1400,6 @@ Global {1A01AF82-6FCB-464C-B39C-F127AEBD315D} = {022E145D-1593-47EE-9608-8E323D3C63F5} {22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379} {4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379} - {4A980AC4-7205-46BF-8CCB-09E44D700FD4} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} {41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6} {88B22DBB-AA8F-4290-A454-2C109352C345} = {DB0EFB20-B024-4E5E-A75C-52143C131D25} diff --git a/img/appinsights/create-insights.PNG b/img/appinsights/create-insights.PNG new file mode 100644 index 000000000..535ae4b98 Binary files /dev/null and b/img/appinsights/create-insights.PNG differ diff --git a/img/appinsights/settings-insights.PNG b/img/appinsights/settings-insights.PNG new file mode 100644 index 000000000..16e6323d3 Binary files /dev/null and b/img/appinsights/settings-insights.PNG differ diff --git a/img/eShopOnContainers-Architecture-With-Azure-API-Management.png b/img/eShopOnContainers-Architecture-With-Azure-API-Management.png new file mode 100644 index 000000000..434740d60 Binary files /dev/null and b/img/eShopOnContainers-Architecture-With-Azure-API-Management.png differ diff --git a/img/eShopOnContainers_Architecture_Diagram.png b/img/eShopOnContainers_Architecture_Diagram.png index edf7d8a95..91609b987 100644 Binary files a/img/eShopOnContainers_Architecture_Diagram.png and b/img/eShopOnContainers_Architecture_Diagram.png differ diff --git a/img/sf/cloud_publishProfile.PNG b/img/sf/cloud_publishProfile.PNG new file mode 100644 index 000000000..edd5c53e5 Binary files /dev/null and b/img/sf/cloud_publishProfile.PNG differ diff --git a/img/sf/create-kv.PNG b/img/sf/create-kv.PNG new file mode 100644 index 000000000..f2c5f91c3 Binary files /dev/null and b/img/sf/create-kv.PNG differ diff --git a/img/sf/install-cert.PNG b/img/sf/install-cert.PNG new file mode 100644 index 000000000..f5c798199 Binary files /dev/null and b/img/sf/install-cert.PNG differ diff --git a/img/sf/set-instrumentationkey.PNG b/img/sf/set-instrumentationkey.PNG new file mode 100644 index 000000000..1d7105a30 Binary files /dev/null and b/img/sf/set-instrumentationkey.PNG differ diff --git a/k8s/conf_local.yml b/k8s/conf_local.yml index 00d1c2398..a605ff7aa 100644 --- a/k8s/conf_local.yml +++ b/k8s/conf_local.yml @@ -25,5 +25,7 @@ data: keystore: keystore-data GracePeriodManager_GracePeriodTime: "1" GracePeriodManager_CheckUpdateTime: "15000" + Instrumentation_Key: "" + diff --git a/k8s/deployments.yaml b/k8s/deployments.yaml index 6001f12b5..14b5ac31b 100644 --- a/k8s/deployments.yaml +++ b/k8s/deployments.yaml @@ -32,13 +32,34 @@ spec: configMapKeyRef: name: externalcfg key: UseAzureServiceBus + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key - name: IdentityUrl valueFrom: configMapKeyRef: name: urls key: IdentityUrl + - name: OrchestratorType + value: 'K8S' ports: - - containerPort: 80 + - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key --- @@ -81,8 +102,29 @@ spec: configMapKeyRef: name: externalcfg key: CatalogBus + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key --- @@ -105,7 +147,7 @@ spec: env: - name: PATH_BASE value: /identity - - name: ConnectionStrings__DefaultConnection + - name: ConnectionString valueFrom: configMapKeyRef: name: externalcfg @@ -146,9 +188,30 @@ spec: valueFrom: configMapKeyRef: name: urls - key: OrderingApiClient + key: OrderingApiClient + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key --- @@ -200,9 +263,30 @@ spec: valueFrom: configMapKeyRef: name: externalcfg - key: GracePeriodManager_GracePeriodTime + key: GracePeriodManager_GracePeriodTime + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key --- @@ -254,9 +338,30 @@ spec: valueFrom: configMapKeyRef: name: urls - key: IdentityUrl + key: IdentityUrl + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key --- @@ -318,9 +423,30 @@ spec: valueFrom: configMapKeyRef: name: urls - key: Marketing_PicBaseUrl + key: Marketing_PicBaseUrl + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key --- @@ -353,8 +479,29 @@ spec: configMapKeyRef: name: externalcfg key: PaymentBus + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key --- @@ -448,9 +595,30 @@ spec: valueFrom: configMapKeyRef: name: urls - key: PaymentHealthCheckUrl + key: PaymentHealthCheckUrl + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key --- @@ -517,7 +685,14 @@ spec: valueFrom: configMapKeyRef: name: urls - key: PaymentHealthCheckUrl + key: PaymentHealthCheckUrl + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 imagePullSecrets: @@ -614,7 +789,28 @@ spec: configMapKeyRef: name: urls key: PaymentHealthCheckUrl + - name: ApplicationInsights__InstrumentationKey + valueFrom: + configMapKeyRef: + name: externalcfg + key: Instrumentation_Key + - name: OrchestratorType + value: 'K8S' ports: - containerPort: 80 + readinessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /hc + port: 80 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 imagePullSecrets: - name: registry-key diff --git a/k8s/sql-data.yaml b/k8s/sql-data.yaml index 4b607ac98..245622e83 100644 --- a/k8s/sql-data.yaml +++ b/k8s/sql-data.yaml @@ -25,11 +25,11 @@ spec: spec: containers: - name: sql-data - image: microsoft/mssql-server-linux:latest + image: microsoft/mssql-server-linux:2017-latest env: - name: ACCEPT_EULA value: "Y" - name: MSSQL_PID value: Developer - - name: SA_PASSWORD + - name: MSSQL_SA_PASSWORD value: Pass@word diff --git a/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj b/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj index c5266d0a9..93a919894 100644 --- a/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj +++ b/src/BuildingBlocks/DataProtection/DataProtection/DataProtection.csproj @@ -7,7 +7,7 @@ - + \ No newline at end of file diff --git a/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs b/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs index 3db776b9a..1f5bffda5 100644 --- a/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs +++ b/src/BuildingBlocks/DataProtection/DataProtection/DataProtectionBuilderExtensions.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.DataProtection.Repositories; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; + using StackExchange.Redis; using System; using System.Linq; using System.Net; @@ -45,10 +46,11 @@ throw new ArgumentException("Redis connection string may not be empty.", nameof(redisConnectionString)); } - var ips = Dns.GetHostAddressesAsync(redisConnectionString).Result; + var configuration = ConfigurationOptions.Parse(redisConnectionString, true); + configuration.ResolveDns = true; return builder.Use(ServiceDescriptor.Singleton(services => - new RedisXmlRepository(ips.First().ToString(), services.GetRequiredService>()))); + new RedisXmlRepository(configuration, services.GetRequiredService>()))); } ///

diff --git a/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs b/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs index f5a903b65..d71f9df53 100644 --- a/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs +++ b/src/BuildingBlocks/DataProtection/DataProtection/RedisXmlRepository.cs @@ -65,7 +65,7 @@ /// /// Thrown if or is . /// - public RedisXmlRepository(string connectionString, ILogger logger) + public RedisXmlRepository(ConfigurationOptions connectionString, ILogger logger) : this(ConnectionMultiplexer.Connect(connectionString), logger) { } diff --git a/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj b/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj index 48f96ab59..ce65f7da8 100644 --- a/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj +++ b/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj index 22a2d3091..ac2d3783e 100644 --- a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj +++ b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj @@ -5,10 +5,6 @@ Microsoft.eShopOnContainers.BuildingBlocks.EventBus - - - - diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs index 0aafaf90a..2e0555e61 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs @@ -15,16 +15,17 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ { private readonly IConnectionFactory _connectionFactory; private readonly ILogger _logger; - + private readonly int _retryCount; IConnection _connection; bool _disposed; object sync_root = new object(); - public DefaultRabbitMQPersistentConnection(IConnectionFactory connectionFactory,ILogger logger) + public DefaultRabbitMQPersistentConnection(IConnectionFactory connectionFactory, ILogger logger, int retryCount = 5) { _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _retryCount = retryCount; } public bool IsConnected @@ -69,7 +70,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ { var policy = RetryPolicy.Handle() .Or() - .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => + .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogWarning(ex.ToString()); } @@ -88,7 +89,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ _connection.ConnectionBlocked += OnConnectionBlocked; _logger.LogInformation($"RabbitMQ persistent connection acquired a connection {_connection.Endpoint.HostName} and is subscribed to failure events"); - + return true; } else diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index f438623a6..2416e1d55 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -26,19 +26,20 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ private readonly IEventBusSubscriptionsManager _subsManager; private readonly ILifetimeScope _autofac; private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus"; + private readonly int _retryCount; private IModel _consumerChannel; private string _queueName; public EventBusRabbitMQ(IRabbitMQPersistentConnection persistentConnection, ILogger logger, - ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager) + ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, int retryCount = 5) { _persistentConnection = persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); _consumerChannel = CreateConsumerChannel(); _autofac = autofac; - + _retryCount = retryCount; _subsManager.OnEventRemoved += SubsManager_OnEventRemoved; } @@ -72,7 +73,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var policy = RetryPolicy.Handle() .Or() - .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => + .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogWarning(ex.ToString()); }); diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/Microsoft.AspNetCore.HealthChecks.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/Microsoft.AspNetCore.HealthChecks.csproj index 023554e60..3c28e8dbc 100644 --- a/src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/Microsoft.AspNetCore.HealthChecks.csproj +++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks/Microsoft.AspNetCore.HealthChecks.csproj @@ -1,7 +1,10 @@  - netstandard1.3 + netstandard2.0 + false + false + false @@ -9,8 +12,11 @@ - + + + + \ No newline at end of file diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj index 0007d0be6..40db99802 100644 --- a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj +++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.AzureStorage/Microsoft.Extensions.HealthChecks.AzureStorage.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj index 35aacef13..a38fa2160 100644 --- a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj +++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks.SqlServer/Microsoft.Extensions.HealthChecks.SqlServer.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj index 8ef22e156..228c2d79d 100644 --- a/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj +++ b/src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks/Microsoft.Extensions.HealthChecks.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj b/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj index e1c32cff2..03f4a0657 100644 --- a/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj +++ b/src/BuildingBlocks/Resilience/Resilience.Http/Resilience.Http.csproj @@ -6,6 +6,7 @@ + diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs index d32660005..18051a501 100644 --- a/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs +++ b/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs @@ -10,6 +10,7 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http { @@ -24,13 +25,15 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http private readonly ILogger _logger; private readonly Func> _policyCreator; private ConcurrentDictionary _policyWrappers; + private readonly IHttpContextAccessor _httpContextAccessor; - public ResilientHttpClient(Func> policyCreator, ILogger logger) + public ResilientHttpClient(Func> policyCreator, ILogger logger, IHttpContextAccessor httpContextAccessor) { _client = new HttpClient(); _logger = logger; _policyCreator = policyCreator; _policyWrappers = new ConcurrentDictionary(); + _httpContextAccessor = httpContextAccessor; } @@ -52,10 +55,12 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http { var requestMessage = new HttpRequestMessage(HttpMethod.Delete, uri); + SetAuthorizationHeader(requestMessage); + if (authorizationToken != null) { requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken); - } + } if (requestId != null) { @@ -65,6 +70,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http return await _client.SendAsync(requestMessage); }); } + public Task GetStringAsync(string uri, string authorizationToken = null, string authorizationMethod = "Bearer") { @@ -74,6 +80,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http { var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); + SetAuthorizationHeader(requestMessage); + if (authorizationToken != null) { requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken); @@ -108,6 +116,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http { var requestMessage = new HttpRequestMessage(method, uri); + SetAuthorizationHeader(requestMessage); + requestMessage.Content = new StringContent(JsonConvert.SerializeObject(item), System.Text.Encoding.UTF8, "application/json"); if (authorizationToken != null) @@ -162,6 +172,15 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http var origin = $"{url.Scheme}://{url.DnsSafeHost}:{url.Port}"; return origin; - } + } + + private void SetAuthorizationHeader(HttpRequestMessage requestMessage) + { + var authorizationHeader = _httpContextAccessor.HttpContext.Request.Headers["Authorization"]; + if (!string.IsNullOrEmpty(authorizationHeader)) + { + requestMessage.Headers.Add("Authorization", new List() { authorizationHeader }); + } + } } } diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs index 6cd378c88..a5f6a63c4 100644 --- a/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs +++ b/src/BuildingBlocks/Resilience/Resilience.Http/StandardHttpClient.cs @@ -1,6 +1,8 @@ -using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; +using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Net.Http.Headers; @@ -12,17 +14,21 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http { private HttpClient _client; private ILogger _logger; + private readonly IHttpContextAccessor _httpContextAccessor; - public StandardHttpClient(ILogger logger) + public StandardHttpClient(ILogger logger, IHttpContextAccessor httpContextAccessor) { _client = new HttpClient(); _logger = logger; + _httpContextAccessor = httpContextAccessor; } public async Task GetStringAsync(string uri, string authorizationToken = null, string authorizationMethod = "Bearer") { var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); + SetAuthorizationHeader(requestMessage); + if (authorizationToken != null) { requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken); @@ -45,6 +51,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http var requestMessage = new HttpRequestMessage(method, uri); + SetAuthorizationHeader(requestMessage); + requestMessage.Content = new StringContent(JsonConvert.SerializeObject(item), System.Text.Encoding.UTF8, "application/json"); if (authorizationToken != null) @@ -84,6 +92,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http { var requestMessage = new HttpRequestMessage(HttpMethod.Delete, uri); + SetAuthorizationHeader(requestMessage); + if (authorizationToken != null) { requestMessage.Headers.Authorization = new AuthenticationHeaderValue(authorizationMethod, authorizationToken); @@ -96,6 +106,15 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http return await _client.SendAsync(requestMessage); } + + private void SetAuthorizationHeader(HttpRequestMessage requestMessage) + { + var authorizationHeader = _httpContextAccessor.HttpContext.Request.Headers["Authorization"]; + if (!string.IsNullOrEmpty(authorizationHeader)) + { + requestMessage.Headers.Add("Authorization", new List() { authorizationHeader }); + } + } } } diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj index 8864c9d06..48d32de2a 100644 --- a/src/Services/Basket/Basket.API/Basket.API.csproj +++ b/src/Services/Basket/Basket.API/Basket.API.csproj @@ -16,8 +16,12 @@ + + + + - + diff --git a/src/Services/Basket/Basket.API/Controllers/BasketController.cs b/src/Services/Basket/Basket.API/Controllers/BasketController.cs index dff9ba54a..18a3b221d 100644 --- a/src/Services/Basket/Basket.API/Controllers/BasketController.cs +++ b/src/Services/Basket/Basket.API/Controllers/BasketController.cs @@ -6,6 +6,7 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.Services.Basket.API.Model; using Microsoft.eShopOnContainers.Services.Basket.API.Services; using System; +using System.Net; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers @@ -18,7 +19,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers private readonly IIdentityService _identitySvc; private readonly IEventBus _eventBus; - public BasketController(IBasketRepository repository, + public BasketController(IBasketRepository repository, IIdentityService identityService, IEventBus eventBus) { @@ -26,8 +27,10 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers _identitySvc = identityService; _eventBus = eventBus; } + // GET /id [HttpGet("{id}")] + [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] public async Task Get(string id) { var basket = await _repository.GetBasketAsync(id); @@ -37,6 +40,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers // POST /value [HttpPost] + [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] public async Task Post([FromBody]CustomerBasket value) { var basket = await _repository.UpdateBasketAsync(value); @@ -46,6 +50,8 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers [Route("checkout")] [HttpPost] + [ProducesResponseType((int)HttpStatusCode.Accepted)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] public async Task Checkout([FromBody]BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId) { var userId = _identitySvc.GetUserIdentity(); diff --git a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs new file mode 100644 index 000000000..dfe690f6f --- /dev/null +++ b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs @@ -0,0 +1,79 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Basket.API.Infrastructure.Middlewares +{ + class ByPassAuthMiddleware + { + private readonly RequestDelegate _next; + private string _currentUserId; + public ByPassAuthMiddleware(RequestDelegate next) + { + _next = next; + _currentUserId = null; + } + + + public async Task Invoke(HttpContext context) + { + var path = context.Request.Path; + if (path == "/noauth") + { + var userid = context.Request.Query["userid"]; + if (!string.IsNullOrEmpty(userid)) + { + _currentUserId = userid; + } + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to {_currentUserId}"); + } + + else if (path == "/noauth/reset") + { + _currentUserId = null; + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to none. Token required for protected endpoints."); + } + else + { + var currentUserId = _currentUserId; + + var authHeader = context.Request.Headers["Authorization"]; + if (authHeader != StringValues.Empty) + { + var header = authHeader.FirstOrDefault(); + if (!string.IsNullOrEmpty(header) && header.StartsWith("Email ") && header.Length > "Email ".Length) + { + currentUserId = header.Substring("Email ".Length); + } + } + + + if (!string.IsNullOrEmpty(currentUserId)) + { + var user = new ClaimsIdentity(new[] { + new Claim("emails", currentUserId), + new Claim("name", "Test user"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("ttp://schemas.microsoft.com/identity/claims/identityprovider", "ByPassAuthMiddleware"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","User"), + new Claim("sub", "1234"), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Microsoft")} + , "ByPassAuth"); + + context.User = new ClaimsPrincipal(user); + } + + await _next.Invoke(context); + } + } + } +} diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs index 88244404a..76a78bad7 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs @@ -18,7 +18,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Even public async Task Handle(ProductPriceChangedIntegrationEvent @event) { - var userIds = await _repository.GetUsersAsync(); + var userIds = _repository.GetUsers(); foreach (var id in userIds) { diff --git a/src/Services/Basket/Basket.API/Model/IBasketRepository.cs b/src/Services/Basket/Basket.API/Model/IBasketRepository.cs index fcdc69faa..850b5b637 100644 --- a/src/Services/Basket/Basket.API/Model/IBasketRepository.cs +++ b/src/Services/Basket/Basket.API/Model/IBasketRepository.cs @@ -6,7 +6,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model public interface IBasketRepository { Task GetBasketAsync(string customerId); - Task> GetUsersAsync(); + IEnumerable GetUsers(); Task UpdateBasketAsync(CustomerBasket basket); Task DeleteBasketAsync(string id); } diff --git a/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs b/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs index e896c0773..f748d2c25 100644 --- a/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs +++ b/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Newtonsoft.Json; using StackExchange.Redis; using System.Collections.Generic; @@ -10,40 +9,33 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model { public class RedisBasketRepository : IBasketRepository { - private ILogger _logger; - private BasketSettings _settings; + private readonly ILogger _logger; - private ConnectionMultiplexer _redis; + private readonly ConnectionMultiplexer _redis; + private readonly IDatabase _database; - public RedisBasketRepository(IOptionsSnapshot options, ILoggerFactory loggerFactory) + public RedisBasketRepository(ILoggerFactory loggerFactory, ConnectionMultiplexer redis) { - _settings = options.Value; _logger = loggerFactory.CreateLogger(); + _redis = redis; + _database = redis.GetDatabase(); } public async Task DeleteBasketAsync(string id) { - var database = await GetDatabase(); - return await database.KeyDeleteAsync(id.ToString()); + return await _database.KeyDeleteAsync(id); } - public async Task> GetUsersAsync() + public IEnumerable GetUsers() { - var server = await GetServer(); - - IEnumerable data = server.Keys(); - if (data == null) - { - return null; - } - return data.Select(k => k.ToString()); + var server = GetServer(); + var data = server.Keys(); + return data?.Select(k => k.ToString()); } public async Task GetBasketAsync(string customerId) { - var database = await GetDatabase(); - - var data = await database.StringGetAsync(customerId.ToString()); + var data = await _database.StringGetAsync(customerId); if (data.IsNullOrEmpty) { return null; @@ -54,9 +46,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model public async Task UpdateBasketAsync(CustomerBasket basket) { - var database = await GetDatabase(); - - var created = await database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket)); + var created = await _database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket)); if (!created) { _logger.LogInformation("Problem occur persisting the item."); @@ -68,34 +58,10 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model return await GetBasketAsync(basket.BuyerId); } - private async Task GetDatabase() - { - if (_redis == null) - { - await ConnectToRedisAsync(); - } - - return _redis.GetDatabase(); - } - - private async Task GetServer() + private IServer GetServer() { - if (_redis == null) - { - await ConnectToRedisAsync(); - } var endpoint = _redis.GetEndPoints(); - return _redis.GetServer(endpoint.First()); } - - private async Task ConnectToRedisAsync() - { - var configuration = ConfigurationOptions.Parse(_settings.ConnectionString, true); - configuration.ResolveDns = true; - - _logger.LogInformation($"Connecting to database {configuration.SslHost}."); - _redis = await ConnectionMultiplexer.ConnectAsync(configuration); - } } } diff --git a/src/Services/Basket/Basket.API/Program.cs b/src/Services/Basket/Basket.API/Program.cs index 53b6f311f..19bbf2c24 100644 --- a/src/Services/Basket/Basket.API/Program.cs +++ b/src/Services/Basket/Basket.API/Program.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.IO; @@ -23,12 +24,17 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API .UseHealthChecks("/hc") .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup() + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); }) + .UseApplicationInsights() .Build(); } } diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index df079e4e6..d1550eec8 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -1,8 +1,11 @@ using Autofac; using Autofac.Extensions.DependencyInjection; using Basket.API.Infrastructure.Filters; +using Basket.API.Infrastructure.Middlewares; using Basket.API.IntegrationEvents.EventHandling; using Basket.API.IntegrationEvents.Events; +using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -43,7 +46,9 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API // This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) - { + { + RegisterAppInsights(services); + // Add framework services. services.AddMvc(options => { @@ -61,7 +66,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API ); }); - services.Configure(Configuration); + services.Configure(Configuration); //By connecting here we are making sure that our service //cannot start until redis is ready. This might slow down startup, @@ -72,7 +77,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API services.AddSingleton(sp => { var settings = sp.GetRequiredService>().Value; - var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); + var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); configuration.ResolveDns = true; @@ -103,7 +108,8 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API HostName = Configuration["EventBusConnection"] }; - if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) { + if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) + { factory.UserName = Configuration["EventBusUserName"]; } @@ -112,7 +118,13 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API factory.Password = Configuration["EventBusPassword"]; } - return new DefaultRabbitMQPersistentConnection(factory, logger); + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); }); } @@ -155,7 +167,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API services.AddSingleton(); services.AddTransient(); services.AddTransient(); - + services.AddOptions(); var container = new ContainerBuilder(); @@ -163,18 +175,20 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API return new AutofacServiceProvider(container.Build()); } - - + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); var pathBase = Configuration["PATH_BASE"]; if (!string.IsNullOrEmpty(pathBase)) { app.UsePathBase(pathBase); - } + } + app.UseStaticFiles(); app.UseCors("CorsPolicy"); @@ -185,7 +199,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API app.UseSwagger() .UseSwaggerUI(c => { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "My API V1"); c.ConfigureOAuth2("basketswaggerui", "", "", "Basket Swagger UI"); }); @@ -193,13 +207,31 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } + private void ConfigureAuthService(IServiceCollection services) { // prevent from mapping "sub" claim to nameidentifier. JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - var identityUrl = Configuration.GetValue("IdentityUrl"); - + var identityUrl = Configuration.GetValue("IdentityUrl"); + services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; @@ -215,6 +247,11 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API protected virtual void ConfigureAuth(IApplicationBuilder app) { + if (Configuration.GetValue("UseLoadTest")) + { + app.UseMiddleware(); + } + app.UseAuthentication(); } @@ -236,7 +273,21 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API } else { - services.AddSingleton(); + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount); + }); } services.AddSingleton(); diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index f062f76d7..16d56d94d 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -10,5 +10,9 @@ "IdentityUrl": "http://localhost:5105", "ConnectionString": "127.0.0.1", "AzureServiceBusEnabled": false, - "SubscriptionClientName": "Basket" + "SubscriptionClientName": "Basket", + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "EventBusRetryCount": 5 } \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj index 0d8c77efd..f5aec67ad 100644 --- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj +++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj @@ -34,7 +34,11 @@ - + + + + + diff --git a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs index fe52b9128..1830fd90a 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers @@ -32,6 +33,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers // GET api/v1/[controller]/items[?pageSize=3&pageIndex=10] [HttpGet] [Route("[action]")] + [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] public async Task Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0) { @@ -54,6 +56,8 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers [HttpGet] [Route("items/{id:int}")] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(CatalogItem),(int)HttpStatusCode.OK)] public async Task GetItemById(int id) { if (id <= 0) @@ -73,6 +77,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers // GET api/v1/[controller]/items/withname/samplename[?pageSize=3&pageIndex=10] [HttpGet] [Route("[action]/withname/{name:minlength(1)}")] + [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] public async Task Items(string name, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0) { @@ -97,6 +102,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers // GET api/v1/[controller]/items/type/1/brand/null[?pageSize=3&pageIndex=10] [HttpGet] [Route("[action]/type/{catalogTypeId}/brand/{catalogBrandId}")] + [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] public async Task Items(int? catalogTypeId, int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0) { var root = (IQueryable)_catalogContext.CatalogItems; @@ -130,6 +136,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers // GET api/v1/[controller]/CatalogTypes [HttpGet] [Route("[action]")] + [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] public async Task CatalogTypes() { var items = await _catalogContext.CatalogTypes @@ -141,6 +148,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers // GET api/v1/[controller]/CatalogBrands [HttpGet] [Route("[action]")] + [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] public async Task CatalogBrands() { var items = await _catalogContext.CatalogBrands @@ -152,6 +160,8 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers //PUT api/v1/[controller]/items [Route("items")] [HttpPut] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType((int)HttpStatusCode.Created)] public async Task UpdateProduct([FromBody]CatalogItem productToUpdate) { var catalogItem = await _catalogContext.CatalogItems @@ -192,6 +202,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers //POST api/v1/[controller]/items [Route("items")] [HttpPost] + [ProducesResponseType((int)HttpStatusCode.Created)] public async Task CreateProduct([FromBody]CatalogItem product) { var item = new CatalogItem @@ -213,6 +224,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers //DELETE api/v1/[controller]/id [Route("{id}")] [HttpDelete] + [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task DeleteProduct(int id) { var product = _catalogContext.CatalogItems.SingleOrDefault(x => x.Id == id); diff --git a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs index 7043ce9f7..f8e986e50 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; using System.IO; +using System.Net; using System.Threading.Tasks; // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 @@ -23,6 +24,8 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers [HttpGet] [Route("api/v1/catalog/items/{catalogItemId:int}/pic")] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] // GET: // public async Task GetImage(int catalogItemId) { diff --git a/src/Services/Catalog/Catalog.API/Program.cs b/src/Services/Catalog/Catalog.API/Program.cs index 1eeeeb5ec..bef3fa360 100644 --- a/src/Services/Catalog/Catalog.API/Program.cs +++ b/src/Services/Catalog/Catalog.API/Program.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -31,15 +32,20 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() + .UseApplicationInsights() .UseHealthChecks("/hc") - .UseContentRoot(Directory.GetCurrentDirectory()) + .UseContentRoot(Directory.GetCurrentDirectory()) .UseWebRoot("Pics") + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); - }) + }) .Build(); } } \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index 8bfa347d2..6037b0eb0 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -4,6 +4,8 @@ using Autofac.Extensions.DependencyInjection; using global::Catalog.API.Infrastructure.Filters; using global::Catalog.API.IntegrationEvents; + using Microsoft.ApplicationInsights.Extensibility; + using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Azure.ServiceBus; @@ -35,12 +37,14 @@ Configuration = configuration; } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } public IServiceProvider ConfigureServices(IServiceCollection services) { // Add framework services. + RegisterAppInsights(services); + services.AddHealthChecks(checks => { var minutes = 1; @@ -70,7 +74,7 @@ { sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency - sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); }); // Changing default behavior when client evaluation occurs to throw. @@ -81,11 +85,15 @@ services.AddDbContext(options => { - options.UseSqlServer(Configuration["ConnectionString"], opts => - opts.MigrationsAssembly("Catalog.API")); + options.UseSqlServer(Configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); }); - services.Configure(Configuration); // Add framework services. @@ -149,7 +157,13 @@ factory.Password = Configuration["EventBusPassword"]; } - return new DefaultRabbitMQPersistentConnection(factory, logger); + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); }); } @@ -167,6 +181,8 @@ loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); var pathBase = Configuration["PATH_BASE"]; if (!string.IsNullOrEmpty(pathBase)) @@ -174,7 +190,7 @@ loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); app.UsePathBase(pathBase); } - + app.UseCors("CorsPolicy"); app.UseMvcWithDefaultRoute(); @@ -188,6 +204,24 @@ ConfigureEventBus(app); } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } + private void RegisterEventBus(IServiceCollection services) { if (Configuration.GetValue("AzureServiceBusEnabled")) @@ -207,7 +241,21 @@ } else { - services.AddSingleton(); + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount); + }); } services.AddSingleton(); diff --git a/src/Services/Catalog/Catalog.API/appsettings.json b/src/Services/Catalog/Catalog.API/appsettings.json index dafeca845..abaa34316 100644 --- a/src/Services/Catalog/Catalog.API/appsettings.json +++ b/src/Services/Catalog/Catalog.API/appsettings.json @@ -12,5 +12,9 @@ }, "AzureServiceBusEnabled": false, "AzureStorageEnabled": false, - "SubscriptionClientName": "Catalog" + "SubscriptionClientName": "Catalog", + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "EventBusRetryCount": 5 } diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj index cee95b94f..8d761b9ed 100644 --- a/src/Services/Identity/Identity.API/Identity.API.csproj +++ b/src/Services/Identity/Identity.API/Identity.API.csproj @@ -15,10 +15,14 @@ - + + + + + - - + + @@ -57,7 +61,6 @@ - diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170912114152_Initial.Designer.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170927170433_Config.Designer.cs similarity index 97% rename from src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170912114152_Initial.Designer.cs rename to src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170927170433_Config.Designer.cs index a718c0943..327d2fee0 100644 --- a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170912114152_Initial.Designer.cs +++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170927170433_Config.Designer.cs @@ -11,8 +11,8 @@ using System; namespace Identity.API.Migrations.ConfigurationDb { [DbContext(typeof(ConfigurationDbContext))] - [Migration("20170912114152_Initial")] - partial class Initial + [Migration("20170927170433_Config")] + partial class Config { protected override void BuildTargetModel(ModelBuilder modelBuilder) { @@ -171,7 +171,11 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("BackChannelLogoutSessionRequired"); - b.Property("BackChannelLogoutUri"); + b.Property("BackChannelLogoutUri") + .HasMaxLength(2000); + + b.Property("ClientClaimsPrefix") + .HasMaxLength(200); b.Property("ClientId") .IsRequired() @@ -194,17 +198,18 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("FrontChannelLogoutSessionRequired"); - b.Property("FrontChannelLogoutUri"); + b.Property("FrontChannelLogoutUri") + .HasMaxLength(2000); b.Property("IdentityTokenLifetime"); b.Property("IncludeJwtId"); - b.Property("LogoUri"); - - b.Property("NormalizedClientId"); + b.Property("LogoUri") + .HasMaxLength(2000); - b.Property("PrefixClientClaims"); + b.Property("PairWiseSubjectSalt") + .HasMaxLength(200); b.Property("ProtocolType") .IsRequired() diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170912114152_Initial.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170927170433_Config.cs similarity index 98% rename from src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170912114152_Initial.cs rename to src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170927170433_Config.cs index 257a6adde..754c75486 100644 --- a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170912114152_Initial.cs +++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20170927170433_Config.cs @@ -1,11 +1,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using System; -using System.Collections.Generic; namespace Identity.API.Migrations.ConfigurationDb { - public partial class Initial : Migration + public partial class Config : Migration { protected override void Up(MigrationBuilder migrationBuilder) { @@ -42,7 +41,8 @@ namespace Identity.API.Migrations.ConfigurationDb AlwaysSendClientClaims = table.Column(type: "bit", nullable: false), AuthorizationCodeLifetime = table.Column(type: "int", nullable: false), BackChannelLogoutSessionRequired = table.Column(type: "bit", nullable: false), - BackChannelLogoutUri = table.Column(type: "nvarchar(max)", nullable: true), + BackChannelLogoutUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + ClientClaimsPrefix = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), ClientName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), ClientUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), @@ -51,12 +51,11 @@ namespace Identity.API.Migrations.ConfigurationDb EnableLocalLogin = table.Column(type: "bit", nullable: false), Enabled = table.Column(type: "bit", nullable: false), FrontChannelLogoutSessionRequired = table.Column(type: "bit", nullable: false), - FrontChannelLogoutUri = table.Column(type: "nvarchar(max)", nullable: true), + FrontChannelLogoutUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), IdentityTokenLifetime = table.Column(type: "int", nullable: false), IncludeJwtId = table.Column(type: "bit", nullable: false), - LogoUri = table.Column(type: "nvarchar(max)", nullable: true), - NormalizedClientId = table.Column(type: "nvarchar(max)", nullable: true), - PrefixClientClaims = table.Column(type: "bit", nullable: false), + LogoUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + PairWiseSubjectSalt = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), ProtocolType = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), RefreshTokenExpiration = table.Column(type: "int", nullable: false), RefreshTokenUsage = table.Column(type: "int", nullable: false), diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs index 560c5ea89..88d9baba3 100644 --- a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs +++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs @@ -170,7 +170,11 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("BackChannelLogoutSessionRequired"); - b.Property("BackChannelLogoutUri"); + b.Property("BackChannelLogoutUri") + .HasMaxLength(2000); + + b.Property("ClientClaimsPrefix") + .HasMaxLength(200); b.Property("ClientId") .IsRequired() @@ -193,17 +197,18 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("FrontChannelLogoutSessionRequired"); - b.Property("FrontChannelLogoutUri"); + b.Property("FrontChannelLogoutUri") + .HasMaxLength(2000); b.Property("IdentityTokenLifetime"); b.Property("IncludeJwtId"); - b.Property("LogoUri"); - - b.Property("NormalizedClientId"); + b.Property("LogoUri") + .HasMaxLength(2000); - b.Property("PrefixClientClaims"); + b.Property("PairWiseSubjectSalt") + .HasMaxLength(200); b.Property("ProtocolType") .IsRequired() diff --git a/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170912114120_Initial.Designer.cs b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170927170423_Grants.Designer.cs similarity index 96% rename from src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170912114120_Initial.Designer.cs rename to src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170927170423_Grants.Designer.cs index 72f0df362..aaf24d10c 100644 --- a/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170912114120_Initial.Designer.cs +++ b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170927170423_Grants.Designer.cs @@ -10,8 +10,8 @@ using System; namespace Identity.API.Migrations.PersistedGrantDb { [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20170912114120_Initial")] - partial class Initial + [Migration("20170927170423_Grants")] + partial class Grants { protected override void BuildTargetModel(ModelBuilder modelBuilder) { diff --git a/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170912114120_Initial.cs b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170927170423_Grants.cs similarity index 95% rename from src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170912114120_Initial.cs rename to src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170927170423_Grants.cs index 44bd9fed1..4017f8bf0 100644 --- a/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170912114120_Initial.cs +++ b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20170927170423_Grants.cs @@ -1,10 +1,9 @@ using Microsoft.EntityFrameworkCore.Migrations; using System; -using System.Collections.Generic; namespace Identity.API.Migrations.PersistedGrantDb { - public partial class Initial : Migration + public partial class Grants : Migration { protected override void Up(MigrationBuilder migrationBuilder) { diff --git a/src/Services/Identity/Identity.API/Program.cs b/src/Services/Identity/Identity.API/Program.cs index 0b32b4549..7b73838e6 100644 --- a/src/Services/Identity/Identity.API/Program.cs +++ b/src/Services/Identity/Identity.API/Program.cs @@ -43,12 +43,17 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup() + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); }) + .UseApplicationInsights() .Build(); } } diff --git a/src/Services/Identity/Identity.API/Startup.cs b/src/Services/Identity/Identity.API/Startup.cs index 8dc48d7ae..9b3a3a4c3 100644 --- a/src/Services/Identity/Identity.API/Startup.cs +++ b/src/Services/Identity/Identity.API/Startup.cs @@ -1,6 +1,8 @@ using Autofac; using Autofac.Extensions.DependencyInjection; using IdentityServer4.Services; +using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Identity; @@ -31,14 +33,21 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API // This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) { + RegisterAppInsights(services); + // Add framework services. services.AddDbContext(options => - options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); + options.UseSqlServer(Configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + })); services.AddIdentity() .AddEntityFrameworkStores() - .AddDefaultTokenProviders() - .AddIdentityServer(); + .AddDefaultTokenProviders(); services.Configure(Configuration); @@ -60,7 +69,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API { minutes = minutesParsed; } - checks.AddSqlCheck("Identity_Db", Configuration.GetConnectionString("DefaultConnection"), TimeSpan.FromMinutes(minutes)); + checks.AddSqlCheck("Identity_Db", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes)); }); services.AddTransient(); @@ -68,7 +77,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API services.AddTransient, EFLoginService>(); services.AddTransient(); - var connectionString = Configuration.GetConnectionString("DefaultConnection"); + var connectionString = Configuration["ConnectionString"]; var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; // Adds IdentityServer @@ -77,13 +86,23 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API .AddAspNetIdentity() .AddConfigurationStore(options => { - options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, opts => - opts.MigrationsAssembly(migrationsAssembly)); + options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(migrationsAssembly); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); }) .AddOperationalStore(options => { - options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, opts => - opts.MigrationsAssembly(migrationsAssembly)); + options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(migrationsAssembly); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); }) .Services.AddTransient(); @@ -98,6 +117,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); if (env.IsDevelopment()) { @@ -138,5 +159,23 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API template: "{controller=Home}/{action=Index}/{id?}"); }); } + + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } } } diff --git a/src/Services/Identity/Identity.API/appsettings.json b/src/Services/Identity/Identity.API/appsettings.json index 09142603a..05e06c441 100644 --- a/src/Services/Identity/Identity.API/appsettings.json +++ b/src/Services/Identity/Identity.API/appsettings.json @@ -1,7 +1,5 @@ { - "ConnectionStrings": { - "DefaultConnection": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word;" - }, + "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word;", "IsClusterEnv": "False", "MvcClient": "http://localhost:5100", "SpaClient": "http://localhost:5104", @@ -14,5 +12,8 @@ "System": "Information", "Microsoft": "Information" } + }, + "ApplicationInsights": { + "InstrumentationKey": "" } } diff --git a/src/Services/Location/Locations.API/Controllers/LocationsController.cs b/src/Services/Location/Locations.API/Controllers/LocationsController.cs index a61c7f2d0..45f4d2ba7 100644 --- a/src/Services/Location/Locations.API/Controllers/LocationsController.cs +++ b/src/Services/Location/Locations.API/Controllers/LocationsController.cs @@ -1,8 +1,11 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services; +using Microsoft.eShopOnContainers.Services.Locations.API.Model; using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; using System; +using System.Collections.Generic; +using System.Net; using System.Threading.Tasks; namespace Locations.API.Controllers @@ -23,6 +26,7 @@ namespace Locations.API.Controllers //GET api/v1/[controller]/user/1 [Route("user/{userId:guid}")] [HttpGet] + [ProducesResponseType(typeof(UserLocation), (int)HttpStatusCode.OK)] public async Task GetUserLocation(Guid userId) { var userLocation = await _locationsService.GetUserLocation(userId.ToString()); @@ -32,6 +36,7 @@ namespace Locations.API.Controllers //GET api/v1/[controller]/ [Route("")] [HttpGet] + //[ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] public async Task GetAllLocations() { var locations = await _locationsService.GetAllLocation(); @@ -41,6 +46,7 @@ namespace Locations.API.Controllers //GET api/v1/[controller]/1 [Route("{locationId}")] [HttpGet] + //[ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] public async Task GetLocation(int locationId) { var location = await _locationsService.GetLocation(locationId); @@ -50,6 +56,8 @@ namespace Locations.API.Controllers //POST api/v1/[controller]/ [Route("")] [HttpPost] + [ProducesResponseType((int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] public async Task CreateOrUpdateUserLocation([FromBody]LocationRequest newLocReq) { var userId = _identityService.GetUserIdentity(); diff --git a/src/Services/Location/Locations.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs b/src/Services/Location/Locations.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs new file mode 100644 index 000000000..6814383b6 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs @@ -0,0 +1,78 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Middlewares +{ + class ByPassAuthMiddleware + { + private readonly RequestDelegate _next; + private string _currentUserId; + public ByPassAuthMiddleware(RequestDelegate next) + { + _next = next; + _currentUserId = null; + } + + + public async Task Invoke(HttpContext context) + { + var path = context.Request.Path; + if (path == "/noauth") + { + var userid = context.Request.Query["userid"]; + if (!string.IsNullOrEmpty(userid)) + { + _currentUserId = userid; + } + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to {_currentUserId}"); + } + + else if (path == "/noauth/reset") + { + _currentUserId = null; + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to none. Token required for protected endpoints."); + } + else + { + var currentUserId = _currentUserId; + + var authHeader = context.Request.Headers["Authorization"]; + if (authHeader != StringValues.Empty) + { + var header = authHeader.FirstOrDefault(); + if (!string.IsNullOrEmpty(header) && header.StartsWith("Email ") && header.Length > "Email ".Length) + { + currentUserId = header.Substring("Email ".Length); + } + } + + + if (!string.IsNullOrEmpty(currentUserId)) + { + var user = new ClaimsIdentity(new[] { + new Claim("emails", currentUserId), + new Claim("name", "Test user"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("ttp://schemas.microsoft.com/identity/claims/identityprovider", "ByPassAuthMiddleware"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","User"), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Microsoft")} + , "ByPassAuth"); + + context.User = new ClaimsPrincipal(user); + } + + await _next.Invoke(context); + } + } + } +} diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj index b1b322708..9ccf4337c 100644 --- a/src/Services/Location/Locations.API/Locations.API.csproj +++ b/src/Services/Location/Locations.API/Locations.API.csproj @@ -7,10 +7,11 @@ aspnet-Locations.API-20161122013619 - - - - + + + + + diff --git a/src/Services/Location/Locations.API/Program.cs b/src/Services/Location/Locations.API/Program.cs index 7ebc0ab8a..85f3191cc 100644 --- a/src/Services/Location/Locations.API/Program.cs +++ b/src/Services/Location/Locations.API/Program.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.IO; @@ -18,11 +19,17 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API .UseHealthChecks("/hc") .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup() + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); - }).Build(); + }) + .UseApplicationInsights() + .Build(); } } diff --git a/src/Services/Location/Locations.API/Startup.cs b/src/Services/Location/Locations.API/Startup.cs index 39e6a20bd..0cf49a3b5 100644 --- a/src/Services/Location/Locations.API/Startup.cs +++ b/src/Services/Location/Locations.API/Startup.cs @@ -1,5 +1,7 @@ using Autofac; using Autofac.Extensions.DependencyInjection; +using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -11,6 +13,7 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure; using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters; +using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Middlewares; using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories; using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services; using Microsoft.Extensions.Configuration; @@ -37,6 +40,8 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API public IServiceProvider ConfigureServices(IServiceCollection services) { + RegisterAppInsights(services); + services.AddMvc(options => { options.Filters.Add(typeof(HttpGlobalExceptionFilter)); @@ -79,7 +84,13 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API factory.Password = Configuration["EventBusPassword"]; } - return new DefaultRabbitMQPersistentConnection(factory, logger); + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); }); } @@ -142,6 +153,9 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + var pathBase = Configuration["PATH_BASE"]; if (!string.IsNullOrEmpty(pathBase)) { @@ -157,7 +171,7 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API app.UseSwagger() .UseSwaggerUI(c => { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "My API V1"); c.ConfigureOAuth2("locationsswaggerui", "", "", "Locations Swagger UI"); }); @@ -165,6 +179,24 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API .Wait(); } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } + private void ConfigureAuthService(IServiceCollection services) { // prevent from mapping "sub" claim to nameidentifier. @@ -185,6 +217,11 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API protected virtual void ConfigureAuth(IApplicationBuilder app) { + if (Configuration.GetValue("UseLoadTest")) + { + app.UseMiddleware(); + } + app.UseAuthentication(); } @@ -206,7 +243,21 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API } else { - services.AddSingleton(); + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount); + }); } services.AddSingleton(); diff --git a/src/Services/Location/Locations.API/appsettings.json b/src/Services/Location/Locations.API/appsettings.json index 511bb5c6a..512b55f2a 100644 --- a/src/Services/Location/Locations.API/appsettings.json +++ b/src/Services/Location/Locations.API/appsettings.json @@ -11,5 +11,9 @@ } }, "AzureServiceBusEnabled": false, - "SubscriptionClientName": "Locations" + "SubscriptionClientName": "Locations", + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "EventBusRetryCount": 5 } \ No newline at end of file diff --git a/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs b/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs index 146802626..313d4d77b 100644 --- a/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs +++ b/src/Services/Marketing/Marketing.API/Controllers/CampaignsController.cs @@ -16,6 +16,7 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers using Extensions.Options; using Microsoft.eShopOnContainers.Services.Marketing.API.ViewModel; using Microsoft.AspNetCore.Http; + using System.Net; [Route("api/v1/[controller]")] [Authorize] @@ -38,6 +39,7 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers } [HttpGet] + [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] public async Task GetAllCampaigns() { var campaignList = await _context.Campaigns @@ -54,6 +56,8 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers } [HttpGet("{id:int}")] + [ProducesResponseType(typeof(CampaignDTO), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task GetCampaignById(int id) { var campaign = await _context.Campaigns @@ -70,6 +74,8 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers } [HttpPost] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.Created)] public async Task CreateCampaign([FromBody] CampaignDTO campaignDto) { if (campaignDto is null) @@ -86,6 +92,9 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers } [HttpPut("{id:int}")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType((int)HttpStatusCode.Created)] public async Task UpdateCampaign(int id, [FromBody] CampaignDTO campaignDto) { if (id < 1 || campaignDto is null) @@ -111,6 +120,9 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers } [HttpDelete("{id:int}")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task Delete(int id) { if (id < 1) @@ -131,6 +143,7 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers } [HttpGet("user")] + [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] public async Task GetCampaignsByUserId( int pageSize = 10, int pageIndex = 0) { var userId = _identityService.GetUserIdentity(); diff --git a/src/Services/Marketing/Marketing.API/Controllers/LocationsController.cs b/src/Services/Marketing/Marketing.API/Controllers/LocationsController.cs index 57f652d4c..0d47a63a4 100644 --- a/src/Services/Marketing/Marketing.API/Controllers/LocationsController.cs +++ b/src/Services/Marketing/Marketing.API/Controllers/LocationsController.cs @@ -7,6 +7,7 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers using Microsoft.eShopOnContainers.Services.Marketing.API.Model; using System.Collections.Generic; using System.Linq; + using System.Net; using System.Threading.Tasks; [Authorize] @@ -21,6 +22,9 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers [HttpGet] [Route("api/v1/campaigns/{campaignId:int}/locations/{userLocationRuleId:int}")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType(typeof(UserLocationRuleDTO),(int)HttpStatusCode.OK)] public IActionResult GetLocationByCampaignAndLocationRuleId(int campaignId, int userLocationRuleId) { @@ -45,6 +49,9 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers [HttpGet] [Route("api/v1/campaigns/{campaignId:int}/locations")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] public IActionResult GetAllLocationsByCampaignId(int campaignId) { if (campaignId < 1) @@ -69,6 +76,8 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers [HttpPost] [Route("api/v1/campaigns/{campaignId:int}/locations")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.Created)] public async Task CreateLocation(int campaignId, [FromBody] UserLocationRuleDTO locationRuleDto) { @@ -89,6 +98,8 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers [HttpDelete] [Route("api/v1/campaigns/{campaignId:int}/locations/{userLocationRuleId:int}")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task DeleteLocationById(int campaignId, int userLocationRuleId) { if (campaignId < 1 || userLocationRuleId < 1) diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs b/src/Services/Marketing/Marketing.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs new file mode 100644 index 000000000..8830e3b90 --- /dev/null +++ b/src/Services/Marketing/Marketing.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs @@ -0,0 +1,78 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Middlewares +{ + class ByPassAuthMiddleware + { + private readonly RequestDelegate _next; + private string _currentUserId; + public ByPassAuthMiddleware(RequestDelegate next) + { + _next = next; + _currentUserId = null; + } + + + public async Task Invoke(HttpContext context) + { + var path = context.Request.Path; + if (path == "/noauth") + { + var userid = context.Request.Query["userid"]; + if (!string.IsNullOrEmpty(userid)) + { + _currentUserId = userid; + } + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to {_currentUserId}"); + } + + else if (path == "/noauth/reset") + { + _currentUserId = null; + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to none. Token required for protected endpoints."); + } + else + { + var currentUserId = _currentUserId; + + var authHeader = context.Request.Headers["Authorization"]; + if (authHeader != StringValues.Empty) + { + var header = authHeader.FirstOrDefault(); + if (!string.IsNullOrEmpty(header) && header.StartsWith("Email ") && header.Length > "Email ".Length) + { + currentUserId = header.Substring("Email ".Length); + } + } + + + if (!string.IsNullOrEmpty(currentUserId)) + { + var user = new ClaimsIdentity(new[] { + new Claim("emails", currentUserId), + new Claim("name", "Test user"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("ttp://schemas.microsoft.com/identity/claims/identityprovider", "ByPassAuthMiddleware"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","User"), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Microsoft")} + , "ByPassAuth"); + + context.User = new ClaimsPrincipal(user); + } + + await _next.Invoke(context); + } + } + } +} diff --git a/src/Services/Marketing/Marketing.API/Marketing.API.csproj b/src/Services/Marketing/Marketing.API/Marketing.API.csproj index 2afba2204..373bda483 100644 --- a/src/Services/Marketing/Marketing.API/Marketing.API.csproj +++ b/src/Services/Marketing/Marketing.API/Marketing.API.csproj @@ -7,9 +7,12 @@ $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; aspnet-Marketing.API-20161122013619 + /subscriptions/6c22bb55-0221-4ce4-9bf1-3c4a10a7294c/resourcegroups/eshop-log/providers/microsoft.insights/components/eshopappinsights + /subscriptions/6c22bb55-0221-4ce4-9bf1-3c4a10a7294c/resourcegroups/eshop-log/providers/microsoft.insights/components/eshopappinsights + PreserveNewest @@ -17,7 +20,11 @@ - + + + + + @@ -45,4 +52,8 @@ PreserveNewest + + + + diff --git a/src/Services/Marketing/Marketing.API/Program.cs b/src/Services/Marketing/Marketing.API/Program.cs index 32852073c..70b2362e1 100644 --- a/src/Services/Marketing/Marketing.API/Program.cs +++ b/src/Services/Marketing/Marketing.API/Program.cs @@ -3,6 +3,7 @@ using AspNetCore.Hosting; using Microsoft.AspNetCore; using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure; + using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System.IO; @@ -25,15 +26,22 @@ public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) + .UseApplicationInsights() .UseHealthChecks("/hc") .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup() .UseWebRoot("Pics") + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); - }).Build(); + }) + .UseApplicationInsights() + .Build(); } } diff --git a/src/Services/Marketing/Marketing.API/Properties/launchSettings.json b/src/Services/Marketing/Marketing.API/Properties/launchSettings.json index ec47d57ce..e222e065d 100644 --- a/src/Services/Marketing/Marketing.API/Properties/launchSettings.json +++ b/src/Services/Marketing/Marketing.API/Properties/launchSettings.json @@ -11,7 +11,7 @@ "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, - "launchUrl": "api/values", + "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } @@ -19,7 +19,7 @@ "Marketing.API": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "api/values", + "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, diff --git a/src/Services/Marketing/Marketing.API/Startup.cs b/src/Services/Marketing/Marketing.API/Startup.cs index 4dd50e7d4..461ecc080 100644 --- a/src/Services/Marketing/Marketing.API/Startup.cs +++ b/src/Services/Marketing/Marketing.API/Startup.cs @@ -21,8 +21,11 @@ using Infrastructure.Services; using IntegrationEvents.Events; using Marketing.API.IntegrationEvents.Handlers; + using Microsoft.ApplicationInsights.Extensibility; + using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore.Diagnostics; + using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Middlewares; using RabbitMQ.Client; using Swashbuckle.AspNetCore.Swagger; using System; @@ -44,6 +47,8 @@ // This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) { + RegisterAppInsights(services); + // Add framework services. services.AddMvc(options => { @@ -73,7 +78,7 @@ { sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency - sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); }); // Changing default behavior when client evaluation occurs to throw. @@ -114,7 +119,14 @@ { factory.Password = Configuration["EventBusPassword"]; } - return new DefaultRabbitMQPersistentConnection(factory, logger); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); }); } @@ -172,6 +184,9 @@ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory) { + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + var pathBase = Configuration["PATH_BASE"]; if (!string.IsNullOrEmpty(pathBase)) @@ -188,13 +203,31 @@ app.UseSwagger() .UseSwaggerUI(c => { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "My API V1"); c.ConfigureOAuth2("marketingswaggerui", "", "", "Marketing Swagger UI"); }); ConfigureEventBus(app); } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } + private void ConfigureAuthService(IServiceCollection services) { // prevent from mapping "sub" claim to nameidentifier. @@ -231,7 +264,21 @@ } else { - services.AddSingleton(); + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount); + }); } services.AddSingleton(); @@ -246,6 +293,11 @@ protected virtual void ConfigureAuth(IApplicationBuilder app) { + if (Configuration.GetValue("UseLoadTest")) + { + app.UseMiddleware(); + } + app.UseAuthentication(); } } diff --git a/src/Services/Marketing/Marketing.API/appsettings.Development.json b/src/Services/Marketing/Marketing.API/appsettings.Development.json deleted file mode 100644 index 5fff67bac..000000000 --- a/src/Services/Marketing/Marketing.API/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - } - } -} diff --git a/src/Services/Marketing/Marketing.API/appsettings.json b/src/Services/Marketing/Marketing.API/appsettings.json index 21aae065a..c4d908c83 100644 --- a/src/Services/Marketing/Marketing.API/appsettings.json +++ b/src/Services/Marketing/Marketing.API/appsettings.json @@ -1,4 +1,4 @@ -{ +{ "Logging": { "IncludeScopes": false, "LogLevel": { @@ -12,6 +12,9 @@ "PicBaseUrl": "http://localhost:5110/api/v1/campaigns/[0]/pic/", "AzureServiceBusEnabled": false, "SubscriptionClientName": "Marketing", - "AzureStorageEnabled": false - -} + "AzureStorageEnabled": false, + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "EventBusRetryCount": 5 +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs index 1e40910be..c43e65d63 100644 --- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs +++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs @@ -7,6 +7,7 @@ using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; using Ordering.API.Application.Commands; using System; using System.Collections.Generic; +using System.Net; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers @@ -29,6 +30,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers [Route("cancel")] [HttpPut] + [ProducesResponseType((int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] public async Task CancelOrder([FromBody]CancelOrderCommand command, [FromHeader(Name = "x-requestid")] string requestId) { bool commandResult = false; @@ -44,6 +47,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers [Route("ship")] [HttpPut] + [ProducesResponseType((int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] public async Task ShipOrder([FromBody]ShipOrderCommand command, [FromHeader(Name = "x-requestid")] string requestId) { bool commandResult = false; @@ -59,6 +64,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers [Route("{orderId:int}")] [HttpGet] + [ProducesResponseType((int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task GetOrder(int orderId) { try diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/GracePeriodManagerService.cs b/src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/GracePeriodManagerService.cs index f38fc8fd8..3fa70e20b 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/GracePeriodManagerService.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/HostedServices/GracePeriodManagerService.cs @@ -71,7 +71,7 @@ { conn.Open(); orderIds = conn.Query( - @"SELECT Id FROM [Microsoft.eShopOnContainers.Services.OrderingDb].[ordering].[orders] + @"SELECT Id FROM [ordering].[orders] WHERE DATEDIFF(minute, [OrderDate], GETDATE()) >= @GracePeriodTime AND [OrderStatusId] = 1", new { GracePeriodTime = _settings.GracePeriodTime }); diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs new file mode 100644 index 000000000..426381448 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Middlewares/ByPassAuthMiddleware.cs @@ -0,0 +1,78 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Ordering.API.Infrastructure.Middlewares +{ + class ByPassAuthMiddleware + { + private readonly RequestDelegate _next; + private string _currentUserId; + public ByPassAuthMiddleware(RequestDelegate next) + { + _next = next; + _currentUserId = null; + } + + + public async Task Invoke(HttpContext context) + { + var path = context.Request.Path; + if (path == "/noauth") + { + var userid = context.Request.Query["userid"]; + if (!string.IsNullOrEmpty(userid)) + { + _currentUserId = userid; + } + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to {_currentUserId}"); + } + + else if (path == "/noauth/reset") + { + _currentUserId = null; + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to none. Token required for protected endpoints."); + } + else + { + var currentUserId = _currentUserId; + + var authHeader = context.Request.Headers["Authorization"]; + if (authHeader != StringValues.Empty) + { + var header = authHeader.FirstOrDefault(); + if (!string.IsNullOrEmpty(header) && header.StartsWith("Email ") && header.Length > "Email ".Length) + { + currentUserId = header.Substring("Email ".Length); + } + } + + + if (!string.IsNullOrEmpty(currentUserId)) + { + var user = new ClaimsIdentity(new[] { + new Claim("emails", currentUserId), + new Claim("name", "Test user"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("ttp://schemas.microsoft.com/identity/claims/identityprovider", "ByPassAuthMiddleware"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","User"), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Microsoft")} + , "ByPassAuth"); + + context.User = new ClaimsPrincipal(user); + } + + await _next.Invoke(context); + } + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Ordering.API.csproj b/src/Services/Ordering/Ordering.API/Ordering.API.csproj index 123f9e838..9dee34091 100644 --- a/src/Services/Ordering/Ordering.API/Ordering.API.csproj +++ b/src/Services/Ordering/Ordering.API/Ordering.API.csproj @@ -33,10 +33,13 @@ - - + - + + + + + @@ -50,10 +53,6 @@ - - - - Always @@ -63,8 +62,4 @@ - - - - diff --git a/src/Services/Ordering/Ordering.API/Program.cs b/src/Services/Ordering/Ordering.API/Program.cs index 46221b42c..011f3004f 100644 --- a/src/Services/Ordering/Ordering.API/Program.cs +++ b/src/Services/Ordering/Ordering.API/Program.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -30,16 +31,22 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API } public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) + WebHost.CreateDefaultBuilder(args) .UseStartup() .UseHealthChecks("/hc") .UseContentRoot(Directory.GetCurrentDirectory()) + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddJsonFile("settings.json"); + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); }) + .UseApplicationInsights() .Build(); } } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 3ddd178c5..76cb274e7 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -7,9 +7,12 @@ using global::Ordering.API.Application.IntegrationEvents.Events; using global::Ordering.API.Infrastructure.Filters; using global::Ordering.API.Infrastructure.HostedServices; + using global::Ordering.API.Infrastructure.Middlewares; using Infrastructure.AutofacModules; using Infrastructure.Filters; using Infrastructure.Services; + using Microsoft.ApplicationInsights.Extensibility; + using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -46,6 +49,8 @@ public IServiceProvider ConfigureServices(IServiceCollection services) { + RegisterAppInsights(services); + // Add framework services. services.AddMvc(options => { @@ -75,7 +80,7 @@ sqlServerOptionsAction: sqlOptions => { sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); - sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); }); }, ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request) @@ -83,10 +88,13 @@ services.AddDbContext(options => { - options.UseSqlServer(Configuration["ConnectionString"], opts => - { - opts.MigrationsAssembly("Ordering.API"); - }); + options.UseSqlServer(Configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); }); @@ -169,7 +177,13 @@ factory.Password = Configuration["EventBusPassword"]; } - return new DefaultRabbitMQPersistentConnection(factory, logger); + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); }); } @@ -193,6 +207,8 @@ { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); var pathBase = Configuration["PATH_BASE"]; if (!string.IsNullOrEmpty(pathBase)) @@ -200,7 +216,7 @@ loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); app.UsePathBase(pathBase); } - + app.UseCors("CorsPolicy"); ConfigureAuth(app); @@ -209,13 +225,31 @@ app.UseSwagger() .UseSwaggerUI(c => { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "My API V1"); c.ConfigureOAuth2("orderingswaggerui", "", "", "Ordering Swagger UI"); }); ConfigureEventBus(app); } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } + private void ConfigureEventBus(IApplicationBuilder app) { var eventBus = app.ApplicationServices.GetRequiredService(); @@ -250,6 +284,11 @@ protected virtual void ConfigureAuth(IApplicationBuilder app) { + if (Configuration.GetValue("UseLoadTest")) + { + app.UseMiddleware(); + } + app.UseAuthentication(); } @@ -271,7 +310,21 @@ } else { - services.AddSingleton(); + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount); + }); } services.AddSingleton(); diff --git a/src/Services/Ordering/Ordering.API/settings.json b/src/Services/Ordering/Ordering.API/settings.json index d2068fcab..61ebe5325 100644 --- a/src/Services/Ordering/Ordering.API/settings.json +++ b/src/Services/Ordering/Ordering.API/settings.json @@ -13,5 +13,9 @@ "AzureServiceBusEnabled": false, "SubscriptionClientName": "Ordering", "GracePeriodTime": "1", - "CheckUpdateTime": "30000" + "CheckUpdateTime": "30000", + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "EventBusRetryCount": 5 } diff --git a/src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj b/src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj index 2673abf84..e8f232b76 100644 --- a/src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj +++ b/src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj @@ -1,20 +1,17 @@  - netstandard1.4 - Ordering.Domain - 2.0.0-preview1-25301-01 - Ordering.Domain - $(AssetTargetFallback);dnxcore50; - false - false - false + netstandard2.0 - - + + + + + + diff --git a/src/Services/Ordering/Ordering.Domain/Properties/AssemblyInfo.cs b/src/Services/Ordering/Ordering.Domain/Properties/AssemblyInfo.cs deleted file mode 100644 index a16c5b744..000000000 --- a/src/Services/Ordering/Ordering.Domain/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Microsoft.eShopOnContainers.Services.Ordering.Domain")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f5598dcb-6dde-4661-ad9d-a55612da7e76")] diff --git a/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj b/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj index fdd0bfa53..c13f431e0 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj +++ b/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj @@ -2,12 +2,6 @@ netstandard2.0 - Ordering.Infrastructure - Ordering.Infrastructure - $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; - false - false - false @@ -20,4 +14,8 @@ + + + + diff --git a/src/Services/Ordering/Ordering.Infrastructure/Properties/AssemblyInfo.cs b/src/Services/Ordering/Ordering.Infrastructure/Properties/AssemblyInfo.cs deleted file mode 100644 index 00732b2ad..000000000 --- a/src/Services/Ordering/Ordering.Infrastructure/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Ordering.Infrastructure")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("95f1f07c-4d92-4742-bd07-e5b805aab651")] diff --git a/src/Services/Payment/Payment.API/Payment.API.csproj b/src/Services/Payment/Payment.API/Payment.API.csproj index 5b7fe983b..1d5493776 100644 --- a/src/Services/Payment/Payment.API/Payment.API.csproj +++ b/src/Services/Payment/Payment.API/Payment.API.csproj @@ -7,8 +7,13 @@ - + + + + + + diff --git a/src/Services/Payment/Payment.API/Program.cs b/src/Services/Payment/Payment.API/Program.cs index a373e2695..aff7bf359 100644 --- a/src/Services/Payment/Payment.API/Program.cs +++ b/src/Services/Payment/Payment.API/Program.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.IO; @@ -18,11 +19,17 @@ namespace Payment.API .UseHealthChecks("/hc") .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup() + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); - }).Build(); + }) + .UseApplicationInsights() + .Build(); } } diff --git a/src/Services/Payment/Payment.API/Startup.cs b/src/Services/Payment/Payment.API/Startup.cs index c26d0935a..4ddf7cebc 100644 --- a/src/Services/Payment/Payment.API/Startup.cs +++ b/src/Services/Payment/Payment.API/Startup.cs @@ -16,6 +16,9 @@ using Payment.API.IntegrationEvents.Events; using RabbitMQ.Client; using System; using System.Threading.Tasks; +using Swashbuckle.AspNetCore.Swagger; +using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.ApplicationInsights.ServiceFabric; namespace Payment.API { @@ -30,10 +33,11 @@ namespace Payment.API // This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) - { - + { services.Configure(Configuration); + RegisterAppInsights(services); + if (Configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => @@ -66,7 +70,13 @@ namespace Payment.API factory.Password = Configuration["EventBusPassword"]; } - return new DefaultRabbitMQPersistentConnection(factory, logger); + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); }); } @@ -83,8 +93,11 @@ namespace Payment.API } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + var pathBase = Configuration["PATH_BASE"]; if (!string.IsNullOrEmpty(pathBase)) { @@ -94,6 +107,24 @@ namespace Payment.API ConfigureEventBus(app); } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } + private void RegisterEventBus(IServiceCollection services) { if (Configuration.GetValue("AzureServiceBusEnabled")) @@ -112,7 +143,21 @@ namespace Payment.API } else { - services.AddSingleton(); + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount); + }); } services.AddTransient(); diff --git a/src/Services/Payment/Payment.API/appsettings.json b/src/Services/Payment/Payment.API/appsettings.json index 9aef99a14..acc9a2be0 100644 --- a/src/Services/Payment/Payment.API/appsettings.json +++ b/src/Services/Payment/Payment.API/appsettings.json @@ -7,5 +7,9 @@ }, "PaymentSucceded": true, "AzureServiceBusEnabled": false, - "SubscriptionClientName": "Payment" + "SubscriptionClientName": "Payment", + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "EventBusRetryCount": 5 } diff --git a/src/Web/WebMVC/Infrastructure/Middlewares/ByPassAuthMiddleware.cs b/src/Web/WebMVC/Infrastructure/Middlewares/ByPassAuthMiddleware.cs new file mode 100644 index 000000000..72adaaa4d --- /dev/null +++ b/src/Web/WebMVC/Infrastructure/Middlewares/ByPassAuthMiddleware.cs @@ -0,0 +1,80 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace WebMVC.Infrastructure.Middlewares +{ + class ByPassAuthMiddleware + { + private readonly RequestDelegate _next; + private string _currentUserId; + public ByPassAuthMiddleware(RequestDelegate next) + { + _next = next; + _currentUserId = null; + } + + + public async Task Invoke(HttpContext context) + { + var path = context.Request.Path; + if (path == "/noauth") + { + var userid = context.Request.Query["userid"]; + if (!string.IsNullOrEmpty(userid)) + { + _currentUserId = userid; + } + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to {_currentUserId}"); + } + + else if (path == "/noauth/reset") + { + _currentUserId = null; + context.Response.StatusCode = 200; + context.Response.ContentType = "text/string"; + await context.Response.WriteAsync($"User set to none. Token required for protected endpoints."); + } + else + { + var currentUserId = _currentUserId; + + var authHeader = context.Request.Headers["Authorization"]; + if (authHeader != StringValues.Empty) + { + var header = authHeader.FirstOrDefault(); + if (!string.IsNullOrEmpty(header) && header.StartsWith("Email ") && header.Length > "Email ".Length) + { + currentUserId = header.Substring("Email ".Length); + } + } + + + if (!string.IsNullOrEmpty(currentUserId)) + { + var user = new ClaimsIdentity(new[] { + new Claim("emails", currentUserId), + new Claim("name", "Test user"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("ttp://schemas.microsoft.com/identity/claims/identityprovider", "ByPassAuthMiddleware"), + new Claim("nonce", Guid.NewGuid().ToString()), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","User"), + new Claim("sub", "1234"), + new Claim("card_expiration", "12/20"), + new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Microsoft")} + , "ByPassAuth"); + + context.User = new ClaimsPrincipal(user); + } + + await _next.Invoke(context); + } + } + } +} diff --git a/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs b/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs index b05c6e038..43eac7b30 100644 --- a/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs +++ b/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs @@ -1,4 +1,5 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.AspNetCore.Http; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; using Microsoft.Extensions.Logging; using Polly; using System; @@ -9,12 +10,21 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure public class ResilientHttpClientFactory : IResilientHttpClientFactory { private readonly ILogger _logger; + private readonly int _retryCount; + private readonly int _exceptionsAllowedBeforeBreaking; + private readonly IHttpContextAccessor _httpContextAccessor; - public ResilientHttpClientFactory(ILogger logger) - =>_logger = logger; + public ResilientHttpClientFactory(ILogger logger, IHttpContextAccessor httpContextAccessor, int exceptionsAllowedBeforeBreaking = 5, int retryCount = 6) + { + _logger = logger; + _exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking; + _retryCount = retryCount; + _httpContextAccessor = httpContextAccessor; + } - public ResilientHttpClient CreateResilientHttpClient() - => new ResilientHttpClient((origin) => CreatePolicies(), _logger); + + public ResilientHttpClient CreateResilientHttpClient() + => new ResilientHttpClient((origin) => CreatePolicies(), _logger, _httpContextAccessor); private Policy[] CreatePolicies() => new Policy[] @@ -22,7 +32,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure Policy.Handle() .WaitAndRetryAsync( // number of retries - 6, + _retryCount, // exponential backofff retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), // on retry @@ -36,9 +46,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure _logger.LogDebug(msg); }), Policy.Handle() - .CircuitBreakerAsync( + .CircuitBreakerAsync( // number of exceptions before breaking circuit - 5, + _exceptionsAllowedBeforeBreaking, // time circuit opened before retry TimeSpan.FromMinutes(1), (exception, duration) => @@ -51,6 +61,6 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure // on circuit closed _logger.LogTrace("Circuit breaker reset"); }) - }; + }; } } diff --git a/src/Web/WebMVC/Program.cs b/src/Web/WebMVC/Program.cs index ec711b2ae..07332a02a 100644 --- a/src/Web/WebMVC/Program.cs +++ b/src/Web/WebMVC/Program.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.IO; @@ -17,11 +18,17 @@ namespace Microsoft.eShopOnContainers.WebMVC .UseContentRoot(Directory.GetCurrentDirectory()) .UseHealthChecks("/hc") .UseStartup() + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); - }).Build(); + }) + .UseApplicationInsights() + .Build(); } } diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs index a5b690296..63ce47045 100644 --- a/src/Web/WebMVC/Startup.cs +++ b/src/Web/WebMVC/Startup.cs @@ -1,4 +1,6 @@ -using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.ApplicationInsights.ServiceFabric; +using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -15,6 +17,7 @@ using Microsoft.Extensions.Logging; using System; using System.IdentityModel.Tokens.Jwt; using WebMVC.Infrastructure; +using WebMVC.Infrastructure.Middlewares; using WebMVC.Services; namespace Microsoft.eShopOnContainers.WebMVC @@ -31,6 +34,8 @@ namespace Microsoft.eShopOnContainers.WebMVC // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + RegisterAppInsights(services); + services.AddMvc(); services.AddSession(); @@ -71,7 +76,25 @@ namespace Microsoft.eShopOnContainers.WebMVC if (Configuration.GetValue("UseResilientHttp") == bool.TrueString) { - services.AddSingleton(); + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + var httpContextAccessor = sp.GetRequiredService(); + + var retryCount = 6; + if (!string.IsNullOrEmpty(Configuration["HttpClientRetryCount"])) + { + retryCount = int.Parse(Configuration["HttpClientRetryCount"]); + } + + var exceptionsAllowedBeforeBreaking = 5; + if (!string.IsNullOrEmpty(Configuration["HttpClientExceptionsAllowedBeforeBreaking"])) + { + exceptionsAllowedBeforeBreaking = int.Parse(Configuration["HttpClientExceptionsAllowedBeforeBreaking"]); + } + + return new ResilientHttpClientFactory(logger, httpContextAccessor, exceptionsAllowedBeforeBreaking, retryCount); + }); services.AddSingleton(sp => sp.GetService().CreateResilientHttpClient()); } else @@ -115,6 +138,8 @@ namespace Microsoft.eShopOnContainers.WebMVC loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); if (env.IsDevelopment()) { @@ -136,6 +161,11 @@ namespace Microsoft.eShopOnContainers.WebMVC app.UseSession(); app.UseStaticFiles(); + if (Configuration.GetValue("UseLoadTest")) + { + app.UseMiddleware(); + } + app.UseAuthentication(); var log = loggerFactory.CreateLogger("identity"); @@ -153,5 +183,23 @@ namespace Microsoft.eShopOnContainers.WebMVC template: "{controller=Error}/{action=Error}"); }); } + + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } } } diff --git a/src/Web/WebMVC/WebMVC.csproj b/src/Web/WebMVC/WebMVC.csproj index 3bb66a650..47603f10f 100644 --- a/src/Web/WebMVC/WebMVC.csproj +++ b/src/Web/WebMVC/WebMVC.csproj @@ -7,16 +7,6 @@ ..\..\..\docker-compose.dcproj - - - - - - - - - - PreserveNewest @@ -28,15 +18,13 @@ - - + + + + + @@ -63,10 +51,6 @@ - - - - diff --git a/src/Web/WebMVC/appsettings.json b/src/Web/WebMVC/appsettings.json index a9a73120f..161e247a6 100644 --- a/src/Web/WebMVC/appsettings.json +++ b/src/Web/WebMVC/appsettings.json @@ -18,5 +18,10 @@ "System": "Information", "Microsoft": "Information" } - } + }, + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "HttpClientRetryCount": 8, + "HttpClientExceptionsAllowedBeforeBreaking": 7 } \ No newline at end of file diff --git a/src/Web/WebMonolithic/docker-compose.override.yml b/src/Web/WebMonolithic/docker-compose.override.yml index e908c1de9..436429c19 100644 --- a/src/Web/WebMonolithic/docker-compose.override.yml +++ b/src/Web/WebMonolithic/docker-compose.override.yml @@ -11,7 +11,7 @@ services: sql.data: environment: - - SA_PASSWORD=Pass@word + - MSSQL_SA_PASSWORD=Pass@word - ACCEPT_EULA=Y ports: - "5433:1433" diff --git a/src/Web/WebMonolithic/docker-compose.yml b/src/Web/WebMonolithic/docker-compose.yml index dceec42c5..7ca7e96b5 100644 --- a/src/Web/WebMonolithic/docker-compose.yml +++ b/src/Web/WebMonolithic/docker-compose.yml @@ -9,4 +9,4 @@ services: depends_on: - sql.data sql.data: - image: microsoft/mssql-server-linux + image: microsoft/mssql-server-linux:2017-latest diff --git a/src/Web/WebSPA/Program.cs b/src/Web/WebSPA/Program.cs index 92a6af2da..c1a7da269 100644 --- a/src/Web/WebSPA/Program.cs +++ b/src/Web/WebSPA/Program.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Hosting; using System.IO; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Configuration; namespace eShopConContainers.WebSPA { @@ -17,12 +18,17 @@ namespace eShopConContainers.WebSPA .UseStartup() .UseHealthChecks("/hc") .UseContentRoot(Directory.GetCurrentDirectory()) + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); }) + .UseApplicationInsights() .Build(); } } diff --git a/src/Web/WebSPA/Startup.cs b/src/Web/WebSPA/Startup.cs index 0e9585c8c..243976d8f 100644 --- a/src/Web/WebSPA/Startup.cs +++ b/src/Web/WebSPA/Startup.cs @@ -1,4 +1,6 @@ using eShopOnContainers.WebSPA; +using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -36,6 +38,8 @@ namespace eShopConContainers.WebSPA // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + RegisterAppInsights(services); + services.AddHealthChecks(checks => { var minutes = 1; @@ -76,6 +80,10 @@ namespace eShopConContainers.WebSPA // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery) { + + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); @@ -116,11 +124,29 @@ namespace eShopConContainers.WebSPA await next(); } }); - + app.UseDefaultFiles(); app.UseStaticFiles(); app.UseMvcWithDefaultRoute(); } + + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } } } diff --git a/src/Web/WebSPA/WebSPA.csproj b/src/Web/WebSPA/WebSPA.csproj index 1efcb89e6..308dc5324 100644 --- a/src/Web/WebSPA/WebSPA.csproj +++ b/src/Web/WebSPA/WebSPA.csproj @@ -27,6 +27,10 @@ + + + + diff --git a/src/Web/WebSPA/appsettings.json b/src/Web/WebSPA/appsettings.json index 7f8a004f8..7b1930f84 100644 --- a/src/Web/WebSPA/appsettings.json +++ b/src/Web/WebSPA/appsettings.json @@ -15,5 +15,8 @@ "System": "Information", "Microsoft": "Information" } + }, + "ApplicationInsights": { + "InstrumentationKey": "" } } \ No newline at end of file diff --git a/src/Web/WebStatus/Program.cs b/src/Web/WebStatus/Program.cs index 6a895f9e7..adab0e6b3 100644 --- a/src/Web/WebStatus/Program.cs +++ b/src/Web/WebStatus/Program.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.IO; @@ -16,11 +17,17 @@ namespace WebStatus WebHost.CreateDefaultBuilder(args) .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup() + .ConfigureAppConfiguration((builderContext, config) => + { + config.AddEnvironmentVariables(); + }) .ConfigureLogging((hostingContext, builder) => { builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); builder.AddConsole(); builder.AddDebug(); - }).Build(); + }) + .UseApplicationInsights() + .Build(); } } diff --git a/src/Web/WebStatus/Startup.cs b/src/Web/WebStatus/Startup.cs index acbe9edcb..19aedc449 100644 --- a/src/Web/WebStatus/Startup.cs +++ b/src/Web/WebStatus/Startup.cs @@ -8,6 +8,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using WebStatus.Extensions; +using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.ApplicationInsights.ServiceFabric; namespace WebStatus { @@ -23,6 +25,8 @@ namespace WebStatus // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + RegisterAppInsights(services); + services.AddOptions(); // Add framework services. @@ -49,8 +53,11 @@ namespace WebStatus } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); @@ -76,5 +83,23 @@ namespace WebStatus template: "{controller=Home}/{action=Index}/{id?}"); }); } + + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } } } diff --git a/src/Web/WebStatus/Views/Shared/_Layout.cshtml b/src/Web/WebStatus/Views/Shared/_Layout.cshtml index 0a540f8a3..9c531eec8 100644 --- a/src/Web/WebStatus/Views/Shared/_Layout.cshtml +++ b/src/Web/WebStatus/Views/Shared/_Layout.cshtml @@ -53,7 +53,6 @@ -