How to set Terraform workspace variables via CLI? - variables

I'm using workspaces in terraform to separate environments at runtime, so that I can separate deployments using a different configs.
However, I'm trying to figure out how to set CLI variables.
my variables.tf:
locals {
environment = "${terraform.workspace}"
lambda_vars = {
deploy_version = "0.1"
deploy_name = "deployment"
deploy_secret_1 = "somesupersecretsecret"
}
}
These variables are used throughout my config.
I'm trying to set new variables using the CLI, but it doesnt work, and I can't seem to find any reference to how to achieve this. I've tried:
terraform apply -var 'local.lambda_vars={ deploy_secret_1 = "somesupersecretsecret1" }'
I feel like I'm going about this the wrong way.
Can anyone help?

If you want to be able to configure the variables then you should use actual variables instead of locals. Locals are a way of composing things so you avoid repeating yourself or can use interpolation. Variables don't allow for any interpolation at all.
So in your case you should declare separate variables for things you want to be able configure. If this is just the deploy_secret_1 then you can do this with something like the following:
variable "deploy_secret_1" {
default = "somesupersecretsecret"
}
locals {
environment = terraform.workspace
lambda_vars = {
deploy_version = "0.1"
deploy_name = "deployment"
deploy_secret_1 = var.deploy_secret_1
}
}
Now if you run the following command:
terraform apply -var 'deploy_secret_1=overriding-secret'
It should overwrite the deploy_secret_1 part but leave the rest as is. If you don't specify the deploy_secret_1 variable either by the command line, environment variables or a tfvars file then it will default to somesupersecretsecret. If you'd rather force it to be defined and error if you don't specify the variable then just omit the default argument to the variable declaration.
If you wanted to be able to override more things then you should declare more variables.

Related

Use env variable in VueJS SPA components at runtime?

I'm building a simple SPA with VueJs and Webpack, and would like to use/access env variables from my VueJS components.
I know I will not be able to change those variables "on the fly" but instead I need to recompile-rebuild-redeploy the entire application to see the changes, but for now it's ok since the actual need is to show different info and/or sections base on the deploy environment (local, staging, production).
To be more specific, for now I'm trying to get the env var COMMIT_HASH just to display it as some applications already do just for development info.
This variable would primarily used by the pipeline for the staging deployment, as in local development would be not that useful and probably not used at all for production deployment.
The problem is that I cannot figure out how to access env variables values from my VueJS components scripts sections at runtime, as process.env is a Node method accessible only during webpack compilation and not at runtime.
I thought about using string replacement and found this question, but then I would need to update Webpack script for any new env variable I need to use, so it looks quite inelegant to me.
I also tought of loading all the env variables in a js object and somehow pass it down to the files being compiled by Webpack, but this also looks inelegant/inefficient to me.
So now I'm stuck as can't figure out how to access env vars from my VueJS components at runtime.
I ended up using string-replace-loader with regex matching and a callback for dynamic replacement.
Basically I'll use env.SOME_VARIABLE in my code and search/replace it with the variable value.
For some reason I couldn't make the regex work with the \w to match for word characters and used [a-zA-Z_] instead.
{
test: /resources.*\.js$/,
loader: 'string-replace-loader',
options: {
search: 'env\.([a-zA-Z_]+)',
replace(match, p1, offset, string) {
return process.env[p1];
},
flags: 'g'
}
}
Notes
Since it is text replacement I cannot simply assign env variable values to vue component data properties as it would be interpreted as a variable:
// E.g. given env `COMMIT_HASH=some_hash`
data() {
return {
/**
* WRONG:
* this would be parsed as
* hash: some_hash
* leading to an
* Uncaught ReferenceError: some_hash is not defined
*/
hash: env.COMMIT_HASH,
/**
* RIGHT:
* wrap string to be replaced in single/double quotes so after
* replacement it became a string literal assignment.
* hash: "some_hash"
*/
hash: "env.COMMIT_HASH",
};
},

Vue. How to pass a variable I have on server (process.env.SERVER) to the browser

On the frontend server I have a file I can read with:
if(!!process.env.SERVER) {
require("dotenv").config( { path: '/hw/.env', debug: true } )
console.log(process.env.myvar)
}
But how can I pass the vlue of process.env.myvar to the browser?
Thanks.
If you want to get some variables for all cases you can create an enviroment file with just .env as the name next to package.json in your project.
To get variables from that file you need to declare them first in the .env like this:
VUE_APP_MYVAR = 'myvar'
In your app you can use it like this:
process.env.VUE_APP_MYVAR
If you need some variables depending on the process, respectively for your enviroment, your myvar can't be called with process.env.SERVER. If SERVER is the process, you need a .env.server file next to your package.json.
You can then, again, declare myvar in .env.server like this:
VUE_APP_MYVAR = 'myvar'
To get process.env.VUE_APP_MYVAR this time you have to ensure, that you build or serve your enviroment named server. Else, your app trying to get process.env.VUE_APP_MYVAR with the process you used.
For Example: If you have .env.development and .env.server, both can contain VUE_APP_MYVAR = 'myvar' with different assigned values. Which one is picked depends on the enviroment you build or serve.
For more information, see the docs: Modes and Environment Variables
#Modes

setting global config values in karate

What i am trying is that to set the global karate.config values from a feature file.
I have something very similar to this https://github.com/intuit/karate/blob/master/karate-demo/src/test/java/demo/oauth/oauth2.feature
but i want to set the global config from the feature file or use the feature file in karate-config.js, then how do i access a variable from the feature file when calling using karate.call. And what is the recommended pathing for it.
To set a global variable, use karate-config.js as explained here: https://github.com/intuit/karate#karate-configjs
When using the call keyword, all global variables are inherited.
There is no recommended pathing. If you want you can create complex JSON for e.g. if you return { foo: { a: 1 } } from karate-config.js you can use the value of foo.a anywhere in a feature file, for e.g:
* path 'blah', foo.a

How to use an idris package installed with a nixpkg in another nixpkg?

Currently I am having some trouble using an Idris package that was installed with nixpkg in another Idris package that depends on it. Both of these packages have been tested on a Debian system, so the problem is not with the Idris code itself, but rather somewhere in how they are being installed on the NixOS system. I believe I can successfully install the first package by calling nix-env -f math.nix -i idris_math where math.nix is defined as:
with import <nixpkgs> { };
stdenv.mkDerivation rec {
name = "idris_math";
idris = haskellPackages.idris;
buildDepends = [ idris ];
src = ./.;
preHook = ''
ln -sv ${idris}/share/x86_64-linux-ghc-8.0.1/${idris.name}/libs $PWD/libs
export IDRIS_LIBRARY_PATH=$PWD/libs
'';
configurePhase = ''
export TARGET=$out/lib/${idris.name}
'';
buildPhase = ''
${idris}/bin/idris --build *.ipkg
'';
installPhase = ''
${idris}/bin/idris --install *.ipkg
${idris}/bin/idris --clean *.ipkg
'';
}
I can then run nix-env -q and see that idris_math has been installed. The second nixpkg looks identical to math.nix, except the name is changed and the buildDepends line is now buildDepends = [ idris idris_math ]. When I try to build or install this package however, I am met with error: undefined variable 'idris_math'. Does anyone know what I am doing wrong, or of a way to fix this?
When you write with import <nixpkgs> {}, every attribute defined in the Nixpkgs set is essentially made into a local variable. This means that, when you write haskellPackages, for example, you are actually referring to the haskellPackages attribute defined by Nixpkgs. You can see all the packages defined this way by looking at the file top-level/all-packages.nix in your Nixpkgs checkout.
Notice that the idris in your buildDepends is referring to the definition of an idris attribute on the previous line. Your new idris_math package isn't similarly defined in this file, or added to the Nixpkgs set anywhere, so you can't get a reference to it by looking for a local variable or for (import <nixpkgs> {}).idris_math, which is basically what is being attempted when you write idris_math in your second derivation.
Depending on what exactly you want to do with your package, you have a couple of options. If you just want to use idris_math as a dependency for another nearby package (or a few), you can just write buildDepends = [ idris (import /path/to/math.nix) ]. This is a very simple way to do what you want, and very likely a good choice if you want to use this is a library when developing Idris packages.
If you want to make idris_math part of the set that you get from import <nixpkgs> {} anywhere on your machine, and to make it easy to nix-env -i, you can try adding it to an overlay. This would require creating a file like ~/.config/nixpkgs/overlays/<my overlay name>/default.nix with contents something like:
self: super:
with super;
{
idris_math = callPackage /path/to/idris_math.nix {};
}
In this scenario, you probably also want to change your idris_math.nix header to be { stdenv, haskellPackages }:, because callPackage looks for this kind of definition and it is useful when tying the knot to combine all the overlays together.

Gradle / Groovy properties

I would like to control 'global' config in Gradle build scripts using external property files on each build machine (dev, ci, uat,...) and specify the filename with a command line argument.
e.g. gradle -DbuildProperties=/example/config/build.properties
I specifically don't want to use gradle.properties as we have existing projects that already use this approach and (for example) we want to be able to amend database urls and jdbc drivers without having to change every project.
So far have tried:-
Properties props = new Properties()
props.load(new FileInputStream("$filename"))
project.setProperty('props', props)
which works but has a deprecated warning, but I can't figure out how to avoid this.
Have also tried using groovy style config files with ConfigSlurper:-
environments {
dev {
db.security {
driver=net.sourceforge.jtds.jdbc.Driver
url=jdbc:someserver://somehost:1234/some_db
username=userId
password=secret
}
}
}
but the colons and forward slashes are causing exceptions and we don't want to have to mess up config with escape characters.
There must be a non-deprecated way to do this - can anyone suggest the 'right' way to do it?
Thanks
You can get rid of the deprecated warning quite easily. The message you got probably looks something like this:
Creating properties on demand (a.k.a. dynamic properties) has been deprecated and is scheduled to be removed in Gradle 2.0. Please read http://gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html for information on the replacement for dynamic properties.
Deprecated dynamic property: "props" on "root project 'private'", value: "true".
It can be fixed by replacing:
project.setProperty('props', props)
with
project.ext.props = props
Just to supplement the response given by #Steinar:
it's still possible to use next syntax:
project.ext.set('prop_name', prop_value)
in case you have several properties from file:
props.each({ project.ext.set(it.key, it.value)} )