How to access GitLab CI/CD Variable in Ruby Recipes? - ruby

I have declared some variables in Gitlab -> Settings -> CI/CD -> Variables.
I want to access these variables in ruby (.rb) files for chef cookbook recipes.
I have declared a variable named "TEST_VARIABLE" in settings as:
Gitlab -> Settings -> CI/CD -> Variables :- Key = TEST_VARIABLE, Value = TEST_VALUE
I have tried accessing them in the below format in the ruby(.rb) recipes.
$TEST_VARIABLE, ${TEST_VARIABLE},TEST_VARIABLE, #{TEST_VARIABLE} and ENV['TEST_VARIABLE']
But nothing works, all returns blank or nil value.
Please let me know how to access these variables in the .rb file.

I dont think that you can use pipeline variables in normal source code. Maybe you can set in your script section a shell environment variable and access it in your ruby code.
script:
- export TEST_VARIABLE=$TEST_VARIABLE

You can pass the variables to the ruby script when you call it.
script:
- ./rubyscript $TEST_VARIABLE

Related

Jenkinsfile environment variables not available with parameter variables

I am using a Jenkins plugin to upload test run results to Jira. Using this plugin I can send two JSON blobs of data for the import, but the variables in those JSON blobs can only be environment variables (not variables generally available in the Jenkinsfile).
When I run it is recognizing environment variables that come from the parameters block (this is a parameterized build), but it does not recognize any environment variables I set, either in an environment {} block in the pipeline or by nesting the build step in a withEnv() {} block.
As a sanity check, right before the step in question, I echo two environment variables, one from the parameters block and one from the environment block, and both spit out to the console as expected, but then, as consumed by the plugin, only the variables coming from the parameters block are read as variables, with the rest being left as string.
So is there some difference in how these environment variables are stored/managed behind the scenes that might play into this?
So, for example, here are the parameters and environment blocks:
parameters {
choice(name: 'ENVIRONMENT', choices: ['dev', 'test', 'staging', 'prod'], description: 'Select the environment to run against.')
choice(name: 'TESTS', choices: ['All', 'API', 'Web'], description: 'Select the tests to run.')
}
environment {
PROJECT_KEY = "$jiraProjectKey"
TEST_PLAN_KEY = "$testPlanKeys[$env.ENVIRONMENT]"
PRODUCT_NAME = "$productName"
TEAM_NAME = "$teamName"
}
When I used these environment variables in the JSON blobs to set the Summary field of a Test Execution in Jira with a line that looks like this:
...
"summary": "${ENVIRONMENT} - ${PRODUCT_NAME} - ${TESTS} Tests",
...
The resulting issue summary is:
dev - ${PRODUCT_NAME} - API Tests
So it will properly interpret the environment variables set by the parameters block, but not ones I set explicitly in the environment block.
In the JSON blobs that you are sending inline make sure that for multiline strings you are using """ to delimit those strings and not '''.
Replace:
... importInfo: '''{...'''
by:
...importInfo: """{..."""

Jenkins Pipeline throws "syntax error: bad substitution" when Passing in Parameter

I have a Terraform project that I was trying to use Jenkin's Custom Checkbox plugin (Custom Checkbox Parameter) with so that I can build separate applications dynamically using the same IaC, however, I'm getting the following error when passing in the name parameter for that plugin into the Terraform plan and apply commands.
syntax error: bad substitution
The idea for all this is just to click on "select all" or each individual app and run the build, and this will create the IaC for the given application(s).
I have a terraform plan that I am running as a smoke test to verify the parameters above are being passed in correctly before running the apply. This looks like the following:
sh 'terraform plan -var-file="terraform-dev.tfvars" -var "app_name=[${params[${please-work}]}]" -input=false'
The documentation for the plugin states that you can reference the items checked by using this format: "${params['please-work']}" which is what I've done above. That said, one caveat to this is that Im having to set the values in quotes for this to work since the variables are being set in the Terraform using list(string).
NOTE: I have tested that all this works if I just hardcode the app names with the escapes as following:
sh 'terraform plan -var-file="terraform-dev.tfvars" -var "app_name=[\\"app-1\\",\\"app-2\\"]" -input=false'
Again, what I need is for this to work with the -var "app_name=[${params[${please-work}]}]" without throwing that error.
If needed, here is the setup for the JSON that the plugin is using:
Additionally, I can see the values are being set the way I need them to be set when running the echo of echo "${params['please-work']}" on the initial build step. So these are coming back as "app-1", "app-2"
Again, all but that one bit is working and I've tried various ways to escape the needed strings to get this work and I need insight on a path forward. This would be greatly appreciated.
You are casting the script argument in your sh step method as a literal string, and therefore it will not interpolate the pipeline variable of type object params within the Groovy pipeline interpreter. You also are passing the variable value for the app_name with [] syntax (attempted list constructor?), which is not syntactically valid for shell, Terraform, or JSON, but is for Jenkins Pipeline and Groovy with undesired behavior (unclear what is desired here). Finally, please-work is a literal string and not a Jenkins Pipeline or Groovy variable, and since params is technically an object and not a Map, you must use the . syntax and not the [] syntax for accessors. You must update with:
sh(label: 'Execute Terraform Plan', script: "terraform plan -var-file='terraform-dev.tfvars' -var 'app_name=${params.please-work}' -input=false")
If another issue arises after fixing all of this, then it would be recommended to convert the plugin usage to the pipeline with a parameters directive, and also to probably remove the unusual characters e.g. - from the parameter name.
Thanks for helping me think through this, Matt. I was able to resolve the issue with the following shell script in the declarative pipeline:
sh "terraform plan -var-file='terraform-dev.tfvars' -var 'app_name=[${params['please-work']}]' -input=false"
This is working now.

Terraform to read variables from environment

I have written a terraform configuration with variable definition like:
variable "GOOGLE_CLOUD_REGION" {
type = string
}
When I run terraform plan I am asked to fill in this variable even though this variable is set within my environment.
Is there a way to tell terraform to work with current env vars? Or do I have to export them and pass them somehow manually one-by-one?
You can define the environment variable TF_VAR_GOOGLE_CLOUD_REGION to set that variable.
If you are using bash, it might look like this:
export TF_VAR_GOOGLE_CLOUD_REGION="$GOOGLE_CLOUD_REGION"
terraform apply ...
From Environment Variables under Configuration Language: Input Variables.
As a fallback for the other ways of defining variables, Terraform searches the environment of its own process for environment variables named TF_VAR_ followed by the name of a declared variable.
This can be useful when running Terraform in automation, or when running a sequence of Terraform commands in succession with the same variables. For example, at a bash prompt on a Unix system:
$ export TF_VAR_image_id=ami-abc123
$ terraform plan
...
You can create a file that ends with .tfvars or .tfvars.json and then when you run a plan you specify that file:
terraform apply -var-file="example.tfvars"
If you name the file terraform.tfvars or terraform.tfvars.json or have a file with names ending in .auto.tfvars or .auto.tfvars.json
then Terraform automatically loads the variable definition file and you don't have to manually specify it when you run a plan.
An example of what the terraform.tfvars file will look like:
first_env_var = "environment_variable_one"
second_env_var = "environment_variable_two"
An example of what the terraform.tfvars.json file will look like:
{
"image_id": "ami-abc123",
"availability_zone_names": ["us-west-1a", "us-west-1c"]
}
I would approach this by creating a variables.tf file, within the project directory. with the required variable block you can specify a default:
variable "GOOGLE_CLOUD_REGION" {
type = string
default = "us-west1"
}
this will then be used as the default value during each run, and you will not be prompted.

How to check if pipeline parameter is empty [duplicate]

We used to be able to check if a parameter is available via:
binding.variables.containsKey()
or
getBinding().hasVariable()
But that no longer works at least as of Jenkins v 2.39. (These functions work for variables set within the groovy script but not the parameters from 'Build with Parameters'.)
Instead of using binding.variables.containsKey() to check, you should use:
params.containsKey()

How to access an environment variable that I defined from the last successful build

I am trying to access an environment variable that I defined in the job 'A' from another job 'B'
job 'A' defines it by -
evn.upload_loaction = "loc"
In job B I am trying to access the last successful build of JOb A and get that variable -
def item = Jenkins.instance.getItem("deploy-artifact-pipeline")
def dev_deployed_build=item.getLastSuccessfulBuild()
def envVars= dev_deployed_build.getEnvVars()
echo envVars['upload_loaction'] // prints null
echo envVars['BUILD_NUMBER'] // prints 21
My custom variable is not recognized but generic ones like build_number is available.
When I trigger Job A as downstream job then I can access using -
def jLz = build (job: 'deploy-artifact-pipeline')
echo jLz.buildVariables.PROCESSOR_UPLOAD_LOCATION // prints loc
Can someone help me with this? Or is there a better way to store and access that variable from a previous build ?
EnvInject plugin and Pipeline job doesn't go hand in hand, if some environment variable needs to be stored I usually prefer that job to be a free style job where you can send your env variable to be stored at the end of the build and that can be accessed for the specific build with "injectedEnvVars/api/json"
An alternate approach that I handled was to create an artifact file with the required information. And in the other Jenkins pipeline I download the artifact file and read the information in it.

Resources