Cannot use environment variable in Circleci orb - circleci-2.0

I am trying to create a Circleci workflow which builds and uploads a java WAR to my organizations existing S3 artifact storage bucket repository. First, the project is built and some information is saved in a file, as well as VERSION being put into BASH_ENV:
export "VERSION=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)" >> $BASH_ENV
if [ $CIRCLE_BRANCH = "master" ]; then
ENVIRONMENT=production
elif [ $CIRCLE_BRANCH = "develop" ]; then
ENVIRONMENT=qa
elif [ $CIRCLE_BRANCH = "release-1.0" ]; then
ENVIRONMENT=staging
else
ENVIRONMENT=$CIRCLE_BRANCH
fi
echo "ENVIRONMENT=$ENVIRONMENT" >> project.info
if [ -z "$ENVIRONMENT" ]; then
echo No environment is set
exit 1
fi
Then, I attempt to upload the artifact using the official S3 orb:
steps:
- attach_workspace:
at: .
- run: source project.info
- run: export "VERSION=$VERSION" >> $BASH_ENV
- aws-s3/copy:
from: target/project-${VERSION}.war
to: 's3://artifact.bucket/project/project-${VERSION}.war'
arguments: '--dryrun'
This upload task fails with The user-provided path target/project-.war does not exist. Because an empty string is being interpolated instead of the expected version.
The Circleci documentation states:
In every step, CircleCI uses bash to source BASH_ENV. This means that BASH_ENV is automatically loaded and run, allowing you to use interpolation and share environment variables across run steps.
Yet it appears that this is not the case. How do I make the S3 upload tasks use the environment variables I am setting?

Related

My yaml is invalid in tag allow_failure using Gitlab CI

In my yaml, i am trying to use the allow_failure:exit_codes: feature:
job name:
script:
- ...
rules:
- when: manual
allow_failure:
exit_codes:
- 1
- 2
- 3
GitLab mark invalid yaml in tag: allow_failure:exit_codes
In the documentation in gitlab, i found version history:
Version history
Introduced in GitLab 13.8.
Feature flag removed in GitLab 13.9.
How can I resolve this error?
Your GitLab version is 13.2.6 but the feature was introduced in GitLab 13.8, therefore you won't be able to use this feature unless you upgrade your GitLab instance to an applicable version.
As a possible alternative you can manually check error codes in your script. This works best if you run your script steps as a script run with bash (as opposed to directly in job steps).
With GitLab Runner version 13.12 or higher, you can use the FF_USE_NEW_BASH_EVAL_STRATEGY feature flag and have bash traps work in inline steps... you can do something like this and not need to create a script file:
MY_JOB:
variables:
FF_USE_NEW_BASH_EVAL_STRATEGY: "1" # needed to make `trap` work with inline scripts
# only available with GitLab runner 13.12+
# It's usually OK to use runners at higher minor version than the GitLab server
script:
- |
cleanup() {
rv=$?
echo "return code was $rv"
if [[ $rv -eq 3 ]]; then # simulate behavior of `allow_failure:exit_codes:[3]`
echo "return code ${rv} is allowed. Exiting 0"
exit 0
fi
exit $rv
}
- trap "cleanup" EXIT
- /bin/false || exit 3 # throw exit code 3

Azure Devops - run build only in the folder that have changes

I have a some spark jobs which are written on scala and build using maven.
Right now the follow a path like this
/src/job1/<<build data>>
/src/job2/<<build data>>
.....
This build data holds the code, pom.xml, tests and other thinks needed for each job pass to maven.
We have a root folder that has a father pom.xml that builds all the code, but I don't want to build all the code every time. I want to be able to test and build only the code for the jobs that changes.
The only way that I think is possible is to run build an tests only in the folders that changes was detected but I can't seem to do that without create one azure devops build for each folder, any ideas?
TL:DR - How to pass the path of folder that have changes in azure devops to the build process?
How to pass the path of folder that have changes in azure devops to the build process?
We could add a powershell scripts to check the folder or path, like:
$editedFiles = git diff HEAD HEAD~ --name-only
echo "$($editedFiles.Length) files modified:"
$editedFiles | ForEach-Object {
echo $_
Switch -Wildcard ($_ ) {
'/src/job1' {
Write-Output "##vso[task.setvariable variable=job1]True"
}
'/src/job2' {
Write-Output "##vso[task.setvariable variable=job2]True" }
}
}
This script sets variables which are then referenced in custom conditions in the pipeline build task or in the build pipeline:
and(succeeded(), eq(variables['job1'], 'True'))
You could check this similar thread for some details.
Hope this helps.
You can work around this by creating a script that will do the following:
Get the changeset/commit in the build to check which files are changed.
Based on the files changes, you define the logic to decide which folder it should build, run tests, etc.
This solution will require you to build all the logic to decide which folders to build and test.
Thanks for your inputs. I was able to do it with your inputs on git, I realized that we are using gitflow workflow and every time that we have pull request to the master branch (meaning deployment) a commit is created with starting "Merged PR", this way I can compare the latest two commits and check what changed.
How I'm doing:
# This part uses this to get the latest two pull requests hashes
$last_pr_commit=git log --grep="^Merged PR" -n 1 --pretty=format:"%h" --abbrev=200
$second_last_pr_commit=git log -n 1 --grep="^Merged PR" --oneline --abbrev=200 $last_pr_commit^...HEAD~2 --pretty=format:"%h"
# This get the path of the files
$result=git diff $last_pr_commit $second_last_pr_commit --name-only
And then I just build the ones that I'm interested.
ForEach ($line in $($result -split "`r`n"))
{
# In my case I only need the two first parts of path
$folderPath=$line.split('/')[0]+'/'+$line.split('/')[1]
if ($line.contains('.scala')){
# Running the tests and packaging
mvn package $folderPath
}
}
This is powershell but it can work with bash changing the for loop.
Thanks

Use pre-installed Terraform plugins instead of downloading them with terraform init

While running terraform init when using Terraform 0.11.3 we are getting the following error:
Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
Error installing provider "template": Get
https://releases.hashicorp.com/terraform-provider-template/: read tcp
172.25.77.25:53742->151.101.13.183:443: read: connection reset by peer.
Terraform analyses the configuration and state and automatically
downloads plugins for the providers used. However, when attempting to
download this plugin an unexpected error occured.
This may be caused if for some reason Terraform is unable to reach the
plugin repository. The repository may be unreachable if access is
blocked by a firewall.
If automatic installation is not possible or desirable in your
environment, you may alternatively manually install plugins by
downloading a suitable distribution package and placing the plugin's
executable file in the following directory:
terraform.d/plugins/linux_amd64
I realized it's because of connectivity issues with https://releases.hashicorp.com domain. For some obvious reasons, we will have to adjust with this connectivity issue as there are some SSL and firewall issues between the control server and Hashicorp's servers.
Is there any way we could bypass this by downloading the plugins from Hashicorp's servers and copying them onto the control server? Or any other alternative to avoid trying to download things from Hashicorp's servers?
You can use pre-installed plugins by either putting the plugins in the same directory as the terraform binary or by setting the -plugin-dir flag.
It's also possible to build a bundle of every provider you need automatically using the terraform-bundle tool.
I run Terraform in our CI pipeline in a Docker container so have a Dockerfile that looks something like this:
FROM golang:alpine AS terraform-bundler-build
RUN apk --no-cache add git unzip && \
go get -d -v github.com/hashicorp/terraform && \
go install ./src/github.com/hashicorp/terraform/tools/terraform-bundle
COPY terraform-bundle.hcl .
RUN terraform-bundle package terraform-bundle.hcl && \
mkdir -p terraform-bundle && \
unzip -d terraform-bundle terraform_*.zip
####################
FROM python:alpine
RUN apk add --no-cache git make && \
pip install awscli
COPY --from=terraform-bundler-build /go/terraform-bundle/* /usr/local/bin/
Note that the finished container image also adds git, make and the AWS CLI as I also require those tools in the CI jobs that uses this container.
The terraform-bundle.hcl then looks something like this (taken from the terraform-bundle README):
terraform {
# Version of Terraform to include in the bundle. An exact version number
# is required.
version = "0.10.0"
}
# Define which provider plugins are to be included
providers {
# Include the newest "aws" provider version in the 1.0 series.
aws = ["~> 1.0"]
# Include both the newest 1.0 and 2.0 versions of the "google" provider.
# Each item in these lists allows a distinct version to be added. If the
# two expressions match different versions then _both_ are included in
# the bundle archive.
google = ["~> 1.0", "~> 2.0"]
# Include a custom plugin to the bundle. Will search for the plugin in the
# plugins directory, and package it with the bundle archive. Plugin must have
# a name of the form: terraform-provider-*, and must be build with the operating
# system and architecture that terraform enterprise is running, e.g. linux and amd64
customplugin = ["0.1"]
}
config plugin_cache_dir in .terraformrc
plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"
then move the pre-installed provider into the plugin_cache_dir,
terraform will not download the provider anymore
btw, use the ~/.terraform.d/plugin directory doesn't work
/.terraform.d/plugin/linux_amd64$ terraform -v
Terraform v0.12.15
The proper way to handle this since terraform 0.14, as also discussed on the terraform-bundle page mentioned in the currently accepted answer, is to use terraform providers mirror as described on https://www.terraform.io/cli/commands/providers/mirror. This command creates all the necessary index files etc so the folder can be used for plugins. Eg:
$ cd your-tf-root-module
$ terraform providers mirror path/to/tf-plugins
...
$ terraform init --plugin-dir path/to/tf-plugins
...
You can cd to each of your root modules (ie those that have terraform state) and run the mirror command; multiple versions of a plugin may be installed there, and that's ok. When you run the terraform init command, it will fetch the proper one. Same as without the --plugin-dir arg.
So the only difference is that the internet is not used to acquire the plugins, terraform init gets them from the plugin folder.
This is very useful also for creating a cache that can then be used by terraform in ci/cd. Eg in circleci you would have a manual job that calls mirror and does a save-cache; and your automated terraform init job would restore-cache, and use --plugin-dir arg; then the automated terraform apply job would behave as usual.
Starting 0.13.2 version of Terraform release, one could download plugins from a local webserver/http server via network mirror protocol.
For more details, check this link
It expects a .terraformrc file in $HOME path, pointing to the provider path of the plugins like below. If the file is in different directory, you could provide the path with TERRAFORM_CONFIG env var.
provider_installation {
network_mirror {
url = "https://terraform-plugins.example.net/providers/"
}
}
Then, you define providers in a custom tf like below.
providers.tf::
terraform {
required_providers {
azurerm = {
source = "registry.terraform.io/example/azurerm"
}
openstack = {
source = "registry.terraform.io/example/openstack"
}
null = {
source = "registry.terraform.io/example/null"
}
random = {
source = "registry.terraform.io/example/random"
}
local = {
source = "registry.terraform.io/example/local"
}
}
}
However, you have to upload the plugin file in .zip format along with index.json and the <version>.json files for terraform to discover the version of plugin to download.
Example index.json containing the version of plugin::
{
"versions": {
"2.3.0": {}
}
}
Again, 2.3.0.json contains hashes of the plugin file. In this case it's <version>.json
{
"archives": {
"linux_amd64": {
"hashes": [
"h1:nFL6uiwsQFLiP8QCr35sPfWe9LpXI3/c7gP9tYnih+k="
],
"url": "terraform-provider-random_2.3.0_linux_amd64.zip"
}
}
}
How do you get details of index.json and <version>.json files?
By running terraform providers on the directory containing tf files. Note, the machine running this command, needs to connect to public terraform registry. Terraform will download the information of these files. If you have different terraform configuration files, it makes sense to automate these steps otherwise, you could manually do :)
Upon, terraform init, terraform downloads the plugins from above web server rather from terraform registry. Make sure you don't use plugin-dir argument with terraform init as it will override all the changes you made.
Updated Dockerfile for #ydaetskcoR 's solution, because currently terraform-bundle doesn't work with 0.12.x (the problem was fixed at 0.12.2, but appeared on 0.12.18)
FROM hashicorp/terraform:0.12.18 as terraform-provider
COPY provider.tf .
RUN terraform init && \
mv .terraform/plugins/linux_amd64/terraform-provider* /bin/
FROM hashicorp/terraform:0.12.18
# Install terraform pre-installed plugins
COPY --from=terraform-provider /bin/terraform-provider* /bin/
And here is the content of provider.tf
provider "template" { version = "~>2.1.2" }
provider "aws" { version = "~>2.15.0" }
...
This took me awhile, had the same problem. I ended up having to download from source and use the image that this spits out. Its nasty, but it does what i need it do to to work with the Google provider.
FROM golang:alpine AS terraform-bundler-build
ENV TERRAFORM_VERSION=0.12.20
ENV GOOGLE_PROVIDER=3.5.0
RUN apk add --update --no-cache git make tree bash curl
ENV GOPATH=/go
RUN mkdir -p $GOPATH/src/github.com/terraform-providers
RUN cd $GOPATH/src/github.com/terraform-providers && curl -sLO https://github.com/terraform-providers/terraform-provider-google-beta/archive/v$GOOGLE_PROVIDER.tar.gz
RUN cd $GOPATH/src/github.com/terraform-providers && tar xvzf v$GOOGLE_PROVIDER.tar.gz && mv terraform-provider-google-beta-$GOOGLE_PROVIDER terraform-provider-google-beta
RUN cd $GOPATH/src/github.com/terraform-providers/terraform-provider-google-beta && pwd && make build
RUN cd $GOPATH/src/github.com/terraform-providers && curl -sLO https://github.com/terraform-providers/terraform-provider-google/archive/v$GOOGLE_PROVIDER.tar.gz
RUN cd $GOPATH/src/github.com/terraform-providers && tar xvzf v$GOOGLE_PROVIDER.tar.gz && mv terraform-provider-google-$GOOGLE_PROVIDER terraform-provider-google
RUN cd $GOPATH/src/github.com/terraform-providers/terraform-provider-google && pwd && make build
RUN mkdir -p $GOPATH/src/github.com/hashicorp
RUN cd $GOPATH/src/github.com/hashicorp && curl -sLO https://github.com/hashicorp/terraform/archive/v$TERRAFORM_VERSION.tar.gz
RUN cd $GOPATH/src/github.com/hashicorp && tar xvzf v$TERRAFORM_VERSION.tar.gz && mv terraform-$TERRAFORM_VERSION terraform
RUN cd $GOPATH/src/github.com/hashicorp/terraform && go install ./tools/terraform-bundle
ENV TF_DEV=false
ENV TF_RELEASE=true
COPY my-build.sh $GOPATH/src/github.com/hashicorp/terraform/scripts/
RUN cd $GOPATH/src/github.com/hashicorp/terraform && /bin/bash scripts/my-build.sh
ENV HOME=/root
COPY terraformrc $HOME/.terraformrc
RUN mkdir -p $HOME/.terraform.d/plugin-cache
########################################
FROM alpine:3
ENV HOME=/root
RUN ["/bin/sh", "-c", "apk add --update --no-cache bash ca-certificates curl git jq openssh"]
RUN ["bin/sh", "-c", "mkdir -p /src"]
COPY --from=terraform-bundler-build /go/bin/terraform* /bin/
RUN mkdir -p /root/.terraform.d/plugins/linux_amd64
COPY --from=terraform-bundler-build /root/.terraform.d/ $HOME/.terraform.d/
RUN cp /bin/terraform-provider-google $HOME/.terraform.d/plugin-cache/linux_amd64
RUN cp /bin/terraform-provider-google-beta $HOME/.terraform.d/plugin-cache/linux_amd64
COPY terraformrc $HOME/.terraformrc
COPY provider.tf $HOME/
COPY backend.tf $HOME/
# For Testing (This should be echoed or taken care of in the CI pipeline)
#COPY google.json $HOME/.google.json
WORKDIR $HOME
ENTRYPOINT ["/bin/bash"]
.terraformrc:
plugin_cache_dir = "$HOME/.terraform.d/plugins/linux_amd64"
disable_checkpoint = true
provider.tf
# Define which provider plugins are to be included
provider "google" {
credentials = ".google.json"
}
provider "google-beta" {
credentials = ".google.json"
}
my-build.sh
#!/usr/bin/env bash
#
# This script builds the application from source for multiple platforms.
# Get the parent directory of where this script is.
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )"
# Change into that directory
cd "$DIR"
echo "DIR=$DIR"
# Get the git commit
GIT_COMMIT=$(git rev-parse HEAD)
GIT_DIRTY=$(test -n "`git status --porcelain`" && echo "+CHANGES" || true)
# Determine the arch/os combos we're building for
XC_ARCH=${XC_ARCH:-"amd64 arm"}
XC_OS=${XC_OS:-linux}
XC_EXCLUDE_OSARCH="!darwin/arm !darwin/386"
mkdir -p bin/
# If its dev mode, only build for ourself
if [[ -n "${TF_DEV}" ]]; then
XC_OS=$(go env GOOS)
XC_ARCH=$(go env GOARCH)
# Allow LD_FLAGS to be appended during development compilations
LD_FLAGS="-X main.GitCommit=${GIT_COMMIT}${GIT_DIRTY} $LD_FLAGS"
fi
if ! which gox > /dev/null; then
echo "==> Installing gox..."
go get -u github.com/mitchellh/gox
fi
# Instruct gox to build statically linked binaries
export CGO_ENABLED=0
# In release mode we don't want debug information in the binary
if [[ -n "${TF_RELEASE}" ]]; then
LD_FLAGS="-s -w"
fi
# Ensure all remote modules are downloaded and cached before build so that
# the concurrent builds launched by gox won't race to redundantly download them.
go mod download
# Build!
echo "==> Building..."
gox \
-os="${XC_OS}" \
-arch="${XC_ARCH}" \
-osarch="${XC_EXCLUDE_OSARCH}" \
-ldflags "${LD_FLAGS}" \
-output "pkg/{{.OS}}_{{.Arch}}/${PWD##*/}" \
.
## Move all the compiled things to the $GOPATH/bin
GOPATH=${GOPATH:-$(go env GOPATH)}
case $(uname) in
CYGWIN*)
GOPATH="$(cygpath $GOPATH)"
;;
esac
OLDIFS=$IFS
IFS=: MAIN_GOPATH=($GOPATH)
IFS=$OLDIFS
#
# Create GOPATH/bin if it's doesn't exists
if [ ! -d $MAIN_GOPATH/bin ]; then
echo "==> Creating GOPATH/bin directory..."
mkdir -p $MAIN_GOPATH/bin
fi
# Copy our OS/Arch to the bin/ directory
DEV_PLATFORM="./pkg/$(go env GOOS)_$(go env GOARCH)"
if [[ -d "${DEV_PLATFORM}" ]]; then
for F in $(find ${DEV_PLATFORM} -mindepth 1 -maxdepth 1 -type f); do
cp ${F} bin/
cp ${F} ${MAIN_GOPATH}/bin/
ls -alrt ${MAIN_GOPATH}/bin/
echo "MAIN_GOPATH=${MAIN_GOPATH}"
done
fi
bucket.tf
terraform {
backend "gcs" {
bucket = "my-terraform-bucket"
prefix = "terraform/state"
credentials = ".google.json"
}
required_version = "v0.12.20"
}
You can use pre-installed plugins by either putting the plugins binaries in the same directory where Terraform binary is available by setting the "plugins-dir" flag.
By default, all plugins downloaded in .terraform folder. For example, Null resource plugin will be available at below location
.terraform\providers\registry.terraform.io\hashicorp\null\3.0.0.\windows_amd64.
Create new folder like "terraform-plugins" inside Terraform directory and copy all content including registry.terraform.io folder mentioned in above example in created folder.
Now run the terraform init command with plugins-dir flag
terraform init -plugin-dir="/terraform-plugins"
specify complete directory path with plugin-dir flag

Terraform state environments/workspaces not listed when created on another machine

I've been using Terraform's state environments (soon to be renamed as workspaces) as part of a CI system (Gitlab CI) to spin up dynamic environments for each branch for tests to run against.
This seems to be working fine but as part of the tear down of the environment after the branch is deleted I am also trying to use terraform env delete [ENVIRONMENT NAME]. When ran locally this is fine but my CI system is running in Docker and so has a clean workspace between creating the environment and then later on a build stage destroying it. In this case it can't seem to see the environment.
If I try to delete it I see this error:
Environment "restrict-dev-websites-internally" doesn't exist!
You can create this environment with the "new" option.
terraform env list also doesn't show the environment.
I've also noticed that I'm unable to select it despite seeing it in S3 (where my remote state is stored). If I create a new environment called the same thing then the environment from my remote state is used (it doesn't try to create another set of resources).
On top of this, when I'm using an environment created by the CI system I notice that sometimes I have an environment selected that terraform env list doesn't show:
$ terraform env list
default
$ cat .terraform/environment
[ENVIRONMENT NAME]
$ terraform env list
default
Note the missing * against the selected environment and that my environment isn't listed as would be expected by the example in the docs:
$ terraform env list
default
* development
mitchellh-test
I'm unsure as to how the state environments are meant to be working so I may have missed a trick here which is causing this odd corruption when working in Docker.
For completeness I'm managing the environments using some wrapper scripts:
env.sh
#!/bin/sh
set -e
if [ "$#" -ne 2 ]; then
echo "Usage: ./env.sh terraform_target env_name"
echo ""
echo "Example: ./env.sh test test-branch"
fi
TERRAFORM_TARGET_LOCATION=${1}
TERRAFORM_ENV=${2}
REPO_BASE=`git rev-parse --show-toplevel`
TERRAFORM_BASE="${REPO_BASE}"/terraform
. "${TERRAFORM_BASE}"/remote.sh "${TERRAFORM_BASE}"/"${TERRAFORM_TARGET_LOCATION}"
if ! terraform env select ${TERRAFORM_ENV} 2> /dev/null; then
terraform env new ${TERRAFORM_ENV}
fi
env-delete.sh
#!/bin/sh
set -e
if [ "$#" -ne 2 ]; then
echo "Usage: ./env.sh terraform_target env_name"
echo ""
echo "Example: ./env.sh test test-branch"
fi
TERRAFORM_TARGET_LOCATION=${1}
TERRAFORM_ENV=${2}
REPO_BASE=`git rev-parse --show-toplevel`
TERRAFORM_BASE="${REPO_BASE}"/terraform
. "${TERRAFORM_BASE}"/remote.sh "${TERRAFORM_BASE}"/"${TERRAFORM_TARGET_LOCATION}"
if terraform env select ${TERRAFORM_ENV} 2> /dev/null; then
terraform env select default
terraform env delete ${TERRAFORM_ENV}
fi
The remote.sh script runs a terraform init with dynamic state file locations depending on the project and path in the project using S3 as a backend.
remote.sh
#!/bin/sh
set -e
terraform --version
TERRAFORM_TARGET_LOCATION="${1}"
cd "${TERRAFORM_TARGET_LOCATION}"
REPO_NAME="$(basename "`git config --get remote.origin.url`" .git)"
STATE_BUCKET="<BUCKET_NAME>"
STATE_KEY="$(git rev-parse --show-prefix | cut -d"/" -f2-)"
STATE_FILE="terraform.tfstate"
terraform init -backend-config="bucket=${STATE_BUCKET}" \
-backend-config="key=${STATE_KEY}/${STATE_FILE}"
terraform get -update=true
When running things locally I have very wide permissions which include full access to all of S3. My Gitlab CI instances use the following IAM privileges attached to an instance profile:
{
"Version" : "2012-10-17",
"Statement": [
{
"Sid" : "1",
"Effect" : "Allow",
"Action" : [ "s3:List*",
"s3:Get*",
"s3:PutObject*" ],
"Resource": [ "arn:aws:s3:::<BUCKET_NAME>",
"arn:aws:s3:::<BUCKET_NAME>/*" ]
},
{
"Sid": "2",
"Effect": "Allow",
"Action": [
"s3:DeleteObject*"
],
"Resource": [
"arn:aws:s3:::<BUCKET_NAME>/env:*"
]
}
]
}
For clarity, my builds can see and use the remote state for the environment fine but are forced to created the environment over and over and are then unable to delete the environment after destroying everything in the state file because it can't select the environment.
I could always create the environment before deleting it so that I have it available in terraform env list but the point is that I'm not sure why the environment is not in the list when the environment was created on another machine or in another container.
You need the state to destroy the environment.
From the documentation as to why they need the state:
Terraform typically uses the configuration to determine dependency
order. However, when you delete a resource from a Terraform
configuration, Terraform must know how to delete that resource.
Terraform can see that a mapping exists for a resource not in your
configuration and plan to destroy. However, since the configuration no
longer exists, it no longer knows the proper destruction order.
You might also try to first import it which might be doable if there are not many instances involved.
I'd suggest considering running a consul container (or 3 to make it stable, they are really small) to store the state in another remote store than your default s3 store. This will make sure your CI environments will not show up in the remote store used by others. Consul has a web gui that will allow you to clean up the K/V stored there if it is ever needed. You can also interact with it through their api using curl or Ansible.
Alternatively, you can make the consul server part of the dev environment you set up, store the state there and read from it when destroying. In that case you would still keep everything else clean. I'd personally do it like this.
If a dev starts an environment on his local machine and you want to keep your remote state clean he should be using the local state. You can also use the solution above for the dev's local machine and have a consul server inside his local setup. Good for him to create/destroy and you will keep you remote state clean as you say.
As a disclaimer, I only started recently with Terraform but I don't quite see the advantage of the environments. I'm using a git repo with subdirs for each environment. That way they are truly independent from each other and I can set a dev locally and our staging/prod on our consul cluster protected with ACL.
Didn't you try the Volumes option in runner configuration?
https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#the-runners-docker-section
To save the terraform state between builds?

Azure batch job start tasks failed

I'm using Azure batch python API. When I'm creating a new job, I see exit code 128 (image attached). How can I know what is the reason for that?
I'm creating a new job using this code :
def wrap_commands_in_shell(commands):
return "/bin/bash -c 'set -e; set -o pipefail; {}; wait'".format(';'.join(commands))
job_tasks = ['cd /mnt/batch/tasks/shared/ && git clone https://github.com/cryptobiu/OSPSI.git',
'cd /mnt/batch/tasks/shared/OSPSI && git checkout cloud',
'cd /mnt/batch/tasks/shared/OSPSI && cmake CMake',
'cd /mnt/batch/tasks/shared/OSPSI && mkdir -p assets'
]
job_creation_information = batch.models.JobAddParameter(job_id, batch.models.PoolInformation(pool_id=pool_id),
job_preparation_task=batch.models.JobPreparationTask(
command_line=wrap_commands_in_shell(
job_tasks),
run_elevated=True,
wait_for_success=True
)
)
To diagnose, you can look at the stderr.txt and stdout.txt for the Job Preparation task that has failed in the Azure Portal, using Azure Batch Explorer, or using an SDK via code. If you look at which node ran the job prep task, navigate to that node, then the job directory. Under the job directory, you should see a jobpreparation directory. In that directory will have the stderr.txt and stdout.txt.
With regard to the exit code, there are a few potential problems that could cause this:
Did you install git, cmake and any other dependencies as part of a start task?
I get a 404 when I try to navigate to: https://github.com/cryptobiu/OSPSI. Does this repo exist? If it's a private repository, are you providing the correct credentials?
A few notes about your job_tasks array:
You should not hardcode the paths /mnt/batch/tasks/shared. This path to the "shared" directory may not be the same between Linux distributions. You should use the environment variable $AZ_BATCH_NODE_SHARED_DIR instead. You can view a full list of Azure Batch pre-filled environment variables here.
You do not need to cd into the directory for each command, you only need to do it once. You can rewrite job_tasks as:
['cd $AZ_BATCH_NODE_SHARED_DIR',
'TODO: INSERT YOUR COMMANDS TO SETUP AUTH WITH GITHUB FOR PRIVATE REPO',
'git clone https://github.com/cryptobiu/OSPSI.git',
'cd OSPSI',
'cmake CMake',
'mkdir -p assets']

Resources