Skip to content

Commit 22e1d97

Browse files
Vasundhara Jagdaleshahabhijeet
authored andcommitted
Added -JsonAttributes and -ChefServiceInterval option (Azure#3083)
* Added -JsonAttributes option to set custom json attributes in first-boot.json Signed-off-by: Vasu1105 <[email protected]> * Fixed multiple condition for SetAzureVMChefExtension command in Resource Management, Updated -JsonAttribute description with example, Added new -ChefServiceInterval option Signed-off-by: Vasu1105 <[email protected]> * Refactored code for Chef extension Set-AzureVMChefExtension Service management command to reduce multiple conditions Signed-off-by: Vasu1105 <[email protected]> * Fixed review comments Signed-off-by: Vasu1105 <[email protected]> * Added automated test for Set-AzureVMChefExtension Signed-off-by: Vasu1105 <[email protected]> * Regenerated record for automated test Signed-off-by: Vasu1105 <[email protected]> * Added code to get current directory Signed-off-by: Vasu1105 <[email protected]> * Added global exception for crdential files Signed-off-by: Vasu1105 <[email protected]> * Updated changelog.md Signed-off-by: Vasu1105 <[email protected]>
1 parent 5cb4d2a commit 22e1d97

File tree

14 files changed

+2106
-80
lines changed

14 files changed

+2106
-80
lines changed

src/ResourceManager/Compute/ChangeLog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
-->
2020
## Current Release
2121

22+
* Updated Set-AzureRmVMChefExtension cmdlet to add following new options :
23+
- JsonAttribute : A JSON string to be added to the first run of chef-client. e.g. -JsonAttribute '{"container_service": {"chef-init-test": {"command": "C:\\opscode\\chef\\bin"}}}'
24+
25+
- ChefServiceInterval : Specifies the frequency (in minutes) at which the chef-service runs. If in case you don't want the chef-service to be installed on the Azure VM then set value as 0 in this field. e.g. -ChefServiceInterval 45
26+
2227
## Version 2.3.0
2328
* Update formats for list of VMs, VMScaleSets and ContainerService
2429
- The default format of Get-AzureRmVM, Get-AzureRmVmss and Get-AzureRmContainerService is not table format when these cmdlets call List Operation

src/ResourceManager/Compute/Commands.Compute/Extension/Chef/SetAzureVMChefExtension.cs

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public class SetAzureVMChefExtensionCommand : VirtualMachineExtensionBaseCmdlet
4545
private string BootstrapVersionTemplate = "bootstrap_version";
4646
private string ClientRbTemplate = "client_rb";
4747
private string BootStrapOptionsTemplate = "bootstrap_options";
48+
private string JsonAttributeTemplate = "custom_json_attr";
49+
private string ChefServiceIntervalTemplate = "chef_service_interval";
4850
private string RunListTemplate = "runlist";
4951

5052
[Parameter(
@@ -100,6 +102,18 @@ public string TypeHandlerVersion
100102
[ValidateNotNullOrEmpty]
101103
public string BootstrapOptions { get; set; }
102104

105+
[Parameter(
106+
ValueFromPipelineByPropertyName = true,
107+
HelpMessage = "A JSON string to be added to the first run of chef-client. e.g. -JsonAttribute '{\"foo\" : \"bar\"}'")]
108+
[ValidateNotNullOrEmpty]
109+
public string JsonAttribute { get; set; }
110+
111+
[Parameter(
112+
ValueFromPipelineByPropertyName = true,
113+
HelpMessage = "Specifies the frequency (in minutes) at which the chef-service runs. If in case you don't want the chef-service to be installed on the Azure VM then set value as 0 in this field.")]
114+
[ValidateNotNullOrEmpty]
115+
public string ChefServiceInterval { get; set; }
116+
103117
[Parameter(
104118
ValueFromPipelineByPropertyName = true,
105119
HelpMessage = "The Chef Server Node Runlist.")]
@@ -211,6 +225,8 @@ private Hashtable PublicConfiguration
211225
bool IsValidationClientNameEmpty = string.IsNullOrEmpty(this.ValidationClientName);
212226
bool IsRunListEmpty = string.IsNullOrEmpty(this.RunList);
213227
bool IsBootstrapOptionsEmpty = string.IsNullOrEmpty(this.BootstrapOptions);
228+
bool IsJsonAttributeEmpty = string.IsNullOrEmpty(this.JsonAttribute);
229+
bool IsChefServiceIntervalEmpty = string.IsNullOrEmpty(this.ChefServiceInterval);
214230
string BootstrapVersion = string.IsNullOrEmpty(this.BootstrapVersion) ? "" : this.BootstrapVersion;
215231

216232
//Cases handled:
@@ -259,44 +275,32 @@ private Hashtable PublicConfiguration
259275
";
260276
ClientConfig = string.Format(UserConfig, this.ChefServerUrl, this.ValidationClientName);
261277
}
262-
if (IsRunListEmpty)
278+
279+
var hashTable = new Hashtable();
280+
hashTable.Add(BootstrapVersionTemplate, BootstrapVersion);
281+
hashTable.Add(ClientRbTemplate, ClientConfig);
282+
283+
if (!IsRunListEmpty)
263284
{
264-
if (IsBootstrapOptionsEmpty)
265-
{
266-
var hashTable = new Hashtable();
267-
hashTable.Add(BootstrapVersionTemplate, BootstrapVersion);
268-
hashTable.Add(ClientRbTemplate, ClientConfig);
269-
this.publicConfiguration = hashTable;
270-
}
271-
else
272-
{
273-
var hashTable = new Hashtable();
274-
hashTable.Add(BootstrapVersionTemplate, BootstrapVersion);
275-
hashTable.Add(ClientRbTemplate, ClientConfig);
276-
hashTable.Add(BootStrapOptionsTemplate, this.BootstrapOptions);
277-
this.publicConfiguration = hashTable;
278-
}
285+
hashTable.Add(RunListTemplate, this.RunList);
279286
}
280-
else
287+
288+
if (!IsBootstrapOptionsEmpty)
281289
{
282-
if (IsBootstrapOptionsEmpty)
283-
{
284-
var hashTable = new Hashtable();
285-
hashTable.Add(BootstrapVersionTemplate, BootstrapVersion);
286-
hashTable.Add(ClientRbTemplate, ClientConfig);
287-
hashTable.Add(RunListTemplate, this.RunList);
288-
this.publicConfiguration = hashTable;
289-
}
290-
else
291-
{
292-
var hashTable = new Hashtable();
293-
hashTable.Add(BootstrapVersionTemplate, BootstrapVersion);
294-
hashTable.Add(ClientRbTemplate, ClientConfig);
295-
hashTable.Add(RunListTemplate, this.RunList);
296-
hashTable.Add(BootStrapOptionsTemplate, this.BootstrapOptions);
297-
this.publicConfiguration = hashTable;
298-
}
290+
hashTable.Add(BootStrapOptionsTemplate, this.BootstrapOptions);
299291
}
292+
293+
if (!IsJsonAttributeEmpty)
294+
{
295+
hashTable.Add(JsonAttributeTemplate, JsonAttribute);
296+
}
297+
298+
if (!IsChefServiceIntervalEmpty)
299+
{
300+
hashTable.Add(ChefServiceIntervalTemplate, ChefServiceInterval);
301+
}
302+
303+
this.publicConfiguration = hashTable;
300304
}
301305

302306
return this.publicConfiguration;

src/ResourceManager/Compute/Commands.Compute/Microsoft.Azure.Commands.Compute.dll-Help.xml

Lines changed: 56 additions & 2 deletions
Large diffs are not rendered by default.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Linq;
4+
using Microsoft.Azure.Test;
5+
using Microsoft.WindowsAzure.ServiceManagemenet;
6+
using Microsoft.WindowsAzure.Management;
7+
using Microsoft.WindowsAzure.Management.Compute;
8+
using Microsoft.WindowsAzure.Management.Network;
9+
using Microsoft.WindowsAzure.Management.Storage;
10+
using Microsoft.WindowsAzure.Commands.Utilities.Common;
11+
using Xunit;
12+
using Microsoft.Azure.Commands.Common.Authentication;
13+
using Xunit.Abstractions;
14+
using Microsoft.WindowsAzure.ServiceManagemenet.Common.Models;
15+
16+
17+
namespace Microsoft.WindowsAzure.Commands.ScenarioTest
18+
{
19+
public class ChefExtensionTests
20+
{
21+
private EnvironmentSetupHelper helper = new EnvironmentSetupHelper();
22+
23+
public ChefExtensionTests(ITestOutputHelper output)
24+
{
25+
XunitTracingInterceptor.AddToContext(new XunitTracingInterceptor(output));
26+
}
27+
28+
[Fact]
29+
[Trait(Category.AcceptanceType, Category.CheckIn)]
30+
[Trait(Category.AcceptanceType, Category.BVT)]
31+
public void TestSetAzureVMChefExtension()
32+
{
33+
this.RunPowerShellTest("Test-SetAzureVMChefExtension");
34+
}
35+
36+
protected void SetupManagementClients()
37+
{
38+
var rdfeTestFactory = new RDFETestEnvironmentFactory();
39+
var managementClient = TestBase.GetServiceClient<ManagementClient>(rdfeTestFactory);
40+
var computeClient = TestBase.GetServiceClient<ComputeManagementClient>(rdfeTestFactory);
41+
var networkClient = TestBase.GetServiceClient<NetworkManagementClient>(rdfeTestFactory);
42+
var storageClient = TestBase.GetServiceClient<StorageManagementClient>(rdfeTestFactory);
43+
44+
helper.SetupSomeOfManagementClients(
45+
managementClient,
46+
computeClient,
47+
networkClient,
48+
storageClient);
49+
}
50+
51+
protected void RunPowerShellTest(params string[] scripts)
52+
{
53+
using (UndoContext context = UndoContext.Current)
54+
{
55+
context.Start(TestUtilities.GetCallingClass(1), TestUtilities.GetCurrentMethodName(2));
56+
57+
SetupManagementClients();
58+
59+
var modules = new List<string>
60+
{
61+
"Resources\\ChefExtension\\ChefExtensionTests.ps1",
62+
"Resources\\ServiceManagement\\Common.ps1",
63+
@"..\..\..\..\..\Package\Debug\ServiceManagement\Azure\Compute\AzurePreview.psd1",
64+
@"..\..\..\..\..\Package\Debug\ServiceManagement\Azure\Compute\PIR.psd1"
65+
};
66+
67+
helper.SetupEnvironment(AzureModule.AzureServiceManagement);
68+
helper.SetupModules(AzureModule.AzureServiceManagement, modules.ToArray());
69+
70+
71+
var scriptEnvPath = new List<string>();
72+
scriptEnvPath.Add(
73+
string.Format(
74+
"$env:PSModulePath=\"{0};$env:PSModulePath\"",
75+
@"..\..\..\..\..\Package\Debug\ServiceManagement\Azure\Compute".AsAbsoluteLocation()));
76+
77+
helper.RunPowerShellTest(scriptEnvPath, scripts);
78+
}
79+
}
80+
}
81+
}

src/ServiceManagement/Common/Commands.ScenarioTest/Commands.ScenarioTest.csproj

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,15 @@
211211
<None Include="Resources\CredentialTests\Common.ps1">
212212
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
213213
</None>
214+
<None Include="Resources\ChefExtension\ChefExtensionTests.ps1">
215+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
216+
</None>
217+
<None Include="Resources\ChefExtension\client.rb">
218+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
219+
</None>
220+
<None Include="Resources\ChefExtension\tstorgnztn-validator.pem">
221+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
222+
</None>
214223
<None Include="Resources\DiagnosticsExtension\DiagnosticsExtensionTests.ps1">
215224
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
216225
</None>
@@ -268,6 +277,9 @@
268277
<None Include="SessionRecords\Microsoft.WindowsAzure.Commands.ScenarioTest.DiagnosticsExtensionTests\TestAzureServiceDiagnosticsExtensionWrongServiceName.json">
269278
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
270279
</None>
280+
<None Include="SessionRecords\Microsoft.WindowsAzure.Commands.ScenarioTest.ChefExtensionTests\TestSetAzureVMChefExtension.json">
281+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
282+
</None>
271283
<None Include="SessionRecords\Microsoft.WindowsAzure.Commands.ScenarioTest.DscExtensionTests\TestGetAzureVMDscExtension.json">
272284
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
273285
</None>
@@ -418,6 +430,7 @@
418430
<Compile Include="CredentialTests\AddAccountForArmTests.cs" />
419431
<Compile Include="CredentialTests\CredentialTestBase.cs" />
420432
<Compile Include="CredentialTests\CredentialTestHelper.cs" />
433+
<Compile Include="ChefExtension\ChefExtensionTests.cs" />
421434
<Compile Include="DiagnosticsExtension\DiagnosticsExtensionTests.cs" />
422435
<Compile Include="DscExtension\DscExtensionTests.cs" />
423436
<Compile Include="MediaServicesTests\MediaServicesTests.cs" />
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
2+
# ----------------------------------------------------------------------------------
3+
#
4+
# Copyright Microsoft Corporation
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ----------------------------------------------------------------------------------
15+
16+
17+
#
18+
# ChefExtensionTests.ps1
19+
#
20+
21+
$PLACEHOLDER = "PLACEHOLDER1@";
22+
23+
<#
24+
.SYNOPSIS
25+
Test the usage of the Set virtual machine chef extension command
26+
#>
27+
28+
# Setup
29+
$vmName = "vmone"
30+
$svcName = "storone"
31+
$storageName = "storone"
32+
$location = "West US"
33+
$TestOutputRoot = [System.AppDomain]::CurrentDomain.BaseDirectory;
34+
35+
function Test-SetAzureVMChefExtension
36+
{
37+
try
38+
{
39+
New-AzureStorageAccount -StorageAccountName $storageName -Location $location
40+
Set-CurrentStorageAccountName $storageName
41+
42+
New-AzureService -ServiceName $svcName -Location $location
43+
New-AzureQuickVM -Windows -ImageName "a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-BYOL-20160915-en.us-127GB.vhd" -Name $vmName -ServiceName $svcName -AdminUsername "pstestuser" -Password $PLACEHOLDER
44+
45+
$vm = Get-AzureVM -ServiceName $svcName -Name $vmName
46+
47+
Set-AzureVMChefExtension -VM $vm -ValidationPem "$TestOutputRoot\Resources\ChefExtension\tstorgnztn-validator.pem" -ClientRb "$TestOutputRoot\Resources\ChefExtension\client.rb" -JsonAttribute '{"container_service": {"chef-init-test": {"command": "C:\\opscode\\chef\\bin"}}}' -ChefServiceInterval 35 -Windows
48+
49+
Update-AzureVM -VM $vm.VM -ServiceName $svcName -Name $vmName
50+
51+
# Call Get-AzureVMDscExtensionStatus to check the status of the installation
52+
[TimeSpan] $timeout = [TimeSpan]::FromMinutes(60)
53+
$maxTime = [datetime]::Now + $timeout
54+
$status = Get-AzureVMChefExtension -VM $vm.VM
55+
56+
while($true)
57+
{
58+
if($status -ne $null -and $status.State -ne $null)
59+
{
60+
if(($status.State -eq "Enable") -or ($status.State -eq "Error"))
61+
{
62+
break;
63+
}
64+
}
65+
66+
if([datetime]::Now -gt $maxTime)
67+
{
68+
Throw "The Chef Extension did not report any status within the given timeout from VM [$vmName]"
69+
}
70+
71+
if ($env:AZURE_TEST_MODE -eq "Record"){
72+
sleep -Seconds 15
73+
}
74+
$status = Get-AzureVMChefExtension -VM $vm.VM
75+
}
76+
77+
# Call Get-AzureVMChefExtension to ensure extension was installed on the VM
78+
$vm = Get-AzureVM -ServiceName $svcName -Name $vmName
79+
$extension = Get-AzureVMChefExtension -VM $vm.VM -Verbose
80+
Assert-NotNull $extension
81+
Assert-NotNull $extension.ExtensionName
82+
Assert-NotNull $extension.Publisher
83+
Assert-NotNull $extension.Version
84+
85+
86+
# Remove Extension
87+
Remove-AzureVMChefExtension -VM $vm.VM -Verbose
88+
}
89+
finally
90+
{
91+
# Cleanup
92+
Remove-AzureStorageAccount -StorageAccountName $storageName -ErrorAction SilentlyContinue
93+
Cleanup-CloudService $svcName
94+
}
95+
96+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
log_level :debug
2+
chef_server_url "https://api.chef.io/organizations/dummy-org"
3+
validation_client_name "dummy-org-validator"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
dummyprivatekey
3+
-----END RSA PRIVATE KEY-----

0 commit comments

Comments
 (0)