Skip to content

Commit 6638449

Browse files
authored
[Storage] Support ORS (#12668)
1 parent 5f19e78 commit 6638449

19 files changed

+4166
-10
lines changed

src/Storage/Storage.Management.Test/ScenarioTests/StorageBlobTests.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,12 @@ public void TestStorageBlobServiceProperties()
6565
{
6666
TestController.NewInstance.RunPsTest(_logger, "Test-StorageBlobServiceProperties");
6767
}
68+
69+
[Fact]
70+
[Trait(Category.AcceptanceType, Category.CheckIn)]
71+
public void TestStorageBlobORS()
72+
{
73+
TestController.NewInstance.RunPsTest(_logger, "Test-StorageBlobORS");
74+
}
6875
}
6976
}

src/Storage/Storage.Management.Test/ScenarioTests/StorageBlobTests.ps1

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,3 +437,107 @@ function Test-StorageBlobServiceProperties
437437

438438

439439

440+
<#
441+
.SYNOPSIS
442+
Test StorageAccount Object Replication
443+
.DESCRIPTION
444+
SmokeTest
445+
#>
446+
function Test-StorageBlobORS
447+
{
448+
# Setup
449+
$rgname = Get-StorageManagementTestResourceName;
450+
451+
try
452+
{
453+
# Test
454+
$stoname1 = 'sto' + $rgname + 'src';
455+
$stoname2 = 'sto' + $rgname + 'dest';
456+
$stotype = 'Standard_LRS';
457+
$loc = Get-ProviderLocation ResourceManagement;
458+
$kind = 'StorageV2'
459+
460+
Write-Verbose "RGName: $rgname | Loc: $loc"
461+
New-AzResourceGroup -Name $rgname -Location $loc;
462+
463+
$loc = Get-ProviderLocation_Canary ResourceManagement;
464+
New-AzStorageAccount -ResourceGroupName $rgname -Name $stoname1 -Location $loc -Type $stotype -Kind $kind
465+
New-AzStorageAccount -ResourceGroupName $rgname -Name $stoname2 -Location $loc -Type $stotype -Kind $kind
466+
467+
# Enable Blob Enable Changefeed and versioning
468+
Update-AzStorageBlobServiceProperty -ResourceGroupName $rgname -StorageAccountName $stoname1 -EnableChangeFeed $true -IsVersioningEnabled $true
469+
Update-AzStorageBlobServiceProperty -ResourceGroupName $rgname -StorageAccountName $stoname2 -EnableChangeFeed $true -IsVersioningEnabled $true
470+
$property1 = Get-AzStorageBlobServiceProperty -ResourceGroupName $rgname -StorageAccountName $stoname1
471+
Assert-AreEqual $true $property1.ChangeFeed.Enabled
472+
Assert-AreEqual $true $property1.IsVersioningEnabled
473+
$property2 = Get-AzStorageBlobServiceProperty -ResourceGroupName $rgname -StorageAccountName $stoname2
474+
Assert-AreEqual $true $property2.ChangeFeed.Enabled
475+
Assert-AreEqual $true $property2.IsVersioningEnabled
476+
477+
# create containers
478+
Get-AzStorageAccount -ResourceGroupName $rgname -StorageAccountName $stoname1 | New-AzRmStorageContainer -name src
479+
Get-AzStorageAccount -ResourceGroupName $rgname -StorageAccountName $stoname2 | New-AzRmStorageContainer -name dest
480+
Get-AzStorageAccount -ResourceGroupName $rgname -StorageAccountName $stoname1 | New-AzRmStorageContainer -name src1
481+
Get-AzStorageAccount -ResourceGroupName $rgname -StorageAccountName $stoname2 | New-AzRmStorageContainer -name dest1
482+
483+
# create rules
484+
$minCreationTime = "2019-01-01T16:00:00Z"
485+
$rule1 = New-AzStorageObjectReplicationPolicyRule -SourceContainer src1 -DestinationContainer dest1
486+
$rule2 = New-AzStorageObjectReplicationPolicyRule -SourceContainer src -DestinationContainer dest -MinCreationTime $minCreationTime -PrefixMatch a,abc,dd #-Tag t1,t2,t3
487+
488+
# set policy to dest account
489+
$destPolicy = Set-AzStorageObjectReplicationPolicy -ResourceGroupName $rgname -StorageAccountName $stoname2 -PolicyId default -SourceAccount $stoname1 -Rule $rule1,$rule2
490+
$policyID = $destPolicy.PolicyId
491+
Assert-AreEqual $stoname1 $destPolicy.SourceAccount
492+
Assert-AreEqual $stoname2 $destPolicy.DestinationAccount
493+
Assert-AreEqual 2 $destPolicy.Rules.Count
494+
Assert-AreEqual src1 $destPolicy.Rules[0].SourceContainer
495+
Assert-AreEqual dest1 $destPolicy.Rules[0].DestinationContainer
496+
Assert-AreEqual $null $destPolicy.Rules[0].Filters
497+
Assert-AreEqual src $destPolicy.Rules[1].SourceContainer
498+
Assert-AreEqual dest $destPolicy.Rules[1].DestinationContainer
499+
Assert-AreEqual 3 $destPolicy.Rules[1].Filters.PrefixMatch.Count
500+
Assert-AreEqual $minCreationTime ($destPolicy.Rules[1].Filters.MinCreationTime.ToUniversalTime().ToString("s")+"Z")
501+
$destPolicy = Get-AzStorageObjectReplicationPolicy -ResourceGroupName $rgname -StorageAccountName $stoname2 -PolicyId $destPolicy.PolicyId
502+
Assert-AreEqual $policyID $destPolicy.PolicyId
503+
Assert-AreEqual $stoname1 $destPolicy.SourceAccount
504+
Assert-AreEqual $stoname2 $destPolicy.DestinationAccount
505+
Assert-AreEqual 2 $destPolicy.Rules.Count
506+
Assert-AreEqual src1 $destPolicy.Rules[0].SourceContainer
507+
Assert-AreEqual dest1 $destPolicy.Rules[0].DestinationContainer
508+
Assert-AreEqual $null $destPolicy.Rules[0].Filters
509+
Assert-AreEqual src $destPolicy.Rules[1].SourceContainer
510+
Assert-AreEqual dest $destPolicy.Rules[1].DestinationContainer
511+
Assert-AreEqual 3 $destPolicy.Rules[1].Filters.PrefixMatch.Count
512+
Assert-AreEqual $minCreationTime ($destPolicy.Rules[1].Filters.MinCreationTime.ToUniversalTime().ToString("s")+"Z")
513+
514+
#Set policy to source account
515+
Set-AzStorageObjectReplicationPolicy -ResourceGroupName $rgname -StorageAccountName $stoname1 -InputObject $destPolicy
516+
$srcPolicy = Get-AzStorageObjectReplicationPolicy -ResourceGroupName $rgname -StorageAccountName $stoname1
517+
Assert-AreEqual $policyID $srcPolicy.PolicyId
518+
Assert-AreEqual $stoname1 $srcPolicy.SourceAccount
519+
Assert-AreEqual $stoname2 $srcPolicy.DestinationAccount
520+
Assert-AreEqual 2 $srcPolicy.Rules.Count
521+
Assert-AreEqual src1 $srcPolicy.Rules[0].SourceContainer
522+
Assert-AreEqual dest1 $srcPolicy.Rules[0].DestinationContainer
523+
Assert-AreEqual $null $srcPolicy.Rules[0].Filters
524+
Assert-AreEqual src $srcPolicy.Rules[1].SourceContainer
525+
Assert-AreEqual dest $srcPolicy.Rules[1].DestinationContainer
526+
Assert-AreEqual 3 $srcPolicy.Rules[1].Filters.PrefixMatch.Count
527+
Assert-AreEqual $minCreationTime ($srcPolicy.Rules[1].Filters.MinCreationTime.ToUniversalTime().ToString("s")+"Z")
528+
529+
#remove policies
530+
Remove-AzStorageObjectReplicationPolicy -ResourceGroupName $rgname -StorageAccountName $stoname2 -PolicyId $destPolicy.PolicyId
531+
Remove-AzStorageObjectReplicationPolicy -ResourceGroupName $rgname -StorageAccountName $stoname1 -PolicyId $srcPolicy.PolicyId
532+
533+
Remove-AzStorageAccount -Force -ResourceGroupName $rgname -Name $stoname1;
534+
Remove-AzStorageAccount -Force -ResourceGroupName $rgname -Name $stoname2;
535+
}
536+
finally
537+
{
538+
# Cleanup
539+
Clean-ResourceGroup $rgname
540+
}
541+
}
542+
543+

src/Storage/Storage.Management.Test/SessionRecords/Microsoft.Azure.Commands.Management.Storage.Test.ScenarioTests.StorageBlobTests/TestStorageBlobORS.json

Lines changed: 2391 additions & 0 deletions
Large diffs are not rendered by default.

src/Storage/Storage.Management/Az.Storage.psd1

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,9 @@ CmdletsToExport = 'Get-AzStorageAccount', 'Get-AzStorageAccountKey',
166166
'Remove-AzDataLakeGen2Item', 'Update-AzDataLakeGen2Item',
167167
'Set-AzDataLakeGen2ItemAclObject', 'Get-AzDataLakeGen2ItemContent',
168168
'Invoke-AzStorageAccountFailover',
169-
'Get-AzStorageBlobQueryResult', 'New-AzStorageBlobQueryConfig'
169+
'Get-AzStorageBlobQueryResult', 'New-AzStorageBlobQueryConfig',
170+
'New-AzStorageObjectReplicationPolicyRule', 'Set-AzStorageObjectReplicationPolicy',
171+
'Get-AzStorageObjectReplicationPolicy', 'Remove-AzStorageObjectReplicationPolicy'
170172

171173
# Variables to export from this module
172174
# VariablesToExport = @()

src/Storage/Storage.Management/Blob/UpdateAzureStorageBlobServiceProperties.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,23 @@ public class UpdateAzStorageBlobServicePropertyCommand : StorageBlobBaseCmdlet
8383
[ValidateNotNull]
8484
public string DefaultServiceVersion { get; set; }
8585

86+
[Parameter(
87+
Mandatory = false,
88+
HelpMessage = "Enable Change Feed logging for the storage account by set to $true, disable Change Feed logging by set to $false.")]
89+
[ValidateNotNullOrEmpty]
90+
public bool EnableChangeFeed
91+
{
92+
get
93+
{
94+
return enableChangeFeed is null ? false : enableChangeFeed.Value;
95+
}
96+
set
97+
{
98+
enableChangeFeed = value;
99+
}
100+
}
101+
private bool? enableChangeFeed = null;
102+
86103
[Parameter(
87104
Mandatory = false,
88105
HelpMessage = "Gets or sets versioning is enabled if set to true.")]
@@ -128,6 +145,11 @@ public override void ExecuteCmdlet()
128145
{
129146
serviceProperties.DefaultServiceVersion = this.DefaultServiceVersion;
130147
}
148+
if (enableChangeFeed != null)
149+
{
150+
serviceProperties.ChangeFeed = new ChangeFeed();
151+
serviceProperties.ChangeFeed.Enabled = enableChangeFeed;
152+
}
131153
if (isVersioningEnabled != null)
132154
{
133155
serviceProperties.IsVersioningEnabled = isVersioningEnabled;

src/Storage/Storage.Management/ChangeLog.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@
2525
- `Start-AzStorageBlobCopy`
2626
- `Get-AzDataLakeGen2Item`
2727
* Fixed [#12592]: Fix download blob fail when related sub directory not exist.
28-
- `Get-AzStorageBlobContent`
28+
- `Get-AzStorageBlobContent`
29+
* Support Set/Get/Remove Object Replication Policy on Storage accounts
30+
- `New-AzStorageObjectReplicationPolicyRule`
31+
- `Set-AzStorageObjectReplicationPolicy`
32+
- `Get-AzStorageObjectReplicationPolicy`
33+
- `Remove-AzStorageObjectReplicationPolicy`
34+
* Support enable/disable Changefeed on Blob Service of a Storage account
35+
- `Update-AzStorageBlobServiceProperty`
2936

3037
## Version 2.4.0
3138
* Supported create container/blob Sas token with new permission x,t
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.Management.Storage.Models;
16+
using Microsoft.WindowsAzure.Commands.Common.Attributes;
17+
using System;
18+
using System.Collections.Generic;
19+
20+
namespace Microsoft.Azure.Commands.Management.Storage.Models
21+
{
22+
/// <summary>
23+
/// Wrapper of SDK type ObjectReplicationPolicy
24+
/// </summary>
25+
public class PSObjectReplicationPolicy
26+
{
27+
[Ps1Xml(Label = "ResourceGroupName", Target = ViewControl.Table, Position = 0)]
28+
public string ResourceGroupName { get; }
29+
[Ps1Xml(Label = "StorageAccountName", Target = ViewControl.Table, Position = 1)]
30+
public string StorageAccountName { get; }
31+
public string ResourceId { get; }
32+
public string Name { get; }
33+
public string Type { get; }
34+
35+
[Ps1Xml(Label = "PolicyId", Target = ViewControl.Table, Position = 2)]
36+
public string PolicyId { get; set; }
37+
[Ps1Xml(Label = "EnabledTime", Target = ViewControl.Table, Position = 3)]
38+
public DateTime? EnabledTime { get; }
39+
[Ps1Xml(Label = "SourceAccount", Target = ViewControl.Table, Position = 4)]
40+
public string SourceAccount { get; set; }
41+
[Ps1Xml(Label = "DestinationAccount", Target = ViewControl.Table, Position = 5)]
42+
public string DestinationAccount { get; set; }
43+
[Ps1Xml(Label = "Rules", Target = ViewControl.Table, ScriptBlock = "if (($_.Rules -ne $null) -and ($_.Rules.Count -ne 0)) {'[' + $_.Rules[0].RuleId + ',...]'} else {$null}", Position = 6)]
44+
public PSObjectReplicationPolicyRule[] Rules { get; set; }
45+
46+
public PSObjectReplicationPolicy()
47+
{ }
48+
49+
public PSObjectReplicationPolicy(ObjectReplicationPolicy policy, string ResourceGroupName, string StorageAccountName)
50+
{
51+
this.ResourceGroupName = ResourceGroupName;
52+
this.StorageAccountName = StorageAccountName;
53+
this.ResourceId = policy.Id;
54+
this.Name = policy.Name;
55+
this.Type = policy.Type;
56+
this.PolicyId = policy.PolicyId;
57+
this.EnabledTime = policy.EnabledTime;
58+
this.SourceAccount = policy.SourceAccount;
59+
this.DestinationAccount = policy.DestinationAccount;
60+
this.Rules = PSObjectReplicationPolicyRule.GetPSObjectReplicationPolicyRules(policy.Rules);
61+
}
62+
63+
public ObjectReplicationPolicy ParseObjectReplicationPolicy()
64+
{
65+
ObjectReplicationPolicy policy = new ObjectReplicationPolicy()
66+
{
67+
SourceAccount = this.SourceAccount,
68+
DestinationAccount = this.DestinationAccount,
69+
Rules = PSObjectReplicationPolicyRule.ParseObjectReplicationPolicyRules(this.Rules)
70+
};
71+
return policy;
72+
}
73+
74+
public static PSObjectReplicationPolicy[] GetPSObjectReplicationPolicies(IEnumerable<ObjectReplicationPolicy> policies, string ResourceGroupName, string StorageAccountName)
75+
{
76+
if (policies == null)
77+
{
78+
return null;
79+
}
80+
List<PSObjectReplicationPolicy> pspolicies = new List<PSObjectReplicationPolicy>();
81+
foreach (ObjectReplicationPolicy policy in policies)
82+
{
83+
pspolicies.Add(new PSObjectReplicationPolicy(policy, ResourceGroupName, StorageAccountName));
84+
}
85+
return pspolicies.ToArray();
86+
}
87+
}
88+
89+
/// <summary>
90+
/// Wrapper of SDK type ObjectReplicationPolicyRule
91+
/// </summary>
92+
public class PSObjectReplicationPolicyRule
93+
{
94+
[Ps1Xml(Label = "RuleId", Target = ViewControl.Table, Position = 0)]
95+
public string RuleId { get; set; }
96+
[Ps1Xml(Label = "SourceContainer", Target = ViewControl.Table, Position = 1)]
97+
public string SourceContainer { get; set; }
98+
[Ps1Xml(Label = "DestinationContainer", Target = ViewControl.Table, Position = 2)]
99+
public string DestinationContainer { get; set; }
100+
[Ps1Xml(Label = "Filter.PrefixMatch", Target = ViewControl.Table, ScriptBlock = "if (($_.Filter -ne $null) -and ($_.Filter.PrefixMatch -ne $null) -and ($_.Filter.PrefixMatch.Count -ne 0)) {'[' + ($_.Filter.PrefixMatch -join ', ') + ']'} else {$null}", Position = 3)]
101+
public PSObjectReplicationPolicyFilter Filters { get; set; }
102+
103+
public PSObjectReplicationPolicyRule()
104+
{
105+
}
106+
107+
public PSObjectReplicationPolicyRule(ObjectReplicationPolicyRule rule)
108+
{
109+
this.RuleId = rule.RuleId;
110+
this.SourceContainer = rule.SourceContainer;
111+
this.DestinationContainer = rule.DestinationContainer;
112+
this.Filters = rule.Filters is null ? null : new PSObjectReplicationPolicyFilter(rule.Filters);
113+
}
114+
115+
public ObjectReplicationPolicyRule ParseObjectReplicationPolicyRule()
116+
{
117+
ObjectReplicationPolicyRule rule = new ObjectReplicationPolicyRule();
118+
rule.RuleId = this.RuleId;
119+
rule.SourceContainer = this.SourceContainer;
120+
rule.DestinationContainer = this.DestinationContainer;
121+
rule.Filters = this.Filters is null ? null : this.Filters.ParseObjectReplicationPolicyFilter();
122+
return rule;
123+
}
124+
125+
public static PSObjectReplicationPolicyRule[] GetPSObjectReplicationPolicyRules(IList<ObjectReplicationPolicyRule> rules)
126+
{
127+
if (rules == null)
128+
{
129+
return null;
130+
}
131+
List<PSObjectReplicationPolicyRule> psrules = new List<PSObjectReplicationPolicyRule>();
132+
foreach (ObjectReplicationPolicyRule rule in rules)
133+
{
134+
psrules.Add(new PSObjectReplicationPolicyRule(rule));
135+
}
136+
return psrules.ToArray();
137+
}
138+
139+
public static List<ObjectReplicationPolicyRule> ParseObjectReplicationPolicyRules(PSObjectReplicationPolicyRule[] psrules)
140+
{
141+
if (psrules == null)
142+
{
143+
return null;
144+
}
145+
List<ObjectReplicationPolicyRule> rules = new List<ObjectReplicationPolicyRule>();
146+
foreach (PSObjectReplicationPolicyRule psrule in psrules)
147+
{
148+
rules.Add(psrule.ParseObjectReplicationPolicyRule());
149+
}
150+
return rules;
151+
}
152+
}
153+
154+
/// <summary>
155+
/// Wrapper of SDK type ObjectReplicationPolicyFilter
156+
/// </summary>
157+
public class PSObjectReplicationPolicyFilter
158+
{
159+
public string[] PrefixMatch { get; set; }
160+
public DateTime? MinCreationTime;
161+
162+
public PSObjectReplicationPolicyFilter()
163+
{
164+
}
165+
166+
public PSObjectReplicationPolicyFilter(ObjectReplicationPolicyFilter filter)
167+
{
168+
if (filter != null)
169+
{
170+
this.PrefixMatch = filter.PrefixMatch is null ? null : new List<string>(filter.PrefixMatch).ToArray();
171+
if (string.IsNullOrEmpty(filter.MinCreationTime))
172+
{
173+
this.MinCreationTime = null;
174+
}
175+
else
176+
{
177+
if (filter.MinCreationTime.ToUpper()[filter.MinCreationTime.Length - 1] != 'Z')
178+
{
179+
filter.MinCreationTime = filter.MinCreationTime + "Z";
180+
}
181+
this.MinCreationTime = Convert.ToDateTime(filter.MinCreationTime);
182+
}
183+
}
184+
}
185+
public ObjectReplicationPolicyFilter ParseObjectReplicationPolicyFilter()
186+
{
187+
return new ObjectReplicationPolicyFilter()
188+
{
189+
PrefixMatch = this.PrefixMatch is null ? null : new List<string>(this.PrefixMatch),
190+
//must be in format: 2020-02-19T16:05:00Z
191+
MinCreationTime = this.MinCreationTime is null ? null : this.MinCreationTime.Value.ToUniversalTime().ToString("s") + "Z"
192+
};
193+
}
194+
}
195+
}

0 commit comments

Comments
 (0)