Skip to content

Commit 92b4e0b

Browse files
authored
Merge pull request #76 from SQLPlayer/TriggersPack
Triggers pack
2 parents 1af72bd + 24b258a commit 92b4e0b

34 files changed

+796
-109
lines changed

README.md

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ The main advantage of the module is the ability to publish all the Azure Data Fa
1111
* Finding the **right order** for deploying objects (no more worrying about object names)
1212
* Built-in mechanism to replace, remove or add the properties with the indicated values (CSV and JSON file formats supported)
1313
* Stopping/starting triggers
14-
* Dropping objects when not exist in the source (code)
15-
* Filtering (include or exclude) objects to be deployed by name and/or type and/or folder
14+
* Dropping objects when not exist in the source (code)
15+
* (new!) Optionally can skip deletion of excluded objects
16+
* Filtering (include or exclude) objects to be deployed by name and/or type **and/or folder** (new!)
1617
* Filtering supports wildcards
1718
* Publish options allow you to control:
1819
* Whether stop and restarting triggers
1920
* Whether delete or not objects not in the source
2021
* Whether create or not a new instance of ADF if it not exist
2122
* Tokenisation in config file allows replace any value by Environment Variable or Variable from DevOps Pipeline
23+
* (new!) Allows to define multiple file (objects) by wildcarding
2224
* Global Parameters
2325

2426
The following features coming in the future:
@@ -131,6 +133,9 @@ $opt = New-AdfPublishOption
131133
* [Boolean] **DeployGlobalParams** - indicates whether deploy Global Parameters of ADF. Nothing happens when parameters are not defined. (default: *true*)
132134
* [Boolean] **FailsWhenConfigItemNotFound** - indicates whether configuration items not found fails the script. (default: *true*)
133135
* [Boolean] **FailsWhenPathNotFound** - indicates whether missing paths fails the script. (default: *true*)
136+
* [Boolean] **DoNotStopStartExcludedTriggers** - specifies whether excluded triggers will be stopped before deployment (default: *false*)
137+
* [Boolean] **DoNotDeleteExcludedObjects** - specifies whether excluded objects can be removed. Applies when `DeleteNotInSource` is set to *True* only. (default: *true*)
138+
134139

135140
Subsequently, you can define the needed options:
136141

@@ -191,11 +196,13 @@ Therefore, an extra character should be provided before the name/pattern:
191196
trigger.*
192197
-*.SharedIR*
193198
-*.LS_SqlServer_DEV19_AW2017
199+
-*.*@testFolder
194200
```
195201

196202
The above file (if used) adds:
197203
- 2 items to *Includes* list (line 1-2)
198204
- 2 items to *Excludes* list (line 3-4)
205+
- all items located in `testFolder` to *Excludes* list (line 5)
199206

200207
> The file should use UTF-8 encoding.
201208
@@ -435,8 +442,10 @@ If you prefer using JSON rather than CSV for setting up configuration - JSON fil
435442

436443

437444
## Step: Stoping triggers
438-
This block stops all triggers which must be stopped due to deployment.
439-
> Operation might be skipped when `StopStartTriggers = false` in *Publish Options*
445+
This block stops all triggers which must be stopped due to deployment.
446+
Since version 0.30 you can better control which triggers you want to omit from stopping. Only need to add such triggers to `Excludes` list and set flag `DoNotStopStartExcludedTriggers` to *true*.
447+
448+
> The step might be skipped when `StopStartTriggers = false` in *Publish Options*
440449
441450
## Step: Deployment of ADF objects
442451
This step is actually responsible for doing all the stuff.
@@ -445,13 +454,61 @@ The mechanism is smart enough to publish all objects in the right order, thence
445454
446455
## Step: Deleting objects not in source
447456
This process removes all objects from ADF service whom couldn't be found in the source (ADF code).
448-
The mechanism is smart enough to dropping the objects in right order.
457+
The mechanism is smart enough to dropping the objects in right order.
458+
Since version 0.30 you can better control which objects you want to omit from removing. Only need to add such objects to `Excludes` list and set flag `DoNotDeleteExcludedObjects` to *true*.
449459

450-
> Operation might be skipped when `DeleteNotInSource = false` in *Publish Options*
460+
> The step might be skipped when `DeleteNotInSource = false` in *Publish Options*
451461
452462
## Step: Restarting all triggers
453463
Restarting all triggers that should be enabled.
454-
> Operation might be skipped when `StopStartTriggers = false` in *Publish Options*
464+
> The step might be skipped when `StopStartTriggers = false` in *Publish Options*
465+
466+
# Selective deployment, triggers and logic
467+
468+
Publishing only selected objects of ADF is not an easy thing. If you add dependencies between objects and a need of stopping triggers before deploying on top of that - the situation becomes even more difficult. Therefore, not always it might be obvious what would happen during the deployment while you have flags set up, an object exist (or not) in the source and/or a trigger is Enabled (or Disabled) on target ADF service where you deploy to.
469+
All these factors:
470+
* Does object exist in the source?
471+
* Is trigger is Enabled in the target?
472+
* What is the value for `DeleteNotInSource` flag?
473+
* What is the value for `StopStartTriggers` flag?
474+
* What is the value for `DoNotStopStartExcludedTriggers` flag?
475+
* What is the value for `DoNotDeleteExcludedObjects` flag?
476+
* Is an object on `Excludes` list?
477+
478+
had to be considered thoroughly, hence the following table arose:
479+
![Matrix of behaviour logic](./matrix-of-behaviour-logic.png)
480+
481+
## Assumptions
482+
483+
It's worth to explain a bit why the behaviour looks as above.
484+
485+
### StopStartTriggers
486+
It allows you to decide. It stops ALL existing and `Started` (Enabled) triggers.
487+
Generally you should use TRUE (default) if you want to avoid troubles.
488+
However, if you choose FALSE - you must accept that process WILL NOT touch triggers. You can still do it for yourself in pre or post-deployment script.
489+
490+
### DoNotStopStartExcludedTriggers
491+
In some scenarios, people still want to let process to manage of triggers, but with some exceptions.
492+
Usage of this flag make sense along with `StopStartTriggers` only and some objects are excluded from deployment.
493+
It guarantees that no objects (excluded) will be even touched in target service during the deployment.
494+
495+
### Excluded (collection)
496+
This option should allow to completely separate group of objects from other group.
497+
In that way you can keep all files in the source but control behaviour with flags.
498+
Exclusion can be defined in two ways:
499+
1) Explicitly in 'Excludes' collection
500+
2) Implicitly by not adding an item in 'Includes' collection
501+
502+
**Important:** Both collections can use wildcards as the name of objects.
503+
It simplify defining multiple objects by one line, or defining objects which does not exist yet.
504+
These collections are very useful while you want to do a selective deployment.
505+
506+
### DoNotDeleteExcludedObjects
507+
Excluded object can be deleted only if flag `DoNotDeleteExcludedObjects` = false.
508+
This situation could cause error when trigger has not been deleted prior.
509+
Otherwise, nothing will happen.
510+
This option gives you a flexibility of deleting objects in the target, but still not touching objects from 'other' group.
511+
455512

456513
# Publish from Azure DevOps
457514

azure.datafactory.tools.psd1

10 Bytes
Binary file not shown.

changelog.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,23 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

7+
## [0.30.0] - 2021-01-08
8+
### Added
9+
* Better control of which: (see new publish flags below)
10+
* triggers could be stop/start
11+
* objects could be removed (if apply)
12+
* Publish flag: `DoNotDeleteExcludedObjects` ([#47](https://github.com/SQLPlayer/azure.datafactory.tools/issues/47))
13+
* Publish flag: `DoNotStopStartExcludedTriggers` allows stopping selected triggers ([#51](https://github.com/SQLPlayer/azure.datafactory.tools/issues/51))
14+
* Numbers to all error messages ([full list](./en-us/messages_index.md))
15+
716
## [0.20.0] - 2020-12-28
817
### Fixed
918
* Do not start trigger which has not been deployed and thus does not exist (#51)
1019

1120
## [0.19.0] - 2020-12-23
1221
### Added
1322
* Support wildcard when specifying object(s) name in config file (#58)
14-
* Added option $IgnoreLackOfReferencedObject (#64)
23+
* Added option `$IgnoreLackOfReferencedObject` (#64)
1524
* Add object name to the msg before action (#49)
1625
* Exit publish cmd when ADF name is already in use (#43)
1726
* Allow selecting objects in given folder (#68)

en-us/messages_index.md

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,39 @@
1-
# Messages:
2-
ADFTmxxx
3-
m = module/feature
4-
0 - Generic
1+
# Messages
52

3+
> ADFTmxxx
4+
m = module/feature
5+
0 - Generic
66
xxx - number of error
77

8-
## Index
9-
ADFT0005: Referenced object [$name] was not found.
10-
ADFT0006: Referenced object [$name] was not found. No error raised as user wanted to carry on.
118

12-
ADFT0007: Could not find object: $type.$name
13-
ADFT0008: Could not find object: $type.$name
14-
ADFT0009: Body of the object is empty!
15-
ADFT0010: Wrong path defined in config for object(path): $type.$name(properties.$path)"
16-
ADFT0011: adf.Location property has not been provided.
9+
## Index of errors
1710

11+
Error number | Message
12+
-- | --
13+
ADFT0005 | Referenced object [*name*] was not found.
14+
ADFT0006 | Referenced object [*name*] was not found. No error raised as user wanted to carry on.
15+
ADFT0007 | Could not find object: *type.name*
16+
ADFT0008 | Could not find object: *type.name*
17+
ADFT0009 | Body of the object is empty!
18+
ADFT0010 | Wrong path defined in config for object(path): *type.name*(*properties.path*)"
19+
ADFT0011 | adf.Location property has not been provided.
20+
ADFT0012 | Deployment for this kind of Integration Runtime is not supported yet.
21+
ADFT0013 | Type *type* is not supported.
22+
ADFT0014 | Type *type* is not supported.
23+
ADFT0015 | Type *type* is not supported.
24+
ADFT0016 | Type '*type*' is not supported.
25+
ADFT0017 | Object [*name*] could not be found.
26+
ADFT0018 | Type *type* is not supported.
27+
ADFT0019 | Folder '*RootFolder*' doesn't exist.
28+
ADFT0020 | The header of config file is wrong. The header must have only 4 columns named: type, name, path, value.
29+
ADFT0021 | Config file, row x : Value in column 'Type' is empty.
30+
ADFT0022 | Config file, row x : Type *type* is not supported.
31+
ADFT0023 | Config file, row x : Value in column 'Name' is empty.
32+
ADFT0024 | Config file, row x : Value in column 'Path' is empty.
33+
ADFT0025 | Config file, row x has too many columns.
34+
ADFT0026 | File does not exist: *FilterFilePath*
35+
ADFT0027 | Azure Data Factory instance does not exist.
36+
ADFT0028 | Expected format of name for 'FullName' input parameter is: objectType.objectName[@folderName]
37+
ADFT0029 | Unknown object type: *type*.
1838

1939

matrix-of-behaviour-logic.png

116 KB
Loading

private/!AdfPublishOption.class.ps1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ class AdfPublishOption {
88
[Boolean] $FailsWhenConfigItemNotFound = $true
99
[Boolean] $FailsWhenPathNotFound = $true
1010
[Boolean] $IgnoreLackOfReferencedObject = $false
11+
[Boolean] $DoNotStopStartExcludedTriggers = $false
12+
[Boolean] $DoNotDeleteExcludedObjects = $true
1113
}

private/AdfObjectName.class.ps1

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,93 @@
11
class AdfObjectName {
22
[string] $Name
33
[string] $Type
4+
[string] $Folder
45

56
AdfObjectName ([string] $Name, [string] $Type)
67
{
78
$this.Name = $Name
89
$this.Type = $Type
910
}
1011

12+
AdfObjectName ([string] $Name, [string] $Type, [string] $Folder)
13+
{
14+
$this.Name = $Name
15+
$this.Type = $Type
16+
$this.Folder = $Folder
17+
}
18+
1119
AdfObjectName ([string] $FullName)
1220
{
13-
if ($FullName.IndexOf('.') -lt 1) {
14-
Write-Error "Expected format of name for 'FullName' input parameter is: objectType.objectName"
21+
$m = [regex]::matches($FullName, '([a-zA-Z]+)\.([a-zA-Z 0-9\-_]+)@?(.*)')
22+
if ($m.Success -eq $false) {
23+
throw "ADFT0028: Expected format of name for 'FullName' input parameter is: objectType.objectName[@folderName]"
1524
}
16-
$parts = $FullName.Split('.')
17-
if ($parts[0] -notin [AdfObject]::allowedTypes ) {
18-
Write-Error -Message "Unknown object type: $parts[0]."
25+
if ($m.Groups[1].Value -notin [AdfObject]::allowedTypes ) {
26+
throw "ADFT0029: Unknown object type: $($m.Groups[1].Value)."
1927
}
20-
$this.Type = $parts[0]
21-
$this.Name = $parts[1]
28+
$this.Type = $m.Groups[1].Value
29+
$this.Name = $m.Groups[2].Value
30+
$this.Folder = $m.Groups[3].Value
2231
}
2332

24-
}
33+
[String] FullName ([boolean] $quoted)
34+
{
35+
if ($quoted) {
36+
return "[$($this.Type)].[$($this.Name)]"
37+
} else {
38+
return "$($this.Type).$($this.Name)"
39+
}
40+
}
41+
42+
[String] FullNameWithFolder ()
43+
{
44+
if ($this.Folder.Length -gt 0) {
45+
return "$($this.Type).$($this.Name)@$($this.Folder)"
46+
} else {
47+
return "$($this.Type).$($this.Name)"
48+
}
49+
}
50+
51+
[String] FullName ()
52+
{
53+
return $this.FullName($false)
54+
}
55+
56+
[String] FullNameQuoted ()
57+
{
58+
return $this.FullName($true)
59+
}
2560

61+
[Boolean] IsNameMatch ([array]$wildcardPatterns)
62+
{
63+
$fullname = $this.FullName()
64+
$r = $wildcardPatterns | Where-Object { $fullname -like $_ }
65+
return $null -ne $r
66+
}
67+
68+
[Boolean] IsNameExcluded ([AdfPublishOption] $opt)
69+
{
70+
$fullname = $this.FullNameWithFolder()
71+
72+
# One can exclude objects by listing them explicitly in Excludes collection, ...
73+
$excPatterns = $opt.Excludes.Keys
74+
$r = $excPatterns | Where-Object { $fullname -like $_ }
75+
if ($null -ne $r)
76+
{
77+
# Means: object is excluded if matches any item in (Excludes) collection
78+
return $true
79+
}
80+
81+
# ... or by listing them implicitly in Includes collection:
82+
$incPatterns = $opt.Includes.Keys
83+
if ($incPatterns.Count -eq 0)
84+
{
85+
# If no items = all objects match => object is not excluded
86+
return $false
87+
}
88+
$r = $incPatterns | Where-Object { $fullname -like $_ }
89+
# Means: object is excluded if not match any item in (Includes) collection
90+
return ($null -eq $r)
91+
}
92+
93+
}

private/Deploy-AdfObjectOnly.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function Deploy-AdfObjectOnly {
7373
-Force | Out-Null
7474
}
7575
else {
76-
Write-Error "Deployment for this kind of Integration Runtime is not supported yet."
76+
Write-Error "ADFT0012: Deployment for this kind of Integration Runtime is not supported yet."
7777
}
7878
}
7979
'linkedService'
@@ -140,7 +140,7 @@ function Deploy-AdfObjectOnly {
140140
}
141141
default
142142
{
143-
Write-Error "Type $($obj.Type) is not supported."
143+
Write-Error "ADFT0013: Type $($obj.Type) is not supported."
144144
}
145145
}
146146

private/Get-AdfObjectByName.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function Get-AdfObjectByName {
4141
}
4242
default
4343
{
44-
Write-Error "Type [$type] is not supported."
44+
Write-Error "ADFT0014: Type [$type] is not supported."
4545
}
4646
}
4747

private/Get-AdfObjectByPattern.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function Get-AdfObjectByPattern {
4141
}
4242
default
4343
{
44-
Write-Error "Type [$type] is not supported."
44+
Write-Error "ADFT0015: Type [$type] is not supported."
4545
}
4646
}
4747

0 commit comments

Comments
 (0)