Merge "HOT for MSSQL Server with unit tests"
This commit is contained in:
commit
063e6a0930
41
hot/Windows/MSSQLServer/MSSQL.ps1
Executable file
41
hot/Windows/MSSQLServer/MSSQL.ps1
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#ps1_sysnative
|
||||||
|
|
||||||
|
# Copyright 2014 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$moduleName = "MSSQL.psm1"
|
||||||
|
$cfnFolder = "C:\cfn"
|
||||||
|
$modulePath = Join-Path $cfnFolder $moduleName
|
||||||
|
Import-Module -Name $modulePath -DisableNameChecking -Force
|
||||||
|
|
||||||
|
|
||||||
|
$mssqlServiceUsername="mssql-service-username"
|
||||||
|
$mssqlServicePassword = "mssql-service-user-password"
|
||||||
|
$mssqlSaPassword = "mssql-sa-password"
|
||||||
|
$mssqlFeatures = "mssql-features"
|
||||||
|
$mssqlInstanceName = "mssql-instance-name"
|
||||||
|
$mssqlIsoUNCPath = "mssql_iso_unc_path"
|
||||||
|
$mssqlWaitConditionEndpoint = "mssql_wait_condition_endpoint"
|
||||||
|
$mssqlWaitConditionToken = "mssql_wait_condition_token"
|
||||||
|
|
||||||
|
Install-MSSQL -MssqlServiceUsername $mssqlServiceUsername `
|
||||||
|
-MssqlServicePassword $mssqlServicePassword `
|
||||||
|
-MssqlSaPassword $mssqlSaPassword `
|
||||||
|
-MssqlFeatures $mssqlFeatures `
|
||||||
|
-MssqlInstanceName $mssqlInstanceName `
|
||||||
|
-MssqlIsoUNCPath $mssqlIsoUNCPath `
|
||||||
|
-MssqlWaitConditionEndpoint $mssqlWaitConditionEndpoint `
|
||||||
|
-MssqlWaitConditionToken $MssqlWaitConditionToken
|
214
hot/Windows/MSSQLServer/MSSQL.psm1
Executable file
214
hot/Windows/MSSQLServer/MSSQL.psm1
Executable file
@ -0,0 +1,214 @@
|
|||||||
|
#ps1_sysnative
|
||||||
|
|
||||||
|
# Copyright 2014 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$modulePath = "heat-powershell-utils.psm1"
|
||||||
|
$currentLocation = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$fullPath = Join-Path $currentLocation $modulePath
|
||||||
|
Import-Module -Name $fullPath -DisableNameChecking -Force
|
||||||
|
|
||||||
|
$heatTemplateName = "MSSQL"
|
||||||
|
$sqlLogFile = Join-Path ${ENV:ProgramFiles} -ChildPath `
|
||||||
|
"\Microsoft SQL Server\110\Setup Bootstrap\Log\Summary.txt"
|
||||||
|
|
||||||
|
function Log {
|
||||||
|
param(
|
||||||
|
$message
|
||||||
|
)
|
||||||
|
LogTo-File -LogMessage $message -Topic $heatTemplateName
|
||||||
|
Log-HeatMessage $message
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install-RequiredFeatures {
|
||||||
|
param()
|
||||||
|
|
||||||
|
$windowsFeatures = @('NET-Framework-Core')
|
||||||
|
$installStatus = Install-WindowsFeatures $windowsFeatures
|
||||||
|
if ($installStatus.Reboot -eq $true) {
|
||||||
|
Log "System will reboot to finish install updates."
|
||||||
|
ExitFrom-Script $rebootAndReexecuteCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-MSSQLUser {
|
||||||
|
param(
|
||||||
|
$mssqlServiceUsername,
|
||||||
|
$mssqlServicePassword
|
||||||
|
)
|
||||||
|
|
||||||
|
Log "Adding the MSSQL user."
|
||||||
|
Add-WindowsUser $mssqlServiceUsername $mssqlServicePassword
|
||||||
|
}
|
||||||
|
|
||||||
|
function Copy-FilesLocal {
|
||||||
|
param(
|
||||||
|
$From
|
||||||
|
)
|
||||||
|
|
||||||
|
$copyLocal = ${ENV:Temp}
|
||||||
|
$fileName = Split-Path -Path $From -Leaf
|
||||||
|
$localPath = Join-Path -Path $copyLocal $fileName
|
||||||
|
Copy-Item -Force -Recurse -Path $From -Destination $localPath
|
||||||
|
Log ("Local iso path:" + $localPath)
|
||||||
|
return $localPath
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-MSSQLParameters {
|
||||||
|
param(
|
||||||
|
$MssqlServiceUsername,
|
||||||
|
$MssqlServicePassword,
|
||||||
|
$MssqlSaPassword,
|
||||||
|
$MssqlFeatures,
|
||||||
|
$MssqlInstanceName
|
||||||
|
)
|
||||||
|
|
||||||
|
$parameters = "/ACTION=install "
|
||||||
|
$parameters += "/Q "
|
||||||
|
$parameters += "/IACCEPTSQLSERVERLICENSETERMS=1 "
|
||||||
|
$parameters += "/INSTANCENAME=$MssqlInstanceName "
|
||||||
|
$parameters += "/FEATURES=$MssqlFeatures "
|
||||||
|
$parameters += "/SQLSYSADMINACCOUNTS=Admin "
|
||||||
|
$parameters += "/UpdateEnabled=1 "
|
||||||
|
$parameters += "/AGTSVCSTARTUPTYPE=Automatic "
|
||||||
|
$parameters += "/BROWSERSVCSTARTUPTYPE=Automatic "
|
||||||
|
$parameters += "/SECURITYMODE=SQL "
|
||||||
|
$parameters += "/SAPWD=$MssqlSaPassword "
|
||||||
|
$parameters += "/SQLSVCACCOUNT=.\$MssqlServiceUsername "
|
||||||
|
$parameters += "/SQLSVCPASSWORD=$MssqlServicePassword "
|
||||||
|
$parameters += "/SQLSVCSTARTUPTYPE=Automatic "
|
||||||
|
$parameters += "/NPENABLED=1 "
|
||||||
|
$parameters += "/TCPENABLED=1 /ERRORREPORTING=1"
|
||||||
|
|
||||||
|
return $parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-MSSQLError {
|
||||||
|
param()
|
||||||
|
|
||||||
|
$sqlErrorString = "Failed: see details below"
|
||||||
|
$errorsCount = (Select-String $sqlErrorString -Path $sqlLogFile).Length
|
||||||
|
if ($errorsCount -ne 0) {
|
||||||
|
Log "MSSQL log file has an error."
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-NetRules {
|
||||||
|
param()
|
||||||
|
Open-Port 80 "TCP" "HTTP"
|
||||||
|
Open-Port 443 "TCP" "HTTPS"
|
||||||
|
Open-Port 1434 "UDP" "SQL Browser"
|
||||||
|
Open-Port 135 "TCP" "SQL Debugger/RPC"
|
||||||
|
Open-Port 5355 "UDP" "Link Local Multicast Name Resolution"
|
||||||
|
|
||||||
|
netsh.exe firewall set multicastbroadcastresponse ENABLE
|
||||||
|
|
||||||
|
$sqlServerBinaryPath = Join-Path ${ENV:ProgramFiles} -ChildPath `
|
||||||
|
"Microsoft SQL Server\MSSQL11.MSSQL\MSSQL\Binn\sqlservr.exe"
|
||||||
|
New-NetFirewallRule -DisplayName "Allow TCP Sql Server Ports" `
|
||||||
|
-Direction Inbound -Action Allow -EdgeTraversalPolicy Allow `
|
||||||
|
-Protocol UDP -LocalPort 100-65000 -Program $sqlServerBinaryPath
|
||||||
|
New-NetFirewallRule -DisplayName "Allow TCP Sql Server Ports" `
|
||||||
|
-Direction Inbound -Action Allow -EdgeTraversalPolicy Allow `
|
||||||
|
-Protocol TCP -LocalPort 100-65000 -Program $sqlServerBinaryPath
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install-MSSQLInternal {
|
||||||
|
param(
|
||||||
|
$MssqlServiceUsername,
|
||||||
|
$MssqlServicePassword,
|
||||||
|
$MssqlSaPassword,
|
||||||
|
$MssqlFeatures,
|
||||||
|
$MssqlInstanceName,
|
||||||
|
$MssqlIsoUNCPath,
|
||||||
|
$MssqlWaitConditionEndpoint,
|
||||||
|
$MssqlWaitConditionToken
|
||||||
|
)
|
||||||
|
|
||||||
|
Log "Started MSSQL instalation."
|
||||||
|
|
||||||
|
Install-RequiredFeatures
|
||||||
|
|
||||||
|
Add-MSSQLUser $MssqlServiceUsername $MssqlServicePassword
|
||||||
|
|
||||||
|
$localIsoPath = Copy-FilesLocal $MssqlIsoUNCPath
|
||||||
|
Log "MSSQL ISO Mount."
|
||||||
|
$iso = Mount-DiskImage -PassThru $localIsoPath
|
||||||
|
|
||||||
|
$isoSetupPath = (Get-Volume -DiskImage $iso).DriveLetter + ":\setup.exe"
|
||||||
|
if (Test-Path $sqlLogFile) {
|
||||||
|
Remove-Item $sqlLogFile -Force
|
||||||
|
}
|
||||||
|
$parameters = Get-MSSQLParameters `
|
||||||
|
-MssqlServiceUsername $mssqlServiceUsername `
|
||||||
|
-MssqlServicePassword $mssqlServicePassword `
|
||||||
|
-MssqlSaPassword $mssqlSaPassword `
|
||||||
|
-MssqlFeatures $mssqlFeatures `
|
||||||
|
-MssqlInstanceName $mssqlInstanceName
|
||||||
|
ExecuteWith-Retry -Command {
|
||||||
|
param($isoSetupPath, $parameters)
|
||||||
|
Start-Process -Wait -FilePath $isoSetupPath `
|
||||||
|
-ArgumentList $parameters
|
||||||
|
} -Arguments @($isoSetupPath, $parameters)
|
||||||
|
|
||||||
|
Dismount-DiskImage -ImagePath $iso.ImagePath
|
||||||
|
Remove-Item $localIsoPath
|
||||||
|
|
||||||
|
if ((Get-MSSQLError) -eq $true) {
|
||||||
|
throw "Failed to install MSSQL Server."
|
||||||
|
}
|
||||||
|
Add-NetRules
|
||||||
|
|
||||||
|
$successMessage = "Finished MSSQL instalation."
|
||||||
|
Log $successMessage
|
||||||
|
Send-HeatWaitSignal -Endpoint $MssqlWaitConditionEndpoint `
|
||||||
|
-Message $successMessage -Success $true `
|
||||||
|
-Token $MssqlWaitConditionToken
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install-MSSQL {
|
||||||
|
param(
|
||||||
|
$MssqlServiceUsername,
|
||||||
|
$MssqlServicePassword,
|
||||||
|
$MssqlSaPassword,
|
||||||
|
$MssqlFeatures,
|
||||||
|
$MssqlInstanceName,
|
||||||
|
$MssqlIsoUNCPath,
|
||||||
|
$MssqlWaitConditionEndpoint,
|
||||||
|
$MssqlWaitConditionToken
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
Install-MSSQLInternal -MssqlServiceUsername $mssqlServiceUsername `
|
||||||
|
-MssqlServicePassword $mssqlServicePassword `
|
||||||
|
-MssqlSaPassword $mssqlSaPassword `
|
||||||
|
-MssqlFeatures $mssqlFeatures `
|
||||||
|
-MssqlInstanceName $mssqlInstanceName `
|
||||||
|
-MssqlIsoUNCPath $mssqlIsoUNCPath `
|
||||||
|
-MssqlWaitConditionEndpoint $mssqlWaitConditionEndpoint `
|
||||||
|
-MssqlWaitConditionToken $MssqlWaitConditionToken
|
||||||
|
} catch {
|
||||||
|
Log "Failed to install template."
|
||||||
|
Send-HeatWaitSignal -Endpoint $MssqlWaitConditionEndpoint `
|
||||||
|
-Message $_.Exception.Message -Success $false `
|
||||||
|
-Token $MssqlWaitConditionToken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-ModuleMember -Function * -ErrorAction SilentlyContinue
|
173
hot/Windows/MSSQLServer/MSSQL.yaml
Executable file
173
hot/Windows/MSSQLServer/MSSQL.yaml
Executable file
@ -0,0 +1,173 @@
|
|||||||
|
heat_template_version: 2013-05-23
|
||||||
|
|
||||||
|
description: >
|
||||||
|
Deploys a Microsoft SQL Server instance.
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
key_name:
|
||||||
|
description: Name of an existing keypair to encrypt the Admin password
|
||||||
|
type: string
|
||||||
|
|
||||||
|
flavor:
|
||||||
|
description: Id or name of an existing flavor
|
||||||
|
type: string
|
||||||
|
default: m1.small
|
||||||
|
|
||||||
|
image:
|
||||||
|
description: Id or name of an existing Windows image
|
||||||
|
type: string
|
||||||
|
|
||||||
|
public_network_id:
|
||||||
|
type: string
|
||||||
|
description: >
|
||||||
|
ID of an existing public network where a floating IP will be
|
||||||
|
allocated.
|
||||||
|
|
||||||
|
private_network_id:
|
||||||
|
type: string
|
||||||
|
description: Id of an existing private network
|
||||||
|
|
||||||
|
mssql_service_username:
|
||||||
|
type: string
|
||||||
|
default: mssqluser
|
||||||
|
description: >
|
||||||
|
The username under which the mssql service runs
|
||||||
|
|
||||||
|
mssql_service_user_password:
|
||||||
|
type: string
|
||||||
|
hidden: true
|
||||||
|
constraints:
|
||||||
|
- length: { min: 8, max: 64 }
|
||||||
|
- allowed_pattern: "(?=^.{6,255}$)((?=.*\\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*"
|
||||||
|
description: >
|
||||||
|
The password of the user under which the mssql service runs
|
||||||
|
|
||||||
|
mssql_sa_password:
|
||||||
|
type: string
|
||||||
|
hidden: true
|
||||||
|
description: >
|
||||||
|
The password of the sa mssql user
|
||||||
|
|
||||||
|
mssql_features:
|
||||||
|
type: string
|
||||||
|
default: >
|
||||||
|
SQLENGINE,ADV_SSMS
|
||||||
|
description: >
|
||||||
|
The mssql features to be installed
|
||||||
|
|
||||||
|
mssql_instance:
|
||||||
|
type: string
|
||||||
|
default: mssql
|
||||||
|
description: >
|
||||||
|
The mssql instance name
|
||||||
|
|
||||||
|
mssql_iso_unc_path:
|
||||||
|
type: string
|
||||||
|
description: >
|
||||||
|
The mssql iso file UNC path. It can be a local path or a network path.
|
||||||
|
|
||||||
|
mssql_max_timeout:
|
||||||
|
type: number
|
||||||
|
default: 3600
|
||||||
|
description: >
|
||||||
|
The maximum allowed time for the mssql instalation to finish.
|
||||||
|
|
||||||
|
resources:
|
||||||
|
server_port:
|
||||||
|
type: OS::Neutron::Port
|
||||||
|
properties:
|
||||||
|
network_id: { get_param: private_network_id }
|
||||||
|
|
||||||
|
server_floating_ip:
|
||||||
|
type: OS::Neutron::FloatingIP
|
||||||
|
depends_on: server_port
|
||||||
|
properties:
|
||||||
|
floating_network_id: { get_param: public_network_id }
|
||||||
|
port_id: { get_resource: server_port }
|
||||||
|
|
||||||
|
utils_module:
|
||||||
|
type: OS::Heat::SoftwareConfig
|
||||||
|
properties:
|
||||||
|
group: ungrouped
|
||||||
|
config: { get_file: heat-powershell-utils.psm1 }
|
||||||
|
|
||||||
|
mssql_module:
|
||||||
|
type: OS::Heat::SoftwareConfig
|
||||||
|
properties:
|
||||||
|
group: ungrouped
|
||||||
|
config: { get_file: MSSQL.psm1 }
|
||||||
|
|
||||||
|
mssql_main:
|
||||||
|
type: OS::Heat::SoftwareConfig
|
||||||
|
properties:
|
||||||
|
group: ungrouped
|
||||||
|
config:
|
||||||
|
str_replace:
|
||||||
|
template: { get_file: MSSQL.ps1 }
|
||||||
|
params:
|
||||||
|
mssql-service-username:
|
||||||
|
{ get_param: mssql_service_username }
|
||||||
|
mssql-service-user-password:
|
||||||
|
{ get_param: mssql_service_user_password }
|
||||||
|
mssql-sa-password:
|
||||||
|
{ get_param: mssql_sa_password }
|
||||||
|
mssql-features:
|
||||||
|
{ get_param: mssql_features }
|
||||||
|
mssql-instance-name:
|
||||||
|
{ get_param: mssql_instance }
|
||||||
|
mssql_iso_unc_path:
|
||||||
|
{ get_param: mssql_iso_unc_path }
|
||||||
|
mssql_wait_condition_endpoint:
|
||||||
|
{ get_attr: [ mssql_wait_condition_handle, endpoint ] }
|
||||||
|
mssql_wait_condition_token:
|
||||||
|
{ get_attr: [ mssql_wait_condition_handle, token ] }
|
||||||
|
|
||||||
|
mssql_init:
|
||||||
|
type: OS::Heat::MultipartMime
|
||||||
|
depends_on: mssql_wait_condition_handle
|
||||||
|
properties:
|
||||||
|
parts:
|
||||||
|
[ {
|
||||||
|
filename: "heat-powershell-utils.psm1",
|
||||||
|
subtype: "x-cfninitdata",
|
||||||
|
config: { get_resource: utils_module }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "MSSQL.psm1",
|
||||||
|
subtype: "x-cfninitdata",
|
||||||
|
config: { get_resource: mssql_module }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "cfn-userdata",
|
||||||
|
subtype: "x-cfninitdata",
|
||||||
|
config: { get_resource: mssql_main }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
mssql:
|
||||||
|
type: OS::Nova::Server
|
||||||
|
depends_on: [ server_port, mssql_init ]
|
||||||
|
properties:
|
||||||
|
image: { get_param: image }
|
||||||
|
flavor: { get_param: flavor }
|
||||||
|
key_name: { get_param: key_name }
|
||||||
|
networks:
|
||||||
|
- port: { get_resource: server_port }
|
||||||
|
user_data_format: RAW
|
||||||
|
user_data: { get_resource: mssql_init }
|
||||||
|
|
||||||
|
mssql_wait_condition:
|
||||||
|
type: OS::Heat::WaitCondition
|
||||||
|
depends_on: mssql_wait_condition_handle
|
||||||
|
properties:
|
||||||
|
count: 1
|
||||||
|
handle: { get_resource: mssql_wait_condition_handle }
|
||||||
|
timeout: { get_param: mssql_max_timeout }
|
||||||
|
|
||||||
|
mssql_wait_condition_handle:
|
||||||
|
type: OS::Heat::WaitConditionHandle
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
mssql_server_public_ip:
|
||||||
|
description: The MSSQL public IP address
|
||||||
|
value: { get_attr: [ server_floating_ip, floating_ip_address ] }
|
205
hot/Windows/MSSQLServer/Tests/MSSQL.Tests.ps1
Executable file
205
hot/Windows/MSSQLServer/Tests/MSSQL.Tests.ps1
Executable file
@ -0,0 +1,205 @@
|
|||||||
|
#ps1_sysnative
|
||||||
|
|
||||||
|
# Copyright 2014 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
$moduleName = "MSSQL"
|
||||||
|
$modulePath = "../MSSQL.psm1"
|
||||||
|
|
||||||
|
$currentLocation = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$fullPath = Join-Path $currentLocation $modulePath
|
||||||
|
|
||||||
|
Remove-Module -Name $moduleName -ErrorAction SilentlyContinue
|
||||||
|
Import-Module -Name $fullPath -DisableNameChecking -Force
|
||||||
|
|
||||||
|
InModuleScope $moduleName {
|
||||||
|
Describe "Test Add MSSQL User" {
|
||||||
|
Context "On success" {
|
||||||
|
Mock Log { return $true } -Verifiable
|
||||||
|
Mock Add-WindowsUser { return $true } -Verifiable
|
||||||
|
|
||||||
|
Add-MSSQLUser "fakeuser" "fakepassword"
|
||||||
|
|
||||||
|
It "should verify caled all mocks" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InModuleScope $moduleName {
|
||||||
|
Describe "Test Add Net Rules" {
|
||||||
|
Context "On success" {
|
||||||
|
Mock netsh.exe { return $true } -Verifiable
|
||||||
|
Mock New-NetFirewallRule { return $true } -Verifiable
|
||||||
|
|
||||||
|
Add-NetRules
|
||||||
|
|
||||||
|
It "should verify caled all mocks" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InModuleScope $moduleName {
|
||||||
|
Describe "Test Get MSSQL Error" {
|
||||||
|
Context "With errors" {
|
||||||
|
$fakeErrors = @("err1")
|
||||||
|
Mock Select-String { return $fakeErrors } -Verifiable
|
||||||
|
Mock Log { return $true } -Verifiable
|
||||||
|
|
||||||
|
$result = Get-MSSQLError
|
||||||
|
|
||||||
|
It "should return true" {
|
||||||
|
$result | Should Be $true
|
||||||
|
}
|
||||||
|
|
||||||
|
It "should verify caled all mocks" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "No errors" {
|
||||||
|
$fakeErrors = @()
|
||||||
|
Mock Select-String { return $fakeErrors } -Verifiable
|
||||||
|
|
||||||
|
$result = Get-MSSQLError
|
||||||
|
|
||||||
|
It "should return false" {
|
||||||
|
$result | Should Be $false
|
||||||
|
}
|
||||||
|
|
||||||
|
It "should verify caled all mocks" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InModuleScope $moduleName {
|
||||||
|
Describe "Test Install Required Features" {
|
||||||
|
Context "No reboot" {
|
||||||
|
$fakeStatus = @{"Reboot"=$false}
|
||||||
|
Mock Install-WindowsFeatures { return $fakeStatus } -Verifiable
|
||||||
|
|
||||||
|
Install-RequiredFeatures
|
||||||
|
|
||||||
|
It "should verify caled all mocks" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context "With reboot" {
|
||||||
|
$fakeStatus = @{"Reboot"=$true}
|
||||||
|
Mock Install-WindowsFeatures { return $fakeStatus } -Verifiable
|
||||||
|
Mock ExitFrom-Script { return $true } -Verifiable
|
||||||
|
Mock Log { return $true } -Verifiable
|
||||||
|
|
||||||
|
Install-RequiredFeatures
|
||||||
|
|
||||||
|
It "should verify caled all mocks" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InModuleScope $moduleName {
|
||||||
|
Describe "Test Install internal MSSQL" {
|
||||||
|
$mssqlServiceUsername="mssql-service-username";
|
||||||
|
$mssqlServicePassword = "mssql-service-user-password";
|
||||||
|
$mssqlSaPassword = "mssql-sa-password";
|
||||||
|
$mssqlFeatures = "mssql-features";
|
||||||
|
$mssqlInstanceName = "mssql-instance-name";
|
||||||
|
$mssqlIsoUNCPath = "mssql_iso_unc_path";
|
||||||
|
$mssqlWaitConditionEndpoint = "mssql_wait_condition_endpoint";
|
||||||
|
$mssqlWaitConditionToken = "mssql_wait_condition_token";
|
||||||
|
Context "On success" {
|
||||||
|
|
||||||
|
$cimInstance = New-CimInstance -ClassName "MSFT_DiskImage" `
|
||||||
|
-Namespace "root/Microsoft/Windows/Storage" `
|
||||||
|
-ClientOnly `
|
||||||
|
-Property @{"ImagePath"="fakePath"}
|
||||||
|
|
||||||
|
Mock Log { return $true } -Verifiable
|
||||||
|
Mock Install-RequiredFeatures { return $true } -Verifiable
|
||||||
|
Mock Add-MsSQLUser { return $true } -Verifiable
|
||||||
|
Mock Copy-FilesLocal { return $true } -Verifiable
|
||||||
|
Mock Mount-DiskImage { return $cimInstance } -Verifiable
|
||||||
|
Mock Get-Volume { return $true } -Verifiable
|
||||||
|
Mock Test-Path { return $true } -Verifiable
|
||||||
|
Mock Remove-Item { return $true } -Verifiable
|
||||||
|
Mock Get-MSSQLParameters { return $true } -Verifiable
|
||||||
|
Mock ExecuteWith-Retry { return $true } -Verifiable
|
||||||
|
Mock Dismount-DiskImage { return $true } -Verifiable
|
||||||
|
Mock Get-MssqlError { return $false } -Verifiable
|
||||||
|
Mock Add-NetRules { return $true } -Verifiable
|
||||||
|
Mock Send-HeatWaitSignal { return $true } -Verifiable
|
||||||
|
|
||||||
|
$result = Install-MSSQLInternal -MssqlServiceUsername $mssqlServiceUsername `
|
||||||
|
-MssqlServicePassword $mssqlServicePassword `
|
||||||
|
-MssqlSaPassword $mssqlSaPassword `
|
||||||
|
-MssqlFeatures $mssqlFeatures `
|
||||||
|
-MssqlInstanceName $mssqlInstanceName `
|
||||||
|
-MssqlIsoUNCPath $mssqlIsoUNCPath `
|
||||||
|
-MssqlWaitConditionEndpoint $mssqlWaitConditionEndpoint `
|
||||||
|
-MssqlWaitConditionToken $MssqlWaitConditionToken
|
||||||
|
|
||||||
|
It "should succeed" {
|
||||||
|
$result | Should Be $true
|
||||||
|
}
|
||||||
|
|
||||||
|
It "should verify caled all mocks" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context "On failure internal" {
|
||||||
|
|
||||||
|
Mock Install-MSSQLInternal { throw } -Verifiable
|
||||||
|
Mock Log { return $true } -Verifiable
|
||||||
|
Mock Send-HeatWaitSignal { return $true } -Verifiable
|
||||||
|
|
||||||
|
Install-MSSQL -MssqlServiceUsername $mssqlServiceUsername `
|
||||||
|
-MssqlServicePassword $mssqlServicePassword `
|
||||||
|
-MssqlSaPassword $mssqlSaPassword `
|
||||||
|
-MssqlFeatures $mssqlFeatures `
|
||||||
|
-MssqlInstanceName $mssqlInstanceName `
|
||||||
|
-MssqlIsoUNCPath $mssqlIsoUNCPath `
|
||||||
|
-MssqlWaitConditionEndpoint $mssqlWaitConditionEndpoint `
|
||||||
|
-MssqlWaitConditionToken $MssqlWaitConditionToken
|
||||||
|
|
||||||
|
It "should verify caled all mocks" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context "On succes internal" {
|
||||||
|
|
||||||
|
Mock Install-MSSQLInternal { return $true } -Verifiable
|
||||||
|
|
||||||
|
$result = Install-MSSQL -MssqlServiceUsername $mssqlServiceUsername `
|
||||||
|
-MssqlServicePassword $mssqlServicePassword `
|
||||||
|
-MssqlSaPassword $mssqlSaPassword `
|
||||||
|
-MssqlFeatures $mssqlFeatures `
|
||||||
|
-MssqlInstanceName $mssqlInstanceName `
|
||||||
|
-MssqlIsoUNCPath $mssqlIsoUNCPath `
|
||||||
|
-MssqlWaitConditionEndpoint $mssqlWaitConditionEndpoint `
|
||||||
|
-MssqlWaitConditionToken $MssqlWaitConditionToken
|
||||||
|
|
||||||
|
It "should be successful" {
|
||||||
|
Assert-VerifiableMocks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
369
hot/Windows/MSSQLServer/heat-powershell-utils.psm1
Executable file
369
hot/Windows/MSSQLServer/heat-powershell-utils.psm1
Executable file
@ -0,0 +1,369 @@
|
|||||||
|
#ps1_sysnative
|
||||||
|
|
||||||
|
# Copyright 2014 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
$rebotCode = 1001
|
||||||
|
$reexecuteCode = 1002
|
||||||
|
$rebootAndReexecuteCode = 1003
|
||||||
|
|
||||||
|
function Log-HeatMessage {
|
||||||
|
param(
|
||||||
|
[string]$Message
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host $Message
|
||||||
|
}
|
||||||
|
|
||||||
|
function ExitFrom-Script {
|
||||||
|
param(
|
||||||
|
[int]$ExitCode
|
||||||
|
)
|
||||||
|
|
||||||
|
exit $ExitCode
|
||||||
|
}
|
||||||
|
|
||||||
|
function ExecuteWith-Retry {
|
||||||
|
param(
|
||||||
|
[ScriptBlock]$Command,
|
||||||
|
[int]$MaxRetryCount=10,
|
||||||
|
[int]$RetryInterval=3,
|
||||||
|
[array]$Arguments=@()
|
||||||
|
)
|
||||||
|
|
||||||
|
$currentErrorActionPreference = $ErrorActionPreference
|
||||||
|
$ErrorActionPreference = "Continue"
|
||||||
|
|
||||||
|
$retryCount = 0
|
||||||
|
while ($true) {
|
||||||
|
try {
|
||||||
|
$res = Invoke-Command -ScriptBlock $Command `
|
||||||
|
-ArgumentList $Arguments
|
||||||
|
$ErrorActionPreference = $currentErrorActionPreference
|
||||||
|
return $res
|
||||||
|
} catch [System.Exception] {
|
||||||
|
$retryCount++
|
||||||
|
if ($retryCount -gt $MaxRetryCount) {
|
||||||
|
$ErrorActionPreference = $currentErrorActionPreference
|
||||||
|
throw $_.Exception
|
||||||
|
} else {
|
||||||
|
Write-Error $_.Exception
|
||||||
|
Start-Sleep $RetryInterval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Execute-Command {
|
||||||
|
param(
|
||||||
|
[ScriptBlock]$Command,
|
||||||
|
[array]$Arguments=@(),
|
||||||
|
[string]$ErrorMessage
|
||||||
|
)
|
||||||
|
|
||||||
|
$res = Invoke-Command -ScriptBlock $Command -ArgumentList $Arguments
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw $ErrorMessage
|
||||||
|
}
|
||||||
|
return $res
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install-WindowsFeatures {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[array]$Features,
|
||||||
|
[int]$RebootCode=$rebootAndReexecuteCode
|
||||||
|
)
|
||||||
|
|
||||||
|
$winVer = (Get-WmiObject -class Win32_OperatingSystem).Version.Split('.')
|
||||||
|
$isWinServer2008R2 = (($winVer[0] -eq 6) -and ($winVer[1] -eq 1))
|
||||||
|
if ($isWinServer2008R2 -eq $true) {
|
||||||
|
Import-Module ServerManager
|
||||||
|
}
|
||||||
|
|
||||||
|
$rebootNeeded = $false
|
||||||
|
foreach ($feature in $Features) {
|
||||||
|
if ($isWinServer2008R2 -eq $true) {
|
||||||
|
$state = ExecuteWith-Retry -Command {
|
||||||
|
Add-WindowsFeature -Name $feature -ErrorAction Stop
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$state = ExecuteWith-Retry -Command {
|
||||||
|
Install-WindowsFeature -Name $feature -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($state.Success -eq $true) {
|
||||||
|
if ($state.RestartNeeded -eq 'Yes') {
|
||||||
|
$rebootNeeded = $true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw "Install failed for feature $feature"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($rebootNeeded -eq $true) {
|
||||||
|
ExitFrom-Script $RebootCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function CopyFrom-SambaShare {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$SambaDrive,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$SambaShare,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$SambaFolder,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$FileName,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$Destination
|
||||||
|
)
|
||||||
|
|
||||||
|
$p = New-PSDrive -Name $SambaDrive -Root $SambaShare -PSProvider FileSystem
|
||||||
|
$samba = ($SambaDrive + ":\\" + $SambaFolder)
|
||||||
|
$localPath = "$Destination\$FileName"
|
||||||
|
if (!(Test-Path $localPath)) {
|
||||||
|
Copy-Item "$samba\$FileName" $Destination -Recurse
|
||||||
|
}
|
||||||
|
return $localPath
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function Unzip-File {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$ZipFile,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$Destination
|
||||||
|
)
|
||||||
|
|
||||||
|
$shellApp = New-Object -ComObject Shell.Application
|
||||||
|
$zipFileNs = $shellApp.NameSpace($ZipFile)
|
||||||
|
$destinationNs = $shellApp.NameSpace($Destination)
|
||||||
|
$destinationNs.CopyHere($zipFileNs.Items(), 0x4)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Download-File {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$DownloadLink,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$DestinationFile
|
||||||
|
)
|
||||||
|
|
||||||
|
$webclient = New-Object System.Net.WebClient
|
||||||
|
ExecuteWith-Retry -Command {
|
||||||
|
$webclient.DownloadFile($DownloadLink, $DestinationFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get-FileHash for Powershell versions less than 4.0 (SHA1 algorithm only)
|
||||||
|
function Get-FileSHA1Hash {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$Path,
|
||||||
|
[string]$Algorithm = "SHA1"
|
||||||
|
)
|
||||||
|
|
||||||
|
process
|
||||||
|
{
|
||||||
|
if ($Algorithm -ne "SHA1") {
|
||||||
|
throw "Unsupported algorithm: $Algorithm"
|
||||||
|
}
|
||||||
|
$fullPath = Resolve-Path $Path
|
||||||
|
$f = [System.IO.File]::OpenRead($fullPath)
|
||||||
|
$sham = $null
|
||||||
|
try {
|
||||||
|
$sham = New-Object System.Security.Cryptography.SHA1Managed
|
||||||
|
$hash = $sham.ComputeHash($f)
|
||||||
|
$hashSB = New-Object System.Text.StringBuilder `
|
||||||
|
-ArgumentList ($hash.Length * 2)
|
||||||
|
foreach ($b in $hash) {
|
||||||
|
$sb = $hashSB.AppendFormat("{0:x2}", $b)
|
||||||
|
}
|
||||||
|
return [PSCustomObject]@{ Algorithm="SHA1";
|
||||||
|
Hash=$hashSB.ToString().ToUpper();
|
||||||
|
Path=$fullPath }
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$f.Close()
|
||||||
|
if($sham) {
|
||||||
|
$sham.Clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Check-FileIntegrityWithSHA1 {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$File,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$ExpectedSHA1Hash
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($PSVersionTable.PSVersion.Major -lt 4) {
|
||||||
|
$hash = (Get-FileSHA1Hash -Path $File).Hash
|
||||||
|
} else {
|
||||||
|
$hash = (Get-FileHash -Path $File -Algorithm "SHA1").Hash
|
||||||
|
}
|
||||||
|
if ($hash -ne $ExpectedSHA1Hash) {
|
||||||
|
throw ("SHA1 hash not valid for file: $filename. " +
|
||||||
|
"Expected: $ExpectedSHA1Hash Current: $hash")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install-Program {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$DownloadLink,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$DestinationFile,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$ExpectedSHA1Hash,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$Arguments,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$ErrorMessage
|
||||||
|
)
|
||||||
|
|
||||||
|
Download-File $DownloadLink $DestinationFile
|
||||||
|
Check-FileIntegrityWithSHA1 $DestinationFile $ExpectedSHA1Hash
|
||||||
|
|
||||||
|
$p = Start-Process -FilePath $DestinationFile `
|
||||||
|
-ArgumentList $Arguments `
|
||||||
|
-PassThru `
|
||||||
|
-Wait
|
||||||
|
if ($p.ExitCode -ne 0) {
|
||||||
|
throw $ErrorMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
Remove-Item $DestinationFile
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-IniFileValue {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
|
||||||
|
[string]$Key,
|
||||||
|
[parameter()]
|
||||||
|
[string]$Section = "DEFAULT",
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$Value,
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
process
|
||||||
|
{
|
||||||
|
$Source = @"
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace PSCloudbase
|
||||||
|
{
|
||||||
|
public sealed class Win32IniApi
|
||||||
|
{
|
||||||
|
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
|
||||||
|
public static extern uint GetPrivateProfileString(
|
||||||
|
string lpAppName,
|
||||||
|
string lpKeyName,
|
||||||
|
string lpDefault,
|
||||||
|
StringBuilder lpReturnedString,
|
||||||
|
uint nSize,
|
||||||
|
string lpFileName);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool WritePrivateProfileString(
|
||||||
|
string lpAppName,
|
||||||
|
string lpKeyName,
|
||||||
|
StringBuilder lpString, // Don't use string, as Powershell replaces $null with an empty string
|
||||||
|
string lpFileName);
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll")]
|
||||||
|
public static extern uint GetLastError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"@
|
||||||
|
Add-Type -TypeDefinition $Source -Language CSharp
|
||||||
|
$retVal = [PSCloudbase.Win32IniApi]::WritePrivateProfileString($Section, $Key, $Value, $Path)
|
||||||
|
if (!$retVal -and [PSCloudbase.Win32IniApi]::GetLastError()) {
|
||||||
|
throw "Cannot set value in ini file: " + [PSCloudbase.Win32IniApi]::GetLastError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function LogTo-File {
|
||||||
|
param(
|
||||||
|
$LogMessage,
|
||||||
|
$LogFile="C:\cfn\userdata.log",
|
||||||
|
$Topic="general"
|
||||||
|
)
|
||||||
|
|
||||||
|
$date = Get-Date
|
||||||
|
$fullMessage = "$Date | $Topic | $LogMessage"
|
||||||
|
Add-Content -Path $logFile -Value $fullMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
function Open-Port($port, $protocol, $name) {
|
||||||
|
netsh.exe advfirewall firewall add rule name=$name dir=in action=allow `
|
||||||
|
protocol=$protocol localport=$port
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-WindowsUser {
|
||||||
|
param(
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$Username,
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$Password
|
||||||
|
)
|
||||||
|
|
||||||
|
NET.EXE USER $Username $Password '/ADD'
|
||||||
|
}
|
||||||
|
|
||||||
|
function Send-HeatWaitSignal {
|
||||||
|
param(
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$Endpoint,
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$Token,
|
||||||
|
$Message,
|
||||||
|
$Success=$true
|
||||||
|
)
|
||||||
|
|
||||||
|
$statusMap = @{
|
||||||
|
$true="SUCCESS";
|
||||||
|
$false="FAILURE"
|
||||||
|
}
|
||||||
|
|
||||||
|
$heatMessage = @{
|
||||||
|
"status"=$statusMap[$Success];
|
||||||
|
"reason"="Configuration script has been executed.";
|
||||||
|
"data"=$Message;
|
||||||
|
}
|
||||||
|
$headers = @{
|
||||||
|
"X-Auth-Token"=$Token;
|
||||||
|
"Accept"="application/json";
|
||||||
|
"Content-Type"= "application/json";
|
||||||
|
}
|
||||||
|
$heatMessageJSON = $heatMessage | ConvertTo-JSON
|
||||||
|
$result = Invoke-RestMethod -Method POST -Uri $Endpoint `
|
||||||
|
-Body $heatMessageJSON -Headers $headers
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-ModuleMember -Function *
|
Loading…
Reference in New Issue
Block a user