From f955f915f1a5e53e81ea790f658348bdcd08e1f9 Mon Sep 17 00:00:00 2001 From: Dirk Eisenberg Date: Thu, 9 Nov 2023 22:18:49 +0100 Subject: [PATCH] Allow to use regex patten for table exclude check when doing a backup --- ...owsAzure.Storage.Table.Backup.Tests.csproj | 28 ++++++++++++++++ .../TableExcludeExpressionTests.cs | 31 ++++++++++++++++++ .../Usings.cs | 1 + .../AssemblyInfo.cs | 18 +++++++++++ .../BackupContext.cs | 15 +++------ .../TabledExcludeExpressionValidator.cs | 32 +++++++++++++++++++ CoreHelpers.WindowsAzure.Storage.Table.sln | 6 ++++ 7 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests.csproj create mode 100644 CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/TableExcludeExpressionTests.cs create mode 100644 CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/Usings.cs create mode 100644 CoreHelpers.WindowsAzure.Storage.Table.Backup/AssemblyInfo.cs create mode 100644 CoreHelpers.WindowsAzure.Storage.Table.Backup/Internal/TabledExcludeExpressionValidator.cs diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests.csproj b/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests.csproj new file mode 100644 index 0000000..2ee0427 --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests.csproj @@ -0,0 +1,28 @@ + + + + net6.0 + enable + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/TableExcludeExpressionTests.cs b/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/TableExcludeExpressionTests.cs new file mode 100644 index 0000000..b213803 --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/TableExcludeExpressionTests.cs @@ -0,0 +1,31 @@ +using CoreHelpers.WindowsAzure.Storage.Table.Backup.Internal; + +namespace CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests; + +public class TableExcludeExpressionTests +{ + [Fact] + public void VerifyFullTableNameTests() + { + var validator = new TabledExcludeExpressionValidator(new string[] { "demoTable", "secondTable" }); + Assert.True(validator.IsTableExcluded("demoTable")); + Assert.True(validator.IsTableExcluded("demotable")); + Assert.True(validator.IsTableExcluded("DEMOTABLE")); + Assert.True(validator.IsTableExcluded("secondtable")); + Assert.False(validator.IsTableExcluded("demo*")); + Assert.False(validator.IsTableExcluded("*Table")); + Assert.False(validator.IsTableExcluded("otherTable")); + } + + [Fact] + public void VerifyRegExPatternTableNameTests() + { + var validator = new TabledExcludeExpressionValidator(new string[] { "demo.*" }); + Assert.True(validator.IsTableExcluded("demoTable")); + Assert.True(validator.IsTableExcluded("demotable")); + Assert.True(validator.IsTableExcluded("DEMOTABLE")); + Assert.True(validator.IsTableExcluded("demo*")); + Assert.False(validator.IsTableExcluded("*Table")); + Assert.False(validator.IsTableExcluded("otherTable")); + } +} \ No newline at end of file diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/Usings.cs b/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Backup/AssemblyInfo.cs b/CoreHelpers.WindowsAzure.Storage.Table.Backup/AssemblyInfo.cs new file mode 100644 index 0000000..13ec9cd --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Backup/AssemblyInfo.cs @@ -0,0 +1,18 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyCompany("Core Helpers")] +[assembly: AssemblyProduct("WindowsAzure.Storage.Table.Backup")] +[assembly: AssemblyTitle("CoreHelpers Azure Storage Abstraction")] + +[assembly: AssemblyFileVersion("2.0.0.0")] +[assembly: AssemblyVersion("2.0.0.0")] + +#if (DEBUG) +[assembly: AssemblyConfiguration("Debug")] +#else +[assembly: AssemblyConfiguration("Release")] +#endif + +[assembly: InternalsVisibleTo("CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests")] \ No newline at end of file diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Backup/BackupContext.cs b/CoreHelpers.WindowsAzure.Storage.Table.Backup/BackupContext.cs index aee2977..c341ccc 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table.Backup/BackupContext.cs +++ b/CoreHelpers.WindowsAzure.Storage.Table.Backup/BackupContext.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Azure.Storage.Blobs; using CoreHelpers.WindowsAzure.Storage.Table.Backup.Abstractions; +using CoreHelpers.WindowsAzure.Storage.Table.Backup.Internal; using Microsoft.Extensions.Logging; namespace CoreHelpers.WindowsAzure.Storage.Table.Backup @@ -34,15 +35,9 @@ public async Task Backup(IStorageContext storageContext, string[] excludedTables { using (_logger.BeginScope("Starting backup procedure...")) { - - // generate the excludeTables - var excludedTablesList = new List(); - if (excludedTables != null) - { - foreach (var tbl in excludedTables) - excludedTablesList.Add(tbl.ToLower()); - } - + // build the exclude validator + var excludeValidator = new TabledExcludeExpressionValidator(excludedTables); + // get all tables var tables = await storageContext.QueryTableList(); _logger.LogInformation($"Processing {tables.Count} tables"); @@ -78,7 +73,7 @@ public async Task Backup(IStorageContext storageContext, string[] excludedTables } // check the excluded tables - if (excludedTablesList.Contains(tableName.ToLower())) + if (excludeValidator.IsTableExcluded(tableName)) { _logger.LogInformation($"Ignoring table {tableName} (is part of excluded tables)..."); continue; diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Backup/Internal/TabledExcludeExpressionValidator.cs b/CoreHelpers.WindowsAzure.Storage.Table.Backup/Internal/TabledExcludeExpressionValidator.cs new file mode 100644 index 0000000..032b5f2 --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Backup/Internal/TabledExcludeExpressionValidator.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; + +namespace CoreHelpers.WindowsAzure.Storage.Table.Backup.Internal; + +internal class TabledExcludeExpressionValidator +{ + private List _excludes = new List(); + public TabledExcludeExpressionValidator(string[]? excludes) + { + if (excludes != null) + _excludes = excludes.Select(e => e.ToLower()).ToList(); + } + + public bool IsTableExcluded(string tableName) + { + // verify if the tablename is in the exclude list + if (_excludes.Contains(tableName.ToLower())) + return true; + + // verify if the tablename matches a regex pattern + foreach (var exclude in _excludes) + { + if (Regex.IsMatch(tableName, exclude, RegexOptions.IgnoreCase)) + return true; + } + + // all the rest don't exclude + return false; + } +} \ No newline at end of file diff --git a/CoreHelpers.WindowsAzure.Storage.Table.sln b/CoreHelpers.WindowsAzure.Storage.Table.sln index 1bd01da..e8fd228 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table.sln +++ b/CoreHelpers.WindowsAzure.Storage.Table.sln @@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreHelpers.WindowsAzure.St EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreHelpers.WindowsAzure.Storage.Table.Backup.Abstractions", "CoreHelpers.WindowsAzure.Storage.Table.Backup.Abstractions\CoreHelpers.WindowsAzure.Storage.Table.Backup.Abstractions.csproj", "{72CBB151-FEEC-4174-AEAE-684EAAF951AB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests", "CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests\CoreHelpers.WindowsAzure.Storage.Table.Backup.Tests.csproj", "{E2137490-9013-41E8-8CF3-F814414E7FD8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -44,6 +46,10 @@ Global {72CBB151-FEEC-4174-AEAE-684EAAF951AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {72CBB151-FEEC-4174-AEAE-684EAAF951AB}.Release|Any CPU.ActiveCfg = Release|Any CPU {72CBB151-FEEC-4174-AEAE-684EAAF951AB}.Release|Any CPU.Build.0 = Release|Any CPU + {E2137490-9013-41E8-8CF3-F814414E7FD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2137490-9013-41E8-8CF3-F814414E7FD8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2137490-9013-41E8-8CF3-F814414E7FD8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2137490-9013-41E8-8CF3-F814414E7FD8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE