From 2220fd20fd57f4524100964531dd1045f3017e49 Mon Sep 17 00:00:00 2001 From: Cesar De la Torre Date: Sat, 22 Apr 2017 21:13:43 -0700 Subject: [PATCH 01/60] Initial commit --- .gitignore | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE | 21 +++++ 2 files changed, 273 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f1e3d20e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,252 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..9a24c91b6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 dotnet-architecture + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 9661b2c047f5ff525f0ab98c54168bef4ccb610f Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Mon, 24 Apr 2017 13:15:54 +0200 Subject: [PATCH 02/60] First deploy scripts --- deploy/az/create-resources.cmd | 5 +++++ deploy/az/mvparams.json | 6 ++++++ deploy/readme.md | 16 ++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 deploy/az/create-resources.cmd create mode 100644 deploy/az/mvparams.json create mode 100644 deploy/readme.md diff --git a/deploy/az/create-resources.cmd b/deploy/az/create-resources.cmd new file mode 100644 index 000000000..c8e317b2d --- /dev/null +++ b/deploy/az/create-resources.cmd @@ -0,0 +1,5 @@ +REM az group create --name eShopOnAzureDev --location westus + +az group deployment create --resource-group eShopOnAzureDev --parameters @mvparams.json ^ + --template-uri https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/docker-simple-on-ubuntu/azuredeploy.json + diff --git a/deploy/az/mvparams.json b/deploy/az/mvparams.json new file mode 100644 index 000000000..c80c82e6c --- /dev/null +++ b/deploy/az/mvparams.json @@ -0,0 +1,6 @@ +{ + "newStorageAccountName": { "value": "eshopsrvmvstorage" }, + "adminUsername": { "value": "eshop" }, + "adminPassword": { "value": "Pass@word" }, + "dnsNameForPublicIP": { "value": "eshop-srv" } +} diff --git a/deploy/readme.md b/deploy/readme.md new file mode 100644 index 000000000..4fd772049 --- /dev/null +++ b/deploy/readme.md @@ -0,0 +1,16 @@ +# Deploying Resources On Azure + +## Pre-requisites +1. [Azure CLI 2.0 Installed](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) +2. Azure subscription created + +## Deploying using CLI + +1. Run `az login` to login into your Azure subscription (note that you maybe need to use `az account set` to set the subscription to use) +2. Edit the file `mvparams.json` with your desired values +3. Run the file `create-resources.cmd` from command-line to create the Linux-based VM with Docker installed + + + + + From 3153bf7654b594b78bc83381c92fc96ce50276cc Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Tue, 25 Apr 2017 11:05:15 +0200 Subject: [PATCH 03/60] Added missing IdSvr certificate! --- .gitignore | 1 - .../Identity.API/Certificate/idsrv3test.pfx | Bin 0 -> 3395 bytes 2 files changed, 1 deletion(-) create mode 100644 src/Services/Identity/Identity.API/Certificate/idsrv3test.pfx diff --git a/.gitignore b/.gitignore index 75d3a4bd2..28ca761bf 100644 --- a/.gitignore +++ b/.gitignore @@ -188,7 +188,6 @@ ClientBin/ *~ *.dbmdl *.dbproj.schemaview -*.pfx *.publishsettings node_modules/ orleans.codegen.cs diff --git a/src/Services/Identity/Identity.API/Certificate/idsrv3test.pfx b/src/Services/Identity/Identity.API/Certificate/idsrv3test.pfx new file mode 100644 index 0000000000000000000000000000000000000000..0247dea03f0cc23694291f21310f3ae88880e2bb GIT binary patch literal 3395 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 V%$88{h~I%@Xjg7x^oQR@_8&Ry9S;Bi literal 0 HcmV?d00001 From fc0a91687ef66d86015c4e4966c7235c75074855 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Tue, 25 Apr 2017 11:22:17 +0200 Subject: [PATCH 04/60] readme updated --- README.md | 99 +++++++------------------------------------------------ 1 file changed, 12 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index a1ae7aff3..2b007b5b0 100644 --- a/README.md +++ b/README.md @@ -1,100 +1,25 @@ -# 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.

+# eShopOnContainers for Azure -> ### DISCLAIMER -> **IMPORTANT:** The current state of this sample application is **BETA**, consider it version a 0.1 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. ->

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. -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 current communication protocol. -

-It also supports asynchronous communication for data updates propagation across multiple services based on Integration Events and an Event Bus 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. -

- -

-

-Additional miroservice 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. - -## Related documentation and guidance -While developing this reference application, we are creating a reference Guide/eBook named "Architecting and Developing Containerized and Microservice based .NET Applications" 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. -

-There are also additional eBooks focusing on Containers/Docker lifecycle (DevOps, CI/CD, etc.) with Microsoft Tools, already published plus an additional eBook focusing on Enterprise Apps Patterns with Xamarin.Forms. -You can download them and start reviewing these Guides/eBooks here: -

- -| Architecting & Developing | Containers Lifecycle & CI/CD | App patterns with Xamarin.Forms | -| ------------ | ------------| ------------| -| | | | -| **Download** (Early DRAFT, still work in progress) | **Download** (First Edition from late 2016) | **Download** (Early DRAFT, still work in progress) | - -Send feedback to [cesardl@microsoft.com](cesardl@microsoft.com) -

-However, we encourage to download and review the "Architecting & Developing eBook" because the architectural styles and architectural patterns and technologies explained in the guidance are using this reference application when explaining many pattern implementations, so you'll understand much better the context, design and decisions taken in the current architecture and internal designs. - -## Overview of the application code -In this repo you can find a sample reference application that will help you to understand how to implement a microservice architecture based application using .NET Core and Docker. +Azure-based version og the eShopOnContainers reference application -The example business domain or scenario is based on an eShop or eCommerce which is implemented as a multi-container application. Each container is a microservice deployment (like the basket-microservice, catalog-microservice, ordering-microservice and the identity-microservice) which are developed using ASP.NET Core running on .NET Core so they can run either on Linux Containers and Windows Containers. -The screenshot below shows the VS Solution structure for those microservices/containers and client apps. +**Please refer to the [original eShopOnContainers](https://github.com/dotnet-architecture/eShopOnContainers) for general info about the project** -- (*Recommended when getting started*) Open eShopOnContainers-ServicesAndWebApps.sln for a solution containing just the server-side projects related to the microservices and web applications. -- Open eShopOnContainers-MobileApps.sln for a solution containing just the client mobile app projects (Xamarin mobile apps only). It works independently based on mocks, too. -- Open eShopOnContainers.sln for a solution containing all the projects (All client apps and services). - - - -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. - -
-*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). - -
-*Xamarin Mobile App (For iOS, Android and Windows/UWP)*: It is a client mobile app supporting the most common mobile OS platforms (iOS, Android and Windows/UWP). In this case, the consumption of the microservices is done from C# but running on the client devices, so out of the Docker Host internal network (Like from your network or even the Internet). - - - -## Setting up your development environment for eShopOnContainers -### Visual Studio 2017 and Windows based -This is the more straightforward way to get started: -https://github.com/dotnet/eShopOnContainers/wiki/02.-Setting-eShopOnContainer-solution-up-in-a-Visual-Studio-2017-environment +> ### DISCLAIMER +> **IMPORTANT:** The current state of this sample application is **BETA**, consider it version a 0.1 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.** -### CLI and Windows based -For those who prefer the CLI on Windows, using dotnet CLI, docker CLI and VS Code for Windows: -https://github.com/dotnet/eShopOnContainers/wiki/03.-Setting-the-eShopOnContainers-solution-up-in-a-Windows-CLI-environment-(dotnet-CLI,-Docker-CLI-and-VS-Code) +## WHAT IS ON THIS REPO? +This repo contains an implementation of eShopOnContainers using Azure services when applicable. Its code is synced periodically with the code of [eShopOnContainers](https://github.com/dotnet-architecture/eShopOnContainers). Also unique features using Azure services will be implemented in this repo (while generic features will be +implemented on _eShopOnContainers_ and integrated in this repo). -### CLI and Mac based -For those who prefer the CLI on a Mac, using dotnet CLI, docker CLI and VS Code for Mac -(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) +This repo also contains scripts for an autometed deploy of all Azure resources and information about how to configure a CI/CD pipeline. -> ### 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. +Status of this repo is in **early development**. -## Sending feedback and pull requests +## HOW TO CONTRIBUTE As mentioned, we'd appreciate to 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 [QUESTION] Answer +1 if the solution is working for you (Through VS2017 or CLI environment): https://github.com/dotnet/eShopOnContainers/issues/107 + From 8148dbe196dcd93d594f0be94ec3ff41562af32c Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Tue, 25 Apr 2017 12:28:07 +0200 Subject: [PATCH 05/60] new cli scripts for deploying --- deploy/az/{ => linux-vm}/create-resources.cmd | 0 deploy/az/{ => linux-vm}/mvparams.json | 0 deploy/az/win-vm/azuredeploy.json | 289 ++++++++++++++++++ deploy/az/win-vm/create-resources.cmd | 3 + deploy/az/win-vm/mvparams.json | 7 + 5 files changed, 299 insertions(+) rename deploy/az/{ => linux-vm}/create-resources.cmd (100%) rename deploy/az/{ => linux-vm}/mvparams.json (100%) create mode 100644 deploy/az/win-vm/azuredeploy.json create mode 100644 deploy/az/win-vm/create-resources.cmd create mode 100644 deploy/az/win-vm/mvparams.json diff --git a/deploy/az/create-resources.cmd b/deploy/az/linux-vm/create-resources.cmd similarity index 100% rename from deploy/az/create-resources.cmd rename to deploy/az/linux-vm/create-resources.cmd diff --git a/deploy/az/mvparams.json b/deploy/az/linux-vm/mvparams.json similarity index 100% rename from deploy/az/mvparams.json rename to deploy/az/linux-vm/mvparams.json diff --git a/deploy/az/win-vm/azuredeploy.json b/deploy/az/win-vm/azuredeploy.json new file mode 100644 index 000000000..89bf54785 --- /dev/null +++ b/deploy/az/win-vm/azuredeploy.json @@ -0,0 +1,289 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + + "VMName": { + "type": "string", + "metadata": { + "description": "This name will also be used to prefix the network security group, storage, virtual network, network card, subnet and public IP address name." + } + }, + + "adminUsername": { + "type": "string", + "metadata": { + "description": "Username for the Virtual Machine." + } + }, + + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Password for the Virtual Machine." + } + }, + + "dnsNameForPublicIP": { + "type": "string", + "metadata": { + "description": "Unique DNS Name for the Public IP used to access the Virtual Machine." + } + }, + + "newStorageAccountName": { + "type": "string", + "metadata": { + "description": "Storage name for the Virtual Machine." + } + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_D1", + "metadata": { + "description": "VM Size" + } + } + }, + + "variables": { + "windowsOSVersion": "2016-Datacenter", + "imagePublisher": "MicrosoftWindowsServer", + "imageOffer": "WindowsServer", + "OSDiskName": "[concat(parameters('VMName'),'_osdisk')]", + "nicName": "[concat(parameters('VMName'),'_nic')]", + "addressPrefix": "10.0.0.0/16", + "subnetName": "[concat(parameters('VMName'),'_subnet')]", + "subnetPrefix": "10.0.0.0/24", + "networkSecurityGroupName": "[concat(parameters('VMName'),'_nsg')]", + "storageAccountType": "Standard_LRS", + "publicIPAddressName": "[concat(parameters('VMName'),'_pubip')]", + "publicIPAddressType": "Dynamic", + "vmStorageAccountContainerName": "vhds", + "apiVersion": "2015-05-01-preview", + "virtualNetworkName": "[concat(parameters('VMName'),'_vnet')]", + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]", + "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]" + }, + "resources": [ + + { + "type": "Microsoft.Network/networkSecurityGroups", + "name": "[variables('networkSecurityGroupName')]", + "apiVersion": "[variables('apiVersion')]", + "location": "[resourceGroup().location]", + "properties": { + "securityRules": [ + { + "name": "HTTP", + "properties": { + "description": "HTTP", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "80", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 100, + "direction": "Inbound" + } + }, + + { + "name": "RDP", + "properties": { + "description": "RDP", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3389", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 200, + "direction": "Inbound" + } + }, + + { + "name": "Docker", + "properties": { + "description": "Docker", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "2375", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 300, + "direction": "Inbound" + } + } + + ] + } + }, + + { + "type": "Microsoft.Storage/storageAccounts", + "name": "[parameters('newStorageAccountName')]", + "apiVersion": "[variables('apiVersion')]", + "location": "[resourceGroup().location]", + "tags": { + "displayName": "StorageAccount" + }, + "properties": { + "accountType": "[variables('storageAccountType')]" + } + }, + + { + "apiVersion": "[variables('apiVersion')]", + "type": "Microsoft.Network/publicIPAddresses", + "name": "[variables('publicIPAddressName')]", + "location": "[resourceGroup().location]", + "tags": { + "displayName": "PublicIPAddress" + }, + "properties": { + "publicIPAllocationMethod": "[variables('publicIPAddressType')]", + "dnsSettings": { + "domainNameLabel": "[tolower(parameters('dnsNameForPublicIP'))]" + } + } + }, + + { + "apiVersion": "[variables('apiVersion')]", + "type": "Microsoft.Network/virtualNetworks", + "name": "[variables('virtualNetworkName')]", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]" + ], + "tags": { + "displayName": "VirtualNetwork" + }, + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[variables('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "addressPrefix": "[variables('subnetPrefix')]", + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" + } + } + } + ] + } + }, + + { + "apiVersion": "[variables('apiVersion')]", + "type": "Microsoft.Network/networkInterfaces", + "name": "[variables('nicName')]", + "location": "[resourceGroup().location]", + "tags": { + "displayName": "NetworkInterface" + }, + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]", + "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]" + ], + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]" + }, + "subnet": { + "id": "[variables('subnetRef')]" + } + } + } + ] + } + }, + + { + "apiVersion": "[variables('apiVersion')]", + "type": "Microsoft.Compute/virtualMachines", + "name": "[parameters('VMName')]", + "location": "[resourceGroup().location]", + "tags": { + "displayName": "VirtualMachine" + }, + "dependsOn": [ + "[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]", + "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]" + ], + "properties": { + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "osProfile": { + "computername": "[parameters('VMName')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]" + }, + "storageProfile": { + "imageReference": { + "publisher": "[variables('imagePublisher')]", + "offer": "[variables('imageOffer')]", + "sku": "[variables('windowsOSVersion')]", + "version": "latest" + }, + "osDisk": { + "name": "osdisk", + "vhd": { + "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName')), variables('apiVersion')).primaryEndpoints.blob, variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]" + }, + "caching": "ReadWrite", + "createOption": "FromImage" + } + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]" + } + ] + } + }, + "resources": [ + { + "name": "containerConfiguration", + "type": "extensions", + "location": "[resourceGroup().location]", + "apiVersion": "2015-06-15", + "dependsOn": [ + "[concat('Microsoft.Compute/virtualMachines/', parameters('VMName'))]" + ], + "tags": { + "displayName": "containerConfiguration" + }, + "properties": { + "publisher": "Microsoft.Compute", + "type": "CustomScriptExtension", + "typeHandlerVersion": "1.2", + "autoUpgradeMinorVersion": true, + "settings": { + "fileUris": [ + "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/windows-server-containers-preview/azure-containers.ps1" + ], + "commandToExecute": "[concat('powershell.exe -ExecutionPolicy Unrestricted -File azure-containers.ps1 -adminuser ',parameters('adminUsername'))]" + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/deploy/az/win-vm/create-resources.cmd b/deploy/az/win-vm/create-resources.cmd new file mode 100644 index 000000000..b35de9431 --- /dev/null +++ b/deploy/az/win-vm/create-resources.cmd @@ -0,0 +1,3 @@ +REM az group create --name eShopOnAzureDevWin --location westus +az group deployment create --resource-group eShopOnAzureDevWin --parameters @mvparams.json --template-file azuredeploy.json + diff --git a/deploy/az/win-vm/mvparams.json b/deploy/az/win-vm/mvparams.json new file mode 100644 index 000000000..7a2773a54 --- /dev/null +++ b/deploy/az/win-vm/mvparams.json @@ -0,0 +1,7 @@ +{ + "newStorageAccountName": { "value": "eshopsrvmvstoragewin" }, + "adminUsername": { "value": "eshop" }, + "adminPassword": { "value": "Pass@word" }, + "dnsNameForPublicIP": { "value": "eshop-srv-win" }, + "VMName": {"value": "eshop-srv-win"} +} From 1cc9e82259047bc771bb7492201b4ad9d0a4f7c7 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Tue, 25 Apr 2017 12:28:21 +0200 Subject: [PATCH 06/60] Run script for release managment --- cli-linux/run.sh | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 cli-linux/run.sh diff --git a/cli-linux/run.sh b/cli-linux/run.sh new file mode 100644 index 000000000..fe3742f67 --- /dev/null +++ b/cli-linux/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash +docker stop $(docker ps -a -q) +docker rm $(docker ps -a -q) +docker images |grep -v REPOSITORY|awk '{print $1}'|xargs -L1 docker pull +export ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=$(curl ipinfo.io/ip) +docker-compose up -f docker-compose.images.yml -f docker-compose.prod.yml + From ea248b556323bf92519a298d446fe45f31ddbf1b Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Tue, 25 Apr 2017 12:51:30 +0200 Subject: [PATCH 07/60] Run containers in detached mode --- cli-linux/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli-linux/run.sh b/cli-linux/run.sh index fe3742f67..d49173f2d 100644 --- a/cli-linux/run.sh +++ b/cli-linux/run.sh @@ -3,5 +3,5 @@ docker stop $(docker ps -a -q) docker rm $(docker ps -a -q) docker images |grep -v REPOSITORY|awk '{print $1}'|xargs -L1 docker pull export ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=$(curl ipinfo.io/ip) -docker-compose up -f docker-compose.images.yml -f docker-compose.prod.yml +docker-compose up -f docker-compose.images.yml -f docker-compose.prod.yml -d From d9f7b3de153accf242d3843af9e10800f4184f03 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Tue, 25 Apr 2017 13:35:33 +0200 Subject: [PATCH 08/60] fix error on docker-compose invoke --- cli-linux/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli-linux/run.sh b/cli-linux/run.sh index d49173f2d..aaeb164fa 100644 --- a/cli-linux/run.sh +++ b/cli-linux/run.sh @@ -3,5 +3,5 @@ docker stop $(docker ps -a -q) docker rm $(docker ps -a -q) docker images |grep -v REPOSITORY|awk '{print $1}'|xargs -L1 docker pull export ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=$(curl ipinfo.io/ip) -docker-compose up -f docker-compose.images.yml -f docker-compose.prod.yml -d +docker-compose -f docker-compose.images.yml -f docker-compose.prod.yml up -d --force-recreate From f724c6b91bd4854df26ee1ca188c53fdbc689b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Fri, 5 May 2017 15:29:23 +0200 Subject: [PATCH 09/60] Modify kubernetes deploy script to support CI vsts --- k8s/deploy.ps1 | 94 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index 61c7bd909..2485d48c5 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -1,9 +1,17 @@ Param( - [parameter(Mandatory=$true)][string]$registry, - [parameter(Mandatory=$true)][string]$dockerUser, - [parameter(Mandatory=$true)][string]$dockerPassword + [parameter(Mandatory=$false)][string]$registry, + [parameter(Mandatory=$false)][string]$dockerUser, + [parameter(Mandatory=$false)][string]$dockerPassword, + [parameter(Mandatory=$false)][bool]$deployCI, + [parameter(Mandatory=$false)][string]$execPath ) +$kubectl_exec = 'kubectl'; + +if(-not [string]::IsNullOrEmpty($execPath)) { + $kubectl_exec = $execPath + '/' + 'kubectl'; +} + $requiredCommands = ("docker", "docker-compose", "kubectl") foreach ($command in $requiredCommands) { if ((Get-Command $command -ErrorAction SilentlyContinue) -eq $null) { @@ -12,69 +20,79 @@ foreach ($command in $requiredCommands) { } } -Write-Host "Logging in to $registry" -ForegroundColor Yellow -docker login -u $dockerUser -p $dockerPassword $registry -if (-not $LastExitCode -eq 0) { - Write-Host "Login failed" -ForegroundColor Red - exit -} +# Not using ACR when deploying through CI VSTS +if(-not $deployCI) { + Write-Host "Logging in to $registry" -ForegroundColor Yellow + docker login -u $dockerUser -p $dockerPassword $registry + if (-not $LastExitCode -eq 0) { + Write-Host "Login failed" -ForegroundColor Red + exit + } -# create registry key secret -kubectl create secret docker-registry registry-key ` + # create registry key secret + & $kubectl_exec create secret docker-registry registry-key ` --docker-server=$registry ` --docker-username=$dockerUser ` --docker-password=$dockerPassword ` --docker-email=not@used.com +} # start sql, rabbitmq, frontend deployments -kubectl create configmap config-files --from-file=nginx-conf=nginx.conf -kubectl label configmap config-files app=eshop -kubectl create -f sql-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml +& $kubectl_exec create configmap config-files --from-file=nginx-conf=nginx.conf +& $kubectl_exec label configmap config-files app=eshop +& $kubectl_exec create -f sql-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml -Write-Host "Building and publishing eShopOnContainers..." -ForegroundColor Yellow -dotnet restore ../eShopOnContainers-ServicesAndWebApps.sln -dotnet publish -c Release -o obj/Docker/publish ../eShopOnContainers-ServicesAndWebApps.sln +# building and publishing docker images not necessary when deploying through CI VSTS +if(-not $deployCI) { + Write-Host "Building and publishing eShopOnContainers..." -ForegroundColor Yellow + dotnet restore ../eShopOnContainers-ServicesAndWebApps.sln + dotnet publish -c Release -o obj/Docker/publish ../eShopOnContainers-ServicesAndWebApps.sln -Write-Host "Building Docker images..." -ForegroundColor Yellow -docker-compose -p .. -f ../docker-compose.yml build + Write-Host "Building Docker images..." -ForegroundColor Yellow + docker-compose -p .. -f ../docker-compose.yml build -Write-Host "Pushing images to $registry..." -ForegroundColor Yellow -$services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "webmvc", "webspa") -foreach ($service in $services) { - docker tag eshop/$service $registry/eshop/$service - docker push $registry/eshop/$service + Write-Host "Pushing images to $registry..." -ForegroundColor Yellow + $services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "webmvc", "webspa") + foreach ($service in $services) { + docker tag eshop/$service $registry/eshop/$service + docker push $registry/eshop/$service + } } Write-Host "Waiting for frontend's external ip..." -ForegroundColor Yellow while ($true) { - $frontendUrl = kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}" + $frontendUrl = & $kubectl_exec get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}" if ([bool]($frontendUrl -as [ipaddress])) { break } Start-Sleep -s 15 } -kubectl create configmap urls ` +& $kubectl_exec create configmap urls ` --from-literal=BasketUrl=http://$($frontendUrl)/basket-api ` --from-literal=CatalogUrl=http://$($frontendUrl)/catalog-api ` --from-literal=IdentityUrl=http://$($frontendUrl)/identity ` --from-literal=OrderingUrl=http://$($frontendUrl)/ordering-api ` --from-literal=MvcClient=http://$($frontendUrl)/webmvc ` --from-literal=SpaClient=http://$($frontendUrl) -kubectl label configmap urls app=eshop +& $kubectl_exec label configmap urls app=eshop Write-Host "Creating deployments..." -kubectl apply -f deployments.yaml +& $kubectl_exec apply -f deployments.yaml + +# not using ACR for pulling images when deploying through CI VSTS +if(-not $deployCI) { + # update deployments with the private registry before k8s tries to pull images + # (deployment templating, or Helm, would obviate this) + & $kubectl_exec set image -f deployments.yaml ` + basket=$registry/eshop/basket.api ` + catalog=$registry/eshop/catalog.api ` + identity=$registry/eshop/identity.api ` + ordering=$registry/eshop/ordering.api ` + webmvc=$registry/eshop/webmvc ` + webspa=$registry/eshop/webspa +} -# update deployments with the private registry before k8s tries to pull images -# (deployment templating, or Helm, would obviate this) -kubectl set image -f deployments.yaml ` - basket=$registry/eshop/basket.api ` - catalog=$registry/eshop/catalog.api ` - identity=$registry/eshop/identity.api ` - ordering=$registry/eshop/ordering.api ` - webmvc=$registry/eshop/webmvc ` - webspa=$registry/eshop/webspa -kubectl rollout resume -f deployments.yaml +& $kubectl_exec rollout resume -f deployments.yaml Write-Host "WebSPA is exposed at http://$frontendUrl, WebMVC at http://$frontendUrl/webmvc" -ForegroundColor Yellow From 867afa3df4fcba9b8a6fb97d144ba696dbd4c7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Fri, 5 May 2017 16:17:35 +0200 Subject: [PATCH 10/60] Update k8s script --- k8s/deploy.ps1 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index 2485d48c5..f0d24e1b1 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -12,16 +12,16 @@ if(-not [string]::IsNullOrEmpty($execPath)) { $kubectl_exec = $execPath + '/' + 'kubectl'; } -$requiredCommands = ("docker", "docker-compose", "kubectl") -foreach ($command in $requiredCommands) { - if ((Get-Command $command -ErrorAction SilentlyContinue) -eq $null) { - Write-Host "$command must be on path" -ForegroundColor Red - exit - } -} - # Not using ACR when deploying through CI VSTS if(-not $deployCI) { + $requiredCommands = ("docker", "docker-compose", "kubectl") + foreach ($command in $requiredCommands) { + if ((Get-Command $command -ErrorAction SilentlyContinue) -eq $null) { + Write-Host "$command must be on path" -ForegroundColor Red + exit + } + } + Write-Host "Logging in to $registry" -ForegroundColor Yellow docker login -u $dockerUser -p $dockerPassword $registry if (-not $LastExitCode -eq 0) { From 81b8950ced7f58165ef80953e5ae52ff089748c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Mon, 8 May 2017 12:03:24 +0200 Subject: [PATCH 11/60] Updated k8s deploy script --- k8s/deploy.ps1 | 54 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index f0d24e1b1..22b94c41e 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -3,16 +3,24 @@ Param( [parameter(Mandatory=$false)][string]$dockerUser, [parameter(Mandatory=$false)][string]$dockerPassword, [parameter(Mandatory=$false)][bool]$deployCI, - [parameter(Mandatory=$false)][string]$execPath + [parameter(Mandatory=$false)][bool]$useDockerHub, + [parameter(Mandatory=$false)][string]$execPath, + [parameter(Mandatory=$false)][string]$kubeconfigPath ) -$kubectl_exec = 'kubectl'; - -if(-not [string]::IsNullOrEmpty($execPath)) { - $kubectl_exec = $execPath + '/' + 'kubectl'; +function ExecKube($cmd) { + if($deployCI) { + $kubeconfig = $kubeconfigPath + 'config'; + $exp = $execPath + 'kubectl ' + $cmd + ' --kubeconfig=' + $kubeconfig + Invoke-Expression $exp + } + else{ + $exp = $execPath + 'kubectl ' + $cmd + Invoke-Expression $exp + } } -# Not using ACR when deploying through CI VSTS +# Check command paths only for manual deployment if(-not $deployCI) { $requiredCommands = ("docker", "docker-compose", "kubectl") foreach ($command in $requiredCommands) { @@ -21,7 +29,10 @@ if(-not $deployCI) { exit } } +} +# Use ACR instead of DockerHub as image repository +if(-not $useDockerHub) { Write-Host "Logging in to $registry" -ForegroundColor Yellow docker login -u $dockerUser -p $dockerPassword $registry if (-not $LastExitCode -eq 0) { @@ -30,17 +41,17 @@ if(-not $deployCI) { } # create registry key secret - & $kubectl_exec create secret docker-registry registry-key ` + ExecKube -cmd 'create secret docker-registry registry-key ` --docker-server=$registry ` --docker-username=$dockerUser ` --docker-password=$dockerPassword ` - --docker-email=not@used.com + --docker-email=not@used.com' } # start sql, rabbitmq, frontend deployments -& $kubectl_exec create configmap config-files --from-file=nginx-conf=nginx.conf -& $kubectl_exec label configmap config-files app=eshop -& $kubectl_exec create -f sql-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml +ExecKube -cmd 'create configmap config-files --from-file=nginx-conf=nginx.conf' +ExecKube -cmd 'label configmap config-files app=eshop' +ExecKube -cmd 'create -f sql-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml' # building and publishing docker images not necessary when deploying through CI VSTS if(-not $deployCI) { @@ -61,38 +72,39 @@ if(-not $deployCI) { Write-Host "Waiting for frontend's external ip..." -ForegroundColor Yellow while ($true) { - $frontendUrl = & $kubectl_exec get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}" + $frontendUrl = & ExecKube -cmd 'get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"' if ([bool]($frontendUrl -as [ipaddress])) { break } Start-Sleep -s 15 } -& $kubectl_exec create configmap urls ` +ExecKube -cmd 'create configmap urls ` --from-literal=BasketUrl=http://$($frontendUrl)/basket-api ` --from-literal=CatalogUrl=http://$($frontendUrl)/catalog-api ` --from-literal=IdentityUrl=http://$($frontendUrl)/identity ` --from-literal=OrderingUrl=http://$($frontendUrl)/ordering-api ` --from-literal=MvcClient=http://$($frontendUrl)/webmvc ` - --from-literal=SpaClient=http://$($frontendUrl) -& $kubectl_exec label configmap urls app=eshop + --from-literal=SpaClient=http://$($frontendUrl)' + +ExecKube -cmd 'label configmap urls app=eshop' Write-Host "Creating deployments..." -& $kubectl_exec apply -f deployments.yaml +ExecKube -cmd 'apply -f deployments.yaml' -# not using ACR for pulling images when deploying through CI VSTS -if(-not $deployCI) { +# use ACR registry for pulling images if docker hub is not specified +if(-not $useDockerHub) { # update deployments with the private registry before k8s tries to pull images # (deployment templating, or Helm, would obviate this) - & $kubectl_exec set image -f deployments.yaml ` + ExecKube -cmd 'set image -f deployments.yaml ` basket=$registry/eshop/basket.api ` catalog=$registry/eshop/catalog.api ` identity=$registry/eshop/identity.api ` ordering=$registry/eshop/ordering.api ` webmvc=$registry/eshop/webmvc ` - webspa=$registry/eshop/webspa + webspa=$registry/eshop/webspa' } -& $kubectl_exec rollout resume -f deployments.yaml +ExecKube -cmd 'rollout resume -f deployments.yaml' Write-Host "WebSPA is exposed at http://$frontendUrl, WebMVC at http://$frontendUrl/webmvc" -ForegroundColor Yellow From 573c5a026fa2eb3f37e3eb7e31f06630f27ae536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Mon, 8 May 2017 16:10:41 +0200 Subject: [PATCH 12/60] Update k8s deploy script. Remove existing services and deployments before deployment --- k8s/deploy.ps1 | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index 22b94c41e..2f7d18d82 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -20,7 +20,7 @@ function ExecKube($cmd) { } } -# Check command paths only for manual deployment +# No when deploying through CI VSTS if(-not $deployCI) { $requiredCommands = ("docker", "docker-compose", "kubectl") foreach ($command in $requiredCommands) { @@ -48,7 +48,14 @@ if(-not $useDockerHub) { --docker-email=not@used.com' } -# start sql, rabbitmq, frontend deployments +# Removing previous services & deployments +Write-Host "Removing existing services & deployments.." -ForegroundColor Yellow +ExecKube -cmd 'delete -f sql-data.yaml -f rabbitmq.yaml' +ExecKube -cmd 'delete -f services.yaml -f frontend.yaml -f deployments.yaml' +ExecKube -cmd 'delete configmap config-files' +ExecKube -cmd 'delete configmap urls' + +# start sql, rabbitmq, frontend deploymentsExecKube -cmd 'delete configmap config-files' ExecKube -cmd 'create configmap config-files --from-file=nginx-conf=nginx.conf' ExecKube -cmd 'label configmap config-files app=eshop' ExecKube -cmd 'create -f sql-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml' @@ -90,10 +97,10 @@ ExecKube -cmd 'create configmap urls ` ExecKube -cmd 'label configmap urls app=eshop' Write-Host "Creating deployments..." -ExecKube -cmd 'apply -f deployments.yaml' +ExecKube -cmd 'create -f deployments.yaml' -# use ACR registry for pulling images if docker hub is not specified -if(-not $useDockerHub) { +# not using ACR for pulling images when deploying through CI VSTS +if(-not $deployCI) { # update deployments with the private registry before k8s tries to pull images # (deployment templating, or Helm, would obviate this) ExecKube -cmd 'set image -f deployments.yaml ` From 4d7ea9460dc67434a6aca6a378366fbd90876651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Tue, 16 May 2017 08:57:08 +0200 Subject: [PATCH 13/60] CICD test --- k8s/deploy.ps1 | 2 +- src/Web/WebMVC/Views/Shared/_Layout.cshtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index 2f7d18d82..255243f34 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -20,7 +20,7 @@ function ExecKube($cmd) { } } -# No when deploying through CI VSTS +# Not used when deploying through CI VSTS if(-not $deployCI) { $requiredCommands = ("docker", "docker-compose", "kubectl") foreach ($command in $requiredCommands) { diff --git a/src/Web/WebMVC/Views/Shared/_Layout.cshtml b/src/Web/WebMVC/Views/Shared/_Layout.cshtml index 456248b94..ee8c407c2 100644 --- a/src/Web/WebMVC/Views/Shared/_Layout.cshtml +++ b/src/Web/WebMVC/Views/Shared/_Layout.cshtml @@ -3,7 +3,7 @@ - @ViewData["Title"] - Microsoft.eShopOnContainers.WebMVC + @ViewData["Title"] - Microsoft.eShopOnContainers.WebMVC Azure From bffd87e3e226f9a3e5c6b0e54147ed2596e3c947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Tue, 16 May 2017 10:11:54 +0200 Subject: [PATCH 14/60] Change k8s deployment script to use internal names in urls for intercommunication between apis --- k8s/deploy.ps1 | 6 +++--- src/Web/WebMVC/Views/Shared/_Layout.cshtml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/k8s/deploy.ps1 b/k8s/deploy.ps1 index 255243f34..49b2648e7 100644 --- a/k8s/deploy.ps1 +++ b/k8s/deploy.ps1 @@ -87,10 +87,10 @@ while ($true) { } ExecKube -cmd 'create configmap urls ` - --from-literal=BasketUrl=http://$($frontendUrl)/basket-api ` - --from-literal=CatalogUrl=http://$($frontendUrl)/catalog-api ` + --from-literal=BasketUrl=http://basket ` + --from-literal=CatalogUrl=http://catalog ` --from-literal=IdentityUrl=http://$($frontendUrl)/identity ` - --from-literal=OrderingUrl=http://$($frontendUrl)/ordering-api ` + --from-literal=OrderingUrl=http://ordering ` --from-literal=MvcClient=http://$($frontendUrl)/webmvc ` --from-literal=SpaClient=http://$($frontendUrl)' diff --git a/src/Web/WebMVC/Views/Shared/_Layout.cshtml b/src/Web/WebMVC/Views/Shared/_Layout.cshtml index ee8c407c2..456248b94 100644 --- a/src/Web/WebMVC/Views/Shared/_Layout.cshtml +++ b/src/Web/WebMVC/Views/Shared/_Layout.cshtml @@ -3,7 +3,7 @@ - @ViewData["Title"] - Microsoft.eShopOnContainers.WebMVC Azure + @ViewData["Title"] - Microsoft.eShopOnContainers.WebMVC From 87236db27bdb1896f287f627b844c85aacc26858 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Thu, 18 May 2017 17:08:11 +0200 Subject: [PATCH 15/60] android build docs --- .../builds/images/android-build-step1.png | Bin 0 -> 52130 bytes .../builds/images/android-build-step2.png | Bin 0 -> 53843 bytes .../builds/images/android-build-step3.png | Bin 0 -> 26156 bytes .../builds/images/android-build-step4.png | Bin 0 -> 53185 bytes .../builds/images/android-build-step5.png | Bin 0 -> 25307 bytes azure-docs/builds/images/android-build.png | Bin 0 -> 59401 bytes azure-docs/builds/xamarin-android.md | 95 ++++++++++++++++++ azure-docs/readme.md | 5 + 8 files changed, 100 insertions(+) create mode 100644 azure-docs/builds/images/android-build-step1.png create mode 100644 azure-docs/builds/images/android-build-step2.png create mode 100644 azure-docs/builds/images/android-build-step3.png create mode 100644 azure-docs/builds/images/android-build-step4.png create mode 100644 azure-docs/builds/images/android-build-step5.png create mode 100644 azure-docs/builds/images/android-build.png create mode 100644 azure-docs/builds/xamarin-android.md create mode 100644 azure-docs/readme.md diff --git a/azure-docs/builds/images/android-build-step1.png b/azure-docs/builds/images/android-build-step1.png new file mode 100644 index 0000000000000000000000000000000000000000..b43243b7350945f67f727bd947eef372e6f9fd9b GIT binary patch literal 52130 zcmeGDWmFv969)|91lQoMAvgq=AvnR^-GT>q1`^yE+=B#y2MO-(?(XicGcQS=|GVFI z-?L{wto4~W(^GxBuhgxoUrC24DM+Cq6Cp!EL7~Y=i>p9E!Q(lc>zlp) zAbpY6c7}q&cKP##UbP_icqJmb$jD0|Zop%s6VRhqJ1zYsNocuzbanac-~?4vJ}mu8 zLUnm1iJLo{I$3>jv2w77!a<^>ex)P-p^G_u@pQ7X{Okf%iZRUpN=5%mbuu^p)0D!+ z%FY~$>kb3y^$OCTE2<6_F7C!o=1}@yAb*;p{C&8Uv#G7|Yf~qvy7rowSMr-bWKCly zdnimOY91NKE8Z?MGnsc6b^al;u;O2(m27^AwNp~q8GRPCgRMm<)uY#HsM%4W z`%Wd%pJ!x;^xJeCMk4a<<?g>Q?zV>mK5-Q$!BVu6JJ@GPj_`;kj3~+OuKW_jQ9DYii*^u`{&hnVke`(Y)0-{3c!}iT*WmS$!lpK$7rsxyt5sTz6BZ+vaB1jlYU4r{1JZG<3lW-l;J(shFnv&RmG~ zgag1qSPj`6_XQCO#-&agmM@7&7B<8Pw5C_{ue1EbszvC^k6ok+aaHAyAhhkz_E5J zAJelsIPSq~+zQ?-LRCIj;&&HP7hV2k#q_kHgl%%`V=_qr_z?sOK#!{}M zM{;yij7qMyj0r|JP6(o*MX%=aMMWi-V~`00A4(PB`Ths&Q4J$KZG{O{clM(k(ZPV9 zjGG6O)ZqT1oI8|-U(K;-z(9OF^o<1S;Y%tfzeM>}bF0#flrJD2DXh6X6fVdpdP}zA zXv@R)?wGOqE~d$t%TEuTD*%2FgARY@HGZ!2kipP>7FuA>2yFK)ao4hxszbSKjM3UVlqc&VH+4(WN6`182l}T(A$mE*ebL~ztyD|HoZPT^BmmH$uFL_ z)N-XdE8*30MOzA9&`z1wo;@s<^*rUxF&SaI5Lb_+pB8TSH;@urgcgDoXMIR%Si0rd zV$41}uVwgP^*!bOw>a|JAf@vTRFa~?dZZM0;*agMjhK&-wdz|-G8Sf&rx0bAGyJ}|luA!jnL1WWZ6hjG3yZjVH#!*&8QE8UKf=s6 z{`eXW#^)lTBYPC^z5^mp;KxrufCMjV*=%`7$;IXHI@qMYh~%WWaNl!Vr)XtcoHQIx z#w@&8ZMm1xq2t2NMH%mQh~hDi(a?L+ZZ%~tT!d??2ZcGBCRaYsBESsqLYtIJn>?3U zy0Orgc``B7$r*JGrQ$y4q+G^T*0&f2b_SJdDTzFvFdmhCVDdh4ELbD%s~T|?)q|mV z9wO;=$m;Bz5!2#i2d8+`{$bSBu2GMrcwLEu_A=!yxHSQZHCX$OL9V_P=SoMveO3{@ zW3^=%?8+AdM5b?pHjk_a}X3V6f_} zFS6r_4%<_3wA}tG5%?ZoN9b+2eSM6E!x=2h_8Q#4js94D0+{^7!e!R)ad|p%K@-|% z_&L(|%TzL9OI-pXF=Vunt^0RVY@{+i=i?9;OugdJ!u4j~@QT3;nYdy9G00e(dTVT&~KDh(O3(4tU z^YF(sM@E*g3WD8_Nycj+OW!>OivX!IFtlc4`X3$5^Lg;%-lAe>Buf2kO|CP?LPd}P zR`!-Wai8B$V&6ZK;K>QySoe=7k?gJrMh0|HbgWbKt|ayZyW1QqHPOdh8^x~o%OOK) z$Ws!ak_lw1PB4@o4ryrgb~IL;FwpE}F`zyv%xHbPeWp$_lRCW^?G}MS#bs z%N%XCj6ljhe!jzvyBpV+BjNkiI6~1ok|H&l

xr48flNAu9movD)EHdC>av2&U% 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 literal 0 HcmV?d00001 diff --git a/azure-docs/builds/images/android-build-step2.png b/azure-docs/builds/images/android-build-step2.png new file mode 100644 index 0000000000000000000000000000000000000000..67419b3ba9e0eba85c00abd36b6474a42b467984 GIT binary patch literal 53843 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

~X6p%XJFcrum}2Uda=F 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 literal 0 HcmV?d00001 diff --git a/azure-docs/builds/images/android-build-step3.png b/azure-docs/builds/images/android-build-step3.png new file mode 100644 index 0000000000000000000000000000000000000000..ae703c16d164d9af8c91c68202b6920580814991 GIT binary patch literal 26156 zcmd>mWl)^W6DNe=mJr+t9xS*^&=B0+-Q67$+}&M*Ey3O0Ex5b8%d)rd{@?p>_u=a9 zs;=(ps@U4ue&(6!>7MENbx#i=veIJ62)GCk5D>`X--YENAfP57ARzPMV8E0G|4~fv z7rgCvH3tX?G{@HuZ%gitB%0BHmDthD z$_Rq>4iz5!1pf7jf{n4Gi=Mp^gqAJnwL0Qk<7N&9mU`f-_7L?QHBn$P+$&i{&)(Y1 z+61BlZ#M``gZ<}yCwl`Uh#OGA(ZAJ%Y^?Fie`?MMi9SGrzjyH zh#|yqwd z_Cf-bCNR-sK8uEFLf614jw->>WgDHl2Wz4keb)$9614avB8^D)%a-N-i4^|lhc3u2 z!>p*7slVUR*$<7>wveP zl)Pfup=owKGLW#5gv3k8i?@~_UrbUq z*?~ti)t<|1`Se7en(5|F7xWy*;KH(*UKp80Naqp#0r3p+>*dMBMe}x(T4k&GsO05gz8|b+gg?7j+^QE9Gorru0duHbTpweZ23jRFGmiTSabLTJ zqa=V9EV?brae4&%cHPS~pVCW(f#nzqH58(HN zmkkGXnWe6}PYw@@Ckwr)y&5=I7yPJIpe$O@iL!UA+1!QIoXcNET)#0==CARbO6;tm zq?J-=)N|JbI(x$Uxsjs@?KFZmQTcNX$51ZU9)9auR*?o0UE93u!B1`XsF_|C_#uo> zw>>Vwl$AmVyfE7rmp~|-ng=uOhH_*SQHfZxjNDsv=DXf@h3LQW-&91Vb>)3>~M1|o3Ghe8I`og z?*HqJ%@We8h$q*qBam!|9La@ORey;YffWb`@IFM&w; zZ-6y_sGj{=wYcs5&Ajx6^y30jpVkci{OIf`^!6Sd*^x>>^3@?kCh+FNA`4fd3W$C{ zcavMlRKrQZ@xiBO5({Nx<}T6;@ke6hUfZZw3TGSag$MsNm40v71KH|qh^uch8`6L$ zrZ-orS<;B{Jh`YTSWgOa2ahM7^S721l&pZdqVTYH$gcV_ADP*@gy^~^&bcqybGRKz39RfN6FPkShJc_=I-^W-Q1bYfxGv7Cv>!C-kyty?S+!P ze6<^}PnFqt;t8-)_L_HKFV$w)^s~`VcG*%p2C1G|vz6V42EE)_V0uB7$E8*k?zJbJ zJ?bN(j=oUFxd{Wmed$`dC-(C z3wsk)e^l^aO`I%a>R%ocJewo3aFM1KQ%{^+iNNtH+39Q<*(%~%c_ZS0=V z0KlD=<~`v%Rhu>ar5@4(HcQLyc#hWR#(}RT9~u>SzjS%!4Pp(u?U2IC=-ke{OX zjsg*TN}_cW;s`D`SF1g{C7c+M*qekG`rJYI3Ha9V3E?~$6OtS4G+$*(kbX6WCRdWC zR^v((&_!F=_<}cQ6gx{E*TQtmi`7!<`|DFsEFs*7{ne~W8%)`ocwDQ&ot;VG@Hl+_ zO@b*xiZR#^Etqoc6g)eFu0-lkt+b7p>!|%Bx)cJ<|=)aCUiH z!0fmwh=8&;88lv{HjztNO!t|m&580ckI}Cx)Xksg-&osH&3}8rJIACAZ5L zgb2!>gTAt)+I+-3P+5W44Q+gJMCRfL$%#*04jetnSQ2I{dzwG`pM879JzUp)1TCK~ z+~QFzMrwtt^(7^CokO<@_2|^>NHo)&*$ND9rH&%YGPsjDtCOt=#*MF%6D=FcNr+(X zb^@$QL1X7r(`qlaZcm4_JSwkNWR5-OpvvbfXW`&vkcsa($}UX1o@DbS>JJ3(_Fo&^ zxYe$X5ax;N>(C~ z%A*}ghVqQT-#sQNvgm7Fekj*e7i?{D zbk!4#86U})mi8kQr`mmQa?RwY^a$B}r}0NJtXHn<8UCNwRi2)elDM!9_kPN?5I`%~hVe%Z$OC z8<~>nt;xMMd=hhXGR*svQp|wBK(rXr@p+ULJ&$-CDB%nOKSEJ%%@ky>~O=bRUY*4|> z0g~kcT=3@{0|RT2L~?|Zv(1yxM<`{Hi^~oNb8o`CYxi`GOIAGR_>+3KrG9R;ziiGn zCk|YhV>3R~Mx!KRGbq&=S&3h3y-82Mmm~|hi{g_4me~*L^}4629uF`$9U5dj0eBV zHGRx8elDAtqkZh2`vA1j1a8@=z6{Pm#J}ia4Kr9uKDjrmWnw!NGTvl+BdyRs z5GsIL;->PBo4#jcS5$_Q0-(#*YVm?|3=brkB$!_`Tjt0HzDRF?xRi0LS-HYV!M7BXXA8~+jCA5YK5?2f1fH1elEZrA~K4*{oFuYIG6uR&fO7<1P*K0l0k)wverTB2zLB*tqjH)NGG0Tmyfc zgZQdjWMG-LItej|D9B7}vhLNX=OSk6u7>5i?E&+fzK+2o(XU%j8@FOVFkGiZGr z5TgK#BK3R`rUQgOB!(NzrV4?m?SF<~F_oSQ1Lq1n+MtK#>#7OiO;mvB`GoL$vw6B= zZlcHYZIIm{8}0(Etg*|e;f7WVh3ubJ-0eF#D(qLXGr1-+Cfu?rT54%=>mJz>1IPg4 zw!84w4Y!I{laVE=?G2BUu@voS_EF6O5!?3LJIev1P9<^L`#aMr?J>&hY2nQumxI9H zG{sw`m_NwP+PfH8__4aOf~fqUvKZ(G$vwEa;?O|SQ%*Yik>vkk@3X7l~OF%eC`pt z8N!a4`n~C<=*#O_`9j1~!Gv5MNpn$!N6F=}5 zwwFX?&^(lhQd^V<)xAC{d_!Ra8?!cQHF+eYW3U_%fj2S+hgR@AR-BO1 zBj~49pAlvS1wHZqq;2Yd=cq0eP~nr;YO!GdAogPq{ql-ULGVHGBwhfGu{>`7L66>z z{KMF=(O`jiO-QkFUg3nA=E!O4VqJBzK3Z_;Mmt?Fu*+1As;a3|ewoOdz3z1DM(kL>6@?!^)~JCJcR z`|2`cUM4j~hDDbvcd{h4G%h4h*Xo&^oRCk-=6oH}#6GrLj8Dq&0<3CJ+>7Gex76~j zfA4tYq84Z?ShtrDMz!5wKzpQ4ooq4@W?<2Saku(%MF;Rma}d_9*PS_( z(6Ln#en^z#9$}j0jah6$X!x^HpX{-p8|;(*#M6GZ;i*2Pp{SrYx@5HrPrY)X2lk>M z_|7t}ZG|k27cJ>U;9ebSTK>5yvoAIpgZSoxOyYz-XFgxNt>a0Ug~ZS= zk&y@DEJ!S}(|Q_E05rN2p`bjHEGC5{ZKcu+K_LH-G2}79FX?+b73?IbQ!VNzLAL0u zW_*qz=UMMh;GVnZqY&2ndh&1~ZKi$Dt!#h{eOa6_av3zBxyeAiPGA-hLn?pM^HZ*k z498|EI6!jHe2^|pM|Gmu9Z6JgXgy4i4GTr^Z@JevIYRkGYutH7$Z{uA!YI({ZLyo_QCy{e|bA;G(f}Ss3Y4+&FvEMs zoipMdq^8eNak{ILyOz@A2SH*>hpz4@L;?X=XS{AZ&V;a;qMaxTtvsQD&+ z(}A?cZ80*Y9`HHHYT+r(F(onFyO&5XEW`TOc?@xPZt&zwLfh@UnIkSowmH87Rz&Lk z3=O09PN^lR=H*w5az+bHDG7wx}qf9D$BbwS*gfwT7;FCs6=6sk-%>ZI72+;qx9n8SS`G$J(a*% z-5)cRyGV&UX@z|`RZ1qA)t66lfNmL-jG3{2SIv$+qX&Xt2odL{PHm0N#3Daly6+~F zua`0y^VZRE+RkOb?+RZd`+CwVj&!Uo0MAI~c-Y@sEf%B5S^o5l)W_47!Z?mnFjqlL z|2107hwtaH_T90M&bV|==X6}dS)W-vi+J|*&E4hxfU5h7mhClixl|tdDey#C+uI#Y z=qbG5r|BmB_Z$ll2^rzzF|e16al3$4K55Kw7m8P{(rrxzqepW-!4FDXx3d7g2RjoS zz`JI!!egcc1&GymCJ7uB-r(37FvDbe41975*`gs}#)>8T z*Hbdqcw|4%uPKI~TdNHW2vB(Rd+_UY<#W5oV1gqAeDUHoSjVkzFJ=x?_}ud5!@kSE z!5NOt{eD(}3{|)y5rt@ucNm#>H1K5lboU`1ePW%Tg6Vi_|2so=s_?HtZ%Y<6Sma4P zgjMX(c@Uz33^?8=&ZQkW$UMPFeURVQ>VK2)P(+(`>=xqK%7fC?D2ZG36Z6jGBNDwq zA1et3Z?k{wP~09vQ3D7m5jtpcH;yx0bJ3p>(f@tGa589`4OZJyg)I)o_@hg|Wg>LI z`@Lnc=c#Xo003Is>WIEqkR2@wOp2ETqk+zE`_`uO2mPv{CZ=ORU73%U*UIdR%3s=F z9$90$4iO|xpLsy60U>w!AF!MR)v3T5JJ6Y^R1>D9_yt(0QoWE9xql!_gSMJ#EQ62t z{1crphf1>Lj}5WOe6 zcsovPA(HU%T-)nTo8hG-)6vU?7uw0Sxn^K}@(3+k4x#&0{Bt3_1*kN%lv)_?bxDzB zaP*sEoSMdR8U4|fVIQ#t$PR157ovOCjRjI9%l$20p6;VqgL*?&8%_H zbTzssgA&B2U;EJ;YG9pA z!7G7OF(TXYX>jtY23F97PMZ%Ln@T@pihbK0*EZ^Nf`?64m=WF9K9v09`zwbFW@h4Lvy-}QANJNn}{ zpZP_a3(dV8shw}*D{HR>Ek_H?CD>IeRYhWBCMB>vD(RxovYQ{?8R z)f?Bpbd_>t&ISdL<|;&##27gppI|4|j*t{1r3Wi8!{(pn1qqrVkjV8n8!=UO0`{`ilPYNJ7#cwLEP zA{`KPug~P)|NljhR`o^ki5GtyPx`>MiQr}kBU)uELBRIoRVeuZzkMW20K;Uq{pqa? zd1>UaQ{(~O>^Ip`n!R-rftB~M2KG*`LW@0Iu7sa}0BRGvs-#`6xnRW9n^J7qXiBfG zN#=_^Gd7pJ$-TelBBg7EDwEAil<|Vl)!mw2kNEob`@8X-gfj-j7;Xcy)~5Gx@27B@ zYdrN`RvjQk$Ht9%dvg9UToSV;8@LP~S6lo?U|&sK^sEV)1KUr(uZ`_L434K_yhi`iR|@`|N%j_l6ghRW*tgmfavCNao#mv3uz>dg zVQw`J%d1|E3e{9?FKU>u0kqfz{UDyNLC;lC7Fby5v0q);hW)=`hD#G4ZE$XXlA21u zq4nWUYW;YNI;>_ZMH!oGVXlX%<|ZDl@qvuP0irib#y~{e>gKL4mOSkf&Q%{1W|Y;i ze}5no8^f<6toLfS!WvasBa0rElh04sAR`!NOj!6fXQB%UP#9+xzMRXO)*|z^nuAp} zdEiBQVZ$3l`}@!q(`7aQP%`4!JUa|zC_8swP=)#GvmKnyx&a~+ZX_HmIRxsUB`QOCK)Ru)DL1FKA!X&>%Ld zO15U8(aWShZ#+VMxw@R-JRk7ldCIC3?nnQ661wAYN8x-r{5a$X}++PBB!68y>kHOW0 z$wr60=vHVdM1`;XaU+FV;>Fsz`N96V9BAIyGLn)kIjBj|T24M;!~2z-X(Qwh&tmGE z8*3dohhk;O#ZdNx&u5xH%v~cjUVC%A^=s4~2%`4c0?le~LiEY``YBv8CEU-f*@!}TAq z7#uL@LEka*^Fgv@*LT2k9tvs@EpS2ojY_m1orG{?jBnB-E<|Kqmh2>puIv}ajzxG!m z3le6}Ugn~pL^W348Sb;IIdo-ZU%pguuaDr4LFNuA+bZuLWKui$Hy5DJzB`RmvSL5> zbp%jnWt$9NGB+$WPtF3n0{MOd<}23Ha}W!$pS*H61PpOJPHl5N}~ zq!RY_WQtTO4lK)DakM%8w3*rD`KEZ&-8d!OTGounD2o{Hd!2q3t8Hw;Bb|EV3=R(F zBd2z>$lMX&(5nt@dkinxtKDskJQ^f?$(fO?m``FeW$I)=^)9WQEv|VL2rP4$8j`fM z@%^*x$#h-V9HYhA&7DpC>(CAc($gWEV2 zYe(bTN_wWVkr3Zzl_ZT;uP7})P7dSxJ;w>#+uL73FT1n^EN(W*46BOYhnI$ys_rKfTW%-HLOZkvEJ!K; z+$=7XjST87RJ<$mdZ-Op-RwM4oGfD>-!Xqlf&MP-*kg4y**;@@iL~txwld8mNftpj7VsYVibT02(8(HtoI0 z-LTUDvxmg_tmTo>xwgKl^vm}INzTlzKJu%H^N|?`nhgOf5D#I=7#_^^+HxQ5)124q z^yUbkQBallzV9&T&vMq=i}l_Ze5xpPxLT{etq@aCd|Pg4yii(kf(TdK6PFZlpn_x+ z_`Q?%Cs;aobn60aQzttU|1%r^NDZ}>GN`B;i!qyB0O_(dP3IZqRoMPeT<%@-QT3+! ztnJFz-d+MzwUfysqL+4v>N-p)yASH479b$k)yqA59i}B&&!{8Jd}BZtC`odLadW?K z68~@KA%1ZNH~ zGXdHT87|u!QqD4o)gc^}aAK|vTEH^4VRu%&V82EPZyBQ4C%onm|8jw9FAe@Dhv+N% z2xvAYuL)Y$<8Otlgc1SsQao#RW)I)wCWWyuL6?B=6 zy%M=yXW@1bu|ifK0izz{d7-ZDZUE)y9MtUSL`yKWc#$SPtyW*|DRDt$!f3Ih+e9uV zbg_0{c20}t{WpDn9>x-x{X{33lpPZ)C z5a&E8aJ;kpsMG9rnQ9n2ZL?Pka{{NB2_7o9j}xy(e_>p@C(gn6b3~~P=Rp4PE0@2O zkuvRJH;Q+F@tz`Fz$^s)^j9|{KhHtk%uG9m_-DVf8!l+{(9R^|4(N!2>?H>_$sJ1?O%M8skqwG$T-li|?I21x;-ECx2QIe5=T4 z`zE^n6Y~vCri#(e7wlX6xJhEhx)ks>()nW5TeJRo3d%jPjHGJ!-5ze&iDa9(CC5vd zGP6A~wBqRl)%;RDkY=w- zm08*#iaaNC#-7TF*Y#9i5r|uh7{_kFB0--q5dRHhgA<%sMHC7L#Uf5-Fk%__Y(Ser z6lhU=Ma~J#(%sV2)_N7cqdq}1_3}TigMspkEkLJA55*wRDE5A=m5ktE;(QO$)!9KO zvyJX$yJ-puu<)N9*h z1pKcUgANe~XCS|?a;*yO(l{z#B?$tI|5L7=A!{SH2qTkci}PO^qI0dpwDb1!Fj!=o z!-1K$C_(edM2qbi5%T+v2k)x*x&QPn;K)QzT_FCDsF&09`N#8)l_sGaom0gaZI8Op zG5%^`7rkzA_p$xDJ^4y}9{H>#Tsf|qD_>SWtEb4G~htIqy?zVgq+7SjF z64X26nEhl^wGKR_bC_S({eR}Qc;jcBy2poX#c_m+Rpflzc4!ZC`GrzN=?AhI5`Y*Z z;@ve>CwAlZWtQ=xnApdhJaGK3 z`l|tv)^|B0ytEtL&1v3SDP&Y5=7Xf8LF~nlFKM z%b$D&t`_QsG)>6e6sW#xLgMY81=d3|!$DtTk(_O}mzzjsGD`*GXDxvdhowjgx( z1lW(UAv$i{`I2;M%fR5MF`mrb$3&?r@S6p43z~O{mE9Ko440}1FOlj4eZr9cMx0&rMxS__?<^`!P4!T z=Kbn>7*x+#wWxwPwtY8cm6JZYFznScw^@REYg&r?zc-RP4lMu|fBfy%XmC&0EB3MP z_oYUfOfXH5v$_K6pVJ>~!n0YQkF5uqiRqH|NkMA3 z2#jZ$hA{2#I{T-@0ZdvgwioYVT-w98w+*LYq;yw{670+f;^KmsEiPzJ_vMX3Z*;I2 z^<;4e2a{sF&m5KKzGk?8iX$!p8*!8B>G->AYv~066xHr$ z(Oc%bR+ha#dpUWgX;8XKQ@-xIkcFqpNRRz6zFQvpDK5eJ?0JJL5oWV9bLW6P*|rGy ztz09e)zcJ#v6Ae`>h}=m#&=&2Rf4|f*#Wx}XQt%UKjtLaW`apa$=8d_9}0uuc9Pjo z-Qvtf<6xi6U&1Ltl-}D{wfJa9TJ2pI|Fb_aCN8df$OUFP(m8xUZDgDwAWdh4#N>y~ zrmvI@(%wcyM#{M~3TJ5|bKagZA<+ZwFAuyLAO1iUscg{ZdqPjc&jyV07BUjDQ*5wHG8`&Wl*|O#Z>t@WM+lD!A;k=DXTLhO_Egh z%5xCT^MLw0g~XVv7v>rdke&8813zH4PSJzm)fjl)rQ<`Uay0SYz_|PcOWZ|!>)`>9 z8h~$vWM!oAbj4Azh?BOvHh%7(=C%tMiaCg&b>E@229876$q87}08XdU*L+&w7qv&N zjvQ|Jo|;dAZr5!kP?IdgbqC69Ug`~J?yO&S1M1f{12+O_L|sU3DcK#aYAY&fix-gUnXoXvaAH_o6Cx0xeRB9M9b7xc?OY(TA&7W6wj zYELTW2mPx0n{0CDdqTX-Z81g_efCG^)-~ZUxw&SU&dl{}$^Ed<3H^#E{rY^#AV~h! z6Bza0cXD=)rQ8}$PFy=2Yogl_CEUs7JU9$`Xgl%q=!iFF-S@t(t5R;A#M@k4qJkk}84Ud^w%(*JVP(`7i3L6@r=t_6y z|8e+~1OHZ=PBaYRaEDQ+FJ^5QD~-cV*yBwc+j3E)&Z}ptS$|NnGO0#E^4^!OlLp}( ziJ}@$cULgwda?BCSpWQKPT77#Ceybz7+wPDwTFVR=8;*m4Rnu5gN1@GN12KmZPeQw zPk9;k&gY#;&EmU-3y9m|n6P$6uOoA7f3lGt&ay14f>4?9MpDq!9Js0{yYie-ptlfb zlm#M8$|2vjn&PVL=tw0?h3RY;JbYvGQXA;=*MApB$M$5L+1(J_qSAZ7ejoe!hzIJ2-z5DthxW`C zdjN`MSJqAofU&UAx%G1FDyme`ofclojSeuybIhJ_U$s?$rLr=OYJSLjJlc37pum?MJT{ySCO5e0vhiyVs$;-Bgr3WJu@@ z(0T~MfB<{1I(JCJL60zdT~@~g zgF%99z)Fl!j~P!QF9^o5AI%CXHFY(p-`ta@S>HU$}(pohl zubW@-5m`!CYotg;S>D$cJaF=TI&o*+C?_KEDXlu-0dFSjFv5!8-^6;M=cHZ|ph{ap zpn{@4x?Nmqkr|m`%h`(PFR5JuGY%DXEIp$?e zTW(;HqNK>nV8U`DbK~M%u#(+x?{Et#!7k+=&fgwjQDs~5s!-KG?pKE-71HV}V1w~# zgC%A)E-0SnlX;UWzTYX`!%e)~PXAd^azRu9quxvozb)1C5tn{ieZEn(s(v@#1MqSt zh-dG7QQo@!UjQMFmOW0|WXlxLbiH|@;yv1JlimsS$tIgq;8?`bl*mx1)6azU>;_$- z0?z)a`-+M-K)If$n}FL#sv;7DhUYF#z}5!Ea%@M7?R>G1g?^2j30MDs6obaLNUOh$ z*?Vk!YDg?zqhM{&ZMuT;A#_g-w#V7+=Rs>7(?iqc;#@2C?k?6T&%KHu>&XbI0@t7G zF~!)|kbym~%d_*e-`xc8+bQh>1}`^7-0g%YpamE>&|GdwdX(gnr)3n$OPSg=@-6?? zJzY(KX!oWM^;|LQ@?fFzglj@?2L{FTo1%j|NdJr9oz33M!>E9{6*bWOT!>3o?5>v zE@zIGcQG{uj~*o89q532@6GW)s#;HFwb-Ap-1?YFpuZZA+VGsY`UG8aJ_LU~eo$wV zdhv1bda3id>3~`CJO4n;Y?lnj4}dOqW)8l#@mQtNSi3H6yh9{%ut{72 zaJ_ie_sE;=EB!&+yo+H`z<%c&s0BEIBS3Q z`>R=kclZ${5X3(OPEVGAo3UHTtv@6264fS9fp*?u-t*JWhn`Bl4HCj{HXg;>+^vqT+@Tbx+-ZlW$4LA>p4WPd8c8en8^3qgqVVJ1 zJ@&#`p^b^B$GL7UhPB#^Y_aUb6LRA;#*cEQVLO%M8h={4D*IU1r za}2F07+Bk_+TTfZ#9O&Yu2*?gZ)A`G`@5AhX#Y;)PTgpu>i)@!2lu`;j@Vx!V%k;P z!#tr!p4SfSIpc^_fTJo_>VTj3i}HKoy2EIqG6)WL%z68E-`rg3A83>OPXrWMF8uUH z?nOQ$5{~9(_uXwu@OiI0SIxywB};kooKhqL+pb+#{a)t;!KZ!`1eZM5#cQ129*^~d z#>SsCY*?+_Avr5h@0%3UaPfzBcHRzZ!MP}j7&&iO@`gpwV^d^@}l;UV3|p|KyF zdwb5`LOI|oGy=Vi3~|jaW3GfL;OlqKrqElkg&*PanH@z}SD#A1oHatU_8Fbcy)0U& zC=|#{1sTQyjcS2e40==1*HDK)R|&;+hXj>*ID=~z3xBFyE1Z@xOyB0{)tD&`>w%Lo z%8t+q>FA2}_Bb_pPT|Mky}qf5L&`xJ+xI3QTeQ9%YiA%t9x+c`Bo)S@kK{qXRb=*b zxM(k-#jYp*Zo3N+N|e;gqhPwQ2P4jt9lT8ILR|f7npDbBI>SOAtP31vaT7&*|fu+ZR zkn^mw)T`~_62V^+>Dk;Ar}{!63BO=dk-xT%gl6FTn}f?qN^el?2>z3lWE?nXgduM~ zKV8ebzeE|6Ott>(=&oJ+^CkK{J-SfkO;#abJ2Al;UjMvq7G*q6eg7Hwt^h_Zp}qHm%Wd09PE?iaL&UE#1|+$2ak$3dLG+wD<$Y1jr%><6>tlGJD8Z={d@V` z)y4URuY=CrUehTa$Sv!rsbZ;VwN*Laf2`5_`hwXR)FLS#hd7aj>s>pU2)@t^ah`Er z4zquW%H&kMW)Jti*;^}Otij9xx#V0y%9Zj#b1v*bK@SVmVo=Kh#&Kx z>C!9JU;~V@B`8BL#e`aa31b#WPl{PId3~Un-dq^GK4Fevkr4n|Dp`q`G z<_uLjLFf$xR+RkwS_fO^B%%18Kk(+ZIr`lea)y8@L)SRPZBo!6WiyczG50So)e-Kc z6E{5XDM2aIu$2+3*Y37gN_zyk|r#-!cF>K6dPcLFtcqWWTb<(w`}xugCN4cRKMXG z#FyIqS(8XQ%5L?_FE62C)LF;?0h>i72E;2-qAc&&0O``+~R8v^Ox zc?}BrwbVfn3h`F(h5Yv!u>jQT6I}>M+}CdisMAZw&h8*ok0!FW-|S^#QG|rWTNmKt zr6}H8RgHM)S9-P*3IW%4r8@1#8#^5k?^xcd!+gkwd@X$S{U3H@T@7J1Hx{2!RWIix zHu*yYxJPILv~fNZ8UB&LGIxLeLrp%F_i<&5>hI7?b!}0(HQ#H)%Ny2N5Lz*%MscEw zJFuSr<^mkdrD4((g5I}!|6V-F*77ipoIMgFi2YGBr61FKQ?b{9RoghC_Zu3TS!In`;tV^&+pNHu&`Dyr5KaoDn*y`^ zchoGOOJ_K+b>TS)oqb3ycTTLeY}p}`9_f{<(PpW4*Wy;v%Vi$gl9TC-?Gpg2=@}*D zoOwGct%Gk4EC+INM{y=M#&X~@)6naUBV`O}wPHa7oX1_UCZo{A47@U>GeSixF zmwNex(I#ewE=-Knx~HJe8~pT+VG>hsTX@*%R+3nhsF}LVWjk9b+k4Wu-lX^FuDx*? z(`|2Plf50buCLga8YRTsX*n(CRU%bZxe_q<%%mPI9gP;3NCz{Ja@I=*xA*N=O1_|2HCLD!4Hqo#KpDcDJt{tlc{qBG!0~RlFhl*GSgKAuIF3dlp#3t{Hdn?~b#X$W;d}xt zyVTJt%P^XwVDIlV!o7X+VByX4cIJ|8+|pp=ZX;EhF{snTCox+LdVA}i1QSxSmPD>jz774bSHL*{iqk!|GKnQqBSfHj@< zPlt0`zLATmT&lk_`kPG`RzH{H8YXT{Fh#85<#R5DDb_Fu1&q^ATRf%Tb=X}yNx9vW z!L+x@h=_Qw?#7PG}@inLUB$+<)wvHk7TZ(}&SmyeDr-5)d$HN5gj84NF}l}zX~IvE$*`)Q*O-(=A8t_rAmmx)POLmwMD;$Q8*PF zJgPryr_vv_jxj?SJW@9l$LbtU8@Gp~GJaL1U=S}9xWQwVJ8>qM7^H~^H0@FF8zXA% zy53Gk!ys^4Y0qn1o^Fy!QrxCaZo|l-5LGWMiQ%@ zREUGxWg~(X_u&35&)MVNwyQ&nGGSXtksgC$@n)8P#iHiO-?oSE){hquQaaT#&AZNW zgDvoYHi8mBq^#}wj1|!fWoa9ig>8nN2Y)@oyAmZi%t8Pvo3*335=NtYqfd9CE@S)1 z+y(Q@Q~>F98mLK(yI+LbcsK2fC8LJ&?_3_i&O0`zW5QYs9ZaE;WZ1I>i$b}*B#YV*6mS7ol$|$5pV=CDm^rjCLIKXgdPY;3l11M zWCTL!U;zXLq$ClPBAtW~S||w+6afjn8z3M^@4c4?e)IkF%35!|_1;=9f92epyYD{x zoO|}(zu&n#dY!oKEn(iJ0?rP9tAU!RHRZuTVepk_1FjRjONHXeH3Z`{;TLesNyC*$ z0WBVKe4A0hk7vc8E}52!tWdOO=_P?2Fd^e5ZA02%o0{rrM>@}+jG9e`@_Vr9SS8HXMW% zl+F;fncXC|?+Msahx`l1cCNjb2|O6Wy|oGGN0>FI*?ijeBwb{i5~<8g<5Shr44XxX zjF?7>Y?xu)`=?%9m9DcRKPwKK75rfcREEbID0~P)2O0@cK5rzfhFMmX7yX$OaJBWA zJ?n9Reh>Fc#RY}kuKDDZbzc81^c5F*)%S3oKMLd^J_=2qZN+#Z#ST&E1uBnCJ1`~8 z?eUMRmb-jC&T*X_N$|ABOyn6Y<+R;XUQfuu2I|H?-~5uEK(j5?Zc4lUS07eb@JP<~ z)3emT<mz0+-H(!MhB+1v$RZiqwK4SJAvq;xhF32U zy4ow-7TkIr!hE5{BbS=qt2Hrd8UI?K;5}h~+rW6VNwnm0poJC#Gb_hT1UzR3yzVYmyKBl2v21SEd~icKfZb@EEze|d3$rFtDcwSk#K#+-+{%0 zJ(a(?*DFI{FnBQ#dbQS8++5^%8<97k9?a4KQUsR;L(##jQlF(xt`0?X*i`s4HNKO1 z+<>uC{xxujm6!+*kyNB<>4E%bjJY5re|D02@j6gF>9_TxJCPCQLen6+I;lF!nW2P19hAhT?YZ znwIJT9bW?5^A0NO_Gh`V*`5@%I_b6<8Q%spcW~|hBAS%j-nXVI8b{~LFNZWxCCsw< zyxt=h&Ipzy7Bw5{az3OqUQhpq-i@khsQ+ohVFmZA={(tBU7Bepo?BY1wRfe;F!XcN z=o!hf97uNGqQ|Dt=}nj_;$$s8+mxzmaEBfN>V6rVjG0ARN1_T0r+#7+S1^>S7udhF_pCQh z+CJ`gYuz4u0b=LTe8Ey-t6^WkUU{ZjUV7t9iW{s=Fo|~Xg*oh}>fvS0mp4{BwnWxe z`F6RS_Q$5qwjH*?CMjH4M?R-ny0c}i{j;;xH%b;$b634e6XQ6EOmuYVP)-DOYShNM5$VKZTxXkRagclZP3di2@W^e>wWeZiT z_X=ywL3Cj@igCX3>iMmjr)i?vd)F7&XMEPy6Wlm_gbOCKe4(8xNNWI4SKioSpp1K$ z^n`dHN9(+Q&c6zfN6bUSF!`x==1s{mz+<*_)WHWqPYo+RsTOyu|f)J@fjpO zn`Ajj^?bSeR~PdUcBgaYJEf52Y#C7@B0O(L>irGoR`Q5R=SexQx4e%_WZk&&Zv|L~ zjzyaXycx+cEs%}z8q3aQfqtEex>`p}xcfcV!8gs8N2LK1s4N>q8E41j5zSV9aCc6eA;_i;qKU=mG4eeGE_Or{7 zU94uM=%3>*NujvQH4K}t8eS9e^TW_ODDC;8(5dhnj%tg8=0Efh!tMc8F5i!?67<7X4~%Lj8<_nL1!?*62D6B+X{$J%1P z=ZR}hVo*p^vLgoVwpM=(0g0B`Ph#G&*R#0gG&(`%ifkZ{_-Z&kP$7(~rIDyU> ziVaZkcF>w2%(%Z5oMg$d{UA9C@TD+me(_fhLbZ7oxe$xW-X1iJ7Q}d zNc(JhD(`7Kw&ne)3mut07d^jVmf=+$-xH4W|8ZYyvz*3-O)p#fhnC84)F)JQ&*xWm zZF2}{?_T56(X16o-QEiCR6Bnw4k;6vG)7(9GBS@N= zXsPUW*K>EVm(%`dx-3iFpY08Q5rCg+ADVOc?;O;CgVaBLSs?bm4{`ioI-dUpErus& zpD$Oh$27UH@F?`!lTLfiRC)a-TW7rEbE4pj`<)prtbM)r`9K1;wn^0aa(+ZsR=63%S3 z-<&&2EXflfk4)|O>8 zCG=+br{fe-MzDn>Ivht{AQ&90Kul7LzaD5fs?t*$^D5jU%5UQ1QB6A0Ns16gP>gh! zVOj0S+q{L)-DK4|3p(sW{)YR>zVr~}+7dhA`nvsQT@~-(UcXsTUPKio8abe(UE{`g#;ho?%nZ18|)$eyp#Tl(z(h50V9J{Lm*# zeAAcw(Fol86EOW-h!|vwtjA&6-%PPbvCQ+rgPoto%Z0%{p8H2+8Svk$yO(+pV$z)YkOH>FNzk#GceF_am&ctyg-GyK%DUANquU(B5 zTMDt~HhYR9_(+wjSetUg*14fPMz-p;JhdPWz?4s&h>m*7C2wTG>7cCyd0*&IOEc?A z3uNE*6;$rb#RjrY9u z=QnrP`&qmRB=O+2WPaVi9bIh@k66jUOi|1YO44(O&8T_)(h9zi*Z#=ut^p25KIrU^gM^YV zEXJ>>e27y2&C6ZQC5BLdZd*;N84=*8tGa=mjJ(->O_p@y$DFBmy3QvJLExJ9NPP9C znyJJ&U5Habqo#NKHXHx)J}-OM>~j|u(V;@%!6P^$!s*F7YBj$f>T=i083xqM+8bVQ zaWVIH?2h98e2>*9K^n58>bXsT@Ki8jx}#~$^gDN^v2xoQX5v@}p|ul?E0M5ist(CG z*>F;=XeoVfs}bO`b-W#1vO_7HHA*!IZ-QMftwLozFbKpMO325e!x}4NKqG7oE<0C` z&inrg!3xIA?Km^*cVO|A_HPTf^G?H!(B%k4@83`wb2J zW!@ofo29Q>SD=D;Rl&P}&5ndSq*`(m=$k$ZST|ssBW^m9Ls(X09j-_I)olxPU(SjE zxY(7E1kn`th>I!}__<@8snr0e_&l&5R+(;aX4~d)jF}DBlR772kH%Vs932e+Tq#>D z+ucvqNw!O!Es=_aF5NZYc=0^hq9Lf%!pI_Gfp`m~qOwRlunrh|?xG6Ae~D#Sd3V2< zPOcrd6#U! z`8~W;jk2q~I5+2K_WIl>JsDvNjCYhQ%0VAuiYU!DGni>R`WWiS0MZw``&=pb#0n1r z4Um!{{G!ce*#ut=pJ#z?IFG`hx!fE|hmI+ds2&DH<5ley)eQ_e+H@`Pt1C5KXcN)}wbeJ(WykP6qx-?0^QLTe&wy0(xRE6~b zyQIDp+vT2WoB6W9w_d^YgI-TD6!CcVqL?xlkw4QiFz=L6soSpOsd`D7dt68(8=8W_ zQA5-x(Z4AZp2w!V&TT`zNAgLSZz+JFTC`T5kglTGz$0}WL9!%;WD%>KjNXoLOR4Q0 zjDryYr8i@%4Ye$i6g&$J+M{V}-Vob)@9c_JHsxET)Y!RNq0TXCWr~A~M4Ik2@?+$5 z&0)PLndpnZr;9Tc%wMvuDqj*lc^1oQiidEjruq5DpxOucjeCER~lLp$}rf>8p!{QQW1F){eN&j?+N8zaNmp7az zmsAN$8Wg#`VJnQ_9n$9F*_4}iHQ6-T%!%k(%fvE`kraRD@wz3T0&KM378A_57~~c6 z`??+JvB8hUn!>5kfGC0Bng_(TW@E-E-*U)I7EJX$@itq9bbsTarmYETFf1Bu`yp#X zVW54~__n{xqaqAJA2I?*oYQ7A`5LR@eqT5%EqI)&N7U~~fO|&S4PWwE$QCwnC9M*) zz?Qaxr1`9`jt;JRGx|-Avk|wslK#Mx5TcOo<+&_?e+zZ!Zd>XN;bR|$3~=mC>FB6D zsy=lq;cfUnqdg-xg42039E6$Tltfa+bO^D zH#7I0HSjza>Sa+R_&3Vm_)CX#0@LA%j4~~Y)61AVuE!$o{1a|LUFrDu4B`LtsPG53fEx+P`VV-}ZMR@W+2Zr2Z=`XsE1*8*c6s4=wen zxJwow3Tu~J8ov1mq4yBL!#1;#KNDCcHWvz$O%lO^7lXU+^Z|4HXWH8OIy#MHy}G!# z=A@()m;EwKe$+sSI84k=xSH4}4$~bb=G$Nz4fUYTt{NLM_H0HAw7_g7j_>rRr@oZQ zBe`jmSq$Wv2ow`GQ73wImfba}pH?|@5dfH{*SY|qmW=jNnfFUN`vYQ$?lb2J+?>5D z#U~(=AfboslZh^pg#^brPo=uL{!P~F(q?f(B~T;Y3duygv_0nh zCTdI0Rik(T%kqX1bbVK@Vemep%&y=>9Z4=_L}nBtcgU(zJAUFmCR;1v1n{!t*z|s0 zV(>?`1Bh&$zrZ4ot9C1JZx45~cRzhnzO(iSNOd-;4iUdLB}@b`%wz_szVEsfM7!2_ zblD%rpXM)PWt!Q9!Sv>12%xq!5mTetGWrdlgfrb5HU>Z9&Zv?4%yGi_@76%zj6bq$ znv3u0#=EMQEpE%>VCCxjQ75%WQhF&!Ce0CF z8Rl9Og|$$>ChO8`9dQrS2&}^=`CwBH9eiK}mNt^}=dt<-E2*Db1Dw!A>XGF(1C^%j zLi%*sn*cNfsk4>;1Eku~J;(esSzZQmrtsFxkPHlD5=2@(w39ECe$)H4_$Nqp(P%+x z)iZI>wCl6bLjU~+6{BOT=q&^&VY!#D0flVvHwnFy+ip56n6$TI+F}lMC%#p<026fD z&$rQzxUp19G~{>A=|hGiUX2UB>B&wx2SijUf*>b|*WOBgQnCZyw^y5q>6f0<{|I1t z+pHUpB|Zq}cTQe@I2kzpm#be&fcHnsEz8og%gB)@quO?T(|^8Te#@7{u7G@DhHCH4 zt7>Z%r$kKWe{94Solf*Ro-7uJ^qPrjK{{{&@@V~O&ryRhROL#pcyzZ}T`U02`VA^p z_1Pu;tfDm6YB9L4>~7S`t?lSaH-+F^YRcMjgCAPhv)(REmZTs)zRU7a3GU9nNaq;T zdsWz44X4G&Cn_`5716*Q?)HrHQk?=w zRuLL|K>2QMHod!^9Dw=!x9xHx+V(Lm@wWT# zYcw1-lPa{93*TU??poB_ISB8EA010eUTtgrNg6E2$VQn8=7`ficDHdu zRe+Xb9>U!)s~{x)>Lk!tNv9D8ft%^XGVvU=_Rp+?c~tEn-)jgIjoK7m8PBov?mI~~ zx}(DGeN`;O8s5p>zy2gxYqbZblsmT@fzGLkN|MIhmqdt4*A|L~Op9(?Wyf#m6bPsu zU^uhc^SWj5R$ijI&D2ekZYhE{FDSyRe30z;x;}(cf|>$~qQihqH6Nq) z{lXnomin!9?WuB>Eu(8DF5u^O4nvbGk|N%9PY71tDU2fS{Vrvk#oP3Evp(_)zvOqU zRDpM$-*$<3go8eslsoC-)3Q%viBQD>HgQ<>4$6=t;P`NxA7rSqo0SV5`M5wc;L2j# zU+iAXwe(m2NiwDreDCF!xBX2D)!P3nFnyKCYU^~cZJENcwx%_@mS1qVL?uD2x^2*Yf>ko+t9&mn|>2&)elGbvO zaCP};?}SoPF)DX2!gaY9NtrvFI$1fmSlQd55M$HO-OC^SmP^_@csf~Gesn=8BN!FB zm*W4CI++{)&icZ|%GMl(7e;`6{|5W_8+CgN7k6VPa}<3C#|faxU+Y7PRHYg~ws?fU_Viu(;*8+9TLMT+dDH)vn`i+a~!=a~N)U^lK9# zPoXj?$V^H5?CqJ2D3ERQRz`D}C{)^pj6WMsA6$DFQ+;I!j24Mwh@*rwREZ16B|4+5 zUJ>|3e^8X&SeiAzRhbvK9(JKZZghBF9~M6Fn&UXZJ7M6Y|B|4tTC*Ktr6hhqTRFBH zCA9uqjTV2JvkDs`BNI_q()@A*@p*CD^EiQ7Rtw3ke6^UOy6FddJ;k2~2FJTrUE85# zlTm2=Pi}v_&th;~VF+Vy$_|XJe6%Vo{Z5t+f*dhejdfp<=+d{<>}9M6rXOPlG>#`? z(Ib{iFjonisQ0Jaj$q0^j4V%6l}g*yrttIqH7I0`0DbIV&2e}D1}zLL$)x!GW2#^d{;=Vzf)`NUh4RYs^jTtD6W`D&Jv zGI3;RH7(YQ+L~#frjK~s{i5dskVjN%UNo9h__clRBnv*|=WM;@=Djw*nxW;pGZA+7 z%RAP;AB1n^?{fqO!r^udRg{*?6FYM_PpOMg;X3p8i7mDc|t_w0zAU8+Su+n-3U2{&ne} zf=bu!iMMP_EMb80rEYJ*H0N1?uY6o!-f3H{Tel5)6RS&PU!9RB=~$B z(kbiMC^QStkX#Z2_ZXgUl;rwagN{@Ull;gSS64#6smZjf#+?~v>ep{OdQ70mr2AmE zx)UKV@twOh?6dF8l#0w$4A_j3KeVONmD0inYRv4hFEs17Y>X$jn3Wib)sjf63p#cD z@h-*fXxCq3OD_?Viv9}OOHR6!{_yk(rPf#(7hxKOCz}^TX3fjuv55nwJVfomhi9jJ z?6hu8*hwsr^U}i1KXS`U^*esuIbSguI=(clk4*X|0u{iQl;yFWF+QClIvDuA>eiqN ztM#(DIMI4DTs$sYcB7@W@5|A13TCH|j_5RtG&=7YGMfW@!WsTqrdqo&XZ>WoO{d8( zw@c~A;>4sn``GK>c5J!a5{mz1OZQW*t+;=Rl(RPx__o$LI?&~;F$7sg?0W=}_Ig8* zuZZZ|0W50;bm*^LWs5S)-4TXk`i=C$Q@ke94U4vpt%`JnstYC7@O?~-7b7m|MW4Pl zH+gNlW>*`3<;CFJzbtb<34^2#=@0$u-Xdz3O0uTYZ@C-`xaku7Kz&1BN8R~cCTtx zl#s271f@)vwb^v=T6`&(o$R)(xs?B}ob59&wdP$7Mhz|b(PoE>TTjYn#xC!^b>DBx z#3~;NzG{-v`DeWuHrAZ3O|J6X!{CU~Qy3Puvhk_|NS78RWvS~>v}vv8rm~% zX5%&ha0Y6G5}uHhXmcmYpXBu9;PULq-l9FFFyKnj1_HP~El_c<4!t;>5xmOP>)i^y zgRP7OWCW}L^(?5+VGK@Qyc?VcMhx6MtM;&C&RxN4{_$mQKJgd$Jhf>s1H(aXV{Re_=yv*+MEXm!)se)# z9V2W;YrJ?diA0;$Nap0~dou*$m>k=Z99mVEszi_&rrE6{_7kQLg$Sv(q`mUUiw%!_ zd8W~XPz|mK4n`0B=b2q}^bm90MO0@dBXv0yxgG7zl#L&Jl)J85NY=Lfn_qj0=VsJ- zubAXwimf3?M!Z8KitCWH6g{PZUK1h4?BdPc9Fdt@%-4eU;FaD=S(joCKAN z4YKrb1()(?XyEE$=h9$Ru1^$HKX!uBo`!Z!H#QYP-ZYrk;nUNj*2q;AMY1N{n0vl9 z*Ve%ZuQUu^7bm@}wHG*tRib{sgGl4A%%md@Ih>fG^6C`9IMC_WDN7CoyXg{V}liu0DBN~;%iK8Zr+qOzSL(P*y}>~- znSsl^QN8x~w`WlYSI%^nwq1UFX_DGaK8)x`$Nj)kLgejE)w!Bx^X%DlNo#{KBc?3(nW5!}KY0h#k;xnEj^cF(+Yxi!PjI_{p`NMe; zrhwr-QF(%^u+&(6mj?r>C1qtM8~Ym>rVFeP?(i)86ai{-l3Z4RKhAqKzdTArqfmI> z;c-VfB?B0MdPq9ofgUa4^f&$B3r&2>*M{KN6XYFBotMphRJ;BeW9>C^`EMZOD)I#W zskL+Dh+6k-a8Z=grJ5Uvxf`M?G|3zN{nmzpo!PM&=khQg3!($_-Xzf9UW|w7Cusoz z!O9)@-*yZ4q~M>(ZpCfc1j=7b_>h9q-l9Q7=qUolkJlWO_%*sak)?&O>Z(kBfRx?($sWuNt_JkJy*cf2!;g z745HJEdK2;G@o{&9|{wTHISPk?99R7Sku)C(Y+|NeX5a@#yW0eK#MCP1%TMT6E-N? ziW<3ccU;E3k!ND`b4wtY(1`bIr(1VNS(X~Oio1D8Pe4ZI*2#C@cey%$ZirVg4EK-{d2-b~xwY*He zS^m~-)%Ekjm0S7Rw(^><^ZgXWe1JVU*%&paaP!pNCDLHM0!?*O9mx!vw|SHdjp-E| zhFxqt{gTHL2>+}!VJ9#kVLDF9usO(#ad*C7`|S71aX;BXkcp6#nzT)zo`8-BcU2wjj~qwv$4(Mp~+~fAM$b4L#}=b@!}BtN;Yu+8=$-zf0n2bs6sL1yb+_ zFS;_^S$_Ct`Tn$TqKz`Ufu9)R3`l{BD@PnY7xi+Wbb#8NeULUQPT}&Hqo9AQxBRJbs^ZccwbX_e?3(m!?i9R~Dmzshpwh!sOC-*`uQvTfFK%fpca5cg}!KWFKj zLVc#YTUQgej#9;)!?OEb?}hmoxEB-cb5oFu5MnfyJy_iGc!wKpXVt(R3l35wyPIW* z_1#Qs^EoX)$J}*d9ie76zucKfw?JP6^}^AC)o1N?Yb&Ah?#N8+k*J6(a{@l(+}Jtw zJQ)(taFVMyh#h634}?G4na5c+28wzBPZe`?ZV7HPQN2h#Y>NPJ>y1FSbEvh^C3X9HiQ1}b!;t2=q}|SH*Rt6rzQ@9KI!e>6pHuj^zGCtT9Sw=yL zJa`;c;Bw2Ex0c?{9h>SdWdsj78Yl$XFJU%_+D$?<%?{K0+^Z8~6F5Nlr+;spfLQ)s zTT?=_V^vg4YY)r(5sqa*DG(3~9#zK&*WY=5{H?GsI`b3ShOJaJ#|kvXF29s=aXH1J z0nQL5^E{SJ^OKQzL!)YY|CgC~s_dJ;wxk#@tmu~{Ow$+XLZv6{*0;b<-)Ggnbul6v zg7W4X^TjQ)IjMx^cX1%u_w?*f`K ztB|PqlOcE5j&oy5p1R?VO;MWJB)YI}f`nE2NO%f2@37%H4N=;lvk2+=~m6yAAu zdrG|lpysB;(MA9qgIpULMUMIS$V|ANELPt{OK~g(pOl;Nu~7`v@bKY^-f(~Fw{Cq# zIe!)JA!%sQ-kO3BsMtBd7nia)qqy4GzO-_t5qnlN&@E+9>M=%V7*y%iwVrnY!}MI-Db`O~L-xT~x6m8ZnNZ8%}Vvuh6U=P$G0U#{;W zM0{>B8&+Pq9kB(cqCzVkE&mMv|}Ue#9kHi>7&+oPe@KZHI+A1!Z$OlQ;( zsm%@1R57?ki}=&yL0HOd5KOq6%+>u-I6?<{t1i1RK~L+y-;mXg&a}YgkI4`SKem76 z(CFaMN91;QNQ5vbr0_B47@}TmA9=ItF?>3RsB1R;SkRj#s~wyv^|xvK9Q^p1{6tig z3d6al4)`6BV)KDqj1-0e69hG07Ec(}9~6+-&`faMtvJ0vonD0BAMUcT)VZ0e)troY zYr`@RAc(HXT3-us>>{&IH_hVWgZtsK#Kzpl&&8r-VfZn$cb?*|NiJ6sGR!9lDB5se8Exk{#YoSC)rue!VU zQwh}7+8h^Y%BnL5xhL|VAouwAg{WR%i_smnDZiOUV+)d6ZBh1zn>|ZI+?iZZ4+_xe z9z9s#p`W+90AbA++}iX*0v+ws40XSwV^0j04+*25b<|95xeoS=AX(8j>BtQ&m1f*E z%D`JoQ*B=UCk2|BU*7)F$#2R{?%hJrx3mT70(X|OYZow^%ZnJ=GS>GL3lozkJY=`( z_9)T8blARtO1__QREk@au^qymrXsG9`HYN3rGsLF?ObtOyn{JZ`snFTgj2rssE8s9 zm}a)X-XLaLkg!AqxqGUCsi#|(xXUB+@nuvGAkQI`wV)KmAnX*)mBWoi+MlYqs{kd>258gXUGho z2UF6l=y$#lKhJRSJo9H|Gr4U-zc|kLPANy7nU3Bv1vD}{{8?WK(6-AXm7m8^a{U}i zG|*^%PpCB4m71*F(Zj%w)&3$!1YU#VOqbnV-+PV2?8xooPZsP->)Uvyj`%aeE~j~0 zUmj*jo=zwZUQz}S{K7bP^5qWWMoMeJ=RYDyYa;9a8IdjTQ8?5Swy$V*fPGm$-!*wc zN4EBPB_^-n7?d`OP%qC+Sh-3vxbpun`GOQi^;o521yI8PI{9|pOzUPdVzFO^I_JV& zn|N3~y12BF4&C}hDw&RS%0T;T53X08{g3e^$^M6Jt~9OK#ZPMP<7^cs$CkN z^_Zpui+f$s{8uCn9Bz+qzJpZ=+ntC4FXr}y(n5y{s_5hT%&Kv9wmd+t6O-hxO*1k&5n%?T(>rl>WzrsfWt{~F`Z%f}UmRo5!*=ajYaADq|w zvOVWfMgkuwRc6%zDr@2!Spp{|mD7~e*oNu|io~xYBSPv#@GCQ$cwi?i6Mm{mTf)VJ)ZF!kwq`(L?!gLPLZ zg}0+={HlF7cNqAZuaf^#`lV9o3ZT;w1X|Gx6GIUM?6XOt<(#w?>^14D|%;{ z7Z231^hA5kZC+W3jm35tPOd-svq}=6=}?Pqp#lKHd=^7=41=1QtvHgoZQg+x*_0lA zU>;Z3CdtTEGAC9e?wWAECLevUd8h@*I^Op=iZojs5>XN07QODcCA}CyZHitY8~Mf+ z=;4j(F2%Lq9-MVmmwt}AJ1|d(eth}Ez=D42Wa04>m5&S93T!CS6w4N7pY)hz0G-0| zgEZ|FH{ZWK#8mxb*QMH_%g9k6tK~5BO{lmj#Mc%py{Cw0h%NK+LrE&r^#ZyRsF|U~ z!PaJ75h2LH{7VzoY4uh@4NEB8pS8#72Nq5e7UuCIdY4|cOQa`$9*r~ww<@EP+otrv z+6QHTN+-EGMl4;fTzypL!!S1#PLcc2$m0Xcd#0K z>65q0x`BHYmo{NN$-}akG~}+?Aoe@}d4<7JYd(wbvEyifpr*!M zWw2?2y&aqCq)8H}7ADXIi`0Zma}SgvF2_<@ht73-ep<1WuBNMghgA6g{a}KO{8ToWV zB=zmap>5~sxHsdztPA9#X$2j#8RT-{HxN6zGXfWe&9DPOIwY4I~=3~RT8f%`%<;$Y|JaliB zd53Cm;D z(@FR_FAZ)Hu{jMH2a!9Ce>b&+%_TK8r%MeSQoc-vT-6KWF(2rjhd|0TYAm0Tx3mvV z-L_^LYX5C)FS;*(?O0=Sqz$5}n!f;p<*!>LOn}Vck+b|cUuOOvg5(u#Kq4W(yCz`bKLu$11iyvZLui{~mNYU*@A(aX zxd1`#0fFe4Ej)t%W{uV9V7|J6BS_b3zV)9e{GSBKpUtnWq-09)U>Ui-^!|sdfI|q>x%g*fE-S*AZ1_h9z{PItuAaJqzPOGZry9ff6{Ce5j zeJwft%*AuAwjWM2aQN9A2667Jmfbad^XNdc7_UqDe(2J)t5~XyAU&S`>zfOMbbY}j zg?9xVCo{G68(G!g`uNpA%Vn>UlBemg@MD=)Hdt(d#a}i*@vdOp_g`+w`fP0_5t!V^ zlaGai&*<@yg0=R5Brt5v(~Lc?-{T&sAUsoe<_ND4q9NF6_jLg|+V@%lKjTo1^~XT~ zgG?*}X+{GbRqKvrqs-;ni!WX?D>L|g6e%gZn656qxOBEmKi1%AE-g4|+wiT47ZXo$ zWwNOt$(3jFJC%78S?b18V<3g~(3Gd(AAYGXSwqR>*+@x@C%o@_Ivv@(sDmG$+mKef35(AJhJ7?8 zuRp}w56B#zRPugz<)vo}^c2|x0*!zBLaGAWV3=wHxA(QSiH5nuEB@4FQPru;Gg}?{ z=7vW+Zkzl2#xyr??d&-1UWBi~PHfnmsux3j5{ce5dmlnSpEzg79R^YR zX_D0~#I|*jBUHHya=R`biRP!1IEOs-)?bxCiChqJXI?j%#x3Jc3jr4LEt7VCq+;9;=o-_>MJwWlcg3Oz@B`ONRo_>5A`Shs)X8Y zJhW${FTS@Zh&ClGFY7tQQJVN_;ZGYnCbtV~58fTx*()$62AEP6RP-h0s=uzb7$E-ERoX`J>}3ClM@3T;0_;O^iKsuX4D}BL-ui_NYXpm zIQi*qR5n4IEPHC($6TV=XM6nw3FY)j^aCx%J(~+R)uoD1uO7-$wyjnw)n9Fw29@7T z_f#YcGsQ5*2iody6OtxJkNtJ=ON5n`}i z-M25`JGP5I52a=!ZPk-Rbs{N;jw2M8-Dkb=fiiP@n*O&Z8XMuleyQ~qY$~olR8*JJ z-*1352>R?znyle14t3S!c=*Uc7oiC^HJ>~_WQOT3sf;bcgOxxtmlgV}Xz63Nt4-<+ z;;eU-Txseg4D4wob9haH^iml^2+!58KMz-Kh<1gKUKzdsA#2zl26VlKu@?cFS<- zseFq&g9SM$M*ndsQhEEcv#L<%z}`VSPnd+55zA=a6}anxEBbDLDv~DTy=KX&k{c4r z8Fu0BXy8GHbtR5EKU}W&Ly*cfyc=9uk7UI2gL>^Z^Z}W_f7iG0MKa{@i*y$io9^1W zeCb(}9X!B(@S*b8@`=;Jj+R_DxzciGm8%SAm$Q2HuS%G5y{zka>i+qs#xX;3rMpX) z2C?Vsa=?Vk6?4k(AcW44zccD)I0nCsW`>~qb8FQyZ6He;sj_|Li;Wc3&f;HT7rBKG zMC%i=5f}b>{Yd-a-?gk#aHkH;P=NGvn?8NE-KwOVxB{hTk7M6E3oC0|@>WcI^(8nDbn)eDxlat!WbBUAF5v{<5MsqgLf&pClcKCc!(-;ES;>8sX77;C=Q+a5 zwT}m>V-qv$6TjB=*|?q`Eygksx)0_u!FKM2ap7{?Gn+9_f20NBaJ3$*a5N7z5bC!C zxN55i^6BKfb7LsmI)E<;W@IYPDl&>K)|5`_H$F=x;xr|Yb#@-|;0w@KwRNRr7Ghbs zeZY$34LsCt-m)m`I!_gU%OBn!CxKo*AD6{=iQajc%I3s~Pxsv!i;Fm}N_gY~@cuBd z+yJUEQ~XWrZ8|jq_bOgW|0LX{$sn0UVAozWmyP2<+eq!eKuB2;me7P zo`izQ2bhbR^%iZtXW-&0Cf3yDWi|uSeYr;6$BZ2mkM#O_`yYp`WGYPE(A}M7dX4NC z+BZhIQlIaH`pOQ8wj`t_GHIRoO%Hq*#M^)42X9$p3;!mn(ch6GeN>HWu-lw@br>_# zpno7l*gYJr=hP?~a*^(8CKS2olD#5bbV1YL8$Z&Da8<9P)Rni9xwvl3POD}0WEpv+ zHKYd@0aI5Mr{5xQaJk-CPcRJ9)K~Gd@*G^`pWJnxjuT%ttd$pRQH`t(33tu(#T7SwsX2BC1R#8|_K|h_YY_= zI!pQC-P1#r&V#mF6dtMfp#x5o{x##YsYESHgk^AB?GDxY;IWYxaPi_L&JOHRI=A0r zF=dK83*L`W!tpKDE$j`6Ny+j`brCWHiFI2Z%{I=_y=7zOo57sh7kW-}{lCbkKsT4) z+q1-<{q*)sp*xgWbk}tKnzJE#!p1?-J?wr!N5vN-G;)Rw{BBG8T-;r+k*Tm1NX&>^ zPry^NW5)miD)!f|EWjbxy`xMYG|1+)1+Qrk1imU^9&&a8TeV)+pqjG%2n=~#kLWUrL%j6N4`{MKonLr3l zA(&FsGKPg7u1sB|-cW-n zD3IqMXEADXYDK=R>2Z%FVN7(gJp%-@gd+V)ZVW+2m(OLswU|rNkX6`(JX}7~Y7AB- z8BclgZgDN$So{vnnb}QHs7LM`dU@<{tMm@E&?f}G(FgbfZ$0Tb9#8{1AHN{5amiZp&iwK~Xfs762g#CnQc*K`_O(+0~4%PJ|Fv z_=&U1PQ@OVlFfi~6KEzGr<~8KCsA|lELjlW>g;ZR?hBE2UQNbsE}8lD-B}eUhx_Zd zjfQ{Cqv6O!HcQwue- zJzLMa`Z(Ze)(J3qMBpm7Ehm2=6q75=v6K`yz2FP>2osR`ejUPYWRQk>$8?|@`Y4AhW&!YC zd<}QT5WDc|elCo`(PS+y=AEif4T>uf!fNITVkrcAz<9vP2a;;R!9Aq)W$`qX@Ys*V z@Z-!YGzfHA`R)@8ce_r%>RpT2tkt_pfreAn@f7s!Lf0UTo=#62a-HEwF2Y`R)p9Zw z{GWNg@GsdOWZ3B^xN*2`#4=q>relF}4OvVK; z+C6jq-dqLC^Hwc>s64yib*t4AHls7#f@#gfj+;~cRAIuT@AY8866tB&)7VU(SmW99 z@?h7?%96XXFMbqKxzv0K?_FPVEHe5%2`D+YIaE#^R~c9?;zd_*qWoNPh(1YFf^F z=gl>RS98zYKN?0CCdk8{FSU1_d~(!1`ZnX5mv@xiB9L0Qcds!VMRAzbnBB>cn`?IS!%@v&|bFBO4 zHJfGm+aw83mY8jazWX97OMs?K5COAjii)3=Sala<-v^qiHW)%SgYH{g#pP~rSX+(f zLbE%`D{}6_R%@u;)6gtY-t^TqPxRc+gnx<3!SQS($gpjF00T`1V6^!;oW;kQtGe>a zaW_Ik@2&gM7`m#Ik@GL;SG$YpM&SF00vrdn453?BvPKWs0?LP3qT3xJYF!)>-sp#o z7k)|E^pMH0*blrPB$aRW89DYN$ao7}P$?aHv)q)pIYY~C6=x%`@>yu2(CN8oa7B}EF}nWU{#^FE zNb#c>(5}XTs&e`v@l2nR{WarQa+`|q8?L?qNvt$2xL^pACIQV^N#D0igX!InulI+r zDZa%z@JeEJLivDVwV;<;d9%eRV&%7Oz@>WAS>*aHMZha9(yf|xWu=gdh={5a0#Rpa zF!o=W%+YUM8eA;Q-QL_JdHtGz+Q%mJZttxMo%QUr_hVu)zhM3!hGcI2qttHv+yu23 zxjs6Jl*rtx_08$P+8vh+C~~jotK)TR3(J65Z_{v)Czt~^dVWv_d%>9HQEz^$W=`D> z&vbXP_Cj^O-=nPn1CH$575%KeCfn{lBM$kBzVx0+EzYbYa)$LiKEC~y;q}4Y*c~kv znS`PG%=>x`mW0wWr*!v0;beg3!fWxzb`ruutgu0`lVN-(g9~<63!`sQ@+Z-S353n2 zf~)K<2#au=$x(818qd^pgswFXk}k{r>#y^A&y9aJp{;teI*j0IVUvU(eH9u(CF_zt_!F?();wmPvXwWi_5-D zxzY;f6f{w->NY!sNnOSpSfP6SILNKSXwy-aY#3+ZrYOCs$V&l^NvLkZ$kG;nA_>7* z&P9mxpw85m%#m~8bw;>&XI|qO2`i4P@ksbxw(lMFqc|y$i{TiK-JAf;s5&S+>`+!t zAdOM)2YRDsm*=!$D#YO%X0BW!QiqGl5L904r7_6&&R+ZzASakYJ<`|A6g$K3-Z`1WYLd2d(s{^M4c~d#BN@k((Q!uK4=w;y(-0C1LCcx*VCAZ z5gmC@UwBaYjSv#uE-TCV^E_m@j7x!$2wP+jm@ez;Uya?-TxKe5U#BTb?rw5-w^2%3 z5lx53?p*U5nxEVcfEI5T74DoO$PP_18kj~&sC3+uJ8Xq|C(k z4ZDEzq>KI%ixxFm?m4)5(D`PECw5_ouD`l|#Qw@PL=`e#sIiUNMy)r2*5Q6QLfe1R zpU!a!TC#jhZ1Lo{x2>zU!?b!XZ_Y#jXz{A6t1Cp=ApEfFLS$+Sg1jSrRTrQiN{H)3 zm0|c{FhX+j!9~~&@yyJw)z?>^LhA*&mXMpigQL~}&^`T9Ecff+*Kk;HLE`aHv{MSgdRRAh5O!LxK>mMNI=`yZn=r|m13p1I?jtY$8y z87(Q_eH?J~<%}Ti>ZptR-kiTVgEm$#8}_(JWICL#BlgABs@Cc;8OW$x%2K%jdI5P2 zx6Ou(cQQYthKvo9~RgXf1Gk6afNipV`2NkexsM zsjP{N`j+WWb-8IJ@71=Q_zz(L5*rdrEk52Eh`y5W9%r5tK+xj@ReKhq-{Wq!G+Kts zV=B~wGJSFP@+eWiR}3A{Dwww(L&*Qqk2R&Qb6uCKLXRSr{L3n)7&4xjZS}OiT3Jb%UF$$csouEvt z7w038q%aj8oTh2n;7q==UA-k`Z+&Nr3!?X zc>Q|=$LaNx7jLUsDu8p_Pdc6s9B7_a>!C=-y$I_a+Z^JOh}AS}W+!nQOH-b5 z#Nopwy(PHcYBQz(g#K8iWp|Psxer|E>0q7BRu~UwKN?wu;g_5&-bRfdU{@pS2nPC3UtN()kF}Io>K`HDunmzOn)WfpNvi(B>y4R@+JiN?* z0PTNK{Qn=OiQa7kM<-svu#9vl9!hW{KSm`VN8I1g{xav2R>Sg0T70{O*QdAUr1o4W zMy#xT-h-whV&3$DtG0S#e_?^L{|6r(X4n7-kMxB z1H6N!2QQ+iK&ntf@sVGTO|zw+K4f9j_lRE|F|hbV-NQSmcRxn=sU1);#&gei(IDWh z-ffHY!cj@I;Wl=+Iu+>w@y;u(@bi1g5)8ncd`IF&oGtGTdhXVwuIdP4~ zg%u-SwaoWt+b}Iu9ltOJRFq>c+nO^8YFkhXL02r<6p@_75a%H?Lz|a*(_8%<#mCP{ zH2;3O!f=k>qf#L2&3b%-mY9G7{FsvQBx50Z!G_Uv<<k-*I`P(c+ee*+z*Lq9Wt&zTlvVUJL6SuGXU%$d=ELd~dN2|W&_j}U zsY!@snwOQzj(_PxTS9JlK`?G^wVsFUC%ky=c}f`{x1elpFr} zQTgp_;Ni%dM;&!DD+BReAyk9?AFli$^V=c#cR|C$PGyJ1#0Vt;O5N6izi{=b?>b@) zepWznKql`&V3^-ezHpKQF#vx`wV7=(e4kw9zfP+n1u$2M_s)F^_#dFH=>8yyHx>XQ zSUOi`t=#Pgkj1;2x2KkL{a#6v`ZsKu2NN7K@Tn1Mq=CkM*!hgY)zY)86X%HK)5+2& z{1inm{x)L+vDUWRMo9|A>mffzOgNwsn5n z%flu7ur@2lQ}s8^NwL4nR;H*w)Z`qk6+MDtV`hN;{`EUi7j$NKyUTgYK}FB7 zZ?y6djL*eGPvk8p9x*rS{L#m#g}~Rc(&W>|tDOq}1m(EPKK)=YUUq-Ye)e@pi`>tv zsFJcp;in_(Gow0b-6Q1ve1s0(#6tP})5x@e@6G5LY=&x!_(IVh>DHpxZU2^e)AIb8 zL04X#Z?x}>o+XBd^Q=z41@+e3B*{g{$teT3BTtfw=y*PQ#VWBo!wr!bZ`>9LtTrhX z*M7p(c8vUiX1!U8VswvN-~C`l%nk9_-_ZDwwFm- z{c|J~F15O$KVWUfD0HTZ^OknzkB_!T1{nYw9k$%qc8}K3nJP_o`tYLL=D14l>SoL| zQSON{Wu^kYznqJ)3pt z_s)&5_x-iG3DA;1w~K8dZ}gxqRm_vBy{T`J79B%tx3zNJvaz%^abEwpgPxgTbhedVo^;7?8Oq=D z=@P>@UaX+S|HV_E>k8)5YhJ%f>R{)O_*^`dxf;&;Hsg|$u+nhS0O%$Xu~vV1UhyGa zv^)KM;#9>-jv$gFrS2-jbU%`TJ?F|=E9IU=Znk}n6%@QF4{)x4*$(c|Y&Yp>PGkJ> zih6|&1gnZX+JdIstgAjb-}4;Hge_ckKGOL5u|ZVkD>w)wvCdWv(3fW zqN9;jdZYiN?1=?^wUJ(kDD=J^N~}9Ctp!o8t)c{l{RoZ+J{&QZHvbb8dr z=#})}A(4%LkVvU5;kkw`U}1b#;)|eLSIn=HjW43ot_l9b1qj0}!xt$tJGzf(?Y_v8 zbcYP+Mo?49I5<3Tv>wx<5VgIw4we@>s>`1~K4uIDYG@C7ispRxJ{0{bFRT9`oP7}F zxmyRf|G!|ENo6q`up|nrUywuBFFY4;a75c&yZC)YknHWH{R2xzondpx98JRaQPO%@?CUgdK*n!buqf!(~e?bl_eRK~{ zA;pw>tl_MfJz+ZGT|mnFH6dKW4?0#T#brS*;)j+m*l(sz!j__hm;`v}; zD|$syigz}Tc>9WmQB@chHDoLz&w>J!qw8!i7Baw;bm4fY4Up%pJ-(owxaKCN>WE2< zLcy@$D|$>pNjEM`dk@6|8zxvOvyj=`3{s@L8<`Dsj_= z;f~^2nQQE1hIJL1c<_uOpM$W~K7hbU7n1;Ftgh{JjyUVex-Bs86H~5_Ll8hm z!1@xH@7n`piB^-Wm0NK60%)&j9MkTd3`$4~ZtEB|+e~TO+lI3K%x z+N;W~eWPQQZMr2$yx`i~pO5NV>O!f=$j2YQUAa`X4Q0I1$H>7SD9rtW4iX3))WDw*_qB?`UGpaRS0%ipSSAU~8ixjcnTF+{T zLR&KNgWX5DPotW=G*ovIcsa5-(SM3QQG88kxi4Z^eKubDn3xPDU`XVVqT3_#a>G}< z+0$-c3JS(TUd>*7!kiUPCgS(R>bDsG$=e($m!2)V7HMPCfVO%k$yC$ubfzvK|4t-d zR_EgA1>GGAAMw3Tq_Z?hNL?4V&%^QTcJUtu^7eB~f(-IqkufEu;f7dDH@*~D} z`o$3gdBd+=uS&^Rtt62dZ6y1ww56{?w)Du!`!fTa#`U6iA{uSyV-HQf`I3>JWv4v{ zVzz!rO=^A-!LvTJMOAAo+?2iRT&k^ODI?98&eS6}UT?gV{P`>)X3NtK%TyevEjBxE zoc(w~*o>&>d#=}b4SROJ*qO(bIG)*d3je{drDYT64mRwhF>Wgg(;9-w>}5>{)!so%7UGJVc2r=k;h>fXqu5r&qVku+eCmUaYJ1&!ko~0~$d%bo$Ew2YGK9 z6;~6riQ)u@;M&1Ma0qTma1SB4OCZ7B8fbzB4-njf2X}XOcWd0G@y2^d^1k19@11Y0 znKkSFnVJ68=X7@8h3q)V1k_VWJ}Uvo=B`8Q+FwbQgg3Z zdfe_VtV*`33<-a6Y>mPGLD5fhTWgf&L-6K}9o`l=6f14SNIAVJFp>9P8Kq48!o$@UmtV!TV)xREo8mv*;OwEy04|;ZH z<-Fz;h&MI2E-yVo!qnfCaVpQ zfLq@LVXz|v5m#;~g#!W8#{kY%Qrk}7s-5Jb_a>VhzaHd-iz4>qo9wER5c~wl;Wg{U zQA^#RWubX z6^)m)psM%YgEc5OFE1udH1!c|0CPa!6Pj@UED@Q!*yl3yh%s}M_$>M6**VRfiC~&U z2L}D|dsi^n(Bm};hX>5^ChoQszZy06;SU4Qjl;fuZ%pJ1Y%FdG3L$ACF(gNYc`tj*)=&5B>y z+~~CE#qPTE$ius`FtL#7ZQuRpXAw)Czr3p(UH0GC7EJhNg^}T_Lz9-DOLh32lMq^D zntnoH>Rs08yZJ;LnmXNdZc|x)1ZAt~$v1VeYSaeS%UVoD&wGqc>myS9-H%`c3NXpHt?yh1WHpIGjVE@GD6Ru(QH;V zkBFBkX#k#+?2S)a`nj&a7s!`uOXFF$M6~F#Fq*4Acg*YN65tA%Mt0_d?k)`<#02}i z5h5;8>L1ultaf?6BZ0pf^xI6Yieqcug&iz5p@c38J^(?tFkmwX@s_myX!c=mIsg)T zg#+Pf@IPq`iZhx|+|jQq1is0dOfGd(G;mh?@qvKkJvmZSF1S&f3;h{M!(2HqDF56g z33$*vzfmhO&%5rb&gsz3z-#Rt;~T%O-DH`EP0g}s*+|A~&0D%Rp3CukW+xiv@Op>J zU|)Y~aMY(=pN~MG)#@?T+cuDm)9U3f*CynQH0#R|ofu~lCNUjb!9jz;a+HhD4jvvd zrWA}31Z#qcLC#?T-*ex67=Gs*KH`Tep1yK=;zu+QSr_liePxyTGpKy@B@MzL6LeqW z=+b4)s$YnQ^7Gh=qq$|z4@H0M<9719WNm^`pK;BIEb!j#CcC=FWnD)9{V{ND&~bPL zgY8!;qQh6_VO@ir_Fk>)HETN2hG0dZ^M0?ci3%5|J*hX%z~?}L94~~H@dI==9U_Qk zQoS^pT{Lv_ot*D;cN%B>Mh8cCH@jxR!e;Z1AFAHMLkI8%n4`JcecFlZT9$wEcx-Ne z-Z{~KH!|}4u!OmdaAdwn^A5RAI$u%bncyR`^NQ{WomZ*3#lsB^Z;6NIvyso6})?a`2lvuVZbU5_H5H75o1fCP+u zEY#@}=!@y?;L6*RMOj8j$=kskblGYi926!CK6vhhO%R zwlkIp4I~C~Gf_gN>S|*vd3bu4<185IQA3whYa5+tSDRum(!9d9pS?5i3bgJOvF10B zyH#RFyObVmM#iRY=#Z0B$_L_A6dwLaFTwhtL0oW-ZNum&BWBZk$+Idbt@1T?3=Z1o zild4vc@+rhn6*pu4rH)}#fGl1gL}as zPS#B6=*nk2^xI3#z7$2tIm?a}Ng>H(E~a)FO}Ce&MJrPMH%YuXG5X)z`VL67Y!v!% zjg?yFE}F+geDw1w`vmsDHlPPd{i4qef_LWhB#6Gx8oIxYs|_>;g;?;-G@|ZbCkCK_ z=H=vU1WGL0J~7&w3kI&NOjnR1T{*}NzfDVINekG|Oai?`eBa{8g$6wGNezjSLh$wF zaOQK!xzIa{m}S+eVx~OM`ne!^bHJ4C1n9>toyYBg51r#EP7#wn<(cmJaPs9`f7#}35;O(PL`2~*-94mmM0BjI6H|o|3>zi z!PA8yaO_D05PJHg=U%^v6iCZIT#MO`zTtd>w#U;-N);<1xrwsw3orii$;m%d-;$7}??};?==JEHV9Q`xs1GHXr6P)e>h^wN zN_o8^`SRGZ$@*U41B3g*MRaK0@VNzO;W(Mgp9@mYpF+L_eRl{Loo*(^H0lzWNX~)= znNX1ps&8xth7P-<)!!L)obA*>Ld{3VEDbe}dTyaUe66_8dD*ixjwu3hUYk&*`WGv6 zjYina-xKc0G81c;+TRe-dLhF&3PgAt5nD29|7@Y*3oJd(S0hc6-M@ZOL7#$R?~-R zwjQWi$P9KOI&Pg?g{hZGnvgKdIKh?n3o zHJ?9cQZ9i_8mx$oOeSVGjRo(vuf(llN7SZMTkbj-dxros8fa(h->3doX??W`kzq}t zb+Oq=vVGVlD*Gtww=WZ_(;T?WN1m`7L}C;LL>d|0x|9TOzB*j6YnarZ@Yj+^DX=Y7 zz~6W`yc;Qkrz=1rFZ*A}i$+o9Kl~;3=>MkY6IELKH=ee)dVle*H-ge~c>fQKA|c_g zuKTaQB%4#)`mx8$)#IPaME4pAG8aR^{|338{?}D9{Tugi&Hrz^@Bn%L5e~OO@Ne9% zXG+Jvz+R;4|Dc`!J62k!jssBxP`%E2bkRuyublI{+$I&`eKhp`0_5e7(}Bb7$9r6y=RtLOn3S z{ld(X`uQKr)uDSC)-#`fi#{ISO~mKvC};(ArHfQ(ka7wB9`icLYtc{W%rG%a3lzy*q^bigIhIJ}k1zFqmRA`ly>irn+piIO%zwOr@qwrFt3Y$SRYCr~{(^u7^|u z-&t_3b*>}&P__CpB5nA#sUc=xFa6N`q39(G5r#_TOyx>a`*V4+JTmL*(Des)lZ5kh z%>AXlZ2*>uT#;YceMN&cTfwGJ-f-M_r4~#bna!v2PRp2dGzm&=Qi2@%3GHqaf&Po; zes#uv)B$=aYT8b;N%z*nS+V^&FX%^{?3sp+r+fSM%L zBv4Zf7p{2N)UnK*0L=rwoHdy9t{tj48C|AM|6&u)HPt%*Xd~34?Y~JHWsN! zM)fvYm7B~fmMjpJF>#sjzG56^P=x;rdvE6Mjulip9}nJZRFGDkbE+$OB>J3&YS}|H zeH(c{)D(R8T71yDzwIhqRE)bBYJCFp_X#Npg#6y7`5cIuq2s5^W@SDrqOQJkO3@|{xFjp*HoB!HbjZ^s580D z>%{rSc{vZQ{S>NajaZ9mtbYF@GlHO!-=@OB{zE@_FCvwTE@OLMpQ}=XSIeig}6jBry@RJi^2bR!Z zoV}5N){Lv)`|!7Kug%+h;E$I5)hBPo2zSiaBd$L>IP!5vc@0Hqb*_P4e>k4}fPDj{ ztsD7O32#EHI*I7v5g^{G^oBGxe0mShE!0(p#|Qopn{oB$x+#6-XH4Tc57Sl~ z77O+2yiGgC%&qx2er;CuIIjv+OrGveI;Z4X5` zV(p5_${Wa^_gEFl>X;=%{uC+?y=p#o1iz@8Jpr_<>fH3uo~-2L8U9`K*7=vx-~$d^ zT#`3i0aE(!VPan~1yvQaQt>Wc9l|E#jyUn$lE3=GN`Bp4u26n_txf@l=o*&bYceYu z!p>7s?;xh*g3M+A*)X+KkNDuKKC_6V)B5Xh*a;9Ld&PF}C0ik1=25}VLkWX>&{C$H z@GvwFl5mrKtRug&%+A)(0q7(hm%EX$#A@$kIy<|4F5-==z{bD1LAq_RdMko z&Z}2R9-}SHehkVxljiEvHIr(xYZwPiEq9_l583o0&US9l$3h%wUGpP;!DJ4XFa0e% zY7}P6`)0nt@Fcia56Ylqp{Rd0)9|YODtDMp_#wE=pY>tg zjX>6wi1PrRp=So~rXz2;PQipl4R>~a$OqcfN0YLO;PxcK4NVY{LL8}ZgA?bK7UA%r z=}$;=;U>2xcO>?}&b@W~jUd%>7h&dNY|L70lb%3l4dO&Z z{7(GsO4wIf%{0=kta(dP71+1dldeF!h}8W9x|`Ji z*{esRHUhy2Egd56Ll3i>gbhT=bgoL@Fv!KLEPgr9&K<=Y!t zVOWjs?aOLfeYd>^xdv7rnUVf6hoWX?T?&T{R0#t{mwS_H2kdka1e14#9Eg%@!|3Z+ z^YlR#k;t+-FRz*!!Iv{e3e6yP9RKQV?bE;0KvUe?oBJ>IM8>Oy`(MLIf-L9%8gs_^ zb8(1wT|rZI!TMRjPxV6iznXA!v1Iz`Tojp@Gw>Hv0;bclufzp^jh@>};ghp;kZ zbGYffn(SP9k_7h<)!5_wb3LH)X8u#gUQglh4*8?`KZ*VD@V>fGxr6NLg1tqA@a~eD zyYKizpk?R7P$t-&##lMI*KtdvfVjuIyhpl{gB6tGrZ;PGjQQ8Y+zM#ce*0fXE2(Jf zUnB@v=8pB=*~|5-6E!)l@ApQC9d{;((LEn8q&*IL#ygZBTnF?D#$VJZPtGq2fhg~o zMQGg2oPX>pF^L0l2Q+}&i;#nYLDgYzPuuw>MEESWwHtC&FA|N>A0>yy9kPvv9NfR z&vc;4i{LPM_2H@&E7U9TTo_o;bJljT?I-l{LkjVmshOZNaB`o^kig zgh{}brFyn8(V1H_O`wkoXhErjW*;{0&OeRB2y2nHr+|h{4#wGU3RH1T0CnkjSW=nF zWzOyDN^nh8KFA`yXJg_b@OEC0R9{9R8Hewr8!i*uyd00anzxumM^^@NAM)zoFGr=p zI0FP)`AjUJL6&$IXa5MbvNe6xM)994R7d1u_O9=&qh zF@;R4jk~mrIgB$5w13Jk_m9oeH#}yxCNjR18tfJBS@+^(-<6MG30@G&cp4>ek-yYw zg2PbGloy5(u0Xvr1SD{23T;G9-hJkDXk#`oC+a+S5pLLVwCodcZ#wthSClDhiamC&pBqK@c@6B3A3^~Z^fJB z1Dbe*+f|;*lnA|jMJed{?NTxMa!DZ`C5M~H)wK#VshQn=57sKNmWxc_K@7Q3eZ+QN zKs>owgWBB}xI{IG`k|KJZ3&Cwq_-(spnKKDA_EX$6L_kSm)q=|g_y$bGAmKS*~KK^JR_m?C0Ez@}30O^}U*@Cgz= zLaEx7qZL4~?gILnh`;4U(31QW|f=UkAFeK>^B%?o4RF8Q5oBBYlD`^!>Uyde}3lPZyCSzDB>^w+(2r zzeo;*jyOGP)P01Fgl<4eF)FCm||x_AEF#xeXdI(0eTx4Px}j)ViLL zOKlRt@SxmeH$G=(M(vBnLzH99vP64WbI5!l*US5oEnL(CZ1Qx)Dn_@>@+J72|H zEys1OYy8xKl+%F;!-_AGDXPi0pK;eO##OF1mkT#EJ#Ioha)L&vPeC*1OJ|6lm#t%` z20(`$0F`lvH8`iG!=>uGjjQmK;j0Jbz~z2rbwcCD3Bb8?RfXec8l1Tp_p{StI?-qu znC0+K=(+ja+3?co7wUT8O!-zTGyDmx`&pp0n6is)_#ZdZw{O=W0NobPoAhFpaU6~6 z2`9JJvjPi zYBHk!v6B8z0%s1!z*yhSKK?OEP#PZl#=yn@2)j$>i8tb_745dL%F4cQ$Y4G(OA|%H z@B(KpdFizkCuwr+_tUQ!lab2?0yx^4vhO<@;h8##jod4dkW`!RJ2fs$9I4@F#3hiOVHGlkV?PvFK7L+4##esVc@kr>9AzgcrO zu1l{|$3EO%mvhkPU1xa|Xh9qcu{Dxihc_$IYUhBNy}DUfb8tc8bl7TBxA}t!J~_IA zYRKJ7OH5%|2X-U6gCR4R$8f}yb7IalHmSo&9cBmjHK6x)S8&X;jdhT2!i%HB$AbMB zQ%>4ev*Sltp@PzOv(c&*CgL zZ2hy$0vF8M8}?s?@D*>4mE~#Tt?@|Q-@wm|hIAOCncr7D9q{2^>747ZN>NfE{|r z(H&OIdtmH&hP@E0`iS7w)s z*B&v)H#H{4fhU z+bLxRE>IVI&88YpMLA=u$Nm=&!N;Ke0`&Xb)}i;ve+4?qwwd=CL`liIA(C}j{bY)y zboKa^*+UWHQiBsf-BNV1mtPZhZ&Yw%?&kEuw#C4u`d8L2?nt>G+WkvEdiUCjeMRP{ zV)M|8fUz4*1B3P#xn=Vf&aEc;dhIQ!>MFb!vS4B3?%OM~9)X!MuEvQ%y*vJoJbp*0 z#X~p&1Bcy3Hx4w5j>VeX#2e{QTv9L&u8mLOXA$m4C+1M@Vok?d?ve7es?P8LYxZeI zrm6_T_mBnyAu;CMM>@YZgZu?W-LJJb@@(HfUP4G4&iGPRZbgZ0vuXcM&^o@hSQD|e zk)Dm1nId`*u)=eC{DD9rt-EV+8DgIt7;ZS09wM-ZF!>!12_Pto42O+=ZkW;y5OnRn z*vtFDBU-0-5YuT&V$K0FeevXUUmY!*BXwFZSk1>bq`;S+5mtD)(Z+^9iH}lG3_2hi z`t}Tjo%-vuCZCV_kCpYC$*Iqcd3gjaYHd^g!AP#i_X?QgoZk=uDOTR5D=MnIeleg@Xb$K_yAq=YS>cX3cO5e|Zfi*=>204~*f8bqz@(>73!yeF61|>r}dUW_hr@lf0*Hmg;+#I2mY{xJWUOO z% zetG0htwMJDyMxs5YglCJt6Tl$$N}^Lk2~&~V0AJ6rR=h@OOuj&Sq$}Jjh({6|G6P2?1C%Kx@1c?Ftgot|qyahfFc|qbFlgz3fVV^d0c;f;?+p z6xzBQoukX|7kqOq7QqoC% z%7nrj`r~k0XuD7U`k?{*XI#&Urykdq)1=Ra@`WoMc~qj%tc15O7It6keAVPlbAqSO zP8d!Q0ii_d%iMm^2*ozyV5foYMJ3o|KXC{`To|G_JUGlM6Hl&9&qly90es@ij%HM3 zl7|xn6-pk++TtXk*bLlffl5juO3eK+H9QYKo5>EbW%d@&-FHNS`t^D$bj`CQk5FS| z6HYPrBBk-DTBB$n#^#Qi{LZxWtc_mUU-1trW9D7%%_vJ#ry527w0gp0L7*uj6uttLA5_Q#bD3#(z* zaUQdOks58~yFgcICP~7Kgu6?)pQ_OJG$=Ee@Iw8-hnHDWffJfNTu4_8yX(j)8cXT& zABMBtBCR|WLAEXyRaxJxaU?kBtQdqvkq_d-i5=6}d%5^Av(oP>%avc_i4`u}j4GCJ zze>NfxAv?zTbwbEf||1Ul`8GHs-)?ut{57thAxew6+Dqvb!DdBb8q({MOO}rQ1`2f zPK3=1C;U26yqF$+)8<1$rKE>#Ik}7@y5A)A{#}SW^xXLY8B8=4++@MNSMFAK!<_JS;6#4Sb=gp@!vt zOz)SaBb8CnQ|)xbbsU&s+iB1W{(YndX^#3)DhH+6#_azuUmVcD`WXswzLC>!Yt!yj70b+yM z#ch`L&+Rfp?ctDp{%G;NDw04F+w3Q=cs!k>O@|G-74KPkrJb>~Sr$DIC%p6a!lFWn zPl3L~*OZ}o!B4W$QfljoHQE}X1^+L5mF69M@1ndcKSAHwEP5H`;3szgw5|N%GN9;@ zD{%RS*Xm!AtWSj#5f$cUur4{T4t)J-#xQ{0@EIOrghNGUdAOu$Y~c44OOsAF{1TJ? zu5FZxduQ^R`(=rA`R#g7sDNGSQeR5mC|)xsAbGf_Ygu*@2#^y zB1SYnewxBDCwYzEVz6j!Qcfu_GSNJGN5OO!k31B_7o7k-v&d`Ei2oih^3|>q{{G!A zpKwt02RK9{6Dj+upH)gY3fn506{>TeA2Q!UQfjg&D6JW?9|J?_vsq*qKOa?g-4DUd z_3M_AHSU1>^zq(+&z$56vHTx+1DiZcIe=V|MfPj{q;j&YVv%jV%R5=CM@a9`K1H#{ z2ce2D$@5y}k0Q1|CFx5dDtIX0<<`10|>h|Gs{+%ru!wnQEnA=c0Rv^b^-_&}Z>^)v7#yXOZpjvn1^0!f;Hc5# zPc}iq72pw56PGVX-3}>Po^RMarkNmA!#v5u5;^)WJU^F8NpI;Cu>?7pPy~yMbXF{P zCJ2DuWl3To5|tk$ats)dK&S#(3(-WBB3dp{I5F^rX`2lX@uipi70#?#6(CtAB$ty( zI9pA31u^x|UR-0O`!Ij0K%>kbDXAhd_kPGR07FcpkEU=CZ%ypf#)+&RbOM zgY@1a1Fb6z%?_4l@G>hm)=+3q0K|CSMb*z!l7YA(EPNGZw=_@TVmmYIZiQ$aBSWZ;^0v?cMA#=|>dV-!Wa4L9DFU7U8^ zmX9#SdsyVaB-yigmAB45+kl(13E_&av!i>9vcyf(u_1H#qkBB$pcxzMGBTWYo#=^8 zJU54SvPL>;{5_*<2#vN4?i$%nBO7_Adx7j$IqgjX9!KC)3a>or>>bDW_cVbE0;j~% zp$i{&ZvQwbtJ>-jm7hORo5RF_AfPX$y?s~r(W*am7Buq0#)Cqcir>|de12pB)GjE7 zZ^R8S(l-Su^v1}zwc{g;rMhJWjyQUg@%<~6)1cx8Hm6hUR*Dx~MoH6RjIU5O@m<4$;i zVYCSuEz5g+dBJK#C(IwIlELsaYa{IBq|d!KNYid;qTEfI*w(u-=5QG5^KO!d6NXia z*j{#fgS`|6ud_6**`P%}v`~%$z#BMDOF(XKvML&&`MY&ZE?XBN+nnEiDh$r|)@>hE z+nbV%>)N^CVQhKx@=dp-`>|B?aX7up2Y!`Eon&xn)TrljMa@+GU**p_X3`~|4UsV) zU~g_c8oju1nwZR+T)8_iP@;a~7~_QR+W(#t!75k8lKtl$khs7NvV`75v9dnGJ@`(dJeaG9^c=+6VJyI#BDP6pe+UzV1qo=s9Ch1oVmDjEdEIZ}D11OTv&IeXYyK>Xsqq}*2hj4#ff5YdYGa3b!tJnFO73}=Iy*uOq2D}YX+Lg2&|OOz4yiVP z6M<9sLs7+A(Z1q07!X1Y-JPDKob^ERk4{Y8(B~i2>XQFrt9y4sE&ffQIkuQbOxbm2 zfEhS4Wdq|+?LSSNv;ThnL6AP({he!dOeO;J+vRYdsIrsy`dUxHJ4xvrLa9m~ZxLvR z18v7@-XDjsn_F67Z?Qqk<*O+^(*zwefN?=#Eq?TUf-WDJ|9jsAB8R@Hi{+!rB-mylPq8Bm)SCC1q0`Duv& zuVdp})*P@hu?HH(JEwryA1NOgqr~ z$DHc7NQ%+@RQBkqTJpgek9RrcVn&EXDfuUC26rQOtNEjbfXet!h|BN-h8GUoY9hUL zU(GrIEL$Z4oU@`$)IZ!u6}Oj6RE`N-`8?ZyeZdPSc#X%~CVBgya{Q%31?_OJB22OT zc=t<~r@!^aXcSj}v%__Eyl$6un(Jj=UrDX?6F2lX6?9u7i8Dyq_+Z|Kk@oykGtgO*_JzItg6aSXz9+)FO%;LES?@di-r7u;wB!CI{+#@WArju@( zM!D?ShCxCyk~lkpD>_zKKAn>y{5pC}(0yK}Yq@#eag3Y3B@Z5`E!^2#%HXB?9N56J zG2giC{Fh+5aaqzFWB@m=Y}MgliY;Gxbj+JK(p~+f>23)toaRcaa8^9(KX|Je(lhch z(4r>W2)Rre2Soe!<14Jhl(xj|_5?s*``czqVUCb&6KXm!&gk3`8OPa-oOj3G31#;J z$H1L=?h7&!7cau9Y}Rmnz#q%AUgaN(T2|&pZzQ+fYMX6ctzXep7N!=i9^(^lEIPP4 zyeM^mWrdwEkEXc@|ZG}XWnafuir4zrqJG8xd|o-$7<46%VWdi zXy`HprQr2Q@;YC^191`JQ+QMJQ|1ej6dB`g?&Eav7)ZPYV2Hc&nNC?S*5o@+wr6qw4;JUO_QCH)O4v|^H?0W&%fdVhfBAGJ%Jm4&9n7olYAwGBx&{or=M{=S`6U*QQKprVQz_T`vr$8kneB4_f6m$YCOBa zqdAc8olTr-wiY($l3;qvEX%?Alsxpb$%G;lLMd;j0a1)4u+i?1D}J@dD|8J;q@*9)uWjsVWo+=nEKG3yrael z=-yL`Vy@#WXsIghFWlqFUaja>T9WBDDTj>(3?amOtX=_m`&?FLmT7j7wpyWfWBbTm z4JUo%!%SZujqdXLxSF|Md^tpAZ4WsgV1n*GE?d5&^P4BakOw=|LGuMAdj>S0Seqk%lqw{T@R2*j6PGN8GzE3 zwLQ8az4OU2Xd~+gDE&<-T@cM}wzZwV6jGCE|MeDWHW3@LIfUzxLp#Gt+x0&Tmp1198u5<^s|mi~?`3w*^sB2Mi4`Zg+kay*TN;B+hcQ zbGVbGxNNz^!R&G0lN(g}C)0r^Z7~2GT2sbW3#ep3o=tSnb9NF#jxpyvb%73;=Ni#I zA*jYm4Q;PYk=lclJfzYo3AWq$L&cnqL-r<>nF`ZM4(>KNNP9?!0HojApXQjG<;fp@ zMLZSpnL8qw){=_hhrMBZ@E)4q67w%tEHepzu^^?7uZtR~W*P5f7tM?%63})ByAoYj zZQ<_kNvTd@bB(awf&s)87=%qXh@LsWNI=(|zGl!c@2gNipMnxwKqvA$RbPY*q8wxv zlB%CX?EnIdPe@f+CK4#Pgug;K?h|O3uzn&}!Bb$9+B^@XuBG3bqOjqq=SsO#Q;uuX zikXH0WM90w&OmW2gUo7cg;qk(Eo~of4|nEAsm7k0s>?Q0dwyNzu|2}h;BkMk7Sp@&y6L@}#YU~28yR^%;}yK! z@SDI~+q|=9c2!{_%Yob%+N;ba?w&T^ttZbGSt@ONPx-O@f>OJyzmRj2|-rl|< z0vpJz`FlQ@IR zY&ns(oP%Slq9V_oI$!4wLk0$w!z>JzO9#jn#dlitOi z>ncO6&H%;Pf~$kq1*!AMu+2tiv(=JN%4rN+j>?~|<~b+2B;$t_y~4^eq%SDk<%4Pc>6EoyB}*?b*`1c7>8w zQK^m7O6=O^v^NG7cNFVe25EGS%5Z&jcRk`w_k(087iiuCmP4kitkp$Yvku{koCEqy zxi!lb=JFJ9uc0!dkV7UEF4_r>2T}c(4op5h}${!(u%Ox_BlY z+7pBJoy(^@pn7N+gWFOXv%!?>CJ|K@od&?9GAjo4`IJAkqz^p3IYbcnjB?=9`R|f+ z^a7oYe}0i2Ibr)<{fB7ora#aAv55)!9~OzGYwCTerT*^lon%BD2X~c!!KkH-Mm7mO zx7i1Ws>)vK-&O9*qyoSP@=Ohu2+Ad1VfRf;!mcmC+ooZZI7*xK;=!ZV{LZZj9Zj=r z*CcBLc220=j7<`Xs^&Nnzn_1hosC$1s{R!38Ebd=u^s1s-aKY?E6Vs-l{1D)!h963Ys5$0hz_lbTaQBr`~KgkDD>H z=7-Sxg?^*+(G*}8Nf>Q=|Lr|kSk8n~&dfidf`}$^8{eW*qSf0RPt}G><|P45ZP~YI zu^LgsU&gYZ84g@ZHqx4Kxoc~N=3rk?B?IdH-y!ycPUr^~6Z=ZFiHx`79OPhM(CagB z5pC0YbK_hJ2CZskmNu7-DL5s8>s-pWHf%J?8BwG)m1O|{{gQ}h;WcBS$0 z{b|oA2@xijnHDm;qVEZ1KD)u>S0Ib}&nWF64c8ENhLfHEuY%e?Gd zVo4!pO>JC%2?5D~RtA$1^;fU1Dvd5ULx|$j@CuZtJ+BDYR}9*ZL(pADAnnXJMOnFM z9ziXgrLVASb!`Xt4{y7Vt(WF={E2aD_I?71 z)-D{dg>L=`vPPAXJ}lO~@FcW@v^3R354*;g?5TJ!smJ^=L?UsoC5t0eOwkj4nG_R;6$QG5z681`#T zlRxx@{gw3tp$S8Hmd2|w`ZuFG$7^X}H6qzDX3-&iOz?r)6usaPHt#=+bUu#85Ny`6RoW{1x(NrR?U_?Gui17qxfVIIHKXb^ zR_CAEr`!_aD~Hn)By|XaH|9`xYQP)&?6o(9bRt=4k)kLcZ0Q&`tg!(BNh>pWBV;|{ z87n6)1lSrs&Wl?Q+|$av5=)jx53>%`j`S0Li|!tJwD5R|4too9L-+ZEynrxmXwmWB zg<#$of0{Om{5Bi4<!CQKRY$q! zev`iE{#T&0SZZH%E4cIU(VP$W1y6OvF6ZjPr1Z*75e43 zz_?SzaH-%v_V(EM9o*ZBj$XI&f{+*ys35a_;j(F<>vVPI4NnQyeCo{NXy6< z3eviNuExr}bGlM&vi!&t_N=-U(c5m7#N*Kujegv5=j>nx-1B2N&)^NaL2E>x%1@@Z z%W?E9d!oK?S-JN_V8=RBO;*G!7O)bxtT-lxC`mYBn z)18RVyQ}Sf7myX0>P&=6g%!ZhEKIN*7H`AT{9C8q4mzy1!QWmU%+7c2a-_BzQNq3LNg-T< zM?i#Zj_k%16+U1p_R=<;orA+}();n3#E7L`Pd3?6Pfu7;{^@xCm+Wo5OMCx*?CxC=Jvb^7<^)OqDRYnX*cnM}|Xu zex0Is;jvE20L9h~9QiYv`~2}w6fz0=(DRNVujW&PfC-Z7O)g}p1W)1iq4DbE;1fb9 zAJhnh3QCl_AK&^x*^2q_$Jm}tU{9U6CO+@W97+53(+-hTVsd+r$bjC1+b^jd35&6-v9ReimtOLT&s z;1V)AmpOA&EPy&^Uxsp+Ylhq}Y;P?UcjvDH(i0GZ&2^SUZI1Zlz2l&aaRVy-KP{VF zT9%`Z!*&-_8x-sUnQF4w6_Ml>f(Z)q9x$4Lgbg?H5?$=qzw_#89#>G_czfn3{inh0 zO>047i4Jqz=#oeBfwk731*ejjRUvz-=ISWlW>X6bcKn{?pA5;r>Y zd`o{3!qsG=e00&^Dzl^X1p6mU!aO~F?-U9bo4x;FneKah1fBwx=>ndRy31Yliwh4o z$g=-jY>F-;%~;WUef(ErBnj9~!9D4v^EkI2{-U{qONWMGbn~6*IoL&Wd^NO6tSKJHp!N^D=xlFIQOzww6yuz-Ft z$NF6)CVcyfzaYQ{FD;7M&Z-8c-!ES9vE)z)&%QS`ssDgLg_v|_<6F>%LBVyy6N2c8 zGh#=r+*Dy$aIHzv9MhM28>spH1yr%XU|6+xdx_!uoNss>LGWl20(y8ygrfYN0dYXN z_V8Umj_BTrDTC^xM&=H8|J_VOgdH0bF1cZ85itr?(`Mt#AwXR-x-*Q`^<}Cufl>dTI;oeo>-* zHJH0@a$0^52OC-hU)-(f>y?()xNH!`(fV9>&oJRoAxaAcku)!$?yOg}@j zSoGj+VJDctK+<0C3=3*3wqCZ!le@d8UWJ}FIy&P%?@4ihrLhaPsGxW0o}!P9(EGuV zK;?(N95w%&3xrJbOWMG5w7S$Vg(gEH*6^Oy)NQb$Os`+#z@3nm{e*RhLah_UwV#0h zNxp1NZN#%zeHkBIHV5n#uq0k!zY{~Kw9|I`oZ*x8Hmlh+u1ha&;3cCWogm>L<%ChN z*ZmMl{sLE&>?c7h-FM^w3#s-&iG}F{&2Da2Vk0ZdWEdY6H3ZrIRltiF=(0pyJ#%!% zkA$k+Jg5)ru)!i^PG&}_f3D`1A8U^=`J2_x4UVOs)|TOa!Oqvq#wNq{#Xn)!4?N;v zhYPsQlo_Pqf&JJQzBKrg(_9>bXR8;F?Jf?8_&=TQi@z#LPwQ<8%i}t4Nq^>jL&xm8 ze{X9sqs8Bu5F`fBXW27DT=#It&jacwCz=%#>by625_~VTa8u6R0BHB3rly{`S#uD7omi7RNdF(B96KkEi0R4k z)3VJ6=OIXMenv^orrzbAOwhH-`tXcvrfKF@D;n5QWD*kLtP(Sq_wKlf z$#Wh7jifIjT-<>QD(UW=`VV!Dl4ej{lw#Et-<*ore*j{bFAKJ@G2|1C#MydEey((Z;WOq)@DZyn zm~)CF5$spCI5%;{CVd|gT+oG%ETu~TvEBEpPKk)G-pMdxwjC2ZL6Xs3%v&gq+?%P? zBfOMM>9KUZ=BjJkxKimpo*?D^)JS@{V0fcqduWaXUmco0r8I7Dg{JdWcitiL(YCmD z=Bl3Ebm?+?f>z_bj7m`#Im59z*vWz1iTLleCeJ-MYCdoAxE$=_(r>LxOK^IV&Ykw*Yc=>v0oMy zt*0e&<)RSg&|F8zA z3%YV|R#@^2E6}|E8h(!6en*nmhoLwU{^cE6Gy8Xhb|e6Fi*MM5Zpo) zM94_fmK%lOwpitdG%95J-A|owy4p`7OFh$Ffo%i(LUhbsg{(2-41ZR(8*9g2r|Wet zzjPj^$!dM&CZ*oTO~fn14^3E{qQrd19~yTfU_-4PBeb63lcm(icvAFeMH zir<@|CNPl{UkYi!T^D&dLmHdy>M+6R$ZtQSouxKtK?y;Q!7R^_epbv*WkD;ini`pSKEZ;Bj$XV?&70Ni_LNX5|pb=zWF`v2BBYX(`VIxqk7 ziLj7DiN4u|b(M+T?+Tll{_cbfk|KmVzW=Kl^7`Ol3ck;X-S~1#?PF+WmpD#PvkpXsTc53!6#k7){!POsY_XTK7cQhF-JGoO6 zzsjCh&v>=_4J>h`eNSZB;wi~NDqr=4ORu=7}4`sv(*_4{4m1Rff=q{{66rdEnz+T%n_w#AJe)Y|yNFkp7@H}@#tIn?Uo6B{WCeQb;G zyU_Zm4QTrIdL=v~O&`>c0c*2RlQEH7fY5lTqGr5%X|Z#)@Y=t<5pzIWzz`+VXSJ}t zY7@djo2>rS^BMzntGeRL3#I;EEk$ATXI8XYFovV{2MsR~R_v;Zn&Y$D1qD7U zb3nPU%w%W_N9a-2!9MH|=Y^w_%?G{slH^5A9>A_$AGoc<{rZq4ot-KDIqCS2PQC>4 zEN?1mKa1CIB7?`kYD_1;|1Ee;vAiKtNhiI1%@WZ#JEl{?+4ep%G+5B7+RY%Wb9g^5 z`b%I$@Avt(>2&H3G)n>=6MRhcbJJqdUJEC~&gMTNRe#m7k_sxnDR>}KuB?BTnGjxm zX>(7?87xS$4`xc{;adZ5aJ?fM4orJT5}h_c^xhvl8wQq}Mfb+QccT&C%s`bJfA%(~ ziB{Ap1Cvd=Yn3zP6}Z}G5w=?4Xwk~*JtrqD%u6sHVMasBV)V{gmd`4CXmGgN;Gw90 zn#`N!k(*VCCg2quLI{lxo^d!#6NB>Eq)H3=EU;V zoixv6x4mSD4(s9k(8GK_Q=OrH?Q+x#ic3q3z^j+2AEYczBdP( zp&t9B?vxNt{Tg38Nv<<-?^jjWj*b1DHHXuzAa({g(>2MkxM(H_XpdJ!J&+LYuQf1E zJ-1n*!9_9o@y`0*({Xnv2pd)>UWnqakUHk8msmi`+{=StzvU$axxnizV^~{E9@J$t zrldq$JAtN>z@_-a3>+bK?9A5&JQeAa^+q)clmS_!w@js6eIvz}Q7ItrQ?DzFKYdO- zj)BbQ5)yOF)HT)P6v^^H}D z1&lvwRZ2wgfojN*dP-}ltlgd`+A;Sw=za=%m_bm(Rtx4Mt+ht##qkgugjb>LB)&^4{X6Sr2zf734)rT%f4 z3-NSP!;w#JE%K5ZoeAyGtfX));S4~h@8h=F330sU!4mQ2ac0oFi@yEjQJ2#3RUoOF z4aj}T3b`R{btPeD5t+w?^he>v{lfoNsHtuom4 ziq11a`&YDXC=S%|M?Ag7tSL|8tMXi?tyW^X>eXa}AezEE>sf=RZ*zyeah?w_;{THi zV7OQ%6Si?MEc^(F(^j%{$(kLzeZ1y)Z zky2wj$Pl5#iRmX#-{;Vj@7wFWC~b^s%abEG#RU{q(HrJ#VQy|u^sTQtWVqq(Ud4O; z6$D~oFvt5m>GV#OsmbBudyJxfT-7w7x9%Xw1mSA06=j&9b6Yn#*JT(k*4H$z{oqn{)zB*po+dC&jq;;BT;5n+yj z+N;XfSnTS521a1DfO29_BUlk}0G3NIjudztu|wY8-I2DA_^1|!i`{|#`j*s6BjPa& zrT)H)4aqQpxWn8LN5?3^K|<2PnrXWBa8P8BvL-$?1FBy}#B=cb>+L4u2Bsr+vG7N#Kde`>a-OgzY)*P~Ce! zI?A;;tJ!WT(keE}Ce}%XlkfD*0J&-WbKt6CX`0x>GAs)~g=twz%I|wp@PY{v&cb{x zr9_LXDY#w|d{<-$1N~G5XBqiXc*u-Lo30i&`q>)`d?6S0%0Cot#$|yldoy253G-~d zpE+uTCdFWrd|}IQ1)_~Rz2P6evprJ<`K1gyb;DHz;KRY%jAY+nYV%4$d4H`1%CV=} zoa%Wi^0to)B=1{fY+OaJPbK47PWdF$t6!4P9e|JLq#|3np*yyeG}ttUz`jH%vU3Py zj^D^qk>}X=ni`X|-OZ}}005qYXsBn{+mOn+Dk4%Swh3-f+lts0#vK2*ijFt_Flw$x z)H@l=&Gce%DpyO4Varlt@Qt?1K91vk*;-Sz*@WdiBXdrD^_fU1^U2qJRoI&q0XP&h z&qWV9rCfLJHtQWnE-4N<6#1396JG>e>O>l3Z%&|n< z$u&+;*m~jgsAIV@KmUWGVTZ?mx@b60Bpg}Xwy>!Zbr$BvbAuz=5}g`W&+dU~=A|LR zW{$%e=+!u1Z%}5)ArQbpb%!_}@q&}0jDTi~v#A zzPO@oRZ<;_!P+QDT&Ry{{J}W-Qo?D%MgzRl{lwASTEA~|oFOx@Tt{U6(@0#VRX=)y z1JUoygygeyz$KlTwtIAuHtQIM=wKi5!(6DK+r|j!HD6R}7Psq40QxREpF(QNAn@uO z7qJjllq*Gh2A5KkLmED~oK&{W|4;K%LXBIlQx-t-Y-m?B>R|umtq>bNcfGRPZ-o*Z z{FOsj@(EV{axsa2x-si%mml?qkPi`je4Oo!&%~xCy#n*s-f3UET6f(IU-;c_t!|^H-)(#( zZ0%fzlLKznV?3azA4%VrLnmsB69ST|z6RYU(vdHeA_kp{X>t1I;c-*~{+dQQv4p|D zMH<_GAj%jXm4B(8{c94L;HIzv_DW+11ADkS1*6_6{w3iwasBs2rVN>D;a@1c`H-np zoG-pV>e)_T;@t|jT<-}4GxnMxl9_8})^9YRqmQ-fZVRta@)?XTk)k&NNb2=(v`C$}9FKpIFvJ~28b*NQ(S4v!WGVf}& z|K77nhJ|kC%2BSf965vh8tzHH*^tH(vu3|;BEoO#iNhRvk1KN1zs3p4kUiLIBl9%S zaf+XGx{&1%T)Um@0P<+yRT9{{-mH6ao!Xe&Sd*y}=DqtE)#Z&_?0VN`t^Ye=+nBKY zae(*aO#>_3{51~j)mFXa_(OT$FNDn^>r*+J($rQqEEqg}|1^K@FaCHuB{ zGDu!+n$miG6@O}?P4_u8yqt9!cy6}Om8j5rq4MJMg^!#;TUA=0Akh9m6HSVdS|#Jq z+Vz?~A)_f_mj!C2d~YGa{qbU#_D_FZwe#qg6Bt^ioe>hyk6V2XtM1uTsaB+!%s(tG zPTE22sFGR&`&5BW>2x_x?IvNh)n>px_i(9+ zyUbL{L4PXf_H6@SWsUC+%2I8J7Lj%?_oJA{*y-(EBJJ0qMxW0&76rizU3cY}%+B`n zxO;jRU%^iwxKHxiz6Z(y;shs9w^_c-9lK)BZgMUNsDEzU0jKz_)R;THS}K zpqVzfHcuj`oi2G-skCotQP^@$obCdkEp`_EVd3_pW-O!X7_Ic2dR80Q3%il_!|Vh4 zNyof0^N;gIG>$qqI(=}MtZ=;=^wr3UpR@tMh+Z~3N6hqr`Lx{A@*?T zvwNhHS`!h2FJu!@UPPGXmYnRn!voN!q<(y`A4>A)kO6aVdMX1n0`Ybc%Ysl5W+y@Q z{@uHQn)}RY7KroIWq|t6=X{aW#flm_RX_ z?FH08U6|r{jgp~M7p^)~iJtY>Ga8*Gv(0G&=Zx8aAHV&xEQel*a@S6Agu@udx`VL+ z>kPdHe|QIUPnI&UkR!WI8;F5*Ft0wORkC=lh#*6JwFG+?%tvrVq7rM6+DzS%Kd1V` zyWG719`lPs=@0;KN{~8h;U2gD@wrUJ>EcS*y}0{y>_>1E|3$4O6432;-p1DU*tu^T z1|9p=I*cyOfQjyvbujzHz+*(ZCGO)^h9p{)=cU<)bWh*P9Ac=5eG(7T+8_PHrb?n&IRl-d|M=jke2FXI04 z#a=)5tw_l4^7A}h_qdLpWg#L-L4b~!@P%K7!(Z|vc6oc^AZv4D=yuN&gQwwukg>M| zA4%z8smHLYr8q5h(tj|8XLT?35OFnHLK6Em-WL9;d5I8I;kprmQ`o@A(KpTry~ zq@*PN8lFWbMmIgZ3`KfXwj|^TIxu89N)RYfA0N|E2&+;FVdtLvXu9;t$lcVw*~(+j zQ2F4>f6dI&^q-(T!^4R4Xyc1s__4i=W}5WoIsfW$XwCKcipS+8o(9WrkT=?8l`X_3 z5U_@UCimz&A66YTUCPy^*;4y!sw@bhUZ;`{eVM%jVqAmUzjaRvuraoom!G~-thW7j zDt)>#`kIZ&;@w)CmvS^8QU3dI%7=ZEKP#HZD&06iy`*FG1BoEVyf4l+tjps<| zpZO^S^E%V4*znk+p&9PdC3;X9HyOROe{Wp9^^kDud@5*U5uq(VInZ2~TbeA&W{ox3 zF>|ZhFMWEAF_Xj*v?Cx-Klbf|K7hkp%Ra&0jiHH0GE$PaWo7yJQz!I_={Hh$Mr~yp z+yTpb>~sWU01o&0J>HKF2GAOKfh4+Ohobe6i2|+}BFJ;9yT^W`!~DVJNq#HiZ$$D-u=# zsa<7H@KjwT<~sXzf>ZPqA)oTE&Y7}pKYsPwC(gm)WCGU6)F@;;4hr@bc-m$Ws#fC{ z{l$7@FW(M)=v&`GW4yq_)|gvl&juDS>I;3XTzlJ4hbBO|*e&qflm3XEv|L^Pb|J4Bf_D|sD%v7>}f|BFK=f}y4-3+u={DZN;fc#II0)6iv zcWxl^YnQ^h!K`fxilI-$FGes6%nl?^kb+)rNM)Ir6TCtwQbkYcZA#l~pk(M6D6LHB zvo)KG)2ZThYFf-^Q!+QU*MJc*O+H?uwF+Jrj=$Qid(W76zOXyq57~3B!zW4|9>DGk z{;Jgqf~WY<$+TQ#j7NG1@2KVNcSRR{(97`H!#>Kk8B#>H@J74=(fph_`MhI2V6<46 zsUs~W#Sr48Tmg%rJxosR@A9XIXReK&-|FB9EXt%CbR*FnSf%$ir|4p~DD!vvaF-Bz zhIJcRW)o&Q5il?HEE{vu{QNmHJoJYa0UaqMse#!qs9sUF(j8Gh0_%7fw3ad60#Bme z=j|>Wc|GzX-e$ol(Iyn+BE+6YIBthtKn{f6Pk>rV(iizp|9`PAUHJJwsIsQeP4~uP z05yV77~_KL9?ykRhtCJ6a+!^xWYTS1gr;Yr!!2o?po9trWX-g1ktT8NmK3|hL#?H^ zSHHFXqFg2m!6X7KCAw-ji;ql;P{q*=mA zYeWH|Yp@8UXQLO)yKKyx_D%XTKbQ8fee5@`>AJaJ=^Z}H1@*qW*>bB`1? z*>di|?bx;_wm{@nywLI?QG!uef5HA|)5dHuGV5`&So_HaX3M58=>ThR-}w48!z zYoVXZLYu$!0(FJ`)nnb>FHzGP_lDT5CN_yJluuO_)?KHaUHNRORzaNt4WFEmct{X1 z(9iR0Jv9-RZG$C`n(n==4O3?YkF1%tam~r3qmBl-UA@%A>1aCikBZue?FWZ^U-iEkRO% zW{-M)xH!H4KSfS}$QO8tcg*KZQfQ7-`1;#19$%rR;ZD6k)Ls1DXH)<;2rg zht&?4$-nprw+Lg`jTV0qF4?~#zyAer_}}0b$L}tYmG@bnS8Q$p7|^`;Cf{%Gb&Z;8(k zYp7|B>DlGbSPwY<^$#!SuQU*|SBD5H1<{_<;>uvfE>9ZjYchK%CGStlo8t|f;>Y#c z30-CiynJTJtMe<%mtFGycFNycsZB z^XC;{L1n|))Bee&#ooYa5qlASVNe0{YYOJ?r%rtz=IeAM&I1!JPLY#pn_^VQcTS&2 zCjJgI^=~h|+$_0$W>XXM)t)kj2o+YxWVSv0Ks}!t@mQr4m@njUY`K=ys7VaWA2<9! z(yuWT(3?@wU>KGmwWfhLd!>x@1+JJJ<;C5T3Sh zAsrc?97Ebx!28@m_8iTPkT)o*P2QyeR9{+aQ%x`FGTH3O_1ngzfe^whj)kCsQ>}@w z$p)8RzA2=qxF_M80;9Du)q6hOvp2$TKbTW_IecJdDKWT5W5PXm@PAT1l>N~SDH__= za*GyG#dE~=aIBXwHjgl^WW&y-%xUHR0p+WzSbd7OV|#C4pOD*&0t#{9cCsM3=~w3D4G8N=X@=@YK(Qjz&_~>8Dlm*`8($Okts?%#UXo&Pgyz0*d69GlPePbcR zJNW^bMq%D`ZN0rezM9^;esCe&*I*&SQQZnQDpk|YYxtUH<}yYd>wD5FpPkxVJu`s4dG8v@4F*Kyod%I<$StFoksl}Y#sxNBeVApVhdZ=uD2t+ z6g5*^E_~D1qI(wadGs482l5gD_J^W-xX_5P81NG}Bl%Jm#F98=E^S*ELvnauM|1ky zVb2sq?V~^Uz>76G{kDzSd}nm7!hqCt$3pqYzEC? zX!hsDiLx#dnrhwh$WaK^XQTLtzrY#SXd7B*F`(GJ#%{-q2s@S<0bxx~(+J$cP_A-N zLNZB*-z&KNvv_3llp*nxN`EaV)TtV()YPRa`P4nKxJ; zAn@=h_0{3tdX0FD!XArwCym`Y;RecG=b13d<0P`_ZkQn=yGj?nO3x$Nf|An+8-ERb zTf9E=N{*>kQr9kQ(!r!M^>2IQ*x8G};de5i6Q1a44f5C$2U9kiaUapm8jF+<%0^Q&LS->0x_QBYTW6)9YDF80LCsKvuya92xH??&Nz>@X~JJMfaQ?E_68)}@J$ zW;9DKfFgJ33I9xipSx6*mT5Gm?4DKR*vacSuN<*7;Q^n@)-U;>mXm>cp@nK9qiD}EC2Qz! z=PAcF)Vky^_HGM3w}kpJ=WdC18RoL49;GZ0!r9n;`=MoU5W?SOC4rsi)K)ENm_`#1 za_Q*RlJ_gpKJu5*fxPO|*h=7}P$}CZqmq7KEM^TgYV+krCc3z&roI+dEEl2*O*^qD zis>fu;(W`cSnfFNHe@X;FtJBX8$(^Cs5wp#SPBiIZ&L>(6!>1oDB0=Ud6OTuW~dZC z$XX|HA4Y?+`FHwnN+o|pJIt^y8(cl?7tU5$s^y%#2e>eJ%E*G7n3SYwWV_yw0;AEs zOcx#VSrdID*nOE~z$o+Kx&m>K+T9LDV<}+x#jBRTdFsykC~yR}pzQ-!UT|)eF*mZK ztHUMTh987sDKh~nNZfO$uW7R2-1&XK{Q{YWT>^FgxM65CSu8q4tspL2FAt0!cirTG zwUklNvDo^~vA4NG6xg(&-lpe+ER%%Q_C-dhcx>{nm@!Ntri4D;s=Bz)tr{6(k^u2H zNFgkbGn_4&O=A1L)JR7D@L9{Y{Qal%c&C8;Zkhuf^BTK{<7@F3ep1w; zJdrIs2?nKQ5~yt^KRR|NnmD$4`kp>co1`fh1iBr6W$u}w5rLHZhORLrQj>$)7Zegd zmykdGI+n!a5B-OyX0)o=+^_449c;fyKR$+l;PEbexL_59+9gw)oR>X&AENzZ8TIi3 zpF>!G!D<-EjC@)1*bCRlAhKkGMjokIXeED{IYpE4<2?vr3mx=8B>2a7o>>Wlh>stS zTm@a=-~C#C34vdO6)OnfAN)w0;kSIZ@pp!Qff8{9@6G%7JMfdoZ$7jA;e=m#A@X0` z$l;iY(pg>%T8>hDlSEmFx)yvG9$+E5X3`M1Z^$nMVkDVlzDhY*!!KZj9a)ieYbb%T z#B1FJsyxU&sFu-sS}kfr4#ncgjr2fp5hUUGJNvynD3(v>%&Z}bH@(H!WM*~ycG9Mh z_XkU=PhBV1V6Wr+-D8WN8R?4<_ag4yN|DXHc)P??YFGd{bAJFoZ7qGwx>XGYyMcsxGo(QWao&Rk5yPiwF1G0`_CG-Yb&Z z1GoBA?+23^#hlv~7_(2hoysQXbcpag)*xEy=RXygt#tCLeqPuFY8Gc}tbHf0wJMxS z?S?7i$>&a^Jeuj`oT9}-b!VV!k}tf)&_Vxz%WipE>c(>>f~%#G9{^_kQEDaHUFWP~ zDZJ^{d>V+YneZ9NMfYq!v7nP`ixiQ;`JqusL^8Nairap0Q&ho5pxC#bJoE~__&WF) z=-^wV%SNo6`wq>-IqkV3KD%_~vqMDd`M7f7J?c{RFQi-&5S^d5P^Ws9R!_+S{rpe5 zv!v>bOC&orJRWO8lV56fW~iv9+^UtinkA=EQ?9MXyY7Uw8qMNUnaS?IW?t&J@z=KP zltRh^#u#`ennSR}x9K=ZPv2i_&r(BrRi%;vk;-&3BQ_Yj$X6Rc%jk{${)5RmsPn9N z`XnTKlES?}rhx3PZhH8H?WJGRL7D7FYPX*`7Z%qFf2EXngj%)_G}a%C+^THs>}*jh zUW|A=*Pi>iNF*^P!f}&GQ){7=Or7p7j+@w4zN^ymZk}syd1`9;8y3_(fI9u55*>B_ za1n25D+z27&!nvKbF~mfYf?GK5{X3dgFRt}?`uc1^*zkT6+plawS5ht*_2Xn^GNjq zTHo%g*Z6{(xQfcyOF8YVrs7umJUuI!tWvX8#VVo8@@9YJY7aQ6OarYR(iJXDE60{3 zN1LtZCMPGcvgFFa9=Gy~H;ZIydgPtbqsWD%Ddu~X3*<}VT}*ys0HyY$7FiVN1WN?oqH4+xG8{yo9uB;lc=b4lhNQEVmWWBUv!d5%tVDeocw}{P zg`|NARSS;ta3r7eaP?u)#0Yo+w_X`EYY(uaK`x&uo-9ErhclYG@E10$yj6)1u8AYy#VXwS0kXb+W_9yESooQHX34g;K z$mcTpo~rB6&Y<$L=-YE|X{gc|S!mhK#l0Ju<&>cF>&ItpqCqB!e?5^+<@Z^59ER`$ zyEgf+$N9{YCi7_5E?JV+Wal6ix6r$NPbPVZi;T(&2pQBqol=S091^ zJFX?dGP`n(LYXh7VM-tRo)aj*f+#I3EPAbMccMN8a39x(VIK8YkY;$0FLpLu2Hx)) z;BmvYB9^TFZ}d{Y*8Uy^Ik#NFm{7uYO;wJpgom1$>t`P7^Ealjz=Bnwt3F)2wFzGd zIBn_}mp=UC{AyBB{%2RQirG1LFf23&IsYlX8T$}e6HN&N;I&+FP^UqQ9Gf02yAMB=jWNEx9^i-%!*-R|btE|0@(K!eryLD7f&Yz3d zmM5J*Ww&dq7Ngn1SbE%K-$}xks;df;<*mZ5yU0onq$A}e zBH$E{JPv&I3WxBNyBwV9QHprp3c=U-sO(n5a@VLC-|lZ~>eV~@6*g?x;%;nm?qVFW zwQ6NHKh;85LHEeziZ-7LgilH|NJJpj?Cz57wXD001eUTJ(J1j}&o8q&lH#x0H4C$q z!Nlp@k9xZN2e;seP<{_krm~!l&R&pFELlvgvopa9(oyKgd!z1oU9NZ)Q-7H*gT!lF zXrK|Q4xXVcXj4@he0T9Z2!>e~b7pyqR3!TMia;u6SFU@%n93*2q2YUH>Jp)5hdUD~ zZw5Ka(-yS|YeJLd^e{%Q26*Xg603MMF&Nuj9j&NFG1=%UpjBrU(0jmJZF@w2Bw2&&4Stl3F z2*|NGls~(KLX1&4k5*FNc)Cz`9;J2iXJDtAcpJq+zG_v$gnvz~jFrgn#O z3`?$IG~1@~?PFYq+Dn{eg-(VGX=OK?$^n=#K~7R1M{AOww^meu6KH{CT8U-*c%@98 zqABs&ao1_PcLpT~;a-wHy!Cx{vuaRlp5xxr1Q}yq!+90U-F@`OHTnKj2&!O9nNr*O zC)W`#mIU9yXf*f1y@gJB_Rdq{kHE>nT*)p0;dO*_k2~4V+|?Bz_vB=u;QTMcW!u={ zIddZBodE!lj$4V^`F&g78eMU;1V)5vj!Y@cXL@*|#YeBnw zG|Y6Y=d!}tNlViB`q6Oz+ER!!1|yoOgVYkbtKxBv-_}J<02t2YGSsardP%4n+*^?6 zE&6E76gRr2Yg*W-?8X^mAUQt#%r*|2e`;p2Tx?6z|665E%4-lGwV!Gqhf)Ygizgd`qA11|V#`nZLs(*d+fa*+C=1BsA0 zSl!0M?5 zJy%mgUewCk-}@ss2g8PVnopFB{AGF>Ok-CKRBm#D=T4&pA|SMK$ z#l^)8?JJ}C4JV6)gLwJIE=y%rGMSyHuC4bROH{l_(8F_TSE}5&0ZDcYqdq1zi@;#w3&}j*SH$ z!c$+%niMAgaIrXrp8(YGcpgCz@89A*db5H-04#MjT7>*p(SV$=b90@E&9Y&{Dxg&p zRm$XF97qjmy?wk;q{;%%RQxwUi2rA>YJ)_M+AIjtiZ{6XC=mqjT!|(Sh&OFp`tQH? i`u~h!{?8!d1t?+{4&qTZ1!4AMhhjp~f@R;n`~E)&{8-Ka literal 0 HcmV?d00001 diff --git a/azure-docs/builds/images/android-build-step5.png b/azure-docs/builds/images/android-build-step5.png new file mode 100644 index 0000000000000000000000000000000000000000..b6789e97f82b55c11f977a898a3bb8fad31459a2 GIT binary patch literal 25307 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 literal 0 HcmV?d00001 diff --git a/azure-docs/builds/images/android-build.png b/azure-docs/builds/images/android-build.png new file mode 100644 index 0000000000000000000000000000000000000000..d2123357130927c56375ea94c77bb53603ec2cb4 GIT binary patch literal 59401 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 literal 0 HcmV?d00001 diff --git a/azure-docs/builds/xamarin-android.md b/azure-docs/builds/xamarin-android.md new file mode 100644 index 000000000..5c4753531 --- /dev/null +++ b/azure-docs/builds/xamarin-android.md @@ -0,0 +1,95 @@ +# Xamarin Android Build + +Follow these steps to create a VSTS build for your eShopOnContainers app. + +**Note**: This document assumes basic knowledge about creating builds and configuring external VSTS connections + +## Creating the build + +Despite the _"Get Sources"_ task there are five tasks more in the build: + +1. Restore NuGet Packages +2. Build Xamarin Android Project +3. Download the certstore to sign the APK +4. Sign the APK +5. Publish the build artifact. + +![Android Build Steps](images/android-build.png) + +Let's discuss each of them. + +### Restore NuGet Packages + +Add a "NuGet restore" task and enter the following configuration: + +1. Enter `eShopOnContainers-Android.sln` in "Path to solution, packages.config, or project.json". This sln is created ex professo for the build and contains only the Xamarin Android project plus the Xamarin Forms one. + +![Android Build Step 1](images/android-build-step1.png) + +### Build the project + +Add a "Xamarin Android" task with following configuration: + +1. `**/*Droid*.csproj` in "Project" +2. `$(build.binariesdirectory)/$(BuildConfiguration)` in "Output Directory" +3. `$(BuildConfiguration)` in "Configuration" +4. Ensure that the "Create App Package" checkbox is enabled +5. In "JDK Options" be sure to select "JDK 8" in the "JDK Version" dropdown. + +![Android Build Step 2](images/android-build-step2.png) + +### Download the keystore to sign the build + +** Note** This require you have a valid keystore. Refer to [this Xamarin article](https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/publishing_an_application/part_2_-_signing_the_android_application_package/) for instructions on how create one, using Visual Studio and Xamarin. Or if you prefer, you can read [how use the Android SDK tools to create a keystore](https://developer.android.com/studio/publish/app-signing.html). + +This build assumes the keystore is stored somewhere in internet. Beware on where you store your keystores! Keem them safe and privately. Always consider other possible alternatives on where store the keycert: + +1. Store in the source control repository, **assuming it's private**. For public repositories this option is discarded +2. Store in the build agent. If you use a custom VSTS build agent, store the keycert files locally in the agent. This is simple and secure. +3. Store in internet. If this is the case, **protect the resource**. You can be forced to use this option if your repository is public *and* you use the VSTS hosted agent. + +Add a task "Download file" (**Note:** this task is installed [through a VSTS extension](https://marketplace.visualstudio.com/items?itemName=automagically.DownloadFile)) with following configuration: + +1. `$(keystore.url)$(keystore.name)` in "File URL" +2. `$(Build.SourcesDirectory)` in "Destination Folder" + +Fill the "Credentials" section accordly. + +![Android Build Step 3](images/android-build-step3.png) + +**Note:** You can, of course, use any other way to download the file (like a Powershell task). + +### Signing the APK + +Add a "Android Signing" task with following configuation: + +1. `$(build.binariesdirectory)/$(BuildConfiguration)/*.apk` in "APK Files" +2. Ensure the checkbox "Sign the APK" is checked +3. `$(Build.SourcesDirectory)\$(keystore.name)` in "Keystore file". This location has to be where the keystore is. If you downloaded it using a previous task (as our example), use the same value. If keystore is physically in the VSTS agent you can use the filepath. +4. `$(keystore.pwd)` in "Keystore Password" +5. `$(keystore.alias)` in "Keystore Alias" +6. `$(key.pwd)` in "Key password". +7. `-verbose` in "Jarsigner Arguments" +7. Ensure the checkbox "Zipalign" is checked. + +![Android Build Step 4](images/android-build-step4.png) + +### Publishing build artifact + +Add a "Publish Build Artifacts" task, with following configuration: + +1. `$(build.binariesdirectory)/$(BuildConfiguration)` in "Path to publish" +2. `drop` in "Artifact Name" +3. `Server` in "Artifact Type" + +![Android Build Step 5](images/android-build-step5.png) + +## Variables + +You need to setup the following variables: + +1. `keystore.pwd` -> Password of the keystore +2. `keystore.alias` -> Alias of the keystore +3. `keystore.url` -> Full URL of the keystore +4. `key.pwd` -> Password of the key + diff --git a/azure-docs/readme.md b/azure-docs/readme.md new file mode 100644 index 000000000..77486b9a1 --- /dev/null +++ b/azure-docs/readme.md @@ -0,0 +1,5 @@ +# Azure Related Documentation + +## Builds and releases + +1. [VSTS build for Xamarin App (Android)](builds/xamarin-android.md) From 40681c184a76b939441b0386b7fcc08791907c03 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Thu, 18 May 2017 18:52:46 +0200 Subject: [PATCH 16/60] iOS build doc --- azure-docs/builds/images/ios-build-step1.png | Bin 0 -> 50438 bytes azure-docs/builds/images/ios-build-step2.png | Bin 0 -> 49324 bytes azure-docs/builds/images/ios-build-step3.png | Bin 0 -> 36281 bytes azure-docs/builds/images/ios-build.png | Bin 0 -> 45847 bytes azure-docs/builds/xamarin-android.md | 2 +- azure-docs/builds/xamarin-iOS.md | 63 +++++++++++++++++++ azure-docs/readme.md | 1 + 7 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 azure-docs/builds/images/ios-build-step1.png create mode 100644 azure-docs/builds/images/ios-build-step2.png create mode 100644 azure-docs/builds/images/ios-build-step3.png create mode 100644 azure-docs/builds/images/ios-build.png create mode 100644 azure-docs/builds/xamarin-iOS.md diff --git a/azure-docs/builds/images/ios-build-step1.png b/azure-docs/builds/images/ios-build-step1.png new file mode 100644 index 0000000000000000000000000000000000000000..e19a7e803bb3969a3840e94746eab6a4fd7e98b4 GIT binary patch literal 50438 zcmd?Rbx_>R_a=%34FN(zkl+?vgKHqb1Pku&?k*D`KyY^p?(XjH5Zs-?1|Mu-N%FqG z?{ELy-COt8t*si0o-_UF={|k>^y%k3(?MTl#L-dlQDIJYE105fT*ydYwFR8o1@Z9C*+LDFCh~})K6klsDe@#FGqG=SR#W}5uVln zen{7-0R88WH*!8jLbbj)A4ooID9CizJWn1&<5|2!Gkbyhv`gcm&bsXbQmZ*QcEGM(b~X%Q-d)Md0?Q z$3|#~HSySIJH+G0(;k^hsAXh~CPVGqaQLPKyu8K$AcF%wh}Ai@s(WjHO_M?mF;& z=R%D@23kL8&u(M8?@+YxAnp`i#5z5vPj?&wa$`|YP)vj-T)v)hsn?6F)ztd^)&xv`0-_g49vGF5~MS2kG(*6XA8$aFU+X(eOd4 zIeLCEI!iH!)LexmUEO0jdbFZNND)dl7qAs8|5l6QJl52c&AYTYqD-%BG*iu~40rB8 zJi$W)eV$)>V^3VHr4%3n0ln?LwXNK;cX5YTHYo?_*=o@@H2m>KT>#(ymX0&J#b-rS zrDl^!I;x>7*D@koMpU?Yz4F32(K{b6*WHF_xt&@TI$rKiX2TG0TIYNY!P#rzRx4?& ze}~N})FncPyT)?#o!r+(HhX$y_~+gmt}}GIGsm{e#zjKY4UqD<_m|ux$;qQ z{&oV$oo2yTazfJR?>Z}^$>=ev7d>!IHFz?b8&PFQ3V`&gP~9*DqT5^_15*Tmh9k9z zu?@LuJDLG;OAKRJNN#Yalzc`~$Nuf$OTduv$#l1w`f1~KUghaYPzgqz-Y;Ji3J!Yb zlT}3=Yo6+Bs}#Xx05HVhh`2BME4|RjEpr?pQnuMF#eplZ083;u=d&WgQUqWtVe)cN zR6o_6;kUCgvAoC=d2jBe2lCm9DxY^*xA@VJh*Bz;H!j$&Yv>2wX~iiJ6YY>Q;wigR zN;sECAtw^S=1LdcS=4j_?H%3nTz)=mK*iyKlheX|EPk8w;LS1}Pj$LHZg8=NY;OiV z(ewoETqd#xXZ+&%vWh!uBa{0ju5AIe9RNMSF5OP>W=ixqlfOV1>G zEbo{$L@Vcr#~<$mrHXzqrY34E`(F3QAIl7Gh=>OjC`}cFlONrCP{He1-{S`i6EZQmzk3w`;^F^&iuMc7h&tz$*cvmwtNNA#&ONf=^!-?zB+vLQ)w2ByuPn6S+vu=z zud$qV;Al}fX`ZrD-?D0;Pnda!M}|B!qVoYBq5xfi3Vplc6lspu&akB^6ByJq9{o@mnsAflE zh7z@xHb)At=18=&-tAm#3JQ>CB;;NfV}hrN3N40_bhkz@?wpQ@FMPYYnt%)L{m^DD z#!m;$4b>y&C56Y)?OL5m3giTYBIcteHr(gP}hsb2Kz}}|b=KYp@#3k`rI(KmU z{P2XCj(qu^kyOK-Zw#aoHRsbKwusbtGoT0q3V(4x75Pgr_=>57syYYqXMfDknKV+87~~qs)GsG?XNox~C(e{zljLI0 zgmqA#BXL-h;}KW%4`DPOgQ9b>AAI5g-};^m3kq&LRBs%|d8lC`8*B`?TedeM9y|Ef zcwDa?(d^uafaAz*UwV&iZ!@WC=HffV98`Mj`%76n#;&{ok`oUa1J1PP%cLL~FP&5vO|h=nlh@!|Zh8Zg0<~#_fQw;{bav;2lDP!8gKNn1Yse z%2@3|#R3AZ?PT3}zkJUZ>EpHd`sR>~YL(U3h&VxWbWBBT8XU!-xm@`U{+?oD|5Q0% zfHl&t*tz;XZt}9pgk?c+|5JM>RHESlO&&+uaN_3STSZ5_nj-;6kP-OvRNFWV;!Av? zwWn8+Ri_U04@JW+orpHct7uAX@2mI zUJd$|-$VOL26*m!IYxyWG=I5v3$E{R{7g>&SFrAShq~i@a(5Ban6qR=q_-Kubb0fS z#0vZ#O{IvzIVJz`S25?eLE^;jf_?%_2xb$ERhJ!D>mlXyo!ae2jfEp~c*vwD)14ivmeJc*1WVRsZmXyC)75i3LL+Hi+8KcwR}F;B zS%wyj4fuLoK|}D|JQPjm#`)%)33D#0n9jYGfuBd5oaWON6B2zDEg`_fOU6);S_F&T zEu=`A-9cT&cx=(@jm*!R7S=SIvHJ(6#v^?yM|4|2pI*G^jInz&G9$`85yRr=^I}ug z)769{`13Y$;a56JAqn2;Yc5?~W?m~hEx&4ML15!*L(Yi`Dz749qrv8TG^LvtE)k3s z+2MwkQJaIOb35(FTOgL2X)J`P+@^y8ewWo^r23qCv zKHDZqbZ9yo51PS@IO^@AL9hcHM53BHZ_}1qj2sz)VB=0OwCOC9!(uS@V`buE!&Mb`0#41MttE{1B)*aS7frNqB1R~Nh-MrJEqMLo!!xqzd zZK1SA?7D>l%R~4iWlC&AytiER9O0_7)w`{ZeJ+-$K3oB^hmr>sy;4n$*cR3v-z%Y8 zA0S3)QZiJaBuoN@I~iuRC7i0$ZqwHu91OSkS^B18te|F}CQ{Rw-^V(ygcpqZQd4qy zg7?G+RyPu+R zf1z||FVxzOJ4isuTfeq2ta6=X^_3Qrt6n_YE%S1q#CT6| zHvgRwJ_Iow=7A)fL+I2m?Xx)bZo=AOf>-#9aF}0`Bxmj<2GoHzjrXqW$X|1bj%}o1 zSQqYuGpCXrX>ho9gIb%=F)5%i*cQ8^?D+g#2XEl|`LqJ52r=H1+N^YGyheectIJK3 zSA*fs*r{b;J)(FDR?rMHr^%*LjGUCZG*h0 zY~7O;Sm#HA8?HciY-jn_30Y{Z_&Ty1tl|$*#rAay@NR_z2Bx-v?V*)80hd>pwHdlzHRA#3`|Rud#5aO$#ER|+ck^59^uAJ{pUHa=A@*zqnn8xO>{@*S zi^UL}d^)~x{hmJP{`5_Njze;#P8{Zg&WA*4%w>?~?|J)F#5!X!JAk2MKG`-X&{Y1w zc^t#YEnswoATFWPo^cjeT>W^zrYbW0HOPl^CJP!3U9Qo^IJ9a0o>&zfU4eXe8Szt= zIVJ26Vh0X+qJn-k%BwFEYen-JuyuBUYNJrc6T$?@yd^V->m+~g%lfHmNR++d`(SoB zvmRI=zUBHwnu*cr)W9&vQ&~JazD?4}tXVx!be$}~`6ilLXV@5!f{duGoFr+kYBE6hTaY{c=Jlr0+K!qPjp_OKPCrYe)E(l>ezppr1$qsFN z?0RTZh`Li~s9tBskqhefEVjxE+S0fEzqRb*;#Jmulp(X7rek~^T0F$Q~BXPGh zoOr!th_kj5a%mTmXm0>g$dR2A(zg&=q*j}FU}t*FW?vtBfLumD|*j45WIV$Po#>yzKHP=SyGqpQszzldft z=(+gqw{L!J32~K{qcL-k`w$@K&*ECdpS$#8?>|`o8yF5kS8>k$2c1KevyfsWG zG9;Co#Gr9?ZWPQ~S9 zM{A`xfntoR+o9}-baQ$eW#*zQUxh=1Jym}z?cJh6sTIr|P)4t&mpgYx; zIK?CdJQ}`U~MfC$Q`re(K+-SraD_n&;;oFU^kv)?sPFjf}aLmQ0 z1qB?*-n~QPW z3q{0YXRpDwRHlWtk0F%AofCBD`Z+%un5h&6q#$Y;=Tk@vN5k9$=~@{VQ*^{^CjDpn zMM~ueylsY^NIKE!$-URC+Jb~EPuOGM4|LdcXQ}C3nNqyC7c6CNV+AZ6LPB?!sy7q@ z+RpKo1O*4$#v#=wvPiC#_DbrS?uc;-8x!|t4GnLRU#J$+_OqYZx!MjQ ze7$2>eRd_gU%6?)LU`0WoK$F`~(-ec+?#0 z_g2Y5Ln*_mUK(&gMlT#1K_%XL{EPG3#I-XV48A2ng?(yd-CcTa%H}H?eApm0s+vAu{TZ z9LEKzwPm1;d-YwD+X8;Rp5rX(ocM$dqoJvi0?Iftcp$$1q>8TGpZ0JyEzfT=opCU3 z!gd>x!BWHO_~bFuPn28-_w_+-3(K!3+xBp$J(J42Vj=6$>O5{h4- z9z-+=8{mv0oiOX1ev^76PqXN+cN4kRLc*qk2!4@=908aU>`rZTY>tafE@|3hW4fTH(s? zy(|ZHBii|j`_~Bt(i>p=7$tqu*DkwW9VSqNdqTx}XUwm+&RFCzjQZPy_?i{FTZ7?+ z-lQTn?U9)~ZqV<}+C7OV@9eT(Ye)PrG?X`-yhao>AjVXn12chsh)s?(zS~VLX(d%k zN}Nq#J$*A)uv)P?2zD#%+Gpb{i5<_H_lWB@UE>eET9ITbbpj)%R?r*JK#zM2=&&b$ zG8#nxyd-t%kFc8L4-m<%&E@kdfh(|`E=J2!5?|p9_K`-7$V2;DD+UNLBvNU1#+Aew zA77er?=GeXq5c?DlccxjlYNvlkzv%3RtcM&|OwdeY;BK^F)0Z`h6wQESkBHTO{P z)(Xg<%xJ@;zoTYGkMKz61ACQFc^Z)osx79|((gt#&a2W_dZl&mL~1m-P;_hPYY81@ zo$|TlTqP^i`gGP>9fC69xUadZ%@y8k!ep%9-YZo^ASu-;7`|;B_4thJlay?I*bP7Y zq_`m$(x_IF%KAM{fuzKne)3~*nhJS5>~sLO3st91Sl&yZC+aePI4Ngt^yQ%(g*LW` zDoQrBLtXjy*`R`2BVBw>KCwv$3UBP6(Dst>bV0kX<>BL8O%Wgjai*XWOhQw*5PEx$ z#p76@V2CaZvMk`r+^RI2fqhN%C2JIrcZ+j#J}lx1_HYZSeRQd&I$CUvNL|OGMd~VW zSWp_ln@aZ|XW;R$dc{sjw9lwo)-cM`#Q685}Nw7CXY>l;1w`g8y zz{f)cfTSe(adr!bD2Juky>K^ZiPvZT>(P6{g@6rNrrc3BY&;hmV6=tk>-)81GY2E> z6yKyJ2>^i73;1o|#%Cmz=UW3N`1%jXJ>{0I{0(R36^ltPP&Gl2zuGCSDD()=Z4=*j zO6@D?IU6Ak%VE7N5rVTef=HiV>3GZ@lq(iasnKcVlOzt-&COLBcjMQc3<4SW0vepHBpUMgE9Jti|E3dp62^unDoJcL zYwtb>yuur-v$DB3>u+w@2+(f17;CClZvQu1s91+uA0?%RiWJVUrEdEfN_W%#bWf+E zX@{rstKC;c$74&A^Pg*Af2)lZ za}f;2c3YG)@^93}+c7je1ElAx9=r_)MPiz^J{oO*tb_uvH|6%0Cw@0*L1BOS)}*Fw zx7}?s$ZW5P`?qhR08F_o){{AwsFX9Na6av5a*F&FzusF&{x`u&EAanCQdDuqVda~G zT%mlf!wSOho<6^f{!eqdN_L<6p%%FBh{yL;s=f&BLj5m;!5t+GCgpfZOc6i3(W@oU z(_49D#K+c*CxO>>=Y$W|tb`|;fZYYF=rP}s_T1a=!3vN_7_bX8H~*{Yb|*n z9(itzn%f(0W>ZeWW=?`4-8LDYrqQUDGe#`DnHBJUXF{i9fnycR;2zp{ZM!XDy2?DF)unxe5;>}s;bX{OiQSx1Ac{B{V27+ zR>zvLqO#B-l+k=4aa1)cYalUa9qM|*%(8>5K8=H}cNuGx$sR zT!KiqMvW|?ho5GT!g9gSaQC5+NqZ@36uvZoR`yht%eG~-8#-lczWTBxH}Kn%&{wbySiiRq`XQVzVWsbjboET{qB#Y#2XVk z(l#PXBxL-BYC}#BVQh2YYuXE=7ZHemS4p97vCwoeEL=~mB*jTsjq9jJ*v;e_c!sj|NRV)#-WmCT5@PC;O zjzk5zndAs%*5Y&cG$r$2Ka6^~prf&-L{HG7ep_F|VRI6BZ;&5OS?TshuQuCs(FP9N z-8k}L*&Q{)MXHtFCr4SY-+Np}mb~?L9CyB&My|H|hk0tpw?cSR^)DXbGgp^Vh&}z7 zYP_KXcUHK}PK?=QQhEo`zsLw&bH3M_3|U$IC`@tDoJ!p2F=pHl#CC-rY(omQ-iDo;D2sV>D^Rw3_=8Kk<&OUsfE~)`v^GtzH9%k+rAeu5T@{ zt)@-4W!h*lEZLn1KSSIy;&zF~2%Xr!ZSCOP{x6Q%R@|Hwuj4_2>V(g`;vGv{`8X^G{!9ZkR8mMr_5wt^~ugBl7o(wCRWXlNGm{&Is_xao~y zZ!f4>vUGSN=m}(-7keW{$`5rpgt2>m6URsCKaWz3c`Y^#VDzOcz!E3Y_mqOfqpRF5|WjYPlsJHx#a{YZJH(hah= zMb{9d1+70cX>0Z+>l5@vri^LODFiiDqF3g7W&U;EQ}wdFFA06-IkbY@Jy=3G5dcTa zc?0{s70ysxObO$GQ^Q%yaS9XQD>Y&(gVC%YdT+?~j&Z9%P*BM8T&0MNtvbplFd9gQ zAtcW*-QHA$yRdQy!~xoIJG;<9hR5TihuLp%R{6i1aeF0A?7bHY@3f+T9CrM?UAhtD z=>La8G?b|?Q;ul598e}VNCB42SpmK!XvH=CB7g3gwI^jXd+IO6hwRf-S<}c7<&%)s zGH*UP`QF5iIcwOq$gXr z%8#GyD*qj__#dj%i}?mSat8GpuDRo=KO0%JV|sDLbn!o|qO^?v8wp1Lf8tlE23u8c z1+{xns_iwA{xi33c?XTwLUL*)EzJZmtBeoo-v$Ckf85)_1+6qq)L3sod~?Q*hV~&~ z!^thJA9uzCbbq6mLWH;Ujw5q+Tx`v~ME4&p=G(=3=DKaLBb&vUMda?6A%Klfe}|KILLe{p>L9uA|VZ@Sis-qIFF*yzTTR35`QAt40=wp zi;R;}*wFs?P|rdqkgldda%h8wH&;GgX^__%Epuw~ z9IVQ5-OSHPRqZP?dKm=n?K;kl{gZnauV!TnvGICIt3d;W8ke?Nq zq*h4ZQcpm*xdn=44~rv4B;^eGb(;-xw&FWGOT%R~q68s@)Kb#L^)rB3H>l2!}x|$M;wbj4E?D(+yKE_)?yvcaGLtQ$T+8l0l5WWa$kdz z9)*m0&%wKlttjgmRp%(KBVT8V>YyOM&*2$~R;>dV26nuWNLAL6L~h18|(kzR+c4`+({ z;KcD@!LeMO9#pE8l#wp(Y{1y@@Ul^{8V^5~vb6qX^ryYw!QLpjsv4zFAy9MlKu{*v zi#drDfCd=;hYm?wf5GU;*C;i`fdJy+3gWmTM=2%{(HyS~ZDp()kfU?yW!-2K-8_#l zV>6|SSi=DfDbNAvat)JT>JAZVnND*BKgWHdABj6oGb?kRK88t=lxUF!eT=W%W%3U| z+|7%s;)`)^<&CSXcBaLX7H6q5QOGh6#G2uYY8I#HS~?7maHh|GG^jJdcF}me(wU8g z%?9U5@9IapK#UHo?A&(hzigg7${DsrM*~}hueLv zt3jjNGS>%~zE!xqD+|p%2?pU)jMpp1S}b;e%NJxI{^paTb2DEFm`ho z6bGYDEw#iX5(gRaongnOI3J2HC5mRartdC3E0RCNmc1Mpq99bg5L(4g=m$2jfUJ;- z7>i;4x(ZOkg+OcL0G}{cJ}?$ns!glnIG=?t!MhZ+tHap zo4{Gkx(^Aaw4o@9(Qb*!MywSDUtN6VSwD8q2=EPWnH`*03PtrvIX6Yk($HOQ)JspE za8|bds@VF+>9<$__Q;!g^XM=56S!Pgk$;$j6o56Yy>W^DRQC8V;?d0xn3I+>3OWj$ zQ1g=Ke1Yd{10bHr-7Y(-4OaCDQ(>=j(io}H4C?-T&9+<+Qq>@0S2tQ~QVQVU?w3B2 z*kqdr!ECv@_~PALdO8RABzsyHXg& z_Y`Pyz@wxla~$#f?$p?iue(n*us_&I=@`KyNSrQS zOYQx^dGXXNMo}rfwa6<}hhnwlE=X z+789?=C@@B-NTFaQL}Pz2YsiLq^bKt51$u7eOOvi#|U@5k&Ua;$XasJfdihlpB zwXA+QAXGKEgM9iEJHxHwfuOVx6<|aQQ~JC{?PZc+6bURDK^YuYeWx@Z< z$ZX;_S>Q14#qgo#WNx`#C?XHM!fs;CyndtnM2m39{m(wKmlVw1dgpmPX^zuMG}v*7 z{x=GZzFaZf$EEFjUnTH`)a{&ps;oJt=c^?N`QI5!3oJSrL5=r{9jZBga?&5jVott( zKb)mgOXntn|BpHI{+tTTAQV8Yfan09UX_6U+37%*4(@+I?q{&{e}SuAShUv!>uG@(+h8)u(L)-tIZ~A|f6`r0|k^s&! z8U|U?TnsQs*(^jiYmeO_s^PSY?9ce;-+fNdy#P!0 z-tzrccFu+NZ|J5vo1EMPl84o?@sfk@;zPH)*MI?&pj7`4hm|_GC`TeM;&LaCA0Q@Y zlhsl5@bx?hz1%#i3$6xO|^0wa`>yp8~GN}NC5gHOBbdAr%#gclUU3g#cO+xsj z_L}yZSd4gyPc90t(-iD=kuJnuZU)sLI-a8bqB%p zqd9|3S{N0asLS3pZ+h<2QNCOC^qCO*)(*9+zKsbH0Y1>(XMmGtA~?$C`}(UmMVUpu z6Z{MONk~hF11IMPdnWbT6DdggG#;PhhxXe}bD}nm_XC@ww-;Q?U_d&-OwsY?6bt6#Ov`tl%#;hXu{vT zY|eYYoLGXpDsN2{cN-%|i`--@s*k<+ROxj;V6NIzU|^JX7bP)OkiT135b#7|w6Znp z#jqH+cncNCkXfT?FHy<6m>2XoZ4Q)u`QEAS<{vv5bs=|LP7p?%)P(x^%7y1zAx8F| zV=@4C^aE3_Bu6S6ER=n~fGPp(B(PXBdNL}h*?lBqX>!~(duuOCiEN&Bw zj!Fv-9~g1Z-(R#NL|hrac%pAvHR#ME6n1WV!1XI1)i^vV%jbxSL+iwdznK5|s>X65 zx{h!6 zKw+`PcXFHnB9R~GM5$w!{TF#bkUMS~|Sxj*mx$S0~c$b@+0DOJN+_tbB^dS^a2{myIb z=ECu0NXL%}d@ol*y=`2*wbPF~TijjgbcZN-V_8|N8et<9b2awdm6?tCt9Kxc{27WiucP_fDZlqz2(kS&^ z@Uh>DY=U)q4pek>#h6?{oGxcQyY`QG>1}D8LHUyyL%7+FZt&_+oq@zA@UZGDEP~ou1PiQMHn$cER?A*WCm8%GK91?-E%WVAa%KSfN)L8QbuzTu^rbuX*F! zD&uRJ#(ui=PsDy9cOu%eWp9ns)?_)DcRW=%N3==8*V)8dz5<0 zQPS2}Qyq0M@Rpio>)v-Cw`UF3w273i1{=AJY9v-VGB62#j3x#?Aaqm3V`Z7p@0F!@ zt7_M>v1yMq&xUtW_vk@%2E#?8e)^GbP$Qeyd8_o0-DX3yQW&_H3%& zveb9u%Yb663sq>Jy0YK}iQt%fvR>4{CF8vG_2MHvMtek{ z4gV-Q`4Fb(o*EI{u+`Ty_NPwOn@^s()MFE4KUYEQ!SMPPB{;Hv zTVJ05j^9QcekY|^h$wXJ^N?-9v3D(4vOcJBc$$#p2l`dWM;MqdgiFj!gY7Q`m(Rz$mCLq>#f3>E<0|?Q4xs=C z>$$+SLFqh8l9KKbi_So_-k9Wfv55aXgp8NFgZU@9XBosh3uMh{He}hit^JGdS2n3m z2%NB6u66-pyhP;&edRV;w>xfg?!$f<4%4gDH{FX50uHEORN?f^juzqzoQdXK{|{~}91{b8C6X^Mzy)$MMQb`w7CJhBg+qKoX5WJ}+% zZO0p7YDmDEWCvftTu`s|2cGBXv^333dxDxL z%+Ro$q_{5j%!{sg?ED((8_*bAuz(jG^=d`-sn$n#PH*`!=F@l|OPVZ?dZp;v{Kd~u z6JfKlOE>D@f!^AuwW*29=g>)TFs3?VdvJlRfyR?tr2N<`fPCspo!8a{0#uc8cd__=-^j(XL-3SdyQxj_(US+{?YzLyPRgL@U`+#OwqWL5_cK!n_ zpi`9X)l{OgkhnSy(GDJ#G<$DXynX!InRwXnyVX@p*f#FGpD7O%I)WHYg7PtAd@-VTVJzLQ^Xv!&Tq z)rRBui8O&-GMliQ<*g`n*1D1sOhs=RpLDy4{TxqbqxNZgS3_=DRx}XZKwy87a4|<~ zEk{x9b)>K#Ch$vwnTEMDa@8zh>K!Rhi*66K_N#kDf;3G*NGxGyFOD9#z4AeuMmLVZ-T z)?s<#3Ch%-CUB*^w%8i;6}4acxx1UH9~*=B_V_vtAeZ^Ta+&4YHxlDqw~*2j9@$($ z(Wk`XkmGqT5XL6T!x_u73-=H84VU{mwhMB5VpiPW>!D&aAm?_%AsGZ;9m?BF9-mV+`S>o7~EQ&(O1210Y)rs+e_e({B!rRIP2PUG2WnM&R; z;i$Si@9U`!BIF%L4i;P(q{7G2%Kr}Ox)AFu^*+FHHU2Qo8LzBNkp`^yrRD|pO_MiG z)=ldYdEDM4dt`W3q3Dy*6bAc3*Dx|RjVbae>HN}SukjT9U=Tty^$CmOTvj^uol5Yh zGgV1`1qH6sYJ0b_o?Hyx8{*)BV($oxlqq45g5y<;iTPsMu;s$ksd@9Q;qhnqh!WF( zt)^LK!A4P9A;$@ll@IJH8_j4HS#n67Natfc$1XyI$q@WOzjj~}9%sVVuc`ySxW}(u zE)?ehcqNHm{28MJU+U`!arxZ1c~KF?Ihy%xf?YE+mA_V`LQMps{+feS%XNmz> zr_e;~3S3ihQ;SX0?kGK%3FfcYQF@OO6BHDhoK)-gwaW45eC>M>&x}^$s(4~xg6p~j zo*Y;E(>}e{aH!5MHc_0odJN3V^iS^NEF-EbNtA*##JP2lT)Yy?*wLbVB+tg#t+R3c zYvRUt%}*Dvzfdjnd>L!1$DLvifmXlE=lzCfMVV*bbS4nS!M=20*bcUmI!7BjHfn~-_KyLI>tRF zPZM4=;@4$eTzm6bXTaX%Ss`Sf*MvaC{H_457RlS>iaTTT5*Qdx81d;rNzttcU!eJX zd>cQR0~W5*!$n4^je9V9Z>|b5OCK%630DT-1H7?6l0e_1^@bpf?*U&c*4w;gQ$`x_ zwnKq$yV%(nA7keMTWWUP+sYSc;W%&_%PB{XqbZ2RMB(Wzgs4$`M8>qVj~{c07m1iGJIDiC0+58grwiWTD8NS>}KyfN`33F3TZ)U_@e z41@?^kyKt`1U-o`TDU06=45Z%sG(@_M5{}pPF2XkI3MRWoJ$mv-&%S!=FLvx!`Ct) zL<3IX=ztgIwde)~t}a`Rr7JHG$=^a;Ep*IolYM4@GMx73mI8YUHWKH8xt#}bE$UDU z0qqfuL)0KJUf#Kal~;Ae;uFD#tx^^30LDQIB$7O^4Ej~xDqGa4&x_EE7~owPpsd-4 zxDQMTsh>IYH|^w5juz{Wy?9Tqb<59vj+e_$soGdf?!Vpc?X9I^M+%1byoI15Q+>zd zvHlQ537-Ebbn-73;Ovomocj?KNSwOs;`1jmKhnx0CzPb2{ZN8CgPY6#gl9}IDB&t! z9(+nB+MvPX6WGrtpvSntkDa-#l%A9!d-~p`Asie(`fbgS<*v=ZFamFY0p+XuDJz>c zZIK&~HKmb;_h1fZx!(SHQL_^DHQw-q65dE+b6idTw1m_bzdZ-FiZV(O8_OY+&rGat zw@LSc8qcc&|8t1y1d#a_6r$>`Gn(>%ppId5lJlCC>N@8l9@g-QLdsKQU6sb)jc#z1 zj>_qhwTd^jrRfJ{65Z|5Z20%`Vr09BxacSSSB*Zf^dR{qW6aO=cx`bLviH&Pm^mem zbj98pQk$g=!{Qv?Kp2G+@3@kvq*!#~;SR&ueYYJyihe(7`2esm55BQ~N9&>0mW@ir3qXj(S%2&CQLN~DT zLQg*1V{@t2#3#kze07FI;~q^AQ818)n6R=9-g%N4*q~z*huT-4$TjDhz8zC=r1mxRj+r!#M%?`f$7f!HcgR}?j?Xk2D9nDSLl z-;wNv(AImL*M3HCY}^9yF0?6~HqECjlHI-3(Hm)r(zV;7H6As@U*Qmwr~Zm&w;y~y zip2X(o4V)xc$dE|?>N?6`)k{BHE{7Q17X*!vBP@|TuK49-U8XkwKy_s`f z$t)d7tO?44zGMA)XFY@dJkTm8Sq$RwE)5+MsRR`ITSL~EJ);RH`N*Cz_@vVw%sOWx zd5@<(64$8vcFeOC>&joW@}F9-}x>C8A7>?CSu?GTTZbozsC|5=j~CU$%v2 z2>7NmA%Z@d5N_ZLMrw~}5z3xC_)9f;z($c{N=anT?Hi38MZbxmIrEtnQLB2u#~FK| zOp=YD{_^c>Ncgh-o{)^Sq=R>c0|S1~^kL9d57Rv*TE0oey3m_sisBzw_Y`QM(?(Sg5(g(^h3qUWVT>!1F@^Dw%TgKDd46?O*2Vm8Y=ag(hCbeWsOoW;*f-0Xi&z}Mj+licH2+WBZMy{7M>6-GB zdi?wfZ-pwM-5_GjaG-ANaJ{W{g)vys) zDE!xDB>MlkRYdB)ZWa0OP5me9omWpv|}FI5AKiz*TLQ0 z9R{B}J7n+uo>S-6`RY`ix^=(5p}Kpz``7(EYprKBg05VwhQz3|6>Ru<$Y^nSc%x<% zS;0o;C4X{rz;rmJxFTsgn|Mk3t>f{cfCa!;S5N(kKmb;x-g33xUK?Jua%M{&9ZGLI zq&RTPHRwF=&`6$eH9auk${1eUs%H1vsxt_U=3=+~h`~m>tnlrQ8?QY@a;f_)d-A+z zbX{lOvlM{AW^R+Sks%>;v^KPVY|;~gU*hmINWI~`S*aeR^q$LAd~faXV}Hj%D|Nv` zzOz#z8$q9IhB6a~b^A&sWM^otd2jbsUo;oX-qLKsB2Tz$sx30dH!t3DNAIS38%419 z)ycvRVjr<`e+3?T?qs6*xTiCrD{!fms;6zm_u%)_m+ ziTwC?6?hez;#cUHoli1t6UrYk(ohG#K15?1J)-_;+-I_6gmt1=piHwPOyerM@zg() zA1p;H(40_lH&Y9t8U)yqg+x#LNpB=71$CUysyv8~`uti|vf*|(TkcqBC)V@>+@!_f zPEU9|oOT>|o1%Bzxii|&=hJ}|^?we-B@!JP`f(55Q_euzM^ojr#Fx4y3iI_r|N zHN~TWNQ_4mo5x#3F5@YhK*Q!!WnWb)tbMQ_*gkgI*Q?BnUp`;95nbO;KLHp(Fv^!Q zB<~IMw;`O;IhA)KPwqmy#1kbWvDV(_GeK7eS)(E4v!Kd{j3*$Y%D- zS^hK5aLhQ zTQ1o(3F0y{VY9Uc7R1-=%mi*#9GZYFkHFI!PS?Ppjv9F@>9dq1A2x4nfI!IE(^&(& zg(@h9#tW;qW*uDwsxp)wyhoe|oexUmz8;!C+~X48^}WT5K9n!9UjJgfkfB~5ZG4)r zl)wbR-4|;61WO42#hO@>Q8r=m%8F z^9qxZV$>gGHa;9a0QRSd?MRk_pa0;R7aS}*AG?{FP5up)#8FSSk6@A?c`p*&sFLpE zq31pLn-e_7%j7)=A8$l1a~1Y5+7^)_JXf~Qv}P+RiQ)?yu-O9p009`p zmwL5Bcm;QVjO7+5{LK*!|DA>ABWS#I{}mtR6#(g8>|6I@4jdY+L(LxlmT+F0q+C|` z$JeCjBzXruOiT<^u<%v{H1toWN|$IWI*I>TW-{VM@UlJgaz?(Rv-ZnXO?j0s(PVJs z9;O|H%`Z3lt0&>ce%KmR3W$A$wcJ@Nt2e8;hyX z^zpjt$Dugq<|7Ye&yuAaH847LXA|vHw?%Q#>r8_4Awa2G{W}GKjt^x3z{w0jz!;uU zxXZpQP=m`6LAjMbknF&hbc9539Nb*9ga|EyvXToNA=j5Rz8fNT<(7LK!UGBm-VcIV zY45U!$RxOZa)J&Og?iH-Y!xjD8;W^Kb$+ISsSZHP($Z*)UHJmN4JQf(XvD+LH#Fjc z0&*K2hy37?he4i&=$@kp&kdx`(cNKh?)!n8!h;WHLIq4@ywWWgRWq0|mT z*q}JR(F*Nmm3J0D1*!|NQs1RpK4`qO&G;b?M{2q!kiL7bAe~sicq?Z*bEGs#HWPod zOw>JgQuLD=Ep6O)&MK{)JG;=#^lZZa^*e=?0v$4=-Gp>YC9!LK6n}^x^ZKp16Xb{F zN>PzZ`_)G3ORh-0e)-9{V}LDTUcpfz_*YR)s}#r6+)L9vEQVs!DLli$!5Jx#Pj4!h zG-vE@!zYCvMIn}uA5x?T<4IeScrg)2%N@7d=IjuT9RX9k4!;$nKf3>>Yg7_u#}G(^ zzkz^YIvOBo1dN50xsZBWL36tiTlO84$l%_dR&bZl1j{ zghz^X5VO{@ujgPq|EZqUg>C)J@mr1SirxX&`|Ws;zUa+D|vcSU%_< zZ?^w!6!pK1Uz&2uQNGzsm+QIe{Vr04nqa+8=d>NZNdpN%?kQEV_@K2Hj>bQs`xCat zdb<3dc0QnHcC@?Ym5n33grl5&4DioI8JVpu1`|KT_^YV zdiWpA(Q)GV0La$MOu*}x!q6CgKBd6}b@ihjzQ(FBrZpgbpkLm;5-f~E_*u%z9mV~@ zg?yKh>3i=wW|+RG|H5)hzs?<{I1Dtlzfi1aaWlf}yWC`d_609)+!o%OOmpbh{Q7=V z8vC6EqZpf$R9d{Gn@moBQEz!|%Xb@^3cLdvCwSPQxSbR~d^q-T>Ecy(=K1wi>+B(^v#QzoG+&^i=ESsnN=#D_#19)4B5MSmo4 zu0Tm76H*7l-B1MT}_T{Z)Ja#|z;!M`uZvDs_F z;3&*GCcR&kk0@H4Y_&2L$zH~pxN4JaG!Y)xYHN}eMze}oB~vp@nfmqHF&rK&@onin z2~685=%n-}TZ_i8_jr?AVhu&n-ek+s)LJjU;umI&!aHB8V-w8-oi+)-nblcpdrhN< zGks~an%-JWJa>1G)NK=LJ{Uf*bC>yM`E`+=*XVxV+hEje@c~yADQnmdo#Er>(hoPh zTj~UhsWMj66)OZ!cRACKX$Se9_LHCJ4Ya3e=R`CfqluN4eXwDC5vE49KTd%kWjIxy zbD55}s2vFSG5Jc;dwH=jR1kFxs=!L>y$j(y9gOb^l9VsS<5stLNqy;0k7`>Lnlb4; z5dB_e)*BwHq8Yv*{^<)=bJhxu8WpmqG&j-U1p;H7j5Q<%2MRC39m;8n1YmKPbfi~j z2bCULB626!`}X2QWn>VWqI5+Kf!gU+t)-cQL3~ZXn7BC65Ie01KwFH|rtnF4q-8En zMY^#9VW>r6Z|mRYz9hQy&XmTLKv;QqU<1;44|;#DES0JOPiAYh z<%MSEmCY=6qSab&cbPD!Z`WqJ>ABZ19G0_LVR9tOiAF zz4M#4ZQ`(JQ8?9>ODS)b_X7f|JuHiDXO!#K8SBQ9+ja|YB#5X-d8k6iTyG8#kZ7>& z&=`^{%9QsBGF65)v#p1jUJsRAD3}eK9A=jQ!k!K~^W!QMlDuZ8-s?W2kn z0SG(RGJ$+{s1C!_Pn4M3ACy(F3umdsXFEtj`GtZ=^GXmUl&%E10#ft)BJ?tP>XMUK zHnJaojRzuDe{_G}t8yl&gB*Xc$R5$r!W642bF%_adyycc!RC337}Uc|XTSbt>&icw zF7o5g@_66l&9ds<=G>`VPxlemi+0TWQ|!{Esz_Vrq0K1T&vJX&?}y8+zD`&kldL86 z)K}Wxyi%4n9XzwOnXihZ$EDCU>ET?0*fGWK}hXUVpcWMFdYeKi73D&KDm z;9`VirQbu4&u&W4F9aELm$uvwy(ZnP&>X6#hI!+6Iq0Ax7b9!bW>* z^ShP7`)Y|kR9`~@lw-Soo%5=lx!NsErw>w=XYgiAnQ}hyUw)Kq_aseb83O+I*}tH_N+fj)#~9&4Jg1`(-LJC8ic4wes`B&>a+cDb}lJ+$M#kr zK3bo4`^FeGr8)uGw?DhRWhtM3benl&*tgNjz`Vho{1x>KkOBtwoedWC47JpE${-Y1 zl8%JtacRMu8`mM)X2k^g_s7|7-RuI#vuzm9n#(DC9p3z8miYAe8N3|fG_TlxAXE#2 zr*#onydKvU2eGv_!{(Iwuv2}yb}?(Ki9ptiI{nqlw=-ufKB-h$$lac{{Gxyr91fxz z966n(PAuOjYco)K`@iE|CnDK7|0UU;>r}76FT;4L8 z%pZB!?d!V+zQWRulcPU=C{q47PA)hvUitBuA(_0dML~g9FRQrQD^ujGvEegIZ zT|C7nOxAz>I2K}*aFJ!%sgYd{EvD0_SJHpf+gvFPo{e=M< zw>&(Vw=K{-5H+z~IY9ct%L93ylZk@QC#Db){IRoXE_Z!=S~q>(j{ovpnx=ng&Dq!b z=}O|cBYu4TWBE;$e{tKZRn1t0%z;|h-LtvYTVdAE3Cc4tk9H zh}n*a?fKv2b!ban1ZZUR9{(FH7SjZea9qhW(aV!k8I>evN z3R9!+lvqDgkCs^G8%G8dE)y5#9Z{{v}pO zq{9xjdQB~&J+!CPu`(5#?2Y*aAIg*%i(bC8aK?w@-C%26@$IgW6&$$Z*d!$PqJB}> zY0yLd0?LIYM!mO|%M{}Cdf7(CgwZP67o;QErv=6no6A?y>GH1MsH(qw#!H)_SEPF6 zJ*ob@uBg@i)5@gu_w`rVKZ}Uwe9&J~du;M7G;`jmvl_d8I>1k6S>ZDveSC|@XKnD~ z?wJn{A!l{O+C6>>zhGc#FPpk4t;ov2?y5PK6$$N)6uR{?v8YwD_K~L#^L)}F&CO91 z_0$6Fr|T@ZT|WBo`{nmL-g;=`1&SKgzqd$nHX(vF$dd3K^)(pHn$P>zdVge-qxH6l z=-SYSf-j8Tfc^U|Xje4%Z$7KK-GDrGgX#MjS4CD+heMxE=^`e`_V7)Jz-JrAZ=4)g z*ZOs3bF%l5T&h9x|4ES*jwT)U8s6syUOepDc4qt5s@?fj7I3_6Pnfw4>4Z=u*YYXM zqNLq3GJKVlR0i!wmgBXM-b5&;VU;dS$BLdA2xYgGG{%5oR>F7tM6m3M`-6Ul;y{ib zoU@9DUF&0gmpN?G-euKtL@x2`L$AAaEr)N+aLt*kL;|WZ^e|Wu9mf54-Nk0VGaVp` zgJ-0RO^kTOPs1#zVP*V4H_J+Q(mS*SC2iH-l4e4u=@S=GoJwkEn(W27*pt3kqaK+) z0Bgv?k7r3PJjs!w0YHrGA0_Szw8kDm^m*Q~3-IW8Wu{v|goMS`AeiNf1;NlN*Su68 zpSN($)MF=q$QH5Il-cb82euKf*Uof_F|3tznf0jTcXWnpL`l(449eP6%l zJf1~z*YdZGg*zJ0k(H&6s(h4>EoDyW-={;zo~MQ3?iSZat1lZp)6D}c8-=VIp2C%04hPdjvDW539qG+72iX+t<0NZ=n@nx%hg*Hiju{?FY#KSv3F zo7bHRNn%+KWnExxMMa96VUnwe_-YVj;=kV2!fTJ+h&vyOm_{?o>ic$}pfKL0{Cs)c zo7LTwzwsQOZTAR4JW7~_B2qsunYCJ0xmJ2wewV}YEn0FUowGh>ER{%HGn&b2IGj{j z-ITFUed?uW#G-VNq*Jq{Wy3ol@R zI%Yl0`>Sj`_4@^RJRnv~qP`Cvd+gQqj$E+K{$PwyCYZ`^6&kOkanJ~=b~1--v)v%U zr_sc_ZHwZWW^BLPe0~a41X0}#CBF4wO+E$Tt2~FtRz?Q<1gO=ANSEq<2z-Wyfp<0t zOw3sDDQ-E`oiYbv6+7N~Mp!@9D)K4<+}Aoov7aFzAk;uP0fq3{T5J5nx!RI(LZ&o0 zYl2Z*21}ytv3(y{zNehucXODF{qFwUt1i=p zPlWLBH9ry)K~Trt8Mh3M$`ETk4t_;tD)<($s`otQ6~jHDFOH#32BGZ_hxV?w=fix* z84cuA5*gg14X2^lwsRTWj`Oy33c{_tS6YX2{+-SL0wd+RzGH|EAS~N|^R&HOFm<7% z&ji;f1}6*PwnFp#uA?UVdz9Ah*CwXjD#z=N!&1PbmU>HNNbhL8B-~%%n*9%fi)#^B zN3^{v(WgD%CHg?J>+unTD9a~kaGnnvJp?(V!{so$kBa$V^`xt5yU?D+cEm;o;>uaV zwZ(cVNpV#{q_AywKI=)3)_>;#*U{`^`q+F4+*!Yy<)?}#eIPTwtM_8Dd$fWg^@)&{ zh7`v|F&hAXASqm7C6q)cy218KzLc+P^&Nea{1lsceoLkz0o!MGe?unXPMJ#=5i^e+ z0p5FTtaHuW>(lpGykB_VaJ-sXQGH`!zjbN<{#@3ib8$6yJEf_P2SdIg)r*Jr{5K5% zI;ip+^s;lgTWx_;?fGT%yjcUyDKCVF80{s#1|}2dm%K^6aIMEOr3*5i zNFYbFlghewlR!-R+Rx96RL1Y>%ww}(Uw_0Eoi6{wu?}+kfJ6h$#xUG7@ZetRIZH-3nZ?3tn zx^z&Nz`;q!`J0VKNQXhPJ>3XRIvFYiX1M_=`l(i+99et z0J!D2`LhLtp^THk{arFR^1Jgcm5B=qHaavbjp4Dm{>XRUVJOk6jG2c!L`O{875t|5 z86qc3ac2|O=kJ~bN6PM7X&CZn82Ixq?BjJSGuIXG~vn}|rmT}3mi_6l-6}D%2zLP8Io^SbK zm=-DLqZ* z-J=v|Z#(XyjXEBShhzbKk(Ok2<_l|=r8TC(mwdZpTA}8OVPPm)%)7 z?n8;!1j!}Y0goLrFsu2@yQOO!q{TsFI_t;n*td&+ak4!PjomQ0N>}`;A|S^K>;sO( zO=w@dw##}y5AN$Cyv<0#LD)!8!pp_i`zW+4e=a^gjiO@ zlDg~MupDTYcOC-m+I|s!?D*_QSL*NVi6s|m%XS3ZSXJzqO}p+dRc|)x5qIC&zC5hJ z_^YuiaHO&3z(eT`*w-8)j3_hXUc-nCsZBbUq&ndHpgz#|^6UQBcgpjg*WGA=jjjs3 zkuc?rk?GT@Tk}j?Ph7hyGnD!~)je2h3*L$L8Y#M+SbUD`va^)5!@yTW9DBJllk|pl z?GKMe*fTe2wcI}Kw7eg0;j18^Hn|&2tq{r+Eja_8Bh2#hLXSorq+YL6Dut1`%GMdW zTlNhU81i;F7t&}K`*da5x(c43)oUEMxT|F|hI z1wes(PKbiHM@7&>4`_nz*CU2M00~p0V^%ou8F3je2iM4s&6Z8}O&bl_gx@j>rj>SC zk77MLwD5ty!3tya1A`X^X-_F`^^Py8ucY7{@^pxmrcf;N6?3%u<6s497U8F?5?YG2 zP=|w^8(m!qEqL9WC;OV+F;(ah^r7UchPNr0!+xSJuvc0{bjUx?l*7&rOMvwA7Aw-Q zf)XoiMbe%6DF$*4&5KF6iS>-h;J0^ELuNyX9hxmCO2LbM?6xX8Bm7Jb`XC&4R}^lS z2tqmr05pZ1+2Q9E%oIk^zW+!z56?V*R(28A0DR2n63JZ;hJ@4-hd4T4jD$f(_t5AC9our>V| zU3rJ@&{-#45b{JwM{%#Jc7U>i_0@(q#1aB^sYoxAugKSb@uhM)aDz6JU*24>#A4K+ zFNlHJw;hB?o7t~osf5oj5O=3-(4tXOyVG(Xh#y^q?)1IG5R;F}d3|{%{7Hpgd|y57 z(Nr3>1Ido3)CqW~8(N5lr>|t<@?Z7~Qf5oM?yFcO74BdNJUM!yzHv-<_UL9stT|If z7JX^o8^#J|Kg<_6fLuVS$fb@n0`PfnL0trqm-Ap@I9%uAM7B3N$ncSY!{()n=@+~q zE6oN+$n!1cun~I)jAG{WKU|osm;efi|MQ_nPbboSrz0A{D*xHp4uUL!jMepm%B|%A z3rAy=0NleSMV+A*7>cE=L}`$n-Y$=cpm#g?rEE5#LPIO7CVe(@e+ktjk@jcwF%Bk#H^cwC%E58zVJ5g`2M4?vwL! z+XsORkk3|XL<()xvE9eX3zkSFmr?{Th;MjJ(X96vg-d>hYw^}GnwF5}D%O{~w1P1? zCGE|o&a_Ve5pt{JTXeBp*>`0%gl3j|Nf$NRD-&1+QscK~GW%uz; z;n5SnJMXIu`gw7ck!cN=>ga`@)I=SbFJ~@ey#X#aTstwA3CK>R*=g#F7OsmYEv(n{3*!Nt9$X{1=Fp- z|3@hbe`KyF^ocA3SztNJ-{&!f29$Q5a7AOq)#3^$k3TCRMxh0c?ia!l%+Q2>4CH+y z_jJqNrZxN}(0it*qd&=&D3q=f!@G@1DrKES|raBXG64hEY9QDzSZ#6E` z$NbBwoO_wezRG70163FJ_WMNpi!;ea%i!qg>0Nd>12VWuT>dP_q)xKsj;4%~2*qcF z&p3ECl;G{uh?$u<`e-msTkd-o4RivbRB@&7(6{pqkuBQ*i8a2wU3NzX(^|LYB+PmY z!$aKNL0?OvdHpn5Z5IlyRN0xk_nJ3?^JnDz9;7ApHpcU^;n&Cv1g!T1oUxI4eI6}e zf>vdF=i_>c>7K`VycWIT9(?`&oULK~lroM~Ut%eVKPgfQ=-@-vZC_N&_Oxk=mKx-y ze`{=Y+OJj47E!b^lV$Gl`81Nx&K7i|E)9CCeip$$lcMw9Gsn5?Gn^E#G^zczWS;QL zl)cxU-QQK{SZ!2;4USgf>pNd~W}D_fdc6Q)HZA8jWrVZTsimv4_d40OEf8ru>C=;B zp-t?=%9yWQw6HI&rjwEBaSw&OQZu%rSwD`l1s5b};O(UiC5XLWV713}ckTOC=J2#~ zs@Z?(%@Mzw^q{-pv)~{vLF!VL?g|q_~y7e;cC>R*C?77~U z_&`z(-l4gs58RGm(LNZl2o!QrH!5-(lkL1$eu?gYIsi_yA!7 z9e_Z5E|asTx6$>0QbPXw!gm<814c*PZ~JA=JPrFT*x0DvLM^$V;C0Mcxaqk4jnPA2 zKjGAew7-`@w_v=a#4@h?2Vxw(*BL<_DeUhe1N^GIR{` zgZ-kc{`?)XdTO1X_V>hJ{l031Wv}Fr*j*MrV9746KOj-pJyM+VxqXmB14F}%51v-_ ze|p036%dsqKfR*3FvaEp;bYqV#&wr&p}4LFzOqkFM3q?nfv+W8x;c-bRdL3Z~v)6e9;Ot zG?0L74yq}M@lGC%+gP{ir6t_|6XZF;8OQ_0gk_TqI)0_LQ=jjiiX*?Y8jaOCB9=0G zpAH;+FUP~3We|1LhXqx9-w`Ov$(VH?8YooSdFg%0Z4B(o#Q7{i5y!XK^{Wd`%Ieum z%7@U)prqlCTcG2QTYtb#){ozv|G0;#LjFgg4=F;XiL1{@)fA|5s49IHs6?ywLvtDQ*6*V`~3_qq+X2>Y23%+|7skMUz3Ud+;Af z|Gp1<``%Kw8Xs;8p*FI>$lW#_bsN&KmSOq7PdY(`J+jPM*b_&~4@50?dwmeAZs@FTq z?Uy1j5Hfywg{XDjuHy{4FonVc(43tAOkcbEU~o!YT|f#%+TnS$D5a7QXy|V5%@66x2jc8z*Q0N^mMJeSVEo9`bLGm8%D zRx3y+cZEB=@Oax8d20C`{u_q;ydHe1;hZDBZtkK6rmcVGbEC1qm?PUpe|V}Fyvubz z@#9pv2C(nMSx?s43L)mcG&y5AD?x~&tKIR$;A%a8OZ4b5D*F`WjG1=FMycUcKO8DH z>=iuLw4d=eU+<%<3qaV8eNG4HPI0KFpRKDHomak^-)0i>a~=s#lRX5OFEgxW9n)ltOFqRlz>0bXXq>s%6nwj09ZfF? zAG$2f-@XsFH`|Ip6K{*}UNjz;0;aU!f~qa%l!678qVXUIIVtW-H;{uxTbIPmOz?yK z&!Fe)Nll1GER*6PQexB=qOv((ItgE)g(2u*OZ*sv(WYR3GYP|spdBmAJi*k7*#JZ$ z2_+FOf|rDqpl1}3mdT5C{G}JlfkjnKfHr|Da^iO1Gu_SjsHDtMA$v8ldvHApE50xz81?k`>dnL4f>0sdukMG)aJ9V}G1I z)KW_%0RpoId4$IXVg$bi+=+uFun%5rPTpx>zIeKxfauG&Q}x$V^=*?=t~D67wLVUB zTx2;O@`8za?2X&yt3X{WatG-b^@|*Fz&XmP$F{8#S7{SP5=k?N_!?|T#f{%{|Mnym z{l)LCFFBGoS$30f)?i`QyfDmvF-m`Upp$XW?h~uiHTkjl=X9U&Qm8;r7Ryga68Y6@ z9ctO2Y&Nl}yM%kTTm~Pv7d@$}+|u~vFfp+Oocz+;%8L7$>hbfaEgu-=azVdNQ}JJ$ zoiQM9HR0(b99(%DMGtU1Z%!%)iK5{#L=|(kakBm?wAqy%9;y7A!rit6vox=U)~dtl zfAek8`})~8{Tmf04Nm7a?}yt+)l#!5W|X2(>D=YXhgW0AMp(RwY>?Am5?tb=H!jnO z{BN=tDnd>Cq)^^P)@!XmUv&SE25<1x#MW4P61GeC(o?Q`TEFAl{K>q60+c3tF zP1pe8lPkntOQz-UFR)fKHBB)ixU>B4crx=+jV5)>wXczB41|(afUseHF$={*j(c@m z=NFPxDf0{E(@)KgN!QS--(h_rKTLYNW)-e^uZsCqtgN9{g&B+ab0%&gJgk2KKnYWr zu@-=k%QwyfDOpmNdEJ8HBnNuiZBQL7`DlRb8VPbmjhm@Xl{d2*(0pf)ThurUO#9=B zRg_4)JEJK_8xJ^vsRktWl-{98Hwp$Olw)3QTfL!YWGry*hBE=%`51rl7aP~Cw}7ce zN2lYXiVSDw7T#gb$HAW%+0R;~#uU>P#c63vGt~)1ZO3wJt4hP27o>5RB7H5jwFp*r z=)s|N$r@O9FTh$nJt@+keXF&wbLMOM_My*2y-VKoMjl#+^n1yGQ|vA_5~|0e{3qvr zIOW>%s{@`1M-@V(j((p~2F9eCYi{l+<0RRA&$`|M%oxw>%gcrEzEJJXcZBl!$dB2^ z6X;i`)PnfsSTW(fmpVHE*9rL;o7t_1VM9ho70e%pTN_as`pou(qG+nkFHWb47bLrq z)cAS5F(HXw7_tSXnDdo4TYtWa_?v$7Y~L$_AJ!GE64`>jb2Ta3S>92{e&FWp`K$TX zKnj_pA)`4JnuBJRtj-xK=feG&OE-i&COMkBBk71CDSl2u<)@XjqLJkFOLakw^V;U0 zihQAT>c(SgYG1XF-9Uczrd&pWnw3ckX!yrja5(1cda{y9%=OZ4Cs@ILU*>5%7YG|i zlTXdX{VHCJbn!WA+@5QK{}aZW=jeToGT4*X|1)}Kq{6>5^cM{OIGr2*%W{?ela_x@ z{M*nS`2F82U;Q5<^4GuBUz-2q`u{x}<*g_~vDhhLch9;Md~`SarFHzrIsTT-`5*M- z|8N1?`5*{jX89Trtz&A@%fRQ<-W24=;xakTMEX*D9sIT%-K}7K^w(0D0`s8#jf;x zgpDE6u3S5rW zLla?yg#ii<6|DgN?GV2&$lN_DeIIU5eUVM24d|&+=mo6TQflSJjbj@=Ic_SRvk@q zpLzT7VT6Q}QW8(m*TL*|jjj%B(}p9&Oqb?-zE^hxS| zV18rLR4{xU3bm8=U&ntxv?XuT{`zyxHMO#G?o3-*jo+<@H)f)Qj3Uw@a;+#m!Q-G+&k_lje!#x#lHgafec=IOgD)ZsZQ*20R4W=T2+%%D6w@-dX1_6FF zowalFkPZL9bW^TrO#6{TJf_1^R`2H=H#&GNK_6ZAI)6*}#rjqx6~aeFR)(Z9vjIL1 zV)B3=n{a(MKON$t;8Sb)=zZJ}KF>20&0@HGA*VH^79x&UkPGRswdeCWRB7CR)m{8Z zm7r1!5aqy0R>f-J4dMPI==(+cdnhA^C8~{wy(>($xqbfeh4)USE&YK0l7fYhcm|o| zT(6@^A!%rnj8;bTD?je&Rm3yRma3HgcG6D@B5~zpLn&X8Yy5&;;4#qvsor5)l{O?@ z$7(9x&%PkVIM||N+e`D7AAab2k<{v9gEssne5|+4{GH`cYdl=yhR`hw0*k;ms=u`W zWckFI-HRKKOvtD$zLXvDgcnZa;-_I07`9{DKXRyyGF=#BJY` zGArJi--PF@9wYL0#W)STk^t~UB}LOS7Md{Xf-TOi?SfxyvzS@~ww8pxS)R>nlGCA)@xoV8sfXf>L4{Aug~Cz(?amq{k_3m2KO-F%w& z?A0${h&i!8m8G&842DpG;!YT<#B#O>ET2|#eFTEDRq8vw^iK32+4Ud9$?OP|#VU?q ztlmsj-fMXB-yVyQHVMQ6=gC(5G3_hw3q2j~;5Mk?FqIhXA>vESCgTQ1Qtj&}HJe%V z7ol%*zX5~&1BnWqv(JX@$xN+Pd1oOB9bE^&lX`~Ny0mWwK ziYXFnHykasemo2YJ`p{93fpZ&Miz-;^Rtz30T26mHG8&Qs&0zrgC{s^OvM<8`26jk z5DdIOHCL2XG~VWiq&^sZX|TsIAG_9v-xtjBSf{nJ^6!pz{gxIW;ZLQi(o`GQ@M!!h zi&!$|WfzF~<7F-aJk($D2b1Jcy8NSLsL95{&<|1=tNs_7k0zv(KPn4L^IiJn@RHqV z553*lS$Txz`>gOPd{S;gq9%Q0$kadRr}w+!XRr9!emTPcXRVmTteBpdSunq2$9uZ5 zcWtb|<0W@OH%$3zce~KXy-n*~&860EerO>P!&q700BgYq=wr-uhng$BFk#ahDzhB% z-baKA{WLJJ$v}sBJu2y9Mx(=H>pf=KVYA!JR3JEl>Lt?4={rt4BAgsINuEhzan(=4 zIqaCi;x37a}rz05vLU&k6O6mS4jrSfhHSOD4|A%xM`sCcQ%ljr1uAc-DI@ zGTcdv&Bn2#;~+{e@(MW@zR?Cpgt|M=uK;iFnrUNL&A6pQ+>{@;J8Bd86(8?dO|}$_ zJfKex3daOJ&dRkjtY2#$Ke(1IJ*RhH=-GJ;sUYHyatsVO&~2_$J6^wVT?;@NmX>^q zXyj||Vxyk>C#?MmnkZ|YG%7G=nhKc%(f zRGSXCEzMt&@eruG_9`#e%w3#EOG;`>8Jfyqa6`M$+3|j)3T+^Uc zMCXF)#|h=5(MK3~f+v}is^k5MXCG+{KjwLT0&a-UoT1}R#&}fyjGD)bZ$6w6qH3ac z)UoRjK6&=Fo~zQ*nubg@S%siDf2%@xkhIwUye=6#Oopy`xro*YAi6sysa46~e~=wv z&3kw&{N-%f-bi*6(dT1g8x{W=n+_DE}@ii%g+!o(*(R{`qDNmyZf zVs3kPrZ{>K$ZGKKrkmA0I7sAPQghXU8>HrS3OR+s{^=*H?QSBoZ2V zUF98fg~TigK!-nM{>V_cQ}Owb%i0?mQ2cog-#q@#Xng#AdOv}mcgH0h9DKW5m{*kU z>?W$)VklYfjtKGyy_BdZ@y~OjaxYD>(}3Bx^Oz#PxW=Ri_%kBHv60Ij=slbFE54PM z1__ff@v8{|^asMywAX?cC2rqG4*RMO281M4Qc?N?Cve#8`c~FRDb4_Ck`Hd2ld8wC zO^9iOQ+5Y|doL&OScU4prB<^tE=TgS#di8_wrJxSb()rCP(GZd+dLXm?y6*HKY0lZ zw}Rw%ka_}os33gzUNH&qT|_AKApWkoFLYzS)3ILOh{*TiB15$5?ZlL)S0O1AkQs}H zy+cDQ2)v8|LoO$6=D}BiG#j(CpHsLvHVlS$U@U3g+l6f9X*uC5Xy2kGHv*XGJV`%Q(8MLBjomlaPgfav!^1&#VeFdkXI9sqFVl|DJmVAMxtzFW2xjN0 zi~gP_gOd}!^60n+)Pwm0zaL6;Lxf6oMvBbm@^%Bm0sPR zlB@h>AAr4EWC`TB9Ux3o$f^61TNTXp`Ss$IMShRirj2K7@VBhccMEofK02&DAlP!l zfuutROUhPW$J;%@uSu_&_}hP0&Kb$L6W^KtN^Jdd`|ZoGIF%u>C~~tMlOs}Mpv$fe zUc2ML?cAL9jtfO5(LKIWb6L&L+i(~xtbh|Y`mV^PB1U>ayUgw&25-#T=8S%^A)jnv z9L%!o3MQ`)=*Cw9{r9zM@`@4&(g#z6zarIc1`S?Pdatn%g5aMdY`pk_?qAon@ZA5^f7%(W;O zNcD!?K9xJ_k|N}{>q(s6aZI!r^zYG;7H$Zyhc+v@Lro7$c-&R@Xw!Blp0*cQm+ zovx4Lcwf%;7+i&)%hcWVu4|z_kcE==bHt;@$Zos)_ruGf7JX$IOH2CsWt7oX`!Ol9 zk@)cT7n6Wnj5i5HV86(nwCS4;>q%X1^2`Cj2ljMM-`;vBfRvmx>417^ zzQZ{{341*HSg|esBCnz{%@$G_`2$?Q4&36wgP3t3w9iYJiYwZYy5nmJC~#ulRNQ-x z)Alo4+@eR{TES}g`jX9a*_(6(quKbaQ(?7nrP@E%#*DRw>UtmIievxmqF-JMtAILl zL=s&`yAr+jd60jkYr>c=F!(t=Y<*w0S8=S}8XA!N_~Ynk*XKNa+F`cs@czi1Xy&^i zdp-y9#=@n%)eG6#>2>Y$hk1)H4Jp>;yZw?7t6>$nTbA1%%OFl0J~xt4 z-P1DrvCDP?b3G9lB2FCT>)Z4L!I&Rhhz3K`%odABOeDr_ecxe1G%u^~Jg*LiJL&YK z!QHkKYD!nXe2%i)5=JgDPG_Q38h=1!pDfC2V=H{FX3eu3G2CLh# zFCoKn+?VeI_F&CGOESy5<9+9w%mA1uesPFA(JYnAeWFwB zH5D26bkIx_Wpjiv_L?evl^9j2k_ujcjQ}uBU3J&w8S#6^S?Oe#M4AAvzTGCu+t5X= z3V@7OkX~j=O+Co=_Lt?h9LO)dEhC4AXO`V8w%2`clrdiPI{{L@`?&MER@IdP2b`$m+kikKXAA194o zWG{B^Jv_q{@9G>qjv_#HmwBpI8B;3%+y0%tbZ$~g5>Dg~7I|JFri1^7OWzIe`lk~7 zzdNGxe*`GG>g(W-j5vb?+@Yt(k$b!M)ZHJ_uWfKnZ3oGm3x^;7Yr)gHT$pZOSp7l4 z{wI8kL=Ai@cr{t)iu*gv+&wQ}EZcp(OU&C49mZ&_d28?4ax3wriK-_rfEuIU>|n(4@*g9kKiNgFZ?wc{d+7$xKQkM zhA6zxckeofc`cVZIHI4TS~6#HNUe=KJj5W%_#$v!Y9FVZlIYq38)a+LIS0ahM3g2a z=Q5$Svq24V{1)8LxUYFC!i0f{`|TZ+G2hG0fe{N%TSH|MErSD05zg30(t zax^oi*W;u31@V*YnWe11(b}W?Q6^G=6Mvui_VyE)(Do6PBpsK0Giep*0`tvqn_<5f z;KTWqOi0`fR9AlJ!C{Y6eg5G^o@BvG_wt^yDLXp*BiJxe7%b%q^No@4FVD~qnDQMS z*vwkhrKS?@dLsm!#5fQj?wmJd-7!ubQfy6Aba5PsT{x3jKCksIZ$naB3(`_bLRg#} ze1#^UJVAaEXq~*JKbg$<^oU}xL11^mU0)n+SK7qW;#wy%s zUqotq#>xaSt&j_iwHf-azNx2;q59Xa=$einmkKX}Xv|F_vz)VX+Ab=%fu=r-J8}(w zT#7XR+Sy?xbOVp{(lH6HrvRkXQSce%^(}SiLAE^gLvHZ)m{faP+`S|jEkK|2w7OdQ z;8{W$6%^%TD^#E>F`Ph`5DvtnF2?U1>I$7eUv6UdlS-^>~pg(wmM`|8-1!bV_fW4FQeLHfN>6-@V=HIs=Vm ziC@*4AAB)yzZnpZr`Er=(3L=1ZtiHu6ysEyo#yl+sbb~-DetYq+U&Zn z(Y8>exI=M=;_mJ)EmA0Mg<{3sU5gbb#fukrD-zt@t!N;4(6IA9^m)JQ+It`T*MIuu zGov@&QOVUo#(Ni4V2!v0At^DyIRR`V5~yF4(@p@2h6DK}nJLYr#>C3bZ!({l9I8JGDeCsP3a{la z4lUkH;POJUhi77ny3Mv4!?Er^AUmiMOSc3+n>D5s2nBP7pf*u{?O9vVHBAocM|_C_ z^?Hh_W0qg7t)}eLdz)sWO>{Uyneg9ZzG?yNchESIc?1NqiS<9|m=5?+gd0j@zE;=j z>cRN)ew8OXA&GwKhzcnM@0ZUkr{(cV&n3VddwNs%NnfX&miGRM9X$2DKY;SxT199G zylTgl5`3!B+mP54pBM0~L}R@se}vn1O`x9og4E!q$V(;tbJcA^QOfA^=3C*1@xp?5 z!XA~!Eu^~7S@tacUY0}zkZ}_|ZTJ*67OS&p6kVtWm5{qM`vZWCBEd=f$%g0_MF)qE zKC^)9?UTOB!JOjOUA&2h6N!W*u2^TlY&1S*mM0%vXF?Ag#!A2bI5b(f#&hG^&~c}g zRIp*!;x0l#SsDFzP9uYdCGD^!*nIpEZ5|kcVK@{#a(^S{j-W@f5%zAVM5(zlT_f)5 z+D}(?Upm^{kdP*a57`&q<;%g}GsZ|(waQ+b=eE{)aCDRwLSOrl=uqZ*9m5`TCUo-t zNVgqL^Q0+$G8iWk1wP^^y?dXLTHy9D0ZaPzt51ZkWSA0r;xIuc3JG1kjSetWnZClu zlX-bV5%{c&0J0=bAANGztoc>i!qmLc>C5^8sk@3#tx?#H9m!_=oLp*C(}+*Z`gfSU zKx}jlCu+^^s$_lMdK0R)bdb?BY3+EuD1dJoU`;HuEm0lCzC5=9Xcuz=5NF4f8-nzI z!+WoEu!~8QB$wo-5YR+D`o1V>RV>h$LY!SR8&r}su&=2A&Dh%34lF-e zil6k=C*#kl9wW#yy{!0WgU}R_6XY%1JegI$*i$Koc0x4yT?8RKTvs>BA3AUGbAO7O z7t50RQyn_7g5NCbFK^^(Dh^Ya?9{7BP2IR?w&H7^UZd}O(@e!soeecjGj+&Z`MfbO zYijDw6^~b@gZi-N^35eez@g0dx85qUXFN>bzTCGn_Te0$D*@*$lnsD zPH#;k4$vpU4GrFspd%ow57WC=_;l=&AZbAFRcuQh0x;Y@VBdW~s}~t=+e01kMtB`HG8n3r1%c9tinGq zfrfNb9%xCr)-G5NW!r|yjgQwf?~Fc;6=j@WUrK24zz2OItVD1JmjH%V3U9546G%VT zQK|-P%_f zdK0pw7eL4w^%9+Tb@Z;Qd#;{%A3NX?aH_x`1;6j~QevZveiU41;0}`}#)LzUCb^KW zajOrGlRjNe((&4b7tGY*#19-{O6{%}cI7lK7_PRwH4Q_j48?S4UmPOVpK_bOt4>Em z=MnrGg*Gz$EQTm&c=B!A4^pu3BsA?u;K#_fMW6(ALDe$ATNA~Yv*}z=r`1YouKWm| z&a%&|zKBe^ji%ItA0H#drr-Xv{-y|Wa?Ma?ZJ%&vU3TRS=bLd(Q?o&~go?BH8lUD` z+_ty2Hu5zUncimqTpF629-I=qqB_%DfSwDM5+hpT$s~i~^3=e+)1PlVuzVe8j}rBw zzOxoJHBSN%(c=x<7=kHF=;K#xBq{eDIXDdTKlaK|N_O?F_6YqU4N%4EQgzej7S>go zoSWLM5_6J)$we*S#?YX{rK{SCwMsH%1bT84M??Gzh6637vh%R8n>?b-)70d@U?UiH zZHzZrH@g^gSix|VXp{~brODJ{gXwZPw*43)vn0>OPBil_!hw2gOiV>Lr#|Z$VgxlO zkQC{wZ28U}F1@6?BAj|xoM?YM^A#3rc<3Ge7ytH1b*A9jh#CFCcUdaX?b;I31Sw0W zfDF=1-FqKKfSbV8qsr?6!W5Y^sas)TD>iC53*LqHmI$>)(z@o zzF$;ZoDmBSgiZF&$`~?@@@vdK9H6Q3=gbP}dHLz;4(M?>{`K-WyGte;X5e`6#0kx0 ziX;{cOU9Aen0+mLUFIIqDi|7484fp+k!|bciIb9Q&Os+YGCnP@DK<6EW;tDjkMpqU zI5k$aS&{m^n$hJvfD5K%G_;RIrEU$LkQWr$vJ4wm7C7f0<>loWD^ZrMt5VpFtD;}3 zQJYK<)))d*peu`@|NO$>)w1a8V)m1{Uq1X)-mw-oW7*1td}#P0@^h24Y{954{>Z^^ z4UFpj(BG4loAxGQOnDq=JR1;p31K@}*wi}f_CQ)g#KpFJ%ay$o0zFA4-7;6Ex2)et z5KoyWh@dQzUo6hgU77Bv{{CZI8J>Y_1SJ>5UbiL2^$AKSGcJqiYW=oxl`BC+ZH(^8 zWhj1h=j4E(`Yye`{J{dtGaOw^YL12uLs9sGu|-b0ko|6tOP)zr1qz<80YR>)Ayluv z(yX$_Ma~yv+OiLvwW(swbhL&(9A~1FM^e0_i>uS%B3y&epuBdApvrTj*Ed`ln-m)V z4+EGSY2u09SR|}krc3~>EZ=x++GvaE4IM@>Y<2L2!3Oa(J(XandgvQZNYkAdc1>Mf zq+glBYouPAjfkyDPpYL(o>uni_p>|hnZ9{)#SaZcJvjkrKj}AFArOdk#?+6C$xhaa zOXGeWf(eZ|EH>>U&pb%`q+lAz6PsaTjYmRs!(dyX{=ufaC_&Uv`t7 z!N-G?+lzzFF(}W%&Xn)I@|LVF)jbc?yA;@#mpf2mZjr-(4;b588**BE80Ta3wE6?~q-CWr>}GepEF(eSV)%ryLU6#7y&dH*}2?U#)^H7UURq`86h@7T2| zqR%?H`I&9c^$!XF|NrTp_P^2`@qb0-|9=f9vz~Sa;!;QRReL=cVz&RSXkaV1Uv2r? zgT|LNE4nl)54<{>uQlljYheA?gdw^7%LESgHnB3_y3B+)a=#nOc5jH~%ufwFgQ#al zbQ$W_U`5;rd-gfAl-NP|e{OU+ydW0zYfBK|L*E^vwV25cKDoBb>iGs<8JubylW`C{ zG#2nQL*&{qdV^HI)o}jDo%5#O8aHb-Hf^a~?0EyZ2DLS?{t&o#!~ONJ=);SjqJDOk zkUwb-H5K6E47z$+=>)Xz{VIBN-K&9hWo@Je$i%anjuKNIM$mcg>-InKXU=R`b6=Z? zzPHbon*55GA4$#~1JYPDzY@%r?b$J2wGJ6_ojDdmsjtiYD@-jl{=dYx(KnvE=~gcW z_G@CZ5TheNDTBX`G!>4q1}mrDl$I(YUHN_^l3Hee@rBKe*jp@oRP}&EqVse3xr}UKiVLPk*?~>g9sOQ;-F~e&~f^ zl+$jlC(t9&JKM0en+bM-`s9a2*Q4gW*^4`Bqb6f!p2;hY7$p^GT+dp=W#LT6oXg6+ z819P$IAZuX8ykO8mlNsYFd&uC*OwB4q`qJA%HQ$@bgQLg`-zd74Yv5g&)64%R;L|g zkEOLZueI#*~GJxget0NmP;RsK&GtLfM;M1gf^}p59VNHs zjh8FNYB5w19PiJD2+`>96P@lS^Xq>Z-0TVB-mR+o{EOENudE-#xa&rX8}hw02hbJp za+=|$sRR7rjmW+cx!p6};{GO0>{!(vIu?+>ZhJrs>{y(1SZ+GQP#UNM?{w&j z%^!G_A){3>^bKC052t0$=8d8Z?_3ONe*J+|7#h!`H#uo;bq$o;R@H|UzRAKIKW?q8Qv^#J@J}z<`Z+67y3J;lrU~z(iy0U6Tvd7P zo+B3EfBePEb+3v`fIbH~eswUrwTN>YF}+u=aSIx(bu}IMM5wllQN-CHhbj7w{^=>! zLUHxAqX*~t+4cEh&|orX*z}>US$a-O{j@iKgq)n}oDYQv%e_?f=%+46sEkmh>C`F) zXAmZBXGYIdy1;}5DdbXw*RmFNN1e!+DWR}K=Fx&mLNd9^pm*W^kYB@fG!i5f8Hz*C zwJF!*QR^U#r_a=M9`5{6KrqD^Xy&Sc7|BuL8K{zy+V#!m^&DDgCOS{9V zd^}hScZ6iPTvC2CeI(eu4_hJPyxx;JLm(>eoO*iKjL2!3f-F0IeAiu$eXFT~X(7u< zc4xrzllvxe)KYb_5Jr`?fUByHFF9Mq)+pp!3XCJ>uu2@A<~XkTZVM)fLxizg#aF{+ zc0@P;E3vf7k5`{+-m(~cgzO0y32TjMiFJe{I)thpQ0+3O%cue=j!slXt|C_AjVz!A z*w<^EIYiD>C1uRU(3M-|8?d}K>)Y1h zPA%cpZ=WeS6^kjm1C}@BQfwl>v&3BJ?+0PM^?Yg26=|=QbvXQ2;NNA$UY#?VQYxK@ zaTW@t%<%sl@Jw#g86x^Bx5eniVlvzM{v%W#zdF39ab^c)fzS3$*&IGc2bd!7rRd0B zLeG&FtL-mC3!C+$ro%{~^i%s`DIjc-53GNXSPk`;S`EhoMIX*^Ka`gJc!>YzWu>HV zSI`huvq!$SR$LkZxS@1s|3SVNtVLe z6%)}kPTq9*w?Xc6zxjPq@Pho>aze}v5C_rAf*4Q~gf)`M88kx;ZgZepL{xKx6E`4= z_UlNF`chQmGgj^Jx}?DB6Y$|HPTED)>raqq<+q|XgD7~g+t+4hV!jS+-pHp^{+O;d zDOSMi$)-}y5=5WMel>8vpQ#Ayej_XLU9LM0E9T&(y4+%wWg^7HD}RG452i08%f!UdDOqo!bZyaIO?Zkar8iO%SB3JN`!oKheCNW|RU_aAA=CO)j%s(vsqb9ETm8xtbi>_ia#-NG~e z%luYwZj@YVC+d@IoWAtORA5IUQ={=srK@-(65v5xP>*P5!B-yHS1M;PQ`qG}kzkWSHzWj_LRoYeH z?LkJs38acrBp%f`SpfZcG4og*&{nG35B)LO_$oq?&ijKPF8;6PvvJTaNH(9Gy7@5U zC;-!2|NNqfE)y$uP0mNr-?T)~?WxB}G?<47B1sh!Z+Zv5puxr4$aS1Z89tkJM z|1o0uO*zAdD|GJZC4>BemPwn`VEt?*qS#-X6PNYR0bd4PnHHPK zXz7wi*p-l<@4$`UN1FM{t=ZTr%~Ky5>Pm<1xQSRm`!WTB0ZJROpvgX==je|+9$Np| zk=8O6YH&Igl|xh94A(N~{t~{5s+}NNEK^Nk+u?fbU5+0V0XIb1sR5I*YWnTQz?2X_L6y3WV0JOT>OEeh49c@Oh`$+qOGUe!1SOgjH+>a`s41jChKx57VKo z7Mu`1iF2qcmS?;QWfgD6jYJRO#XxWYbg%Avua}j^w-Es*WT>TRw6^f?L|*#+}L&`C7Q0CjJ3f^s5fPi9KiL(w6L#Xw2pCp;>KnXQah}RIP{C z3CaHV!4XO;@L=2_EC-gA(%bnfS%!(sYUtco{E@H8eezR{7f-5}?DW%;#K^l9`Sau? z2MT9t+e7vsl=HL;H5jv^S)k6ws?|;u+1LsEXbx6jzE!b#1aIellB~yEWJy1Q`mr)O zsL=Bs*5wE?!vrI%!K&?#mou6}d9!myh3GpC;N*!qVz80B`l;6uL zKZo~~*pV_9gWS6st7tkZzC5=ju*qeU+1G{iPcyTG+~`lKwe1?|m#}Of&=POfz|z@k zbA3PCOT4VH)O2JLJ?(6WEBKzp-WjjsFDgK;t2s?N;l|XXN(I_#eHzR>Q#05MDz@B8 z2o1hpCkr)@^E>o2o;PAq;u7_Dd5RCs2@g+=QHd?)bRy}ic~_`ceYkpJ(Q=Ar3MvY; z9VqHLGJ|(oI~8oj_bM2ij6DO-+m5eaT_z9de3j977#i{ZYAdXO@Vv8?@u|vvf%J}C z6uK@YjwtxL<*UNOADT~7p{hp6`pv~AVy*6Nqe8P!qfaxSJg!dy7wGKKmPVxF@RR=2u~k5rX{J@y*)S98_782GA{ZogXzOk~2F!~3y|8|OY7s&@<08LW*xPNvB?&H@%$vN4}5 z(roOeM#YIi5t-5zqlLVSL#ntvv>QqxV6Q-_nnDpND#wOyyPyiz9NF$cdyZCidFINu zbc~#eL1pHMcHA0R&Oo=8*k9-tG|Bfp55GoFhslC6MadJNHiQ7M?2%XjAcV(Mvz^Kg&mMe|zEe@7?K(r!OZDB1F|o2DKmfcER5 zWDhD?hgT4f8>f^S@U1otHVrn@=T*Uh{ROL}rQ|p}D^F8_<@l7vQiHc9_eOLcF778& zg+~yH1CIrLhU%`#Zl0=Yy{ATh)GoZ*{)O)97}zq#TD=YJ$_Tru64)cbAc| zBjF<*s&cpK^OLllzKiAv19(V9%!}5DH+&Kj0$J)R4gEGdjxXB`esE?^D&fXi>@P1V z162^>L*Yod9geA;%Qfr&wta#0k*}Y;8WI#!v{Vbs*h}TWFjft@>7n$3m=9FgQ*jo0 z9t4x=0TeGX4-w`buMi{yu|tiD78lOxjIt+Kf4Sg|=1O>l%Y813!%5@sKQloXmsvcW z2%Qw$&xNM@_P(93_Ed=wXH?t$bL>)|MaMp&;?!O6W}tIY6+HNEDd(6*CLv+IWq*AI z$(__(>gtbBis-({@q24kHifBk5IU9n%g$krOQ^Ld^-vqK-A`+?Z6&NAT%y(5SeAGz z#>?Ye>%qRg55}M0QyTz#XaEb+!-*R=x?(m(?cC%@hGp#iF|#`!7*9M#5N@3aXoxe3xS)x_VEawyi)rm-hB=VdN)y#~sM7qJ;TR zXZ4q3{4ON!T-|20a6rhKw}b5Cv!?c8?Gdu>uLJ~yE|&oZU|E(+W0v8QEJsg;tQPga z4u6vLHUsxdqyx!_U3$7OkL@6gN-7?U%Yk!*JahiE>|g1()A=OA@H|XkkPX}19GoOK zJi1r4dIJ)S2&#SxUac}h0Qxc@V(~L(E4EMXpr+*M&OEkvV4XQHjRTJ`7fQ(<>S_fh zj&vLP+%Q+KQLSmn&KSmeRtLz+;!k2L>|? zTA&Upl&a@+1y{(1ZoT@$z}KB@>YXQAwdr+FpwyI2qJH`H^eFkij7 zWnQTb9LUx|bsSvWvZerD_ros_Hz0izgPVLUa}K0Dw>2MfZke!A{V_6|-aHot)W_mq zJM1-h-UJ%^%TY*C!V!rOZo1!aiZRSn0XsJFw=h&A?gr5LhpsERvI3{>d?u3TJIp=Fj6!-rLi#ooad|;Q?5c?{fJ4@AM&gMW zkx@9A3VwydU6frCirb5?W^E{_f4#Hg$>Un^nf@Z0YH(j8%nz?{(_gh|Jss7z)wwrk zT}VJ$2xF0Gg!Po3l3!HP-WCs5T!_OqO0PzN+v+5mBxmM_B;4 zK__`LmGMaDEYP_59^Q0D_$`Gu|M2Pf^bXn2R-XXWuFf1wcqFzAlDw2Sv{Z61f(+F3 z!8@`2G2fy`J;1Y?pGPNsJb5yL1*1zp*u2Qk^egjlX4Q_R`oWdKL;v=FuSJEUOj|JS z!HoR1W^bzDqjyNIH0jw1>r}W?!JMqIMB;9}wVr#G)$x;czO`!zg^bhvv^kW!|DEix zZ8$pSy*5{Fr{c6egL-X)+j&M8Eyv;Rb<)WRMH8>g4l6_4HEh1gH~tuhr<}MxMqYPw zYmjZ>i8P^D8DF1fw8B@-AS|azm9}3_ZA<%R znGv1!p_M@WL9u0JABljebmjx{y~r8h#?=A7mzm_%DylR}$O-RXhB{?Y`_6@A%_wO0 z40&Cf*-V0E5V3WkhQ4PXLM6QiAK~ZE=Zz1UYHf{Y8IQrz#Vow8=56V8Mmz{~x&8XR zw*=*C%A2k)j1h4FGh%YC6&dQz)}9&8IEsdC)E;RdmNveTI})=?=+%_jjxu!#A~M}` zw(dv5{De(^+fH*)+~CPF+ORj39N-yE-HXlmwv4_vA0^SHlZ@t(uf4#?mfqK%Y%@bJ zqrnyX{#S6>NLwE2ziV}t+!uPg2Y_q4KWWXuXMP4}*8P_Ae1H4Z&^)ej{o6bFgT{YL zl;8bNiL%UpOO#6){#*Bq_un*BN#1|cL0bRQ-8bsLxvl>NAL`Jm;f0O71R-#6r{vq6 zHfiZ-&#G^gV_ZGadxpK-Opj;BtQ)0csSG6Ra(5M!aSxnwXDgvc&cV`TOY)El9(ac@ zfsK>59Oqz?ozX{}oY57EgerRL8$+%^@7>iFZ~to|D~Hwnzn~C1EjxF6f#LDVjprJR{eg0+N^M1oEtDj=mC!WB&4EF8Kd` zb*69bcC&_;o}R)}Wf+<-X~B18-Fh9;r=aNDmP?Ah0*y9tvvvgd%tliKTt{ za|`6WHj@6w<~=b32>heDHv7tGvF`*dhpY@S>=fzVIQ>X9{-MC>d38R%Ot)BfVdl77 zvYfKovh}KWcG_U*M+X-i9aEtBw>xWY@N4XEs=A31(RF&$->dp|zlMr3{(r&Z0mg3- zOq&t;-6bBlpJZ45W>vcL!fXfqYGU%!__=hDw5h<=DCs51keUFfU|^yjJ~CC#gc+#r z&UEFUPLZJ7oe{^KZ-%3H;y|D9v-pVA_(zH~l>}A7kGp1MCOxOhd?H}I% z2LqNneEOOTelsUr8+v(mKt}j}V}rQI(E+ZcaNe+!u*4xROe1V_hHM6}qtmnTO@X)f41c2mL9VpE`32 zduSd!W}S8Ni&=pl!%(LxRf4gM8RCIatO1Ap!S>*G5>VTY%&?t(@Xwaw`);goYtabv|&@C=E| zfFk#cw>8ZMAV04m-fgw`iD};7i*kA%xlG~*AHs4@$n^Yij2#@JFxmaBxr7WA6MZdE z4nplfKjU9ueiHurV;Z$%LFuyEj>H!5>-=+l)7Jz*)aZewAr`im&~aQV)L zP#%Z9g)1B4$z~kytUm)xM}$QBGD>oMftooZ!^;QOjMyH&1SK*A8QCB!J7@C1J6>Mb zP~iG;poHqf9aob>3zG?4$YCqdkL>=6QI`q1y`iJd_%i{^5--1ileMYzdMT>q)Bb338Ah*eE=U%L^$^|um0k;Y#g=s}JP&krs6ayE7OIE;SXf!j**TN@b3 zYHKkXovA<%nW{4<+dL%P6si%AJe@b~#dox`3R`G!O{?NnMfNB&qe%sR_HT~7b6R!@bM|A zBB~mEvKn7guHg7CQ(WG_6#I>c0aI^U(=ys4VBZX_mxwMY`-Jx>J!0Zi z9u(DM@tcWQLDP7r=fL+T`_qL)&CJB5(GbZe96gzf!xy05z)y(jr z{;dz#LET8-Xz!uP$1_|4>E5QEuv1^yNXG4Gwo$M3_usy~yCbD3aoZA_aXv5e_>zxf zG;WZn)}z$j@{hAHH>)HV-7}~rhnHi($VSaFw__A06h;ic3(yAVu_?J-@ixFwSqR@B ziyd!SQGSO6cE1nJY{Fo-63!XUe%Cd1B$7qdrxvi`bCTvFBI}`%zIzb_A2?DK?f5vl ztV4L;DbQqvmrz!|f*NY($O=55l4es8ki3b~H_*+!RS1lBpsaJEw(B|C|JWGh3!$^N zx5+yRWWRWaEBL!!M|dr&>rDGe?Rl=@)G;p%ks&-u;Ze%+3koJlNp|SEe_(%TDKbtg z#f%{l>UIT;71Q&3k!;OQGW}loGE01yL~Lk!*OyM5yIB}a;&b&{^9joBJ6>TTV<6Y3 z7SGzaHTf@bnC2>zl>1I&-9!-P4&m@Rxf?Yh%k`#!_*ME~x_5{}eUY^G_;b5oynu^T zke2um>R_p|IkJLhPU(2r<8!+{zB33{?;h^pw1G6pqrtzTw0`ylkePM=QLJa?+e81% z$Gt%Sh4wsN`Z`)* z>hMnhH=5a9F{Fns+mQiT9cKYdnEAVtum#kPYEb>Qs&}8*y2d$arr#dA^Jk*x=(FA@ zipNig!SutzS+K)p?a+9YsW{TToXJ^T<-6}wa%WxN8-_1H^;1xp_?989`tTC&1aZru(zo_!#%B+cX5z&&X{7Q;ugn{)# z-rhfBP0G`h6pouE-JVC{w>zTo4*>L0!sg^{p@$C6pm&u3oT=JL!KN;gL41|PP9%ah z3$kR1_;qY{LA-BD7`c7kuBB>a2e(V|_w3bVUbkQE&2dm^(z30|v-f~?a@tmZ@+AJ#|3>%{l%|5BiWgEZG%YVp%RUbiQM#1XY=RMIuM@xaSaqgU{$A(4L0 zn}6UmcSCe%>r+q1?+$#;=#Sydx`co8xY~k_Eoa-gmUT&eO$qD(b<@kuIo(3}w)@sC ze#OliONOgTpkko|-~8w+D@Arb`MRR?llk|(1fv_vk=^`uRVUP*9s!q76NFa81H@M- zR3BLEa__xedkKu}@GR1HD`T^KEr<;=8{P{OPh1X9n Y@xuO8nEVuNe*t?a$f!zJN*V|KKhWS~MF0Q* literal 0 HcmV?d00001 diff --git a/azure-docs/builds/images/ios-build-step2.png b/azure-docs/builds/images/ios-build-step2.png new file mode 100644 index 0000000000000000000000000000000000000000..04b747911a5e93b8b96714ffe8e30b91d1b8373e GIT binary patch literal 49324 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 literal 0 HcmV?d00001 diff --git a/azure-docs/builds/images/ios-build.png b/azure-docs/builds/images/ios-build.png new file mode 100644 index 0000000000000000000000000000000000000000..35f25c29fb3435921a74a4f785ac77a153fadd3d GIT binary patch literal 45847 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 ZB~GynzpzicDZ+uWaD)BHESFGaWJ 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 Q4+s3nNGOU|h<*wDZ`8Tb?f?J) literal 0 HcmV?d00001 diff --git a/azure-docs/builds/xamarin-android.md b/azure-docs/builds/xamarin-android.md index 5c4753531..1459f151e 100644 --- a/azure-docs/builds/xamarin-android.md +++ b/azure-docs/builds/xamarin-android.md @@ -1,6 +1,6 @@ # Xamarin Android Build -Follow these steps to create a VSTS build for your eShopOnContainers app. +Follow these steps to create a VSTS build for your eShopOnContainers app (android). **Note**: This document assumes basic knowledge about creating builds and configuring external VSTS connections diff --git a/azure-docs/builds/xamarin-iOS.md b/azure-docs/builds/xamarin-iOS.md new file mode 100644 index 000000000..d42780e82 --- /dev/null +++ b/azure-docs/builds/xamarin-iOS.md @@ -0,0 +1,63 @@ +# Xamarin iOS Build + +Follow these steps to create a VSTS build for your eShopOnContainers app (iOS) + +**Note**: This document assumes basic knowledge about creating builds and configuring external VSTS connections + +## Creating the build + +Despite the _"Get Sources"_ task there are three tasks more in the build: + +1. Build Xamarin iOS Project +2. Copy generated packages +3. Publish the build artifact. + +![iOS Build Steps](images/android-ios.png) + +Let's discuss each of them. + +### Build the project + +Add a "Xamarin iOS" task with following configuration: + +1. `eShopOnContainers-iOS.sln` in "Solution". This solution has been created ex professo for the build. +2. Ensure that the "Create App Package" checkbox is enabled + +**About signing & Provisioning section** + +In order to deploy your app to a physical device you must sign it using a certificate with a provisioning profile. Refer to [this blog +post of the Xamarin team](https://blog.xamarin.com/continuous-integration-for-ios-apps-with-visual-studio-team-services/) for more info. + +Basically you have three options for setting the certificate (p12 file) and the provisioning profile: + +1. Use MacInCloud VSTS agent and setup the p12 file and provisioning profile in the setup [https://blogs.msdn.microsoft.com/visualstudioalm/2015/11/18/macincloud-visual-studio-team-services-build-and-improvements-to-ios-build-support/](https://blogs.msdn.microsoft.com/visualstudioalm/2015/11/18/macincloud-visual-studio-team-services-build-and-improvements-to-ios-build-support/) +2. Use a custom mac machine with the certificate and provisioning profile installed. In this case you don't have to do anything else. +3. Have the p12 file and the provisioning profile reachable on somewhere + +If you choose option 3, you need to download the certificate and the provisioning profile into the build agent (using a previous build task). +Once downloaded two files, you have to specify the location of both in the "Signing & Provisioning Section". + +![iOS Build Step 1](images/ios-build-step1.png) + +### Copy generated files to output folder + +Add a "Copy files" task with following configuration: + +1. `src/Mobile/eShopOnContainers/eShopOnContainers.iOS/bin/iPhone/$(BuildConfiguration)` in "Source Folder" +2. `**/*.ipa` in "Contents" +3. `$(Build.ArtifactStagingDirectory)` in "Target Folder" +4. Ensure that "Clean Target folder" (under "Advanced" section) is checked + +This way we copy the generated IPA in the _Build.ArtifactStagingDirectory_ folder (and remove any previous IPA generated by a previous build). + +![iOS Build Step 2](images/ios-build-step2.png) + +### Publishing build artifact + +Add a "Publish Build Artifacts" task, with following configuration: + +1. `$(Build.ArtifactStagingDirectory)` in "Path to publish" +2. `drop` in "Artifact Name" +3. `Server` in "Artifact Type" + +![Android Build Step 3](images/ios-build-step3.png) diff --git a/azure-docs/readme.md b/azure-docs/readme.md index 77486b9a1..f7a60b5b3 100644 --- a/azure-docs/readme.md +++ b/azure-docs/readme.md @@ -3,3 +3,4 @@ ## Builds and releases 1. [VSTS build for Xamarin App (Android)](builds/xamarin-android.md) +2. [VSTS build for Xamarin App (iOS)](builds/xamarin-iOS.md) From 76b6ec2582f4f5e9fb28de6d982eabefe6e4cea8 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Thu, 18 May 2017 18:54:40 +0200 Subject: [PATCH 17/60] Error in image link in ios build doc --- azure-docs/builds/xamarin-iOS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-docs/builds/xamarin-iOS.md b/azure-docs/builds/xamarin-iOS.md index d42780e82..a47a880f3 100644 --- a/azure-docs/builds/xamarin-iOS.md +++ b/azure-docs/builds/xamarin-iOS.md @@ -12,7 +12,7 @@ Despite the _"Get Sources"_ task there are three tasks more in the build: 2. Copy generated packages 3. Publish the build artifact. -![iOS Build Steps](images/android-ios.png) +![iOS Build Steps](images/ios-build.png) Let's discuss each of them. From 5d2d2dc98610d832925907ab7b9c56d36e33964b Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Fri, 19 May 2017 11:27:32 +0200 Subject: [PATCH 18/60] VMs deploy doc added VMs deploy template updated SQL deploy template --- deploy/arm/eShopOnAzure.Deploy.sln | 22 ++ .../Deploy-AzureResourceGroup.ps1 | 120 +++++++++++ .../eShopOnAzure.Deploy/Deployment.targets | 123 +++++++++++ .../eShopOnAzure.Deploy.deployproj | 38 ++++ deploy/arm/eShopOnAzure.Deploy/sqldeploy.json | 103 +++++++++ .../sqldeploy.parameters.json | 21 ++ deploy/az/linux-vm/create-resources.cmd | 5 - deploy/az/vms/linux-vm/azuredeploy.json | 199 ++++++++++++++++++ deploy/az/vms/linux-vm/create-resources.cmd | 21 ++ deploy/az/{ => vms}/linux-vm/mvparams.json | 3 +- deploy/az/vms/readme.md | 54 +++++ deploy/az/{ => vms}/win-vm/azuredeploy.json | 13 +- deploy/az/vms/win-vm/create-resources.cmd | 15 ++ deploy/az/{ => vms}/win-vm/mvparams.json | 0 deploy/az/win-vm/create-resources.cmd | 3 - deploy/readme.md | 12 +- 16 files changed, 734 insertions(+), 18 deletions(-) create mode 100644 deploy/arm/eShopOnAzure.Deploy.sln create mode 100644 deploy/arm/eShopOnAzure.Deploy/Deploy-AzureResourceGroup.ps1 create mode 100644 deploy/arm/eShopOnAzure.Deploy/Deployment.targets create mode 100644 deploy/arm/eShopOnAzure.Deploy/eShopOnAzure.Deploy.deployproj create mode 100644 deploy/arm/eShopOnAzure.Deploy/sqldeploy.json create mode 100644 deploy/arm/eShopOnAzure.Deploy/sqldeploy.parameters.json delete mode 100644 deploy/az/linux-vm/create-resources.cmd create mode 100644 deploy/az/vms/linux-vm/azuredeploy.json create mode 100644 deploy/az/vms/linux-vm/create-resources.cmd rename deploy/az/{ => vms}/linux-vm/mvparams.json (63%) create mode 100644 deploy/az/vms/readme.md rename deploy/az/{ => vms}/win-vm/azuredeploy.json (93%) create mode 100644 deploy/az/vms/win-vm/create-resources.cmd rename deploy/az/{ => vms}/win-vm/mvparams.json (100%) delete mode 100644 deploy/az/win-vm/create-resources.cmd diff --git a/deploy/arm/eShopOnAzure.Deploy.sln b/deploy/arm/eShopOnAzure.Deploy.sln new file mode 100644 index 000000000..6fb65821a --- /dev/null +++ b/deploy/arm/eShopOnAzure.Deploy.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.6 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{151D2E53-A2C4-4D7D-83FE-D05416EBD58E}") = "eShopOnAzure.Deploy", "eShopOnAzure.Deploy\eShopOnAzure.Deploy.deployproj", "{642B3F2E-3011-4B1A-8D22-D35C11C44F05}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {642B3F2E-3011-4B1A-8D22-D35C11C44F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {642B3F2E-3011-4B1A-8D22-D35C11C44F05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {642B3F2E-3011-4B1A-8D22-D35C11C44F05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {642B3F2E-3011-4B1A-8D22-D35C11C44F05}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/deploy/arm/eShopOnAzure.Deploy/Deploy-AzureResourceGroup.ps1 b/deploy/arm/eShopOnAzure.Deploy/Deploy-AzureResourceGroup.ps1 new file mode 100644 index 000000000..cf119eea6 --- /dev/null +++ b/deploy/arm/eShopOnAzure.Deploy/Deploy-AzureResourceGroup.ps1 @@ -0,0 +1,120 @@ +#Requires -Version 3.0 +#Requires -Module AzureRM.Resources +#Requires -Module Azure.Storage + +Param( + [string] [Parameter(Mandatory=$true)] $ResourceGroupLocation, + [string] $ResourceGroupName = 'eShopOnAzure.Deploy', + [switch] $UploadArtifacts, + [string] $StorageAccountName, + [string] $StorageContainerName = $ResourceGroupName.ToLowerInvariant() + '-stageartifacts', + [string] $TemplateFile = 'azuredeploy.json', + [string] $TemplateParametersFile = 'azuredeploy.parameters.json', + [string] $ArtifactStagingDirectory = '.', + [string] $DSCSourceFolder = 'DSC', + [switch] $ValidateOnly +) + +try { + [Microsoft.Azure.Common.Authentication.AzureSession]::ClientFactory.AddUserAgent("VSAzureTools-$UI$($host.name)".replace(' ','_'), '3.0.0') +} catch { } + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 3 + +function Format-ValidationOutput { + param ($ValidationOutput, [int] $Depth = 0) + Set-StrictMode -Off + return @($ValidationOutput | Where-Object { $_ -ne $null } | ForEach-Object { @(' ' * $Depth + ': ' + $_.Message) + @(Format-ValidationOutput @($_.Details) ($Depth + 1)) }) +} + +$OptionalParameters = New-Object -TypeName Hashtable +$TemplateFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $TemplateFile)) +$TemplateParametersFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $TemplateParametersFile)) + +if ($UploadArtifacts) { + # Convert relative paths to absolute paths if needed + $ArtifactStagingDirectory = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $ArtifactStagingDirectory)) + $DSCSourceFolder = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $DSCSourceFolder)) + + # Parse the parameter file and update the values of artifacts location and artifacts location SAS token if they are present + $JsonParameters = Get-Content $TemplateParametersFile -Raw | ConvertFrom-Json + if (($JsonParameters | Get-Member -Type NoteProperty 'parameters') -ne $null) { + $JsonParameters = $JsonParameters.parameters + } + $ArtifactsLocationName = '_artifactsLocation' + $ArtifactsLocationSasTokenName = '_artifactsLocationSasToken' + $OptionalParameters[$ArtifactsLocationName] = $JsonParameters | Select -Expand $ArtifactsLocationName -ErrorAction Ignore | Select -Expand 'value' -ErrorAction Ignore + $OptionalParameters[$ArtifactsLocationSasTokenName] = $JsonParameters | Select -Expand $ArtifactsLocationSasTokenName -ErrorAction Ignore | Select -Expand 'value' -ErrorAction Ignore + + # Create DSC configuration archive + if (Test-Path $DSCSourceFolder) { + $DSCSourceFilePaths = @(Get-ChildItem $DSCSourceFolder -File -Filter '*.ps1' | ForEach-Object -Process {$_.FullName}) + foreach ($DSCSourceFilePath in $DSCSourceFilePaths) { + $DSCArchiveFilePath = $DSCSourceFilePath.Substring(0, $DSCSourceFilePath.Length - 4) + '.zip' + Publish-AzureRmVMDscConfiguration $DSCSourceFilePath -OutputArchivePath $DSCArchiveFilePath -Force -Verbose + } + } + + # Create a storage account name if none was provided + if ($StorageAccountName -eq '') { + $StorageAccountName = 'stage' + ((Get-AzureRmContext).Subscription.SubscriptionId).Replace('-', '').substring(0, 19) + } + + $StorageAccount = (Get-AzureRmStorageAccount | Where-Object{$_.StorageAccountName -eq $StorageAccountName}) + + # Create the storage account if it doesn't already exist + if ($StorageAccount -eq $null) { + $StorageResourceGroupName = 'ARM_Deploy_Staging' + New-AzureRmResourceGroup -Location "$ResourceGroupLocation" -Name $StorageResourceGroupName -Force + $StorageAccount = New-AzureRmStorageAccount -StorageAccountName $StorageAccountName -Type 'Standard_LRS' -ResourceGroupName $StorageResourceGroupName -Location "$ResourceGroupLocation" + } + + # Generate the value for artifacts location if it is not provided in the parameter file + if ($OptionalParameters[$ArtifactsLocationName] -eq $null) { + $OptionalParameters[$ArtifactsLocationName] = $StorageAccount.Context.BlobEndPoint + $StorageContainerName + } + + # Copy files from the local storage staging location to the storage account container + New-AzureStorageContainer -Name $StorageContainerName -Context $StorageAccount.Context -ErrorAction SilentlyContinue *>&1 + + $ArtifactFilePaths = Get-ChildItem $ArtifactStagingDirectory -Recurse -File | ForEach-Object -Process {$_.FullName} + foreach ($SourcePath in $ArtifactFilePaths) { + Set-AzureStorageBlobContent -File $SourcePath -Blob $SourcePath.Substring($ArtifactStagingDirectory.length + 1) ` + -Container $StorageContainerName -Context $StorageAccount.Context -Force + } + + # Generate a 4 hour SAS token for the artifacts location if one was not provided in the parameters file + if ($OptionalParameters[$ArtifactsLocationSasTokenName] -eq $null) { + $OptionalParameters[$ArtifactsLocationSasTokenName] = ConvertTo-SecureString -AsPlainText -Force ` + (New-AzureStorageContainerSASToken -Container $StorageContainerName -Context $StorageAccount.Context -Permission r -ExpiryTime (Get-Date).AddHours(4)) + } +} + +# Create or update the resource group using the specified template file and template parameters file +New-AzureRmResourceGroup -Name $ResourceGroupName -Location $ResourceGroupLocation -Verbose -Force + +if ($ValidateOnly) { + $ErrorMessages = Format-ValidationOutput (Test-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroupName ` + -TemplateFile $TemplateFile ` + -TemplateParameterFile $TemplateParametersFile ` + @OptionalParameters) + if ($ErrorMessages) { + Write-Output '', 'Validation returned the following errors:', @($ErrorMessages), '', 'Template is invalid.' + } + else { + Write-Output '', 'Template is valid.' + } +} +else { + New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $TemplateFile).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) ` + -ResourceGroupName $ResourceGroupName ` + -TemplateFile $TemplateFile ` + -TemplateParameterFile $TemplateParametersFile ` + @OptionalParameters ` + -Force -Verbose ` + -ErrorVariable ErrorMessages + if ($ErrorMessages) { + Write-Output '', 'Template deployment returned the following errors:', @(@($ErrorMessages) | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") }) + } +} \ No newline at end of file diff --git a/deploy/arm/eShopOnAzure.Deploy/Deployment.targets b/deploy/arm/eShopOnAzure.Deploy/Deployment.targets new file mode 100644 index 000000000..0d792ec66 --- /dev/null +++ b/deploy/arm/eShopOnAzure.Deploy/Deployment.targets @@ -0,0 +1,123 @@ + + + + Debug + AnyCPU + bin\$(Configuration)\ + false + true + false + None + obj\ + $(BaseIntermediateOutputPath)\ + $(BaseIntermediateOutputPath)$(Configuration)\ + $(IntermediateOutputPath)ProjectReferences + $(ProjectReferencesOutputPath)\ + true + + + + false + false + + + + + + + + + + + Always + + + Never + + + false + Build + + + + + + + + _GetDeploymentProjectContent; + _CalculateContentOutputRelativePaths; + _GetReferencedProjectsOutput; + _CalculateArtifactStagingDirectory; + _CopyOutputToArtifactStagingDirectory; + + + + + + + + + + + + + + + + + Configuration=$(Configuration);Platform=$(Platform) + + + + + + + $([System.IO.Path]::GetFileNameWithoutExtension('%(ProjectReference.Identity)')) + + + + + + + $(OutDir) + $(OutputPath) + $(ArtifactStagingDirectory)\ + $(ArtifactStagingDirectory)staging\ + $(Build_StagingDirectory) + + + + + + + <_OriginalIdentity>%(DeploymentProjectContentOutput.Identity) + <_RelativePath>$(_OriginalIdentity.Replace('$(MSBuildProjectDirectory)', '')) + + + + + $(_RelativePath) + + + + + + + + + PrepareForRun + + + + + + + + + + + diff --git a/deploy/arm/eShopOnAzure.Deploy/eShopOnAzure.Deploy.deployproj b/deploy/arm/eShopOnAzure.Deploy/eShopOnAzure.Deploy.deployproj new file mode 100644 index 000000000..b44305d1e --- /dev/null +++ b/deploy/arm/eShopOnAzure.Deploy/eShopOnAzure.Deploy.deployproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + + + Release + AnyCPU + + + + 642b3f2e-3011-4b1a-8d22-d35c11c44f05 + + + Deployment + 1.0 + + + + + + + + + + + False + + + + Never + + + + + \ No newline at end of file diff --git a/deploy/arm/eShopOnAzure.Deploy/sqldeploy.json b/deploy/arm/eShopOnAzure.Deploy/sqldeploy.json new file mode 100644 index 000000000..c4b9dca20 --- /dev/null +++ b/deploy/arm/eShopOnAzure.Deploy/sqldeploy.json @@ -0,0 +1,103 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "sql_server": { + "type": "object" + }, + "suffix": { + "type": "string" + } + }, + "variables": { + "sql_server_name": "[concat(parameters('sql_server').name, '-', parameters('suffix'))]" + }, + "resources": [ + { + "type": "Microsoft.Sql/servers", + "name": "[variables('sql_server_name')]", + "apiVersion": "2014-04-01-preview", + "location": "[resourceGroup().location]", + "properties": { + "administratorLogin": "[parameters('sql_server').admin]", + "administratorLoginPassword": "[parameters('sql_server').adminpwd]", + "version": "12.0" + }, + "resources": [ + { + "type": "databases", + "name": "[parameters('sql_server').dbs.ordering]", + "apiVersion": "2014-04-01-preview", + "location": "[resourceGroup().location]", + "properties": { + "edition": "Standard", + "collation": "SQL_Latin1_General_CP1_CI_AS", + "maxSizeBytes": "1073741824", + "requestedServiceObjectiveName": "S1" + }, + "dependsOn": [ + "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" + ] + }, + { + "type": "databases", + "name": "[parameters('sql_server').dbs.identity]", + "apiVersion": "2014-04-01-preview", + "location": "[resourceGroup().location]", + "properties": { + "edition": "Standard", + "collation": "SQL_Latin1_General_CP1_CI_AS", + "maxSizeBytes": "1073741824", + "requestedServiceObjectiveName": "S1" + }, + "dependsOn": [ + "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" + ] + }, + { + "type": "databases", + "name": "[parameters('sql_server').dbs.catalog]", + "apiVersion": "2014-04-01-preview", + "location": "[resourceGroup().location]", + "properties": { + "edition": "Standard", + "collation": "SQL_Latin1_General_CP1_CI_AS", + "maxSizeBytes": "1073741824", + "requestedServiceObjectiveName": "S1" + }, + "dependsOn": [ + "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" + ] + }, + { + "type": "firewallrules", + "name": "AllowAllWindowsAzureIps", + "apiVersion": "2014-04-01-preview", + "location": "[resourceGroup().location]", + "properties": { + "startIpAddress": "0.0.0.0", + "endIpAddress": "0.0.0.0" + }, + "dependsOn": [ + "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" + ] + }, + { + "type": "firewallrules", + "name": "AllConnectionsAllowed", + "apiVersion": "2014-04-01-preview", + "location": "[resourceGroup().location]", + "properties": { + "startIpAddress": "0.0.0.0", + "endIpAddress": "255.255.255.255" + }, + "dependsOn": [ + "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" + ] + } + ] + } + ], + "outputs": { + } +} diff --git a/deploy/arm/eShopOnAzure.Deploy/sqldeploy.parameters.json b/deploy/arm/eShopOnAzure.Deploy/sqldeploy.parameters.json new file mode 100644 index 000000000..5b0dfdbae --- /dev/null +++ b/deploy/arm/eShopOnAzure.Deploy/sqldeploy.parameters.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "sql_server": { + "value": { + "name": "eshop-sqlsrv", + "admin": "eshop", + "adminpwd": "Pass@word", + "dbs": { + "ordering": "orderingdb", + "identity": "identitydb", + "catalog": "catalogdb" + } + } + }, + "suffix": { + "value": "edu" + } + } +} diff --git a/deploy/az/linux-vm/create-resources.cmd b/deploy/az/linux-vm/create-resources.cmd deleted file mode 100644 index c8e317b2d..000000000 --- a/deploy/az/linux-vm/create-resources.cmd +++ /dev/null @@ -1,5 +0,0 @@ -REM az group create --name eShopOnAzureDev --location westus - -az group deployment create --resource-group eShopOnAzureDev --parameters @mvparams.json ^ - --template-uri https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/docker-simple-on-ubuntu/azuredeploy.json - diff --git a/deploy/az/vms/linux-vm/azuredeploy.json b/deploy/az/vms/linux-vm/azuredeploy.json new file mode 100644 index 000000000..5b4778ebe --- /dev/null +++ b/deploy/az/vms/linux-vm/azuredeploy.json @@ -0,0 +1,199 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "newStorageAccountName": { + "type": "string", + "metadata": { + "description": "Unique DNS Name for the Storage Account where the Virtual Machine's disks will be placed." + } + }, + "adminUsername": { + "type": "string", + "metadata": { + "description": "Username for the Virtual Machine." + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Password for the Virtual Machine." + } + }, + "dnsNameForPublicIP": { + "type": "string", + "metadata": { + "description": "Unique DNS Name for the Public IP used to access the Virtual Machine." + } + }, + "ubuntuOSVersion": { + "type": "string", + "defaultValue": "14.04.4-LTS", + "metadata": { + "description": "The Ubuntu version for deploying the Docker containers. This will pick a fully patched image of this given Ubuntu version. Allowed values: 14.04.4-LTS, 15.10, 16.04.0-LTS" + }, + "allowedValues": [ + "14.04.4-LTS", + "15.10", + "16.04.0-LTS" + ] + }, + "VMName": { + "type": "string", + "metadata": { + "description": "Name of VM in Azure" + } + } + }, + "variables": { + "newStorageAccountName": "[take(concat(parameters('newStorageAccountName'), uniqueString(resourceGroup().id)), 23)]", + "dnsNameForPublicIP": "[concat(parameters('dnsNameForPublicIP'), uniqueString(resourceGroup().id))]", + "imagePublisher": "Canonical", + "imageOffer": "UbuntuServer", + "OSDiskName": "osdiskfordockersimple", + "nicName": "myVMNicD", + "extensionName": "DockerExtension", + "addressPrefix": "10.0.0.0/16", + "subnetName": "Subnet", + "subnetPrefix": "10.0.0.0/24", + "storageAccountType": "Standard_LRS", + "publicIPAddressName": "myPublicIPD", + "publicIPAddressType": "Dynamic", + "vmStorageAccountContainerName": "vhds", + "vmName": "[parameters('VMName')]", + "vmSize": "Standard_F1", + "virtualNetworkName": "MyVNETD", + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]", + "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]" + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "name": "[variables('newStorageAccountName')]", + "apiVersion": "2015-05-01-preview", + "location": "[resourceGroup().location]", + "properties": { + "accountType": "[variables('storageAccountType')]" + } + }, + { + "apiVersion": "2015-05-01-preview", + "type": "Microsoft.Network/publicIPAddresses", + "name": "[variables('publicIPAddressName')]", + "location": "[resourceGroup().location]", + "properties": { + "publicIPAllocationMethod": "[variables('publicIPAddressType')]", + "dnsSettings": { + "domainNameLabel": "[variables('dnsNameForPublicIP')]" + } + } + }, + { + "apiVersion": "2015-05-01-preview", + "type": "Microsoft.Network/virtualNetworks", + "name": "[variables('virtualNetworkName')]", + "location": "[resourceGroup().location]", + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[variables('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "addressPrefix": "[variables('subnetPrefix')]" + } + } + ] + } + }, + { + "apiVersion": "2015-05-01-preview", + "type": "Microsoft.Network/networkInterfaces", + "name": "[variables('nicName')]", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]", + "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]" + ], + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]" + }, + "subnet": { + "id": "[variables('subnetRef')]" + } + } + } + ] + } + }, + { + "apiVersion": "2015-05-01-preview", + "type": "Microsoft.Compute/virtualMachines", + "name": "[variables('vmName')]", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Storage/storageAccounts/', variables('newStorageAccountName'))]", + "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]" + ], + "properties": { + "hardwareProfile": { + "vmSize": "[variables('vmSize')]" + }, + "osProfile": { + "computerName": "[variables('vmName')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]" + }, + "storageProfile": { + "imageReference": { + "publisher": "[variables('imagePublisher')]", + "offer": "[variables('imageOffer')]", + "sku": "[parameters('ubuntuOSVersion')]", + "version": "latest" + }, + "osDisk": { + "name": "osdisk1", + "vhd": { + "uri": "[concat('http://',variables('newStorageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]" + }, + "caching": "ReadWrite", + "createOption": "FromImage" + } + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]" + } + ] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "name": "[concat(variables('vmName'),'/', variables('extensionName'))]", + "apiVersion": "2015-05-01-preview", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]" + ], + "properties": { + "publisher": "Microsoft.Azure.Extensions", + "type": "DockerExtension", + "typeHandlerVersion": "1.0", + "autoUpgradeMinorVersion": true, + "settings": { } + } + } + ] +} + diff --git a/deploy/az/vms/linux-vm/create-resources.cmd b/deploy/az/vms/linux-vm/create-resources.cmd new file mode 100644 index 000000000..82ac4da6d --- /dev/null +++ b/deploy/az/vms/linux-vm/create-resources.cmd @@ -0,0 +1,21 @@ +@echo off +if %1.==. GOTO error +if NOT %2.==-c. GOTO createvm +if %3.==. GOTO error +echo Creating resource group %1 in '%3' +call az group create --name %1 --location %3 +:createvm +echo Creating VM in resource group %1 +call az group deployment create --resource-group %1 --parameters @mvparams.json --template-file azuredeploy.json +GOTO end +:error +echo. +echo Usage: +echo create-resources resource-group-name [-c location] +echo resource-grop-name: Name of the resource group to use or create +echo -c: If appears means that resource group must be created. If -c is specified, must use enter location +echo. +echo Examples: +echo create-resources testgroup (Creates VM in a existing testgroup resource group) +echo create-resources newgroup -c westus (Creates the VM in a NEW resource group named newgroup in the westus location) +:end diff --git a/deploy/az/linux-vm/mvparams.json b/deploy/az/vms/linux-vm/mvparams.json similarity index 63% rename from deploy/az/linux-vm/mvparams.json rename to deploy/az/vms/linux-vm/mvparams.json index c80c82e6c..d34dfd1d9 100644 --- a/deploy/az/linux-vm/mvparams.json +++ b/deploy/az/vms/linux-vm/mvparams.json @@ -2,5 +2,6 @@ "newStorageAccountName": { "value": "eshopsrvmvstorage" }, "adminUsername": { "value": "eshop" }, "adminPassword": { "value": "Pass@word" }, - "dnsNameForPublicIP": { "value": "eshop-srv" } + "dnsNameForPublicIP": { "value": "eshop-srv" }, + "VMName": {"value": "MyDockerVM2"} } diff --git a/deploy/az/vms/readme.md b/deploy/az/vms/readme.md new file mode 100644 index 000000000..a2e9c42b7 --- /dev/null +++ b/deploy/az/vms/readme.md @@ -0,0 +1,54 @@ +# Deploy a VM to run the services + +Follow these instructions to deploy a Linux-based VM with the Docker Host installed, or a VM with Windows Server 2016 plus +windows containers and Docker Daemon. + +You can use this machine to installthe microservices and having a "development" environment (useful to develop and test the client apps). + +Please note that this deployment is not a production deployment. In a production-based scenario, you should deploy all containers in ACS. + +## Create the VM + +Ensure you are logged in the desired subscription (use `az login` and `az account set` if needed. Refer to [this article](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli) for more details. + +Go to `linux-vm` or `win-vm` folder (based on if you want a Linux or Windows VM). Then: + +1. Edit the file `mvparams.json` with your desired values +2. Run the file `create-resources.cmd` from command-line to create the VM. + +**Note:** To avoid errors, ARM template used (`azuredeploy.json`), generates unique names for: + +1. VM used storage +2. Public DNS + +Those public names are based on the parameters set in `mvparams.json` file. + +### The mvparams.json file + +This file contains the minimum set of parameters needed by the ARM template to deploy the VM. ARM template accepts some other parameters (set with +default values). Look the template for more info. + +The parameters defined in this file are: + +1. `newStorageAccountName`: Name of the storage created for the VM. To ensure uniqueness a unique suffix will be added to this value. +2. `adminUsername`: Admin login +3. `adminPassword`: Admin password +4. `dnsNameForPublicIP`: DNS of the VM. To ensure uniqueness a unique suffix will be added to this value. +5. `VMName`: Name of the VM inside Azure + +## Finding the IP and DNS of the VM + +To find the IP and FQDN of the VM you can type `az vm list --resource-group --output table --show-details` (where resourcegroup is the +name of the resourcegroup where you created the VM). This command will generate output like: + +``` +Name ResourceGroup PowerState PublicIps Fqdns Location +---------- --------------- ------------ ------------- ------------------------------------------------ ---------- +MyDockerVM MyResourceGroup VM running xx.xx.xxx.xxx eshop-srvxxxxxxxxxxxxx.westus.cloudapp.azure.com westus +``` + +You can use this information to connect your new VM. + +## Deploy services in the VM + +We are providing public images of the services in DockerHub (https://hub.docker.com/u/eshop/). diff --git a/deploy/az/win-vm/azuredeploy.json b/deploy/az/vms/win-vm/azuredeploy.json similarity index 93% rename from deploy/az/win-vm/azuredeploy.json rename to deploy/az/vms/win-vm/azuredeploy.json index 89bf54785..78bebdfef 100644 --- a/deploy/az/win-vm/azuredeploy.json +++ b/deploy/az/vms/win-vm/azuredeploy.json @@ -43,10 +43,12 @@ "metadata": { "description": "VM Size" } - } + } }, "variables": { + "newStorageAccountName": "[take(concat(parameters('newStorageAccountName'), uniqueString(resourceGroup().id)), 23)]", + "dnsNameForPublicIP": "[concat(parameters('dnsNameForPublicIP'), uniqueString(resourceGroup().id))]", "windowsOSVersion": "2016-Datacenter", "imagePublisher": "MicrosoftWindowsServer", "imageOffer": "WindowsServer", @@ -66,7 +68,6 @@ "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]" }, "resources": [ - { "type": "Microsoft.Network/networkSecurityGroups", "name": "[variables('networkSecurityGroupName')]", @@ -125,7 +126,7 @@ { "type": "Microsoft.Storage/storageAccounts", - "name": "[parameters('newStorageAccountName')]", + "name": "[variables('newStorageAccountName')]", "apiVersion": "[variables('apiVersion')]", "location": "[resourceGroup().location]", "tags": { @@ -147,7 +148,7 @@ "properties": { "publicIPAllocationMethod": "[variables('publicIPAddressType')]", "dnsSettings": { - "domainNameLabel": "[tolower(parameters('dnsNameForPublicIP'))]" + "domainNameLabel": "[tolower(variables('dnsNameForPublicIP'))]" } } }, @@ -222,7 +223,7 @@ "displayName": "VirtualMachine" }, "dependsOn": [ - "[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]", + "[concat('Microsoft.Storage/storageAccounts/', variables('newStorageAccountName'))]", "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]" ], "properties": { @@ -244,7 +245,7 @@ "osDisk": { "name": "osdisk", "vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName')), variables('apiVersion')).primaryEndpoints.blob, variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]" + "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('newStorageAccountName')), variables('apiVersion')).primaryEndpoints.blob, variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]" }, "caching": "ReadWrite", "createOption": "FromImage" diff --git a/deploy/az/vms/win-vm/create-resources.cmd b/deploy/az/vms/win-vm/create-resources.cmd new file mode 100644 index 000000000..07ac2a2da --- /dev/null +++ b/deploy/az/vms/win-vm/create-resources.cmd @@ -0,0 +1,15 @@ +if %1.==. GOTO error +if %2.!=-c. GOTO createvm +if %3.==. GOTO error +az group create --name %1 --location %3 +createvm: +az group deployment create --resource-group %1 --parameters @mvparams.json --template-file azuredeploy.json +GOTO end +error: +@echo Usage: create-resources [-c location] +@echo : Name of the resource group to use or create +@echo -c: If appears means that resource group must be created. If -c is specified, must use enter location +@echo Examples: +@echo create-resources testgroup (Creates VM in a existing testgroup resource group) +@echo create-resources newgroup -c westus (Creates the VM in a NEW resource group named newgroup in the westus location) +end: diff --git a/deploy/az/win-vm/mvparams.json b/deploy/az/vms/win-vm/mvparams.json similarity index 100% rename from deploy/az/win-vm/mvparams.json rename to deploy/az/vms/win-vm/mvparams.json diff --git a/deploy/az/win-vm/create-resources.cmd b/deploy/az/win-vm/create-resources.cmd deleted file mode 100644 index b35de9431..000000000 --- a/deploy/az/win-vm/create-resources.cmd +++ /dev/null @@ -1,3 +0,0 @@ -REM az group create --name eShopOnAzureDevWin --location westus -az group deployment create --resource-group eShopOnAzureDevWin --parameters @mvparams.json --template-file azuredeploy.json - diff --git a/deploy/readme.md b/deploy/readme.md index 4fd772049..66efea64b 100644 --- a/deploy/readme.md +++ b/deploy/readme.md @@ -4,11 +4,17 @@ 1. [Azure CLI 2.0 Installed](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) 2. Azure subscription created +Login into your azure subscription by typing `az login` (note that you maybe need to use `az account set` to set the subscription to use). Refer to [this article](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli) for more details + ## Deploying using CLI -1. Run `az login` to login into your Azure subscription (note that you maybe need to use `az account set` to set the subscription to use) -2. Edit the file `mvparams.json` with your desired values -3. Run the file `create-resources.cmd` from command-line to create the Linux-based VM with Docker installed +## Deploying Virtual machines to host the services + +1. [Deploying a Linux VM or Windows Server 2016 to run a single-development environment](az/vms/readme.md) + +## Deploying Azure resources used by the services + +1. [Deploying SQL Server and databases](arm/sql-server.md) From fb72a0efc61a22f42bbbea4e5597f5facd9cd717 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Fri, 19 May 2017 13:19:20 +0200 Subject: [PATCH 19/60] update to doc --- deploy/az/vms/readme.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/deploy/az/vms/readme.md b/deploy/az/vms/readme.md index a2e9c42b7..ad9993e53 100644 --- a/deploy/az/vms/readme.md +++ b/deploy/az/vms/readme.md @@ -51,4 +51,13 @@ You can use this information to connect your new VM. ## Deploy services in the VM -We are providing public images of the services in DockerHub (https://hub.docker.com/u/eshop/). +We are providing public images of the services in DockerHub (https://hub.docker.com/u/eshop/). To use these images, just create a folder in the VM and copy +following files to it (those files are in the root of the repo): + +1. `docker-compose.yml` +2. `docker-compose.prod.yml` + +Then log into the VM and run the command `docker-compose -f docker-compose.yml -f docker-compose.prod.yml up --no-build -d` to start all the microservices. + + + From 09b0e3ee48cc4e7ab43708e1b1f7c434cb09cf90 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Fri, 19 May 2017 14:38:16 +0200 Subject: [PATCH 20/60] Doc updated --- deploy/arm/eShopOnAzure.Deploy.sln | 22 ---- .../Deploy-AzureResourceGroup.ps1 | 120 ----------------- .../eShopOnAzure.Deploy/Deployment.targets | 123 ------------------ .../eShopOnAzure.Deploy.deployproj | 38 ------ deploy/az/create-resources.cmd | 23 ++++ deploy/az/readme.md | 20 +++ deploy/az/sql/readme.md | 33 +++++ .../sql}/sqldeploy.json | 0 .../sql}/sqldeploy.parameters.json | 0 deploy/az/vms/linux-vm/create-resources.cmd | 21 --- .../{azuredeploy.json => linuxvm.json} | 0 ...{mvparams.json => linuxvm.parameters.json} | 0 deploy/az/vms/readme.md | 14 +- deploy/az/vms/win-vm/create-resources.cmd | 15 --- .../{azuredeploy.json => windowsvm.json} | 0 ...vparams.json => windowsvm.parameters.json} | 0 deploy/readme.md | 2 +- 17 files changed, 87 insertions(+), 344 deletions(-) delete mode 100644 deploy/arm/eShopOnAzure.Deploy.sln delete mode 100644 deploy/arm/eShopOnAzure.Deploy/Deploy-AzureResourceGroup.ps1 delete mode 100644 deploy/arm/eShopOnAzure.Deploy/Deployment.targets delete mode 100644 deploy/arm/eShopOnAzure.Deploy/eShopOnAzure.Deploy.deployproj create mode 100644 deploy/az/create-resources.cmd create mode 100644 deploy/az/readme.md create mode 100644 deploy/az/sql/readme.md rename deploy/{arm/eShopOnAzure.Deploy => az/sql}/sqldeploy.json (100%) rename deploy/{arm/eShopOnAzure.Deploy => az/sql}/sqldeploy.parameters.json (100%) delete mode 100644 deploy/az/vms/linux-vm/create-resources.cmd rename deploy/az/vms/linux-vm/{azuredeploy.json => linuxvm.json} (100%) rename deploy/az/vms/linux-vm/{mvparams.json => linuxvm.parameters.json} (100%) delete mode 100644 deploy/az/vms/win-vm/create-resources.cmd rename deploy/az/vms/win-vm/{azuredeploy.json => windowsvm.json} (100%) rename deploy/az/vms/win-vm/{mvparams.json => windowsvm.parameters.json} (100%) diff --git a/deploy/arm/eShopOnAzure.Deploy.sln b/deploy/arm/eShopOnAzure.Deploy.sln deleted file mode 100644 index 6fb65821a..000000000 --- a/deploy/arm/eShopOnAzure.Deploy.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.6 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{151D2E53-A2C4-4D7D-83FE-D05416EBD58E}") = "eShopOnAzure.Deploy", "eShopOnAzure.Deploy\eShopOnAzure.Deploy.deployproj", "{642B3F2E-3011-4B1A-8D22-D35C11C44F05}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {642B3F2E-3011-4B1A-8D22-D35C11C44F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {642B3F2E-3011-4B1A-8D22-D35C11C44F05}.Debug|Any CPU.Build.0 = Debug|Any CPU - {642B3F2E-3011-4B1A-8D22-D35C11C44F05}.Release|Any CPU.ActiveCfg = Release|Any CPU - {642B3F2E-3011-4B1A-8D22-D35C11C44F05}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/deploy/arm/eShopOnAzure.Deploy/Deploy-AzureResourceGroup.ps1 b/deploy/arm/eShopOnAzure.Deploy/Deploy-AzureResourceGroup.ps1 deleted file mode 100644 index cf119eea6..000000000 --- a/deploy/arm/eShopOnAzure.Deploy/Deploy-AzureResourceGroup.ps1 +++ /dev/null @@ -1,120 +0,0 @@ -#Requires -Version 3.0 -#Requires -Module AzureRM.Resources -#Requires -Module Azure.Storage - -Param( - [string] [Parameter(Mandatory=$true)] $ResourceGroupLocation, - [string] $ResourceGroupName = 'eShopOnAzure.Deploy', - [switch] $UploadArtifacts, - [string] $StorageAccountName, - [string] $StorageContainerName = $ResourceGroupName.ToLowerInvariant() + '-stageartifacts', - [string] $TemplateFile = 'azuredeploy.json', - [string] $TemplateParametersFile = 'azuredeploy.parameters.json', - [string] $ArtifactStagingDirectory = '.', - [string] $DSCSourceFolder = 'DSC', - [switch] $ValidateOnly -) - -try { - [Microsoft.Azure.Common.Authentication.AzureSession]::ClientFactory.AddUserAgent("VSAzureTools-$UI$($host.name)".replace(' ','_'), '3.0.0') -} catch { } - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 3 - -function Format-ValidationOutput { - param ($ValidationOutput, [int] $Depth = 0) - Set-StrictMode -Off - return @($ValidationOutput | Where-Object { $_ -ne $null } | ForEach-Object { @(' ' * $Depth + ': ' + $_.Message) + @(Format-ValidationOutput @($_.Details) ($Depth + 1)) }) -} - -$OptionalParameters = New-Object -TypeName Hashtable -$TemplateFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $TemplateFile)) -$TemplateParametersFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $TemplateParametersFile)) - -if ($UploadArtifacts) { - # Convert relative paths to absolute paths if needed - $ArtifactStagingDirectory = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $ArtifactStagingDirectory)) - $DSCSourceFolder = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $DSCSourceFolder)) - - # Parse the parameter file and update the values of artifacts location and artifacts location SAS token if they are present - $JsonParameters = Get-Content $TemplateParametersFile -Raw | ConvertFrom-Json - if (($JsonParameters | Get-Member -Type NoteProperty 'parameters') -ne $null) { - $JsonParameters = $JsonParameters.parameters - } - $ArtifactsLocationName = '_artifactsLocation' - $ArtifactsLocationSasTokenName = '_artifactsLocationSasToken' - $OptionalParameters[$ArtifactsLocationName] = $JsonParameters | Select -Expand $ArtifactsLocationName -ErrorAction Ignore | Select -Expand 'value' -ErrorAction Ignore - $OptionalParameters[$ArtifactsLocationSasTokenName] = $JsonParameters | Select -Expand $ArtifactsLocationSasTokenName -ErrorAction Ignore | Select -Expand 'value' -ErrorAction Ignore - - # Create DSC configuration archive - if (Test-Path $DSCSourceFolder) { - $DSCSourceFilePaths = @(Get-ChildItem $DSCSourceFolder -File -Filter '*.ps1' | ForEach-Object -Process {$_.FullName}) - foreach ($DSCSourceFilePath in $DSCSourceFilePaths) { - $DSCArchiveFilePath = $DSCSourceFilePath.Substring(0, $DSCSourceFilePath.Length - 4) + '.zip' - Publish-AzureRmVMDscConfiguration $DSCSourceFilePath -OutputArchivePath $DSCArchiveFilePath -Force -Verbose - } - } - - # Create a storage account name if none was provided - if ($StorageAccountName -eq '') { - $StorageAccountName = 'stage' + ((Get-AzureRmContext).Subscription.SubscriptionId).Replace('-', '').substring(0, 19) - } - - $StorageAccount = (Get-AzureRmStorageAccount | Where-Object{$_.StorageAccountName -eq $StorageAccountName}) - - # Create the storage account if it doesn't already exist - if ($StorageAccount -eq $null) { - $StorageResourceGroupName = 'ARM_Deploy_Staging' - New-AzureRmResourceGroup -Location "$ResourceGroupLocation" -Name $StorageResourceGroupName -Force - $StorageAccount = New-AzureRmStorageAccount -StorageAccountName $StorageAccountName -Type 'Standard_LRS' -ResourceGroupName $StorageResourceGroupName -Location "$ResourceGroupLocation" - } - - # Generate the value for artifacts location if it is not provided in the parameter file - if ($OptionalParameters[$ArtifactsLocationName] -eq $null) { - $OptionalParameters[$ArtifactsLocationName] = $StorageAccount.Context.BlobEndPoint + $StorageContainerName - } - - # Copy files from the local storage staging location to the storage account container - New-AzureStorageContainer -Name $StorageContainerName -Context $StorageAccount.Context -ErrorAction SilentlyContinue *>&1 - - $ArtifactFilePaths = Get-ChildItem $ArtifactStagingDirectory -Recurse -File | ForEach-Object -Process {$_.FullName} - foreach ($SourcePath in $ArtifactFilePaths) { - Set-AzureStorageBlobContent -File $SourcePath -Blob $SourcePath.Substring($ArtifactStagingDirectory.length + 1) ` - -Container $StorageContainerName -Context $StorageAccount.Context -Force - } - - # Generate a 4 hour SAS token for the artifacts location if one was not provided in the parameters file - if ($OptionalParameters[$ArtifactsLocationSasTokenName] -eq $null) { - $OptionalParameters[$ArtifactsLocationSasTokenName] = ConvertTo-SecureString -AsPlainText -Force ` - (New-AzureStorageContainerSASToken -Container $StorageContainerName -Context $StorageAccount.Context -Permission r -ExpiryTime (Get-Date).AddHours(4)) - } -} - -# Create or update the resource group using the specified template file and template parameters file -New-AzureRmResourceGroup -Name $ResourceGroupName -Location $ResourceGroupLocation -Verbose -Force - -if ($ValidateOnly) { - $ErrorMessages = Format-ValidationOutput (Test-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroupName ` - -TemplateFile $TemplateFile ` - -TemplateParameterFile $TemplateParametersFile ` - @OptionalParameters) - if ($ErrorMessages) { - Write-Output '', 'Validation returned the following errors:', @($ErrorMessages), '', 'Template is invalid.' - } - else { - Write-Output '', 'Template is valid.' - } -} -else { - New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $TemplateFile).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) ` - -ResourceGroupName $ResourceGroupName ` - -TemplateFile $TemplateFile ` - -TemplateParameterFile $TemplateParametersFile ` - @OptionalParameters ` - -Force -Verbose ` - -ErrorVariable ErrorMessages - if ($ErrorMessages) { - Write-Output '', 'Template deployment returned the following errors:', @(@($ErrorMessages) | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") }) - } -} \ No newline at end of file diff --git a/deploy/arm/eShopOnAzure.Deploy/Deployment.targets b/deploy/arm/eShopOnAzure.Deploy/Deployment.targets deleted file mode 100644 index 0d792ec66..000000000 --- a/deploy/arm/eShopOnAzure.Deploy/Deployment.targets +++ /dev/null @@ -1,123 +0,0 @@ - - - - Debug - AnyCPU - bin\$(Configuration)\ - false - true - false - None - obj\ - $(BaseIntermediateOutputPath)\ - $(BaseIntermediateOutputPath)$(Configuration)\ - $(IntermediateOutputPath)ProjectReferences - $(ProjectReferencesOutputPath)\ - true - - - - false - false - - - - - - - - - - - Always - - - Never - - - false - Build - - - - - - - - _GetDeploymentProjectContent; - _CalculateContentOutputRelativePaths; - _GetReferencedProjectsOutput; - _CalculateArtifactStagingDirectory; - _CopyOutputToArtifactStagingDirectory; - - - - - - - - - - - - - - - - - Configuration=$(Configuration);Platform=$(Platform) - - - - - - - $([System.IO.Path]::GetFileNameWithoutExtension('%(ProjectReference.Identity)')) - - - - - - - $(OutDir) - $(OutputPath) - $(ArtifactStagingDirectory)\ - $(ArtifactStagingDirectory)staging\ - $(Build_StagingDirectory) - - - - - - - <_OriginalIdentity>%(DeploymentProjectContentOutput.Identity) - <_RelativePath>$(_OriginalIdentity.Replace('$(MSBuildProjectDirectory)', '')) - - - - - $(_RelativePath) - - - - - - - - - PrepareForRun - - - - - - - - - - - diff --git a/deploy/arm/eShopOnAzure.Deploy/eShopOnAzure.Deploy.deployproj b/deploy/arm/eShopOnAzure.Deploy/eShopOnAzure.Deploy.deployproj deleted file mode 100644 index b44305d1e..000000000 --- a/deploy/arm/eShopOnAzure.Deploy/eShopOnAzure.Deploy.deployproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - - Debug - AnyCPU - - - Release - AnyCPU - - - - 642b3f2e-3011-4b1a-8d22-d35c11c44f05 - - - Deployment - 1.0 - - - - - - - - - - - False - - - - Never - - - - - \ No newline at end of file diff --git a/deploy/az/create-resources.cmd b/deploy/az/create-resources.cmd new file mode 100644 index 000000000..bd27efe3e --- /dev/null +++ b/deploy/az/create-resources.cmd @@ -0,0 +1,23 @@ +@echo off +if %1.==. GOTO error +if %2.==. GOTO error +if NOT %3.==-c. GOTO deployresources +if %4.==. GOTO error +echo Creating resource group %2 in '%4' +call az group create --name %2 --location %4 +:deployresources +echo Deploying ARM template '%1.json' in resource group %2 +call az group deployment create --resource-group %2 --parameters @%1.parameters.json --template-file %1.json +GOTO end +:error +echo. +echo Usage: +echo create-resources arm-file resource-group-name [-c location] +echo arm-file: Path to ARM template WITHOUT .json extension. An parameter file with same name plus '.parameters' MUST exist in same folde +echo resource-grop-name: Name of the resource group to use or create +echo -c: If appears means that resource group must be created. If -c is specified, must use enter location +echo. +echo Examples: +echo create-resources path_and_filename testgroup (Deploys path_and_filename.json with parameters specified in path_and_filename.parameters.json file). +echo create-resources path_and_filename newgroup -c westus (Deploys path_and_filename.json (with parameters specified in path_and_filename.parameters.json file) in a NEW resource group named newgroup in the westus location) +:end diff --git a/deploy/az/readme.md b/deploy/az/readme.md new file mode 100644 index 000000000..cee4581cb --- /dev/null +++ b/deploy/az/readme.md @@ -0,0 +1,20 @@ +# Deploying resources using create-resources script + +The `create-resources` script is a basic script to allow easy deployment of one ARM template in one resource group. You can deploy to an existing resource group or to create one. + +## Deploying to a existing resource group + +Just type `create-resources path-to-arm-template resourcegroup`. Called this way the script will: + +1. Search for `path-to-arm-template.json` and `path-to-arm-template.parameters.json` files +2. If they exist, will deploy them in the `resourcegroup` specified (that has to exist). + +## Deploying to a new resource group + +Just type `create-resources path-to-arm-template resourcegroup -c location`. Called this way the script will: + +1. Search for `path-to-arm-template.json` and `path-to-arm-template.parameters.json` files +2. If they exist, will create the `resourcegroup` specified in the `location` specified. +3. Finally will deploy `path-to-arm-template.json` and `path-to-arm-template.parameters.json` files in the `resourcegroup` + + diff --git a/deploy/az/sql/readme.md b/deploy/az/sql/readme.md new file mode 100644 index 000000000..bbc0b9140 --- /dev/null +++ b/deploy/az/sql/readme.md @@ -0,0 +1,33 @@ +# Deploying SQL Server & SQL Databases + +The ARM template `sqldeploy.json` and its parameter file (`sqldeploy.parameters.json`) are used to deploy following resources: + +1. One SQL Server +2. Three SQL databases (for ordering, catalog and identity) services. +3. Firewall rules to **allow access from any IP to SQL Server**. This allows easy management, but is not desired in production environments. + +## Editing sqldeploy.parameters.json file + +You have to edit the `sqldeploy.parameters.json` file to set your values. There are two parameters: + +1. `sql_server` is a object parameter that contains the sql server name, the admin login and password, and the database names. +2. `suffix` is a suffix that will be added to thee sql_server name to ensure uniqueness. + +## Deploy the template + +Once parameter file is edited you can deploy it using [create-resources script](../readme.md). + +i. e. if you are in windows, to deploy sql databases in a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd sql\sqldeploy newResourceGroup -c westus +``` + + + + + + + + + diff --git a/deploy/arm/eShopOnAzure.Deploy/sqldeploy.json b/deploy/az/sql/sqldeploy.json similarity index 100% rename from deploy/arm/eShopOnAzure.Deploy/sqldeploy.json rename to deploy/az/sql/sqldeploy.json diff --git a/deploy/arm/eShopOnAzure.Deploy/sqldeploy.parameters.json b/deploy/az/sql/sqldeploy.parameters.json similarity index 100% rename from deploy/arm/eShopOnAzure.Deploy/sqldeploy.parameters.json rename to deploy/az/sql/sqldeploy.parameters.json diff --git a/deploy/az/vms/linux-vm/create-resources.cmd b/deploy/az/vms/linux-vm/create-resources.cmd deleted file mode 100644 index 82ac4da6d..000000000 --- a/deploy/az/vms/linux-vm/create-resources.cmd +++ /dev/null @@ -1,21 +0,0 @@ -@echo off -if %1.==. GOTO error -if NOT %2.==-c. GOTO createvm -if %3.==. GOTO error -echo Creating resource group %1 in '%3' -call az group create --name %1 --location %3 -:createvm -echo Creating VM in resource group %1 -call az group deployment create --resource-group %1 --parameters @mvparams.json --template-file azuredeploy.json -GOTO end -:error -echo. -echo Usage: -echo create-resources resource-group-name [-c location] -echo resource-grop-name: Name of the resource group to use or create -echo -c: If appears means that resource group must be created. If -c is specified, must use enter location -echo. -echo Examples: -echo create-resources testgroup (Creates VM in a existing testgroup resource group) -echo create-resources newgroup -c westus (Creates the VM in a NEW resource group named newgroup in the westus location) -:end diff --git a/deploy/az/vms/linux-vm/azuredeploy.json b/deploy/az/vms/linux-vm/linuxvm.json similarity index 100% rename from deploy/az/vms/linux-vm/azuredeploy.json rename to deploy/az/vms/linux-vm/linuxvm.json diff --git a/deploy/az/vms/linux-vm/mvparams.json b/deploy/az/vms/linux-vm/linuxvm.parameters.json similarity index 100% rename from deploy/az/vms/linux-vm/mvparams.json rename to deploy/az/vms/linux-vm/linuxvm.parameters.json diff --git a/deploy/az/vms/readme.md b/deploy/az/vms/readme.md index ad9993e53..28b528330 100644 --- a/deploy/az/vms/readme.md +++ b/deploy/az/vms/readme.md @@ -13,15 +13,21 @@ Ensure you are logged in the desired subscription (use `az login` and `az accoun Go to `linux-vm` or `win-vm` folder (based on if you want a Linux or Windows VM). Then: -1. Edit the file `mvparams.json` with your desired values -2. Run the file `create-resources.cmd` from command-line to create the VM. +1. Edit the file `linuxvm.parameters.json` or `windowsvm.parameters.json` (based on what VM do you want to create) with your desired values +2. Run the [create-resources script](../readme.md) to deploy the desired template (`linux-vm/linuxvm.json` or `win-vm/windowsvm.json`). -**Note:** To avoid errors, ARM template used (`azuredeploy.json`), generates unique names for: +I. e. if you are in Windows and want to deploy a linux based VM, in a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd vms\linux-vm\linuxvm newResourceGroup -c westus +``` + +**Note:** To avoid errors, ARM template used generates unique names for: 1. VM used storage 2. Public DNS -Those public names are based on the parameters set in `mvparams.json` file. +Those public names are based on the parameters set in the parameters file. ### The mvparams.json file diff --git a/deploy/az/vms/win-vm/create-resources.cmd b/deploy/az/vms/win-vm/create-resources.cmd deleted file mode 100644 index 07ac2a2da..000000000 --- a/deploy/az/vms/win-vm/create-resources.cmd +++ /dev/null @@ -1,15 +0,0 @@ -if %1.==. GOTO error -if %2.!=-c. GOTO createvm -if %3.==. GOTO error -az group create --name %1 --location %3 -createvm: -az group deployment create --resource-group %1 --parameters @mvparams.json --template-file azuredeploy.json -GOTO end -error: -@echo Usage: create-resources [-c location] -@echo : Name of the resource group to use or create -@echo -c: If appears means that resource group must be created. If -c is specified, must use enter location -@echo Examples: -@echo create-resources testgroup (Creates VM in a existing testgroup resource group) -@echo create-resources newgroup -c westus (Creates the VM in a NEW resource group named newgroup in the westus location) -end: diff --git a/deploy/az/vms/win-vm/azuredeploy.json b/deploy/az/vms/win-vm/windowsvm.json similarity index 100% rename from deploy/az/vms/win-vm/azuredeploy.json rename to deploy/az/vms/win-vm/windowsvm.json diff --git a/deploy/az/vms/win-vm/mvparams.json b/deploy/az/vms/win-vm/windowsvm.parameters.json similarity index 100% rename from deploy/az/vms/win-vm/mvparams.json rename to deploy/az/vms/win-vm/windowsvm.parameters.json diff --git a/deploy/readme.md b/deploy/readme.md index 66efea64b..0a24fdaba 100644 --- a/deploy/readme.md +++ b/deploy/readme.md @@ -14,7 +14,7 @@ Login into your azure subscription by typing `az login` (note that you maybe nee ## Deploying Azure resources used by the services -1. [Deploying SQL Server and databases](arm/sql-server.md) +1. [Deploying SQL Server and databases](az/sql/readme.md) From c9976d424808b457e08de585be51cf94d4e93263 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Fri, 19 May 2017 14:40:56 +0200 Subject: [PATCH 21/60] minor fixes --- deploy/az/vms/readme.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/deploy/az/vms/readme.md b/deploy/az/vms/readme.md index 28b528330..6def07978 100644 --- a/deploy/az/vms/readme.md +++ b/deploy/az/vms/readme.md @@ -29,12 +29,11 @@ create-resources.cmd vms\linux-vm\linuxvm newResourceGroup -c westus Those public names are based on the parameters set in the parameters file. -### The mvparams.json file +### The parameters file (linuxvm.parameters.json or winsowsvm.parameters.json) -This file contains the minimum set of parameters needed by the ARM template to deploy the VM. ARM template accepts some other parameters (set with -default values). Look the template for more info. +Both files are identical and contains the minimum set of parameters needed by the ARM template to deploy the VM. ARM template accepts some other parameters (set with default values). Look the template for more info. -The parameters defined in this file are: +The parameters defined are: 1. `newStorageAccountName`: Name of the storage created for the VM. To ensure uniqueness a unique suffix will be added to this value. 2. `adminUsername`: Admin login From 58005c73dc35e81de7ee94ccd9299a653bb8c1a3 Mon Sep 17 00:00:00 2001 From: Cesar De la Torre Date: Fri, 19 May 2017 09:58:56 -0700 Subject: [PATCH 22/60] Update readme.md --- deploy/az/vms/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/az/vms/readme.md b/deploy/az/vms/readme.md index 6def07978..b91fb504c 100644 --- a/deploy/az/vms/readme.md +++ b/deploy/az/vms/readme.md @@ -3,7 +3,7 @@ Follow these instructions to deploy a Linux-based VM with the Docker Host installed, or a VM with Windows Server 2016 plus windows containers and Docker Daemon. -You can use this machine to installthe microservices and having a "development" environment (useful to develop and test the client apps). +You can use this machine to install the microservices and having a "development" environment (useful to develop and test the client apps). Please note that this deployment is not a production deployment. In a production-based scenario, you should deploy all containers in ACS. From 1b1764f3aa4b9a3825cdbe66a048aeecab720956 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Fri, 19 May 2017 20:22:55 +0200 Subject: [PATCH 23/60] Doc updated with docker-machine --- deploy/az/vms/docker-machine.md | 48 ++++++++++++++++++++ deploy/az/vms/plain-vm.md | 77 +++++++++++++++++++++++++++++++++ deploy/az/vms/readme.md | 70 +++--------------------------- deploy/readme.md | 5 ++- 4 files changed, 135 insertions(+), 65 deletions(-) create mode 100644 deploy/az/vms/docker-machine.md create mode 100644 deploy/az/vms/plain-vm.md diff --git a/deploy/az/vms/docker-machine.md b/deploy/az/vms/docker-machine.md new file mode 100644 index 000000000..71cbbd4a7 --- /dev/null +++ b/deploy/az/vms/docker-machine.md @@ -0,0 +1,48 @@ +# Create a VM using docker-machine + +Ensure you are logged in the desired subscription Refer to [this article](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli) for more details. + +1. Use `az account show` to find your subscription id. +2. Use `docker-machine create --driver azure --azure-subscription-id --azure-resource-group --azure-ssh-user ` + +After use `docker-machine create` you'll need to authenticate in Azure (even thought if you are logged using `az`, because this is not an Azure CLI 2.0 command). This command will fully create the VM with all the needed settings to run Docker. + +**Note** Refer to this article with all the [parameters that docker-machine accepts when creating Azure VMs](https://docs.docker.com/machine/drivers/azure/#options) for finding more parameters. + +## Connecting your local environment with docker host running on the VM + +Using docker-machine you control the remote VM from your local development environment (you don't need to use ssh to login to remote VM). + +Connecting your local environment to a remote host is using by setting some environment variables, but the easiest way is to use again the docker-machine command. Just type `docker-machine env machine_name` (where machine_name is the name you gave when you created the VM). That command **do not change anything**, so do'nt do really nothing, but **outputs the environment variables you have to set**. This is the output of the command (running on a windows workstation): + +``` +SET DOCKER_TLS_VERIFY=1 +SET DOCKER_HOST=tcp://104.42.236.237:2376 +SET DOCKER_CERT_PATH=C:\Users\etoma\.docker\machine\machines\ufohost +SET DOCKER_MACHINE_NAME=ufohost +SET COMPOSE_CONVERT_WINDOWS_PATHS=true +REM Run this command to configure your shell: +REM @FOR /f "tokens=*" %i IN ('docker-machine env ufohost') DO @%i +``` + +You have to set all these environment variables, or (as the command suggest) just copy and paste the last line in your terminal. + +Once you did this, your local development machine is connected to VM running Docker on Azure: all docker and docker-compose commands will run in the VM instead of your local Docker machine! + + + + + + + + + + + + + + + + + + diff --git a/deploy/az/vms/plain-vm.md b/deploy/az/vms/plain-vm.md new file mode 100644 index 000000000..4e06ed0d3 --- /dev/null +++ b/deploy/az/vms/plain-vm.md @@ -0,0 +1,77 @@ +# Deploy a VM to run the services + +Follow these instructions to deploy a Linux-based VM with the Docker Host installed, or a VM with Windows Server 2016 plus +windows containers and Docker Daemon. + +**Note**: Use this option, only if you want to provide an environment using images pulled from DockerHub (for example, to create a test environment). If you want to +be able to deploy images built by yourself (but not pushed to DockerHub) follow the [instructions about using docker-machine](./docker-machine.md). + +You can use this machine to install the microservices and having a "development" environment (useful to develop and test the client apps). + +Please note that this deployment is not a production deployment. In a production-based scenario, you should deploy all containers in ACS. + +## Create the VM + +Ensure you are logged in the desired subscription (use `az login` and `az account set` if needed. Refer to [this article](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli) for more details. + +Go to `linux-vm` or `win-vm` folder (based on if you want a Linux or Windows VM). Then: + +1. Edit the file `linuxvm.parameters.json` or `windowsvm.parameters.json` (based on what VM do you want to create) with your desired values +2. Run the [create-resources script](../readme.md) to deploy the desired template (`linux-vm/linuxvm.json` or `win-vm/windowsvm.json`). + +I. e. if you are in Windows and want to deploy a linux based VM, in a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd vms\linux-vm\linuxvm newResourceGroup -c westus +``` + +**Note:** To avoid errors, ARM template used generates unique names for: + +1. VM used storage +2. Public DNS + +Those public names are based on the parameters set in the parameters file. + +### The parameters file (linuxvm.parameters.json or winsowsvm.parameters.json) + +Both files are identical and contains the minimum set of parameters needed by the ARM template to deploy the VM. ARM template accepts some other parameters (set with default values). Look the template for more info. + +The parameters defined are: + +1. `newStorageAccountName`: Name of the storage created for the VM. To ensure uniqueness a unique suffix will be added to this value. +2. `adminUsername`: Admin login +3. `adminPassword`: Admin password +4. `dnsNameForPublicIP`: DNS of the VM. To ensure uniqueness a unique suffix will be added to this value. +5. `VMName`: Name of the VM inside Azure + +## Finding the IP and DNS of the VM + +To find the IP and FQDN of the VM you can type `az vm list --resource-group --output table --show-details` (where resourcegroup is the +name of the resourcegroup where you created the VM). This command will generate output like: + +``` +Name ResourceGroup PowerState PublicIps Fqdns Location +---------- --------------- ------------ ------------- ------------------------------------------------ ---------- +MyDockerVM MyResourceGroup VM running xx.xx.xxx.xxx eshop-srvxxxxxxxxxxxxx.westus.cloudapp.azure.com westus +``` + +You can use this information to connect your new VM. + +## Deploy services in the VM + +We are providing public images of the services in DockerHub (https://hub.docker.com/u/eshop/). To use these images, just create a folder in the VM and copy +following files to it (those files are in the root of the repo): + +1. `docker-compose.nobuild.yml` +2. `docker-compose.prod.yml` + +**Note:** The `docker-compose.nobuild.yml` is just a version of the `docker-compose.yml` without the `build` section. Is neede due [docker-compose bug](https://github.com/docker/compose/issues/2945). + +Then log into the VM and run the command `docker-compose -f docker-compose.nobuild.yml -f docker-compose.prod.yml up --no-build -d` to start all the microservices. + + + + + + + diff --git a/deploy/az/vms/readme.md b/deploy/az/vms/readme.md index b91fb504c..25085f75c 100644 --- a/deploy/az/vms/readme.md +++ b/deploy/az/vms/readme.md @@ -1,68 +1,10 @@ -# Deploy a VM to run the services +## Create VM with Docker installed -Follow these instructions to deploy a Linux-based VM with the Docker Host installed, or a VM with Windows Server 2016 plus -windows containers and Docker Daemon. - -You can use this machine to install the microservices and having a "development" environment (useful to develop and test the client apps). - -Please note that this deployment is not a production deployment. In a production-based scenario, you should deploy all containers in ACS. - -## Create the VM - -Ensure you are logged in the desired subscription (use `az login` and `az account set` if needed. Refer to [this article](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli) for more details. - -Go to `linux-vm` or `win-vm` folder (based on if you want a Linux or Windows VM). Then: - -1. Edit the file `linuxvm.parameters.json` or `windowsvm.parameters.json` (based on what VM do you want to create) with your desired values -2. Run the [create-resources script](../readme.md) to deploy the desired template (`linux-vm/linuxvm.json` or `win-vm/windowsvm.json`). - -I. e. if you are in Windows and want to deploy a linux based VM, in a new resourcegroup located in westus, go to `deploy\az` folder and type: - -``` -create-resources.cmd vms\linux-vm\linuxvm newResourceGroup -c westus -``` - -**Note:** To avoid errors, ARM template used generates unique names for: - -1. VM used storage -2. Public DNS - -Those public names are based on the parameters set in the parameters file. - -### The parameters file (linuxvm.parameters.json or winsowsvm.parameters.json) - -Both files are identical and contains the minimum set of parameters needed by the ARM template to deploy the VM. ARM template accepts some other parameters (set with default values). Look the template for more info. - -The parameters defined are: - -1. `newStorageAccountName`: Name of the storage created for the VM. To ensure uniqueness a unique suffix will be added to this value. -2. `adminUsername`: Admin login -3. `adminPassword`: Admin password -4. `dnsNameForPublicIP`: DNS of the VM. To ensure uniqueness a unique suffix will be added to this value. -5. `VMName`: Name of the VM inside Azure - -## Finding the IP and DNS of the VM - -To find the IP and FQDN of the VM you can type `az vm list --resource-group --output table --show-details` (where resourcegroup is the -name of the resourcegroup where you created the VM). This command will generate output like: - -``` -Name ResourceGroup PowerState PublicIps Fqdns Location ----------- --------------- ------------ ------------- ------------------------------------------------ ---------- -MyDockerVM MyResourceGroup VM running xx.xx.xxx.xxx eshop-srvxxxxxxxxxxxxx.westus.cloudapp.azure.com westus -``` - -You can use this information to connect your new VM. - -## Deploy services in the VM - -We are providing public images of the services in DockerHub (https://hub.docker.com/u/eshop/). To use these images, just create a folder in the VM and copy -following files to it (those files are in the root of the repo): - -1. `docker-compose.yml` -2. `docker-compose.prod.yml` - -Then log into the VM and run the command `docker-compose -f docker-compose.yml -f docker-compose.prod.yml up --no-build -d` to start all the microservices. +There are two options for creating VM machines with Docker installed: +1. [Deploying a Linux VM to run single-server development environment using docker-machine (**Recommended for development environments**)](./docker-machine.md) +2. [Deploying a Linux VM or Windows Server 2016 to run a single-server development environment using ARM template (**Recommended for creating testing environments**)](./plain-vm.md) +If you want to create a VM for deploying images you build locally, then use the first option. +If you want to create a VM to run images deployed to DockerHub (to provide some test environment) then use the second option. \ No newline at end of file diff --git a/deploy/readme.md b/deploy/readme.md index 0a24fdaba..bf51a7bf2 100644 --- a/deploy/readme.md +++ b/deploy/readme.md @@ -10,7 +10,10 @@ Login into your azure subscription by typing `az login` (note that you maybe nee ## Deploying Virtual machines to host the services -1. [Deploying a Linux VM or Windows Server 2016 to run a single-development environment](az/vms/readme.md) +1. [Deploying a Linux VM to run single-server development environment using docker-machine (**Recommended for development environments**)](az/vms/docker-machine.md) +2. [Deploying a Linux VM or Windows Server 2016 to run a single-server development environment using ARM template (**Recommended for creating testing environments**)](az/vms/plain-vm.md) + +Using `docker-machine` is the recommended way to create a VM with docker installed. But it is limited to Linux based VMs. ## Deploying Azure resources used by the services From 7980c2679dca250d76fa6f470ad688459a39e5e0 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 15:32:22 +0200 Subject: [PATCH 24/60] - Declare new ServiceBus instance with "AzureServiceBus" boolean condition - Add ServiceBusConnection and AzureServiceBus variables in settings - Add EventBusServiceBus dependencies --- .../Ordering/Ordering.API/Ordering.API.csproj | 1 + src/Services/Ordering/Ordering.API/Startup.cs | 56 ++++++++++++++++--- .../Ordering/Ordering.API/settings.json | 4 +- 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/Services/Ordering/Ordering.API/Ordering.API.csproj b/src/Services/Ordering/Ordering.API/Ordering.API.csproj index 975645ce4..5e36a1bc0 100644 --- a/src/Services/Ordering/Ordering.API/Ordering.API.csproj +++ b/src/Services/Ordering/Ordering.API/Ordering.API.csproj @@ -24,6 +24,7 @@ + diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 0cc8dbc0a..678f1f587 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -12,10 +12,12 @@ using Infrastructure.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; + using Microsoft.Azure.ServiceBus; using Microsoft.EntityFrameworkCore; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; using Microsoft.Extensions.Configuration; @@ -113,20 +115,33 @@ var serviceProvider = services.BuildServiceProvider(); services.AddTransient(); - services.AddSingleton(sp => + if (Configuration.GetValue("AzureServiceBus")) { - var logger = sp.GetRequiredService>(); + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); + + var serviceBusConnection = new ServiceBusConnectionStringBuilder(Configuration["ServiceBusConnection"]); - var factory = new ConnectionFactory() + return new DefaultServiceBusPersisterConnection(serviceBusConnection, TimeSpan.FromSeconds(5), RetryPolicy.Default, logger); + }); + } + else + { + services.AddSingleton(sp => { - HostName = Configuration["EventBusConnection"] - }; + var logger = sp.GetRequiredService>(); - return new DefaultRabbitMQPersistentConnection(factory, logger); - }); + var factory = new ConnectionFactory() + { + HostName = Configuration["EventBusConnection"] + }; - services.AddSingleton(); - services.AddSingleton(); + return new DefaultRabbitMQPersistentConnection(factory, logger); + }); + } + + RegisterServiceBus(services); services.AddOptions(); @@ -174,5 +189,28 @@ RequireHttpsMetadata = false }); } + + private void RegisterServiceBus(IServiceCollection services) + { + if (Configuration.GetValue("AzureServiceBus")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + var subscriptionClientName = "Ordering"; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName); + }); + } + else + { + services.AddSingleton(); + } + + services.AddSingleton(); + } } } diff --git a/src/Services/Ordering/Ordering.API/settings.json b/src/Services/Ordering/Ordering.API/settings.json index 09552377a..e30e813a5 100644 --- a/src/Services/Ordering/Ordering.API/settings.json +++ b/src/Services/Ordering/Ordering.API/settings.json @@ -8,5 +8,7 @@ "System": "Information", "Microsoft": "Information" } - } + }, + "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "AzureServiceBus": "true" } From 3acd556c5c9bffa74e7f4547656228d8fd17f357 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 15:33:05 +0200 Subject: [PATCH 25/60] - Declare new ServiceBus instance with "AzureServiceBus" boolean condition DI - Add ServiceBusConnection and AzureServiceBus variables in settings - Add EventBusServiceBus dependencies --- .../Catalog/Catalog.API/Catalog.API.csproj | 1 + .../Catalog/Catalog.API/CatalogSettings.cs | 2 + src/Services/Catalog/Catalog.API/Startup.cs | 59 +++++++++++++++---- .../Catalog/Catalog.API/settings.json | 4 +- 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj index 4306d6922..ff69bff56 100644 --- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj +++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj @@ -57,6 +57,7 @@ + diff --git a/src/Services/Catalog/Catalog.API/CatalogSettings.cs b/src/Services/Catalog/Catalog.API/CatalogSettings.cs index af6e0ab13..5ef5b973c 100644 --- a/src/Services/Catalog/Catalog.API/CatalogSettings.cs +++ b/src/Services/Catalog/Catalog.API/CatalogSettings.cs @@ -5,5 +5,7 @@ public string ExternalCatalogBaseUrl {get;set;} public string EventBusConnection { get; set; } + + public string ServiceBusConnection { get; set; } } } diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index 65fb26515..8434a40d2 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -4,11 +4,13 @@ using global::Catalog.API.IntegrationEvents; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; + using Microsoft.Azure.ServiceBus; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; @@ -109,20 +111,34 @@ services.AddTransient(); - services.AddSingleton(sp => + if (Configuration.GetValue("AzureServiceBus")) { - var settings = sp.GetRequiredService>().Value; - var logger = sp.GetRequiredService>(); - var factory = new ConnectionFactory() + services.AddSingleton(sp => { - HostName = settings.EventBusConnection - }; + var settings = sp.GetRequiredService>().Value; + var logger = sp.GetRequiredService>(); - return new DefaultRabbitMQPersistentConnection(factory, logger); - }); + var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnection); - services.AddSingleton(); - services.AddSingleton(); + return new DefaultServiceBusPersisterConnection(serviceBusConnection, TimeSpan.FromSeconds(5), RetryPolicy.Default, logger); + }); + } + else + { + services.AddSingleton(sp => + { + var settings = sp.GetRequiredService>().Value; + var logger = sp.GetRequiredService>(); + var factory = new ConnectionFactory() + { + HostName = settings.EventBusConnection + }; + + return new DefaultRabbitMQPersistentConnection(factory, logger); + }); + } + + RegisterServiceBus(services); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) @@ -179,5 +195,28 @@ ctx.Database.CloseConnection(); } } + + private void RegisterServiceBus(IServiceCollection services) + { + if (Configuration.GetValue("AzureServiceBus")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + var subscriptionClientName = "Catalog"; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName); + }); + } + else + { + services.AddSingleton(); + } + + services.AddSingleton(); + } } } diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index e67fec713..7d80981e7 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -8,5 +8,7 @@ "System": "Information", "Microsoft": "Information" } - } + }, + "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "AzureServiceBus": "true" } From 721a4fd02b9c56be0e0e3063c6c0f57db99cae1f Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 15:33:38 +0200 Subject: [PATCH 26/60] - Declare new ServiceBus instance with "AzureServiceBus" boolean condition DI - Add ServiceBusConnection and AzureServiceBus variables in settings - Add EventBusServiceBus dependencies --- .../Basket/Basket.API/Basket.API.csproj | 1 + .../Basket/Basket.API/BasketSettings.cs | 2 + src/Services/Basket/Basket.API/Startup.cs | 53 +++++++++++++++---- .../Basket/Basket.API/appsettings.json | 4 +- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj index b3ba97b10..16130b599 100644 --- a/src/Services/Basket/Basket.API/Basket.API.csproj +++ b/src/Services/Basket/Basket.API/Basket.API.csproj @@ -41,6 +41,7 @@ + diff --git a/src/Services/Basket/Basket.API/BasketSettings.cs b/src/Services/Basket/Basket.API/BasketSettings.cs index 9d143545a..f42af2234 100644 --- a/src/Services/Basket/Basket.API/BasketSettings.cs +++ b/src/Services/Basket/Basket.API/BasketSettings.cs @@ -5,5 +5,7 @@ public string ConnectionString { get; set; } public string EventBusConnection { get; set; } + + public string ServiceBusConnection { get; set; } } } diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 855312a65..4594a1dd1 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -21,6 +21,8 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using System; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +using Microsoft.Azure.ServiceBus; namespace Microsoft.eShopOnContainers.Services.Basket.API { @@ -70,17 +72,33 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API }); - services.AddSingleton(sp => + if (Configuration.GetValue("AzureServiceBus")) { - var settings = sp.GetRequiredService>().Value; - var logger = sp.GetRequiredService>(); - var factory = new ConnectionFactory() + services.AddSingleton(sp => { - HostName = settings.EventBusConnection - }; + var settings = sp.GetRequiredService>().Value; + var logger = sp.GetRequiredService>(); + + var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnection); + + return new DefaultServiceBusPersisterConnection(serviceBusConnection, TimeSpan.FromSeconds(5) , RetryPolicy.Default,logger); + }); + } + else + { + services.AddSingleton(sp => + { + var settings = sp.GetRequiredService>().Value; + var logger = sp.GetRequiredService>(); + var factory = new ConnectionFactory() + { + HostName = settings.EventBusConnection + }; + + return new DefaultRabbitMQPersistentConnection(factory, logger); + }); + } - return new DefaultRabbitMQPersistentConnection(factory, logger); - }); services.AddSwaggerGen(); @@ -113,7 +131,24 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API private void RegisterServiceBus(IServiceCollection services) { - services.AddSingleton(); + if (Configuration.GetValue("AzureServiceBus")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + var subscriptionClientName = "Basket"; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName); + }); + } + else + { + services.AddSingleton(); + } + services.AddSingleton(); services.AddTransient(); diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index 31f76d0d0..f68afbe8f 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -8,5 +8,7 @@ } }, "IdentityUrl": "http://localhost:5105", - "ConnectionString": "127.0.0.1" + "ConnectionString": "127.0.0.1", + "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "AzureServiceBus": "true" } From aa7556a1bdbfce4cff7f22c5185423c2cfd4acb4 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 15:34:55 +0200 Subject: [PATCH 27/60] Create EventBusServiceBus project and add EventBusServiceBus/ServiceBusPersisterConnection to project --- eShopOnContainers-ServicesAndWebApps.sln | 53 ++++++- .../DefaultServiceBusPersisterConnection.cs | 49 +++++++ .../EventBusServiceBus/EventBusServiceBus.cs | 134 ++++++++++++++++++ .../EventBusServiceBus.csproj | 17 +++ .../IServiceBusPersisterConnection.cs | 14 ++ 5 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs create mode 100644 src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs create mode 100644 src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj create mode 100644 src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index eb0e83e02..6aa891a2e 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.26403.3 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}" EndProject @@ -76,6 +76,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBusServiceBus", "src\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj", "{69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -1002,6 +1004,54 @@ Global {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x64.Build.0 = Release|Any CPU {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.ActiveCfg = Release|Any CPU {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.Build.0 = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|ARM.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|iPhone.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|x64.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|x64.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|x86.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.AppStore|x86.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|ARM.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|ARM.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|iPhone.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|x64.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|x64.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|x86.ActiveCfg = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Debug|x86.Build.0 = Debug|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|Any CPU.Build.0 = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|ARM.ActiveCfg = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|ARM.Build.0 = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|iPhone.ActiveCfg = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|iPhone.Build.0 = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x64.ActiveCfg = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x64.Build.0 = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x86.ActiveCfg = Release|Any CPU + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1038,5 +1088,6 @@ Global {22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379} {4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379} {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} EndGlobalSection EndGlobal diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs new file mode 100644 index 000000000..3b9d9bda4 --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs @@ -0,0 +1,49 @@ +using Microsoft.Azure.ServiceBus; +using Microsoft.Extensions.Logging; +using System; +using System.IO; + +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus +{ + public class DefaultServiceBusPersisterConnection : ServiceBusConnection, IServiceBusPersisterConnection + { + private readonly ILogger _logger; + private readonly ServiceBusConnectionStringBuilder _serviceBusConnectionStringBuilder; + private ITopicClient _topicClient; + + bool _disposed; + object sync_root = new object(); + + public DefaultServiceBusPersisterConnection(ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder, + TimeSpan operationTimeout, RetryPolicy retryPolicy, ILogger logger) + : base(operationTimeout, retryPolicy) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + + InitializeConnection(serviceBusConnectionStringBuilder); + _serviceBusConnectionStringBuilder = serviceBusConnectionStringBuilder ?? + throw new ArgumentNullException(nameof(serviceBusConnectionStringBuilder)); + } + + public bool IsConnected => _topicClient.IsClosedOrClosing; + + public ServiceBusConnectionStringBuilder ServiceBusConnectionStringBuilder => _serviceBusConnectionStringBuilder; + + public ITopicClient CreateModel() + { + if(_topicClient.IsClosedOrClosing) + { + _topicClient = new TopicClient(_serviceBusConnectionStringBuilder, RetryPolicy); + } + + return _topicClient; + } + + public void Dispose() + { + if (_disposed) return; + + _disposed = true; + } + } +} diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs new file mode 100644 index 000000000..1433a9f65 --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs @@ -0,0 +1,134 @@ +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus +{ + using System; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + using Microsoft.Extensions.Logging; + using Microsoft.Azure.ServiceBus; + using Newtonsoft.Json; + using System.Text; + using System.Threading.Tasks; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; + using System.Reflection; + using Microsoft.Azure.ServiceBus.Filters; + + public class EventBusServiceBus : IEventBus + { + private readonly IServiceBusPersisterConnection _serviceBusPersisterConnection; + private ServiceBusConnectionStringBuilder _serviceBusConnectionStringBuilder; + private readonly ILogger _logger; + private readonly IEventBusSubscriptionsManager _subsManager; + private readonly SubscriptionClient _subscriptionClient; + + public EventBusServiceBus(IServiceBusPersisterConnection serviceBusPersisterConnection, + ILogger logger, IEventBusSubscriptionsManager subsManager, string subscriptionClientName) + { + _serviceBusPersisterConnection = serviceBusPersisterConnection; + _logger = logger; + _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); + + _subscriptionClient = new SubscriptionClient(serviceBusPersisterConnection.ServiceBusConnectionStringBuilder, + subscriptionClientName); + } + + public void Publish(IntegrationEvent @event) + { + var eventName = @event.GetType().Name; + var jsonMessage = JsonConvert.SerializeObject(@event); + var body = Encoding.UTF8.GetBytes(jsonMessage); + + var message = new Message + { + MessageId = new Guid().ToString(), + Body = Encoding.UTF8.GetBytes(jsonMessage), + Label = eventName, + }; + + var topicClient = _serviceBusPersisterConnection.CreateModel(); + + topicClient.SendAsync(message) + .GetAwaiter() + .GetResult(); + } + + public void Subscribe(Func handler) + where T : IntegrationEvent + where TH : IIntegrationEventHandler + { + var eventName = typeof(T).Name; + var containsKey = _subsManager.HasSubscriptionsForEvent(); + if (!containsKey) + { + try + { + _subscriptionClient.AddRuleAsync(new RuleDescription + { + Filter = new CorrelationFilter { Label = eventName }, + Name = eventName + }).GetAwaiter().GetResult(); + } + catch(ServiceBusException) + { + _logger.LogWarning($"The messaging entity {eventName} already exists."); + } + } + + _subsManager.AddSubscription(handler); + } + + public void Unsubscribe() + where T : IntegrationEvent + where TH : IIntegrationEventHandler + { + var eventName = typeof(T).Name; + + try + { + _subscriptionClient + .RemoveRuleAsync(eventName) + .GetAwaiter() + .GetResult(); + } + catch (MessagingEntityNotFoundException) + { + _logger.LogWarning($"The messaging entity {eventName} Could not be found."); + } + + _subsManager.RemoveSubscription(); + } + + public void Dispose() + { + _subsManager.Clear(); + } + + //private async Task CreateConsumerChannel() + //{ + // _subscriptionClient.RegisterMessageHandler( + // async (message, token) => + // { + // var eventName = message.Label; + // var messageData = Encoding.UTF8.GetString(message.Body); + // await ProcessEvent(eventName, messageData); + // }, + // new MessageHandlerOptions() { MaxConcurrentCalls = 10, AutoComplete = true }); + //} + + private async Task ProcessEvent(string eventName, string message) + { + if (_subsManager.HasSubscriptionsForEvent(eventName)) + { + var eventType = _subsManager.GetEventTypeByName(eventName); + var integrationEvent = JsonConvert.DeserializeObject(message, eventType); + var handlers = _subsManager.GetHandlersForEvent(eventName); + + foreach (var handlerfactory in handlers) + { + var handler = handlerfactory.DynamicInvoke(); + var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); + await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); + } + } + } + } +} diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj new file mode 100644 index 000000000..5be30800e --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp1.1 + Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus + + + + + + + + + + + + \ No newline at end of file diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs new file mode 100644 index 000000000..e995db27e --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs @@ -0,0 +1,14 @@ +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus +{ + using System; + using Microsoft.Azure.ServiceBus; + + public interface IServiceBusPersisterConnection : IDisposable + { + ServiceBusConnectionStringBuilder ServiceBusConnectionStringBuilder { get; } + + bool IsConnected { get; } + + ITopicClient CreateModel(); + } +} \ No newline at end of file From 04b35492c3978eac889d0be990778a97b7361025 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 16:25:41 +0200 Subject: [PATCH 28/60] Add SubscriptionClientName EnvironmentVariable --- src/Services/Basket/Basket.API/Startup.cs | 2 +- src/Services/Basket/Basket.API/appsettings.json | 5 +++-- src/Services/Catalog/Catalog.API/Startup.cs | 2 +- src/Services/Catalog/Catalog.API/settings.json | 3 ++- src/Services/Ordering/Ordering.API/Startup.cs | 2 +- src/Services/Ordering/Ordering.API/settings.json | 3 ++- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 4594a1dd1..62c500f34 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -138,7 +138,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API var serviceBusPersisterConnection = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); - var subscriptionClientName = "Basket"; + var subscriptionClientName = Configuration.GetValue("SubscriptionClientName"); return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, subscriptionClientName); diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index f68afbe8f..6bd839e35 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -10,5 +10,6 @@ "IdentityUrl": "http://localhost:5105", "ConnectionString": "127.0.0.1", "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", - "AzureServiceBus": "true" -} + "AzureServiceBus": "true", + "SubscriptionClientName": "Basket" +} \ 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 8434a40d2..e27d73696 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -205,7 +205,7 @@ var serviceBusPersisterConnection = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); - var subscriptionClientName = "Catalog"; + var subscriptionClientName = Configuration.GetValue("SubscriptionClientName"); return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, subscriptionClientName); diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index 7d80981e7..458755222 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -10,5 +10,6 @@ } }, "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", - "AzureServiceBus": "true" + "AzureServiceBus": "true", + "SubscriptionClientName": "Catalog" } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 678f1f587..c283dff47 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -199,7 +199,7 @@ var serviceBusPersisterConnection = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); - var subscriptionClientName = "Ordering"; + var subscriptionClientName = Configuration.GetValue("SubscriptionClientName"); return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, subscriptionClientName); diff --git a/src/Services/Ordering/Ordering.API/settings.json b/src/Services/Ordering/Ordering.API/settings.json index e30e813a5..478542d2d 100644 --- a/src/Services/Ordering/Ordering.API/settings.json +++ b/src/Services/Ordering/Ordering.API/settings.json @@ -10,5 +10,6 @@ } }, "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", - "AzureServiceBus": "true" + "AzureServiceBus": "true", + "SubscriptionClientName": "Ordering" } From 64430618d770b94e13f954ff210078d01f1cfcdf Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 16:26:21 +0200 Subject: [PATCH 29/60] remove declaration from interface --- .../EventBusServiceBus/IServiceBusPersisterConnection.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs index e995db27e..283031247 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs @@ -7,8 +7,6 @@ { ServiceBusConnectionStringBuilder ServiceBusConnectionStringBuilder { get; } - bool IsConnected { get; } - ITopicClient CreateModel(); } } \ No newline at end of file From d3bd0fabfdc7557a495cf0fe3af66cecd05570a0 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 16:26:40 +0200 Subject: [PATCH 30/60] change log leve --- .../EventBusServiceBus/EventBusServiceBus.cs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs index 1433a9f65..3e941c8e0 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs @@ -29,6 +29,8 @@ _subscriptionClient = new SubscriptionClient(serviceBusPersisterConnection.ServiceBusConnectionStringBuilder, subscriptionClientName); + + CreateConsumerChannel(); } public void Publish(IntegrationEvent @event) @@ -69,7 +71,7 @@ } catch(ServiceBusException) { - _logger.LogWarning($"The messaging entity {eventName} already exists."); + _logger.LogInformation($"The messaging entity {eventName} already exists."); } } @@ -91,7 +93,7 @@ } catch (MessagingEntityNotFoundException) { - _logger.LogWarning($"The messaging entity {eventName} Could not be found."); + _logger.LogInformation($"The messaging entity {eventName} Could not be found."); } _subsManager.RemoveSubscription(); @@ -102,17 +104,17 @@ _subsManager.Clear(); } - //private async Task CreateConsumerChannel() - //{ - // _subscriptionClient.RegisterMessageHandler( - // async (message, token) => - // { - // var eventName = message.Label; - // var messageData = Encoding.UTF8.GetString(message.Body); - // await ProcessEvent(eventName, messageData); - // }, - // new MessageHandlerOptions() { MaxConcurrentCalls = 10, AutoComplete = true }); - //} + private void CreateConsumerChannel() + { + _subscriptionClient.RegisterMessageHandler( + async (message, token) => + { + var eventName = message.Label; + var messageData = Encoding.UTF8.GetString(message.Body); + await ProcessEvent(eventName, messageData); + }, + new MessageHandlerOptions() { MaxConcurrentCalls = 10, AutoComplete = true }); + } private async Task ProcessEvent(string eventName, string message) { From 390654a8854799eb453d02b56220f580d8facd8f Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 16:26:56 +0200 Subject: [PATCH 31/60] Remove old ServiceBusConnection declaration --- .../DefaultServiceBusPersisterConnection.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs index 3b9d9bda4..c85c1ecfe 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs @@ -5,35 +5,31 @@ using System.IO; namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus { - public class DefaultServiceBusPersisterConnection : ServiceBusConnection, IServiceBusPersisterConnection + public class DefaultServiceBusPersisterConnection :IServiceBusPersisterConnection { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ServiceBusConnectionStringBuilder _serviceBusConnectionStringBuilder; private ITopicClient _topicClient; bool _disposed; - object sync_root = new object(); public DefaultServiceBusPersisterConnection(ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder, - TimeSpan operationTimeout, RetryPolicy retryPolicy, ILogger logger) - : base(operationTimeout, retryPolicy) + TimeSpan operationTimeout, RetryPolicy retryPolicy, ILogger logger) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - - InitializeConnection(serviceBusConnectionStringBuilder); + _serviceBusConnectionStringBuilder = serviceBusConnectionStringBuilder ?? throw new ArgumentNullException(nameof(serviceBusConnectionStringBuilder)); + _topicClient = new TopicClient(_serviceBusConnectionStringBuilder, RetryPolicy.Default); } - public bool IsConnected => _topicClient.IsClosedOrClosing; - public ServiceBusConnectionStringBuilder ServiceBusConnectionStringBuilder => _serviceBusConnectionStringBuilder; public ITopicClient CreateModel() { if(_topicClient.IsClosedOrClosing) { - _topicClient = new TopicClient(_serviceBusConnectionStringBuilder, RetryPolicy); + _topicClient = new TopicClient(_serviceBusConnectionStringBuilder, RetryPolicy.Default); } return _topicClient; From 9a100c9a27a737d9414cb1006d6bb1f8a646ef4a Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 18:59:29 +0200 Subject: [PATCH 32/60] Remove retry policy from DefaultServiceBusPersisterConnection parameter --- .../DefaultServiceBusPersisterConnection.cs | 4 ++-- src/Services/Basket/Basket.API/Startup.cs | 4 ++-- src/Services/Catalog/Catalog.API/Startup.cs | 4 ++-- src/Services/Ordering/Ordering.API/Startup.cs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs index c85c1ecfe..db1b6b390 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs @@ -13,8 +13,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus bool _disposed; - public DefaultServiceBusPersisterConnection(ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder, - TimeSpan operationTimeout, RetryPolicy retryPolicy, ILogger logger) + public DefaultServiceBusPersisterConnection(ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder, + ILogger logger) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 62c500f34..20c44b5be 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -81,7 +81,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnection); - return new DefaultServiceBusPersisterConnection(serviceBusConnection, TimeSpan.FromSeconds(5) , RetryPolicy.Default,logger); + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); } else @@ -138,7 +138,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API var serviceBusPersisterConnection = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); - var subscriptionClientName = Configuration.GetValue("SubscriptionClientName"); + var subscriptionClientName = Configuration["SubscriptionClientName"]; return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, subscriptionClientName); diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index e27d73696..fe38eeb87 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -120,7 +120,7 @@ var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnection); - return new DefaultServiceBusPersisterConnection(serviceBusConnection, TimeSpan.FromSeconds(5), RetryPolicy.Default, logger); + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); } else @@ -205,7 +205,7 @@ var serviceBusPersisterConnection = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); - var subscriptionClientName = Configuration.GetValue("SubscriptionClientName"); + var subscriptionClientName = Configuration["SubscriptionClientName"]; return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, subscriptionClientName); diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index c283dff47..594717976 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -123,7 +123,7 @@ var serviceBusConnection = new ServiceBusConnectionStringBuilder(Configuration["ServiceBusConnection"]); - return new DefaultServiceBusPersisterConnection(serviceBusConnection, TimeSpan.FromSeconds(5), RetryPolicy.Default, logger); + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); } else @@ -199,7 +199,7 @@ var serviceBusPersisterConnection = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); - var subscriptionClientName = Configuration.GetValue("SubscriptionClientName"); + var subscriptionClientName = Configuration["SubscriptionClientName"]; return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, subscriptionClientName); From e454940801de8ec1d921883d29bccf014ed3c24a Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Wed, 24 May 2017 19:23:14 +0200 Subject: [PATCH 33/60] environment variable renaming --- src/Services/Basket/Basket.API/BasketSettings.cs | 2 +- src/Services/Basket/Basket.API/Startup.cs | 6 +++--- src/Services/Basket/Basket.API/appsettings.json | 4 ++-- src/Services/Catalog/Catalog.API/CatalogSettings.cs | 2 +- src/Services/Catalog/Catalog.API/Startup.cs | 6 +++--- src/Services/Catalog/Catalog.API/settings.json | 4 ++-- src/Services/Ordering/Ordering.API/Startup.cs | 7 ++++--- src/Services/Ordering/Ordering.API/settings.json | 4 ++-- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/Services/Basket/Basket.API/BasketSettings.cs b/src/Services/Basket/Basket.API/BasketSettings.cs index f42af2234..721461a1c 100644 --- a/src/Services/Basket/Basket.API/BasketSettings.cs +++ b/src/Services/Basket/Basket.API/BasketSettings.cs @@ -6,6 +6,6 @@ public string EventBusConnection { get; set; } - public string ServiceBusConnection { get; set; } + public string ServiceBusConnectionString { get; set; } } } diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 20c44b5be..7a12607c8 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -72,14 +72,14 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API }); - if (Configuration.GetValue("AzureServiceBus")) + if (Configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { var settings = sp.GetRequiredService>().Value; var logger = sp.GetRequiredService>(); - var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnection); + var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnectionString); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); @@ -131,7 +131,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API private void RegisterServiceBus(IServiceCollection services) { - if (Configuration.GetValue("AzureServiceBus")) + if (Configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index 6bd839e35..fcbff20e5 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -9,7 +9,7 @@ }, "IdentityUrl": "http://localhost:5105", "ConnectionString": "127.0.0.1", - "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", - "AzureServiceBus": "true", + "ServiceBusConnectionString": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Basket" } \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/CatalogSettings.cs b/src/Services/Catalog/Catalog.API/CatalogSettings.cs index 5ef5b973c..62e92c6ce 100644 --- a/src/Services/Catalog/Catalog.API/CatalogSettings.cs +++ b/src/Services/Catalog/Catalog.API/CatalogSettings.cs @@ -6,6 +6,6 @@ public string EventBusConnection { get; set; } - public string ServiceBusConnection { get; set; } + public string ServiceBusConnectionString { get; set; } } } diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index fe38eeb87..1b90bd270 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -111,14 +111,14 @@ services.AddTransient(); - if (Configuration.GetValue("AzureServiceBus")) + if (Configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { var settings = sp.GetRequiredService>().Value; var logger = sp.GetRequiredService>(); - var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnection); + var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnectionString); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); @@ -198,7 +198,7 @@ private void RegisterServiceBus(IServiceCollection services) { - if (Configuration.GetValue("AzureServiceBus")) + if (Configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index 458755222..111d04da6 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -9,7 +9,7 @@ "Microsoft": "Information" } }, - "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", - "AzureServiceBus": "true", + "ServiceBusConnectionString": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Catalog" } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 594717976..a3cceb9a5 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -115,13 +115,14 @@ var serviceProvider = services.BuildServiceProvider(); services.AddTransient(); - if (Configuration.GetValue("AzureServiceBus")) + if (Configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { var logger = sp.GetRequiredService>(); - var serviceBusConnection = new ServiceBusConnectionStringBuilder(Configuration["ServiceBusConnection"]); + var serviceBusConnectionString = Configuration["ServiceBusConnectionString"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); @@ -192,7 +193,7 @@ private void RegisterServiceBus(IServiceCollection services) { - if (Configuration.GetValue("AzureServiceBus")) + if (Configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { diff --git a/src/Services/Ordering/Ordering.API/settings.json b/src/Services/Ordering/Ordering.API/settings.json index 478542d2d..13ee06c52 100644 --- a/src/Services/Ordering/Ordering.API/settings.json +++ b/src/Services/Ordering/Ordering.API/settings.json @@ -9,7 +9,7 @@ "Microsoft": "Information" } }, - "ServiceBusConnection": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", - "AzureServiceBus": "true", + "ServiceBusConnectionString": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Ordering" } From 4399d6a4f32a495178c4804949da0f2391c7a7ba Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Fri, 26 May 2017 01:35:19 +0200 Subject: [PATCH 34/60] Remove "Default" rule when the class is Instantiated --- .../EventBusServiceBus/EventBusServiceBus.cs | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs index 3e941c8e0..b71945aba 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs @@ -30,7 +30,8 @@ _subscriptionClient = new SubscriptionClient(serviceBusPersisterConnection.ServiceBusConnectionStringBuilder, subscriptionClientName); - CreateConsumerChannel(); + RemoveDefaultRule(); + RegisterSubscriptionClientMessageHandler(); } public void Publish(IntegrationEvent @event) @@ -60,7 +61,7 @@ var eventName = typeof(T).Name; var containsKey = _subsManager.HasSubscriptionsForEvent(); if (!containsKey) - { + { try { _subscriptionClient.AddRuleAsync(new RuleDescription @@ -104,7 +105,7 @@ _subsManager.Clear(); } - private void CreateConsumerChannel() + private void RegisterSubscriptionClientMessageHandler() { _subscriptionClient.RegisterMessageHandler( async (message, token) => @@ -132,5 +133,20 @@ } } } + + private void RemoveDefaultRule() + { + try + { + _subscriptionClient + .RemoveRuleAsync(SubscriptionClient.DefaultRule) + .GetAwaiter() + .GetResult(); + } + catch (MessagingEntityNotFoundException) + { + _logger.LogInformation($"The messaging entity {SubscriptionClient.DefaultRule} Could not be found."); + } + } } } From ed0e548e2d2cf64a4d7abcaac6a1c63dc471cc70 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Fri, 26 May 2017 01:35:44 +0200 Subject: [PATCH 35/60] minor naming --- src/Services/Basket/Basket.API/Startup.cs | 4 ++-- src/Services/Catalog/Catalog.API/Startup.cs | 10 ++++++++-- src/Services/Ordering/Ordering.API/Startup.cs | 11 +++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 7a12607c8..9c975d4ff 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -126,10 +126,10 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API }); services.AddTransient(); - RegisterServiceBus(services); + RegisterEventBus(services); } - private void RegisterServiceBus(IServiceCollection services) + private void RegisterEventBus(IServiceCollection services) { if (Configuration.GetValue("AzureServiceBusEnabled")) { diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index 1b90bd270..25255cbaa 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -138,7 +138,7 @@ }); } - RegisterServiceBus(services); + RegisterEventBus(services); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) @@ -170,6 +170,8 @@ .Options); integrationEventLogContext.Database.Migrate(); + + ConfigureEventBus(app); } private void WaitForSqlAvailability(CatalogContext ctx, ILoggerFactory loggerFactory, int? retry = 0) @@ -196,7 +198,7 @@ } } - private void RegisterServiceBus(IServiceCollection services) + private void RegisterEventBus(IServiceCollection services) { if (Configuration.GetValue("AzureServiceBusEnabled")) { @@ -218,5 +220,9 @@ services.AddSingleton(); } + protected virtual void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + } } } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index a3cceb9a5..7728725c1 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -142,7 +142,7 @@ }); } - RegisterServiceBus(services); + RegisterEventBus(services); services.AddOptions(); @@ -178,6 +178,8 @@ .UseSqlServer(Configuration["ConnectionString"], b => b.MigrationsAssembly("Ordering.API")) .Options); integrationEventLogContext.Database.Migrate(); + + ConfigureEventBus(app); } protected virtual void ConfigureAuth(IApplicationBuilder app) @@ -191,7 +193,7 @@ }); } - private void RegisterServiceBus(IServiceCollection services) + private void RegisterEventBus(IServiceCollection services) { if (Configuration.GetValue("AzureServiceBusEnabled")) { @@ -213,5 +215,10 @@ services.AddSingleton(); } + + protected virtual void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + } } } From 9549786003d723493d865ba83420ed127bc34d53 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Sat, 27 May 2017 18:33:38 +0200 Subject: [PATCH 36/60] Remove basket.data from docker-compose --- docker-compose.override.yml | 1 - docker-compose.prod.yml | 1 - docker-compose.yml | 6 ------ 3 files changed, 8 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 04d1c4d9c..e7d1072ee 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -12,7 +12,6 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=basket.data - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - EventBusConnection=rabbitmq ports: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index c5d8839ea..35fa2473c 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -17,7 +17,6 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=basket.data - identityUrl=http://identity.api #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. - EventBusConnection=rabbitmq ports: diff --git a/docker-compose.yml b/docker-compose.yml index 09212da8e..1af3b4787 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,6 @@ services: context: ./src/Services/Basket/Basket.API dockerfile: Dockerfile depends_on: - - basket.data - identity.api - rabbitmq @@ -59,11 +58,6 @@ services: sql.data: image: microsoft/mssql-server-linux - basket.data: - image: redis - ports: - - "6379:6379" - rabbitmq: image: rabbitmq ports: From b30d09fbf50e2160710d0107cf203f02333b68e9 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Sat, 27 May 2017 18:34:36 +0200 Subject: [PATCH 37/60] Add Redis connectionString to environment variable --- src/Services/Basket/Basket.API/appsettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index 31f76d0d0..a44967e59 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -8,5 +8,5 @@ } }, "IdentityUrl": "http://localhost:5105", - "ConnectionString": "127.0.0.1" + "ConnectionString": "eshoponazure.redis.cache.windows.net:6379,password=I9t4YmytcxvAjThGz98oUbfcI0Zcu7sIB2nhmmDxjVo=,ssl=false,abortConnect=false" } From c23d2551cde82bb0fdc7e8e74cedcd352c01e1cc Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Sat, 27 May 2017 18:35:28 +0200 Subject: [PATCH 38/60] Add new redis connection getting data from environment variable --- .../Basket.API/Model/RedisBasketRepository.cs | 24 +++++-------------- src/Services/Basket/Basket.API/Startup.cs | 11 ++++----- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs b/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs index 4ca90f383..e896c0773 100644 --- a/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs +++ b/src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs @@ -4,7 +4,6 @@ using Newtonsoft.Json; using StackExchange.Redis; using System.Collections.Generic; using System.Linq; -using System.Net; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Basket.API.Model @@ -16,12 +15,10 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model private ConnectionMultiplexer _redis; - public RedisBasketRepository(IOptionsSnapshot options, ILoggerFactory loggerFactory) { _settings = options.Value; _logger = loggerFactory.CreateLogger(); - } public async Task DeleteBasketAsync(string id) @@ -93,21 +90,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model } private async Task ConnectToRedisAsync() - { - // TODO: Need to make this more robust. ConnectionMultiplexer.ConnectAsync doesn't like domain names or IPv6 addresses. - if (IPAddress.TryParse(_settings.ConnectionString, out var ip)) - { - _redis = await ConnectionMultiplexer.ConnectAsync(ip.ToString()); - _logger.LogInformation($"Connecting to database at {_settings.ConnectionString}"); - } - else - { - // workaround for https://github.com/StackExchange/StackExchange.Redis/issues/410 - var ips = await Dns.GetHostAddressesAsync(_settings.ConnectionString); - _logger.LogInformation($"Connecting to database {_settings.ConnectionString} at IP {ips.First().ToString()}"); - _redis = await ConnectionMultiplexer.ConnectAsync(ips.First().ToString()); - } + { + 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/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 855312a65..8f3735310 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -16,11 +16,8 @@ using Microsoft.Extensions.HealthChecks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using RabbitMQ.Client; -using StackExchange.Redis; -using System.Linq; -using System.Net; using System.Threading.Tasks; -using System; +using StackExchange.Redis; namespace Microsoft.eShopOnContainers.Services.Basket.API { @@ -64,12 +61,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API services.AddSingleton(sp => { var settings = sp.GetRequiredService>().Value; - var ips = Dns.GetHostAddressesAsync(settings.ConnectionString).Result; + var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); + configuration.ResolveDns = true; - return ConnectionMultiplexer.Connect(ips.First().ToString()); + return ConnectionMultiplexer.Connect(configuration); }); - services.AddSingleton(sp => { var settings = sp.GetRequiredService>().Value; From cd790f276f6a6710c788a42a4ac8f396c836393f Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Sat, 27 May 2017 18:35:44 +0200 Subject: [PATCH 39/60] Update StackExchange.Redis version --- src/Services/Basket/Basket.API/Basket.API.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj index b3ba97b10..5f8765f40 100644 --- a/src/Services/Basket/Basket.API/Basket.API.csproj +++ b/src/Services/Basket/Basket.API/Basket.API.csproj @@ -22,6 +22,7 @@ + @@ -33,7 +34,6 @@ - From ec7a2518392d3bc9315ce77a3c059e2a1b3a0711 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Mon, 29 May 2017 09:21:27 +0200 Subject: [PATCH 40/60] Service Bus deploy template and doc --- deploy/az/servicebus/readme.md | 33 ++++ deploy/az/servicebus/sbusdeploy.json | 145 ++++++++++++++++++ .../az/servicebus/sbusdeploy.parameters.json | 9 ++ deploy/readme.md | 1 + 4 files changed, 188 insertions(+) create mode 100644 deploy/az/servicebus/readme.md create mode 100644 deploy/az/servicebus/sbusdeploy.json create mode 100644 deploy/az/servicebus/sbusdeploy.parameters.json diff --git a/deploy/az/servicebus/readme.md b/deploy/az/servicebus/readme.md new file mode 100644 index 000000000..3ed8e8a0e --- /dev/null +++ b/deploy/az/servicebus/readme.md @@ -0,0 +1,33 @@ +# Deploying Azure Service Bus + +The ARM template `sbusdeploy.json` and its parameter file (`sbusdeploy.parameters.json`) are used to deploy following resources: + +1. One Service Bus namespace +2. One Service Bus +3. Subscriptions used by application + +## Editing sbusdeploy.parameters.json file + +You can edit the `sbusdeploy.parameters.parameters.json` file to set your values, but is not needed. The only parameter than can +be set is: + +1. `namespaceprefix` is a string that is used to create the namespace. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. + +## Deploy the template + +Once parameter file is edited you can deploy it using [create-resources script](../readme.md). + +i. e. if you are in windows, to deploy sql databases in a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd servicebus\sbusdeploy newResourceGroup -c westus +``` + + + + + + + + + diff --git a/deploy/az/servicebus/sbusdeploy.json b/deploy/az/servicebus/sbusdeploy.json new file mode 100644 index 000000000..5f6ce3c90 --- /dev/null +++ b/deploy/az/servicebus/sbusdeploy.json @@ -0,0 +1,145 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "namespaceprefix": { + "type": "string", + "metadata": { + "description": "Name of the Service Bus namespace" + } + } + }, + "variables": { + "serviceBusTopicName": "eshop_event_bus", + "BasketSubscriptionName": "Basket", + "CatalogSubscriptionName": "Catalog", + "OrderingSubscriptionName": "Ordering", + "location": "[resourceGroup().location]", + "sbVersion": "2015-08-01", + "defaultSASKeyName": "Root", + "namespace":"[concat(parameters('namespaceprefix'), uniqueString(resourceGroup().id))]", + "authRuleResourceId": "[resourceId('Microsoft.ServiceBus/namespaces/topics/authorizationRules', variables('namespace'), variables('serviceBusTopicName'), variables('defaultSASKeyName'))]" + }, + "resources": [ + { + "apiVersion": "[variables('sbVersion')]", + "name": "[variables('namespace')]", + "type": "Microsoft.ServiceBus/Namespaces", + "location": "[variables('location')]", + "sku": { + "name": "Standard", + "tier": "Standard" + }, + "resources": [ + { + "apiVersion": "[variables('sbVersion')]", + "name": "[variables('serviceBusTopicName')]", + "type": "Topics", + "dependsOn": [ + "[concat('Microsoft.ServiceBus/namespaces/', variables('namespace'))]" + ], + "properties": { + "path": "[variables('serviceBusTopicName')]", + "defaultMessageTimeToLive": "14.00:00:00", + "maxSizeInMegabytes": 1024, + "requiresDuplicateDetection": false, + "enableBatchedOperations": true, + "sizeInBytes": 0, + "filteringMessagesBeforePublishing": false, + "isAnonymousAccessible": false, + "status": "Active", + "supportOrdering": false, + "autoDeleteOnIdle": "10675199.02:48:05.4775807", + "enablePartitioning": true, + "isExpress": false, + "enableSubscriptionPartitioning": false, + "enableExpress": false + }, + "resources": [ + { + "type": "AuthorizationRules", + "name": "[variables('defaultSASKeyName')]", + "apiVersion": "[variables('sbVersion')]", + "properties": { + "rights": [ + "Manage", + "Send", + "Listen" + ] + }, + "dependsOn": [ + "[variables('serviceBusTopicName')]" + ] + }, + { + "apiVersion": "[variables('sbVersion')]", + "name": "[variables('BasketSubscriptionName')]", + "type": "Subscriptions", + "dependsOn": [ + "[variables('serviceBusTopicName')]" + ], + "properties": { + "lockDuration": "00:00:30", + "requiresSession": false, + "defaultMessageTimeToLive": "14.00:00:00", + "deadLetteringOnMessageExpiration": true, + "deadLetteringOnFilterEvaluationExceptions": true, + "maxDeliveryCount": 10, + "enableBatchedOperations": false, + "status": "Active", + "autoDeleteOnIdle": "10675199.02:48:05.4775807", + "entityAvailabilityStatus": "Available" + } + }, + { + "apiVersion": "[variables('sbVersion')]", + "name": "[variables('OrderingSubscriptionName')]", + "type": "Subscriptions", + "dependsOn": [ + "[variables('serviceBusTopicName')]" + ], + "properties": { + "lockDuration": "00:00:30", + "requiresSession": false, + "defaultMessageTimeToLive": "14.00:00:00", + "deadLetteringOnMessageExpiration": true, + "deadLetteringOnFilterEvaluationExceptions": true, + "maxDeliveryCount": 10, + "enableBatchedOperations": false, + "status": "Active", + "autoDeleteOnIdle": "10675199.02:48:05.4775807", + "entityAvailabilityStatus": "Available" + } + }, + { + "apiVersion": "[variables('sbVersion')]", + "name": "[variables('CatalogSubscriptionName')]", + "type": "Subscriptions", + "dependsOn": [ + "[variables('serviceBusTopicName')]" + ], + "properties": { + "lockDuration": "00:00:30", + "requiresSession": false, + "defaultMessageTimeToLive": "14.00:00:00", + "deadLetteringOnMessageExpiration": true, + "deadLetteringOnFilterEvaluationExceptions": true, + "maxDeliveryCount": 10, + "enableBatchedOperations": false, + "status": "Active", + "autoDeleteOnIdle": "10675199.02:48:05.4775807", + "entityAvailabilityStatus": "Available" + } + } + ] + } + ] + } + ], + "outputs": { + "NamespaceConnectionString": { + "type": "string", + "value": "[listkeys(variables('authRuleResourceId'), variables('sbVersion')).primaryConnectionString]" + } + } +} \ No newline at end of file diff --git a/deploy/az/servicebus/sbusdeploy.parameters.json b/deploy/az/servicebus/sbusdeploy.parameters.json new file mode 100644 index 000000000..f14b5329d --- /dev/null +++ b/deploy/az/servicebus/sbusdeploy.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "namespaceprefix": { + "value": "eshopsb" + } + } +} diff --git a/deploy/readme.md b/deploy/readme.md index bf51a7bf2..a9520e1f7 100644 --- a/deploy/readme.md +++ b/deploy/readme.md @@ -18,6 +18,7 @@ Using `docker-machine` is the recommended way to create a VM with docker install ## Deploying Azure resources used by the services 1. [Deploying SQL Server and databases](az/sql/readme.md) +2. [Deploying Azure Service Bus](az/servicebus/readme.md) From 41a681429371c7549208c61b6689b8102da475cb Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Mon, 29 May 2017 10:12:07 +0200 Subject: [PATCH 41/60] Add new connection string --- src/Services/Basket/Basket.API/appsettings.json | 2 +- src/Services/Catalog/Catalog.API/settings.json | 2 +- src/Services/Ordering/Ordering.API/settings.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index fcbff20e5..718639474 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -9,7 +9,7 @@ }, "IdentityUrl": "http://localhost:5105", "ConnectionString": "127.0.0.1", - "ServiceBusConnectionString": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "ServiceBusConnectionString": "Endpoint=sb://eshopsbez55a72p6wm62.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=oA6WpfCfCbScZbQa/DBOLfwl6oi5ezPsCYL7QsTb4PY=;EntityPath=eshop_event_bus", "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Basket" } \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index 111d04da6..3cfe64f5e 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -9,7 +9,7 @@ "Microsoft": "Information" } }, - "ServiceBusConnectionString": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "ServiceBusConnectionString": "Endpoint=sb://eshopsbez55a72p6wm62.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=oA6WpfCfCbScZbQa/DBOLfwl6oi5ezPsCYL7QsTb4PY=;EntityPath=eshop_event_bus", "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Catalog" } diff --git a/src/Services/Ordering/Ordering.API/settings.json b/src/Services/Ordering/Ordering.API/settings.json index 13ee06c52..1270a34f6 100644 --- a/src/Services/Ordering/Ordering.API/settings.json +++ b/src/Services/Ordering/Ordering.API/settings.json @@ -9,7 +9,7 @@ "Microsoft": "Information" } }, - "ServiceBusConnectionString": "Endpoint=sb://eshoponazuretest.servicebus.windows.net/;SharedAccessKeyName=Root;SharedAccessKey=Xo9wlr4bRv5iqTTditgFhTeZqxIpczaAUqfspo+QE/s=;EntityPath=eshop_event_bus", + "ServiceBusConnectionString": "Endpoint=sb://eshopsbez55a72p6wm62.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=oA6WpfCfCbScZbQa/DBOLfwl6oi5ezPsCYL7QsTb4PY=;EntityPath=eshop_event_bus", "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Ordering" } From db7d2a3ff3d066d02599a1753d8b7af4865142bb Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Mon, 29 May 2017 11:01:56 +0200 Subject: [PATCH 42/60] Add "AzureRedisConnectionString" environment variable and add a connectionString condition when "AzureRedisEnabled" environment variable is true --- src/Services/Basket/Basket.API/Startup.cs | 7 ++++++- src/Services/Basket/Basket.API/appsettings.json | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 8f3735310..f2f5afc91 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -61,7 +61,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API services.AddSingleton(sp => { var settings = sp.GetRequiredService>().Value; - var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); + if (Configuration.GetValue("AzureRedisEnabled")) + { + settings.ConnectionString = Configuration["AzureRedisConnectionString"]; + } + + ConfigurationOptions configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); configuration.ResolveDns = true; return ConnectionMultiplexer.Connect(configuration); diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index a44967e59..43f70e202 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -8,5 +8,7 @@ } }, "IdentityUrl": "http://localhost:5105", - "ConnectionString": "eshoponazure.redis.cache.windows.net:6379,password=I9t4YmytcxvAjThGz98oUbfcI0Zcu7sIB2nhmmDxjVo=,ssl=false,abortConnect=false" + "ConnectionString": "127.0.0.1", + "AzureRedisConnectionString": "eshoponazure.redis.cache.windows.net:6379,password=I9t4YmytcxvAjThGz98oUbfcI0Zcu7sIB2nhmmDxjVo=,ssl=false,abortConnect=false", + "AzureRedisEnabled": "true" } From 60c08ce9c599f57fabbeebf0b581918fd0361329 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Mon, 29 May 2017 11:06:22 +0200 Subject: [PATCH 43/60] Revert "Remove basket.data from docker-compose" This reverts commit 9549786003d723493d865ba83420ed127bc34d53. --- docker-compose.override.yml | 1 + docker-compose.prod.yml | 1 + docker-compose.yml | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index e7d1072ee..04d1c4d9c 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -12,6 +12,7 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=basket.data - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - EventBusConnection=rabbitmq ports: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 35fa2473c..c5d8839ea 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -17,6 +17,7 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=basket.data - identityUrl=http://identity.api #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. - EventBusConnection=rabbitmq ports: diff --git a/docker-compose.yml b/docker-compose.yml index 1af3b4787..09212da8e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,7 @@ services: context: ./src/Services/Basket/Basket.API dockerfile: Dockerfile depends_on: + - basket.data - identity.api - rabbitmq @@ -58,6 +59,11 @@ services: sql.data: image: microsoft/mssql-server-linux + basket.data: + image: redis + ports: + - "6379:6379" + rabbitmq: image: rabbitmq ports: From bd03600aaaf6d48b975d22c6ed8427925d10bd28 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Mon, 29 May 2017 11:51:34 +0200 Subject: [PATCH 44/60] sql template updated --- deploy/az/sql/readme.md | 11 +++++++---- deploy/az/sql/sqldeploy.json | 13 +++++++++---- deploy/az/sql/sqldeploy.parameters.json | 13 +++++++------ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/deploy/az/sql/readme.md b/deploy/az/sql/readme.md index bbc0b9140..0359fb727 100644 --- a/deploy/az/sql/readme.md +++ b/deploy/az/sql/readme.md @@ -8,15 +8,17 @@ The ARM template `sqldeploy.json` and its parameter file (`sqldeploy.parameters. ## Editing sqldeploy.parameters.json file -You have to edit the `sqldeploy.parameters.json` file to set your values. There are two parameters: +You **must** edit the `sqldeploy.parameters.json` file to set login and password of the admin user. -1. `sql_server` is a object parameter that contains the sql server name, the admin login and password, and the database names. -2. `suffix` is a suffix that will be added to thee sql_server name to ensure uniqueness. +1. `sql_server` is a object parameter that contains the sql server name and the database names. You can leave default values if you want. +2. `admin` is a string with the admin logon. You MUST provide a valid value +3. `adminpwd` is a string with the admin password. You MUST provide a valid value + +ARM script ensures uniqueness of the SQL server created by appending one unique string in its name (defined in the `sql_server.name` parameter). ## Deploy the template Once parameter file is edited you can deploy it using [create-resources script](../readme.md). - i. e. if you are in windows, to deploy sql databases in a new resourcegroup located in westus, go to `deploy\az` folder and type: ``` @@ -31,3 +33,4 @@ create-resources.cmd sql\sqldeploy newResourceGroup -c westus + diff --git a/deploy/az/sql/sqldeploy.json b/deploy/az/sql/sqldeploy.json index c4b9dca20..f3880e7b8 100644 --- a/deploy/az/sql/sqldeploy.json +++ b/deploy/az/sql/sqldeploy.json @@ -5,12 +5,17 @@ "sql_server": { "type": "object" }, - "suffix": { + "admin": { + "type": "string" + }, + "adminpwd": { "type": "string" } }, "variables": { - "sql_server_name": "[concat(parameters('sql_server').name, '-', parameters('suffix'))]" + "sql_server_name": "[concat(parameters('sql_server').name, '-', uniqueString(resourceGroup().id))]", + "admin": "[parameters('admin')]", + "adminpwd": "[parameters('adminpwd')]" }, "resources": [ { @@ -19,8 +24,8 @@ "apiVersion": "2014-04-01-preview", "location": "[resourceGroup().location]", "properties": { - "administratorLogin": "[parameters('sql_server').admin]", - "administratorLoginPassword": "[parameters('sql_server').adminpwd]", + "administratorLogin": "[variables('admin')]", + "administratorLoginPassword": "[variables('adminpwd')]", "version": "12.0" }, "resources": [ diff --git a/deploy/az/sql/sqldeploy.parameters.json b/deploy/az/sql/sqldeploy.parameters.json index 5b0dfdbae..473cf08cd 100644 --- a/deploy/az/sql/sqldeploy.parameters.json +++ b/deploy/az/sql/sqldeploy.parameters.json @@ -4,9 +4,7 @@ "parameters": { "sql_server": { "value": { - "name": "eshop-sqlsrv", - "admin": "eshop", - "adminpwd": "Pass@word", + "name": "eshopsql", "dbs": { "ordering": "orderingdb", "identity": "identitydb", @@ -14,8 +12,11 @@ } } }, - "suffix": { - "value": "edu" + "admin": { + "value": null + }, + "adminpwd": { + "value": null } } -} +} \ No newline at end of file From 0473a972252a4f164d724437c634cd02793b5947 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Mon, 29 May 2017 12:42:51 +0200 Subject: [PATCH 45/60] change the "AzureRedisEnabled" condition to configure declaration --- src/Services/Basket/Basket.API/Startup.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index f2f5afc91..79adb1618 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -50,7 +50,14 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API options.Filters.Add(typeof(HttpGlobalExceptionFilter)); }).AddControllersAsServices(); - services.Configure(Configuration); + services.Configure(options => + { + Configuration.Bind(options); + if (Configuration.GetValue("AzureRedisEnabled")) + { + options.ConnectionString = Configuration["AzureRedisConnectionString"]; + } + }); //By connecting here we are making sure that our service //cannot start until redis is ready. This might slow down startup, @@ -61,11 +68,6 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API services.AddSingleton(sp => { var settings = sp.GetRequiredService>().Value; - if (Configuration.GetValue("AzureRedisEnabled")) - { - settings.ConnectionString = Configuration["AzureRedisConnectionString"]; - } - ConfigurationOptions configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); configuration.ResolveDns = true; From 2d4f9d332360ae2b35f051b65d9631dc1128d1af Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Mon, 29 May 2017 15:42:09 +0200 Subject: [PATCH 46/60] Add ESHOP_AZURE_SERVICE_BUS variable from .env with default value --- docker-compose.override.yml | 8 ++++---- docker-compose.prod.yml | 8 ++++---- docker-compose.vs.debug.yml | 2 +- docker-compose.vs.release.yml | 2 +- docker-compose.yml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 04d1c4d9c..3d63a5547 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' # 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: @@ -14,7 +14,7 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=basket.data - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - - EventBusConnection=rabbitmq + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5103:80" @@ -24,7 +24,7 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word - ExternalCatalogBaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - - EventBusConnection=rabbitmq + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5101:80" @@ -45,7 +45,7 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - - EventBusConnection=rabbitmq + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5102:80" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index c5d8839ea..30a8c764f 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' # 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: @@ -19,7 +19,7 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=basket.data - identityUrl=http://identity.api #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. - - EventBusConnection=rabbitmq + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5103:80" @@ -29,7 +29,7 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word - ExternalCatalogBaseUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5101 #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. - - EventBusConnection=rabbitmq + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5101:80" @@ -50,7 +50,7 @@ services: - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word - identityUrl=http://identity.api #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. - - EventBusConnection=rabbitmq + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} ports: - "5102:80" diff --git a/docker-compose.vs.debug.yml b/docker-compose.vs.debug.yml index 2e7145637..413940bef 100644 --- a/docker-compose.vs.debug.yml +++ b/docker-compose.vs.debug.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: diff --git a/docker-compose.vs.release.yml b/docker-compose.vs.release.yml index d1ca5b2c6..6637b71b5 100644 --- a/docker-compose.vs.release.yml +++ b/docker-compose.vs.release.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: diff --git a/docker-compose.yml b/docker-compose.yml index 09212da8e..6a0953706 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: From 64b9ea6f7908e2613183344750f425a9dd0ab6a2 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Mon, 29 May 2017 15:42:59 +0200 Subject: [PATCH 47/60] Redis deploy ARM template and doc --- deploy/az/redis/readme.md | 31 +++++++++++++++ deploy/az/redis/redisdeploy.json | 42 +++++++++++++++++++++ deploy/az/redis/redisdeploy.parameters.json | 9 +++++ deploy/readme.md | 1 + 4 files changed, 83 insertions(+) create mode 100644 deploy/az/redis/readme.md create mode 100644 deploy/az/redis/redisdeploy.json create mode 100644 deploy/az/redis/redisdeploy.parameters.json diff --git a/deploy/az/redis/readme.md b/deploy/az/redis/readme.md new file mode 100644 index 000000000..093a9af14 --- /dev/null +++ b/deploy/az/redis/readme.md @@ -0,0 +1,31 @@ +# Deploying Redis Cache + +The ARM template `redisdeploy.json` and its parameter file (`redisdeploy.parameters.json`) are used to deploy following resources: + +1. One Redis Cache + +## Editing sbusdeploy.parameters.json file + +You can edit the `redisdeploy.parameters.parameters.json` file to set your values, but is not needed. The only parameter than can +be set is: + +1. `namespaceprefix` is a string that is used to create the Redis namespace. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value. + +## Deploy the template + +Once parameter file is edited you can deploy it using [create-resources script](../readme.md). + +i. e. if you are in windows, to deploy sql databases in a new resourcegroup located in westus, go to `deploy\az` folder and type: + +``` +create-resources.cmd redis\redisdeploy newResourceGroup -c westus +``` + + + + + + + + + diff --git a/deploy/az/redis/redisdeploy.json b/deploy/az/redis/redisdeploy.json new file mode 100644 index 000000000..04b53a3b6 --- /dev/null +++ b/deploy/az/redis/redisdeploy.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "namespaceprefix": { + "type": "string", + "metadata": { + "description": "Name of the Redis namespace" + } + } + }, + "variables": { + "location": "[resourceGroup().location]", + "namespaceprefix": "[concat(parameters('namespaceprefix'), uniqueString(resourceGroup().id))]", + "sbVersion": "2016-04-01" + }, + "resources": [ + { + "type": "Microsoft.Cache/Redis", + "name": "[variables('namespaceprefix')]", + "apiVersion": "[variables('sbVersion')]", + "location": "[variables('location')]", + "scale": null, + "properties": { + "redisVersion": "3.2.7", + "sku": { + "name": "Standard", + "family": "C", + "capacity": 1 + }, + "enableNonSslPort": true, + "redisConfiguration": { + "maxclients": "1000", + "maxmemory-reserved": "50", + "maxfragmentationmemory-reserved": "50", + "maxmemory-policy": "volatile-lru", + "maxmemory-delta": "50" + } + } + } + ] +} \ No newline at end of file diff --git a/deploy/az/redis/redisdeploy.parameters.json b/deploy/az/redis/redisdeploy.parameters.json new file mode 100644 index 000000000..42d2e470e --- /dev/null +++ b/deploy/az/redis/redisdeploy.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "namespaceprefix": { + "value": "eshopredis" + } + } +} \ No newline at end of file diff --git a/deploy/readme.md b/deploy/readme.md index a9520e1f7..7d760c6bd 100644 --- a/deploy/readme.md +++ b/deploy/readme.md @@ -19,6 +19,7 @@ Using `docker-machine` is the recommended way to create a VM with docker install 1. [Deploying SQL Server and databases](az/sql/readme.md) 2. [Deploying Azure Service Bus](az/servicebus/readme.md) +3. [Deploying Redis Cache](az/redis/readme.md) From e309d97d18c53959ce94a636e7ea1905564ed14d Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Mon, 29 May 2017 16:03:51 +0200 Subject: [PATCH 48/60] remove AzureRedisConnectionString variable from settings --- src/Services/Basket/Basket.API/appsettings.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index 43f70e202..3a5b1b0b9 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -7,8 +7,5 @@ "Microsoft": "Information" } }, - "IdentityUrl": "http://localhost:5105", - "ConnectionString": "127.0.0.1", - "AzureRedisConnectionString": "eshoponazure.redis.cache.windows.net:6379,password=I9t4YmytcxvAjThGz98oUbfcI0Zcu7sIB2nhmmDxjVo=,ssl=false,abortConnect=false", - "AzureRedisEnabled": "true" + "IdentityUrl": "http://localhost:5105" } From 6b480e3d41f6eaaf8737ff20752dd624c6007185 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Mon, 29 May 2017 16:04:35 +0200 Subject: [PATCH 49/60] Apply ConnectionString changes (remove condition) --- src/Services/Basket/Basket.API/Startup.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 79adb1618..dd20b9353 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -50,14 +50,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API options.Filters.Add(typeof(HttpGlobalExceptionFilter)); }).AddControllersAsServices(); - services.Configure(options => - { - Configuration.Bind(options); - if (Configuration.GetValue("AzureRedisEnabled")) - { - options.ConnectionString = Configuration["AzureRedisConnectionString"]; - } - }); + services.Configure(Configuration); //By connecting here we are making sure that our service //cannot start until redis is ready. This might slow down startup, From 45ed8a60ad87c0da8f84f93aae143dce7e9c8bcc Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Tue, 30 May 2017 17:14:28 +0200 Subject: [PATCH 50/60] Add PictureFileName field for saving the name of the file. PictureUri will be the url of the image (api or azure storage) --- .../Infrastructure/CatalogContext.cs | 4 +- .../Infrastructure/CatalogContextSeed.cs | 24 ++--- ...70530133114_AddPictureFileName.Designer.cs | 99 +++++++++++++++++++ .../20170530133114_AddPictureFileName.cs | 25 +++++ .../CatalogContextModelSnapshot.cs | 2 +- .../Catalog/Catalog.API/Model/CatalogItem.cs | 2 + 6 files changed, 142 insertions(+), 14 deletions(-) create mode 100644 src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.Designer.cs create mode 100644 src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.cs diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs index cd26632e0..f58541b62 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs @@ -36,9 +36,11 @@ builder.Property(ci => ci.Price) .IsRequired(true); - builder.Property(ci => ci.PictureUri) + builder.Property(ci => ci.PictureFileName) .IsRequired(false); + builder.Ignore(ci => ci.PictureUri); + builder.HasOne(ci => ci.CatalogBrand) .WithMany() .HasForeignKey(ci => ci.CatalogBrandId); diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs index 5f2370fb6..e6bb1dafe 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs @@ -70,18 +70,18 @@ { return new List() { - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/1" }, - new CatalogItem() { CatalogTypeId=1,CatalogBrandId=2, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/2" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/3" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/4" }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=5, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/5" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/6" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/7" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/8" }, - new CatalogItem() { CatalogTypeId=1,CatalogBrandId=5, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/9" }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/10" }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/11" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/12" } + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureFileName = "1.png" }, + new CatalogItem() { CatalogTypeId=1,CatalogBrandId=2, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureFileName = "2.png" }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureFileName = "3.png" }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureFileName = "4.png" }, + new CatalogItem() { CatalogTypeId=3,CatalogBrandId=5, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureFileName = "5.png" }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureFileName = "6.png" }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureFileName = "7.png" }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureFileName = "8.png" }, + new CatalogItem() { CatalogTypeId=1,CatalogBrandId=5, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureFileName = "9.png" }, + new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureFileName = "10.png" }, + new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureFileName = "11.png" }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureFileName = "12.png" }, }; } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.Designer.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.Designer.cs new file mode 100644 index 000000000..ebfabd154 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.Designer.cs @@ -0,0 +1,99 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; + +namespace Catalog.API.Infrastructure.Migrations +{ + [DbContext(typeof(CatalogContext))] + [Migration("20170530133114_AddPictureFile")] + partial class AddPictureFile + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.1") + .HasAnnotation("SqlServer:Sequence:.catalog_brand_hilo", "'catalog_brand_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.catalog_hilo", "'catalog_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "catalog_brand_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Brand") + .IsRequired() + .HasMaxLength(100); + + b.HasKey("Id"); + + b.ToTable("CatalogBrand"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "catalog_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("CatalogBrandId"); + + b.Property("CatalogTypeId"); + + b.Property("Description"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50); + + b.Property("PictureFile"); + + b.Property("Price"); + + b.HasKey("Id"); + + b.HasIndex("CatalogBrandId"); + + b.HasIndex("CatalogTypeId"); + + b.ToTable("Catalog"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "catalog_type_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Type") + .IsRequired() + .HasMaxLength(100); + + b.HasKey("Id"); + + b.ToTable("CatalogType"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", "CatalogBrand") + .WithMany() + .HasForeignKey("CatalogBrandId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", "CatalogType") + .WithMany() + .HasForeignKey("CatalogTypeId") + .OnDelete(DeleteBehavior.Cascade); + }); + } + } +} diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.cs new file mode 100644 index 000000000..fc7f4dc8d --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Catalog.API.Infrastructure.Migrations +{ + public partial class AddPictureFile : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "PictureUri", + table: "Catalog", + newName: "PictureFileName"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "PictureFileName", + table: "Catalog", + newName: "PictureUri"); + } + } +} diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/CatalogContextModelSnapshot.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/CatalogContextModelSnapshot.cs index ba1151672..020ef3de2 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/CatalogContextModelSnapshot.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/CatalogContextModelSnapshot.cs @@ -52,7 +52,7 @@ namespace Catalog.API.Infrastructure.Migrations .IsRequired() .HasMaxLength(50); - b.Property("PictureUri"); + b.Property("PictureFileName"); b.Property("Price"); diff --git a/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs b/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs index a232cb2fe..8e7bb5d21 100644 --- a/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs +++ b/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs @@ -12,6 +12,8 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model public decimal Price { get; set; } + public string PictureFileName { get; set; } + public string PictureUri { get; set; } public int CatalogTypeId { get; set; } From 1a385a21791a181a19fda7596610732f917c4740 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Tue, 30 May 2017 17:16:17 +0200 Subject: [PATCH 51/60] Add AzureStorageEnabled environment variable to get the origin of the product image from PicBaseUrl environment variable --- .../Catalog/Catalog.API/CatalogSettings.cs | 4 ++- .../Controllers/CatalogController.cs | 13 ++++--- .../Catalog.API/Controllers/PicController.cs | 34 +++++++++++++++---- .../Catalog/Catalog.API/settings.json | 3 +- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/Services/Catalog/Catalog.API/CatalogSettings.cs b/src/Services/Catalog/Catalog.API/CatalogSettings.cs index 62e92c6ce..03bb584f3 100644 --- a/src/Services/Catalog/Catalog.API/CatalogSettings.cs +++ b/src/Services/Catalog/Catalog.API/CatalogSettings.cs @@ -2,10 +2,12 @@ { public class CatalogSettings { - public string ExternalCatalogBaseUrl {get;set;} + public string PicBaseUrl { get;set;} public string EventBusConnection { get; set; } public string ServiceBusConnectionString { get; set; } + + public bool AzureStorageEnabled { get; set; } } } diff --git a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs index 374d8ec7c..ca1ef9e3b 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs @@ -200,7 +200,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers CatalogTypeId = product.CatalogTypeId, Description = product.Description, Name = product.Name, - PictureUri = product.PictureUri, + PictureFileName = product.PictureFileName, Price = product.Price }; _catalogContext.CatalogItems.Add(item); @@ -231,11 +231,14 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers private List ChangeUriPlaceholder(List items) { - var baseUri = _settings.ExternalCatalogBaseUrl; - - items.ForEach(x => + var baseUri = _settings.PicBaseUrl; + + items.ForEach(catalogItem => { - x.PictureUri = x.PictureUri.Replace("http://externalcatalogbaseurltobereplaced", baseUri); + catalogItem.PictureUri = _settings.AzureStorageEnabled + ? baseUri + catalogItem.PictureFileName + : baseUri + catalogItem.Id; + }); return items; diff --git a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs index 8d8aaf9f2..a2106bead 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs @@ -1,6 +1,9 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; using System.IO; +using System.Threading.Tasks; // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 @@ -10,21 +13,38 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers public class PicController : Controller { private readonly IHostingEnvironment _env; - public PicController(IHostingEnvironment env) + private readonly CatalogContext _catalogContext; + + public PicController(IHostingEnvironment env, + CatalogContext catalogContext) { _env = env; + _catalogContext = catalogContext; } [HttpGet("{id}")] // GET: // - public IActionResult GetImage(int id) + public async Task GetImage(int id) { - var webRoot = _env.WebRootPath; - var path = Path.Combine(webRoot, id + ".png"); + if (id <= 0) + { + return BadRequest(); + } + + var item = await _catalogContext.CatalogItems + .SingleOrDefaultAsync(ci => ci.Id == id); + + if (item != null) + { + var webRoot = _env.WebRootPath; + var path = Path.Combine(webRoot, item.PictureFileName); + + var buffer = System.IO.File.ReadAllBytes(path); + + return File(buffer, "image/png"); + } - var buffer = System.IO.File.ReadAllBytes(path); - - return File(buffer, "image/png"); + return NotFound(); } } } diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index 3cfe64f5e..b431cf8f0 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -1,6 +1,6 @@ { "ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word", - "ExternalCatalogBaseUrl": "http://localhost:5101", + "PicBaseUrl": "http://localhost:5101", "Logging": { "IncludeScopes": false, "LogLevel": { @@ -11,5 +11,6 @@ }, "ServiceBusConnectionString": "Endpoint=sb://eshopsbez55a72p6wm62.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=oA6WpfCfCbScZbQa/DBOLfwl6oi5ezPsCYL7QsTb4PY=;EntityPath=eshop_event_bus", "AzureServiceBusEnabled": "true", + "AzureStorageEnabled": false, "SubscriptionClientName": "Catalog" } From 9866aae07c03d42c72ccfc574ab94e491942291b Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Tue, 30 May 2017 17:24:46 +0200 Subject: [PATCH 52/60] Change version of docker-compose from 2 to 2.1 for default values. I set "http://localhost:5101/api/v1/pic/" because docker-compose doesn't allow to declare another variable such as default value --- docker-compose.override.yml | 4 ++-- docker-compose.vs.debug.yml | 2 +- docker-compose.vs.release.yml | 2 +- docker-compose.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 04d1c4d9c..945accc67 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' # 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: @@ -23,7 +23,7 @@ services: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word - - ExternalCatalogBaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. + - PicBaseUrl=${ESHOP_AZURE_STORAGE_ACCOUNT:-http://localhost:5101/api/v1/pic/} #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - EventBusConnection=rabbitmq ports: - "5101:80" diff --git a/docker-compose.vs.debug.yml b/docker-compose.vs.debug.yml index 2e7145637..413940bef 100644 --- a/docker-compose.vs.debug.yml +++ b/docker-compose.vs.debug.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: diff --git a/docker-compose.vs.release.yml b/docker-compose.vs.release.yml index d1ca5b2c6..6637b71b5 100644 --- a/docker-compose.vs.release.yml +++ b/docker-compose.vs.release.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: diff --git a/docker-compose.yml b/docker-compose.yml index 09212da8e..6a0953706 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: From 2cad62d642905979f3f9be9ded769d966c230548 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Tue, 30 May 2017 17:30:01 +0200 Subject: [PATCH 53/60] Add ESHOP_AZURE_REDIS variable from .env with default value --- docker-compose.override.yml | 4 ++-- docker-compose.prod.yml | 4 ++-- docker-compose.vs.debug.yml | 2 +- docker-compose.vs.release.yml | 2 +- docker-compose.yml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 04d1c4d9c..c5666d6fa 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' # 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: @@ -12,7 +12,7 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=basket.data + - ConnectionString=${ESHOP_AZURE_REDIS:-basket.data} - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - EventBusConnection=rabbitmq ports: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index c5d8839ea..739d4f218 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' # 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: @@ -17,7 +17,7 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - - ConnectionString=basket.data + - ConnectionString=${ESHOP_AZURE_REDIS:-basket.data} - identityUrl=http://identity.api #Local: You need to open your host's firewall at range 5100-5105. at range 5100-5105. - EventBusConnection=rabbitmq ports: diff --git a/docker-compose.vs.debug.yml b/docker-compose.vs.debug.yml index 2e7145637..413940bef 100644 --- a/docker-compose.vs.debug.yml +++ b/docker-compose.vs.debug.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: diff --git a/docker-compose.vs.release.yml b/docker-compose.vs.release.yml index d1ca5b2c6..6637b71b5 100644 --- a/docker-compose.vs.release.yml +++ b/docker-compose.vs.release.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: diff --git a/docker-compose.yml b/docker-compose.yml index 09212da8e..6a0953706 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: basket.api: From 7694602be247c7d1a1d198e290b620d0e6cb1f70 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Tue, 30 May 2017 17:53:15 +0200 Subject: [PATCH 54/60] Rename property PictureFile to PictureFileName in Migration Designer --- .../20170530133114_AddPictureFileName.Designer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.Designer.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.Designer.cs index ebfabd154..23c0e5344 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.Designer.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogMigrations/20170530133114_AddPictureFileName.Designer.cs @@ -53,7 +53,7 @@ namespace Catalog.API.Infrastructure.Migrations .IsRequired() .HasMaxLength(50); - b.Property("PictureFile"); + b.Property("PictureFileName"); b.Property("Price"); From 83ae0d48fcee2da667290d3d3d425571bffdf6b5 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Tue, 30 May 2017 17:56:36 +0200 Subject: [PATCH 55/60] remove ServiceBusConnectionString variable from appsettings.json --- src/Services/Basket/Basket.API/BasketSettings.cs | 2 -- src/Services/Basket/Basket.API/appsettings.json | 1 - src/Services/Catalog/Catalog.API/CatalogSettings.cs | 2 -- src/Services/Catalog/Catalog.API/settings.json | 1 - src/Services/Ordering/Ordering.API/settings.json | 1 - 5 files changed, 7 deletions(-) diff --git a/src/Services/Basket/Basket.API/BasketSettings.cs b/src/Services/Basket/Basket.API/BasketSettings.cs index 721461a1c..9d143545a 100644 --- a/src/Services/Basket/Basket.API/BasketSettings.cs +++ b/src/Services/Basket/Basket.API/BasketSettings.cs @@ -5,7 +5,5 @@ public string ConnectionString { get; set; } public string EventBusConnection { get; set; } - - public string ServiceBusConnectionString { get; set; } } } diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index 718639474..6d49d9475 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -9,7 +9,6 @@ }, "IdentityUrl": "http://localhost:5105", "ConnectionString": "127.0.0.1", - "ServiceBusConnectionString": "Endpoint=sb://eshopsbez55a72p6wm62.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=oA6WpfCfCbScZbQa/DBOLfwl6oi5ezPsCYL7QsTb4PY=;EntityPath=eshop_event_bus", "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Basket" } \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/CatalogSettings.cs b/src/Services/Catalog/Catalog.API/CatalogSettings.cs index 62e92c6ce..af6e0ab13 100644 --- a/src/Services/Catalog/Catalog.API/CatalogSettings.cs +++ b/src/Services/Catalog/Catalog.API/CatalogSettings.cs @@ -5,7 +5,5 @@ public string ExternalCatalogBaseUrl {get;set;} public string EventBusConnection { get; set; } - - public string ServiceBusConnectionString { get; set; } } } diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index 3cfe64f5e..82bbc4c1d 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -9,7 +9,6 @@ "Microsoft": "Information" } }, - "ServiceBusConnectionString": "Endpoint=sb://eshopsbez55a72p6wm62.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=oA6WpfCfCbScZbQa/DBOLfwl6oi5ezPsCYL7QsTb4PY=;EntityPath=eshop_event_bus", "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Catalog" } diff --git a/src/Services/Ordering/Ordering.API/settings.json b/src/Services/Ordering/Ordering.API/settings.json index 1270a34f6..00970cbec 100644 --- a/src/Services/Ordering/Ordering.API/settings.json +++ b/src/Services/Ordering/Ordering.API/settings.json @@ -9,7 +9,6 @@ "Microsoft": "Information" } }, - "ServiceBusConnectionString": "Endpoint=sb://eshopsbez55a72p6wm62.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=oA6WpfCfCbScZbQa/DBOLfwl6oi5ezPsCYL7QsTb4PY=;EntityPath=eshop_event_bus", "AzureServiceBusEnabled": "true", "SubscriptionClientName": "Ordering" } From 18167186c9b3f5ed3b616cb9e73f33a05be56dab Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Tue, 30 May 2017 17:59:57 +0200 Subject: [PATCH 56/60] Apply EventBusConnectionChanges --- src/Services/Basket/Basket.API/Startup.cs | 2 +- src/Services/Basket/Basket.API/appsettings.json | 2 +- src/Services/Catalog/Catalog.API/Startup.cs | 2 +- src/Services/Catalog/Catalog.API/settings.json | 2 +- src/Services/Ordering/Ordering.API/Startup.cs | 2 +- src/Services/Ordering/Ordering.API/settings.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 9c975d4ff..ea4c8cad4 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -79,7 +79,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API var settings = sp.GetRequiredService>().Value; var logger = sp.GetRequiredService>(); - var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnectionString); + var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.EventBusConnection); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index 6d49d9475..f062f76d7 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -9,6 +9,6 @@ }, "IdentityUrl": "http://localhost:5105", "ConnectionString": "127.0.0.1", - "AzureServiceBusEnabled": "true", + "AzureServiceBusEnabled": false, "SubscriptionClientName": "Basket" } \ 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 25255cbaa..edc63c29d 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -118,7 +118,7 @@ var settings = sp.GetRequiredService>().Value; var logger = sp.GetRequiredService>(); - var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.ServiceBusConnectionString); + var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.EventBusConnection); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); }); diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index 82bbc4c1d..29d7240f6 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -9,6 +9,6 @@ "Microsoft": "Information" } }, - "AzureServiceBusEnabled": "true", + "AzureServiceBusEnabled": false, "SubscriptionClientName": "Catalog" } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 7728725c1..9116a3ad2 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -121,7 +121,7 @@ { var logger = sp.GetRequiredService>(); - var serviceBusConnectionString = Configuration["ServiceBusConnectionString"]; + var serviceBusConnectionString = Configuration["EventBusConnection"]; var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); diff --git a/src/Services/Ordering/Ordering.API/settings.json b/src/Services/Ordering/Ordering.API/settings.json index 00970cbec..9f1c58322 100644 --- a/src/Services/Ordering/Ordering.API/settings.json +++ b/src/Services/Ordering/Ordering.API/settings.json @@ -9,6 +9,6 @@ "Microsoft": "Information" } }, - "AzureServiceBusEnabled": "true", + "AzureServiceBusEnabled": false, "SubscriptionClientName": "Ordering" } From 4d07fecc3b026be68b795b6a29531a04a056ab54 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Tue, 30 May 2017 18:35:09 +0200 Subject: [PATCH 57/60] fix merge error --- src/Services/Basket/Basket.API/Startup.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 0888fad6c..a5b5a35aa 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -18,6 +18,8 @@ using Microsoft.Extensions.Options; using RabbitMQ.Client; using System.Threading.Tasks; using StackExchange.Redis; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +using Microsoft.Azure.ServiceBus; namespace Microsoft.eShopOnContainers.Services.Basket.API { From 9979f1af9694e65865c2b941e782ad129f6c936e Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Fri, 16 Jun 2017 12:14:29 +0200 Subject: [PATCH 58/60] Deploy storage --- deploy/az/storage/deploystorage.json | 91 +++++++++++++++++++ .../az/storage/deploystorage.parameters.json | 12 +++ 2 files changed, 103 insertions(+) create mode 100644 deploy/az/storage/deploystorage.json create mode 100644 deploy/az/storage/deploystorage.parameters.json diff --git a/deploy/az/storage/deploystorage.json b/deploy/az/storage/deploystorage.json new file mode 100644 index 000000000..e3fced6b2 --- /dev/null +++ b/deploy/az/storage/deploystorage.json @@ -0,0 +1,91 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "catalogstorage": { + "type": "string" + }, + "profileName" : { + "type": "string" + } + }, + "variables": { + "catalogstorage": "[concat(parameters('catalogstorage'), uniqueString(resourceGroup().id))]", + "endpointName": "[concat('endpoint-', uniqueString(resourceGroup().id))]", + "profileName": "[parameters('profileName')]" + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "name": "[variables('catalogstorage')]", + "apiVersion": "2016-01-01", + "location": "[resourceGroup().location]", + "tags": { + "displayName": "[variables('catalogstorage')]" + }, + "sku": { + "name": "Standard_LRS" + }, + "kind": "Storage" + }, + { + "name": "[variables('profileName')]", + "type": "Microsoft.Cdn/profiles", + "location": "[resourceGroup().location]", + "apiVersion": "2016-04-02", + "tags": { + "displayName": "[variables('profileName')]" + }, + "sku": { + "name": "Standard_Verizon" + }, + "resources": [ + { + "apiVersion": "2016-04-02", + "name": "[variables('endpointName')]", + "type": "endpoints", + "dependsOn": [ + "[variables('profileName')]", + "[variables('catalogstorage')]" + ], + "location": "[resourceGroup().location]", + "tags": { + "displayName": "[variables('endpointName')]" + }, + "properties": { + "originHostHeader": "[replace(replace(reference(resourceId('Microsoft.Storage/storageAccounts', variables('catalogstorage')),'2015-06-15' ).primaryEndpoints.blob,'https://',''),'/','')]", + "isHttpAllowed": true, + "isHttpsAllowed": true, + "queryStringCachingBehavior": "IgnoreQueryString", + "contentTypesToCompress": [ + "text/plain", + "text/html", + "text/css", + "application/x-javascript", + "text/javascript" + ], + "isCompressionEnabled": "True", + "origins": [ + { + "name": "origin1", + "properties": { + "hostName": "[replace(replace(reference(resourceId('Microsoft.Storage/storageAccounts', variables('catalogstorage')),'2015-06-15' ).primaryEndpoints.blob,'https://',''),'/','')]" + } + } + ] + } + } + ] + } + ], + "outputs": { + "hostName": { + "type": "string", + "value": "[reference(resourceId('Microsoft.cdn/profiles/endpoints', variables('profileName'), variables('endpointName'))).hostName]" + }, + "originHostHeader": { + "type": "string", + "value": "[reference(resourceId('Microsoft.cdn/profiles/endpoints', variables('profileName'), variables('endpointName'))).originHostHeader]" + } + } +} \ No newline at end of file diff --git a/deploy/az/storage/deploystorage.parameters.json b/deploy/az/storage/deploystorage.parameters.json new file mode 100644 index 000000000..2c5256a09 --- /dev/null +++ b/deploy/az/storage/deploystorage.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "catalogstorage": { + "value": "catalog" + }, + "profileName":{ + "value": "eshopcatalog" + } + } +} \ No newline at end of file From 9f6216b7a386d525f75058ac74562a4a22b20e81 Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Fri, 16 Jun 2017 13:14:14 +0200 Subject: [PATCH 59/60] Update to resources deployed: - SQL (marketingdb) - CosmosDb --- deploy/az/cosmos/deploycosmos.json | 32 +++++++++++++++++++ deploy/az/cosmos/deploycosmos.parameters.json | 9 ++++++ deploy/az/sql/sqldeploy.json | 15 +++++++++ deploy/az/sql/sqldeploy.parameters.json | 3 +- 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 deploy/az/cosmos/deploycosmos.json create mode 100644 deploy/az/cosmos/deploycosmos.parameters.json diff --git a/deploy/az/cosmos/deploycosmos.json b/deploy/az/cosmos/deploycosmos.json new file mode 100644 index 000000000..8c03983a2 --- /dev/null +++ b/deploy/az/cosmos/deploycosmos.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "type": "String" + } + }, + "variables": { + "name": "[concat(parameters('name'), uniqueString(resourceGroup().id))]", + "location":"[resourceGroup().location]" + }, + "resources": [ + { + "type": "Microsoft.DocumentDb/databaseAccounts", + "kind": "MongoDB", + "name": "[variables('name')]", + "apiVersion": "2015-04-08", + "location": "[variables('location')]", + "properties": { + "databaseAccountOfferType": "Standard", + "locations": [ + { + "id": "[concat(variables('name'), '-', variables('location'))]", + "failoverPriority": 0, + "locationName": "[variables('location')]" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/deploy/az/cosmos/deploycosmos.parameters.json b/deploy/az/cosmos/deploycosmos.parameters.json new file mode 100644 index 000000000..725bb7cf9 --- /dev/null +++ b/deploy/az/cosmos/deploycosmos.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "eshop-nosql" + } + } +} \ No newline at end of file diff --git a/deploy/az/sql/sqldeploy.json b/deploy/az/sql/sqldeploy.json index f3880e7b8..397c94ad6 100644 --- a/deploy/az/sql/sqldeploy.json +++ b/deploy/az/sql/sqldeploy.json @@ -74,6 +74,21 @@ "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" ] }, + { + "type": "databases", + "name": "[parameters('sql_server').dbs.marketing]", + "apiVersion": "2014-04-01-preview", + "location": "[resourceGroup().location]", + "properties": { + "edition": "Standard", + "collation": "SQL_Latin1_General_CP1_CI_AS", + "maxSizeBytes": "1073741824", + "requestedServiceObjectiveName": "S1" + }, + "dependsOn": [ + "[concat('Microsoft.Sql/servers/', variables('sql_server_name'))]" + ] + }, { "type": "firewallrules", "name": "AllowAllWindowsAzureIps", diff --git a/deploy/az/sql/sqldeploy.parameters.json b/deploy/az/sql/sqldeploy.parameters.json index 473cf08cd..982e78f4c 100644 --- a/deploy/az/sql/sqldeploy.parameters.json +++ b/deploy/az/sql/sqldeploy.parameters.json @@ -8,7 +8,8 @@ "dbs": { "ordering": "orderingdb", "identity": "identitydb", - "catalog": "catalogdb" + "catalog": "catalogdb", + "marketing": "marketingdb" } } }, From a56f99f6848b04810f86f2652bf7d5a33ac71aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Mon, 26 Jun 2017 18:05:02 +0200 Subject: [PATCH 60/60] Fix merge --- eShopOnContainers-ServicesAndWebApps.sln | 51 +----------------- .../EventBus/EventBus/EventBus.csproj | 1 + .../EventBusServiceBus/EventBusServiceBus.cs | 54 ++++++++++++++----- src/Services/Basket/Basket.API/Startup.cs | 3 +- .../Infrastructure/CatalogContextSeed.cs | 26 ++++----- src/Services/Catalog/Catalog.API/Startup.cs | 3 +- .../Catalog/Catalog.API/settings.json | 2 +- src/Services/Ordering/Ordering.API/Startup.cs | 4 +- 8 files changed, 64 insertions(+), 80 deletions(-) diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index a9f611b2b..19ecd4787 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.26430.12 +VisualStudioVersion = 15.0.26430.13 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}" EndProject @@ -1264,54 +1264,6 @@ Global {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|x64.Build.0 = Release|Any CPU {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|x86.ActiveCfg = Release|Any CPU {DF395F85-B010-465D-857A-7EBCC512C0C2}.Release|x86.Build.0 = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|ARM.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|iPhone.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|x64.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|x64.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|x86.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.AppStore|x86.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|ARM.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|ARM.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|iPhone.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|x64.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|x64.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|x86.ActiveCfg = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Debug|x86.Build.0 = Debug|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|Any CPU.Build.0 = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|ARM.ActiveCfg = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|ARM.Build.0 = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|iPhone.ActiveCfg = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|iPhone.Build.0 = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x64.ActiveCfg = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x64.Build.0 = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.ActiveCfg = Release|Any CPU - {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.Build.0 = Release|Any CPU {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU @@ -1406,5 +1358,6 @@ Global {23A33F9B-7672-426D-ACF9-FF8436ADC81A} = {88B22DBB-AA8F-4290-A454-2C109352C345} {A5260DE0-1FDD-467E-9CC1-A028AB081CEE} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {DF395F85-B010-465D-857A-7EBCC512C0C2} = {A5260DE0-1FDD-467E-9CC1-A028AB081CEE} + {69AF10D3-AA76-4FF7-B187-EC7E8CC5F5B8} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} EndGlobalSection EndGlobal diff --git a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj index 37aeb8d1f..fe7e35d98 100644 --- a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj +++ b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj @@ -10,6 +10,7 @@ + diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs index b71945aba..24c5fba39 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs @@ -11,17 +11,21 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using System.Reflection; using Microsoft.Azure.ServiceBus.Filters; + using Autofac; + using Newtonsoft.Json.Linq; public class EventBusServiceBus : IEventBus { private readonly IServiceBusPersisterConnection _serviceBusPersisterConnection; - private ServiceBusConnectionStringBuilder _serviceBusConnectionStringBuilder; private readonly ILogger _logger; private readonly IEventBusSubscriptionsManager _subsManager; private readonly SubscriptionClient _subscriptionClient; - + private readonly ILifetimeScope _autofac; + private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus"; + public EventBusServiceBus(IServiceBusPersisterConnection serviceBusPersisterConnection, - ILogger logger, IEventBusSubscriptionsManager subsManager, string subscriptionClientName) + ILogger logger, IEventBusSubscriptionsManager subsManager, string subscriptionClientName, + ILifetimeScope autofac) { _serviceBusPersisterConnection = serviceBusPersisterConnection; _logger = logger; @@ -29,6 +33,7 @@ _subscriptionClient = new SubscriptionClient(serviceBusPersisterConnection.ServiceBusConnectionStringBuilder, subscriptionClientName); + _autofac = autofac; RemoveDefaultRule(); RegisterSubscriptionClientMessageHandler(); @@ -54,7 +59,13 @@ .GetResult(); } - public void Subscribe(Func handler) + public void SubscribeDynamic(string eventName) + where TH : IDynamicIntegrationEventHandler + { + _subsManager.AddDynamicSubscription(eventName); + } + + public void Subscribe() where T : IntegrationEvent where TH : IIntegrationEventHandler { @@ -76,7 +87,7 @@ } } - _subsManager.AddSubscription(handler); + _subsManager.AddSubscription(); } public void Unsubscribe() @@ -100,6 +111,12 @@ _subsManager.RemoveSubscription(); } + public void UnsubscribeDynamic(string eventName) + where TH : IDynamicIntegrationEventHandler + { + _subsManager.RemoveDynamicSubscription(eventName); + } + public void Dispose() { _subsManager.Clear(); @@ -121,15 +138,26 @@ { if (_subsManager.HasSubscriptionsForEvent(eventName)) { - var eventType = _subsManager.GetEventTypeByName(eventName); - var integrationEvent = JsonConvert.DeserializeObject(message, eventType); - var handlers = _subsManager.GetHandlersForEvent(eventName); - - foreach (var handlerfactory in handlers) + using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) { - var handler = handlerfactory.DynamicInvoke(); - var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); - await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); + var subscriptions = _subsManager.GetHandlersForEvent(eventName); + foreach (var subscription in subscriptions) + { + if (subscription.IsDynamic) + { + var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; + dynamic eventData = JObject.Parse(message); + await handler.Handle(eventData); + } + else + { + var eventType = _subsManager.GetEventTypeByName(eventName); + var integrationEvent = JsonConvert.DeserializeObject(message, eventType); + var handler = scope.ResolveOptional(subscription.HandlerType); + var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); + await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); + } + } } } } diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 61009a7dc..9ac2f9bd4 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -145,12 +145,13 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API services.AddSingleton(sp => { var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); var subscriptionClientName = Configuration["SubscriptionClientName"]; return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, subscriptionClientName); + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); }); } else diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs index 669768abd..8ebcf4036 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs @@ -70,19 +70,19 @@ { return new List() { - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/1", AvailableStock = 100}, - new CatalogItem() { CatalogTypeId=1,CatalogBrandId=2, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/2", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/3", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/4", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=5, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/5", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/6", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/7", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/8", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=1,CatalogBrandId=5, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/9", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/10", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/11", AvailableStock = 100 }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/12", AvailableStock = 100 } - }; + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, PictureFileName = "1.png", Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/1", AvailableStock = 100}, + new CatalogItem() { CatalogTypeId=1,CatalogBrandId=2, PictureFileName = "2.png", Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/2", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, PictureFileName = "3.png", Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/3", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, PictureFileName = "4.png", Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/4", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=3,CatalogBrandId=5, PictureFileName = "5.png", Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/5", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, PictureFileName = "6.png", Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/6", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, PictureFileName = "7.png", Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/7", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, PictureFileName = "8.png", Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/8", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=1,CatalogBrandId=5, PictureFileName = "9.png", Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/9", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, PictureFileName = "10.png", Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/10", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, PictureFileName = "11.png", Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/11", AvailableStock = 100 }, + new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, PictureFileName = "12.png", Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureUri = "http://externalcatalogbaseurltobereplaced/api/v1/pic/12", AvailableStock = 100 } + }; } } } diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index d4f29a693..61944ed2a 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -214,12 +214,13 @@ services.AddSingleton(sp => { var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); var subscriptionClientName = Configuration["SubscriptionClientName"]; return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, subscriptionClientName); + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); }); } diff --git a/src/Services/Catalog/Catalog.API/settings.json b/src/Services/Catalog/Catalog.API/settings.json index 1543e5fba..f21be6e5d 100644 --- a/src/Services/Catalog/Catalog.API/settings.json +++ b/src/Services/Catalog/Catalog.API/settings.json @@ -10,6 +10,6 @@ } }, "AzureServiceBusEnabled": false, - "AzureStorageEnabled": false, + "AzureStorageEnabled": true, "SubscriptionClientName": "Catalog" } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 8e4f05179..42b479685 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -178,7 +178,6 @@ }); WaitForSqlAvailabilityAsync(loggerFactory, app).Wait(); - ConfigureEventBus(app); var integrationEventLogContext = new IntegrationEventLogContext( new DbContextOptionsBuilder() @@ -219,12 +218,13 @@ services.AddSingleton(sp => { var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); var subscriptionClientName = Configuration["SubscriptionClientName"]; return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, subscriptionClientName); + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); }); } else