Merge branch 'PaaSClient'
Conflicts: modules/InstallationSDK.ChefClientInstaller/InstallationSDK.ChefClientInstaller.Unit.Tests.ps1 modules/InstallationSDK.ChefClientInstaller/InstallationSDK.ChefClientInstaller.psproj
This commit is contained in:
Коммит
d64bcb2901
|
@ -0,0 +1,4 @@
|
|||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Insert your custom logic below...
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
ECHO Starting custom deployment script
|
||||
|
||||
REM Switch CWD to same directory as batch file
|
||||
cd /d %~dp0
|
||||
|
||||
PowerShell.exe -ExecutionPolicy Unrestricted .\Start.ps1 >> ".\Start.log" 2>&1
|
||||
|
||||
EXIT /B %ERRORLEVEL%
|
|
@ -0,0 +1,32 @@
|
|||
$VerbosePreference = "Continue"
|
||||
|
||||
$exitCode = 1
|
||||
|
||||
& {
|
||||
$VerbosePreference = "Continue"
|
||||
Write-Verbose "Starting installation from $(pwd)"
|
||||
|
||||
try
|
||||
{
|
||||
.\Main.ps1
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Verbose "$_"
|
||||
|
||||
if ($_ -is [System.Management.Automation.ErrorRecord])
|
||||
{
|
||||
Write-Verbose "$($_.ScriptStackTrace)"
|
||||
}
|
||||
elseif ($_ -is [Exception])
|
||||
{
|
||||
Write-Verbose "$($_.ErrorRecord.ScriptStackTrace)"
|
||||
}
|
||||
|
||||
throw
|
||||
}
|
||||
|
||||
$Script:exitCode = 0
|
||||
} *> .\Start.transcript.log
|
||||
|
||||
exit $exitCode
|
|
@ -0,0 +1,159 @@
|
|||
$ErrorActionPreference = "Stop"
|
||||
|
||||
[void][Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime")
|
||||
$roleEnvironment = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]
|
||||
|
||||
function Get-CloudServiceRole
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets one or more Azure Roles.
|
||||
|
||||
.PARAMETER Current
|
||||
If set, gets only the current role.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Switch] $Current
|
||||
)
|
||||
Process
|
||||
{
|
||||
if ($Current)
|
||||
{
|
||||
return $roleEnvironment::CurrentRoleInstance.Role
|
||||
}
|
||||
else
|
||||
{
|
||||
return ($roleEnvironment::Roles).Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-CloudServiceConfigurationSettingValue
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets the configuration setting value from the Azure CSCFG.
|
||||
|
||||
.PARAMETER Name
|
||||
The setting to retrieve.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $Name
|
||||
)
|
||||
Process
|
||||
{
|
||||
try
|
||||
{
|
||||
return $roleEnvironment::GetConfigurationSettingValue($Name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
# TODO: DO we want this in prod? Or just return an error?
|
||||
# If setting doesn't exist. Just return null.
|
||||
return $null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-CloudServiceRoleInstance
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets one or more Azure Role Instances.
|
||||
|
||||
.PARAMETER Role
|
||||
The role to get the instances of.
|
||||
|
||||
.PARAMETER Current
|
||||
If set, gets the current role instance.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory, ParameterSetName="ByRole")]
|
||||
[ValidateNotNull()]
|
||||
[Object] $Role,
|
||||
|
||||
[Parameter(ParameterSetName="ByCurrent")]
|
||||
[Switch] $Current
|
||||
)
|
||||
Process
|
||||
{
|
||||
if ($PSCmdlet.ParamSetName -eq "ByRole")
|
||||
{
|
||||
return $Role.Instances
|
||||
}
|
||||
else
|
||||
{
|
||||
return $roleEnvironment::CurrentRoleInstance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-CloudServiceLocalResource
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets details for an Azure Local Resource.
|
||||
|
||||
.PARAMETER ResourceName
|
||||
The name of the Azure Local Resource.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String] $ResourceName
|
||||
)
|
||||
Process
|
||||
{
|
||||
try
|
||||
{
|
||||
return $roleEnvironment::GetLocalResource($resourceName)
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Warning "Unable to get to get Azure local resource $ResourceName, possibly because it does not exist ($_)."
|
||||
return $null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-CloudServiceEnvironmentType
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets the type of environment that the scripts are currently running in.
|
||||
|
||||
.NOTES
|
||||
Will be one of "Emulated", "Azure", or "NotAvailable"
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
Param()
|
||||
Process
|
||||
{
|
||||
if ($roleEnvironment::IsAvailable)
|
||||
{
|
||||
if ($roleEnvironment::IsEmulated)
|
||||
{
|
||||
return "Emulated"
|
||||
}
|
||||
|
||||
return "Azure"
|
||||
}
|
||||
|
||||
return "NotAvailable"
|
||||
}
|
||||
}
|
||||
|
||||
Export-ModuleMember Get-CloudServiceRole
|
||||
Export-ModuleMember Get-CloudServiceRoleInstance
|
||||
Export-ModuleMember Get-CloudServiceLocalResource
|
||||
Export-ModuleMember Get-CloudServiceEnvironmentType
|
||||
Export-ModuleMember Get-CloudServiceConfigurationSettingValue
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"Name": "InstallationSDK.AzureServiceRuntime",
|
||||
"OutputPath": "bin",
|
||||
"Module": {
|
||||
"Id": "6D6BB33F-84DE-408D-869E-747082A76505",
|
||||
"Name": "InstallationSDK.AzureServiceRuntime",
|
||||
"Version": "1.0.0",
|
||||
"Author": "ampdmi",
|
||||
"CompanyName": "Microsoft",
|
||||
"Description": "PowerShell Cmdlets for interacting with the Azure Service Runtime.",
|
||||
"Copyright": "(c) 2014 Microsoft. All rights reserved.",
|
||||
"PowerShellVersion": "3.0",
|
||||
"RequiredModules": []
|
||||
},
|
||||
"Files": {
|
||||
"RootModule": "InstallationSDK.AzureServiceRuntime.psm1"
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ $ErrorActionPreference = "STOP"
|
|||
$modulesToCleanup = @($ModuleUnderTest)
|
||||
|
||||
|
||||
Import-Module Pester
|
||||
Import-Module Pester
|
||||
|
||||
#region Helper Functions
|
||||
|
||||
|
@ -71,6 +71,60 @@ function Cleanup
|
|||
Remove-Variable -Name TestDrive -Force -Scope Script -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
function CreateRoleInstanceEndpoint
|
||||
{
|
||||
param(
|
||||
[string]$parsableIPAddress,
|
||||
[string]$parsableIPAddressPublic,
|
||||
[string]$protocol
|
||||
)
|
||||
|
||||
$ip = $parsableIPAddress.Split(":")
|
||||
$ipEndpoint = New-Object System.Net.IPEndPoint -ArgumentList ([System.Net.IPAddress]$ip[0], $ip[1])
|
||||
|
||||
$publicIpEndpoint = $null
|
||||
if($parsableIPAddressPublic)
|
||||
{
|
||||
$public = $parsableIPAddressPublic.Split(":")
|
||||
$publicIpEndpoint = New-Object System.Net.IPEndPoint -ArgumentList ([System.Net.IPAddress]$public[0], $public[1])
|
||||
}
|
||||
|
||||
New-Object psobject -Property @{
|
||||
"IPEndpoint" = $ipEndpoint
|
||||
"PublicIPEndpoint" = $publicIpEndpoint
|
||||
"Protocol" = $protocol
|
||||
}
|
||||
}
|
||||
|
||||
function CreateVirtualIPEndpoint
|
||||
{
|
||||
param(
|
||||
[string]$groupName,
|
||||
[System.Net.IPAddress[]]$ipAddresses,
|
||||
$roleInstanceEndpoints
|
||||
)
|
||||
# Weird dictionary thingy
|
||||
$instanceEndpoints = @{}
|
||||
$i = 0
|
||||
foreach($roleInstanceEndpoint in $roleInstanceEndpoints)
|
||||
{
|
||||
$instanceEndpoints[($i++)] = $roleInstanceEndpoint
|
||||
}
|
||||
|
||||
$virtualIpEndpoints = @{}
|
||||
foreach($ipAddress in $ipAddresses)
|
||||
{
|
||||
$virtualIpEndpoints[$ipAddress] = New-Object psobject -Property @{
|
||||
"PublicIPAddress" = $ipAddress
|
||||
"InstanceEndpoints" = $instanceEndpoints
|
||||
}
|
||||
}
|
||||
|
||||
New-Object psobject -Property @{
|
||||
"VirtualIPGroupName" = $groupName
|
||||
"VirtualIPEndpoints" = $virtualIpEndpoints
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Setup
|
||||
|
@ -87,9 +141,15 @@ Cleanup
|
|||
WriteVerbose "Building Project Dependencies"
|
||||
foreach ($dependantPSproject in $PSProjDepedencies)
|
||||
{
|
||||
New-ProjectBuild -Path $dependantPSproject
|
||||
$moduleName = [IO.Path]::GetFileNameWithoutExtension((Split-Path -Leaf $dependantPSproject))
|
||||
$moduleFolder = Join-Path (Split-Path $dependantPSproject) "bin"
|
||||
$moduleName = [IO.Path]::GetFileNameWithoutExtension((Split-Path -Leaf $dependantPSproject))
|
||||
|
||||
if (Test-Path $moduleFolder)
|
||||
{
|
||||
Remove-Item -Path $moduleFolder -Recurse -Force
|
||||
}
|
||||
|
||||
New-ProjectBuild -Path $dependantPSproject
|
||||
|
||||
SafeAddModuleFolderToPSRoot $moduleFolder
|
||||
ImportModuleAndToCleanupList $moduleName
|
||||
|
@ -98,7 +158,13 @@ foreach ($dependantPSproject in $PSProjDepedencies)
|
|||
#
|
||||
# Build Module Under Test
|
||||
#
|
||||
$ModuleRoot = Join-Path $PSScriptRoot "bin"
|
||||
WriteVerbose "Building the Module Under Test"
|
||||
if (Test-Path $ModuleRoot)
|
||||
{
|
||||
Remove-Item -Path $ModuleRoot -Recurse -Force
|
||||
}
|
||||
|
||||
$psprojFile = Resolve-Path (Join-Path $PSScriptRoot "*.psproj")
|
||||
Write-Verbose "Building psproj: $psprojFile"
|
||||
New-ProjectBuild -Path $psprojFile
|
||||
|
@ -107,7 +173,6 @@ New-ProjectBuild -Path $psprojFile
|
|||
# Loading Module-Under-Test
|
||||
#
|
||||
WriteVerbose "Loading Module-Under-Test"
|
||||
$ModuleRoot = Join-Path $PSScriptRoot "bin"
|
||||
SafeAddModuleFolderToPSRoot $moduleRoot
|
||||
Import-Module $ModuleUnderTest
|
||||
|
||||
|
@ -272,6 +337,63 @@ InModuleScope $ModuleUnderTest {
|
|||
$path | Should Match ([Regex]::Escape("$InstallLocation\chef\bin"))
|
||||
}
|
||||
}
|
||||
|
||||
Describe "Export-ChefAzureOhaiHints" {
|
||||
Mock Get-CloudServiceRoleInstance {
|
||||
param([Switch]$Current)
|
||||
|
||||
# These RoleInstanceEndpoints were taken directly from a "test" azure instance
|
||||
$endpoint1 = CreateRoleInstanceEndpoint "100.68.46.96:80" "255.255.255.255:80" "http"
|
||||
$rdp = CreateRoleInstanceEndpoint "100.68.46.96:3389" $null "tcp"
|
||||
$rdpInput = CreateRoleInstanceEndpoint "100.68.46.96:20000" "255.255.255.255:3389" "tcp"
|
||||
|
||||
|
||||
New-Object psobject -Property @{
|
||||
"DeploymentID" = "9662c0f4355042c7b2eae7dd06e70c28"
|
||||
"ID" = "WebRole1_IN_0"
|
||||
"UpdateDomain" = 0
|
||||
"FaultDomain" = 0
|
||||
"Role" = New-Object psobject -property @{"Name" = "WebRole1"}
|
||||
"InstanceEndpoints" = @{
|
||||
"Endpoint1" = $endpoint1
|
||||
"Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp" = $rdp
|
||||
"Microsoft.WindowsAzure.Plugins.RemoteForwarder.RdpInput" = $rdpInput
|
||||
}
|
||||
# Couldn't get a good working sample of VirtualIPGroups, these VirtualIPEndpoints were filled in using reasonable, expected values
|
||||
"VirtualIPGroups" = @{
|
||||
"Group1" = CreateVirtualIPEndpoint "SomeGroup1" ("192.167.0.1","192.167.0.2","127.0.0.1") ($endpoint1,$rdp,$rdpInput)
|
||||
"Group2" = CreateVirtualIPEndpoint "SomeGroup2" ("255.255.255.255","0.0.0.0","169.245.214.223") ($endpoint1,$rdp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$roleInstance = Get-CloudServiceRoleInstance -Current
|
||||
|
||||
$hintsDirectory = "TestDrive:\\Chef\Ohai\Hints"
|
||||
Export-ChefAzureOhaiHints -path $hintsDirectory
|
||||
|
||||
$expectedAzureHintFile = Join-Path $hintsDirectory "azure.json"
|
||||
|
||||
It "Should Parse Correctly" {
|
||||
$expectedAzureHintFile | Should Exist
|
||||
{ ConvertFrom-Json ((Get-Content $expectedAzureHintFile) -join "`n") } | Should Not Throw
|
||||
}
|
||||
|
||||
It "Should have every property defined" {
|
||||
$deserialized = ConvertFrom-Json ((Get-Content $expectedAzureHintFile) -join "`n")
|
||||
$deserialized.deployment_id | Should Not BeNullOrEmpty
|
||||
$deserialized.deployment_id | Should BeExactly $roleInstance.DeploymentID
|
||||
$deserialized.role | Should Not BeNullOrEmpty
|
||||
$deserialized.role | Should BeExactly $roleInstance.Role.Name
|
||||
$deserialized.instance_endpoints.'Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp'.ip_endpoint | Should Not BeNullOrEmpty
|
||||
$deserialized.instance_endpoints.'Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp'.ip_endpoint | Should BeExactly $roleInstance.InstanceEndpoints["Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp"].IPEndpoint.ToString()
|
||||
$deserialized.instance_endpoints.'Microsoft.WindowsAzure.Plugins.RemoteAccess.Rdp'.public_ip_endpoint | Should BeNullOrEmpty
|
||||
$deserialized.virtual_ip_groups.'Group1'.group_name | Should Not BeNullOrEmpty
|
||||
$deserialized.virtual_ip_groups.'Group1'.group_name | Should BeExactly $roleInstance.VirtualIPGroups["Group1"].VirtualIPGroupName
|
||||
$deserialized.virtual_ip_groups.'Group1'.virtual_ip_endpoints.'192.167.0.1'.instance_endpoints.'0'.ip_endpoint | Should Not BeNullOrEmpty
|
||||
$deserialized.virtual_ip_groups.'Group1'.virtual_ip_endpoints.'192.167.0.1'.instance_endpoints.'0'.ip_endpoint | Should BeExactly $roleInstance.VirtualIPGroups["Group1"].VirtualIPEndpoints[[Net.IPAddress]"192.167.0.1"].InstanceEndpoints[0].IPEndpoint.ToString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
|
@ -98,7 +98,7 @@ function Get-ChefClientConfig
|
|||
{
|
||||
# Regex matches simple "somekey value" pattern
|
||||
# Parses out custom Ruby (like now = Time.new)
|
||||
Get-Content -Path $Path | foreach {
|
||||
Get-Content -Path $Path | where { $_ } | foreach {
|
||||
if (-not ($_ -match "^[a-zA-Z0-9_]*\s*[:'`"0-9].*['`"]?" ))
|
||||
{
|
||||
# Ran into this scenario before
|
||||
|
@ -223,7 +223,7 @@ function Save-ChefClientConfig
|
|||
|
||||
function Get-ChefNodeList
|
||||
{
|
||||
<#
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets the list of nodes from the chef server
|
||||
|
||||
|
@ -277,6 +277,106 @@ function Get-ChefNodeList
|
|||
}
|
||||
}
|
||||
|
||||
function Export-ChefAzureOhaiHints
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Generate Azure Ohai Hints File
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$Path = 'c:/chef/ohai/hints'
|
||||
)
|
||||
|
||||
# There may be some issues with calling Get-CloudServiceRoleInstance, so call it twice to make sure we get the proper object
|
||||
Get-CloudServiceRoleInstance -Current -ErrorAction SilentlyContinue | out-Null
|
||||
$roleInstance = Get-CloudServiceRoleInstance -Current
|
||||
|
||||
# Because Ohai::Config[:hints_path] is actual ruby code, not a configuration settting, we can't use the ClientRBObject.
|
||||
# So just hard code the path here. Alternatively, we could try to read/parse from the client.rb file directly, but that's costly.
|
||||
# And since it's ruby code, it might be a non-string (path_to_hints.to_s or something weird like that) that PSH wouldn't know what to do with.
|
||||
# This seemed the least hacky way...
|
||||
|
||||
# TL;DR - Important! If the path to \Ohai\Hints ($Path) is changed, also change it in Client.Rb directly!
|
||||
|
||||
# Azure Ohai Plugin specifically looks for an "azure" hint file (which would be named azure.json)
|
||||
New-Item $Path -Force -ItemType Directory -ErrorAction SilentlyContinue
|
||||
$azureJsonFile = Join-Path $Path "azure.json"
|
||||
|
||||
New-Item -Type Directory -Force -Path $Path -ErrorAction SilentlyContinue | Out-Null
|
||||
|
||||
$azureHints = @{}
|
||||
$azureHints["deployment_id"] = $roleInstance.DeploymentID
|
||||
$azureHints["instance_id"] = $roleInstance.Id
|
||||
$azureHints["update_domain"] = $roleInstance.UpdateDomain
|
||||
$azureHints["fault_domain"] = $roleInstance.FaultDomain
|
||||
$azureHints["role"] = $roleInstance.Role.Name
|
||||
|
||||
$azureHints["instance_endpoints"] = @{}
|
||||
foreach($endpointKey in $roleInstance.InstanceEndpoints.Keys) {
|
||||
$endpoint = $roleInstance.InstanceEndpoints[$endpointKey]
|
||||
|
||||
$azureHints["instance_endpoints"][$endpointKey] = @{
|
||||
"ip_endpoint" = Convert-ToStringSafe $endpoint.IPEndpoint
|
||||
"public_ip_endpoint" = Convert-ToStringSafe $endpoint.PublicIPEndpoint
|
||||
"protocol" = $endpoint.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
$azureHints["virtual_ip_groups"] = @{}
|
||||
foreach($ipGroupKey in $roleInstance.VirtualIPGroups.Keys) {
|
||||
$group = $roleInstance.VirtualIPGroups[$ipGroupKey]
|
||||
$vip_ip_endpoints = @{}
|
||||
|
||||
foreach($vipEndpointKey in $group.VirtualIPEndpoints.Keys) {
|
||||
$vipEndpoint = $group.VirtualIPEndpoints[$vipEndpointKey]
|
||||
$vip_instance_endpoints = @{}
|
||||
foreach($instanceEndpointKey in $vipEndpoint.InstanceEndpoints.Keys) {
|
||||
$instanceEndpoint = $vipEndpoint.InstanceEndpoints[$instanceEndpointKey]
|
||||
$vip_instance_endpoints[(Convert-ToStringSafe $instanceEndpointKey)] = @{
|
||||
"ip_endpoint" = Convert-ToStringSafe $instanceEndpoint.IPEndpoint
|
||||
"public_ip_endpoint" = Convert-ToStringSafe $instanceEndpoint.PublicIPEndpoint
|
||||
"protocol" = $instanceEndpoint.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
$vip_ip_endpoints[(Convert-ToStringSafe $vipEndpointKey)] = @{
|
||||
"public_ip_address" = Convert-ToStringSafe $vipEndpoint.PublicIPAddress
|
||||
"instance_endpoints" = $vip_instance_endpoints
|
||||
}
|
||||
}
|
||||
|
||||
$azureHints["virtual_ip_groups"][$ipGroupKey] = @{
|
||||
"group_name" = $group.VirtualIPGroupName
|
||||
"virtual_ip_endpoints" = $vip_ip_endpoints
|
||||
}
|
||||
}
|
||||
|
||||
# In my testing, it can go as deep as depth "6". Any less than that and the cmdlet will just call .ToString() on nested collections
|
||||
$azureHints | ConvertTo-Json -Depth 6 | Set-Content $azureJsonFile
|
||||
}
|
||||
|
||||
function Convert-ToStringSafe
|
||||
{
|
||||
<#
|
||||
.SYPNOSIS
|
||||
Quick utility function to prevent things from getting too deserialized (e.g. IPAddress getting each of its properties deserialized)
|
||||
#>
|
||||
param(
|
||||
$value
|
||||
)
|
||||
|
||||
if($value -or ($value -eq 0))
|
||||
{
|
||||
$value.ToString()
|
||||
}
|
||||
else
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
# Wrap cmd exe files to make things mockable. Can't use Start-Process because I want the output (Start-Process would write to a file first with -RedirectStandardOutput)
|
||||
function Invoke-Knife
|
||||
{
|
||||
|
@ -316,4 +416,5 @@ param(
|
|||
Export-ModuleMember Install-ChefClient
|
||||
Export-ModuleMember Get-ChefClientConfig
|
||||
Export-ModuleMember Save-ChefClientConfig
|
||||
Export-ModuleMember Get-ChefNodeList
|
||||
Export-ModuleMember Get-ChefNodeList
|
||||
Export-ModuleMember Export-ChefAzureOhaiHints
|
|
@ -25,43 +25,21 @@ namespace Microsoft.OnlinePublishing.Chef
|
|||
/// <summary>
|
||||
/// Stop the Chef Client windows service with the default wait time of 1 minute.
|
||||
/// </summary>
|
||||
public static void Stop()
|
||||
/// <param name="terminateOnFailure">Should the process terminate the processes of the Client service if it failes to stop in alloted time.</param>
|
||||
public static void Stop(bool terminateOnFailure)
|
||||
{
|
||||
Stop(new TimeSpan(0, 1, 0));
|
||||
Stop(new TimeSpan(0, 1, 0), terminateOnFailure);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the Chef Client windows service.
|
||||
/// </summary>
|
||||
/// <param name="timeToWait">Wait time for operation to complete.</param>
|
||||
public static void Stop(TimeSpan timeToWait)
|
||||
/// <param name="terminateOnFailure">Should the process terminate the processes of the Client service if it failes to stop in alloted time.</param>
|
||||
public static void Stop(TimeSpan timeToWait, bool terminateOnFailure)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Stop Chef Client
|
||||
Trace.TraceInformation("Chef Client - attempting to stop the Chef Client windows service.");
|
||||
using (var chefService = new ServiceController("chef-client"))
|
||||
{
|
||||
if (chefService != null && chefService.Status != ServiceControllerStatus.Stopped)
|
||||
{
|
||||
chefService.Stop();
|
||||
chefService.WaitForStatus(ServiceControllerStatus.Stopped, timeToWait);
|
||||
Trace.TraceInformation("Chef Client - Chef Client windows service Stopped.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.TraceInformation("Chef Client - Chef Client windows service is not running.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.ServiceProcess.TimeoutException)
|
||||
{
|
||||
Trace.TraceInformation("Chef Client - failed to stop Chef Client in time allotted [{0}].", timeToWait);
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Trace.TraceInformation("Chef Client - Invalid Operation, is the role running with elevated privileges. Ex:{0}.", e.ToString());
|
||||
}
|
||||
var service = new WindowsService() { Name = "chef-client", TerminateOnFailure = terminateOnFailure, TimeToWait = timeToWait };
|
||||
service.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -69,37 +47,21 @@ namespace Microsoft.OnlinePublishing.Chef
|
|||
/// </summary>
|
||||
public static void Start()
|
||||
{
|
||||
try
|
||||
{
|
||||
RoleEnvironment.Changing += ChefConfigChanging;
|
||||
RoleEnvironment.StatusCheck += Chef_StatusCheck;
|
||||
Start(new TimeSpan( 0, 1, 0) );
|
||||
}
|
||||
|
||||
// Start Chef Client - wait 30 seconds
|
||||
Trace.TraceInformation("Chef Client - Attempting to start Chef-Client.");
|
||||
using (var chefService = new ServiceController("chef-client"))
|
||||
{
|
||||
if (chefService != null && chefService.Status != ServiceControllerStatus.Running)
|
||||
{
|
||||
chefService.Start();
|
||||
chefService.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 30));
|
||||
Trace.TraceInformation("Chef Client - Chef-Client Started.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.TraceInformation("Chef Client - Chef-Client previously running.");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Start Chef Client windows service.
|
||||
/// </summary>
|
||||
public static void Start(TimeSpan timeToWait)
|
||||
{
|
||||
RoleEnvironment.Changing += ChefConfigChanging;
|
||||
RoleEnvironment.StatusCheck += Chef_StatusCheck;
|
||||
|
||||
ClientService.statusCheckFilePath = CloudConfigurationManager.GetSetting("ChefClient_SetBusyCheck");
|
||||
}
|
||||
catch (System.ServiceProcess.TimeoutException)
|
||||
{
|
||||
Trace.TraceInformation("Chef Client - failed to start Chef Client within time range.");
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Trace.TraceInformation("Chef Client - Invalid Operation, is the role running with elevated privileges. Ex:{0}.", e.ToString());
|
||||
}
|
||||
// Start Chef Client - wait 30 seconds
|
||||
var service = new WindowsService() { Name = "chef-client", TimeToWait = timeToWait };
|
||||
service.Start();
|
||||
ClientService.statusCheckFilePath = CloudConfigurationManager.GetSetting("ChefClient_SetBusyCheck");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -114,6 +76,7 @@ namespace Microsoft.OnlinePublishing.Chef
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
e.SetBusy();
|
||||
}
|
||||
|
||||
|
@ -139,7 +102,7 @@ namespace Microsoft.OnlinePublishing.Chef
|
|||
c.ConfigurationSettingName == "ChefClient_Role" ||
|
||||
c.ConfigurationSettingName == "ChefClient_Environment" ))
|
||||
{
|
||||
Stop(new TimeSpan(0, 0, 5));
|
||||
Stop(new TimeSpan(0, 0, 30), true);
|
||||
e.Cancel = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="WindowsService.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
namespace Microsoft.OnlinePublishing.Chef
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceProcess;
|
||||
using System.Management;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Service gives the ability to stop a windows service (namely chef-client).
|
||||
/// If the service failes to stop in a given timespan, then the service and its child processes are terminated.
|
||||
/// </summary>
|
||||
class WindowsService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Name of the Windows Service.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alloted time to wait during shutdown sequence.
|
||||
/// </summary>
|
||||
public TimeSpan TimeToWait { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether or not to terminate processes upon failure to stop teh service in the alloted time to wait.
|
||||
/// </summary>
|
||||
public bool TerminateOnFailure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Start Chef Client windows service.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Start Chef Client - wait 30 seconds
|
||||
Trace.TraceInformation("{0} - Attempting to start {0}.", Name);
|
||||
using (var chefService = new ServiceController(Name))
|
||||
{
|
||||
if (chefService != null && chefService.Status != ServiceControllerStatus.Running)
|
||||
{
|
||||
chefService.Start();
|
||||
chefService.WaitForStatus(ServiceControllerStatus.Running, TimeToWait);
|
||||
Trace.TraceInformation("{0} - {0} Started.", Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.TraceInformation("{0} - {0} previously running.", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.ServiceProcess.TimeoutException)
|
||||
{
|
||||
Trace.TraceInformation("{0} - failed to start Chef Client within time range.", Name);
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Trace.TraceInformation("{0} - Invalid Operation, is the role running with elevated privileges. Ex:{1}.", Name, e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the Windows Service, if Terminate on Failure, then terminate process and all child spawn.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Stop Chef Client
|
||||
Trace.TraceInformation("{0} - attempting to stop the {0} windows service.", Name);
|
||||
using (var chefService = new ServiceController(Name))
|
||||
{
|
||||
if (chefService != null && chefService.Status != ServiceControllerStatus.Stopped)
|
||||
{
|
||||
chefService.Stop();
|
||||
chefService.WaitForStatus(ServiceControllerStatus.Stopped, TimeToWait);
|
||||
Trace.TraceInformation("{0} - {0} windows service Stopped.", Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.TraceInformation("{0} - {0} windows service is not running.", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.ServiceProcess.TimeoutException)
|
||||
{
|
||||
Trace.TraceInformation("{0} - failed to stop {0} in time allotted [{1}].", Name, TimeToWait);
|
||||
if (TerminateOnFailure)
|
||||
{
|
||||
Trace.TraceInformation("{0} - attempting to terminate service process and its children.", Name);
|
||||
KillService();
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Trace.TraceInformation("{0} - Invalid Operation, is the role running with elevated privileges. Ex:{1}.", Name, e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locate process by service name and kill it and its spawn.
|
||||
/// </summary>
|
||||
private void KillService()
|
||||
{
|
||||
var searcher = new ManagementObjectSearcher(
|
||||
"SELECT * " +
|
||||
"FROM Win32_Service " +
|
||||
"WHERE Name=\"" + Name + "\"");
|
||||
var collection = searcher.Get();
|
||||
foreach (var item in collection)
|
||||
{
|
||||
var serviceProcessId = (UInt32)item["ProcessId"];
|
||||
KillSpawnedProcesses(serviceProcessId);
|
||||
Trace.TraceInformation("{0} - Killing Service process with Id [{1}].", Name, serviceProcessId);
|
||||
KillProcess(serviceProcessId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kill process and all spawn. Travers all children for multi generation children.
|
||||
/// </summary>
|
||||
/// <param name="parentProcessId">Parent ID</param>
|
||||
private void KillSpawnedProcesses(UInt32 parentProcessId)
|
||||
{
|
||||
Trace.TraceInformation("{0} - Finding processes spawned by process with Id [" + parentProcessId + "]", Name);
|
||||
|
||||
var searcher = new ManagementObjectSearcher(
|
||||
"SELECT * " +
|
||||
"FROM Win32_Process " +
|
||||
"WHERE ParentProcessId=" + parentProcessId);
|
||||
var collection = searcher.Get();
|
||||
if (collection.Count > 0)
|
||||
{
|
||||
Trace.TraceInformation("{0} - Killing [{1}] processes spawned by process with Id [{2}].", Name, collection.Count, parentProcessId);
|
||||
foreach (var item in collection)
|
||||
{
|
||||
var childProcessId = (UInt32)item["ProcessId"];
|
||||
KillSpawnedProcesses(childProcessId);
|
||||
KillProcess(childProcessId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to kill process. It can ocurr that the process has been killed prior to getting to this statement as the process tree is being killed.
|
||||
/// </summary>
|
||||
/// <param name="processId">ID of process to kill.</param>
|
||||
private void KillProcess(uint processId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((int)processId != Process.GetCurrentProcess().Id)
|
||||
{
|
||||
var process = Process.GetProcessById((int)processId);
|
||||
Trace.TraceInformation("{0} - Killing process [{1}] with Id [{2}]", Name, process.ProcessName, processId);
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
Trace.TraceInformation("{0} - failed to find process [{1}]. Process already killed. Ex:{2}", Name, processId, e.ToString());
|
||||
}
|
||||
catch (System.ComponentModel.Win32Exception e)
|
||||
{
|
||||
Trace.TraceInformation("{0} - failed to kill process [{1}]. Ex:{2}", Name, processId, e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,6 +64,14 @@ if ($config -and $config.name)
|
|||
$name = $config.name
|
||||
}
|
||||
|
||||
# Allow to pull from CSCFG allowing for easier targetting of node name prefix, this can only be set on initial deployment
|
||||
# once the node name is established, the exisitng name will always win.
|
||||
$cscfgName = Get-CloudServiceConfigurationSettingValue "ChefClient_Name"
|
||||
if ($cscfgName)
|
||||
{
|
||||
$name = $cscfgName
|
||||
}
|
||||
|
||||
# Add Instance number to the node name
|
||||
Write-Output "Role Instance Name: $($roleInstance.Id)"
|
||||
$nodeName = $($roleInstance.Id).Replace($roleName, $name)
|
||||
|
@ -239,6 +247,11 @@ else
|
|||
|
||||
# Value from Cloud Service CsCfg always wins.
|
||||
$chefRole = Get-CloudServiceConfigurationSettingValue "ChefClient_Role"
|
||||
$chefEnvironment = Get-CloudServiceConfigurationSettingValue "ChefClient_Environment"
|
||||
$azureRegion = Get-CloudServiceConfigurationSettingValue "ChefClient_Region"
|
||||
$servicefunction = Get-CloudServiceConfigurationSettingValue "ChefClient_Function"
|
||||
$serviceName = Get-CloudServiceConfigurationSettingValue "ChefClient_ServiceName"
|
||||
|
||||
# Create first-run-bootstrap.json to register new node with Chef Server
|
||||
if ($chefRole -or ($config -and $config.role))
|
||||
{
|
||||
|
@ -248,7 +261,19 @@ if ($chefRole -or ($config -and $config.role))
|
|||
$chefRole = $($config.role)
|
||||
}
|
||||
$bootStrapperFile = "first-run-bootstrap.json"
|
||||
$bootStrapper = "{`r`n `"run_list`": [ `"role[$chefRole]`" ]`r`n}"
|
||||
$bootStrapper =
|
||||
@"
|
||||
{
|
||||
"run_list": [ "role[$chefRole]" ],
|
||||
"azure": {
|
||||
"chef_environment":"$chefEnvironment",
|
||||
"chef_role": "$chefRole",
|
||||
"region": "$azureRegion",
|
||||
"function": "$servicefunction",
|
||||
"service_name": "$serviceName"
|
||||
}
|
||||
}
|
||||
"@
|
||||
Write-Output "Setting bootstrap content: $bootStrapper"
|
||||
|
||||
$pathToBootStrapper = Join-Path $RootPath $bootStrapperFile
|
||||
|
@ -268,6 +293,9 @@ if ($chefEnvironment)
|
|||
Copy-Item -Path $TemplateClientRb -Destination $pathToClientRb -Force
|
||||
$ClientRbObject | Save-ChefClientConfig -Path $pathToClientRb -Append
|
||||
|
||||
# Setup Azure Ohai
|
||||
Export-ChefAzureOhaiHints -Path "$RootPath/ohai/hints"
|
||||
|
||||
start-service chef-client
|
||||
|
||||
Write-Output "Script:main.ps1 exiting"
|
|
@ -0,0 +1,5 @@
|
|||
log_level :info
|
||||
log_location 'c:/chef/client_' + Time.new.strftime("%Y%m%d") + '.log'
|
||||
cache_path 'c:\chef'
|
||||
client_key 'c:\chef\client.pem'
|
||||
Ohai::Config[:hints_path] = [ 'c:/chef/ohai/hints' ]
|
|
@ -0,0 +1,155 @@
|
|||
Param
|
||||
(
|
||||
# Path to the folder where the package is installed
|
||||
$installPath,
|
||||
|
||||
# Path to the tools directory in the folder where the package is installed
|
||||
$toolsPath,
|
||||
|
||||
# A reference to the package object
|
||||
$package,
|
||||
|
||||
# A reference to the EnvDTE project object and represents the project the package is installed into.
|
||||
# http://msdn.microsoft.com/en-us/library/51h9a6ew(v=VS.80).aspx
|
||||
$project
|
||||
)
|
||||
|
||||
# http://msdn.microsoft.com/en-us/library/aa983962(VS.71).aspx
|
||||
$BuildTypes = @{
|
||||
"None" = "0";
|
||||
"Compile" = "1";
|
||||
"Content" = "2";
|
||||
}
|
||||
|
||||
$CopyToOutputDirectory = @{
|
||||
"DoNotCopy" = "0";
|
||||
"CopyAlways" = "1";
|
||||
"CopyIfNewer" = "2";
|
||||
}
|
||||
|
||||
function Add-ContentsToProjectOutput
|
||||
{
|
||||
<#
|
||||
.DESCRIPTION
|
||||
If the project item given by ProjectItem exists at the corresponding location given by PackagePath,
|
||||
then sets its properties such that the item will be copied to the build output. The intent is to not
|
||||
modify user's file which may also be present under the given project item.
|
||||
|
||||
.PARAMETER ProjectItem
|
||||
The project item; should be a child object of a VS project.
|
||||
|
||||
.PARAMETER PackagePath
|
||||
The physical path that should correspond to ProjectItem. If the path does not exist or otherwise does
|
||||
not match ProjectItem, then it will not be modified.
|
||||
|
||||
.PARAMETER ProjectPath
|
||||
The logical path of the ProjectItem within the project. Used purely for logging.
|
||||
|
||||
.PARAMETER Recurse
|
||||
A value indicating whether a ProjectItem whose type is PhysicalDirectory should be traversed.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateNotNull()]
|
||||
[Object] $ProjectItem,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String] $PackagePath,
|
||||
|
||||
[Parameter()]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String] $ProjectPath = "./",
|
||||
|
||||
[Parameter()]
|
||||
[Switch] $Recurse
|
||||
)
|
||||
Process
|
||||
{
|
||||
$name = $ProjectItem.Name
|
||||
|
||||
if ((IsPhysicalFolder $ProjectItem) -and $Recurse)
|
||||
{
|
||||
if (-not (Test-Path $PackagePath -PathType Container))
|
||||
{
|
||||
Write-Verbose "Folder '$ProjectPath' does not exist at location '$PackagePath'"
|
||||
return $null
|
||||
}
|
||||
|
||||
Write-Verbose "'$ProjectPath' maps to folder '$PackagePath', checking its contents"
|
||||
|
||||
return ($ProjectItem.ProjectItems | % {
|
||||
Add-ContentsToProjectOutput `
|
||||
-ProjectItem $_ `
|
||||
-PackagePath (Join-Path $PackagePath $_.Name) `
|
||||
-ProjectPath (Join-Path $ProjectPath $_.Name) `
|
||||
-Recurse:$Recurse
|
||||
})
|
||||
}
|
||||
elseif (IsPhysicalFile $ProjectItem)
|
||||
{
|
||||
if (-not (Test-Path $PackagePath -PathType Leaf))
|
||||
{
|
||||
Write-Verbose "File '$ProjectPath' does not exist at location '$PackagePath'"
|
||||
return $null
|
||||
}
|
||||
|
||||
Write-Verbose "'$ProjectPath' maps to file '$PackagePath', adding it to build output"
|
||||
|
||||
$ProjectItem.Properties.Item("CopyToOutputDirectory").Value = $CopyToOutputDirectory.CopyIfNewer
|
||||
$ProjectItem.Properties.Item("BuildAction").Value = $BuildTypes.None
|
||||
|
||||
return $ProjectItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function IsPhysicalFolder
|
||||
{
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateNotNull()]
|
||||
[Object] $ProjectItem
|
||||
)
|
||||
Process
|
||||
{
|
||||
return ($ProjectItem.Kind -ieq "{6bb5f8ef-4483-11d3-8bcf-00c04f8ec28c}")
|
||||
}
|
||||
}
|
||||
|
||||
function IsPhysicalFile
|
||||
{
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateNotNull()]
|
||||
[Object] $ProjectItem
|
||||
)
|
||||
Process
|
||||
{
|
||||
return ($ProjectItem.Kind -ieq "{6bb5f8ee-4483-11d3-8bcf-00c04f8ec28c}")
|
||||
}
|
||||
}
|
||||
|
||||
$rootItem = $project.ProjectItems.Item("Deployment")
|
||||
|
||||
if (-not $rootItem)
|
||||
{
|
||||
Write-Warning "Root 'Deployment' item does not exist."
|
||||
return
|
||||
}
|
||||
|
||||
$modified = Add-ContentsToProjectOutput `
|
||||
-ProjectItem $rootItem `
|
||||
-PackagePath (Join-Path $installPath "content/Deployment/")`
|
||||
-ProjectPath $rootItem.Name `
|
||||
-Recurse
|
||||
|
||||
Write-Verbose "Modified $($modified.Count) item(s)."
|
||||
|
||||
return $modified
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Microsoft.OnlinePublishing.InstallationSDK.ChefClientInstaller</id>
|
||||
<version>0.1.7</version>
|
||||
<title>Microsoft Online Publishing Installation SDK Chef Client Installer</title>
|
||||
<authors>ampdmi@microsoft.com</authors>
|
||||
<owners>ampdmi@microsoft.com</owners>
|
||||
<projectUrl>http://aka.ms/msompinstallationsdk</projectUrl>
|
||||
<description>PowerShell scripts for performing installation of Chef Client for Azure Roles.</description>
|
||||
<tags>Online-Media-Publishing MS-Internal-Only Azure Installation Deployment SDK</tags>
|
||||
<releaseNotes>
|
||||
0.1.7:
|
||||
- Terminate the Chef-Client processes if the service fails to stop in the allotted time.
|
||||
0.1.6:
|
||||
- Write Azure Role Environment information into an Ohai hints file, where the built in Azure Ohai plug-in can read from.
|
||||
0.1.5:
|
||||
- Added Role and Environment to be cscfg configurable. ChefClient_ServerUrl, ChefClient_Role,
|
||||
and ChefClient_Environment are now configurable from loud service config updates.
|
||||
- Add a set instance busy check file and configurable path in ChefClient_SetBusyCheck
|
||||
0.1.4:
|
||||
- Added support for deploying the node-based encrypted_data_bag_secret.
|
||||
0.1.3:
|
||||
- Removed Client MSI from package so it meets size requirements for MS-NuGet and NuGet.
|
||||
0.1.2:
|
||||
- Update to client to create base folder structure and PSModulePath.
|
||||
0.1.1:
|
||||
- BugFix:Upon OS update, client service is not reinstalled.
|
||||
0.1.0:
|
||||
- Initial Release
|
||||
See http://aka.ms/msompinstallationsdk for complete release history.
|
||||
Join the ampdmitalk DG to ask questions and take part in the deployment and monitoring community.
|
||||
</releaseNotes>
|
||||
<dependencies>
|
||||
<dependency id="Microsoft.OnlinePublishing.InstallationSDK" version="1.1.0"/>
|
||||
</dependencies>
|
||||
<frameworkAssemblies>
|
||||
<frameworkAssembly assemblyName="System.ServiceProcess"/>
|
||||
<frameworkAssembly assemblyName="System.Management"/>
|
||||
</frameworkAssemblies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\Nuget\Install.ps1" target="tools" />
|
||||
<!-- InstallationSDK.ChefClientInstaller Module -->
|
||||
<file src="..\Modules\InstallationSDK.ChefClientInstaller\bin\InstallationSDK.ChefClientInstaller\InstallationSDK.ChefClientInstaller.psm1" target="content\Deployment\Modules\InstallationSDK.ChefClientInstaller" />
|
||||
<file src="..\Modules\InstallationSDK.ChefClientInstaller\bin\InstallationSDK.ChefClientInstaller\InstallationSDK.ChefClientInstaller.psd1" target="content\Deployment\Modules\InstallationSDK.ChefClientInstaller" />
|
||||
<file src="..\Modules\InstallationSDK.ChefClientInstaller\bin\InstallationSDK.ChefClientInstaller\resources\Readme.txt" target="content\Deployment\Modules\InstallationSDK.ChefClientInstaller\resources" />
|
||||
<file src="..\Modules\InstallationSDK.ChefClientInstaller\bin\InstallationSDK.ChefClientInstaller\code\*.*" target="content" />
|
||||
<file src="..\Modules\InstallationSDK.ChefClientInstaller\bin\InstallationSDK.ChefClientInstaller\script\*.*" target="content\Deployment" />
|
||||
</files>
|
||||
</package>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Microsoft.OnlinePublishing.InstallationSDK</id>
|
||||
<version>1.1.0</version>
|
||||
<title>Microsoft.OnlinePublishing.InstallationSDK</title>
|
||||
<authors>ampdmi@microsoft.com</authors>
|
||||
<owners>ampdmi@microsoft.com</owners>
|
||||
<projectUrl>http://aka.ms/msompinstallationsdk</projectUrl>
|
||||
<description>PowerShell scripts for performing service installation tasks in an Azure Cloud Service.</description>
|
||||
<tags>Online-Media-Publishing MS-Internal-Only Azure Installation Deployment SDK</tags>
|
||||
<releaseNotes>
|
||||
1.1.0:
|
||||
- Added the Get-CloudServiceConfigurationSettingValue for getting the value from the cscfg while running in Azure.
|
||||
1.0.0:
|
||||
- Initial Release
|
||||
|
||||
See http://aka.ms/msompinstallationsdk for complete release history.
|
||||
Join the ampdmitalk DG to ask questions and take part in the deployment and monitoring community.
|
||||
</releaseNotes>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\Nuget\Install.ps1" target="tools" />
|
||||
|
||||
<file src="..\Core\Main.ps1" target="content\Deployment\" />
|
||||
<file src="..\Core\Start.ps1" target="content\Deployment\" />
|
||||
<file src="..\Core\Start.cmd" target="content\Deployment\" />
|
||||
|
||||
<!-- InstallationSDK.AzureServiceRuntime Module -->
|
||||
<file src="..\Modules\InstallationSDK.AzureServiceRuntime\bin\InstallationSDK.AzureServiceRuntime\InstallationSDK.AzureServiceRuntime.psm1" target="content\Deployment\Modules\InstallationSDK.AzureServiceRuntime" />
|
||||
<file src="..\Modules\InstallationSDK.AzureServiceRuntime\bin\InstallationSDK.AzureServiceRuntime\InstallationSDK.AzureServiceRuntime.psd1" target="content\Deployment\Modules\InstallationSDK.AzureServiceRuntime" />
|
||||
</files>
|
||||
</package>
|
|
@ -1,5 +0,0 @@
|
|||
now = Time.new
|
||||
log_level :info
|
||||
log_location 'c:/chef/client_' + now.strftime("%Y%m%d") + '.log'
|
||||
cache_path 'c:\chef'
|
||||
client_key 'c:\chef\client.pem'
|
Загрузка…
Ссылка в новой задаче