Skip to content

Commit 0f36c10

Browse files
committed
Add Save-AzureRmResourceGroupDeploymentTemplate cmdlet and test
1 parent 8abf31d commit 0f36c10

File tree

13 files changed

+1605
-3
lines changed

13 files changed

+1605
-3
lines changed

src/ResourceManager/Resources/Commands.ResourceManager/Cmdlets/Commands.Resources.Rest.csproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
<Compile Include="Handlers\CmdletInfoHandler.cs" />
137137
<Compile Include="Handlers\UserAgentHandler.cs" />
138138
<Compile Include="Implementation\FindAzureResourceGroupCmdlet.cs" />
139+
<Compile Include="Implementation\SaveAzureResourceGroupDeploymentTemplateCmdlet.cs" />
139140
<Compile Include="Implementation\GetAzureResourceGroupDeploymentOperationCmdlet.cs" />
140141
<Compile Include="Implementation\Lock\GetAzureResourceLockCmdlet.cs" />
141142
<Compile Include="Implementation\InvokeAzureResourceActionCmdlet.cs" />
@@ -170,8 +171,14 @@
170171
<Compile Include="Json\TimeSpanConverter.cs" />
171172
<Compile Include="Properties\AssemblyInfo.cs" />
172173
<Compile Include="Implementation\Resource\GetAzureResourceCmdlet.cs" />
174+
<Compile Include="Properties\Resources.Designer.cs">
175+
<DependentUpon>Resources.resx</DependentUpon>
176+
<AutoGen>True</AutoGen>
177+
<DesignTime>True</DesignTime>
178+
</Compile>
173179
<Compile Include="RestClients\ResourceManagerRestClientBase.cs" />
174180
<Compile Include="RestClients\ResourceManagerRestRestClient.cs" />
181+
<Compile Include="Utilities\FileUtility.cs" />
175182
<Compile Include="Utilities\HttpUtility.cs" />
176183
</ItemGroup>
177184
<ItemGroup>
@@ -207,5 +214,12 @@
207214
<Name>Commands.Tags</Name>
208215
</ProjectReference>
209216
</ItemGroup>
217+
<ItemGroup>
218+
<EmbeddedResource Include="Properties\Resources.resx">
219+
<Generator>ResXFileCodeGenerator</Generator>
220+
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
221+
<SubType>Designer</SubType>
222+
</EmbeddedResource>
223+
</ItemGroup>
210224
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
211225
</Project>

src/ResourceManager/Resources/Commands.ResourceManager/Cmdlets/Components/Constants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ public static class Constants
5959
/// </summary>
6060
public static readonly string MoveResources = "moveResources";
6161

62+
/// <summary>
63+
/// The export action.
64+
/// </summary>
65+
public static readonly string ExportTemplate = "exportTemplate";
66+
6267
/// <summary>
6368
/// The locks resource type.
6469
/// </summary>

src/ResourceManager/Resources/Commands.ResourceManager/Cmdlets/Implementation/GetAzureResourceGroupDeploymentOperationCmdlet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation
2929
public class GetAzureResourceGroupDeploymentOperationCmdlet : ResourceManagerCmdletBase
3030
{
3131
/// <summary>
32-
/// Gets or sets the resource group name parameter.
32+
/// Gets or sets the deployment name parameter.
3333
/// </summary>
3434
[Alias("Name")]
3535
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The deployment name.")]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
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+
namespace Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation
16+
{
17+
using System.Management.Automation;
18+
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.Components;
19+
using Microsoft.WindowsAzure.Commands.Utilities.Common;
20+
using Newtonsoft.Json.Linq;
21+
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.Utilities;
22+
23+
/// <summary>
24+
/// Saves the deployment template to a file on disk.
25+
/// </summary>
26+
[Cmdlet(VerbsData.Save, "AzureRmResourceGroupDeploymentTemplate"), OutputType(typeof(PSObject))]
27+
public class GetAzureResourceGroupDeploymentTemplateCmdlet : ResourceManagerCmdletBase
28+
{
29+
/// <summary>
30+
/// Gets or sets the resource group name parameter.
31+
/// </summary>
32+
[Alias("ResourceGroup")]
33+
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The resource group name.")]
34+
[ValidateNotNullOrEmpty]
35+
public string ResourceGroupName { get; set; }
36+
37+
/// <summary>
38+
/// Gets or sets the deployment name parameter.
39+
/// </summary>
40+
[Alias("Name")]
41+
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The deployment name.")]
42+
[ValidateNotNullOrEmpty]
43+
public string DeploymentName { get; set; }
44+
45+
/// <summary>
46+
/// Gets or sets the file path.
47+
/// </summary>
48+
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "The output path of the template file.")]
49+
[ValidateNotNullOrEmpty]
50+
public string Path { get; set; }
51+
52+
/// <summary>
53+
/// Gets or sets the force parameter.
54+
/// </summary>
55+
[Parameter(Mandatory = false, HelpMessage = "Do not ask for confirmation.")]
56+
public SwitchParameter Force { get; set; }
57+
58+
/// <summary>
59+
/// Executes the cmdlet.
60+
/// </summary>
61+
protected override void OnProcessRecord()
62+
{
63+
base.OnProcessRecord();
64+
65+
var resourceId = this.GetResourceId();
66+
67+
var apiVersion = this.DetermineApiVersion(resourceId: resourceId).Result;
68+
69+
var operationResult = this.GetResourcesClient()
70+
.InvokeActionOnResource<JObject>(
71+
resourceId: resourceId,
72+
action: Constants.ExportTemplate,
73+
apiVersion: apiVersion,
74+
cancellationToken: this.CancellationToken.Value)
75+
.Result;
76+
77+
var managementUri = this.GetResourcesClient()
78+
.GetResourceManagementRequestUri(
79+
resourceId: resourceId,
80+
apiVersion: apiVersion,
81+
action: Constants.ExportTemplate);
82+
83+
var activity = string.Format("POST {0}", managementUri.PathAndQuery);
84+
var resultString = this.GetLongRunningOperationTracker(activityName: activity, isResourceCreateOrUpdate: false)
85+
.WaitOnOperation(operationResult: operationResult);
86+
87+
var template = JToken.FromObject(JObject.Parse(resultString)["template"]);
88+
89+
string path = FileUtility.SaveTemplateFile(
90+
deploymentName: this.DeploymentName,
91+
contents: template.ToString(),
92+
outputPath: string.IsNullOrEmpty(this.Path) ? System.IO.Path.Combine(CurrentPath(), this.DeploymentName) : this.TryResolvePath(this.Path),
93+
overwrite: this.Force,
94+
confirmAction: ConfirmAction);
95+
96+
WriteObject(PowerShellUtilities.ConstructPSObject(null, "Path", path));
97+
}
98+
99+
/// <summary>
100+
/// Gets the resource Id from the supplied PowerShell parameters.
101+
/// </summary>
102+
protected string GetResourceId()
103+
{
104+
return ResourceIdUtility.GetResourceId(
105+
subscriptionId: DefaultContext.Subscription.Id,
106+
resourceGroupName: this.ResourceGroupName,
107+
resourceType: Constants.MicrosoftResourcesDeploymentType,
108+
resourceName: this.DeploymentName);
109+
}
110+
}
111+
}

src/ResourceManager/Resources/Commands.ResourceManager/Cmdlets/Properties/Resources.Designer.cs

Lines changed: 81 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<root>
3+
<!--
4+
Microsoft ResX Schema
5+
6+
Version 2.0
7+
8+
The primary goals of this format is to allow a simple XML format
9+
that is mostly human readable. The generation and parsing of the
10+
various data types are done through the TypeConverter classes
11+
associated with the data types.
12+
13+
Example:
14+
15+
... ado.net/XML headers & schema ...
16+
<resheader name="resmimetype">text/microsoft-resx</resheader>
17+
<resheader name="version">2.0</resheader>
18+
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
19+
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
20+
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
21+
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
22+
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
23+
<value>[base64 mime encoded serialized .NET Framework object]</value>
24+
</data>
25+
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
26+
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
27+
<comment>This is a comment</comment>
28+
</data>
29+
30+
There are any number of "resheader" rows that contain simple
31+
name/value pairs.
32+
33+
Each data row contains a name, and value. The row also contains a
34+
type or mimetype. Type corresponds to a .NET class that support
35+
text/value conversion through the TypeConverter architecture.
36+
Classes that don't support this are serialized and stored with the
37+
mimetype set.
38+
39+
The mimetype is used for serialized objects, and tells the
40+
ResXResourceReader how to depersist the object. This is currently not
41+
extensible. For a given mimetype the value must be set accordingly:
42+
43+
Note - application/x-microsoft.net.object.binary.base64 is the format
44+
that the ResXResourceWriter will generate, however the reader can
45+
read any of the formats listed below.
46+
47+
mimetype: application/x-microsoft.net.object.binary.base64
48+
value : The object must be serialized with
49+
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
50+
: and then encoded with base64 encoding.
51+
52+
mimetype: application/x-microsoft.net.object.soap.base64
53+
value : The object must be serialized with
54+
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
55+
: and then encoded with base64 encoding.
56+
57+
mimetype: application/x-microsoft.net.object.bytearray.base64
58+
value : The object must be serialized into a byte array
59+
: using a System.ComponentModel.TypeConverter
60+
: and then encoded with base64 encoding.
61+
-->
62+
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
63+
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
64+
<xsd:element name="root" msdata:IsDataSet="true">
65+
<xsd:complexType>
66+
<xsd:choice maxOccurs="unbounded">
67+
<xsd:element name="metadata">
68+
<xsd:complexType>
69+
<xsd:sequence>
70+
<xsd:element name="value" type="xsd:string" minOccurs="0" />
71+
</xsd:sequence>
72+
<xsd:attribute name="name" use="required" type="xsd:string" />
73+
<xsd:attribute name="type" type="xsd:string" />
74+
<xsd:attribute name="mimetype" type="xsd:string" />
75+
<xsd:attribute ref="xml:space" />
76+
</xsd:complexType>
77+
</xsd:element>
78+
<xsd:element name="assembly">
79+
<xsd:complexType>
80+
<xsd:attribute name="alias" type="xsd:string" />
81+
<xsd:attribute name="name" type="xsd:string" />
82+
</xsd:complexType>
83+
</xsd:element>
84+
<xsd:element name="data">
85+
<xsd:complexType>
86+
<xsd:sequence>
87+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
88+
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
89+
</xsd:sequence>
90+
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
91+
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
92+
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
93+
<xsd:attribute ref="xml:space" />
94+
</xsd:complexType>
95+
</xsd:element>
96+
<xsd:element name="resheader">
97+
<xsd:complexType>
98+
<xsd:sequence>
99+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
100+
</xsd:sequence>
101+
<xsd:attribute name="name" type="xsd:string" use="required" />
102+
</xsd:complexType>
103+
</xsd:element>
104+
</xsd:choice>
105+
</xsd:complexType>
106+
</xsd:element>
107+
</xsd:schema>
108+
<resheader name="resmimetype">
109+
<value>text/microsoft-resx</value>
110+
</resheader>
111+
<resheader name="version">
112+
<value>2.0</value>
113+
</resheader>
114+
<resheader name="reader">
115+
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116+
</resheader>
117+
<resheader name="writer">
118+
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119+
</resheader>
120+
<data name="FileAlreadyExists" xml:space="preserve">
121+
<value>The provided file path '{0}' already exists, do you want to override it?</value>
122+
</data>
123+
<data name="OverrdingFile" xml:space="preserve">
124+
<value>Overriding the existing file.</value>
125+
</data>
126+
</root>

0 commit comments

Comments
 (0)