Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added "Set Entities" script for Azure Table storage #222

Merged
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c1e8c82
Added SetEntities script to Azure Table
Annelotte-Mons Sep 14, 2021
c1a2c27
Added AzTable-SetEntities Script
Annelotte-Mons Sep 14, 2021
d995851
removed obsolete file
Annelotte-Mons Sep 14, 2021
7a2e7b1
Merge branch 'arcus-azure:master' into master
Annelotte-Mons Dec 8, 2021
d915132
Merge branch 'master' into feature/ps-AzTable-SetEntities
Annelotte-Mons Dec 8, 2021
8afd1b5
Renamed script + added to docs
Annelotte-Mons Dec 8, 2021
7fabee3
Merge branch 'arcus-azure:main' into master
Annelotte-Mons May 25, 2023
59d8e31
forward merge
Annelotte-Mons May 25, 2023
73b912b
updated logging, added some checks and aligned coding style
pim-simons May 25, 2023
87c5451
removed $RetryIntervalSeconds and $MaxRetryCount as they were not bei…
pim-simons May 25, 2023
ff82d8b
align with config file (removed entities node)
pim-simons May 25, 2023
6eb2e6c
added docs
pim-simons May 25, 2023
7521f7d
try to revert doc changes in version 0.6.0
pim-simons May 25, 2023
a2ff1c9
Apply suggestions from code review
pim-simons May 26, 2023
8b49c27
test path check
pim-simons May 26, 2023
d78e3f2
simplified partitionkey and rowkey if statement
pim-simons May 26, 2023
cc0f8b0
removed comments
pim-simons May 26, 2023
cdb36fd
remove unused params
pim-simons May 26, 2023
0b42a21
added unit tests and some more config validation
pim-simons May 26, 2023
853c382
added extra unit test and integrations tests
pim-simons May 26, 2023
a43e007
implement step in pipeline to update powershell to latest version
pim-simons May 31, 2023
b65c37f
use correct condition
pim-simons May 31, 2023
bfc16e0
add `-ErrorAction SilentlyContinue` to `Test-Json` as we only need th…
pim-simons May 31, 2023
d17d58f
undo comment out
pim-simons May 31, 2023
5e586e9
added json schema to validation
pim-simons May 31, 2023
c361071
use pwsh
pim-simons May 31, 2023
01058af
added json schema to docs
pim-simons May 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,54 @@ PS> Create-AzStorageTable `
# Failed to re-create the Azure storage table 'products' in Azure storage account 'admin', retrying in 5 seconds...
# Azure storage table 'products' created in Azure storage account 'admin'
```


## Set the entities in a table of an Azure Storage Account

Deletes all entities of a specified table in an Azure Storage Account and creates new entities based on a configuration file.

| Parameter | Mandatory | Description |
| ---------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
| `ResourceGroupName` | yes | The resource group where the Azure Storage Account is located |
| `StorageAccountName` | yes | The name of the Azure Storage Account that contains the table |
| `TableName` | yes | The name of the table in which the entities should be set |
| `ConfigurationFile` | yes | Path to the JSON Configuration file containing all the entities to be set |

**Configuration File**

The configuration file is a simple JSON file that contains all of the entities that should be set on the specified table, the JSON file consists of an array of JSON objects (= your entities). Each object contains simple name-value pairs (string-string).

Defining the PartitionKey and/or RowKey are optional, if not provided a random GUID will be set for these.

**Example Configuration File**

```json
[
{
"PartitionKey": "SystemA",
pim-simons marked this conversation as resolved.
Show resolved Hide resolved
"RowKey": "100",
"ReadPath": "/home/in",
"ReadIntervalInSeconds": "30"
},
{
"PartitionKey": "SystemA",
"RowKey": "200",
"ReadPath": "/data/in",
"ReadIntervalInSeconds": "10",
"HasSubdirectories": "true"
}
]
```

**Example**

```powershell
PS> Set-AzTableStorageEntities `
-ResourceGroupName "someresourcegroup" `
-StorageAccountName "somestorageaccount" `
-TableName "sometable" `
-ConfigurationFile ".\config.json"
# Deleting all existing entities in Azure storage table 'sometable' for Azure storage account 'somestorageaccount' in resource group 'someresourcegroup'...
# Successfully deleted all existing entities in Azure storage table 'sometable' for Azure storage account 'somestorageaccount' in resource group 'someresourcegroup'
# Successfully added all entities in Azure storage table 'sometable' for Azure storage account 'somestorageaccount' in resource group 'someresourcegroup'
```
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,48 @@ function Create-AzStorageTable {
}
}

Export-ModuleMember -Function Create-AzStorageTable
Export-ModuleMember -Function Create-AzStorageTable



<#
.Synopsis
Sets the entities in a specified table storage.

.Description
Sets (Delete & Add) the entities in a specified table storage to the values specified in a (JSON) configuration file.

.Parameter ResourceGroupName
The resource group where the Azure Storage Account is located.

.Parameter StorageAccountName
The name of the Azure Storage Account which holds the Azure table storage.

.Parameter TableName
The name of the table on the Azure Storage Account.

.Parameter ConfigurationFile
The Configuration File (JSON) specifying the entities that have to be set in the table storage. The JSON file has a single property "entities" which is an array of objects.

.Parameter RetryIntervalSeconds
The optional amount of seconds to wait each retry-run when a failure occures during the re-creating process.

.Parameter MaxRetryCount
The optional maximum amount of retry-runs should happen when a failure occurs during the re-creating process.
pim-simons marked this conversation as resolved.
Show resolved Hide resolved
#>
function Set-AzTableStorageEntities {
param(
[Parameter(Mandatory = $true)][string] $ResourceGroupName = $(throw "Name of resource group is required"),
[Parameter(Mandatory = $true)][string] $StorageAccountName = $(throw "Name of Azure storage account is required"),
[Parameter(Mandatory = $true)][string] $TableName = $(throw "Name of Azure table is required"),
[Parameter(Mandatory = $true)][string] $ConfigurationFile = $(throw "Path to the configuration file is required")
)

. $PSScriptRoot\Scripts\Set-AzTableStorageEntities.ps1 `
-ResourceGroupName $ResourceGroupName `
-StorageAccountName $StorageAccountName `
-TableName $TableName `
-ConfigurationFile $ConfigurationFile
}

Export-ModuleMember -Function Set-AzTableStorageEntities
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
param(
[Parameter(Mandatory = $true)][string] $ResourceGroupName = $(throw "Name of resource group is required"),
[Parameter(Mandatory = $true)][string] $StorageAccountName = $(throw "Name of Azure storage account is required"),
[Parameter(Mandatory = $true)][string] $TableName = $(throw "Name of Azure table is required"),
[Parameter(Mandatory = $true)][string] $ConfigurationFile = $(throw "Path to the configuration file is required")
)

if (-not (Test-Path -Path $ConfigurationFile)) {
throw "Cannot re-create entities based on JSON configuration file because no file was found at: '$ConfigurationFile'"
}
if ((Get-Content -Path $ConfigurationFile -Raw) -eq $null) {
throw "Cannot re-create entities based on JSON configuration file because the file is empty."
}
if (-not (Get-Content -Path $ConfigurationFile -Raw | Test-Json)) {
pim-simons marked this conversation as resolved.
Show resolved Hide resolved
throw "Cannot re-create entities based on JSON configuration file because the file does not contain valid JSON."
}

Write-Verbose "Retrieving Azure storage account context for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName'..."
pim-simons marked this conversation as resolved.
Show resolved Hide resolved
$storageAccount = Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName
if ($storageAccount -eq $null) {
throw "Retrieving Azure storage account context for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName' failed."
}
$ctx = $storageAccount.Context
Write-Verbose "Azure storage account context has been retrieved for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName'"

Write-Verbose "Retrieving Azure storage table '$TableName' for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName'..."
$storageTable = Get-AzStorageTable -Name $TableName -Context $ctx
if ($storageTable -eq $null) {
throw "Retrieving Azure storage table '$TableName' for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName' failed."
}
$cloudTable = ($storageTable).CloudTable
Write-Verbose "Azure storage table '$TableName' has been retrieved for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName'"

Write-Host "Deleting all existing entities in Azure storage table '$TableName' for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName'..."
$entitiesToDelete = Get-AzTableRow -table $cloudTable
$deletedEntities = $entitiesToDelete | Remove-AzTableRow -table $cloudTable
Write-Host "Successfully deleted all existing entities in Azure storage table '$TableName' for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName'"

$configFile = Get-Content -Path $ConfigurationFile | ConvertFrom-Json
pim-simons marked this conversation as resolved.
Show resolved Hide resolved
foreach ($entityToAdd in $configFile) {
if ($entityToAdd.PartitionKey) {
$partitionKey = $entityToAdd.PartitionKey
$entityToAdd.PSObject.Properties.Remove('PartitionKey')
} else {
$partitionKey = New-Guid
}

if ($entityToAdd.RowKey) {
$rowKey = $entityToAdd.RowKey
$entityToAdd.PSObject.Properties.Remove('RowKey')
} else {
$rowKey = New-Guid
}

$entityHash = @{}
$entityToAdd.PSObject.Properties | foreach { $entityHash[$_.Name] = $_.Value }

$addedRow = Add-AzTableRow `
-table $cloudTable `
-partitionKey $partitionKey `
-rowKey $rowKey `
-property $entityHash

Write-Verbose "Successfully added row with PartitionKey '$partitionKey' and RowKey '$rowKey' to Azure storage table '$TableName' for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName'"
stijnmoreels marked this conversation as resolved.
Show resolved Hide resolved
}

Write-Host "Successfully added all entities in Azure storage table '$TableName' for Azure storage account '$StorageAccountName' in resource group '$ResourceGroupName'"
stijnmoreels marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -22,66 +22,118 @@ InModuleScope Arcus.Scripting.Storage.Table {
$config = & $PSScriptRoot\Load-JsonAppsettings.ps1
& $PSScriptRoot\Connect-AzAccountFromConfig.ps1 -config $config
}
Context "Create Azure table storage table" {
It "Create an new Azure table within an Azure storage account" {
#Context "Create Azure table storage table" {
# It "Create an new Azure table within an Azure storage account" {
# # Arrange
# $tableName = "arcusnewtable"
# $storageAccount = Get-AzStorageAccount -ResourceGroupName $config.Arcus.ResourceGroupName -Name $config.Arcus.Storage.StorageAccount.Name
# try {
# # Act
# Create-AzStorageTable `
# -ResourceGroupName $config.Arcus.ResourceGroupName `
# -StorageAccountName $config.Arcus.Storage.StorageAccount.Name `
# -Table $tableName

# # Assert
# $storageTable = Get-AzStorageTable -Name $tableName -Context $storageAccount.Context
# $storageTable.Name | Should -Be $tableName
# } finally {
# Remove-AzStorageTable -Name $tableName -Context $storageAccount.Context -Force
# }
# }
# It "Re-creates a new Azure table within an Azure storage account" {
# # Arrange
# $tableName = "arcusalreadyexistingtable"
# try {
# $storageAccount = Get-AzStorageAccount -ResourceGroupName $config.Arcus.ResourceGroupName -Name $config.Arcus.Storage.StorageAccount.Name
# Retry-Func { New-AzStorageTable -Name $tableName -Context $storageAccount.Context -ErrorAction SilentlyContinue }
# $storageTable = Get-AzStorageTable –Name $tableName –Context $storageAccount.Context
# $partitionKey = "arcus-azure-resources"
# Add-AzTableRow -Table $storageTable.CloudTable -PartitionKey $partitionKey -RowKey ("Scripting") -Property @{"Resource"="Table storage"}
# Get-AzTableRow -Table $storageTable.CloudTable -PartitionKey $partitionKey |
# Should -Not -Be $null

# # Act
# Create-AzStorageTable `
# -ResourceGroupName $config.Arcus.ResourceGroupName `
# -StorageAccountName $config.Arcus.Storage.StorageAccount.Name `
# -Table $tableName `
# -Recreate

# # Assert
# Get-AzTableRow -Table $storageTable.CloudTable -PartitionKey $partitionKey |
# Should -Be $null

# } finally {
# Remove-AzStorageTable -Name $tableName -Context $storageAccount.Context -Force
# }
# }
# It "Fails to re-create a new Azure table within an Azure storage account with not enough retry time" {
# # Arrange
# $tableName = "arcusfailedrecreatetable"
# try {
# $storageAccount = Get-AzStorageAccount -ResourceGroupName $config.Arcus.ResourceGroupName -Name $config.Arcus.Storage.StorageAccount.Name
# Retry-Func { New-AzStorageTable -Name $tableName -Context $storageAccount.Context -ErrorAction SilentlyContinue }

# # Act
# { Create-AzStorageTable `
# -ResourceGroupName $config.Arcus.ResourceGroupName `
# -StorageAccountName $config.Arcus.Storage.StorageAccount.Name `
# -Table $tableName `
# -Recreate `
# -MaxRetryCount 2 } | Should -Throw
# } finally {
# Remove-AzStorageTable -Name $tableName -Context $storageAccount.Context -Force -ErrorAction SilentlyContinue
# }
# }
#}
Context "Setting Azure Table Storage Entities" {
It "Setting entities in an Azure Table Storage account" {
# Arrange
$tableName = "arcusnewtable"
$storageAccount = Get-AzStorageAccount -ResourceGroupName $config.Arcus.ResourceGroupName -Name $config.Arcus.Storage.StorageAccount.Name
$resourceGroup = $config.Arcus.ResourceGroupName
$storageAccountName = $config.Arcus.Storage.StorageAccount.Name
$tableName = "SetEntityTable"
$configFile = "$PSScriptRoot\Files\TableStorage\set-aztablestorageentities-config.json"
$storageAccount = Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $storageAccountName

try {
# Act
Create-AzStorageTable `
-ResourceGroupName $config.Arcus.ResourceGroupName `
-StorageAccountName $config.Arcus.Storage.StorageAccount.Name `
-Table $tableName

Set-AzTableStorageEntities -ResourceGroupName $resourceGroup -StorageAccountName $storageAccountName -TableName $tableName -ConfigurationFile $configFile

# Assert
$storageTable = Get-AzStorageTable -Name $tableName -Context $storageAccount.Context
$storageTable.Name | Should -Be $tableName
$storageTable = Get-AzStorageTable –Name $tableName –Context $storageAccount.Context
(Get-AzTableRow -table $storageTable.CloudTable | measure).Count |
Should -Be 2
} finally {
Remove-AzStorageTable -Name $tableName -Context $storageAccount.Context -Force
Remove-AzStorageTable -Name $tableName -Context $storageAccount.Context -Force -ErrorAction SilentlyContinue
}
}
It "Re-creates a new Azure table within an Azure storage account" {
It "Setting entities in an Azure Table Storage account without specifying PartitionKey and RowKey" {
# Arrange
$tableName = "arcusalreadyexistingtable"
try {
$storageAccount = Get-AzStorageAccount -ResourceGroupName $config.Arcus.ResourceGroupName -Name $config.Arcus.Storage.StorageAccount.Name
Retry-Func { New-AzStorageTable -Name $tableName -Context $storageAccount.Context -ErrorAction SilentlyContinue }
$storageTable = Get-AzStorageTable –Name $tableName –Context $storageAccount.Context
$partitionKey = "arcus-azure-resources"
Add-AzTableRow -Table $storageTable.CloudTable -PartitionKey $partitionKey -RowKey ("Scripting") -Property @{"Resource"="Table storage"}
Get-AzTableRow -Table $storageTable.CloudTable -PartitionKey $partitionKey |
Should -Not -Be $null
$resourceGroup = $config.Arcus.ResourceGroupName
$storageAccountName = $config.Arcus.Storage.StorageAccount.Name
$tableName = "SetEntityTableNoKeys"
$configFile = "$PSScriptRoot\Files\TableStorage\set-aztablestorageentities-config-nokeys.json"
$storageAccount = Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $storageAccountName

try {
# Act
Create-AzStorageTable `
-ResourceGroupName $config.Arcus.ResourceGroupName `
-StorageAccountName $config.Arcus.Storage.StorageAccount.Name `
-Table $tableName `
-Recreate
-Table $tableName

# Assert
Get-AzTableRow -Table $storageTable.CloudTable -PartitionKey $partitionKey |
Should -Be $null

} finally {
Remove-AzStorageTable -Name $tableName -Context $storageAccount.Context -Force
}
}
It "Fails to re-create a new Azure table within an Azure storage account with not enough retry time" {
# Arrange
$tableName = "arcusfailedrecreatetable"
try {
$storageAccount = Get-AzStorageAccount -ResourceGroupName $config.Arcus.ResourceGroupName -Name $config.Arcus.Storage.StorageAccount.Name
Retry-Func { New-AzStorageTable -Name $tableName -Context $storageAccount.Context -ErrorAction SilentlyContinue }
Set-AzTableStorageEntities -ResourceGroupName $resourceGroup -StorageAccountName $storageAccountName -TableName $tableName -ConfigurationFile $configFile

# Act
{ Create-AzStorageTable `
-ResourceGroupName $config.Arcus.ResourceGroupName `
-StorageAccountName $config.Arcus.Storage.StorageAccount.Name `
-Table $tableName `
-Recreate `
-MaxRetryCount 2 } | Should -Throw
# Assert
$storageTable = Get-AzStorageTable –Name $tableName –Context $storageAccount.Context
(Get-AzTableRow -table $storageTable.CloudTable | measure).Count |
Should -Be 2
} finally {
Remove-AzStorageTable -Name $tableName -Context $storageAccount.Context -Force -ErrorAction SilentlyContinue
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<Folder Include="Files\IntegrationAccount\Partners\" />
<Folder Include="Files\IntegrationAccount\Schemas\" />
<Folder Include="Files\IntegrationAccount\Schemas\Common\" />
<Folder Include="Files\TableStorage\" />
<Folder Include="SqlScripts\" />
<Folder Include="SqlScripts\MigrationScriptsAreSuccessfullyExecuted\" />
<Folder Include="SqlScripts\MigrationStopsOnError\" />
Expand Down Expand Up @@ -94,6 +95,8 @@
<Content Include="Files\IntegrationAccount\Schemas\NestedSchema.xsd" />
<Content Include="Files\IntegrationAccount\Schemas\Acknowledgement.xsd" />
<Content Include="Files\IntegrationAccount\Schemas\Common\NestedSchemaRoot.xsd" />
<Content Include="Files\TableStorage\set-aztablestorageentities-config-nokeys.json" />
<Content Include="Files\TableStorage\set-aztablestorageentities-config.json" />
<Content Include="SqlScripts\1_EmptyMigration.sql" />
<Content Include="SqlScripts\MigrationScriptsAreSuccessfullyExecuted\0.0.1_baseline.sql" />
<Content Include="SqlScripts\MigrationScriptsAreSuccessfullyExecuted\0.1.0_AddCustomerTable.sql" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"ReadPath": "/home/in",
"ReadIntervalInSeconds": "30"
},
{
"ReadPath": "/data/in",
"ReadIntervalInSeconds": "10",
"HasSubdirectories": "true"
}
]
Loading