Working in a very restrictive environment I have been forced to rely on tools which are already installed on my PC, in order to automate tasks, especially ones launched through SSH. My previous attempt was a Python one, using Fabric, however that was nixed due to the external requirements (Python + Fabric itself).
So the new one is much more basic, Powershell (pre-installed) and plink.exe (ssh equivalent, part of Putty, "graciously" provided by our infrastructure overlords).
I basically recreated the Python version, in a cruder form, by controlling the plink.exe process directly and redirecting input/output.
Without further ado, the culprits:
./spoc.ps1 - entry point
./powershell - scripts which do the "heavy lifting"
./configurations - scripts which contain just configuration variables
./commands - convenience commands used by the entry point
./spoc.ps1
param(
[String]$Environment = "local",
[String]$Application = "test-app",
[String]$Command = "scp",
[ValidateSet("All", "File", "Console", "None")]
[String]$LogOutput = "Console"
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$scriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
. "${scriptRoot}\powershell\common.ps1"
. "${scriptRoot}\powershell\package.ps1"
. "${scriptRoot}\powershell\oneshot.ps1"
$env:sshUser = getUser
$env:logOutput = "Console"
##- DynamicParameter.
# Parameter with set validation based on an array provided at runtime.
function DynamicParameter {
param (
$name,
$completionValues
)
$attributeCollection = New-Object Collections.ObjectModel.Collection[System.Attribute]
$parameterAttribute = New-Object Management.Automation.ParameterAttribute
$parameterAttribute.Mandatory = $true
$attributeCollection.Add($parameterAttribute)
$validateSetAttribute = New-Object Management.Automation.ValidateSetAttribute($completionValues)
$attributeCollection.Add($validateSetAttribute)
$runtimeParameter = New-Object `
Management.Automation.RuntimeDefinedParameter($name, [string], $attributeCollection)
return $runtimeParameter
}
#-##
##- Spoc.
function Spoc {
##- Parameters.
[CmdletBinding()]
param (
[ValidateSet("All", "File", "Console", "None")]
[String]$LogOutput = "Console"
)
DynamicParam {
$runtimeParameters = New-Object Management.Automation.RuntimeDefinedParameterDictionary
$environmentCompletions = $(Get-ChildItem -Path ".\configurations" -Directory | Select-Object -ExpandProperty Name)
$environmentParameter = DynamicParameter "Environment" $environmentCompletions
$runtimeParameters.Add("Environment", $environmentParameter)
$applicationCompletions = $(Get-ChildItem -Path ".\configurations\test" | Select-Object -ExpandProperty Name | % { $_.replace(".ps1", "") })
$applicationCompletions += "test-app"
$applicationCompletions += "test-app-zip"
$applicationParameter = DynamicParameter "Application" $applicationCompletions
$runtimeParameters.Add("Application", $applicationParameter)
$commandCompletions = $(Get-ChildItem -Path ".\commands\*.ps1" | Select-Object -ExpandProperty Name | % { $_.replace(".ps1", "") })
$commandParameter = DynamicParameter "Command" $commandCompletions
$runtimeParameters.Add("Command", $commandParameter)
return $runtimeParameters
}
begin {
$Environment = $PsBoundParameters["Environment"]
$Application = $PsBoundParameters["Application"]
$Command = $PsBoundParameters["Command"]
}
#-##
process {
##- Parameter warnings.
if($Environment -eq "local") {
Warning "No environment parameter provided, using default value: local."
}
if($Application -eq "test-app") {
Warning "No application parameter provided, using default value: test-app."
}
if($Command -eq "scp") {
Warning "No command parameter provided, using default value: scp."
}
#-##
$env:sshUser = getUser
$env:password = getPassword
$logTargets = @("All", "File", "Console", "None")
$env:logOutput = $LogOutput
. "${scriptRoot}\configurations\${Environment}\${Application}.ps1"
Invoke-Expression "${scriptRoot}\commands\${Command}.ps1"
}
}
#-##
if(!($MyInvocation.InvocationName -eq ".")) {
Spoc -Environment $Environment -Application $Application -Command $Command -LogOutput $LogOutput
}
./powershell/common.ps1
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
##- Logging functions.
function global:Write {
param (
[Parameter(Mandatory)]
[string]$logLevel,
[Parameter(Mandatory)]
[String]$message
)
$messageTime = $(Get-Date -format "HH:mm:ss dd.MM.yyyy")
$color = "Gray"
if($logLevel -eq "warning") {
$color = "Yellow"
}
if($logLevel -eq "error") {
$color = "Red"
}
if(($env:logOutput -eq "All") -or ($env:logOutput -eq "Console")) {
Write-Host -ForegroundColor $color $message
}
if(($env:logOutput -eq "All") -or ($env:logOutput -eq "File")) {
Write-Output "[${logLevel}][${messageTime}]${message}" | Out-File -Append "Z:\work\tmp\launcher.txt"
}
}
function global:Info {
##- Parameters.
param (
[Parameter(Mandatory)]
[AllowEmptyString()]
[String]$message
)
#-##
global:Write "info" $message
}
function global:Warning {
##- Parameters.
param (
[Parameter(Mandatory)]
[AllowEmptyString()]
[String]$message
)
#-##
global:Write "warning" $message
}
function global:Error {
##- Parameters.
param (
[Parameter(Mandatory)]
[AllowEmptyString()]
[String]$message
)
#-##
global:Write "error" $message
}
function global:ErrorExit {
##- Parameters.
param (
[Parameter(Mandatory)]
[AllowEmptyString()]
[String]$message
)
#-##
global:Error $message
throw
}
#-##
##- Environment, user, password.
function getUser() {
return "${env:USERNAME}a"
}
function getPassword() {
$password = Read-Host -Prompt "Password" -AsSecureString
$password = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($password)
return $password
}
#-##
##- BaseRun.
function BaseRun
{
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$hostname,
[Parameter(Mandatory)]
[String]$command,
[String]$arguments
)
#-##
##- Process info.
$procInfo = New-Object System.Diagnostics.ProcessStartInfo
$procInfo.RedirectStandardOutput = $true
$procInfo.RedirectStandardError = $true
$procInfo.RedirectStandardInput = $true
$procInfo.FileName = $command
$procInfo.Arguments = $arguments
$procInfo.UseShellExecute = $false
#-##
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $procInfo
$global:hostname = $hostname
$global:outputBuffer = New-Object System.Text.StringBuilder
try {
##- Register output and error event handlers.
Register-ObjectEvent -InputObject $process `
-EventName OutputDataReceived -SourceIdentifier processOutputDataReceived `
-Action {
$data = $EventArgs.data
if($data -ne $null) {
if($data -notmatch "\[sudo\] password for.*") {
$outputBuffer.Append("${data}`n")
Info "[${hostname}][output] ${data}"
}
}
} | Out-Null
Register-ObjectEvent -InputObject $process `
-EventName ErrorDataReceived -SourceIdentifier processErrorDataReceived `
-Action {
$data = $EventArgs.data
if($data -ne $null) {
$outputBuffer.Append("${data}`n")
Error "[${hostname}][error] ${data}"
}
} | Out-Null
#-##
[void]$process.Start()
##- Input password.
# Only input the password for plink.exe (non-local execution)
# or for pscp.exe (local execution of scp).
if (($hostname -ne "local") -or ($command -match "pscp.exe")) {
if(!(Test-Path Env:\sshUser)) {
ErrorExit "No password provided, set `$env:password"
}
$inputStream = $process.StandardInput
# A slightly longer timeout is needed to make sure that the app was started.
Start-Sleep -m 2000
$inputStream.Write("${env:password}`n")
$inputStream.Close()
}
#-##
$process.BeginOutputReadLine()
$process.BeginErrorReadLine()
$process.WaitForExit()
}
finally {
Unregister-Event -SourceIdentifier processOutputDataReceived
Unregister-Event -SourceIdentifier processErrorDataReceived
}
# Return both the exit code and the command output.
$process.ExitCode
$outputBuffer.ToString()
}
#-##
##- LocalRun.
function LocalRun {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$command,
[bool]$captureOutput = $false
)
#-##
Info "[local][command] $command"
$commandComponents = $command -split " "
$command = $commandComponents[0]
if($commandComponents.Count -gt 2) {
$arguments = $commandComponents[1..$($commandComponents.Count - 1)] -join " "
} else {
$arguments = ""
}
$baseRunResult = BaseRun "local" $command $arguments
if ($baseRunResult[0] -ne 0) {
Start-Sleep -m 1000
ErrorExit "Execution stopped due to an error, check the command output."
}
if($captureOutput -eq $true) {
return $baseRunResult[1]
}
}
#-##
##- Run.
function Run {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$sshHostname,
[Parameter(Mandatory)]
[String]$command,
[bool]$captureOutput = $false
)
#-##
Info "[${sshHostname}][command] $command"
$initialLogOutput = $env:logOutput
# Silence the output so we don't echo the password.
$env:logOutput = "None"
# Dummy plink connection to check the connectivity, password, etc.
$plink = "C:\Tools\PuTTY\plink.exe"
$plinkNonInteractiveArgs = "-batch -v -pw ${env:password}"
$plinkInteractiveArgs = "-l ${env:sshUser} -t ${sshHostname} whoami"
$plinkArguments = "${plinkNonInteractiveArgs} ${plinkInteractiveArgs}"
$sshCheck = BaseRun $sshHostname $plink $plinkArguments
$env:logOutput = $initialLogOutput
$lastLine = $($sshCheck -split "`n")[-2]
if($lastLine -match "Host does not exist") {
ErrorExit "Cannot connect to ${sshHostname}, host not found."
}
if($lastLine -match "Disconnected: User aborted at host key verification") {
Error "Cannot authenticate to ${sshHostname}, server key not accepted."
ErrorExit "Run ${plink} ${plinkInteractiveArgs} and accept the key."
}
if($lastLine -match "Disconnected: Unable to authenticate") {
ErrorExit "Cannot authenticate to ${sshHostname}, wrong password."
}
$baseRunResult = BaseRun $sshHostname "C:\Tools\PuTTY\plink.exe" `
"-batch -l ${env:sshUser} -pw ${env:password} -t ${sshHostname} ${command}"
if ($baseRunResult[0] -ne 0) {
Start-Sleep -m 1000
ErrorExit "Execution stopped due to an error, check the command output."
}
if($captureOutput -eq $true) {
return $baseRunResult[1]
}
}
#-##
##- RunAsUser.
function RunAsUser {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$sshHostname,
[Parameter(Mandatory)]
[String]$applicationUser,
[Parameter(Mandatory)]
[String]$command,
[bool]$captureOutput = $false
)
#-##
$command = "sudo su - ${applicationUser}<<END`n${command}`nEND"
$runResult = Run $sshHostname $command $captureOutput
if($captureOutput -eq $true) {
return $runResult
}
}
#-##
##- Command line functions.
function Local-Scp {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$fileToCopy,
[Parameter(Mandatory)]
[String]$sourceServer,
[Parameter(Mandatory)]
[String]$sourceFolder,
[Parameter(Mandatory)]
[String]$targetFolder,
[bool]$captureOutput = $false
)
#-##
$pscp = "C:\Tools\PuTTY\pscp.exe"
$pscpArguments = "${env:sshUser}@${sourceServer}:${sourceFolder}/${fileToCopy} ${targetFolder}/${fileToCopy}"
$localRunResult = LocalRun "${pscp} ${pscpArguments}" $captureOutput
if($captureOutput -eq $true) {
return $localRunResult
}
}
function Scp-File {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$fileToCopy,
[Parameter(Mandatory)]
[String]$sourceServer,
[Parameter(Mandatory)]
[String]$sourceFolder,
[Parameter(Mandatory)]
[String]$targetServer,
[Parameter(Mandatory)]
[String]$targetFolder,
[bool]$captureOutput = $false
)
#-##
$runResult = Run $targetServer `
"scp ${sourceServer}:${sourceFolder}/${fileToCopy} ${targetFolder}" $captureOutput
if($captureOutput -eq $true) {
return $runResult
}
}
function Ssh-Command {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$sshHostname,
[Parameter(Mandatory)]
[String]$command,
[bool]$captureOutput = $false
)
#-##
$runResult = Run $sshHostname $command $captureOutput
if($captureOutput -eq $true) {
return $runResult
}
}
function Ssh-CommandAsUser {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$sshHostname,
[Parameter(Mandatory)]
[String]$applicationUser,
[Parameter(Mandatory)]
[String]$command,
[bool]$captureOutput = $false
)
#-##
$runResult = RunAsUser $sshHostname $applicationUser $command $captureOutput
if($captureOutput -eq $true) {
return $runResult
}
}
#-##
./powershell/package.ps1
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
##- Scp.
function Scp {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$fileToCopy,
[Parameter(Mandatory)]
[String]$sourceServer,
[Parameter(Mandatory)]
[String]$sourceFolder,
[Parameter(Mandatory)]
[String]$targetServer,
[Parameter(Mandatory)]
[String]$targetFolder,
[Parameter(Mandatory)]
[String]$targetUser
)
#-##
Info "Starting to scp."
$intermediaryServer = "dummy-server"
# Short server name, used as a subfolder in /data/packages on ldps101.
# Example: lcob, lbat, etc.
$serverFolder = $($targetServer -split "\.")[0] -replace "[0-9]*", ""
$intermediaryFolder = "/data/packages/${serverFolder}/${targetUser}"
Ssh-Command $intermediaryServer "mkdir -pv ${intermediaryFolder}"
Scp-File $fileToCopy $sourceServer $sourceFolder $intermediaryServer $intermediaryFolder
Ssh-Command $intermediaryServer "chmod -v ugo+rwx ${intermediaryFolder}/${fileToCopy}"
$scpTime = $(Get-Date -format yyyyMMdd)
$targetTmpFolder = "/tmp/${serverFolder}/${targetUser}/${scpTime}"
Ssh-Command $targetServer "mkdir -pv ${targetTmpFolder}"
Scp-File $fileToCopy $intermediaryServer $intermediaryFolder $targetServer $targetTmpFolder
Ssh-CommandAsUser $targetServer $targetUser "mkdir -pv ${targetFolder}"
Ssh-CommandAsUser $targetServer $targetUser "cp -v ${targetTmpFolder}/${fileToCopy} ${targetFolder}"
Ssh-Command $targetServer "rm -rvf ${targetTmpFolder}"
Info "Finished scping."
}
#-##
##- Backup.
function Backup {
##- Parameters.
param(
[Parameter(Mandatory)]
[String]$installationFolder,
[Parameter(Mandatory)]
[String]$newArchive,
[Parameter(Mandatory)]
[String]$exclusions,
[Parameter(Mandatory)]
[String]$applicationUser,
[Parameter(Mandatory)]
[String]$targetServer
)
#-##
Info "Starting to backup."
$tarListCommand = "tar --exclude=`"*/*`" -tvf ${installationFolder}/package-repo/${newArchive}"
$zipListCommand = "zipinfo -1 ${installationFolder}/package-repo/${newArchive} -x `"*/**`""
$archiveInfo = @{
".tar" = @("tar -cvf", $tarListCommand);
".tar.gz" = @("tar -czvf", $tarListCommand);
".tar.bz2" = @("tar -cjvf", $tarListCommand);
".zip" = @("zip -r", $zipListCommand)
}
$index = 0
foreach ($archiveType in $archiveInfo.GetEnumerator()) {
if ($newArchive.EndsWith($archiveType.Name)) {
$archiveListCommand = $archiveType.Value[1]
$newArchiveBasename = $newArchive -replace $archiveType.Name, ""
$archiveFormat = $archiveType.Name
$archiveCommand = $archiveType.Value[0]
} else {
$index += 1
}
}
if($index -ge $archiveInfo.Count) {
ErrorExit "Unsupported archive format: ${newArchive}. Supported formats: tar, tar.gz, tar.bz2, zip."
}
$archiveTime = $(Get-Date -format yyyyMMdd)
$archiveName = "${newArchiveBasename}_${archiveTime}.bak${archiveFormat}"
$archiveListOutput = Ssh-CommandAsUser $targetServer $applicationUser $archiveListCommand $true
$installationFolderListOutput = Ssh-CommandAsUser `
$targetServer $applicationUser "ls -p1 ${installationFolder}" $true
# The files to archive are files that are both in the new tar and in the current installation.
# We don't archive excluded files (temporary files, input files, output files, in general).
$toArchiveList = ""
foreach($archiveListFile in $archiveListOutput.Split("`r`n")) {
$archiveListFile = $archiveListFile.Split(" ")[-1]
if(($installationFolderListOutput.Split("`r`n") -contains $archiveListFile) -and
($exclusions.Split(",") -notcontains $archiveListFile)) {
$toArchiveList += "$archiveListFile "
}
}
if ($toArchiveList -ne " ") {
$archivePath = "${installationFolder}/package-repo/${archiveName}"
$archiveCommand = "${archiveCommand} ${archivePath} ${toArchiveList}"
Ssh-CommandAsUser $targetServer $applicationUser "cd ${installationFolder}; $archiveCommand"
} else {
Warning "Not archiving anything as the list of files to archive was empty."
}
$oldBackupsCommand = "ls -1rt ${installationFolder}/package-repo | grep ${Application}"
$oldBackups = Ssh-CommandAsUser $targetServer $applicationUser $oldBackupsCommand $true
$oldBackups = $oldBackups -replace "${env:sshUser}'s password:", ""
$initialOldBackupsList = $oldBackups.Split("`n")
# Remove empty lines in the output.
$oldBackupsList = @()
foreach ($oldBackup in $initialOldBackupsList) {
if($oldBackup -ne "") {
$oldBackupsList += $oldBackup
}
}
if($oldBackupsList.Count -gt 3) {
# Ignore the last 2 elements: current backup and archive for the new deployment.
$backupsToDelete = $oldBackupsList[0..($oldBackupsList.Count - 3)]
$cdCommand = "cd ${installationFolder}/package-repo"
#Ssh-CommandAsUser $targetServer $applicationUser "${cdCommand}; rm -v ${backupsToDelete}"
}
Info "Finished backing up."
}
#-##
##- Clean.
function Clean {
##- Parameters.
param(
[Parameter(Mandatory)]
$targetFolder,
[Parameter(Mandatory)]
$applicationUser,
[Parameter(Mandatory)]
$targetServer
)
#-##
Info "Starting to clean."
$cleanCommand = "rm -rfv ${targetFolder}"
Ssh-CommandAsUser $targetServer $applicationUser $cleanCommand
Info "Finished cleaning."
}
#-##
##- Unpack.
function Unpack {
##- Parameters.
param(
[Parameter(Mandatory)]
$archiveName,
[Parameter(Mandatory)]
$installationFolder,
[Parameter(Mandatory)]
$applicationUser,
[Parameter(Mandatory)]
$targetServer
)
#-##
Info "Starting to unpack."
$archiveInfo = @{
".tar" = @("tar -xvf", "-C");
".tar.gz" = @("tar -xzvf", "-C");
".tar.bz2" = @("tar -xjvf", "-C");
".zip" = @("unzip -o", "-d")
}
$index = 0
foreach ($archiveType in $archiveInfo.GetEnumerator()) {
if ($archiveName.EndsWith($archiveType.Name)) {
$unpackCommand = $archiveType.Value[0]
$unpackFolderFlag = $archiveType.Value[1]
$archiveUnpackCommand = "${unpackCommand} " +
"${installationFolder}/package-repo/${archiveName} " +
"${unpackFolderFlag} ${installationFolder}"
} else {
$index += 1
}
}
if($index -ge $archiveInfo.Count) {
ErrorExit "Unsupported archive format: ${archiveName}. Supported formats: tar, tar.gz, tar.bz2, zip."
}
Ssh-CommandAsUser $targetServer $applicationUser $archiveUnpackCommand
Info "Finished unpacking."
}
#-##
./powershell/oneshot.ps1
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
##- Download-Folder.
function Download-Folder {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$sourceServer,
[Parameter(Mandatory)]
[String]$sourceUser,
[Parameter(Mandatory)]
[String]$sourceFolder,
[String]$exclusions = "dummy-exclusion",
[Parameter(Mandatory)]
[String]$targetFolder
)
#-##
Info "Starting to download folder."
$archiveTime = $(Get-Date -format yyyyMMdd)
$temporaryFolder = "/tmp/${sourceUser}${archiveTime}"
Ssh-CommandAsUser $sourceServer $sourceUser "mkdir -pv ${temporaryFolder}"
$archiveCommand = "tar -czvf ${temporaryFolder}/archive.tar.gz ${sourceFolder}"
Ssh-CommandAsUser $sourceServer $sourceUser $archiveCommand
Local-Scp "archive.tar.gz" $sourceServer $temporaryFolder $targetFolder
Ssh-CommandAsUser $sourceServer $sourceUser "rm -rvf ${temporaryFolder}"
Info "Finished downloading."
}
#-##
##- Setup-Cobol
function Setup-Cobol {
##- Parameters.
param (
[Parameter(Mandatory)]
[ValidateSet("test", "hom1", "hom2", "hom3")]
[String]$environment,
[Parameter(Mandatory)]
[String]$cobolPackageInfo
)
#-##
Info "Creating UC4 Cobol deployment package."
$cobolFolder = "T:\dummy-folder"
#$cobolFolder = "Z:\work\tmp\uc4"
$cobolCsv="${cobolFolder}\packages_deployment_UC4T.csv"
$environment = $environment.ToUpper()
$cobolDate = $(Get-Date -format yyyyMMdd)
$cobolPackageInfo = $cobolPackageInfo.Replace("date_of_delivery(YYYYMMDD)", $cobolDate)
$cobolPackageInfo += ";$environment"
$cobolPackageInfo = $cobolPackageInfo -replace "`r`n", ""
Info "Will write ${cobolPackageInfo} to ${cobolCsv}."
if(Test-Path $cobolCsv) {
ErrorExit "Cobol file already exists, aborting."
}
try {
New-Item -ItemType Directory $cobolFolder
} catch {
}
$encoding = New-Object Text.AsciiEncoding
$writer = New-Object IO.StreamWriter($cobolCsv, $false, $encoding)
$writer.Write("${cobolPackageInfo}`n")
$writer.Close()
Info "Wrote ${cobolPackageInfo} to ${cobolCsv}."
}
#-##
##- Create-Branch
function Create-Branch {
##- Parameters.
param (
[Parameter(Mandatory)]
[String]$branchName
)
#-##
Info "Creating SVN branch."
$env:sshUser = getUser
$env:password = getPassword
$sshHostname = "dummy-server"
$svnScript = "/home/dummy-user/utilities/svn.sh"
Ssh-Command -sshHostname $sshHostname -command "${svnScript} branch ${branchName} HEAD trunk"
Info "Finished creating SVN branch."
}
#-##
##- Install-Script
function Install-Script {
##- Parameters.
param (
[ValidateSet("dev", "test", "test2", "hom1", "hom2", "hom3", "sup", "prod")]
[String]$environment = "test",
[Parameter(Mandatory)]
[String]$project,
[String]$tnsString = "dummy-tns",
[String]$user = "designer",
[Parameter(Mandatory)]
[String]$archive
)
#-##
Info "Installing SQL script."
$env:password = getPassword
# The environment should actually be uppercase, especially the directories.
$environment = $environment.ToUpper()
if ($environment -eq "PROD") {
Warning "Running on production, are you sure you want to run the script?"
$production = Read-Host -Prompt "Enter `"PROD`" if you want to continue: "
if ($production -ne "PROD") {
ErrorExit "Production run cancelled by user."
}
}
$installDate = $(Get-Date -format yyyyMMdd)
$targetRootDir = "T:\dummy-z"
#$targetRootDir = "Z:\work\tmp"
$sourceRootDir = "Z:\Downloads"
$scriptDir = ${archive} -replace ".zip", ""
$scriptVersion = 1
$unversionedDir = "${targetRootDir}/${environment}/${project}/${installDate}/${scriptDir}"
$targetDir="${unversionedDir}_${scriptVersion}"
while (Test-Path "${unversionedDir}_${scriptVersion}") {
$scriptVersion += 1
$targetDir="${unversionedDir}_${scriptVersion}"
}
New-Item -ItemType Directory -Force -Verbose -Path $targetDir | Out-Null
$originalLocation = Get-Location
Set-Location -Verbose $targetDir
Move-Item -verbose "${sourceRootDir}/${archive}" "${targetDir}"
#Copy-Item -Verbose "${sourceRootDir}/${archive}" "${targetDir}"
Info "Unpacking SQL script archive."
unzip.exe -o $archive
if($LastExitCode -ne 0) {
ErrorExit "Unzip failed with exit code: ${LastExitCode}"
}
Info "Finished unpacking SQL script archive."
$installScripts = Get-ChildItem "*instal*.sql" | Select -expand Name
if(!$installScripts) {
ErrorExit "No SQL install scripts found, aborting."
}
foreach($installScript in $installScripts) {
Info "sqlplus ${user}/{env:password}@`"${tnsString}`" @${installScript}"
Write-Output exit | sqlplus.exe ${user}/${env:password}@"${tnsString}" @$installScript
if($LastExitCode -ne 0) {
ErrorExit "SqlPlus failed with exit code: ${LastExitCode}"
}
}
$installLogs = Get-ChildItem "*.log" | Select -expand Name
$timestampedLog = ""
$timestampedLogNames = ""
foreach($installLog in $installLogs) {
$timestampedLog = $installLog -replace ".log", ""
$timestampedLog += "${environment}_${installDate}_${scriptVersion}.log"
Move-Item -Verbose $installLog $timestampedLog
$timestampedLogNames += $timestampedLog
}
# Put log file name in the Windows clipboard.
Write-Output $timestampedLogNames | clip.exe
# Open Windows Explorer with the log already selected.
try {
Get-Command explorer.exe | Out-Null
explorer.exe "/e,/select,`"${timestampedLog}`""
if($LastExitCode -ne 0) {
ErrorExit "Explorer failed with exit code: ${LastExitCode}"
}
} catch {
ErrorExit "Explorer not found?!?"
}
Set-Location -verbose $originalLocation
Info "Finished installing SQL script."
}
#-##
##- Wait
function Wait {
Info "Press any key to continue."
$host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown") | Out-Null
Info "Key pressed, continuing."
}
#-##
./configurations/local/test-app.ps1
$SOURCE_SERVER="dummy-server"
$ARCHIVE_NAME="test-app-1.0.0.tar.gz"
$APPLICATION_FOLDER="test-app"
$INSTALLATION_FOLDER="/home/dummy-user"
$INSTALLATION_SERVER="dummy-server"
$SU_USER="dummy-user"
# Configuration values for the scp command.
$SCP_FILE_TO_COPY=${ARCHIVE_NAME}
$SCP_SOURCE_FOLDER="${INSTALLATION_FOLDER}/todeploy"
$SCP_TARGET_FOLDER="${INSTALLATION_FOLDER}/package-repo"
$SCP_SOURCE_SERVER=${SOURCE_SERVER}
$SCP_TARGET_SERVER=${INSTALLATION_SERVER}
$SCP_TARGET_USER=${SU_USER}
# Configuration values for the archive command.
$BACKUP_INSTALLATION_FOLDER=${INSTALLATION_FOLDER}
$BACKUP_NEW_ARCHIVE=${ARCHIVE_NAME}
$BACKUP_EXCLUSIONS="dummy-exclusion"
$BACKUP_APPLICATION_USER=${SU_USER}
$BACKUP_TARGET_SERVER=${INSTALLATION_SERVER}
# Configuration values for the clean command.
$CLEAN_TARGET_FOLDER="${INSTALLATION_FOLDER}/${APPLICATION_FOLDER}"
$CLEAN_APPLICATION_USER=${SU_USER}
$CLEAN_TARGET_SERVER=${INSTALLATION_SERVER}
# Configuration values for the deploy command.
$UNPACK_INSTALLATION_FOLDER=${INSTALLATION_FOLDER}
$UNPACK_ARCHIVE_NAME=${ARCHIVE_NAME}
$UNPACK_APPLICATION_USER=${SU_USER}
$UNPACK_TARGET_SERVER=${INSTALLATION_SERVER}
./commands/scp.ps1
Scp $SCP_FILE_TO_COPY $SCP_SOURCE_SERVER $SCP_SOURCE_FOLDER `
$SCP_TARGET_SERVER $SCP_TARGET_FOLDER $SCP_TARGET_USER
./commands/backup.ps1
Backup $BACKUP_INSTALLATION_FOLDER $BACKUP_NEW_ARCHIVE $BACKUP_EXCLUSIONS `
$BACKUP_APPLICATION_USER $BACKUP_TARGET_SERVER
./commands/clean.ps1
Clean $CLEAN_TARGET_FOLDER $CLEAN_APPLICATION_USER $CLEAN_TARGET_SERVER
./commands/unpack.ps1
Unpack $UNPACK_ARCHIVE_NAME $UNPACK_INSTALLATION_FOLDER `
$UNPACK_APPLICATION_USER $UNPACK_TARGET_SERVER
./commands/deploy.ps1
Invoke-Expression ".\commands\scp.ps1"
Invoke-Expression ".\commands\backup.ps1"
Invoke-Expression ".\commands\unpack.ps1"
./commands/deploy.ps1
Invoke-Expression ".\commands\scp.ps1"
Invoke-Expression ".\commands\backup.ps1"
Invoke-Expression ".\commands\unpack.ps1"
./commands/clean-deploy.ps1
Invoke-Expression ".\commands\scp.ps1"
Invoke-Expression ".\commands\backup.ps1"
Invoke-Expression ".\commands\clean.ps1"
Invoke-Expression ".\commands\unpack.ps1"