43 | ```
44 |
45 | ### Azure DevOps
46 |
47 | This sample uses [multi-stage YAML pipelines](https://docs.microsoft.com/azure/devops/pipelines/process/stages?view=azure-devops&tabs=yaml). To set up the sample pipeline, follow these steps:
48 |
49 | 1. Make sure that the [multi-stage pipeline preview feature](https://docs.microsoft.com/azure/devops/project/navigation/preview-features?view=azure-devops) is enabled.
50 |
51 | 1. Clone or fork the samples repository into your own repository.
52 |
53 | 1. Choose one of these steps:
54 |
55 | * Create an [Azure Resource Manager service connection](https://docs.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-azure-rm) that has the name "Azure Samples Subscription" in your project that points to the Azure subscription that you want to use for deployment.
56 |
57 | * Edit all instances of `azureSubscription: 'Azure Samples Subscription'` in the `./powershell/azure-pipelines.yml` file by using the name for an existing Azure Resource Manager service connection in your project.
58 |
59 | > [!NOTE]
60 | > To use the Azure Resource Manager service connection, make sure that the connection has selected the **Allow all pipelines to use this connection** checkbox. Otherwise, you must authorize the pipeline that you create in the next step.
61 |
62 | 1. Update these `./pipeline/azure-pipelines.yml` variables:
63 |
64 | * `groupId`: A value that's unique to you or your organization and is used to start the names for all resources and resource groups that are created
65 |
66 | * `location`: The name for the Azure region where you want to deploy the resources
67 |
68 | * `abbrevLocationName`: The abbreviated region name that's used in resource names
69 |
70 | 1. Create a new pipeline in your project that uses the `./powershell/azure-pipelines.yml` file from this sample.
71 |
72 | 
73 |
74 | ## Supporting documentation
75 |
76 | To learn more about the different parts in these samples, review these topics:
77 |
78 | * [Concepts](../concept-review.md) introduces the main concepts that underlie these samples.
79 |
80 | * [Naming convention](../naming-convention.md) describes the naming convention to use when creating the resources in these samples.
81 |
82 | * [Samples file structure and definitions](../file-definitions.md) explains the purpose for each file in these samples.
83 |
84 | * [Scaling](../api-connection-scale.md) expands on the reasons why these samples provide the capability to scale by increasing the number of copies for the logic apps deployed and organizing resources into separate resource groups.
85 |
86 | ## Created resources
87 |
88 | This sample creates these resources:
89 |
90 | TODO: add API management resource to the diagram
91 |
92 | 
93 |
94 | To learn about the scripts in this sample and how they work, review [Samples file structure and definitions](../file-definitions.md).
95 |
96 |
97 | TODO: Update descriptions to include the API management bits.
98 |
99 | This sample also implements these template and definition files:
100 |
101 | | File name | Description |
102 | |-----------|-------------|
103 | | `shared-template.json` | This template deploys the Azure function app and all its dependent resources. The `full-deploy.ps1` script not only creates Azure resources for the function app but can publish that app's source from `./sample=function`. You must publish the app first before the logic app definition can work. To run this script, you must have the Azure Function CLI installed on your computer. Remember that the `full-deploy.ps1` script is used for local execution from a development computer. The idea behind this deployment is that the function app's code gets its own CI/CD pipeline. |
104 | | `connectors-template.json` | This template provides the parameters to inject into the logic app definition but doesn't actually deploy anything. This approach is consistent with the method for injecting parameters into a logic app across the other samples. |
105 | | `logic-app-template.json` | This template creates a shell for a logic app definition, which is blank to support separating the template from the definition. |
106 | | `logic-app-definition.json` | This file defines a basic logic app that uses a timer as a trigger and calls the provided `AwesomeFunction` each time that the logic app gets triggered. |
107 | |||
108 |
109 | ## Clean up
110 |
111 | When you're done with the sample, delete the resource groups that were created by the sample. To remove all the resource groups with names that start with a specific `groupId` value, run this command from the PowerShell directory that contains this sample:
112 |
113 | ```powershell
114 | ./clean-up.ps1 -groupId
115 | ```
116 |
--------------------------------------------------------------------------------
/api-management-actions/sample-function/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # Azure Functions localsettings file
5 | # local.settings.json
6 |
7 | # User-specific files
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 | [Ll]og/
27 |
28 | # Visual Studio 2015 cache/options directory
29 | .vs/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # MSTest test Results
34 | [Tt]est[Rr]esult*/
35 | [Bb]uild[Ll]og.*
36 |
37 | # NUNIT
38 | *.VisualState.xml
39 | TestResult.xml
40 |
41 | # Build Results of an ATL Project
42 | [Dd]ebugPS/
43 | [Rr]eleasePS/
44 | dlldata.c
45 |
46 | # DNX
47 | project.lock.json
48 | project.fragment.lock.json
49 | artifacts/
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # NCrunch
117 | _NCrunch_*
118 | .*crunch*.local.xml
119 | nCrunchTemp_*
120 |
121 | # MightyMoose
122 | *.mm.*
123 | AutoTest.Net/
124 |
125 | # Web workbench (sass)
126 | .sass-cache/
127 |
128 | # Installshield output folder
129 | [Ee]xpress/
130 |
131 | # DocProject is a documentation generator add-in
132 | DocProject/buildhelp/
133 | DocProject/Help/*.HxT
134 | DocProject/Help/*.HxC
135 | DocProject/Help/*.hhc
136 | DocProject/Help/*.hhk
137 | DocProject/Help/*.hhp
138 | DocProject/Help/Html2
139 | DocProject/Help/html
140 |
141 | # Click-Once directory
142 | publish/
143 |
144 | # Publish Web Output
145 | *.[Pp]ublish.xml
146 | *.azurePubxml
147 | # TODO: Comment the next line if you want to checkin your web deploy settings
148 | # but database connection strings (with potential passwords) will be unencrypted
149 | #*.pubxml
150 | *.publishproj
151 |
152 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
153 | # checkin your Azure Web App publish settings, but sensitive information contained
154 | # in these scripts will be unencrypted
155 | PublishScripts/
156 |
157 | # NuGet Packages
158 | *.nupkg
159 | # The packages folder can be ignored because of Package Restore
160 | **/packages/*
161 | # except build/, which is used as an MSBuild target.
162 | !**/packages/build/
163 | # Uncomment if necessary, but generally, the file is regenerated when needed
164 | #!**/packages/repositories.config
165 | # NuGet v3's project.json files produces more ignoreable files
166 | *.nuget.props
167 | *.nuget.targets
168 |
169 | # Microsoft Azure Build Output
170 | csx/
171 | *.build.csdef
172 |
173 | # Microsoft Azure Emulator
174 | ecf/
175 | rcf/
176 |
177 | # Windows Store app package directories and files
178 | AppPackages/
179 | BundleArtifacts/
180 | Package.StoreAssociation.xml
181 | _pkginfo.txt
182 |
183 | # Visual Studio cache files
184 | # files ending in .cache can be ignored
185 | *.[Cc]ache
186 | # but keep track of directories ending in .cache
187 | !*.[Cc]ache/
188 |
189 | # Others
190 | ClientBin/
191 | ~$*
192 | *~
193 | *.dbmdl
194 | *.dbproj.schemaview
195 | *.jfm
196 | *.pfx
197 | *.publishsettings
198 | node_modules/
199 | orleans.codegen.cs
200 |
201 | # Since there are multiple workflows, uncomment next line to ignore bower_components
202 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
203 | #bower_components/
204 |
205 | # RIA/Silverlight projects
206 | Generated_Code/
207 |
208 | # Backup & report files from converting an old project file
209 | # to a newer Visual Studio version. Backup files are not needed,
210 | # because we have git ;-)
211 | _UpgradeReport_Files/
212 | Backup*/
213 | UpgradeLog*.XML
214 | UpgradeLog*.htm
215 |
216 | # SQL Server files
217 | *.mdf
218 | *.ldf
219 |
220 | # Business Intelligence projects
221 | *.rdl.data
222 | *.bim.layout
223 | *.bim_*.settings
224 |
225 | # Microsoft Fakes
226 | FakesAssemblies/
227 |
228 | # GhostDoc plugin setting file
229 | *.GhostDoc.xml
230 |
231 | # Node.js Tools for Visual Studio
232 | .ntvs_analysis.dat
233 |
234 | # Visual Studio 6 build log
235 | *.plg
236 |
237 | # Visual Studio 6 workspace options file
238 | *.opt
239 |
240 | # Visual Studio LightSwitch build output
241 | **/*.HTMLClient/GeneratedArtifacts
242 | **/*.DesktopClient/GeneratedArtifacts
243 | **/*.DesktopClient/ModelManifest.xml
244 | **/*.Server/GeneratedArtifacts
245 | **/*.Server/ModelManifest.xml
246 | _Pvt_Extensions
247 |
248 | # Paket dependency manager
249 | .paket/paket.exe
250 | paket-files/
251 |
252 | # FAKE - F# Make
253 | .fake/
254 |
255 | # JetBrains Rider
256 | .idea/
257 | *.sln.iml
258 |
259 | # CodeRush
260 | .cr/
261 |
262 | # Python Tools for Visual Studio (PTVS)
263 | __pycache__/
264 | *.pyc
--------------------------------------------------------------------------------
/api-management-actions/sample-function/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "ms-azuretools.vscode-azurefunctions"
4 | ]
5 | }
--------------------------------------------------------------------------------
/api-management-actions/sample-function/AwesomeFunction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Threading.Tasks;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Azure.WebJobs;
6 | using Microsoft.Azure.WebJobs.Extensions.Http;
7 | using Microsoft.AspNetCore.Http;
8 | using Microsoft.Extensions.Logging;
9 | using Newtonsoft.Json;
10 |
11 | namespace SampleFunction
12 | {
13 | public static class AwesomeFunction
14 | {
15 | [FunctionName("AwesomeFunction")]
16 | public static async Task Run(
17 | [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
18 | ILogger log)
19 | {
20 | log.LogInformation("C# HTTP trigger function processed a request.");
21 |
22 | string name = req.Query["name"];
23 |
24 | string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
25 | dynamic data = JsonConvert.DeserializeObject(requestBody);
26 | name = name ?? data?.name;
27 |
28 | return name != null
29 | ? (ActionResult)new OkObjectResult($"Hello, {name}")
30 | : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/api-management-actions/sample-function/SampleFunction.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netcoreapp2.1
4 | v2
5 |
6 |
7 |
8 |
9 |
10 |
11 | PreserveNewest
12 |
13 |
14 | PreserveNewest
15 | Never
16 |
17 |
18 |
--------------------------------------------------------------------------------
/api-management-actions/sample-function/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0"
3 | }
--------------------------------------------------------------------------------
/api-management-actions/sample-function/local.settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "IsEncrypted": false,
3 | "Values": {
4 | "AzureWebJobsStorage": "UseDevelopmentStorage=true",
5 | "FUNCTIONS_WORKER_RUNTIME": "dotnet"
6 | }
7 | }
--------------------------------------------------------------------------------
/api-management-actions/templates/connectors-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "sharedResourceGroupName": "[toLower(concat(variables('baseName'), 'rgp', variables('location'), '-shared'))]",
42 | "functionAppName": "[concat(variables('baseName'), 'fa', parameters('locationName'))]",
43 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
44 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
45 | },
46 | "resources": [
47 |
48 | ],
49 | "outputs": {
50 | "functionAppName": {
51 | "type": "string",
52 | "value": "[variables('functionAppName')]"
53 | },
54 | "functionAppResourceGroup": {
55 | "type": "string",
56 | "value": "[variables('sharedResourceGroupName')]"
57 | },
58 | "subscriptionId": {
59 | "type": "string",
60 | "value": "[subscription().subscriptionId]"
61 | },
62 | "logicAppName": {
63 | "type": "string",
64 | "value": "[variables('logicAppName')]"
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/api-management-actions/templates/logic-app-definition-parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$armValues": {
3 | "value": {
4 | "functionAppName": "{functionAppName}",
5 | "functionAppResourceGroup": "{functionAppResourceGroup}",
6 | "subscriptionId": "{subscriptionId}"
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/api-management-actions/templates/logic-app-definition.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
3 | "actions": {
4 | "AwesomeFunction": {
5 | "inputs": {
6 | "function": {
7 | "id": "/subscriptions/{subscriptionId}/resourceGroups/{functionAppResourceGroup}/providers/Microsoft.Web/sites/{functionAppName}/functions/AwesomeFunction"
8 | },
9 | "method": "GET",
10 | "queries": {
11 | "name": "sample"
12 | }
13 | },
14 | "runAfter": {},
15 | "type": "Function"
16 | }
17 | },
18 | "contentVersion": "1.0.0.0",
19 | "outputs": {},
20 | "parameters": {
21 | "$armValues": {
22 | "defaultValue": {},
23 | "type": "Object"
24 | }
25 | },
26 | "triggers": {
27 | "Sliding_Window": {
28 | "recurrence": {
29 | "frequency": "Minute",
30 | "interval": 3
31 | },
32 | "type": "SlidingWindow"
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/api-management-actions/templates/logic-app-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
42 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
43 | },
44 | "resources": [
45 | {
46 | "name": "[variables('logicAppName')]",
47 | "type": "Microsoft.Logic/workflows",
48 | "location": "[variables('location')]",
49 | "apiVersion": "2016-06-01",
50 | "properties": {
51 | "definition": {
52 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
53 | "contentVersion": "1.0.0.0",
54 | "parameters": {},
55 | "triggers": {},
56 | "actions": {},
57 | "outputs": {}
58 | }
59 | }
60 | }
61 | ],
62 | "outputs": {
63 | "logicAppName": {
64 | "type": "string",
65 | "value": "[variables('logicAppName')]"
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/concepts-review.md:
--------------------------------------------------------------------------------
1 | # Concepts
2 |
3 | This topic introduces concepts that are followed by the Azure Logic Apps samples that show how to set up a continuous integration (CI) and continuous deployment (CD) pipeline.
4 |
5 | ## Developer workflow
6 |
7 | These samples show how you can streamline both the developer workflow and the release pipeline. A developer's typical workflow looks like this example:
8 |
9 | 
10 |
11 | 1. The developer makes their changes in their development environment by using Visual Studio Code, Visual Studio, or the Azure portal. They run all the validation steps in that environment and are ready to integrate.
12 |
13 | 2. The developer downloads the logic app's definition by using Visual Studio Code.
14 |
15 | 3. The developer reviews the logic app's definition, parameters, and connections to make sure that any environment-specific components are provided dynamically, such as parameters passed into the definition, API connections that might need to be added to the connectors template, resources added to the shared template, or updates to the Azure Resource Manager template that's used to deploy the logic app. For examples, see the samples in this repository.
16 |
17 | 4. The developer commits the updated templates to source control.
18 |
19 | 5. The release pipeline automation propagates the changes to all the environments based on the implemented checkpoints.
20 |
21 | ## Duplicate resources
22 |
23 | A typical enterprise scenario usually duplicates resources for these reasons:
24 |
25 | * Development teams
26 |
27 | Most enterprise development shops have more than one developer on the team. This factor might require that different developers have separate instances. Often, one developer's impact on the resources in the environment can slow down or even halt the development efforts of other team members. When these developers have their own instances, they can work on their areas in a silo, and then integrate that work into the shared environments when other team members are ready to use that work. So, each developer has an environment that looks like this example:
28 |
29 | 
30 |
31 | * Scaling
32 |
33 | Duplicate resources can make scaling up and down easier, depending on your approach. For more information, see the [Scaling considerations](./scaling.md) topic.
34 |
35 | 
36 |
37 | * Disaster Recovery (DR)
38 |
39 | DR usually involves setting up a primary region and a secondary region. Some Azure resources have built-in geo-redundant features, but not all do. These resources require duplication across multiple regions and are usually set up to integrate with other resources in those regions. While the production environment is the only environment that actually requires DR capabilities, you must still develop and test the DR resources, which means that these resources require duplication in every environment for DR.
40 |
41 | 
42 |
43 | * Multiple environments
44 |
45 | An enterprise usually needs more than one environment, for example, dev, test, staging, and production.
46 |
47 | 
48 |
49 | Some might argue the merits for these reasons to duplicate resources, for example:
50 |
51 | * Your throughput requirements or API connections don't need the scaling solution.
52 | * You don't have that many environments.
53 | * Your workload is not critical and doesn't require DR.
54 |
55 | However, most workloads have at least one of these reasons to duplicate resources. These samples show how you can meet these duplication needs.
56 |
57 | ## Predictable naming
58 |
59 | When you have duplicate resources, you need a consistent way to assign resource names that are unique to their environment but also easily readable by humans. A GUID assigned to each resource name provides uniqueness but not human readability. You need a [naming convention](./naming-convention.md) that meets both needs.
60 |
61 | ## Separation of concerns
62 |
63 | Each sample uses an almost identical [file structure](./file-definitions.md), not only for consistency but also to separate concerns along these boundaries:
64 |
65 | * Shared resources
66 |
67 | These resources are often used across the solution space, for example, by different logic apps, function apps, and web apps. Examples include databases, API Management resources, and Log Analytics workspaces.
68 |
69 | * Logic app dependencies
70 |
71 | Your logic app depends on specific resources, typically API connections, that aren't shared by other logic apps or areas of the solution. These resources have the same lifespan as your logic app, so they also reside in the same Azure resource group as your logic app.
72 |
73 | * Logic app definition
74 |
75 | These samples separate the logic app's definition from the Azure Resource Manager template, which is used in deployment, for these reasons:
76 |
77 | * The logic app's definition, which is the "application code", is the most frequently updated part in the CI/CD pipeline. To streamline the development process by expediting these changes over other changes, these samples pull out just the logic app definition from a development environment by using the [Visual Studio Code extension for Azure Logic Apps](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-logicapps).
78 |
79 | * The separation between definition and template is at the heart of implementing a CI/CD pipeline for Azure Logic Apps. By separating these pieces, you can focus on building the logic app's workflow, while reducing the effort to deploy these resources across multiple environments.
80 |
81 | * Logic app deployment template
82 |
83 | Likewise, these samples separate the Resource Manager template, which is used in deployment, from the logic app's definition for these reasons:
84 |
85 | * The template isn't the same as the logic app's definition.
86 |
87 | * The rate of change in the template is much slower than in the logic app definition.
88 |
--------------------------------------------------------------------------------
/file-definitions.md:
--------------------------------------------------------------------------------
1 | # Samples file structure and definitions
2 |
3 | All the samples that create a continuous integration (CI) and continuous delivery (CD) pipeline for Azure Logic Apps follow a similar file structure. Although some minor differences exist, each sample contains the files described in this topic.
4 |
5 | ## PowerShell scripts
6 |
7 | The scripts in each sample follow the workflow that's described by this diagram:
8 |
9 | 
10 |
11 | | Script file name | Description |
12 | |------------------|-------------|
13 | | `full-deploy.ps1` | Runs both the `logic-app-deploy.ps1` and `shared-deploy.ps1` scripts for a sample. This script is provided for convenience during deployment and isn't meant for use in a CI/CD pipeline. However, the deployments for the shared resources and logic app resource happen inside different CI/CD pipelines. |
14 | | `logic-app-deploy.ps1` | Brings all the logic app pieces together and performs these actions:
1. Deploy the templates for the API connectors.
2. Take the output from the connectors deployment and inject the values into both the logic app definition template and logic app definition's parameters file.
3. Deploy the number of logic app instances that's defined by the input parameters.
The parameters that pass into this script are also used for naming your logic app resources, based on the [naming convention](./naming-convention.md) used by these samples. |
15 | | `shared-deploy.ps1` | Deploys the `shared-template.json` template and is a variation on the standard PowerShell script that you get when you export from an Azure resource.
This script differs by using the parameters that pass into the script's execution to construct the parameters that pass into resource deployment. These parameters are used to implement the [naming convention](./naming-convention.md) used throughout these samples. |
16 | | `clean-up.ps1` | Removes all the resources that are deployed by a sample. Examines your subscription, finds all the resource groups that start with the group ID that's passed in, and deletes those groups.
**Caution**: Proceed carefully when you run this script. |
17 | |||
18 |
19 | ## Templates
20 |
21 | | Template file name | Description |
22 | |--------------------|-------------|
23 | | `connectors-template.json` | This Azure Resource Manager template sets up the resources that deploy to the same resource group as the logic app.
Generally, these resources include the API connections used by the logic app. This template must provide the outputs that get injected into the `logic-app-definition.json` file and `logic-app-definition-parameters.json` file. |
24 | | `connectors-parameters.json` (optional) | This file contains parameters that deploy with the `connectors-template.json` file.
- If this file is provided, the parameters that pass in during script execution get appended to the parameters defined in this file.
- If this file isn't provided, the parameters that pass in during script execution get passed along as a hash table to the connectors template during deployment. |
25 | | `logic-app-definition.json` | This file contains your logic app's workflow definition, or "code". The separation between the logic app's definition file and the Resource Manager template used for deployment is critical to supporting multiple environments.
These samples are designed to use the [Visual Studio Code extension for Azure Logic Apps](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-logicapps) so that you can download the logic app's current workflow definition, add that definition to source control, and set up a CI/CD pipeline that deploys to multiple environments. |
26 | | `logic-app-definition-parameters.json` | This file contains parameters that deploy with the `logic-app-definition.json` file.
**Important**: Make sure that the parameters that are defined in this file are also defined in the `logic-app-definition.json` file.
The `logic-app-deploy.ps1` script replaces tokens in both the `logic-app-definition.json` file and the `logic-app-definition-parameters.json` file. The replaced tokens are defined by the output from the `connectors-template.json` file. |
27 | | `logic-app-template.json` | This Azure Resource Manager template sets up the logic app but is mostly generic without much content.
**Note**: Some samples require that the template run one time to succeed. In other words, this template only deploys the first time when the logic app deploys to an environment. When this requirement exists, the `overrideExisting` parameters in the `logic-app-deploy.ps1` script must be set to `false`. |
28 | | `logic-app-template-parameters.json` (optional) | This file contains parameters that deploy with the `logic-app-template.json` file.
- If this file is provided, the parameters that pass in during script execution get appended to the parameters defined in this file.
- If this file isn't provided, the parameters that pass in during script execution get passed along as a hash table to the logic app template during deployment. |
29 | | `shared-template.json` | This Azure Resource Manager template sets up the shared resources used by the logic app and deploys those resources to a separate resource group for these reasons:
- **Separate concerns**: These resources, such as databases, storage accounts, and event hubs, are most likely used by resources other than just the logic app.
- **Scaling**: These samples provide the capability to scale the logic app's implementations, or more specifically, the API connection implementations. The shared resources in this resource group don't require the scaling capability that other resources require. For more information, see the [Scaling](./api-connection-scale.md) topic.
- **Lifecycle management**: The lifespan for the shared resources in this resource group likely differ from the logic app. For example, future demands might require that you replace the logic app with an alternative solution. Separate resource groups gives you the flexibility to replace logic apps without having to cherry pick resources from a single resource group that stores all the resources together.
- **Rate of change**: Usually, the rate of change in shared resources templates is much lower than the rate of change in logic apps. |
30 | | `shared-template-parameters.json` (optional) | This file contains the parameters that deploy with the `shared-template.json` file.
- If this file is provided, the parameters that pass in during script execution get appended to the parameters defined in this file.
- If this file isn't provided, the parameters that pass in during script execution get passed along as a hash table to the shared resources template during deployment. |
31 | |||
32 |
--------------------------------------------------------------------------------
/function-app-actions/powershell/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | location: westus
3 | groupId: cse01
4 | abbrevLocationName: westus
5 | instanceCount: 1
6 | identifier: sample-function-app
7 | sampleDirectory: function-app-actions
8 | sharedResourceGroupIdentifier: shared
9 |
10 | trigger:
11 | - master
12 |
13 | stages:
14 | - stage: BuildFunctionApp
15 | variables:
16 | project: '**/$(sampleDirectory)/sample-function/*.csproj'
17 | buildPlatform: 'Any CPU'
18 | buildConfiguration: 'Release'
19 | jobs:
20 | - job: BuildFunctionApp
21 | pool:
22 | vmImage: 'windows-2019'
23 | steps:
24 | - task: DotNetCoreCLI@2
25 | displayName: Build Project
26 | inputs:
27 | command: 'build'
28 | projects: '$(project)'
29 | arguments: '--configuration $(buildConfiguration)'
30 | - task: ArchiveFiles@2
31 | displayName: 'Archive files'
32 | inputs:
33 | rootFolderOrFile: '$(System.DefaultWorkingDirectory)/$(sampleDirectory)/sample-function/bin/$(buildConfiguration)/netcoreapp2.1/'
34 | includeRootFolder: false
35 | archiveType: zip
36 | archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
37 | replaceExistingArchive: true
38 | - task: PublishPipelineArtifact@1
39 | inputs:
40 | path: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
41 | ArtifactName: 'function-app'
42 | - stage: Development
43 | jobs:
44 | - job: DeployDevelopmentEnvironment
45 | variables:
46 | environment: d
47 | pool:
48 | vmImage: 'windows-2019'
49 | steps:
50 | - script: |
51 | echo ##vso[task.setvariable variable=resourceGroupName]$(groupId)$(environment)rgp$(location)-$(sharedResourceGroupIdentifier)
52 | echo ##vso[task.setvariable variable=templateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\shared-template.json
53 | echo ##vso[task.setvariable variable=logicAppDeployScript]$(Build.Repository.LocalPath)\$(sampleDirectory)\powershell\logic-app-deploy.ps1
54 | echo ##vso[task.setvariable variable=functionAppName]$(groupId)$(environment)fa$(abbrevLocationName)
55 | name: setDynamicVariableNames
56 | - powershell: |
57 | Write-Host "templateFilePath: $(templateFilePath)"
58 | Write-Host "resourceGroupName: $(resourceGroupName)"
59 | Write-Host "logicAppDeployScript: $(logicAppDeployScript)"
60 | name: printOutVariables
61 | - task: AzureResourceGroupDeployment@2
62 | name: SharedResourcesDeployment
63 | inputs:
64 | azureSubscription: 'Azure Samples Subscription'
65 | action: 'Create Or Update Resource Group'
66 | resourceGroupName: $(resourceGroupName)
67 | location: $(location)
68 | templateLocation: Linked artifact
69 | csmFile: $(templateFilePath)
70 | deploymentMode: 'Incremental'
71 | deploymentName: $(Build.BuildNumber)
72 | overrideParameters: -groupId $(groupId) -environment $(environment) -locationName $(abbrevLocationName)
73 | - task: DownloadPipelineArtifact@2
74 | displayName: Download Function App
75 | inputs:
76 | artifactName: function-app
77 | - task: AzureFunctionApp@1
78 | name: DeployFunctionApp
79 | inputs:
80 | azureSubscription: 'Azure Samples Subscription'
81 | appType: 'functionApp'
82 | appName: $(functionAppName)
83 | package: '$(Pipeline.Workspace)/**/$(Build.BuildId).zip'
84 | deploymentMethod: 'auto'
85 | - script: |
86 | echo ##vso[task.setvariable variable=connectorsTemplateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\connectors-template.json
87 | echo ##vso[task.setvariable variable=logicAppTemplateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-template.json
88 | echo ##vso[task.setvariable variable=logicAppDefinitionPath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-definition.json
89 | echo ##vso[task.setvariable variable=logicAppDefinitionParametersFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-definition-parameters.json
90 | - task: AzurePowerShell@4
91 | name: DeployLogicAppSample
92 | inputs:
93 | azureSubscription: 'Azure Samples Subscription'
94 | ScriptType: 'FilePath'
95 | ScriptPath: '$(logicAppDeployScript)'
96 | FailOnStandardError: true
97 | azurePowerShellVersion: LatestVersion
98 | ScriptArguments: >-
99 | -groupId $(groupId)
100 | -location $(location)
101 | -abbrevLocationName $(abbrevLocationName)
102 | -environment $(environment)
103 | -instanceCount $(instanceCount)
104 | -identifier $(identifier)
105 | -connectorsTemplateFilePath $(connectorsTemplateFilePath)
106 | -logicAppTemplateFilePath $(logicAppTemplateFilePath)
107 | -logicAppDefinitionPath $(logicAppDefinitionPath)
108 | -logicAppDefinitionParametersFilePath $(logicAppDefinitionParametersFilePath)
--------------------------------------------------------------------------------
/function-app-actions/powershell/clean-up.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deletes all resource groups where their names start with the "groupId" that's passed as input.
4 |
5 | .PARAMETER groupId
6 | The value that identifies the resource group to delete
7 | #>
8 |
9 | param(
10 | [Parameter(Mandatory = $True)]
11 | [string]
12 | $groupId
13 | )
14 |
15 | $resourceGroups = Get-AzResourceGroup;
16 |
17 | foreach ($resourceGroup in $resourceGroups) {
18 | if ($resourceGroup.ResourceGroupName.StartsWith($groupId, 'CurrentCultureIgnoreCase')) {
19 | Remove-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Force -AsJob
20 | Write-Host "Deleted resource group $($resourceGroup.ResourceGroupName)"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/function-app-actions/powershell/full-deploy.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deploys a template for a logic app to Azure.
4 |
5 | .DESCRIPTION
6 | Deploys an Azure Resource Manager template with the LogicApp definition seperated within the directory
7 |
8 | .PARAMETER groupId
9 | The value used for constructing resources in the resource group and identifies the resources that are used together in a specific solution
10 |
11 | .PARAMETER location
12 | The region or location name to use for the resource group and the resources in that group
13 |
14 | .PARAMETER environment
15 | The alphabetical character that identifies the deployment environment to use in the name for each resource that's created in the resource group. For example, values include "d" for development, "t" for test, "s" for staging, and "p" for production.
16 |
17 | .PARAMETER abbrevLocationName
18 | The abbreviated region name that's used in resource names due to character limitations on some resource types. Defaults to the "location" parameter value.
19 |
20 | .PARAMETER deploymentName
21 | The name used for the deployment. If not given, a GUID is assigned as the deployment name.
22 |
23 | .PARAMETER instanceCount
24 | The number of resource group instances to create
25 |
26 | .PARAMETER overrideExistingLogicApp
27 | If true, the script runs the Azure Resource Manager template deployment for the logic app, even when the logic app already exists.
28 | #>
29 |
30 | param(
31 |
32 | [Parameter(Mandatory=$True)]
33 | [string]
34 | $groupId,
35 |
36 | [Parameter(Mandatory=$True)]
37 | [string]
38 | $location,
39 |
40 | [Parameter(Mandatory=$True)]
41 | [string]
42 | $environment,
43 |
44 | [Parameter(Mandatory=$False)]
45 | [string]
46 | $abbrevLocationName = $location,
47 |
48 | [Parameter(Mandatory=$False)]
49 | [string]
50 | $deploymentName = [guid]::NewGuid(),
51 |
52 | [Parameter(Mandatory=$False)]
53 | [int]
54 | $instanceCount = 1,
55 |
56 | [Parameter(Mandatory = $False)]
57 | [bool]
58 | $overrideExistingLogicApp = $True
59 | )
60 |
61 | Write-Host "Running shared deployment script"
62 |
63 | $result = & "${PSScriptRoot}\shared-deploy.ps1" -groupId $groupId `
64 | -location $location `
65 | -environment $environment `
66 | -abbrevLocationName $abbrevLocationName `
67 | -deploymentName $deploymentName;
68 |
69 | Write-Host "Deploying Function App"
70 |
71 | Push-Location "${$PSScriptRoot}../sample-function"
72 |
73 | $deployCommand = "func azure functionapp publish {0}" -f $result.Outputs.functionAppName.Value
74 |
75 | Invoke-Expression $deployCommand
76 |
77 | Pop-Location
78 |
79 | Write-Host "Running logic app deployment script"
80 |
81 | & "${PSScriptRoot}\logic-app-deploy.ps1" -groupId $groupId `
82 | -location $location `
83 | -environment $environment `
84 | -abbrevLocationName $abbrevLocationName `
85 | -deploymentName $deploymentName `
86 | -identifier "sample-function-app" `
87 | -instanceCount $instanceCount `
88 | -overrideExisting $overrideExistingLogicApp;
--------------------------------------------------------------------------------
/function-app-actions/powershell/shared-deploy.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deploy the shared resources.
4 |
5 | .DESCRIPTION
6 | Deploys an Azure Resource Manager template with the LogicApp definition seperated within the directory
7 |
8 | .PARAMETER groupId
9 | The value used for constructing resources in the resource group and identifies the resources that are used together in a specific solution
10 |
11 | .PARAMETER location
12 | The region or location name to use for the resource group and the resources in that group
13 |
14 | .PARAMETER environment
15 | The alphabetical character that identifies the deployment environment to use in the name for each resource that's created in the resource group. For example, values include "d" for development, "t" for test, "s" for staging, and "p" for production.
16 |
17 | .PARAMETER abbrevLocationName
18 | OPTIONAL: The abbreviated region name that's used in resource names due to character limitations on some resource types. Defaults to the "location" parameter value.
19 |
20 | .PARAMETER deploymentName
21 | OPTIONAL: The name used for the deployment. If not given, a GUID is assigned as the deployment name.
22 |
23 | .PARAMETER identifier
24 | OPTIONAL: Value appended to the end of the resource group and the logic app within the resource group
25 |
26 | .PARAMETER parametersFilePath
27 | OPTIONAL: Path to the parameter file. Defaults to the file contained within the local directory
28 |
29 | .PARAMETER templateFilePath
30 | OPTIONAL: Path to the template file. Defaults to the file contained within the local directory
31 | #>
32 |
33 | param(
34 | [Parameter(Mandatory = $True)]
35 | [string]
36 | $groupId,
37 |
38 | [Parameter(Mandatory = $True)]
39 | [string]
40 | $location,
41 |
42 | [Parameter(Mandatory = $True)]
43 | [string]
44 | $environment,
45 |
46 | [Parameter(Mandatory = $False)]
47 | [string]
48 | $abbrevLocationName = $location,
49 |
50 | [Parameter(Mandatory = $False)]
51 | [string]
52 | $deploymentName = [guid]::NewGuid(),
53 |
54 | [Parameter(Mandatory = $False)]
55 | [string]
56 | $identifier = "shared",
57 |
58 | [Parameter(Mandatory = $False)]
59 | [string]
60 | $parametersFilePath = "../templates/shared-parameters.json",
61 |
62 | [Parameter(Mandatory = $False)]
63 | [string]
64 | $templateFilePath = "../templates/shared-template.json"
65 | )
66 |
67 | Function RegisterRP {
68 | <#
69 | .SYNOPSIS
70 | Register the Azure resource provider.
71 | #>
72 | Param(
73 | [Parameter(Mandatory = $True, HelpMessage = "The name of the resource provider to register")]
74 | [string]$ResourceProviderNamespace
75 | )
76 |
77 | Write-Host "Registering resource provider '$ResourceProviderNamespace'";
78 | $registered = Register-AzResourceProvider -ProviderNamespace $ResourceProviderNamespace;
79 | }
80 |
81 | Function Set-RelativeFilePaths {
82 | <#
83 | .SYNOPSIS
84 | Fix relative paths that can't be evaluated as given.
85 | .DESCRIPTION
86 | Validate whether the file paths can be evaluated as they're passed as input.
87 | If the paths are relative and can't be found, try to fix by prepending the
88 | root path for script execution to the given path.
89 | #>
90 | Param()
91 | $parametersFilePath = Set-RelativeFilePath -filePath $parametersFilePath
92 | $templateFilePath = Set-RelativeFilePath -filePath $templateFilePath
93 | }
94 |
95 | Function Set-RelativeFilePath {
96 | <#
97 | .SYNOPSIS
98 | Validate a single file path and prepend the root path for script execution when the path fails.
99 | #>
100 | Param(
101 | [Parameter(Mandatory = $True, HelpMessage = "The path of the file to test whether the file exists")]
102 | [string]$filePath
103 | )
104 |
105 | if (Test-Path $filePath) {
106 | return $filePath;
107 | }
108 | else {
109 | return "{0}\{1}" -f $PSScriptRoot, $filePath;
110 | }
111 | }
112 |
113 | Function Set-ResourceGroup {
114 | <#
115 | .SYNOPSIS
116 | Check whether the resource group exists. If not, create the resource group.
117 | #>
118 | Param(
119 | [Parameter(Mandatory = $True, HelpMessage = "The name for the resource group to create, if not already existing")]
120 | [string]$resourceGroupName
121 | )
122 |
123 | Write-Host "Working with resource group name: '$resourceGroupName'"
124 |
125 | Write-Host "Checking whether the resource group exists"
126 | $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
127 | if (!$resourceGroup) {
128 | Write-Host "Resource group '$resourceGroupName' does not exist. Creating new resource group";
129 |
130 | Write-Host "Creating resource group '$resourceGroupName' in location '$location'";
131 | New-AzResourceGroup -Name $resourceGroupName -Location $location
132 | }
133 | else {
134 | Write-Host "Using existing resource group '$resourceGroupName'";
135 | }
136 | }
137 |
138 | Function New-ResourceManagerTemplateDeployment {
139 | <#
140 | .SYNOPSIS
141 | Create an Azure Resource Manager template deployment.
142 | .OUTPUTS
143 | The results from the Azure Resource Manager template deployment
144 | #>
145 | Param(
146 | [Parameter(Mandatory = $True, HelpMessage = "The path for the parameter file to use for deployment")]
147 | [string]$parametersFilePath,
148 | [Parameter(Mandatory = $True, HelpMessage = "The name for the resource group to use for deployment")]
149 | [string]$resourceGroupName,
150 | [Parameter(Mandatory = $True, HelpMessage = "The path to the template file to use for the deployment")]
151 | [string]$templateFilePath,
152 | [Parameter(Mandatory = $True, HelpMessage = "The values to append to the parameters before deployment")]
153 | [hashtable]$armParameters
154 | )
155 | if (Test-Path $parametersFilePath) {
156 | Write-Host "Loading parameters from file";
157 | $parametersFromFile = Get-Content -Raw -Encoding UTF8 -Path $parametersFilePath | ConvertFrom-Json
158 |
159 | Write-Host "Adding script parameters";
160 | New-Parameter -parameters $parametersFromFile -name "groupId" -value $groupId
161 | New-Parameter -parameters $parametersFromFile -name "environment" -value $environment
162 | New-Parameter -parameters $parametersFromFile -name "locationName" -value $locationName
163 |
164 | Write-Host "Starting deployment...";
165 | return New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath -TemplateParameterObject $parametersFromFile;
166 | }
167 | else {
168 | Write-Host "Starting deployment...";
169 | return New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath -TemplateParameterObject $armParameters;
170 | }
171 | }
172 |
173 | Function New-Parameter {
174 | <#
175 | .SYNOPSIS
176 | Append a parameter to the hash table for parameters that are passed as input.
177 | #>
178 | Param (
179 | [Parameter(Mandatory = $True, HelpMessage = "The hash table where to add the parameter")]
180 | [hashtable]$parameters,
181 | [Parameter(Mandatory = $True, HelpMessage = "The name for the parameter to add")]
182 | [string]$name,
183 | [Parameter(Mandatory = $True, HelpMessage = "The value for the parameter to add")]
184 | [string]$value
185 | )
186 | $parameters | Add-Member -MemberType NoteProperty -Name $name -Value @{value = $value }
187 | }
188 |
189 | #******************************************************************************
190 | # Script body
191 | # Execution begins here
192 | #******************************************************************************
193 |
194 | if (!$PSScriptRoot) { $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent }
195 |
196 | Set-RelativeFilePaths;
197 |
198 | $resourceProviders = @("Microsoft.Web","Microsoft.Insights","Microsoft.Storage");
199 | if ($resourceProviders.length) {
200 | Write-Host "Registering resource providers"
201 | foreach ($resourceProvider in $resourceProviders) {
202 | RegisterRP($resourceProvider);
203 | }
204 | }
205 |
206 | $resourceGroupName = "{0}{1}rgp{2}-{3}" -f $groupId, $environment, $location, $identifier;
207 |
208 | Set-ResourceGroup -resourceGroupName $resourceGroupName;
209 |
210 | $armParameters = @{
211 | groupId = $groupId
212 | environment = $environment
213 | locationName = $abbrevLocationName
214 | };
215 |
216 | $result = New-ResourceManagerTemplateDeployment -parametersFilePath $parametersFilePath `
217 | -resourceGroupName $resourceGroupName `
218 | -templateFilePath $templateFilePath `
219 | -armParameters $armParameters;
220 |
221 | return $result;
--------------------------------------------------------------------------------
/function-app-actions/sample-function/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # Azure Functions localsettings file
5 | # local.settings.json
6 |
7 | # User-specific files
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 | [Ll]og/
27 |
28 | # Visual Studio 2015 cache/options directory
29 | .vs/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # MSTest test Results
34 | [Tt]est[Rr]esult*/
35 | [Bb]uild[Ll]og.*
36 |
37 | # NUNIT
38 | *.VisualState.xml
39 | TestResult.xml
40 |
41 | # Build Results of an ATL Project
42 | [Dd]ebugPS/
43 | [Rr]eleasePS/
44 | dlldata.c
45 |
46 | # DNX
47 | project.lock.json
48 | project.fragment.lock.json
49 | artifacts/
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # NCrunch
117 | _NCrunch_*
118 | .*crunch*.local.xml
119 | nCrunchTemp_*
120 |
121 | # MightyMoose
122 | *.mm.*
123 | AutoTest.Net/
124 |
125 | # Web workbench (sass)
126 | .sass-cache/
127 |
128 | # Installshield output folder
129 | [Ee]xpress/
130 |
131 | # DocProject is a documentation generator add-in
132 | DocProject/buildhelp/
133 | DocProject/Help/*.HxT
134 | DocProject/Help/*.HxC
135 | DocProject/Help/*.hhc
136 | DocProject/Help/*.hhk
137 | DocProject/Help/*.hhp
138 | DocProject/Help/Html2
139 | DocProject/Help/html
140 |
141 | # Click-Once directory
142 | publish/
143 |
144 | # Publish Web Output
145 | *.[Pp]ublish.xml
146 | *.azurePubxml
147 | # TODO: Comment the next line if you want to checkin your web deploy settings
148 | # but database connection strings (with potential passwords) will be unencrypted
149 | #*.pubxml
150 | *.publishproj
151 |
152 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
153 | # checkin your Azure Web App publish settings, but sensitive information contained
154 | # in these scripts will be unencrypted
155 | PublishScripts/
156 |
157 | # NuGet Packages
158 | *.nupkg
159 | # The packages folder can be ignored because of Package Restore
160 | **/packages/*
161 | # except build/, which is used as an MSBuild target.
162 | !**/packages/build/
163 | # Uncomment if necessary, but generally, the file is regenerated when needed
164 | #!**/packages/repositories.config
165 | # NuGet v3's project.json files produces more ignoreable files
166 | *.nuget.props
167 | *.nuget.targets
168 |
169 | # Microsoft Azure Build Output
170 | csx/
171 | *.build.csdef
172 |
173 | # Microsoft Azure Emulator
174 | ecf/
175 | rcf/
176 |
177 | # Windows Store app package directories and files
178 | AppPackages/
179 | BundleArtifacts/
180 | Package.StoreAssociation.xml
181 | _pkginfo.txt
182 |
183 | # Visual Studio cache files
184 | # files ending in .cache can be ignored
185 | *.[Cc]ache
186 | # but keep track of directories ending in .cache
187 | !*.[Cc]ache/
188 |
189 | # Others
190 | ClientBin/
191 | ~$*
192 | *~
193 | *.dbmdl
194 | *.dbproj.schemaview
195 | *.jfm
196 | *.pfx
197 | *.publishsettings
198 | node_modules/
199 | orleans.codegen.cs
200 |
201 | # Since there are multiple workflows, uncomment next line to ignore bower_components
202 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
203 | #bower_components/
204 |
205 | # RIA/Silverlight projects
206 | Generated_Code/
207 |
208 | # Backup & report files from converting an old project file
209 | # to a newer Visual Studio version. Backup files are not needed,
210 | # because we have git ;-)
211 | _UpgradeReport_Files/
212 | Backup*/
213 | UpgradeLog*.XML
214 | UpgradeLog*.htm
215 |
216 | # SQL Server files
217 | *.mdf
218 | *.ldf
219 |
220 | # Business Intelligence projects
221 | *.rdl.data
222 | *.bim.layout
223 | *.bim_*.settings
224 |
225 | # Microsoft Fakes
226 | FakesAssemblies/
227 |
228 | # GhostDoc plugin setting file
229 | *.GhostDoc.xml
230 |
231 | # Node.js Tools for Visual Studio
232 | .ntvs_analysis.dat
233 |
234 | # Visual Studio 6 build log
235 | *.plg
236 |
237 | # Visual Studio 6 workspace options file
238 | *.opt
239 |
240 | # Visual Studio LightSwitch build output
241 | **/*.HTMLClient/GeneratedArtifacts
242 | **/*.DesktopClient/GeneratedArtifacts
243 | **/*.DesktopClient/ModelManifest.xml
244 | **/*.Server/GeneratedArtifacts
245 | **/*.Server/ModelManifest.xml
246 | _Pvt_Extensions
247 |
248 | # Paket dependency manager
249 | .paket/paket.exe
250 | paket-files/
251 |
252 | # FAKE - F# Make
253 | .fake/
254 |
255 | # JetBrains Rider
256 | .idea/
257 | *.sln.iml
258 |
259 | # CodeRush
260 | .cr/
261 |
262 | # Python Tools for Visual Studio (PTVS)
263 | __pycache__/
264 | *.pyc
--------------------------------------------------------------------------------
/function-app-actions/sample-function/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "ms-azuretools.vscode-azurefunctions"
4 | ]
5 | }
--------------------------------------------------------------------------------
/function-app-actions/sample-function/AwesomeFunction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Threading.Tasks;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Azure.WebJobs;
6 | using Microsoft.Azure.WebJobs.Extensions.Http;
7 | using Microsoft.AspNetCore.Http;
8 | using Microsoft.Extensions.Logging;
9 | using Newtonsoft.Json;
10 |
11 | namespace SampleFunction
12 | {
13 | public static class AwesomeFunction
14 | {
15 | [FunctionName("AwesomeFunction")]
16 | public static async Task Run(
17 | [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
18 | ILogger log)
19 | {
20 | log.LogInformation("C# HTTP trigger function processed a request.");
21 |
22 | string name = req.Query["name"];
23 |
24 | string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
25 | dynamic data = JsonConvert.DeserializeObject(requestBody);
26 | name = name ?? data?.name;
27 |
28 | return name != null
29 | ? (ActionResult)new OkObjectResult($"Hello, {name}")
30 | : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/function-app-actions/sample-function/SampleFunction.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netcoreapp2.1
4 | v2
5 |
6 |
7 |
8 |
9 |
10 |
11 | PreserveNewest
12 |
13 |
14 | PreserveNewest
15 | Never
16 |
17 |
18 |
--------------------------------------------------------------------------------
/function-app-actions/sample-function/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0"
3 | }
--------------------------------------------------------------------------------
/function-app-actions/sample-function/local.settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "IsEncrypted": false,
3 | "Values": {
4 | "AzureWebJobsStorage": "UseDevelopmentStorage=true",
5 | "FUNCTIONS_WORKER_RUNTIME": "dotnet"
6 | }
7 | }
--------------------------------------------------------------------------------
/function-app-actions/templates/connectors-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "sharedResourceGroupName": "[toLower(concat(variables('baseName'), 'rgp', variables('location'), '-shared'))]",
42 | "functionAppName": "[concat(variables('baseName'), 'fa', parameters('locationName'))]",
43 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
44 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
45 | },
46 | "resources": [
47 |
48 | ],
49 | "outputs": {
50 | "functionAppName": {
51 | "type": "string",
52 | "value": "[variables('functionAppName')]"
53 | },
54 | "functionAppResourceGroup": {
55 | "type": "string",
56 | "value": "[variables('sharedResourceGroupName')]"
57 | },
58 | "subscriptionId": {
59 | "type": "string",
60 | "value": "[subscription().subscriptionId]"
61 | },
62 | "logicAppName": {
63 | "type": "string",
64 | "value": "[variables('logicAppName')]"
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/function-app-actions/templates/logic-app-definition-parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$armValues": {
3 | "value": {
4 | "functionAppName": "{functionAppName}",
5 | "functionAppResourceGroup": "{functionAppResourceGroup}",
6 | "subscriptionId": "{subscriptionId}"
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/function-app-actions/templates/logic-app-definition.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
3 | "actions": {
4 | "AwesomeFunction": {
5 | "inputs": {
6 | "function": {
7 | "id": "/subscriptions/{subscriptionId}/resourceGroups/{functionAppResourceGroup}/providers/Microsoft.Web/sites/{functionAppName}/functions/AwesomeFunction"
8 | },
9 | "method": "GET",
10 | "queries": {
11 | "name": "sample"
12 | }
13 | },
14 | "runAfter": {},
15 | "type": "Function"
16 | }
17 | },
18 | "contentVersion": "1.0.0.0",
19 | "outputs": {},
20 | "parameters": {
21 | "$armValues": {
22 | "defaultValue": {},
23 | "type": "Object"
24 | }
25 | },
26 | "triggers": {
27 | "Sliding_Window": {
28 | "recurrence": {
29 | "frequency": "Minute",
30 | "interval": 3
31 | },
32 | "type": "SlidingWindow"
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/function-app-actions/templates/logic-app-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
42 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
43 | },
44 | "resources": [
45 | {
46 | "name": "[variables('logicAppName')]",
47 | "type": "Microsoft.Logic/workflows",
48 | "location": "[variables('location')]",
49 | "apiVersion": "2016-06-01",
50 | "properties": {
51 | "definition": {
52 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
53 | "contentVersion": "1.0.0.0",
54 | "parameters": {},
55 | "triggers": {},
56 | "actions": {},
57 | "outputs": {}
58 | }
59 | }
60 | }
61 | ],
62 | "outputs": {
63 | "logicAppName": {
64 | "type": "string",
65 | "value": "[variables('logicAppName')]"
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/function-app-actions/templates/shared-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "appInsightsRegion": {
25 | "defaultValue": "westus2",
26 | "type": "string",
27 | "metadata": {
28 | "description": "The region where to deploy the Application Insights resource"
29 | }
30 | }
31 | },
32 | "variables": {
33 | "location": "[resourceGroup().location]",
34 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
35 | "appServicePlanName": "[concat(variables('baseName'), 'asp', parameters('locationName'))]",
36 | "functionAppName": "[concat(variables('baseName'), 'fa', parameters('locationName'))]",
37 | "storageAccountName": "[concat(variables('baseName'), 'sa2', parameters('locationName'))]",
38 | "appInsightsName": "[toLower(concat(variables('baseName'), 'ai', parameters('locationName')))]"
39 | },
40 | "resources": [
41 | {
42 | "type": "Microsoft.Web/serverfarms",
43 | "apiVersion": "2016-09-01",
44 | "name": "[variables('appServicePlanName')]",
45 | "location": "[variables('location')]",
46 | "sku": {
47 | "name": "Y1",
48 | "tier": "Dynamic",
49 | "size": "Y1",
50 | "family": "Y",
51 | "capacity": 0
52 | },
53 | "tags": {
54 | "groupdId": "[parameters('groupId')]"
55 | },
56 | "properties": {
57 | "name": "[variables('appServicePlanName')]"
58 | },
59 | "kind": "functionapp"
60 | },
61 | {
62 | "name": "[variables('storageAccountName')]",
63 | "type": "Microsoft.Storage/storageAccounts",
64 | "apiVersion": "2019-04-01",
65 | "tags": {
66 | "groupdId": "[parameters('groupId')]"
67 | },
68 | "sku": {
69 | "name": "Standard_LRS"
70 | },
71 | "kind": "StorageV2",
72 | "location": "[variables('location')]",
73 | "properties": {
74 | "accessTier": "Hot"
75 | },
76 | "resources": []
77 | },
78 | {
79 | "type": "Microsoft.Insights/components",
80 | "apiVersion": "2015-05-01",
81 | "name": "[variables('appInsightsName')]",
82 | "location": "[parameters('appInsightsRegion')]",
83 | "kind": "web",
84 | "properties": {
85 | "Application_Type": "web"
86 | }
87 | },
88 | {
89 | "type": "Microsoft.Web/sites",
90 | "apiVersion": "2016-08-01",
91 | "name": "[variables('functionAppName')]",
92 | "location": "[variables('location')]",
93 | "tags": {
94 | "groupdId": "[parameters('groupId')]"
95 | },
96 | "dependsOn": [
97 | "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
98 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
99 | "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
100 | ],
101 | "kind": "functionapp",
102 | "properties": {
103 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
104 | "httpsOnly": true,
105 | "siteConfig": {
106 | "appSettings": [
107 | {
108 | "name": "AzureWebJobsDashboard",
109 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(concat(resourceGroup().id, '/providers/', 'Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2015-05-01-preview').key1)]"
110 | },
111 | {
112 | "name": "AzureWebJobsStorage",
113 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(concat(resourceGroup().id, '/providers/', 'Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2015-05-01-preview').key1)]"
114 | },
115 | {
116 | "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
117 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(concat(resourceGroup().id, '/providers/', 'Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2015-05-01-preview').key1)]"
118 | },
119 | {
120 | "name": "WEBSITE_CONTENTSHARE",
121 | "value": "[variables('functionAppName')]"
122 | },
123 | {
124 | "name": "FUNCTIONS_EXTENSION_VERSION",
125 | "value": "~2"
126 | },
127 | {
128 | "name": "FUNCTIONS_WORKER_RUNTIME",
129 | "value": "dotnet"
130 | },
131 | {
132 | "name": "WEBSITE_NODE_DEFAULT_VERSION",
133 | "value": "10.14.1"
134 | },
135 | {
136 | "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
137 | "value": "[reference(resourceId('Microsoft.Insights/components/', variables('appInsightsName'))).InstrumentationKey]"
138 | }
139 | ]
140 | }
141 | }
142 | }
143 | ],
144 | "outputs": {
145 | "functionAppName": {
146 | "type": "string",
147 | "value": "[variables('functionAppName')]"
148 | }
149 | }
150 | }
--------------------------------------------------------------------------------
/images/create-pipeline.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/create-pipeline.gif
--------------------------------------------------------------------------------
/images/developer-workflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/developer-workflow.png
--------------------------------------------------------------------------------
/images/double-sb-connection-single-instance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/double-sb-connection-single-instance.png
--------------------------------------------------------------------------------
/images/double-sb-connection-three-instance-one-cosmos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/double-sb-connection-three-instance-one-cosmos.png
--------------------------------------------------------------------------------
/images/double-sb-connection-three-instance-two-cosmos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/double-sb-connection-three-instance-two-cosmos.png
--------------------------------------------------------------------------------
/images/double-sb-connection-two-instance-one-cosmos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/double-sb-connection-two-instance-one-cosmos.png
--------------------------------------------------------------------------------
/images/double-sb-connection-two-instance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/double-sb-connection-two-instance.png
--------------------------------------------------------------------------------
/images/dup-dr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/dup-dr.png
--------------------------------------------------------------------------------
/images/dup-environments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/dup-environments.png
--------------------------------------------------------------------------------
/images/dup-none.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/dup-none.png
--------------------------------------------------------------------------------
/images/dup-scale.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/dup-scale.png
--------------------------------------------------------------------------------
/images/function-app-sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/function-app-sample.png
--------------------------------------------------------------------------------
/images/sample-integration-act.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/sample-integration-act.png
--------------------------------------------------------------------------------
/images/scaled-logic-app-resources.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/scaled-logic-app-resources.png
--------------------------------------------------------------------------------
/images/scaled-resource-group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/scaled-resource-group.png
--------------------------------------------------------------------------------
/images/script-flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/script-flow.png
--------------------------------------------------------------------------------
/images/servicebus-sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/servicebus-sample.png
--------------------------------------------------------------------------------
/images/single-sb-connection-single-instance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/single-sb-connection-single-instance.png
--------------------------------------------------------------------------------
/images/storage-sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/azure-logic-apps-deployment-samples/a8eebaf9ceea8b05b0fced59a1ef423210bd8494/images/storage-sample.png
--------------------------------------------------------------------------------
/integration-account-connections/powershell/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | location: westus
3 | groupId: cse01
4 | abbrevLocationName: westus
5 | instanceCount: 1
6 | identifier: sample-int-account
7 | sampleDirectory: integration-account-connections
8 | sharedResourceGroupIdentifier: shared
9 |
10 | trigger:
11 | - master
12 |
13 | stages:
14 | - stage: Development
15 | jobs:
16 | - job: DeployDevelopmentEnvironment
17 | variables:
18 | environment: d
19 | pool:
20 | vmImage: 'windows-2019'
21 | steps:
22 | - script: |
23 | echo ##vso[task.setvariable variable=resourceGroupName]$(groupId)$(environment)rgp$(location)-$(sharedResourceGroupIdentifier)
24 | echo ##vso[task.setvariable variable=templateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\shared-template.json
25 | echo ##vso[task.setvariable variable=logicAppDeployScript]$(Build.Repository.LocalPath)\$(sampleDirectory)\powershell\logic-app-deploy.ps1
26 | name: setDynamicVariableNames
27 | - powershell: |
28 | Write-Host "templateFilePath: $(templateFilePath)"
29 | Write-Host "resourceGroupName: $(resourceGroupName)"
30 | Write-Host "logicAppDeployScript: $(logicAppDeployScript)"
31 | name: printOutVariables
32 | - task: AzureResourceGroupDeployment@2
33 | name: SharedResourcesDeployment
34 | inputs:
35 | azureSubscription: 'Azure Samples Subscription'
36 | action: 'Create Or Update Resource Group'
37 | resourceGroupName: $(resourceGroupName)
38 | location: $(location)
39 | templateLocation: Linked artifact
40 | csmFile: $(templateFilePath)
41 | deploymentMode: 'Incremental'
42 | deploymentName: $(Build.BuildNumber)
43 | overrideParameters: -groupId $(groupId) -environment $(environment) -locationName $(abbrevLocationName)
44 | - script: |
45 | echo ##vso[task.setvariable variable=connectorsTemplateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\connectors-template.json
46 | echo ##vso[task.setvariable variable=logicAppTemplateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-template.json
47 | echo ##vso[task.setvariable variable=logicAppDefinitionPath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-definition.json
48 | echo ##vso[task.setvariable variable=logicAppDefinitionParametersFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-definition-parameters.json
49 | - task: AzurePowerShell@4
50 | name: DeployLogicAppSample
51 | inputs:
52 | azureSubscription: 'Azure Samples Subscription'
53 | ScriptType: 'FilePath'
54 | ScriptPath: '$(logicAppDeployScript)'
55 | FailOnStandardError: true
56 | azurePowerShellVersion: LatestVersion
57 | ScriptArguments: >-
58 | -groupId $(groupId)
59 | -location $(location)
60 | -abbrevLocationName $(abbrevLocationName)
61 | -environment $(environment)
62 | -instanceCount $(instanceCount)
63 | -identifier $(identifier)
64 | -connectorsTemplateFilePath $(connectorsTemplateFilePath)
65 | -logicAppTemplateFilePath $(logicAppTemplateFilePath)
66 | -logicAppDefinitionPath $(logicAppDefinitionPath)
67 | -logicAppDefinitionParametersFilePath $(logicAppDefinitionParametersFilePath)
--------------------------------------------------------------------------------
/integration-account-connections/powershell/clean-up.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deletes all resource groups where their names start with the "groupId" that's passed as input.
4 |
5 | .PARAMETER groupId
6 | The value that identifies the resource group to delete
7 | #>
8 |
9 | param(
10 | [Parameter(Mandatory = $True)]
11 | [string]
12 | $groupId
13 | )
14 |
15 | $resourceGroups = Get-AzResourceGroup;
16 |
17 | foreach ($resourceGroup in $resourceGroups) {
18 | if ($resourceGroup.ResourceGroupName.StartsWith($groupId, 'CurrentCultureIgnoreCase')) {
19 | Remove-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Force -AsJob
20 | Write-Host "Deleted resource group $($resourceGroup.ResourceGroupName)"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/integration-account-connections/powershell/full-deploy.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deploys a template for a logic app to Azure.
4 |
5 | .DESCRIPTION
6 | Deploys an Azure Resource Manager template with the LogicApp definition seperated within the directory
7 |
8 | .PARAMETER groupId
9 | The value used for constructing resources in the resource group and identifies the resources that are used together in a specific solution
10 |
11 | .PARAMETER location
12 | The region or location name to use for the resource group and the resources in that group
13 |
14 | .PARAMETER environment
15 | The alphabetical character that identifies the deployment environment to use in the name for each resource that's created in the resource group. For example, values include "d" for development, "t" for test, "s" for staging, and "p" for production.
16 |
17 | .PARAMETER abbrevLocationName
18 | The abbreviated region name that's used in resource names due to character limitations on some resource types. Defaults to the "location" parameter value.
19 |
20 | .PARAMETER deploymentName
21 | The name used for the deployment. If not given, a GUID is assigned as the deployment name.
22 |
23 | .PARAMETER instanceCount
24 | The number of resource group instances to create
25 |
26 | .PARAMETER overrideExistingLogicApp
27 | If true, the script runs the Azure Resource Manager template deployment for the logic app, even when the logic app already exists.
28 | #>
29 |
30 | param(
31 |
32 | [Parameter(Mandatory=$True)]
33 | [string]
34 | $groupId,
35 |
36 | [Parameter(Mandatory=$True)]
37 | [string]
38 | $location,
39 |
40 | [Parameter(Mandatory=$True)]
41 | [string]
42 | $environment,
43 |
44 | [Parameter(Mandatory=$False)]
45 | [string]
46 | $abbrevLocationName = $location,
47 |
48 | [Parameter(Mandatory=$False)]
49 | [string]
50 | $deploymentName = [guid]::NewGuid(),
51 |
52 | [Parameter(Mandatory=$False)]
53 | [int]
54 | $instanceCount = 1,
55 |
56 | [Parameter(Mandatory = $False)]
57 | [bool]
58 | $overrideExistingLogicApp = $True
59 | )
60 |
61 | Write-Host "Running shared deployment script"
62 |
63 | & "${PSScriptRoot}\shared-deploy.ps1" -groupId $groupId `
64 | -location $location `
65 | -environment $environment `
66 | -abbrevLocationName $abbrevLocationName `
67 | -deploymentName $deploymentName;
68 |
69 | Write-Host "Running logic app deployment script"
70 |
71 | & "${PSScriptRoot}\logic-app-deploy.ps1" -groupId $groupId `
72 | -location $location `
73 | -environment $environment `
74 | -abbrevLocationName $abbrevLocationName `
75 | -deploymentName $deploymentName `
76 | -identifier "sample-int-account" `
77 | -instanceCount $instanceCount `
78 | -overrideExisting $overrideExistingLogicApp;
--------------------------------------------------------------------------------
/integration-account-connections/powershell/shared-deploy.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deploy the shared resources.
4 |
5 | .DESCRIPTION
6 | Deploys an Azure Resource Manager template with the LogicApp definition seperated within the directory
7 |
8 | .PARAMETER groupId
9 | The value used for constructing resources in the resource group and identifies the resources that are used together in a specific solution
10 |
11 | .PARAMETER location
12 | The region or location name to use for the resource group and the resources in that group
13 |
14 | .PARAMETER environment
15 | The alphabetical character that identifies the deployment environment to use in the name for each resource that's created in the resource group. For example, values include "d" for development, "t" for test, "s" for staging, and "p" for production.
16 |
17 | .PARAMETER abbrevLocationName
18 | OPTIONAL: The abbreviated region name that's used in resource names due to character limitations on some resource types. Defaults to the "location" parameter value.
19 |
20 | .PARAMETER deploymentName
21 | OPTIONAL: The name used for the deployment. If not given, a GUID is assigned as the deployment name.
22 |
23 | .PARAMETER identifier
24 | OPTIONAL: Value appended to the end of the resource group and the logic app within the resource group
25 |
26 | .PARAMETER parametersFilePath
27 | OPTIONAL: Path to the parameter file. Defaults to the file contained within the local directory
28 |
29 | .PARAMETER templateFilePath
30 | OPTIONAL: Path to the template file. Defaults to the file contained within the local directory
31 | #>
32 |
33 | param(
34 | [Parameter(Mandatory = $True)]
35 | [string]
36 | $groupId,
37 |
38 | [Parameter(Mandatory = $True)]
39 | [string]
40 | $location,
41 |
42 | [Parameter(Mandatory = $True)]
43 | [string]
44 | $environment,
45 |
46 | [Parameter(Mandatory = $False)]
47 | [string]
48 | $abbrevLocationName = $location,
49 |
50 | [Parameter(Mandatory = $False)]
51 | [string]
52 | $deploymentName = [guid]::NewGuid(),
53 |
54 | [Parameter(Mandatory = $False)]
55 | [string]
56 | $identifier = "shared",
57 |
58 | [Parameter(Mandatory = $False)]
59 | [string]
60 | $parametersFilePath = "../templates/shared-parameters.json",
61 |
62 | [Parameter(Mandatory = $False)]
63 | [string]
64 | $templateFilePath = "../templates/shared-template.json"
65 | )
66 |
67 | Function RegisterRP {
68 | <#
69 | .SYNOPSIS
70 | Register the Azure resource provider.
71 | #>
72 | Param(
73 | [Parameter(Mandatory = $True, HelpMessage = "The name of the resource provider to register")]
74 | [string]$ResourceProviderNamespace
75 | )
76 |
77 | Write-Host "Registering resource provider '$ResourceProviderNamespace'";
78 | Register-AzResourceProvider -ProviderNamespace $ResourceProviderNamespace;
79 | }
80 |
81 | Function Set-RelativeFilePaths {
82 | <#
83 | .SYNOPSIS
84 | Fix relative paths that can't be evaluated as given.
85 | .DESCRIPTION
86 | Validate whether the file paths can be evaluated as they're passed as input.
87 | If the paths are relative and can't be found, try to fix by prepending the
88 | root path for script execution to the given path.
89 | #>
90 | Param()
91 | $parametersFilePath = Set-RelativeFilePath -filePath $parametersFilePath
92 | $templateFilePath = Set-RelativeFilePath -filePath $templateFilePath
93 | }
94 |
95 | Function Set-RelativeFilePath {
96 | <#
97 | .SYNOPSIS
98 | Validate a single file path and prepend the root path for script execution when the path fails.
99 | #>
100 | Param(
101 | [Parameter(Mandatory = $True, HelpMessage = "The path of the file to test whether the file exists")]
102 | [string]$filePath
103 | )
104 |
105 | if (Test-Path $filePath) {
106 | return $filePath;
107 | }
108 | else {
109 | return "{0}\{1}" -f $PSScriptRoot, $filePath;
110 | }
111 | }
112 |
113 | Function Set-ResourceGroup {
114 | <#
115 | .SYNOPSIS
116 | Check whether the resource group exists. If not, create the resource group.
117 | #>
118 | Param(
119 | [Parameter(Mandatory = $True, HelpMessage = "The name for the resource group to create, if not already existing")]
120 | [string]$resourceGroupName
121 | )
122 |
123 | Write-Host "Working with resource group name: '$resourceGroupName'"
124 |
125 | Write-Host "Checking whether the resource group exists"
126 | $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
127 | if (!$resourceGroup) {
128 | Write-Host "Resource group '$resourceGroupName' does not exist. Creating new resource group";
129 |
130 | Write-Host "Creating resource group '$resourceGroupName' in location '$location'";
131 | New-AzResourceGroup -Name $resourceGroupName -Location $location
132 | }
133 | else {
134 | Write-Host "Using existing resource group '$resourceGroupName'";
135 | }
136 | }
137 |
138 | Function New-ResourceManagerTemplateDeployment {
139 | <#
140 | .SYNOPSIS
141 | Create an Azure Resource Manager template deployment.
142 | .OUTPUTS
143 | The results from the Azure Resource Manager template deployment
144 | #>
145 | Param(
146 | [Parameter(Mandatory = $True, HelpMessage = "The path for the parameter file to use for deployment")]
147 | [string]$parametersFilePath,
148 | [Parameter(Mandatory = $True, HelpMessage = "The name for the resource group to use for deployment")]
149 | [string]$resourceGroupName,
150 | [Parameter(Mandatory = $True, HelpMessage = "The path to the template file to use for the deployment")]
151 | [string]$templateFilePath,
152 | [Parameter(Mandatory = $True, HelpMessage = "The values to append to the parameters before deployment")]
153 | [hashtable]$armParameters
154 | )
155 | if (Test-Path $parametersFilePath) {
156 | Write-Host "Loading parameters from file";
157 | $parametersFromFile = Get-Content -Raw -Encoding UTF8 -Path $parametersFilePath | ConvertFrom-Json
158 |
159 | Write-Host "Adding script parameters";
160 | New-Parameter -parameters $parametersFromFile -name "groupId" -value $groupId
161 | New-Parameter -parameters $parametersFromFile -name "environment" -value $environment
162 | New-Parameter -parameters $parametersFromFile -name "locationName" -value $locationName
163 |
164 | Write-Host "Starting deployment...";
165 | return New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath -TemplateParameterObject $parametersFromFile;
166 | }
167 | else {
168 | Write-Host "Starting deployment...";
169 | return New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath -TemplateParameterObject $armParameters;
170 | }
171 | }
172 |
173 | Function New-Parameter {
174 | <#
175 | .SYNOPSIS
176 | Append a parameter to the hash table for parameters that are passed as input.
177 | #>
178 | Param (
179 | [Parameter(Mandatory = $True, HelpMessage = "The hash table where to add the parameter")]
180 | [hashtable]$parameters,
181 | [Parameter(Mandatory = $True, HelpMessage = "The name for the parameter to add")]
182 | [string]$name,
183 | [Parameter(Mandatory = $True, HelpMessage = "The value for the parameter to add")]
184 | [string]$value
185 | )
186 | $parameters | Add-Member -MemberType NoteProperty -Name $name -Value @{value = $value }
187 | }
188 |
189 | #******************************************************************************
190 | # Script body
191 | # Execution begins here
192 | #******************************************************************************
193 |
194 | if (!$PSScriptRoot) { $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent }
195 |
196 | Set-RelativeFilePaths
197 |
198 | $resourceProviders = @("Microsoft.Logic");
199 | if ($resourceProviders.length) {
200 | Write-Host "Registering resource providers"
201 | foreach ($resourceProvider in $resourceProviders) {
202 | RegisterRP($resourceProvider);
203 | }
204 | }
205 |
206 | $resourceGroupName = "{0}{1}rgp{2}-{3}" -f $groupId, $environment, $location, $identifier
207 |
208 | Set-ResourceGroup -resourceGroupName $resourceGroupName
209 |
210 | $armParameters = @{
211 | groupId = $groupId
212 | environment = $environment
213 | locationName = $abbrevLocationName
214 | };
215 |
216 | New-ResourceManagerTemplateDeployment -parametersFilePath $parametersFilePath `
217 | -resourceGroupName $resourceGroupName `
218 | -templateFilePath $templateFilePath `
219 | -armParameters $armParameters
220 |
--------------------------------------------------------------------------------
/integration-account-connections/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_type: sample
3 | languages:
4 | - azurepowershell
5 | products:
6 | - azure
7 | - logic-apps
8 | - azure-resource-manager
9 | ---
10 |
11 | # Connect to an integration account from Azure Logic Apps and deploy by using Azure DevOps Pipelines
12 |
13 | This sample shows how to create a logic app that handles X12 messages by connecting to an integration account and deploy the app by using Azure DevOps Pipelines.
14 |
15 | In this topic, you complete the following tasks:
16 |
17 | * Set up the logic app with a connection to an integration account, which is used by most of the integration account's related actions.
18 |
19 | * Set up an X12 API connection, which is used by all the X12-related actions to work with the integration account.
20 |
21 | To learn more about the template and definition files in this sample and how they work, review [Samples file structure and definitions](../file-definitions.md).
22 |
23 | ## How this sample works
24 |
25 | This sample uses the outputs from creating the X12 connection and defines these output variables in the `connectors-template.json` file:
26 |
27 | ```json
28 | "outputs": {
29 | "x12ManagedApiId": {
30 | "type": "string",
31 | "value": "[variables('x12ConnectionId')]"
32 | },
33 | "x12ConnId": {
34 | "type": "string",
35 | "value": "[resourceId('Microsoft.Web/connections', variables('x12ConnectionName'))]"
36 | },
37 | "logicAppName": {
38 | "type": "string",
39 | "value": "[variables('logicAppName')]"
40 | }
41 | }
42 | ```
43 |
44 | The `logic-app-definition-parameters.json` file replaces the `x12ConnId` and `x12ManagedApiId` values and updates the logic app's definition with the resulting values:
45 |
46 | ```json
47 | {
48 | "$connections": {
49 | "value": {
50 | "x12": {
51 | "connectionId": "{x12ConnId}",
52 | "connectionName": "x12",
53 | "id": "{x12ManagedApiId}"
54 | }
55 | }
56 | }
57 | }
58 | ```
59 |
60 | In the `logic-app-template` file, the following code sets up the logic app to use the integration account that's defined in the `shared-template. json` file:
61 |
62 | ``` json
63 | "integrationAccount": {
64 | "id": "[resourceId(subscription().subscriptionId, variables('sharedResourceGroupName'), 'Microsoft.Logic/integrationAccounts', variables('integrationAccountName'))]"
65 | }
66 | ```
67 |
68 | ## Prerequisites
69 |
70 | * Install [Azure PowerShell 2.4.0](https://docs.microsoft.com/powershell/azure/install-az-ps?view=azps-2.4.0) on your platform.
71 |
72 | ## Set up sample
73 |
74 | To set up, deploy, and run this sample, you can use the command line or set up an Azure DevOps pipeline.
75 |
76 | ### Command line
77 |
78 | To run this sample from the command line, follow these steps.
79 |
80 | 1. Clone or download this sample repository.
81 |
82 | 1. Sign in to Azure by running this command from any command line tool that you want.
83 |
84 | ```powershell
85 | Connect-AzAccount
86 | ```
87 |
88 | 1. To target your deployment, select the appropriate [Azure context](https://docs.microsoft.com/powershell/module/az.accounts/Select-AzContext?view=azps-2.4.0) to use.
89 |
90 | 1. To push a full deployment for this sample to Azure, run this command from the PowerShell directory that contains this sample:
91 |
92 | ```powershell
93 | ./full-deploy.ps1 -groupId -environment -location
94 | ```
95 |
96 | ### Azure DevOps
97 |
98 | This sample uses [multi-stage YAML pipelines](https://docs.microsoft.com/azure/devops/pipelines/process/stages?view=azure-devops&tabs=yaml). To set up the sample pipeline, follow these steps:
99 |
100 | 1. Make sure that the [multi-stage pipeline preview feature](https://docs.microsoft.com/azure/devops/project/navigation/preview-features?view=azure-devops) is enabled.
101 |
102 | 1. Clone or fork the samples repository into your own repository.
103 |
104 | 1. Choose one of these steps:
105 |
106 | * Create an [Azure Resource Manager service connection](https://docs.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-azure-rm) that has the name "Azure Samples Subscription" in your project that points to the Azure subscription that you want to use for deployment.
107 |
108 | * Edit all instances of `azureSubscription: 'Azure Samples Subscription'` in the `./powershell/azure-pipelines.yml` file by using the name for an existing Azure Resource Manager service connection in your project.
109 |
110 | > [!NOTE]
111 | > To use the Azure Resource Manager service connection, make sure that the connection has selected the **Allow all pipelines to use this connection** checkbox. Otherwise, you must authorize the pipeline that you create in the next step.
112 |
113 | 1. Update these `./pipeline/azure-pipelines.yml` variables:
114 |
115 | * `groupId`: A value that's unique to you or your organization and is used to start the names for all resources and resource groups that are created
116 |
117 | * `location`: The name for the Azure region where you want to deploy the resources
118 |
119 | * `abbrevLocationName`: The abbreviated region name that's used in resource names
120 |
121 | 1. Create a new pipeline in your project that uses the `./powershell/azure-pipelines.yml` file from this sample.
122 |
123 | 
124 |
125 | ## Supporting documentation
126 |
127 | To learn more about the different parts in these samples, review these topics:
128 |
129 | * [Concepts](../concept-review.md) introduces the main concepts that underlie these samples.
130 |
131 | * [Naming convention](../naming-convention.md) describes the naming convention to use when creating the resources in these samples.
132 |
133 | * [Samples file structure and definitions](../file-definitions.md) explains the purpose for each file in these samples.
134 |
135 | * [Scaling](../api-connection-scale.md) expands on the reasons why these samples provide the capability to scale by increasing the number of copies for the logic apps deployed and organizing resources into separate resource groups.
136 |
137 | ## Resources
138 |
139 | This sample creates these resources:
140 |
141 | 
142 |
143 | To learn about the scripts in this sample and how they work, review [Samples file structure and definitions](../file-definitions.md).
144 |
145 | This sample also implements these template and definition files:
146 |
147 | | File name | Description |
148 | |-----------|-------------|
149 | | `shared-template.json` | This template creates and deploys an integration account. |
150 | | `connectors-template.json` | This template creates an X12 API connection to the integration account that's created by the `shared-template.json` file. |
151 | | `logic-app-template.json` | This template creates a shell for a logic app definition, which is blank to support separating the template from the definition. The logic app's integration account property is set up to point at the integration account that's created by the `shared-template.json` file. |
152 | | `logic-app-definition.json` | This file in this sample is blank. Any sample that's created for an integration account requires uploading and setting up the integration account with partners, agreements, schemas, and maps. This task is outside the scope for this specific sample. |
153 | |||
154 |
155 | ## Clean up
156 |
157 | When you're done with the sample, delete the resource groups that were created by the sample. To remove all the resource groups with names that start with a specific `groupId` value, run this command from the PowerShell directory that contains this sample:
158 |
159 | ```powershell
160 | ./clean-up.ps1 -groupId
161 | ```
162 |
--------------------------------------------------------------------------------
/integration-account-connections/templates/connectors-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "sharedResourceGroupName": "[toLower(concat(variables('baseName'), 'rgp', variables('location'), '-shared'))]",
42 | "baseConnectionsId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', variables('location'), '/managedApis/')]",
43 | "integrationAccountName": "[toLower(concat(variables('baseName'), 'iact', parameters('locationName')))]",
44 | "integrationAccountId": "[resourceId(subscription().subscriptionId, variables('sharedResourceGroupName'), 'Microsoft.Logic/integrationAccounts', variables('integrationAccountName'))]",
45 | "x12ConnectionName": "x12",
46 | "x12ConnectionId": "[concat(variables('baseConnectionsId'), 'x12')]",
47 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
48 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
49 | },
50 | "resources": [
51 | {
52 | "type": "Microsoft.Web/connections",
53 | "apiVersion": "2016-06-01",
54 | "name": "[variables('x12ConnectionName')]",
55 | "location": "[variables('location')]",
56 | "tags": {
57 | "groupdId": "[parameters('groupId')]"
58 | },
59 | "properties": {
60 | "displayName": "integrationAccount",
61 | "customParameterValues": {},
62 | "api": {
63 | "id": "[variables('x12ConnectionId')]"
64 | },
65 | "parameterValues": {
66 | "integrationAccountId": "[variables('integrationAccountId')]",
67 | "integrationAccountUrl": "[listCallbackURL(variables('integrationAccountId'), '2016-06-01').value]"
68 | }
69 | }
70 | }
71 | ],
72 | "outputs": {
73 | "x12ManagedApiId": {
74 | "type": "string",
75 | "value": "[variables('x12ConnectionId')]"
76 | },
77 | "x12ConnId": {
78 | "type": "string",
79 | "value": "[resourceId('Microsoft.Web/connections', variables('x12ConnectionName'))]"
80 | },
81 | "logicAppName": {
82 | "type": "string",
83 | "value": "[variables('logicAppName')]"
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/integration-account-connections/templates/logic-app-definition-parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$connections": {
3 | "value": {
4 | "x12": {
5 | "connectionId": "{x12ConnId}",
6 | "connectionName": "x12",
7 | "id": "{x12ManagedApiId}"
8 | }
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/integration-account-connections/templates/logic-app-definition.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "$connections": {
6 | "defaultValue": {},
7 | "type": "Object"
8 | }
9 | },
10 | "triggers": {},
11 | "actions": {},
12 | "outputs": {}
13 | }
--------------------------------------------------------------------------------
/integration-account-connections/templates/logic-app-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "sharedResourceGroupName": "[toLower(concat(variables('baseName'), 'rgp', variables('location'), '-shared'))]",
42 | "integrationAccountName": "[toLower(concat(variables('baseName'), 'iact', parameters('locationName')))]",
43 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
44 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
45 | },
46 | "resources": [
47 | {
48 | "name": "[variables('logicAppName')]",
49 | "type": "Microsoft.Logic/workflows",
50 | "location": "[variables('location')]",
51 | "apiVersion": "2016-06-01",
52 | "properties": {
53 | "integrationAccount": {
54 | "id": "[resourceId(subscription().subscriptionId, variables('sharedResourceGroupName'), 'Microsoft.Logic/integrationAccounts', variables('integrationAccountName'))]"
55 | },
56 | "definition": {
57 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
58 | "contentVersion": "1.0.0.0",
59 | "parameters": {},
60 | "triggers": {},
61 | "actions": {},
62 | "outputs": {}
63 | }
64 | }
65 | }
66 | ],
67 | "outputs": {
68 | "logicAppName": {
69 | "type": "string",
70 | "value": "[variables('logicAppName')]"
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/integration-account-connections/templates/shared-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "integrationAccountSku": {
25 | "type": "string",
26 | "allowedValues": [
27 | "Free",
28 | "Standard"
29 | ],
30 | "defaultValue": "Free",
31 | "metadata": {
32 | "description": "The SKU for the integration account"
33 | }
34 | }
35 | },
36 | "variables": {
37 | "location": "[resourceGroup().location]",
38 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
39 | "integrationAccountName": "[toLower(concat(variables('baseName'), 'iact', parameters('locationName')))]"
40 | },
41 | "resources": [
42 | {
43 | "name": "[variables('integrationAccountName')]",
44 | "type": "Microsoft.Logic/integrationAccounts",
45 | "apiVersion": "2016-06-01",
46 | "location": "[variables('location')]",
47 | "tags": {
48 | "groupdId": "[parameters('groupId')]"
49 | },
50 | "properties": {},
51 | "sku": {
52 | "name": "[parameters('integrationAccountSku')]"
53 | },
54 | "resources": []
55 | }
56 | ]
57 | }
--------------------------------------------------------------------------------
/naming-convention.md:
--------------------------------------------------------------------------------
1 | # Naming conventions for Azure resources
2 |
3 | This topic describes the naming convention that these samples use when creating the resources in the Azure Logic Apps samples for continuous integration (CI) and continuous deployment (CD) pipelines. This convention follows this format:
4 |
5 | `-`
6 |
7 | Based on each identifier that's described in this topic, here are some examples:
8 |
9 | | Group ID | Environment | Resource type | Region | Optional info | Resource name |
10 | |----------|-------------|---------------|--------|---------------|---------------|
11 | | cse01 | Development | Storage account V2 | West US | Ingest | cse01dsa2westusingest |
12 | | cse01 | Test | Logic app | Central US | Sample Service Bus connection | cse01tlacentralus-sample-sb-conn |
13 | | cse01 | Development | Resource group | Central US | Shared resources | cse01drgpentralus-shared |
14 | |||||||
15 |
16 | ## Group ID
17 |
18 | This label describes the higher-level functionality for a resource group because you can define multiple resource groups for a specific business solution.
19 |
20 | ## Environment
21 |
22 | This character represents the environment where the resource is used, for example:
23 |
24 | | Environment | Character |
25 | |-------------|-----------|
26 | | Development | d |
27 | | Test | t |
28 | | Integration | i |
29 | | Production | p |
30 | |||
31 |
32 | ## Resource type
33 |
34 | These characters are an acronym for the resource type, for example:
35 |
36 | | Resource type | Acronym |
37 | |---------------|---------|
38 | | Storage account | sa |
39 | | Storage account V2 | sa2 |
40 | | Function app | fa |
41 | | Logic app | la |
42 | | Integration account | iact |
43 | | Service Bus | sb |
44 | | Network security group | nsg |
45 | | Resource group | rgp |
46 | | Event hub | eh |
47 | | Event Grid subscription | egs |
48 | | Log Analytics workspace | law |
49 | | Log Analytics solution | las |
50 | |||
51 |
52 | ## Region
53 |
54 | The region where to deploy the resource as defined by the resource definition's `.location` property. For regions with long names, such as North Central US, you can use the designated abbreviation, for example, "West US" is `westus` and "Central US" is `centralus`.
55 |
56 | ## Optional information or identification
57 |
58 | If a solution uses more than one resource that has the same type, such as multiple storage accounts or function apps, those resources might need more information to identify its purpose. If the resource name permits, add a hyphen and a suitable label for this information.
59 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Azure Logic Apps: Set up a continuous integration (CI) and continuous delivery (CD) pipeline
2 |
3 | These samples show some strategies that you can use to implement a continuous integration (CI) and continuous delivery (CD) pipeline for Azure Logic Apps.
4 |
5 | ## Supporting documents
6 |
7 | To learn more about the different parts in these samples, review these topics:
8 |
9 | 1. [Concepts](concepts-review.md) introduces the main concepts that underlie these samples.
10 |
11 | 1. [Naming conventions](naming-convention.md) describes the naming convention to use when creating the resources in these samples.
12 |
13 | 1. [Samples file structure and definitions](file-definitions.md) explains the purpose for each file in these samples.
14 |
15 | 1. [Scaling](api-connection-scale.md) expands on the reasons why these samples provide the capability to scale by increasing the number of copies for the logic apps deployed and organizing resources into separate resource groups.
16 |
17 | ## Samples inventory
18 |
19 | * [Azure function app actions](./function-app-actions/)
20 | * [Azure Service Bus connections](./service-bus-connections/)
21 | * [Azure storage account connections](./storage-account-connections/)
22 | * [Integration account connections](./integration-account-connections/)
23 | * [API Management actions](./api-management-actions/)
24 |
--------------------------------------------------------------------------------
/service-bus-connections/powershell/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | location: westus
3 | groupId: cse01
4 | abbrevLocationName: westus
5 | instanceCount: 1
6 | identifier: sample-sb-conn
7 | sampleDirectory: service-bus-connections
8 | sharedResourceGroupIdentifier: shared
9 |
10 | trigger:
11 | - master
12 |
13 | stages:
14 | - stage: Development
15 | jobs:
16 | - job: DeployDevelopmentEnvironment
17 | variables:
18 | environment: d
19 | pool:
20 | vmImage: 'windows-2019'
21 | steps:
22 | - script: |
23 | echo ##vso[task.setvariable variable=resourceGroupName]$(groupId)$(environment)rgp$(location)-$(sharedResourceGroupIdentifier)
24 | echo ##vso[task.setvariable variable=templateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\shared-template.json
25 | echo ##vso[task.setvariable variable=logicAppDeployScript]$(Build.Repository.LocalPath)\$(sampleDirectory)\powershell\logic-app-deploy.ps1
26 | name: setDynamicVariableNames
27 | - powershell: |
28 | Write-Host "templateFilePath: $(templateFilePath)"
29 | Write-Host "resourceGroupName: $(resourceGroupName)"
30 | Write-Host "logicAppDeployScript: $(logicAppDeployScript)"
31 | name: printOutVariables
32 | - task: AzureResourceGroupDeployment@2
33 | name: SharedResourcesDeployment
34 | inputs:
35 | azureSubscription: 'Azure Samples Subscription'
36 | action: 'Create Or Update Resource Group'
37 | resourceGroupName: $(resourceGroupName)
38 | location: $(location)
39 | templateLocation: Linked artifact
40 | csmFile: $(templateFilePath)
41 | deploymentMode: 'Incremental'
42 | deploymentName: $(Build.BuildNumber)
43 | overrideParameters: -groupId $(groupId) -environment $(environment) -locationName $(abbrevLocationName)
44 | - script: |
45 | echo ##vso[task.setvariable variable=connectorsTemplateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\connectors-template.json
46 | echo ##vso[task.setvariable variable=logicAppTemplateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-template.json
47 | echo ##vso[task.setvariable variable=logicAppDefinitionPath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-definition.json
48 | echo ##vso[task.setvariable variable=logicAppDefinitionParametersFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-definition-parameters.json
49 | - task: AzurePowerShell@4
50 | name: DeployLogicAppSample
51 | inputs:
52 | azureSubscription: 'Azure Samples Subscription'
53 | ScriptType: 'FilePath'
54 | ScriptPath: '$(logicAppDeployScript)'
55 | FailOnStandardError: true
56 | azurePowerShellVersion: LatestVersion
57 | ScriptArguments: >-
58 | -groupId $(groupId)
59 | -location $(location)
60 | -abbrevLocationName $(abbrevLocationName)
61 | -environment $(environment)
62 | -instanceCount $(instanceCount)
63 | -identifier $(identifier)
64 | -connectorsTemplateFilePath $(connectorsTemplateFilePath)
65 | -logicAppTemplateFilePath $(logicAppTemplateFilePath)
66 | -logicAppDefinitionPath $(logicAppDefinitionPath)
67 | -logicAppDefinitionParametersFilePath $(logicAppDefinitionParametersFilePath)
--------------------------------------------------------------------------------
/service-bus-connections/powershell/clean-up.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deletes all resource groups where their names start with the "groupId" that's passed as input.
4 |
5 | .PARAMETER groupId
6 | The value that identifies the resource group to delete
7 | #>
8 |
9 | param(
10 | [Parameter(Mandatory = $True)]
11 | [string]
12 | $groupId
13 | )
14 |
15 | $resourceGroups = Get-AzResourceGroup;
16 |
17 | foreach ($resourceGroup in $resourceGroups) {
18 | if ($resourceGroup.ResourceGroupName.StartsWith($groupId, 'CurrentCultureIgnoreCase')) {
19 | Remove-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Force -AsJob
20 | Write-Host "Deleted resource group $($resourceGroup.ResourceGroupName)"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/service-bus-connections/powershell/full-deploy.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deploys a template for a logic app to Azure.
4 |
5 | .DESCRIPTION
6 | Deploys an Azure Resource Manager template with the LogicApp definition seperated within the directory
7 |
8 | .PARAMETER groupId
9 | The value used for constructing resources in the resource group and identifies the resources that are used together in a specific solution
10 |
11 | .PARAMETER location
12 | The region or location name to use for the resource group and the resources in that group
13 |
14 | .PARAMETER environment
15 | The alphabetical character that identifies the deployment environment to use in the name for each resource that's created in the resource group. For example, values include "d" for development, "t" for test, "s" for staging, and "p" for production.
16 |
17 | .PARAMETER abbrevLocationName
18 | The abbreviated region name that's used in resource names due to character limitations on some resource types. Defaults to the "location" parameter value.
19 |
20 | .PARAMETER deploymentName
21 | The name used for the deployment. If not given, a GUID is assigned as the deployment name.
22 |
23 | .PARAMETER instanceCount
24 | The number of resource group instances to create
25 |
26 | .PARAMETER overrideExistingLogicApp
27 | If true, the script runs the Azure Resource Manager template deployment for the logic app, even when the logic app already exists.
28 | #>
29 |
30 | param(
31 |
32 | [Parameter(Mandatory=$True)]
33 | [string]
34 | $groupId,
35 |
36 | [Parameter(Mandatory=$True)]
37 | [string]
38 | $location,
39 |
40 | [Parameter(Mandatory=$True)]
41 | [string]
42 | $environment,
43 |
44 | [Parameter(Mandatory=$False)]
45 | [string]
46 | $abbrevLocationName = $location,
47 |
48 | [Parameter(Mandatory=$False)]
49 | [string]
50 | $deploymentName = [guid]::NewGuid(),
51 |
52 | [Parameter(Mandatory=$False)]
53 | [int]
54 | $instanceCount = 1,
55 |
56 | [Parameter(Mandatory = $False)]
57 | [bool]
58 | $overrideExistingLogicApp = $True
59 | )
60 |
61 | Write-Host "Running shared deployment script"
62 |
63 | & "${PSScriptRoot}\shared-deploy.ps1" -groupId $groupId `
64 | -location $location `
65 | -environment $environment `
66 | -abbrevLocationName $abbrevLocationName `
67 | -deploymentName $deploymentName;
68 |
69 | Write-Host "Running logic app deployment script"
70 |
71 | & "${PSScriptRoot}\logic-app-deploy.ps1" -groupId $groupId `
72 | -location $location `
73 | -environment $environment `
74 | -abbrevLocationName $abbrevLocationName `
75 | -deploymentName $deploymentName `
76 | -identifier "sample-sb-conn" `
77 | -instanceCount $instanceCount `
78 | -overrideExisting $overrideExistingLogicApp;
--------------------------------------------------------------------------------
/service-bus-connections/powershell/shared-deploy.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deploy the shared resources.
4 |
5 | .DESCRIPTION
6 | Deploys an Azure Resource Manager template with the LogicApp definition seperated within the directory
7 |
8 | .PARAMETER groupId
9 | The value used for constructing resources in the resource group and identifies the resources that are used together in a specific solution
10 |
11 | .PARAMETER location
12 | The region or location name to use for the resource group and the resources in that group
13 |
14 | .PARAMETER environment
15 | The alphabetical character that identifies the deployment environment to use in the name for each resource that's created in the resource group. For example, values include "d" for development, "t" for test, "s" for staging, and "p" for production.
16 |
17 | .PARAMETER abbrevLocationName
18 | OPTIONAL: The abbreviated region name that's used in resource names due to character limitations on some resource types. Defaults to the "location" parameter value.
19 |
20 | .PARAMETER deploymentName
21 | OPTIONAL: The name used for the deployment. If not given, a GUID is assigned as the deployment name.
22 |
23 | .PARAMETER identifier
24 | OPTIONAL: Value appended to the end of the resource group and the logic app within the resource group
25 |
26 | .PARAMETER parametersFilePath
27 | OPTIONAL: Path to the parameter file. Defaults to the file contained within the local directory
28 |
29 | .PARAMETER templateFilePath
30 | OPTIONAL: Path to the template file. Defaults to the file contained within the local directory
31 | #>
32 |
33 | param(
34 | [Parameter(Mandatory = $True)]
35 | [string]
36 | $groupId,
37 |
38 | [Parameter(Mandatory = $True)]
39 | [string]
40 | $location,
41 |
42 | [Parameter(Mandatory = $True)]
43 | [string]
44 | $environment,
45 |
46 | [Parameter(Mandatory = $False)]
47 | [string]
48 | $abbrevLocationName = $location,
49 |
50 | [Parameter(Mandatory = $False)]
51 | [string]
52 | $deploymentName = [guid]::NewGuid(),
53 |
54 | [Parameter(Mandatory = $False)]
55 | [string]
56 | $identifier = "shared",
57 |
58 | [Parameter(Mandatory = $False)]
59 | [string]
60 | $parametersFilePath = "../templates/shared-parameters.json",
61 |
62 | [Parameter(Mandatory = $False)]
63 | [string]
64 | $templateFilePath = "../templates/shared-template.json"
65 | )
66 |
67 | Function RegisterRP {
68 | <#
69 | .SYNOPSIS
70 | Register the Azure resource provider.
71 | #>
72 | Param(
73 | [Parameter(Mandatory = $True, HelpMessage = "The name of the resource provider to register")]
74 | [string]$ResourceProviderNamespace
75 | )
76 |
77 | Write-Host "Registering resource provider '$ResourceProviderNamespace'";
78 | Register-AzResourceProvider -ProviderNamespace $ResourceProviderNamespace;
79 | }
80 |
81 | Function Set-RelativeFilePaths {
82 | <#
83 | .SYNOPSIS
84 | Fix relative paths that can't be evaluated as given.
85 | .DESCRIPTION
86 | Validate whether the file paths can be evaluated as they're passed as input.
87 | If the paths are relative and can't be found, try to fix by prepending the
88 | root path for script execution to the given path.
89 | #>
90 | Param()
91 | $parametersFilePath = Set-RelativeFilePath -filePath $parametersFilePath
92 | $templateFilePath = Set-RelativeFilePath -filePath $templateFilePath
93 | }
94 |
95 | Function Set-RelativeFilePath {
96 | <#
97 | .SYNOPSIS
98 | Validate a single file path and prepend the root path for script execution when the path fails.
99 | #>
100 | Param(
101 | [Parameter(Mandatory = $True, HelpMessage = "The path of the file to test whether the file exists")]
102 | [string]$filePath
103 | )
104 |
105 | if (Test-Path $filePath) {
106 | return $filePath;
107 | }
108 | else {
109 | return "{0}\{1}" -f $PSScriptRoot, $filePath;
110 | }
111 | }
112 |
113 | Function Set-ResourceGroup {
114 | <#
115 | .SYNOPSIS
116 | Check whether the resource group exists. If not, create the resource group.
117 | #>
118 | Param(
119 | [Parameter(Mandatory = $True, HelpMessage = "The name for the resource group to create, if not already existing")]
120 | [string]$resourceGroupName
121 | )
122 |
123 | Write-Host "Working with resource group name: '$resourceGroupName'"
124 |
125 | Write-Host "Checking whether the resource group exists"
126 | $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
127 | if (!$resourceGroup) {
128 | Write-Host "Resource group '$resourceGroupName' does not exist. Creating new resource group";
129 |
130 | Write-Host "Creating resource group '$resourceGroupName' in location '$location'";
131 | New-AzResourceGroup -Name $resourceGroupName -Location $location
132 | }
133 | else {
134 | Write-Host "Using existing resource group '$resourceGroupName'";
135 | }
136 | }
137 |
138 | Function New-ResourceManagerTemplateDeployment {
139 | <#
140 | .SYNOPSIS
141 | Create an Azure Resource Manager template deployment.
142 | .OUTPUTS
143 | The results from the Azure Resource Manager template deployment
144 | #>
145 | Param(
146 | [Parameter(Mandatory = $True, HelpMessage = "The path for the parameter file to use for deployment")]
147 | [string]$parametersFilePath,
148 | [Parameter(Mandatory = $True, HelpMessage = "The name for the resource group to use for deployment")]
149 | [string]$resourceGroupName,
150 | [Parameter(Mandatory = $True, HelpMessage = "The path to the template file to use for the deployment")]
151 | [string]$templateFilePath,
152 | [Parameter(Mandatory = $True, HelpMessage = "The values to append to the parameters before deployment")]
153 | [hashtable]$armParameters
154 | )
155 | if (Test-Path $parametersFilePath) {
156 | Write-Host "Loading parameters from file";
157 | $parametersFromFile = Get-Content -Raw -Encoding UTF8 -Path $parametersFilePath | ConvertFrom-Json
158 |
159 | Write-Host "Adding script parameters";
160 | New-Parameter -parameters $parametersFromFile -name "groupId" -value $groupId
161 | New-Parameter -parameters $parametersFromFile -name "environment" -value $environment
162 | New-Parameter -parameters $parametersFromFile -name "locationName" -value $locationName
163 |
164 | Write-Host "Starting deployment...";
165 | return New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath -TemplateParameterObject $parametersFromFile;
166 | }
167 | else {
168 | Write-Host "Starting deployment...";
169 | return New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath -TemplateParameterObject $armParameters;
170 | }
171 | }
172 |
173 | Function New-Parameter {
174 | <#
175 | .SYNOPSIS
176 | Append a parameter to the hash table for parameters that are passed as input.
177 | #>
178 | Param (
179 | [Parameter(Mandatory = $True, HelpMessage = "The hash table where to add the parameter")]
180 | [hashtable]$parameters,
181 | [Parameter(Mandatory = $True, HelpMessage = "The name for the parameter to add")]
182 | [string]$name,
183 | [Parameter(Mandatory = $True, HelpMessage = "The value for the parameter to add")]
184 | [string]$value
185 | )
186 | $parameters | Add-Member -MemberType NoteProperty -Name $name -Value @{value = $value }
187 | }
188 |
189 | #******************************************************************************
190 | # Script body
191 | # Execution begins here
192 | #******************************************************************************
193 |
194 | if (!$PSScriptRoot) { $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent }
195 |
196 | Set-RelativeFilePaths
197 |
198 | $resourceProviders = @("microsoft.servicebus");
199 | if ($resourceProviders.length) {
200 | Write-Host "Registering resource providers"
201 | foreach ($resourceProvider in $resourceProviders) {
202 | RegisterRP($resourceProvider);
203 | }
204 | }
205 |
206 | $resourceGroupName = "{0}{1}rgp{2}-{3}" -f $groupId, $environment, $location, $identifier
207 |
208 | Set-ResourceGroup -resourceGroupName $resourceGroupName
209 |
210 | $armParameters = @{
211 | groupId = $groupId
212 | environment = $environment
213 | locationName = $abbrevLocationName
214 | };
215 |
216 | New-ResourceManagerTemplateDeployment -parametersFilePath $parametersFilePath `
217 | -resourceGroupName $resourceGroupName `
218 | -templateFilePath $templateFilePath `
219 | -armParameters $armParameters
220 |
--------------------------------------------------------------------------------
/service-bus-connections/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_type: sample
3 | languages:
4 | - azurepowershell
5 | products:
6 | - azure
7 | - logic-apps
8 | - azure-resource-manager
9 | - azure-service-bus
10 | ---
11 |
12 | # Connect to Azure Service Bus queues from Azure Logic Apps and deploy with Azure DevOps Pipelines
13 |
14 | This sample shows how to create a logic app that handles messages in an Azure Service Bus queue and deploy the app by using Azure DevOps Pipelines. The logic app creates Azure Service Bus API connections: one connection reads messages from the queue while the other connection sends messages to the queue. To learn more about the template and definition files in this sample and how they work, review [Samples file structure and definitions](../file-definitions.md).
15 |
16 | ## How this sample works
17 |
18 | This sample uses the outputs from creating Azure Service Bus connections and defines these output variables in the `connectors-template.json` file:
19 |
20 | ```json
21 | "outputs": {
22 | "serviceBusManagedApiId": {
23 | "type": "string",
24 | "value": "[variables('serviceBusConnectionId')]"
25 | },
26 | "serviceBusConnId1": {
27 | "type": "string",
28 | "value": "[resourceId('Microsoft.Web/connections', concat(variables('serviceBusConnectionName'), '-1'))]"
29 | },
30 | "serviceBusConnId2": {
31 | "type": "string",
32 | "value": "[resourceId('Microsoft.Web/connections', concat(variables('serviceBusConnectionName'), '-2'))]"
33 | },
34 | "logicAppName": {
35 | "type": "string",
36 | "value": "[variables('logicAppName')]"
37 | }
38 | }
39 | ```
40 |
41 | The `logic-app-definition-parameters.json` file replaces the `serviceBusConnId1`, `serviceBusConnId2`, and `serviceBusManagedApiId` values and updates the logic app's definition with the resulting values:
42 |
43 | ``` json
44 | {
45 | "$connections": {
46 | "value": {
47 | "servicebus-1": {
48 | "connectionId": "{serviceBusConnId1}",
49 | "connectionName": "servicebus-1",
50 | "id": "{serviceBusManagedApiId}"
51 | },
52 | "servicebus-2": {
53 | "connectionId": "{serviceBusConnId2}",
54 | "connectionName": "servicebus-2",
55 | "id": "{serviceBusManagedApiId}"
56 | }
57 | }
58 | }
59 | }
60 | ```
61 |
62 | ## Prerequisites
63 |
64 | * Install [Azure PowerShell 2.4.0](https://docs.microsoft.com/powershell/azure/install-az-ps?view=azps-2.4.0) on your platform.
65 |
66 | ## Set up sample
67 |
68 | To set up, deploy, and run this sample, you can use the command line or set up an Azure DevOps pipeline.
69 |
70 | ### Command line
71 |
72 | To run this sample from the command line, follow these steps.
73 |
74 | 1. Clone or download this sample repository.
75 |
76 | 1. Sign in to Azure by running this command from any command line tool that you want.
77 |
78 | ```powershell
79 | Connect-AzAccount
80 | ```
81 |
82 | 1. To target your deployment, select the appropriate [Azure context](https://docs.microsoft.com/powershell/module/az.accounts/Select-AzContext?view=azps-2.4.0) to use.
83 |
84 | 1. To push a full deployment for this sample to Azure, run this command from the PowerShell directory that contains this sample:
85 |
86 | ```powershell
87 | ./full-deploy.ps1 -groupId -environment -location
88 | ```
89 |
90 | ### Azure DevOps
91 |
92 | This sample uses [multi-stage YAML pipelines](https://docs.microsoft.com/azure/devops/pipelines/process/stages?view=azure-devops&tabs=yaml). To set up the sample pipeline, follow these steps:
93 |
94 | 1. Make sure that the [multi-stage pipeline preview feature](https://docs.microsoft.com/azure/devops/project/navigation/preview-features?view=azure-devops) is enabled.
95 |
96 | 1. Clone or fork the samples repository into your own repository.
97 |
98 | 1. Choose one of these steps:
99 |
100 | * Create an [Azure Resource Manager service connection](https://docs.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-azure-rm) that has the name "Azure Samples Subscription" in your project that points to the Azure subscription that you want to use for deployment.
101 |
102 | * Edit all instances of `azureSubscription: 'Azure Samples Subscription'` in the `./powershell/azure-pipelines.yml` file by using the name for an existing Azure Resource Manager service connection in your project.
103 |
104 | > [!NOTE]
105 | > To use the Azure Resource Manager service connection, make sure that the connection has selected the **Allow all pipelines to use this connection** checkbox. Otherwise, you must authorize the pipeline that you create in the next step.
106 |
107 | 1. Update these `./pipeline/azure-pipelines.yml` variables:
108 |
109 | * `groupId`: A value that's unique to you or your organization and is used to start the names for all resources and resource groups that are created
110 |
111 | * `location`: The name for the Azure region where you want to deploy the resources
112 |
113 | * `abbrevLocationName`: The abbreviated region name that's used in resource names
114 |
115 | 1. Create a new pipeline in your project that uses the `./powershell/azure-pipelines.yml` file from this sample.
116 |
117 | 
118 |
119 | ## Supporting documentation
120 |
121 | To learn more about the different parts in these samples, review these topics:
122 |
123 | * [Concepts](../concept-review.md) introduces the main concepts that underlie these samples.
124 |
125 | * [Naming convention](../naming-convention.md) describes the naming convention to use when creating the resources in these samples.
126 |
127 | * [Samples file structure and definitions](../file-definitions.md) explains the purpose for each file in these samples.
128 |
129 | * [Scaling](../api-connection-scale.md) expands on the reasons why these samples provide the capability to scale by increasing the number of copies for the logic apps deployed and organizing resources into separate resource groups.
130 |
131 | ## Resources
132 |
133 | This sample creates these resources:
134 |
135 | 
136 |
137 | To learn about the scripts in this sample and how they work, review [Samples file structure and definitions](../file-definitions.md).
138 |
139 | This sample also implements these template and definition files:
140 |
141 | | File name | Description |
142 | |-----------|-------------|
143 | | `shared-template.json` | This template creates a single service bus resource that sets up the `queue_1` and `queue_2` queues. |
144 | | `connectors-template.json` | This template creates two Service Bus API connections. Both connections are set up with the connection strings for the service bus that's created by the `shared_template.json` file. |
145 | | `logic-app-template.json` | This template creates a shell for a logic app definition, which is blank to support separating the template from the definition. |
146 | | `logic-app-definition.json` | This file defines a basic logic app that gets a message from `queue_1` by using one API connection and sends the message to `queue_2` by using the other API connection. |
147 | | `logic-app-definition-parameters.json` | This file contains the setup information for the Azure Service Bus connectors. |
148 | |||
149 |
150 | ## Clean up
151 |
152 | When you're done with the sample, delete the resource groups that were created by the sample. To remove all the resource groups with names that start with a specific `groupId` value, run this command from the PowerShell directory that contains this sample:
153 |
154 | ```powershell
155 | ./clean-up.ps1 -groupId
156 | ```
157 |
--------------------------------------------------------------------------------
/service-bus-connections/templates/connectors-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "sharedResourceGroupName": "[toLower(concat(variables('baseName'), 'rgp', variables('location'), '-shared'))]",
42 | "servicesBusName": "[toLower(concat(variables('baseName'), 'sb', parameters('locationName')))]",
43 | "serviceBusAuthRuleId": "[resourceId(subscription().subscriptionId, variables('sharedResourceGroupName'), 'Microsoft.ServiceBus/namespaces/authorizationRules', variables('servicesBusName'), 'RootManageSharedAccessKey')]",
44 | "baseConnectionsId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', variables('location'), '/managedApis/')]",
45 | "serviceBusConnectionName": "servicebus",
46 | "serviceBusConnectionId": "[concat(variables('baseConnectionsId'), 'servicebus')]",
47 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
48 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
49 | },
50 | "resources": [
51 | {
52 | "type": "Microsoft.Web/connections",
53 | "apiVersion": "2016-06-01",
54 | "name": "[concat(variables('serviceBusConnectionName'), '-1')]",
55 | "location": "[variables('location')]",
56 | "tags": {
57 | "groupdId": "[parameters('groupId')]"
58 | },
59 | "properties": {
60 | "displayName": "[variables('serviceBusConnectionName')]",
61 | "customParameterValues": {},
62 | "api": {
63 | "id": "[variables('serviceBusConnectionId')]"
64 | },
65 | "parameterValues": {
66 | "connectionString": "[listKeys(variables('ServiceBusAuthRuleId'), '2015-08-01').primaryConnectionString]"
67 | }
68 | }
69 | },
70 | {
71 | "type": "Microsoft.Web/connections",
72 | "apiVersion": "2016-06-01",
73 | "name": "[concat(variables('serviceBusConnectionName'), '-2')]",
74 | "location": "[variables('location')]",
75 | "tags": {
76 | "groupdId": "[parameters('groupId')]"
77 | },
78 | "properties": {
79 | "displayName": "[variables('serviceBusConnectionName')]",
80 | "customParameterValues": {},
81 | "api": {
82 | "id": "[variables('serviceBusConnectionId')]"
83 | },
84 | "parameterValues": {
85 | "connectionString": "[listKeys(variables('ServiceBusAuthRuleId'), '2015-08-01').primaryConnectionString]"
86 | }
87 | }
88 | }
89 | ],
90 | "outputs": {
91 | "serviceBusManagedApiId": {
92 | "type": "string",
93 | "value": "[variables('serviceBusConnectionId')]"
94 | },
95 | "serviceBusConnId1": {
96 | "type": "string",
97 | "value": "[resourceId('Microsoft.Web/connections', concat(variables('serviceBusConnectionName'), '-1'))]"
98 | },
99 | "serviceBusConnId2": {
100 | "type": "string",
101 | "value": "[resourceId('Microsoft.Web/connections', concat(variables('serviceBusConnectionName'), '-2'))]"
102 | },
103 | "logicAppName": {
104 | "type": "string",
105 | "value": "[variables('logicAppName')]"
106 | }
107 | }
108 | }
--------------------------------------------------------------------------------
/service-bus-connections/templates/logic-app-definition-parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$connections": {
3 | "value": {
4 | "servicebus-1": {
5 | "connectionId": "{serviceBusConnId1}",
6 | "connectionName": "servicebus-1",
7 | "id": "{serviceBusManagedApiId}"
8 | },
9 | "servicebus-2": {
10 | "connectionId": "{serviceBusConnId2}",
11 | "connectionName": "servicebus-2",
12 | "id": "{serviceBusManagedApiId}"
13 | }
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/service-bus-connections/templates/logic-app-definition.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "$connections": {
6 | "defaultValue": {},
7 | "type": "Object"
8 | }
9 | },
10 | "triggers": {
11 | "When_a_message_is_received_in_a_queue_(peek-lock)": {
12 | "recurrence": {
13 | "frequency": "Minute",
14 | "interval": 1
15 | },
16 | "type": "ApiConnection",
17 | "inputs": {
18 | "host": {
19 | "connection": {
20 | "name": "@parameters('$connections')['servicebus-1']['connectionId']"
21 | }
22 | },
23 | "method": "get",
24 | "path": "/@{encodeURIComponent(encodeURIComponent('queue_1'))}/messages/head/peek",
25 | "queries": {
26 | "queueType": "Main",
27 | "sessionId": "None"
28 | }
29 | }
30 | }
31 | },
32 | "actions": {
33 | "Complete_the_message_in_a_queue": {
34 | "runAfter": {
35 | "Send_message": [
36 | "Succeeded"
37 | ]
38 | },
39 | "type": "ApiConnection",
40 | "inputs": {
41 | "host": {
42 | "connection": {
43 | "name": "@parameters('$connections')['servicebus-1']['connectionId']"
44 | }
45 | },
46 | "method": "delete",
47 | "path": "/@{encodeURIComponent(encodeURIComponent('queue_1'))}/messages/complete",
48 | "queries": {
49 | "lockToken": "@triggerBody()?['LockToken']",
50 | "queueType": "Main",
51 | "sessionId": ""
52 | }
53 | }
54 | },
55 | "Initialize_variable": {
56 | "runAfter": {},
57 | "type": "InitializeVariable",
58 | "inputs": {
59 | "variables": [
60 | {
61 | "name": "awesomeStuff",
62 | "type": "String",
63 | "value": "HappensHere"
64 | }
65 | ]
66 | }
67 | },
68 | "Send_message": {
69 | "runAfter": {
70 | "Initialize_variable": [
71 | "Succeeded"
72 | ]
73 | },
74 | "type": "ApiConnection",
75 | "inputs": {
76 | "body": {
77 | "ContentData": "@{triggerBody()?['ContentData']}",
78 | "ContentType": "@triggerBody()?['ContentType']",
79 | "CorrelationId": "@triggerBody()?['CorrelationId']",
80 | "Properties": "@triggerBody()?['Properties']"
81 | },
82 | "host": {
83 | "connection": {
84 | "name": "@parameters('$connections')['servicebus-2']['connectionId']"
85 | }
86 | },
87 | "method": "post",
88 | "path": "/@{encodeURIComponent(encodeURIComponent('queue_2'))}/messages",
89 | "queries": {
90 | "systemProperties": "None"
91 | }
92 | }
93 | }
94 | },
95 | "outputs": {}
96 | }
--------------------------------------------------------------------------------
/service-bus-connections/templates/logic-app-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
42 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
43 | },
44 | "resources": [
45 | {
46 | "name": "[variables('logicAppName')]",
47 | "type": "Microsoft.Logic/workflows",
48 | "location": "[variables('location')]",
49 | "apiVersion": "2016-06-01",
50 | "properties": {
51 | "definition": {
52 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
53 | "contentVersion": "1.0.0.0",
54 | "parameters": {},
55 | "triggers": {},
56 | "actions": {},
57 | "outputs": {}
58 | }
59 | }
60 | }
61 | ],
62 | "outputs": {
63 | "logicAppName": {
64 | "type": "string",
65 | "value": "[variables('logicAppName')]"
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/service-bus-connections/templates/shared-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "queues": {
25 | "type": "array",
26 | "defaultValue": [
27 | "queue_1",
28 | "queue_2"
29 | ],
30 | "metadata": {
31 | "description": "The array of queues to create"
32 | }
33 | },
34 | "serviceBusSku": {
35 | "type": "string",
36 | "allowedValues": [
37 | "Standard",
38 | "Premium"
39 | ],
40 | "defaultValue": "Standard",
41 | "metadata": {
42 | "description": "The SKU for the Azure Service Bus namespace"
43 | }
44 | },
45 | "serviceBusCapacity": {
46 | "type": "int",
47 | "allowedValues": [
48 | 1,
49 | 2,
50 | 4
51 | ],
52 | "defaultValue": 1,
53 | "metadata": {
54 | "description": "The specified messaging units for the Azure Service Bus namespace"
55 | }
56 | }
57 | },
58 | "variables": {
59 | "location": "[resourceGroup().location]",
60 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
61 | "servicesBusName": "[toLower(concat(variables('baseName'), 'sb', parameters('locationName')))]"
62 | },
63 | "resources": [
64 | {
65 | "name": "[variables('servicesBusName')]",
66 | "type": "Microsoft.ServiceBus/namespaces",
67 | "apiVersion": "2017-04-01",
68 | "tags": {
69 | "groupdId": "[parameters('groupId')]"
70 | },
71 | "location": "[variables('location')]",
72 | "sku": {
73 | "name": "[parameters('serviceBusSku')]",
74 | "tier": "[parameters('serviceBusSku')]",
75 | "capacity": "[parameters('serviceBusCapacity')]"
76 | },
77 | "properties": {},
78 | "resources": []
79 | },
80 | {
81 | "name": "[concat(variables('servicesBusName'), '/',parameters('queues')[copyindex()])]",
82 | "type": "Microsoft.ServiceBus/namespaces/queues",
83 | "apiVersion": "2017-04-01",
84 | "tags": {
85 | "groupdId": "[parameters('groupId')]"
86 | },
87 | "dependsOn": [
88 | "[resourceId('Microsoft.ServiceBus/namespaces', variables('servicesBusName'))]"
89 | ],
90 | "copy": {
91 | "name": "queueCopy",
92 | "count": "[length(parameters('queues'))]"
93 | },
94 | "properties": {
95 | "requiresDuplicateDetection": true,
96 | "requiresSession": true,
97 | "enableBatchedOperations": true
98 | },
99 | "resources": []
100 | },
101 | {
102 | "type": "Microsoft.ServiceBus/namespaces/AuthorizationRules",
103 | "name": "[concat(variables('servicesBusName'), '/', 'RootManageSharedAccessKey')]",
104 | "apiVersion": "2017-04-01",
105 | "location": "[variables('location')]",
106 | "dependsOn": [
107 | "[resourceId('Microsoft.ServiceBus/namespaces', variables('servicesBusName'))]"
108 | ],
109 | "properties": {
110 | "rights": [
111 | "Listen",
112 | "Manage",
113 | "Send"
114 | ]
115 | }
116 | }
117 | ]
118 | }
--------------------------------------------------------------------------------
/storage-account-connections/powershell/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | location: westus
3 | groupId: cse01
4 | abbrevLocationName: westus
5 | instanceCount: 1
6 | identifier: sample-storage-conn
7 | sampleDirectory: storage-account-connections
8 | sharedResourceGroupIdentifier: shared
9 |
10 | trigger:
11 | - master
12 |
13 | stages:
14 | - stage: Development
15 | jobs:
16 | - job: DeployDevelopmentEnvironment
17 | variables:
18 | environment: d
19 | pool:
20 | vmImage: 'windows-2019'
21 | steps:
22 | - script: |
23 | echo ##vso[task.setvariable variable=resourceGroupName]$(groupId)$(environment)rgp$(location)-$(sharedResourceGroupIdentifier)
24 | echo ##vso[task.setvariable variable=templateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\shared-template.json
25 | echo ##vso[task.setvariable variable=logicAppDeployScript]$(Build.Repository.LocalPath)\$(sampleDirectory)\powershell\logic-app-deploy.ps1
26 | name: setDynamicVariableNames
27 | - powershell: |
28 | Write-Host "templateFilePath: $(templateFilePath)"
29 | Write-Host "resourceGroupName: $(resourceGroupName)"
30 | Write-Host "logicAppDeployScript: $(logicAppDeployScript)"
31 | name: printOutVariables
32 | - task: AzureResourceGroupDeployment@2
33 | name: SharedResourcesDeployment
34 | inputs:
35 | azureSubscription: 'Azure Samples Subscription'
36 | action: 'Create Or Update Resource Group'
37 | resourceGroupName: $(resourceGroupName)
38 | location: $(location)
39 | templateLocation: Linked artifact
40 | csmFile: $(templateFilePath)
41 | deploymentMode: 'Incremental'
42 | deploymentName: $(Build.BuildNumber)
43 | overrideParameters: -groupId $(groupId) -environment $(environment) -locationName $(abbrevLocationName)
44 | - script: |
45 | echo ##vso[task.setvariable variable=connectorsTemplateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\connectors-template.json
46 | echo ##vso[task.setvariable variable=logicAppTemplateFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-template.json
47 | echo ##vso[task.setvariable variable=logicAppDefinitionPath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-definition.json
48 | echo ##vso[task.setvariable variable=logicAppDefinitionParametersFilePath]$(Build.Repository.LocalPath)\$(sampleDirectory)\templates\logic-app-definition-parameters.json
49 | - task: AzurePowerShell@4
50 | name: DeployLogicAppSample
51 | inputs:
52 | azureSubscription: 'Azure Samples Subscription'
53 | ScriptType: 'FilePath'
54 | ScriptPath: '$(logicAppDeployScript)'
55 | FailOnStandardError: true
56 | azurePowerShellVersion: LatestVersion
57 | ScriptArguments: >-
58 | -groupId $(groupId)
59 | -location $(location)
60 | -abbrevLocationName $(abbrevLocationName)
61 | -environment $(environment)
62 | -instanceCount $(instanceCount)
63 | -identifier $(identifier)
64 | -connectorsTemplateFilePath $(connectorsTemplateFilePath)
65 | -logicAppTemplateFilePath $(logicAppTemplateFilePath)
66 | -logicAppDefinitionPath $(logicAppDefinitionPath)
67 | -logicAppDefinitionParametersFilePath $(logicAppDefinitionParametersFilePath)
--------------------------------------------------------------------------------
/storage-account-connections/powershell/clean-up.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deletes all resource groups where their names start with the "groupId" that's passed as input.
4 |
5 | .PARAMETER groupId
6 | The value that identifies the resource group to delete
7 | #>
8 |
9 | param(
10 | [Parameter(Mandatory = $True)]
11 | [string]
12 | $groupId
13 | )
14 |
15 | $resourceGroups = Get-AzResourceGroup;
16 |
17 | foreach ($resourceGroup in $resourceGroups) {
18 | if ($resourceGroup.ResourceGroupName.StartsWith($groupId, 'CurrentCultureIgnoreCase')) {
19 | Remove-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Force -AsJob
20 | Write-Host "Deleted resource group $($resourceGroup.ResourceGroupName)"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/storage-account-connections/powershell/full-deploy.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Deploys a template for a logic app to Azure.
4 |
5 | .DESCRIPTION
6 | Deploys an Azure Resource Manager template with the LogicApp definition seperated within the directory
7 |
8 | .PARAMETER groupId
9 | The value used for constructing resources in the resource group and identifies the resources that are used together in a specific solution
10 |
11 | .PARAMETER location
12 | The region or location name to use for the resource group and the resources in that group
13 |
14 | .PARAMETER environment
15 | The alphabetical character that identifies the deployment environment to use in the name for each resource that's created in the resource group. For example, values include "d" for development, "t" for test, "s" for staging, and "p" for production.
16 |
17 | .PARAMETER abbrevLocationName
18 | The abbreviated region name that's used in resource names due to character limitations on some resource types. Defaults to the "location" parameter value.
19 |
20 | .PARAMETER deploymentName
21 | The name used for the deployment. If not given, a GUID is assigned as the deployment name.
22 |
23 | .PARAMETER instanceCount
24 | The number of resource group instances to create
25 |
26 | .PARAMETER overrideExistingLogicApp
27 | If true, the script runs the Azure Resource Manager template deployment for the logic app, even when the logic app already exists.
28 | #>
29 |
30 | param(
31 |
32 | [Parameter(Mandatory=$True)]
33 | [string]
34 | $groupId,
35 |
36 | [Parameter(Mandatory=$True)]
37 | [string]
38 | $location,
39 |
40 | [Parameter(Mandatory=$True)]
41 | [string]
42 | $environment,
43 |
44 | [Parameter(Mandatory=$False)]
45 | [string]
46 | $abbrevLocationName = $location,
47 |
48 | [Parameter(Mandatory=$False)]
49 | [string]
50 | $deploymentName = [guid]::NewGuid(),
51 |
52 | [Parameter(Mandatory=$False)]
53 | [int]
54 | $instanceCount = 1,
55 |
56 | [Parameter(Mandatory = $False)]
57 | [bool]
58 | $overrideExistingLogicApp = $True
59 | )
60 |
61 | Write-Host "Running shared deployment script"
62 |
63 | & "${PSScriptRoot}\shared-deploy.ps1" -groupId $groupId `
64 | -location $location `
65 | -environment $environment `
66 | -abbrevLocationName $abbrevLocationName `
67 | -deploymentName $deploymentName;
68 |
69 | Write-Host "Running logic app deployment script"
70 |
71 | & "${PSScriptRoot}\logic-app-deploy.ps1" -groupId $groupId `
72 | -location $location `
73 | -environment $environment `
74 | -abbrevLocationName $abbrevLocationName `
75 | -deploymentName $deploymentName `
76 | -identifier "sample-storage-conn" `
77 | -instanceCount $instanceCount `
78 | -overrideExisting $overrideExistingLogicApp;
--------------------------------------------------------------------------------
/storage-account-connections/templates/connectors-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "sharedResourceGroupName": "[toLower(concat(variables('baseName'), 'rgp', variables('location'), '-shared'))]",
42 | "baseConnectionsId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', variables('location'), '/managedApis/')]",
43 | "storageAccountName": "[toLower(concat(variables('baseName'), 'sa2', parameters('locationName')))]",
44 | "storageAccountId": "[resourceId(subscription().subscriptionId, variables('sharedResourceGroupName'), 'Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
45 | "tablesConnectionName": "azuretables",
46 | "tablesConnectionId": "[concat(variables('baseConnectionsId'), 'azuretables')]",
47 | "blobConnectionName": "azureblob",
48 | "blobConnectionId": "[concat(variables('baseConnectionsId'), 'azureblob')]",
49 | "fileConnectionName": "azurefile",
50 | "fileConnectionId": "[concat(variables('baseConnectionsId'), 'azurefile')]",
51 | "queuesConnectionName": "azurequeues",
52 | "queuesConnectionId": "[concat(variables('baseConnectionsId'), 'azurequeues')]",
53 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
54 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
55 | },
56 | "resources": [
57 | {
58 | "type": "Microsoft.Web/connections",
59 | "apiVersion": "2016-06-01",
60 | "name": "[variables('tablesConnectionName')]",
61 | "location": "[variables('location')]",
62 | "tags": {
63 | "groupdId": "[parameters('groupId')]"
64 | },
65 | "properties": {
66 | "displayName": "storageAccount",
67 | "customParameterValues": {},
68 | "api": {
69 | "id": "[variables('tablesConnectionId')]"
70 | },
71 | "parameterValues": {
72 | "storageaccount": "[variables('storageAccountName')]",
73 | "sharedkey": "[listKeys(variables('storageAccountId'), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]"
74 | }
75 | }
76 | },
77 | {
78 | "type": "Microsoft.Web/connections",
79 | "apiVersion": "2016-06-01",
80 | "name": "[variables('queuesConnectionName')]",
81 | "location": "[variables('location')]",
82 | "tags": {
83 | "groupdId": "[parameters('groupId')]"
84 | },
85 | "properties": {
86 | "displayName": "storageAccount",
87 | "customParameterValues": {},
88 | "api": {
89 | "id": "[variables('queuesConnectionId')]"
90 | },
91 | "parameterValues": {
92 | "storageaccount": "[variables('storageAccountName')]",
93 | "sharedkey": "[listKeys(variables('storageAccountId'), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]"
94 | }
95 | }
96 | },
97 | {
98 | "type": "Microsoft.Web/connections",
99 | "apiVersion": "2016-06-01",
100 | "name": "[variables('blobConnectionName')]",
101 | "location": "[variables('location')]",
102 | "tags": {
103 | "groupdId": "[parameters('groupId')]"
104 | },
105 | "properties": {
106 | "displayName": "storageAccount",
107 | "customParameterValues": {},
108 | "api": {
109 | "id": "[variables('blobConnectionId')]"
110 | },
111 | "parameterValues": {
112 | "accountName": "[variables('storageAccountName')]",
113 | "accessKey": "[listKeys(variables('storageAccountId'), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]"
114 | }
115 | }
116 | },
117 | {
118 | "type": "Microsoft.Web/connections",
119 | "apiVersion": "2016-06-01",
120 | "name": "[variables('fileConnectionName')]",
121 | "location": "[variables('location')]",
122 | "tags": {
123 | "groupdId": "[parameters('groupId')]"
124 | },
125 | "properties": {
126 | "displayName": "storageAccount",
127 | "customParameterValues": {},
128 | "api": {
129 | "id": "[variables('fileConnectionId')]"
130 | },
131 | "parameterValues": {
132 | "accountName": "[variables('storageAccountName')]",
133 | "accessKey": "[listKeys(variables('storageAccountId'), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]"
134 | }
135 | }
136 | }
137 | ],
138 | "outputs": {
139 | "tablesManagedApiId": {
140 | "type": "string",
141 | "value": "[variables('tablesConnectionId')]"
142 | },
143 | "tablesConnId": {
144 | "type": "string",
145 | "value": "[resourceId('Microsoft.Web/connections', variables('tablesConnectionName'))]"
146 | },
147 | "fileManagedApiId": {
148 | "type": "string",
149 | "value": "[variables('fileConnectionId')]"
150 | },
151 | "fileConnId": {
152 | "type": "string",
153 | "value": "[resourceId('Microsoft.Web/connections', variables('fileConnectionName'))]"
154 | },
155 | "blobManagedApiId": {
156 | "type": "string",
157 | "value": "[variables('blobConnectionId')]"
158 | },
159 | "blobConnId": {
160 | "type": "string",
161 | "value": "[resourceId('Microsoft.Web/connections', variables('blobConnectionName'))]"
162 | },
163 | "queuesManagedApiId": {
164 | "type": "string",
165 | "value": "[variables('queuesConnectionId')]"
166 | },
167 | "queuesConnId": {
168 | "type": "string",
169 | "value": "[resourceId('Microsoft.Web/connections', variables('queuesConnectionName'))]"
170 | },
171 | "logicAppName": {
172 | "type": "string",
173 | "value": "[variables('logicAppName')]"
174 | }
175 | }
176 | }
--------------------------------------------------------------------------------
/storage-account-connections/templates/logic-app-definition-parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$connections": {
3 | "value": {
4 | "azuretables": {
5 | "connectionId": "{tablesConnId}",
6 | "connectionName": "azuretables",
7 | "id": "{tablesManagedApiId}"
8 | },
9 | "azureblob": {
10 | "connectionId": "{blobConnId}",
11 | "connectionName": "azureblob",
12 | "id": "{blobManagedApiId}"
13 | },
14 | "azurefile": {
15 | "connectionId": "{fileConnId}",
16 | "connectionName": "azurefile",
17 | "id": "{fileManagedApiId}"
18 | },
19 | "azurequeues": {
20 | "connectionId": "{queuesConnId}",
21 | "connectionName": "azurequeues",
22 | "id": "{queuesManagedApiId}"
23 | }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/storage-account-connections/templates/logic-app-definition.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
3 | "actions": {
4 | "Create_blob": {
5 | "inputs": {
6 | "body": "@triggerBody()?['MessageText']",
7 | "host": {
8 | "connection": {
9 | "name": "@parameters('$connections')['azureblob']['connectionId']"
10 | }
11 | },
12 | "method": "post",
13 | "path": "/datasets/default/files",
14 | "queries": {
15 | "folderPath": "/samplecontainer1",
16 | "name": "@triggerBody()?['MessageId']",
17 | "queryParametersSingleEncoded": true
18 | }
19 | },
20 | "runAfter": {},
21 | "runtimeConfiguration": {
22 | "contentTransfer": {
23 | "transferMode": "Chunked"
24 | }
25 | },
26 | "type": "ApiConnection"
27 | },
28 | "Create_file": {
29 | "inputs": {
30 | "body": "@triggerBody()?['MessageText']",
31 | "host": {
32 | "connection": {
33 | "name": "@parameters('$connections')['azurefile']['connectionId']"
34 | }
35 | },
36 | "method": "post",
37 | "path": "/datasets/default/files",
38 | "queries": {
39 | "folderPath": "/sampleshare1",
40 | "name": "@triggerBody()?['MessageId']",
41 | "queryParametersSingleEncoded": true
42 | }
43 | },
44 | "runAfter": {
45 | "Insert_Entity": [
46 | "Succeeded"
47 | ]
48 | },
49 | "runtimeConfiguration": {
50 | "contentTransfer": {
51 | "transferMode": "Chunked"
52 | }
53 | },
54 | "type": "ApiConnection"
55 | },
56 | "Insert_Entity": {
57 | "inputs": {
58 | "body": "@triggerBody()",
59 | "host": {
60 | "connection": {
61 | "name": "@parameters('$connections')['azuretables']['connectionId']"
62 | }
63 | },
64 | "method": "post",
65 | "path": "/Tables/@{encodeURIComponent('sampleTable1')}/entities"
66 | },
67 | "runAfter": {
68 | "Create_blob": [
69 | "Succeeded"
70 | ]
71 | },
72 | "type": "ApiConnection"
73 | }
74 | },
75 | "contentVersion": "1.0.0.0",
76 | "outputs": {},
77 | "parameters": {
78 | "$connections": {
79 | "defaultValue": {},
80 | "type": "Object"
81 | }
82 | },
83 | "triggers": {
84 | "When_there_are_messages_in_a_queue": {
85 | "inputs": {
86 | "host": {
87 | "connection": {
88 | "name": "@parameters('$connections')['azurequeues']['connectionId']"
89 | }
90 | },
91 | "method": "get",
92 | "path": "/@{encodeURIComponent('samplequeue1')}/message_trigger"
93 | },
94 | "recurrence": {
95 | "frequency": "Minute",
96 | "interval": 3
97 | },
98 | "splitOn": "@triggerBody()?['QueueMessagesList']?['QueueMessage']",
99 | "type": "ApiConnection"
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/storage-account-connections/templates/logic-app-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "identifier": {
25 | "type": "string",
26 | "metadata": {
27 | "description": "The value that's appended to the logic app name and identifies the logic app's purpose or function."
28 | }
29 | },
30 | "instance": {
31 | "type": "int",
32 | "defaultValue": 1,
33 | "metadata": {
34 | "description": "The value that tracks the number of resource group instances"
35 | }
36 | }
37 | },
38 | "variables": {
39 | "location": "[resourceGroup().location]",
40 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
41 | "instance": "[if(equals(parameters('instance'), 1), '', concat('-', sub(parameters('instance'), 1)))]",
42 | "logicAppName": "[toLower(concat(variables('baseName'), 'la', parameters('locationName'), '-', parameters('identifier'), variables('instance')))]"
43 | },
44 | "resources": [
45 | {
46 | "name": "[variables('logicAppName')]",
47 | "type": "Microsoft.Logic/workflows",
48 | "location": "[variables('location')]",
49 | "apiVersion": "2016-06-01",
50 | "properties": {
51 | "definition": {
52 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
53 | "contentVersion": "1.0.0.0",
54 | "parameters": {},
55 | "triggers": {},
56 | "actions": {},
57 | "outputs": {}
58 | }
59 | }
60 | }
61 | ],
62 | "outputs": {
63 | "logicAppName": {
64 | "type": "string",
65 | "value": "[variables('logicAppName')]"
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/storage-account-connections/templates/shared-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "groupId": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The group name to use for creating resource names"
9 | }
10 | },
11 | "environment": {
12 | "type": "string",
13 | "defaultValue": "d",
14 | "metadata": {
15 | "description": "The alphabetical character that identifies the deployment environment to use in the name for each created resource. For example, values include 'd' for development, 't' for test, 's' for staging, and 'p' for production."
16 | }
17 | },
18 | "locationName": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "The name that identifies the region or location in resource names and is usually the shortened version of that name"
22 | }
23 | },
24 | "containers": {
25 | "type": "array",
26 | "defaultValue": [
27 | "samplecontainer1",
28 | "samplecontainer2"
29 | ],
30 | "metadata": {
31 | "description": "The array of containers to create"
32 | }
33 | }
34 | },
35 | "variables": {
36 | "location": "[resourceGroup().location]",
37 | "baseName": "[concat(parameters('groupId'), parameters('environment'))]",
38 | "storageAccountName": "[toLower(concat(variables('baseName'), 'sa2', parameters('locationName')))]"
39 | },
40 | "resources": [
41 | {
42 | "name": "[variables('storageAccountName')]",
43 | "type": "Microsoft.Storage/storageAccounts",
44 | "apiVersion": "2019-04-01",
45 | "tags": {
46 | "groupdId": "[parameters('groupId')]"
47 | },
48 | "sku": {
49 | "name": "Standard_LRS"
50 | },
51 | "kind": "StorageV2",
52 | "location": "[variables('location')]",
53 | "properties": {
54 | "accessTier": "Hot"
55 | },
56 | "resources": []
57 | },
58 | {
59 | "name": "[concat(variables('storageAccountName'), '/default/',toLower(parameters('containers')[copyindex()]))]",
60 | "type": "Microsoft.Storage/storageAccounts/blobServices/containers",
61 | "apiVersion": "2019-04-01",
62 | "tags": {
63 | "groupdId": "[parameters('groupId')]"
64 | },
65 | "dependsOn": [
66 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
67 | ],
68 | "copy": {
69 | "name": "containerCopy",
70 | "count": "[length(parameters('containers'))]"
71 | },
72 | "properties": {
73 | "publicAccess": "Container"
74 | },
75 | "resources": []
76 | }
77 | ],
78 | "outputs": {
79 | "storageAccountName": {
80 | "type": "string",
81 | "value": "[variables('storageAccountName')]"
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------