How to use output variable for replacing variables in config file - octopus-deploy

I have defined 3 steps in my deploy process:
Generate password (Run a Script)
Deploy admin API (Deploy an IIS Web Site)
Deploy public API (Deploy an IIS Web Site)
In step 1, I use following PowerShell script to generate random password:
[Reflection.Assembly]::LoadWithPartialName("System.Web")
$pwd = [System.Web.Security.Membership]::GeneratePassword(15,2)
Set-OctopusVariable -name "Password" -value $pwd -sensitive
There are some variables defined in the project under Variables section, and they correctly replace corresponding values in config files in step 2 and 3.
My question is, how to use Password variable from step 1 to replace corresponding fields in config files in steps 2 and 3?

You need to use the name of the step that the variable was created in when you retrieve it:
In the config file (in the package for steps 2 and 3) use a value like this:
#{Octopus.Action[NameOfStep1].Output.Password}

Related

How do I prevent users from accidentally deploying to too many tenants in Octopus?

Over the years we’ve had a few instances of Octopus Deploy users accidentally releasing a version to multiple environments, based on a tenant tag.
I usually tell users to check that the Tenant list under ‘Preview and customize’ only contains the 1 environment intended, but we still have some slip through where Octopus deploys to 20+ environments, which I then need to roll back.
Is there a way to alert users when there are more than 1 Tenant in the list, so they can sense check it before proceeding to deploy?
This can be achieved with a PowerShell script, which you add as a deployment step. The script will check for more than one tenant, and alert the user to perform manual intervention if it detects more than 1 target
To have the script work successfully, you must perform the following:
Set a Secret Project Variable named APIKey with the value of an API-Key with access to the deployments within that space.
Change the $octopusURL variable in the Script to match your Octopus Hostname.
Place the Script at the beginning of your deployment inside a "Run A Script" step.
Create a Manual Intervention step as the 2nd process step in your project with the run condition set to: #{Octopus.Action[Run a Script].Output.MultipleTenants}
If you decide to change the name of the step that contains the Script below, be sure to place the step name within the square brackets ([]) on the run condition variable.
$ErrorActionPreference = "Stop";
# Define working variables
$octopusURL = "http://OctopusURL"
$octopusAPIKey = "$APIKey"
$header = #{ "X-Octopus-ApiKey" = $octopusAPIKey }
$spaceId = $OctopusParameters["Octopus.Space.Id"]
# Get Release Deployment Data
$releaseData = Invoke-RestMethod -method GET -uri "$($octopusURL)/api/$($spaceId)/releases/#{Octopus.Release.Id}/deployments/" -Headers $header
# Get DateTime of Deployment Created
$checkDate = Get-Date $OctopusParameters["Octopus.Deployment.Created"] -format "yyyy-MM-dd HH:mm:ss"
write-host "The following tenants are being deployed to at $($checkDate):"
# Instantiate list
$tenantList = #()
# ForEach Deployment Item inside the Release do the following:
foreach($item in $releaseData.Items){
# Generate compatible DateTime for comparison with deployment Time
$date = Get-Date $item.Created.Substring(0,19) -format "yyyy-MM-dd HH:mm:ss"
# Check date equivalence, if equal then do the following:
if($date -eq $checkDate){
write-host "The tenant with ID: $($item.TenantId) is included in this deployment at $($date)."
# Add tenant to list
$tenantList = $TenantList + ($item.TenantId)
# If a release is redeployed, previous tenants may exist in the JSON items, this elseif generates the list of tenants deployed to previously, but not in THIS deployment:
}elseif($tenantList -notcontains $item.TenantId){
write-host "The tenant with ID: $($item.TenantId) is not included in this deployment as it was deployed at $($date)."
}
}
# Condition check list size, create output variable if more than one Tenant.
if($tenantList.Count -gt 1){
Set-OctopusVariable -name "MultipleTenants" -value "True"
}

Upload multiple files with one shortcut in PhpStorm

How can I upload a selection of files with a single shortcut in PhpStorm?
Ideally it uses the PhpStorm Deployment-mechanism, - but all answers are welcome. Such as making a bash-file, that scp's the files over (which is then executed using PhpStorm).
I'm looking for a way, where I can simply press something like: CMD + OPT + CTRL + J - and then it uploads all these marked files.
My project have below-shown structure. I've marked the files I would like to be able to upload with an (x):
project
|- subfolder
|- subsubfolder
|- assets
| |- css (x)
| |- js (x)
| |- admin (x)
| |- img
|
|- foo.php
|- bar.php
|- style.css (x)
|- bundle.js (x)
|- other.php
|- other-1.php
Attempt1
I've already tried the: "Upload changed files automatically to the default server" == "Always|On explicit save..." - and it's quite magically. But if the setup isn't right - then it can mess up badly.
Alright. This is how I did it. FINALLY!!! I've been looking for this for years (no exaggeration). I just got too annoyed with it now, that I dived down into the suggestion #LazyOne came with ( <3 ).
I using PhpStorm v. 2020 and I'm on a Mac.
Step 1 - Install SSHPASS
This was the first hurdle. There are a couple of different taps out there. This one worked for me:
brew install hudochenkov/sshpass/sshpass
This is necessary to avoid getting prompted for the password whenever the scp-command is executed.
Step 2 - Get SCP to work from a terminal
It's annoying to debug from inside PhpStorm. So I would suggest starting in the terminal, getting a SCP-command to work. It relative to soooo many things, so it might differ from one host to another.
Please note that SCP is using SSH to copy files, to SSH should be enabled for this to work.
Here's a command that works for me:
sshpass -p 'mypassword' scp style.css app.js SERVER_USER#SERVER_IP:public_html/wp-content/themes/my_theme_name/
This copies two files to the given destination.
Why I'm not using a SSH-key instead?
I'm on a server where there is a master-user, that I can add my ssh-key to - so that can access the server. But I can't do that for the individual instances.
Step 3 - Make a shell-script
I made a script called uploader.sh and added this content:
#!/bin/bash
sshpass -p 'mypassword' scp myfile.css anotherfile.js athirdfile.php SERVER_USER#SERVER_IP:public_html/wp-content/themes/my_theme_name/
Then I went to 'Run' >> 'Edit configurations' and add a new Shell-file.
Note!! Remember to uncheck 'Execute in terminal'. The reason being that it's nice to be able to just keep working whereever you are. And if you execute it in the terminal, then the cursor will finish in the terminal. If it's unchecked, then it doesn't do that.
Here you can see my configuration:
Step 4 - Run and test
Now go tho 'Run' >> 'Run' and choose the one you just added. Then you should see a window like this:
And to run latest 'Run' again, you can simply press CMD + r.
BAM!
Step 5 - Add uploader.sh to .gitignore
Now the password to your server is stored in clean-text in a file on your machine. It's bad for security purposed. So if you're coding a backend for nuclear launches, then you probably shouldn't do this.
But remember to add the uploader.sh file to your .gitignore-file to avoid uploading it to the repo.
Useful resources
How to use sshpass, to pass a password to scp.

How do I make jmeter use the different hostname/port for different threads of same test plan

In my test scenario I have to test 2 urls with different host and port under same test plan. Is it possible to do so
You can make variable as property and send to jmeter script
Add to Test Plan In User define variables 2 rows:
baseUrl with Value ${__P(baseUrl,localhost)}
port with Value ${__P(port,8080)}
localhost and 8080 are default values you can change it
and when you execute add the values you want e.g.:
jmeterw.cmd ... -JbaseUrl=192.168.0.33 -Jport=80
Define your host and port combinations in a CSV endpoints.csv file like:
somehost,someport
someotherhost, someotherport
and put the CSV file to the "bin" folder of your JMeter installation
Add CSV Data Set Config to your test plan and configure it like:
Set HTTP Request sampler to use ${host} and ${port} variables defined via the CSV Data Set Config
That's it, on each iteration (or virtual user hit) the next line will be picked up from the endpoints.csv file.
See Using CSV DATA SET CONFIG article for more information on parameterising JMeter tests using CSV files.

Create And Import configuration file

I wanna To Create some configuration File such as:
Config File:
username="your username"
password="your pass"
option 3
option 4
option 5
option 6
On the first time of run it will said File : "Config" as been created
with the Property:
after that, the user fill that file
And on the next run it will Get the information from the file.
How I can create in powershell file with Lines(each line is another propery) Or Create File with content of Properties
And how I can do read from file and get the propry
I mean how i can Create by properyies and how I import it
You can use the following :
Puting config to file
$a = [PSCustomObject]#{"username"="toto";"Pwd"="XXXX";"Option1"="o1"}
$a | Export-Clixml c:\temp\confif.txt
Getting config from file :
$b = Import-Clixml c:\temp\confif.txt

Why I cannot scale openshift cart having an environment variable defined?

I am trying to integrate Hazelcast in Tomcat cartridge (https://github.com/worldline/openshift-cartridge-tomcat). The problem is to retrieve ip:ports of gears of a scalable application. I looked at how vert.x does it and it is perfectly fine. It uses pub/sub mechanist to set ip and port in the future environment variable. I can see this in hook folder "set-vertex-cluster" file.
echo $list > $OPENSHIFT_VERTX_DIR/env/OPENSHIFT_VERTX_HAZELCAST_CLUSTER
I did id the same way replacing VERTX by TOMCAT (short name of cart).
But after creating the app there is no OPENSHIFT_TOMCAT_HAZELCAST_CLUSTER env variable.
I looked at how JbossEAP does it. It has
touch ${OPENSHIFT_JBOSSEAP_DIR}/env/OPENSHIFT_JBOSSEAP_CLUSTER
https://github.com/openshift/origin-server/blob/master/cartridges/openshift-origin-cartridge-jbosseap/bin/install
It worked for me, and finally I see OPENSHIFT_VERTX_HAZELCAST_CLUSTER env var and it is populated by gear_ip:gear_port.It's good. But when I scale the app I get the error:
Activation of new gears failed: 53d2ed31e0b8cd2bba00051f: Error activating gear: CLIENT_ERROR: Failed to execute: 'control start' for /var/lib/openshift/53d2ed31e0b8cd2bba00051f/tomcat
Unable to complete the requested operation due to: An invalid exit code (1) was returned from the server ex-std-node92.prod.rhcloud.com. This indicates an unexpected problem during the execution of your request.
Reference ID: 0b4e8a465d1901e8317a18739586e6d1
OPENSHIFT_VERTX_HAZELCAST_CLUSTER is populated by gear1_ip:gear1_port and gear2_ip:gear2_port but of course the second gear failed to start.
When I remove
touch ${OPENSHIFT_TOMCAT_DIR}/env/OPENSHIFT_TOMCAT_HAZELCAST_CLUSTER
from bin/install file everything is fine! Except that I don't have list of cluster members...
I am going mad, struggling with the problem all day long. Can anybody help me, please?
UPDATED:
• Customer A create an OpenShift Application A1 with the Git downloadable cartridge
• OpenShift install the downloadable cartridge into Node N1 and install it into the Application A1.
• Customer A now want to scale the application A1.
• OpenShift try to scale the application A1 by acquiring a new gear in Node N2 (notice that it is different from N1 above) and copy the content from A1 into N2 (but somehow will not copy all the environment variables and necessary settings). In .env folder of every gear
• The gear creation now fail on N2, because the downable cartridge content is not available on N2, because of following commands in bin/tomcat
# Filter user-owned configuration files through sed to replace all
# ${OPENSHIFT_*} variables with their actual values, and write the
# resulting filtered files to the live Tomcat configuration location.
sed_replace_env=$(print_sed_exp_replace_env_var)
replacement_conf_files=(
"server.xml"
"context.xml"
)
for conf_file in "${replacement_conf_files[#]}"; do
sed ${sed_replace_env} ${OPENSHIFT_REPO_DIR}/.openshift/config/${conf_file} > ${OPENSHIFT_TOMCAT_DIR}/conf/${conf_file}
done
The particular function
function print_sed_exp_replace_env_var {
sed_exp=""
for openshift_var in $(env | grep OPENSHIFT_ | awk -F '=' '{print $1}')
do
# environment variable values that contain " or / need to be escaped
# or they will cause problems in the sed command line.
variable_val=$(echo "${!openshift_var}" | sed -e "s#\/#\\\\/#g" | sed -e "s/\"/\\\\\"/g")
# the entire sed s/search/replace/g command needs to be quoted in case the variable value
# contains a space.
sed_exp="${sed_exp} -e \"s/\\\${env.${openshift_var}}/${variable_val}/g\""
done
printf "%s\n" "$sed_exp"
}
As you can see, there is a dangerous of the sed command that may replace entire file into blank file for server.xml and context.xml if the environment variables are not present.
The correct order that OpenShift should perform is:
Customer A create an OpenShift Application A1 with the Git downloadable cartridge
• OpenShift install the downloadable cartridge into Node N1 and install it into the Application A1.
• Customer A now want to scale the application A1.
• OpenShift try to scale the application A1 by acquiring a new gear in Node N2 (notice that it is different from N1 above). Copy all necessary environment variables into the new gears as well
• There is a script within your cartridge that require the server.xml and context.xml template from downloadable cartridge, it can now be successfully found and copy.

Resources