Skip to content

Commit 8d4d9a3

Browse files
committed
Merge pull request #1041 from markcowl/storagecontext
Make storage data cmdlets work with ARM and ASM
2 parents f2674a6 + fed6d76 commit 8d4d9a3

File tree

145 files changed

+5147
-716
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

145 files changed

+5147
-716
lines changed

setup/azurecmdfiles.wxi

Lines changed: 259 additions & 55 deletions
Large diffs are not rendered by default.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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 System;
16+
using System.Collections.Generic;
17+
using Microsoft.WindowsAzure.Commands.Common;
18+
using Microsoft.Azure.Common.Authentication.Models;
19+
using Microsoft.WindowsAzure.Commands.Common.Storage;
20+
using ArmStorage = Microsoft.Azure.Management.Storage;
21+
using SmStorage = Microsoft.WindowsAzure.Management.Storage;
22+
using Microsoft.WindowsAzure.Storage;
23+
using Microsoft.Azure.Common.Authentication;
24+
using Microsoft.WindowsAzure.Storage.Auth;
25+
26+
namespace Microsoft.WindowsAzure.Commands.Utilities.Common
27+
{
28+
public static class AzureContextExtensions
29+
{
30+
/// <summary>
31+
/// Set the current storage account using the given connection string
32+
/// </summary>
33+
/// <param name="context">The current context.</param>
34+
/// <param name="connectionString">The connection string to check.</param>
35+
public static void SetCurrentStorageAccount(this AzureContext context, string connectionString)
36+
{
37+
if (context.Subscription != null)
38+
{
39+
context.Subscription.SetProperty(AzureSubscription.Property.StorageAccount, connectionString);
40+
}
41+
}
42+
43+
/// <summary>
44+
/// Set the current storage account using the given connection string.
45+
/// </summary>
46+
/// <param name="context">The current context.</param>
47+
/// <param name="account">A storage account.</param>
48+
public static void SetCurrentStorageAccount(this AzureContext context, IStorageContextProvider account)
49+
{
50+
if (context.Subscription != null && account != null && account.Context != null
51+
&& account.Context.StorageAccount != null)
52+
{
53+
context.SetCurrentStorageAccount(account.Context.StorageAccount.ToString(true));
54+
}
55+
}
56+
57+
/// <summary>
58+
/// Get the current storage account.
59+
/// </summary>
60+
/// <param name="context">The current context.</param>
61+
/// <returns>The current storage account, or null, if no current storage account is set.</returns>
62+
public static CloudStorageAccount GetCurrentStorageAccount(this AzureContext context)
63+
{
64+
if (context != null && context.Subscription != null)
65+
{
66+
try
67+
{
68+
return
69+
CloudStorageAccount.Parse(
70+
context.Subscription.GetProperty(AzureSubscription.Property.StorageAccount));
71+
}
72+
catch
73+
{
74+
// return null if we could not parse the connection string
75+
}
76+
}
77+
78+
return null;
79+
}
80+
81+
}
82+
}

src/Common/Commands.Common.Storage/Commands.Common.Storage.csproj

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@
6767
<HintPath>..\..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll</HintPath>
6868
<Private>True</Private>
6969
</Reference>
70+
<Reference Include="Microsoft.Azure.Management.Storage, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
71+
<HintPath>..\..\packages\Microsoft.Azure.Management.Storage.2.4.0-preview\lib\net40\Microsoft.Azure.Management.Storage.dll</HintPath>
72+
<Private>True</Private>
73+
</Reference>
7074
<Reference Include="Microsoft.Azure.ResourceManager, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
7175
<SpecificVersion>False</SpecificVersion>
7276
<HintPath>..\..\packages\Microsoft.Azure.Management.Resources.2.18.7-preview\lib\net40\Microsoft.Azure.ResourceManager.dll</HintPath>
@@ -161,15 +165,18 @@
161165
<Compile Include="AzureStorageContext.cs" />
162166
<Compile Include="BlobUploadParameters.cs" />
163167
<Compile Include="IStorageClientWrapper.cs" />
168+
<Compile Include="IStorageContextProvider.cs" />
164169
<Compile Include="Properties\Resources.Designer.cs">
165170
<AutoGen>True</AutoGen>
166171
<DesignTime>True</DesignTime>
167172
<DependentUpon>Resources.resx</DependentUpon>
168173
</Compile>
169174
<Compile Include="StorageClientWrapper.cs" />
170175
<Compile Include="Properties\AssemblyInfo.cs" />
176+
<Compile Include="StorageIdentity.cs" />
171177
<Compile Include="StorageUtilities.cs" />
172178
<Compile Include="WindowsAzureSubscriptionExtensions.cs" />
179+
<Compile Include="AzureContextExtensions.cs" />
173180
</ItemGroup>
174181
<ItemGroup>
175182
<EmbeddedResource Include="Properties\Resources.resx">
@@ -180,6 +187,12 @@
180187
<ItemGroup>
181188
<None Include="packages.config" />
182189
</ItemGroup>
190+
<ItemGroup>
191+
<ProjectReference Include="..\Commands.Common\Commands.Common.csproj">
192+
<Project>{5ee72c53-1720-4309-b54b-5fb79703195f}</Project>
193+
<Name>Commands.Common</Name>
194+
</ProjectReference>
195+
</ItemGroup>
183196
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
184197
<Import Project="..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
185198
</Project>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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 System;
16+
using System.Collections.Generic;
17+
using System.Linq;
18+
using System.Text;
19+
using System.Threading.Tasks;
20+
21+
namespace Microsoft.WindowsAzure.Commands.Common.Storage
22+
{
23+
public interface IStorageContextProvider
24+
{
25+
AzureStorageContext Context
26+
{
27+
get;
28+
}
29+
}
30+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 System;
16+
using System.IO;
17+
using System.Text.RegularExpressions;
18+
19+
namespace Microsoft.WindowsAzure.Commands.Common.Storage
20+
{
21+
public class StorageIdentity
22+
{
23+
private const string StorageIdentityRegex =
24+
"/subscriptions/([^/]+)/resourceGroups/([^/]+)/microsoft.storage/storageAccounts/(\\w+)";
25+
public StorageIdentity(string identity)
26+
{
27+
var matcher = new Regex(StorageIdentityRegex);
28+
var result = matcher.Match(identity);
29+
if (!result.Success || result.Groups == null || result.Groups.Count < 3)
30+
{
31+
throw new InvalidOperationException(string.Format("Cannot find resource grpoup name and storage account name from resource identity {0}", identity));
32+
}
33+
34+
this.ResourceGroupName = result.Groups[1].Value;
35+
this.StorageAccountName = result.Groups[2].Value;
36+
}
37+
38+
public string ResourceGroupName { get; private set; }
39+
40+
public string StorageAccountName { get; private set; }
41+
}
42+
}

src/Common/Commands.Common.Storage/StorageUtilities.cs

Lines changed: 133 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
using System.CodeDom;
3+
using System.Diagnostics.Eventing.Reader;
4+
using System.Text;
5+
using Microsoft.Azure.Management.Storage;
6+
27
namespace Microsoft.WindowsAzure.Commands.Common.Storage
38
{
49
using System;
@@ -8,6 +13,7 @@ namespace Microsoft.WindowsAzure.Commands.Common.Storage
813
using Microsoft.WindowsAzure.Storage.Auth;
914
using Microsoft.WindowsAzure.Storage.Blob;
1015
using Microsoft.WindowsAzure.Storage.Table;
16+
using Arm = Microsoft.Azure.Management.Storage;
1117

1218
public class StorageUtilities
1319
{
@@ -26,38 +32,143 @@ public static Uri CreateHttpsEndpoint(string endpointUri)
2632
return new Uri(endpoint);
2733
}
2834

29-
public static CloudStorageAccount GenerateCloudStorageAccount(StorageManagementClient storageClient, string accountName)
35+
/// <summary>
36+
/// Create a cloud storage account using an ARM storage management client
37+
/// </summary>
38+
/// <param name="storageClient">The client to use to get storage account details.</param>
39+
/// <param name="resourceGroupName">The resource group contining the storage account.</param>
40+
/// <param name="accountName">The name of the storage account.</param>
41+
/// <returns>A CloudStorageAccount that can be used by windows azure storage library to manipulate objects in the storage account.</returns>
42+
public static CloudStorageAccount GenerateCloudStorageAccount(Arm.IStorageManagementClient storageClient,
43+
string resourceGroupName, string accountName)
3044
{
31-
var storageServiceResponse = storageClient.StorageAccounts.Get(accountName);
32-
var storageKeysResponse = storageClient.StorageAccounts.GetKeys(accountName);
33-
34-
Uri fileEndpoint = null;
35-
Uri blobEndpoint = null;
36-
Uri queueEndpoint = null;
37-
Uri tableEndpoint = null;
45+
if (!TestMockSupport.RunningMocked)
46+
{
47+
var storageServiceResponse = storageClient.StorageAccounts.GetProperties(resourceGroupName, accountName);
48+
Uri blobEndpoint = storageServiceResponse.StorageAccount.PrimaryEndpoints.Blob;
49+
Uri queueEndpoint = storageServiceResponse.StorageAccount.PrimaryEndpoints.Queue;
50+
Uri tableEndpoint = storageServiceResponse.StorageAccount.PrimaryEndpoints.Table;
51+
return new CloudStorageAccount(
52+
GenerateStorageCredentials(storageClient, resourceGroupName, accountName),
53+
blobEndpoint,
54+
queueEndpoint,
55+
tableEndpoint, null);
56+
}
57+
else
58+
{
59+
return new CloudStorageAccount(
60+
new StorageCredentials(accountName,
61+
Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()))),
62+
new Uri(string.Format("https://{0}.blob.core.windows.net", accountName)),
63+
new Uri(string.Format("https://{0}.queue.core.windows.net", accountName)),
64+
new Uri(string.Format("https://{0}.table.core.windows.net", accountName)),
65+
null);
66+
}
67+
}
3868

39-
if (storageServiceResponse.StorageAccount.Properties.Endpoints.Count >= 4)
69+
/// <summary>
70+
/// Create a cloud storage account using a service management storage client
71+
/// </summary>
72+
/// <param name="storageClient">The client to use to get storage account details.</param>
73+
/// <param name="accountName">The name of the storage account.</param>
74+
/// <returns>A CloudStorageAccount that can be used by windows azure storage library to manipulate objects in the storage account.</returns>
75+
public static CloudStorageAccount GenerateCloudStorageAccount(IStorageManagementClient storageClient, string accountName)
76+
{
77+
if (!TestMockSupport.RunningMocked)
4078
{
41-
fileEndpoint = StorageUtilities.CreateHttpsEndpoint(storageServiceResponse.StorageAccount.Properties.Endpoints[3].ToString());
79+
var storageServiceResponse = storageClient.StorageAccounts.Get(accountName);
80+
81+
Uri fileEndpoint = null;
82+
Uri blobEndpoint = null;
83+
Uri queueEndpoint = null;
84+
Uri tableEndpoint = null;
85+
86+
if (storageServiceResponse.StorageAccount.Properties.Endpoints.Count >= 4)
87+
{
88+
fileEndpoint =
89+
StorageUtilities.CreateHttpsEndpoint(
90+
storageServiceResponse.StorageAccount.Properties.Endpoints[3].ToString());
91+
}
92+
93+
if (storageServiceResponse.StorageAccount.Properties.Endpoints.Count >= 3)
94+
{
95+
tableEndpoint =
96+
StorageUtilities.CreateHttpsEndpoint(
97+
storageServiceResponse.StorageAccount.Properties.Endpoints[2].ToString());
98+
queueEndpoint =
99+
StorageUtilities.CreateHttpsEndpoint(
100+
storageServiceResponse.StorageAccount.Properties.Endpoints[1].ToString());
101+
}
102+
103+
if (storageServiceResponse.StorageAccount.Properties.Endpoints.Count >= 1)
104+
{
105+
blobEndpoint =
106+
StorageUtilities.CreateHttpsEndpoint(
107+
storageServiceResponse.StorageAccount.Properties.Endpoints[0].ToString());
108+
}
109+
110+
return new CloudStorageAccount(
111+
GenerateStorageCredentials(storageClient, storageServiceResponse.StorageAccount.Name),
112+
blobEndpoint,
113+
queueEndpoint,
114+
tableEndpoint,
115+
fileEndpoint);
42116
}
43-
44-
if (storageServiceResponse.StorageAccount.Properties.Endpoints.Count >= 3)
117+
else
45118
{
46-
tableEndpoint = StorageUtilities.CreateHttpsEndpoint(storageServiceResponse.StorageAccount.Properties.Endpoints[2].ToString());
47-
queueEndpoint = StorageUtilities.CreateHttpsEndpoint(storageServiceResponse.StorageAccount.Properties.Endpoints[1].ToString());
119+
return new CloudStorageAccount(
120+
new StorageCredentials(accountName,
121+
Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()))),
122+
new Uri(string.Format("https://{0}.blob.core.windows.net", accountName)),
123+
new Uri(string.Format("https://{0}.queue.core.windows.net", accountName)),
124+
new Uri(string.Format("https://{0}.table.core.windows.net", accountName)),
125+
new Uri(string.Format("https://{0}.file.core.windows.net", accountName)));
48126
}
127+
}
49128

50-
if (storageServiceResponse.StorageAccount.Properties.Endpoints.Count >= 1)
129+
/// <summary>
130+
/// Create storage credentials for the given account
131+
/// </summary>
132+
/// <param name="storageClient">The ARM storage management client.</param>
133+
/// <param name="resourceGroupName">The resource group containing the storage account.</param>
134+
/// <param name="accountName">The storage account name.</param>
135+
/// <returns>Storage credentials for the given account.</returns>
136+
public static StorageCredentials GenerateStorageCredentials(Arm.IStorageManagementClient storageClient,
137+
string resourceGroupName, string accountName)
138+
{
139+
if (!TestMockSupport.RunningMocked)
140+
{
141+
var storageKeysResponse = storageClient.StorageAccounts.ListKeys(resourceGroupName, accountName);
142+
return new StorageCredentials(accountName,
143+
storageKeysResponse.StorageAccountKeys.Key1);
144+
}
145+
else
51146
{
52-
blobEndpoint = StorageUtilities.CreateHttpsEndpoint(storageServiceResponse.StorageAccount.Properties.Endpoints[0].ToString());
147+
return new StorageCredentials(accountName,
148+
Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())));
53149
}
150+
}
54151

55-
return new CloudStorageAccount(
56-
new StorageCredentials(storageServiceResponse.StorageAccount.Name, storageKeysResponse.PrimaryKey),
57-
blobEndpoint,
58-
queueEndpoint,
59-
tableEndpoint,
60-
fileEndpoint);
152+
/// <summary>
153+
/// Create storage credentials for the given account
154+
/// </summary>
155+
/// <param name="storageClient">The RDFE storage management client.</param>
156+
/// <param name="accountName">The storage account name.</param>
157+
/// <returns>Storage credentials for the given account.</returns>
158+
public static StorageCredentials GenerateStorageCredentials(IStorageManagementClient storageClient,
159+
string accountName)
160+
{
161+
if (!TestMockSupport.RunningMocked)
162+
{
163+
var storageKeysResponse = storageClient.StorageAccounts.GetKeys(accountName);
164+
return new StorageCredentials(accountName,
165+
storageKeysResponse.PrimaryKey);
166+
}
167+
else
168+
{
169+
return new StorageCredentials(accountName,
170+
Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())));
171+
}
61172
}
62173

63174
public static string GenerateTableStorageSasUrl(string connectionString, string tableName, DateTime expiryTime, SharedAccessTablePermissions permissions)

0 commit comments

Comments
 (0)