From e0817e271483c534fe98f4f6187a2d44fcd72a05 Mon Sep 17 00:00:00 2001 From: Etienne Pierrot Date: Thu, 17 Feb 2022 14:17:30 +0100 Subject: [PATCH 1/3] setup docker-compose.yml --- .netconfig | 2 +- docker-compose.yml | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 docker-compose.yml diff --git a/.netconfig b/.netconfig index 6ab504d..b14e7e0 100644 --- a/.netconfig +++ b/.netconfig @@ -1,4 +1,4 @@ [octopus] - serverUrl = https://etienne.octopus.app/ + serverUrl = http://localhost:8080/ projectName = test prefix = "PREFIX" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..81d79e7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3' +services: + octopus: + privileged: true + ports: + - "8080:8080" + - "10943:10943" + environment: + ADMIN_USERNAME: admin + ADMIN_EMAIL: octopusguides@gmail.com + ADMIN_PASSWORD: Password01! + ACCEPT_EULA: Y + DB_CONNECTION_STRING: Server=mssql,1433;Database=Octopus;User Id=SA;Password=Password01!;ConnectRetryCount=6 + CONNSTRING: Server=mssql,1433;Database=Octopus;User Id=SA;Password=Password01!;ConnectRetryCount=6 + MASTER_KEY: 6EdU6IWsCtMEwk0kPKflQQ== + image: octopusdeploy/octopusdeploy:latest + labels: + autoheal: true + depends_on: + - mssql + mssql: + environment: + ACCEPT_EULA: Y + SA_PASSWORD: Password01! + MSSQL_PID: Express + image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu + autoheal: + image: willfarrell/autoheal:latest + volumes: + - /var/run/docker.sock:/var/run/docker.sock \ No newline at end of file From 8b4ae067cb0e20a6246333ed2a19fea66a95c7ce Mon Sep 17 00:00:00 2001 From: Etienne Pierrot Date: Thu, 17 Feb 2022 14:18:28 +0100 Subject: [PATCH 2/3] renaming --- test/Octopus.Config.Exporter.Cli.Test.fsproj | 2 +- ...ocusVariableManagerTest.fs => OctopusVariableManagerTest.fs} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename test/{OctocusVariableManagerTest.fs => OctopusVariableManagerTest.fs} (98%) diff --git a/test/Octopus.Config.Exporter.Cli.Test.fsproj b/test/Octopus.Config.Exporter.Cli.Test.fsproj index 08f8d1e..bbb40ec 100644 --- a/test/Octopus.Config.Exporter.Cli.Test.fsproj +++ b/test/Octopus.Config.Exporter.Cli.Test.fsproj @@ -8,7 +8,7 @@ - + diff --git a/test/OctocusVariableManagerTest.fs b/test/OctopusVariableManagerTest.fs similarity index 98% rename from test/OctocusVariableManagerTest.fs rename to test/OctopusVariableManagerTest.fs index 660fe96..51d4f13 100644 --- a/test/OctocusVariableManagerTest.fs +++ b/test/OctopusVariableManagerTest.fs @@ -1,4 +1,4 @@ -module OctocusVariableManagerTest +module OctopusVariableManagerTest open FsUnit open OctocusVariableManager open Xunit From f39cd5c10d1bac7a02d6824854e4c14432cb0e34 Mon Sep 17 00:00:00 2001 From: Etienne Pierrot Date: Fri, 18 Feb 2022 18:32:00 +0100 Subject: [PATCH 3/3] add octopus scripting --- src/OctopusConnector.fs | 7 + test/Create-Key.ps1 | 26 +++ test/Octopus.Config.Exporter.Cli.Test.fsproj | 3 + test/Octopus.ps1 | 185 +++++++++++++++++++ test/OctopusConnectorTest.fs | 12 +- test/start-octopus.sh | 3 + 6 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 test/Create-Key.ps1 create mode 100644 test/Octopus.ps1 create mode 100755 test/start-octopus.sh diff --git a/src/OctopusConnector.fs b/src/OctopusConnector.fs index 8f1e4b8..758f747 100644 --- a/src/OctopusConnector.fs +++ b/src/OctopusConnector.fs @@ -1,4 +1,5 @@ module OctopusConnector +open System open Octopus.Client open Octopus.Client.Model open OctocusVariableManager @@ -59,3 +60,9 @@ type OctopusWrapper(octopusConfig :OctopusConfig) = projectResource.LifecycleId <- "Default Lifecycle" projectResource.IsDisabled <- false repo.Projects.Create projectResource |> ignore + + member this.CreateKey username password = + repo.Users.SignIn(username, password) + let user = repo.Users.GetCurrent() + let apiKey = repo.Users.CreateApiKey(user) + apiKey.ApiKey diff --git a/test/Create-Key.ps1 b/test/Create-Key.ps1 new file mode 100644 index 0000000..d6265da --- /dev/null +++ b/test/Create-Key.ps1 @@ -0,0 +1,26 @@ +. $PSScriptRoot\Octopus.ps1 + +Wait-ForOctopus + +#Creating a connection +$repository = Connect-ToOctopus "http://localhost:8080" + +#Creating login object +$LoginObj = New-Object Octopus.Client.Model.LoginCommand +$LoginObj.Username = "admin" +$LoginObj.Password = "Password01!" + +#Loging in to Octopus +$repository.Users.SignIn($LoginObj) + +#Getting current user logged in +$UserObj = $repository.Users.GetCurrent() + +#Creating API Key for user. This automatically gets saved to the database. +$ApiObj = $repository.Users.CreateApiKey($UserObj, "Terraform tests") + +#Save the API key so we can use it later +Set-Content -Path tests\octopus_api.txt -Value $ApiObj.ApiKey + +echo "TF_ACC=true" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append +echo "OCTOPUS_APIKEY=$($ApiObj.ApiKey)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append \ No newline at end of file diff --git a/test/Octopus.Config.Exporter.Cli.Test.fsproj b/test/Octopus.Config.Exporter.Cli.Test.fsproj index bbb40ec..1392ea1 100644 --- a/test/Octopus.Config.Exporter.Cli.Test.fsproj +++ b/test/Octopus.Config.Exporter.Cli.Test.fsproj @@ -13,6 +13,9 @@ + + + diff --git a/test/Octopus.ps1 b/test/Octopus.ps1 new file mode 100644 index 0000000..0ef1bbc --- /dev/null +++ b/test/Octopus.ps1 @@ -0,0 +1,185 @@ +Install-Module -Name PowershellOctopusClient -Force +Import-Module -Name PowershellOctopusClient + +function Wait-ForOctopus() { + $start = Get-Date + do { + Write-Host "Waiting for Octopus" + + # show the status of the containers + #$containers = & docker container ls + #Write-Host $containers + + # Get the logs of the octopus container + #$logs = & docker logs tests_octopus_1 + #Write-Host $logs + + sleep 5 + $now = Get-Date + $wait = New-Timespan -Start $start -End $now + if ($wait.TotalMinutes -ge 5) { + Write-Host "Gave up waiting" + break; + } + + } until (Test-Connection -IPv4 -ComputerName localhost -TCPPort 8080 -Quiet) +} + +function Get-CompleteExceptionMessage() { + param ( + [System.Management.Automation.ErrorRecord]$Exception, + [int]$limit = -1 + ) + + $msg = "" + + if ($null -ne $Exception) { + try { + $e = $Exception.Exception + $msg = $e.Message + while ($e.InnerException) { + $e = $e.InnerException + $msg += "`n" + $e.Message + } + + } catch { + # Ignore + } + } + + if ($limit -gt 0) { + $msg = $msg.SubString(0, [math]::min($limit,$msg.Length)) + } + + return $msg +} + + +function Connect-ToOctopus() { + param ( + [string]$url, + [string]$username = "admin", + [string]$password = "Password01!" + ) + try + { + $endpoint = New-Object Octopus.Client.OctopusServerEndpoint $url + $repository = New-Object Octopus.Client.OctopusRepository $endpoint + $LoginObj = New-Object Octopus.Client.Model.LoginCommand + $LoginObj.Username = $username + $LoginObj.Password = $password + Invoke-ScriptBlockWithRetries { $repository.Users.SignIn($LoginObj) } -FailureMessage "Failed to log into Octopus at $url" | Out-Null + return $repository + } catch { + Write-Error (Get-CompleteExceptionMessage $_) + throw $_ + } +} + +function Invoke-CommandWithRetries +{ + [CmdletBinding()] + param ( + [Parameter(Mandatory = $True)] + [string]$Command, + [Array]$Arguments, + [bool]$TrustExitCode = $True, + [int]$RetrySleepSeconds = 10, + [int]$MaxAttempts = 10, + [bool]$PrintCommand = $True, + [bool]$PrintOutput = $False, + [int[]]$AllowedReturnValues = @(), + [string]$ErrorMessage + ) + + Process + { + $attempt = 0 + while ($true) + { + Write-Host $(if ($PrintCommand) { "Executing: $Command $Arguments" } + else { "Executing command..." }) + + try + { + $output = & $Command $Arguments 2>&1 + if ($PrintOutput) { Write-Host $output } + + $stderr = $output | where { $_ -is [System.Management.Automation.ErrorRecord] } + if (($LASTEXITCODE -eq 0 -or $AllowedReturnValues -contains $LASTEXITCODE) -and ($TrustExitCode -or !($stderr))) + { + Write-Host "Command executed successfully" + return $output + } + + Write-Host "Command failed with exit code ($LASTEXITCODE) and stderr: $stderr" -ForegroundColor Yellow + } + catch + { + Write-Host "Command failed with exit code ($LASTEXITCODE), exception ($_) and stderr: $stderr" -ForegroundColor Yellow + } + + if ($attempt -eq $MaxAttempts) + { + $ex = new-object System.Management.Automation.CmdletInvocationException "All retry attempts exhausted $ErrorMessage" + $category = [System.Management.Automation.ErrorCategory]::LimitsExceeded + $errRecord = new-object System.Management.Automation.ErrorRecord $ex, "CommandFailed", $category, $Command + $psCmdlet.WriteError($errRecord) + return $output + } + + $attempt++; + Write-Host "Retrying test execution [#$attempt/$MaxAttempts] in $RetrySleepSeconds seconds..." + Start-Sleep -s $RetrySleepSeconds + } + } +} + +function Invoke-ScriptBlockWithRetries { + [CmdletBinding()] + param ( + [parameter(Mandatory, ValueFromPipeline)] + [ValidateNotNullOrEmpty()] + [scriptblock] $ScriptBlock, + [int] $RetryCount = 3, + [int] $TimeoutInSecs = 30, + [string] $SuccessMessage = "", + [string] $FailureMessage = "" + ) + + process { + $Attempt = 1 + + do { + try { + $PreviousPreference = $ErrorActionPreference + $ErrorActionPreference = 'Stop' + Invoke-Command -ScriptBlock $ScriptBlock -OutVariable Result | Out-Null + $ErrorActionPreference = $PreviousPreference + + # flow control will execute the next line only if the command in the scriptblock executed without any errors + # if an error is thrown, flow control will go to the 'catch' block + if (-not [string]::IsNullOrEmpty($SuccessMessage)) { + Write-Host "$SuccessMessage `n" + } + return $result + } + catch { + if ($Attempt -gt $RetryCount) { + if (-not [string]::IsNullOrEmpty($FailureMessage)) { + Write-Host "$FailureMessage! Error was $(Get-CompleteExceptionMessage $_). Total retry attempts: $RetryCount" + } + throw $_.exception + } + else { + if (-not [string]::IsNullOrEmpty($FailureMessage)) { + Write-Host "[$Attempt/$RetryCount] $FailureMessage. Error was $(Get-CompleteExceptionMessage $_). Retrying in $TimeoutInSecs seconds..." + } + Start-Sleep -Seconds $TimeoutInSecs + $Attempt = $Attempt + 1 + } + } + } + While ($true) + } +} \ No newline at end of file diff --git a/test/OctopusConnectorTest.fs b/test/OctopusConnectorTest.fs index 69e9c8a..5b39262 100644 --- a/test/OctopusConnectorTest.fs +++ b/test/OctopusConnectorTest.fs @@ -9,6 +9,8 @@ open OctocusVariableManager open TestHelper open System + + type TestCliArguments = | [] [] OctopusServer of server:string | [] [] OctopusApiKey of apiKey:string @@ -16,23 +18,29 @@ type TestCliArguments = interface IArgParserTemplate with member s.Usage = "" + + let [] type ``Connector``(output:ITestOutputHelper) = + let mutable octopusConfig let getOctopusConfig (parsedResult :ParseResults) = { Url = parsedResult.GetResult OctopusServer; ApiKey = parsedResult.GetResult OctopusApiKey; ProjectName = parsedResult.GetResult OctopusProject } + let originalConfig = ParseResult(true) |> getOctopusConfig let testConfig = {originalConfig with ProjectName = Guid.NewGuid().ToString().Substring(0, 8)} let octopusWrapper = new OctopusWrapper(testConfig) - do - octopusWrapper.CreateProject testConfig + do + let apiKey = octopusWrapper.CreateKey "admin" "Password01!" + let testConfig = {originalConfig with ApiKey = apiKey} + octopusWrapper.CreateProject testConfig [] let ``GetVariables should retrieve variables from octopus`` () = diff --git a/test/start-octopus.sh b/test/start-octopus.sh new file mode 100755 index 0000000..da095d2 --- /dev/null +++ b/test/start-octopus.sh @@ -0,0 +1,3 @@ + +docker-compose up --detach +