Skip to content

Commit 69b488e

Browse files
authored
Template Specs: Adding tag assignment/viewing support (#13619)
1 parent b16bcfb commit 69b488e

21 files changed

+13408
-22
lines changed

src/Resources/ResourceManager/Implementation/TemplateSpecs/NewAzTemplateSpec.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using Microsoft.WindowsAzure.Commands.Utilities.Common;
2222
using Newtonsoft.Json.Linq;
2323
using System;
24+
using System.Collections;
2425
using System.IO;
2526
using System.Management.Automation;
2627

@@ -98,6 +99,13 @@ public class NewAzTemplateSpec : TemplateSpecCmdletBase
9899
[LocationCompleter("Microsoft.Resources/templateSpecs")]
99100
public string Location { get; set; }
100101

102+
[Alias("Tags")]
103+
[Parameter(
104+
Mandatory = false,
105+
HelpMessage = "Hashtable of tags for the new template spec resource(s).")]
106+
[ValidateNotNull]
107+
public Hashtable Tag { get; set; }
108+
101109
[Parameter(
102110
ParameterSetName = FromJsonStringParameterSet,
103111
Mandatory = true,
@@ -204,7 +212,9 @@ public override void ExecuteCmdlet()
204212
packagedTemplate,
205213
templateSpecDescription: Description,
206214
templateSpecDisplayName: DisplayName,
207-
versionDescription: VersionDescription
215+
versionDescription: VersionDescription,
216+
templateSpecTags:Tag, // Note: Only applied if template spec doesn't exist
217+
versionTags: Tag
208218
);
209219

210220
WriteObject(templateSpecVersion);

src/Resources/ResourceManager/Implementation/TemplateSpecs/SetAzTemplateSpec.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using Microsoft.WindowsAzure.Commands.Utilities.Common;
2121
using Newtonsoft.Json.Linq;
2222
using System;
23+
using System.Collections;
2324
using System.IO;
2425
using System.Management.Automation;
2526

@@ -120,6 +121,13 @@ public class SetAzTemplateSpec : TemplateSpecCmdletBase
120121
[LocationCompleter("Microsoft.Resources/templateSpecs")]
121122
public string Location { get; set; }
122123

124+
[Alias("Tags")]
125+
[Parameter(
126+
Mandatory = false,
127+
HelpMessage = "Hashtable of tags for the template spec and/or version")]
128+
[ValidateNotNull]
129+
public Hashtable Tag { get; set; }
130+
123131
[Parameter(Mandatory = true, ParameterSetName = UpdateVersionByNameFromJsonParameterSet, ValueFromPipelineByPropertyName = true,
124132
HelpMessage = "The Azure Resource Manager template JSON.")]
125133
[Parameter(Mandatory = true, ParameterSetName = UpdateVersionByIdFromJsonParameterSet, ValueFromPipelineByPropertyName = true,
@@ -245,7 +253,9 @@ public override void ExecuteCmdlet()
245253
packagedTemplate,
246254
templateSpecDescription: Description,
247255
templateSpecDisplayName: DisplayName,
248-
versionDescription: VersionDescription
256+
versionDescription: VersionDescription,
257+
templateSpecTags: Tag, // Note: Only applied if template spec doesn't exist
258+
versionTags: Tag
249259
);
250260

251261
WriteObject(templateSpecVersion);
@@ -264,7 +274,8 @@ public override void ExecuteCmdlet()
264274
Name,
265275
Location,
266276
templateSpecDescription: Description,
267-
templateSpecDisplayName: DisplayName
277+
templateSpecDisplayName: DisplayName,
278+
tags: Tag
268279
);
269280

270281
// As the root template spec is a seperate resource type, it won't contain version

src/Resources/ResourceManager/SdkClient/TemplateSpecsSdkClient.cs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
1717
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.Components;
1818
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels;
19+
using Microsoft.Azure.Commands.ResourceManager.Common.Tags;
1920
using Microsoft.Azure.Management.ResourceManager;
2021
using Microsoft.Azure.Management.ResourceManager.Models;
2122
using System;
23+
using System.Collections;
2224
using System.Collections.Generic;
2325
using System.Linq;
2426
using System.Management.Automation;
@@ -181,14 +183,18 @@ public PSTemplateSpec CreateOrUpdateTemplateSpecVersion(
181183
PackagedTemplate packagedTemplate,
182184
string templateSpecDisplayName = null,
183185
string templateSpecDescription = null,
184-
string versionDescription = null)
186+
string versionDescription = null,
187+
Hashtable templateSpecTags = null,
188+
Hashtable versionTags = null)
185189
{
186190
var templateSpecModel = this.CreateOrUpdateTemplateSpecInternal(
187191
resourceGroupName,
188192
templateSpecName,
189193
location,
190194
templateSpecDisplayName,
191-
templateSpecDescription
195+
templateSpecDescription,
196+
tags: templateSpecTags,
197+
onlyApplyTagsOnCreate: true // Don't update tags if the template spec already exists
192198
);
193199

194200
var existingTemplateSpecVersion = this.GetAzureSdkTemplateSpecVersion(
@@ -206,6 +212,31 @@ public PSTemplateSpec CreateOrUpdateTemplateSpecVersion(
206212
Description = versionDescription ?? existingTemplateSpecVersion?.Description
207213
};
208214

215+
// Handle our conditional tagging:
216+
// ------------------------------------------
217+
218+
if (versionTags != null)
219+
{
220+
// Explicit version tags provided. Use them:
221+
templateSpecVersionModel.Tags =
222+
TagsConversionHelper.CreateTagDictionary(versionTags, true);
223+
}
224+
else if (existingTemplateSpecVersion != null)
225+
{
226+
// No tags were provided. The template spec version already exists
227+
// ... keep the existing version's tags:
228+
templateSpecVersionModel.Tags = existingTemplateSpecVersion.Tags;
229+
}
230+
else
231+
{
232+
// No tags were provided. The template spec version does not already exist
233+
// ... inherit the tags present on the underlying template spec:
234+
templateSpecVersionModel.Tags = templateSpecModel.Tags;
235+
}
236+
237+
// Perform the actual version create/update:
238+
// ------------------------------------------
239+
209240
templateSpecVersionModel = TemplateSpecsClient.TemplateSpecVersions.CreateOrUpdate(
210241
resourceGroupName,
211242
templateSpecName,
@@ -221,14 +252,17 @@ public PSTemplateSpec CreateOrUpdateTemplateSpec(
221252
string templateSpecName,
222253
string location,
223254
string templateSpecDisplayName = null,
224-
string templateSpecDescription = null)
255+
string templateSpecDescription = null,
256+
Hashtable tags = null)
225257
{
226258
var sdkTemplateSpecModel = this.CreateOrUpdateTemplateSpecInternal(
227259
resourceGroupName,
228260
templateSpecName,
229261
location,
230262
templateSpecDisplayName,
231-
templateSpecDescription
263+
templateSpecDescription,
264+
tags,
265+
onlyApplyTagsOnCreate: false // Apply tags on updates too
232266
);
233267

234268
return new PSTemplateSpec(sdkTemplateSpecModel);
@@ -285,7 +319,9 @@ protected TemplateSpec CreateOrUpdateTemplateSpecInternal(
285319
string templateSpecName,
286320
string location,
287321
string templateSpecDisplayName = null,
288-
string templateSpecDescription = null)
322+
string templateSpecDescription = null,
323+
Hashtable tags = null,
324+
bool onlyApplyTagsOnCreate = false)
289325
{
290326
var existingTemplateSpec = this.GetAzureSdkTemplateSpec(
291327
resourceGroupName,
@@ -314,6 +350,11 @@ protected TemplateSpec CreateOrUpdateTemplateSpecInternal(
314350
Tags = existingTemplateSpec?.Tags
315351
};
316352

353+
if ((tags != null) && (existingTemplateSpec == null || !onlyApplyTagsOnCreate))
354+
{
355+
templateSpecModel.Tags = TagsConversionHelper.CreateTagDictionary(tags, true);
356+
}
357+
317358
templateSpecModel = TemplateSpecsClient.TemplateSpecs.CreateOrUpdate(
318359
resourceGroupName,
319360
templateSpecName,

src/Resources/ResourceManager/SdkModels/TemplateSpecs/PSTemplateSpec.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ internal PSTemplateSpec(TemplateSpec templateSpec,
8181
this.LastModifiedTime = templateSpec.SystemData.LastModifiedAt;
8282
this.Description = templateSpec.Description;
8383
this.DisplayName = templateSpec.DisplayName;
84-
this.Tags = templateSpec.Tags;
84+
this.Tags = templateSpec.Tags == null
85+
? new Dictionary<string, string>()
86+
: new Dictionary<string, string>(templateSpec.Tags);
8587

8688
this.Versions = versionModels?
8789
.Select(v => PSTemplateSpecVersion.FromAzureSDKTemplateSpecVersion(v))

src/Resources/ResourceManager/SdkModels/TemplateSpecs/PSTemplateSpecVersion.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ internal static PSTemplateSpecVersion FromAzureSDKTemplateSpecVersion(
8888
LastModifiedTime = templateSpecVersion.SystemData.LastModifiedAt,
8989
Name = templateSpecVersion.Name,
9090
Description = templateSpecVersion.Description,
91-
Tags = templateSpecVersion.Tags,
91+
Tags = templateSpecVersion.Tags == null
92+
? new Dictionary<string, string>()
93+
: new Dictionary<string, string>(templateSpecVersion.Tags),
9294
// Note: Cast is redundant, but present for clarity reasons:
9395
Template = ((JToken)templateSpecVersion.Template).ToString()
9496
};

src/Resources/Resources.Test/ScenarioTests/TemplateSpecTests.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,69 @@ public void TestTemplateSpecRemoval()
5151
{
5252
TestRunner.RunTestScript("Test-RemoveTemplateSpec");
5353
}
54+
55+
[Fact()]
56+
[Trait(Category.AcceptanceType, Category.CheckIn)]
57+
public void NewTemplateSpec_Tags_AppliesTagsToBothTemplateSpecAndVersionIfNotExist()
58+
{
59+
TestRunner.RunTestScript("Test-NewAppliesTagsToBothTemplateSpecAndVersionIfNotExist");
60+
}
61+
62+
[Fact()]
63+
[Trait(Category.AcceptanceType, Category.CheckIn)]
64+
public void NewTemplateSpec_Tags_AppliesTagsToOnlyVersionIfTemplateSpecExists()
65+
{
66+
TestRunner.RunTestScript("Test-NewAppliesTagsToOnlyVersionIfTemplateSpecExists");
67+
}
68+
69+
[Fact()]
70+
[Trait(Category.AcceptanceType, Category.CheckIn)]
71+
public void NewTemplateSpec_Tags_AppliesInheritedTagsIfNoTagsSuppliedAndSpecExists()
72+
{
73+
TestRunner.RunTestScript("Test-NewAppliesInheritedTagsIfNoTagsSuppliedAndSpecExists");
74+
}
75+
76+
[Fact()]
77+
[Trait(Category.AcceptanceType, Category.CheckIn)]
78+
public void NewTemplateSpec_Tags_RemovesTagsFromExistingVersionIfTagsExplicityEmpty()
79+
{
80+
TestRunner.RunTestScript("Test-NewRemovesTagsFromExistingVersionIfTagsExplicitlyEmpty");
81+
}
82+
83+
[Fact()]
84+
[Trait(Category.AcceptanceType, Category.CheckIn)]
85+
public void SetTemplateSpec_Tags_AppliesTagsToBothTemplateSpecAndVersionIfNotExist()
86+
{
87+
TestRunner.RunTestScript("Test-SetAppliesTagsToBothTemplateSpecAndVersionIfNotExist");
88+
}
89+
90+
[Fact()]
91+
[Trait(Category.AcceptanceType, Category.CheckIn)]
92+
public void SetTemplateSpec_Tags_AppliesTagsOnlyToVersionIfVersionSpecified()
93+
{
94+
TestRunner.RunTestScript("Test-SetAppliesTagsOnlyToVersionIfVersionSpecified");
95+
}
96+
97+
[Fact()]
98+
[Trait(Category.AcceptanceType, Category.CheckIn)]
99+
public void SetTemplateSpec_Tags_AppliesTagsToTemplateSpecIfNoVersionSpecified()
100+
{
101+
TestRunner.RunTestScript("Test-SetAppliesTagsToTemplateSpecIfNoVersionSpecified");
102+
}
103+
104+
[Fact()]
105+
[Trait(Category.AcceptanceType, Category.CheckIn)]
106+
public void SetTemplateSpec_Tags_AppliesInheritedTagsIfNewVersionAndNoTagsProvidedAndSpecExists()
107+
{
108+
TestRunner.RunTestScript("Test-SetAppliesInheritedTagsIfNewVersionAndNoTagsProvidedAndSpecExists");
109+
}
110+
111+
[Fact()]
112+
[Trait(Category.AcceptanceType, Category.CheckIn)]
113+
public void SetTemplateSpec_Tags_RemovesTagsIfTagsExplicitlyEmpty()
114+
{
115+
TestRunner.RunTestScript("Test-SetRemovesTagsIfTagsExplicitlyEmpty");
116+
}
117+
54118
}
55119
}

0 commit comments

Comments
 (0)