Using K8s Secrets for Quasar Vue3 App Values - environment-variables

I am BRAND new to Quasar Vue3 apps(DevOps helping dev team). We use GitLab for our CICD pipelines and our apps run on OpenShift containers. We also use OpenShift secrets for populating the environment variables for each environment(envFrom) when the container starts. However, we are having a hard time figuring out how to do this with a new Quasar Vue3 app. We've gone through various iterations found on "Google University" and Quasar's documentation, but nothing has helped. We've tried the method of using process.env in the quasar.config.js file:
env: {
myVar: process.env.VUE_APP_VARIABLE
}
However, that seems to be a build-time method and only uses a dummy value we've put into a GitLab CICD variable for testing.
I've also tried the method of using a .js script file defining a function:
export default function getEnv(name) {
return process.env[name];
}
And then importing and calling that function in the MainLayout.vue file:
import getEnv from '../service/env.js'
return {
.
.
myVar: getEnv("VUE_APP_VARIABLE")
}
That works if I return hard-coded string from the script(eg: return "ValueFromScript";), but if I try to return using process.env at all with varied syntaxes, I get blank/null values
return process.env[name];
return process.env."name";
return process.env.VUE_APP_VARIABLE;
return process.env["VUE_APP_VARIABLE"];
etc.
Lastly, we've experemented with the "dotenv" method described here, but that only reads from a .env file.
Can anyone tell me what I'm missing or if this is even possible? I really want to avoid using .env files, it's really not the best practice for production applications.
Thanks.

This is a web application that runs in a browser, you can't access runtime env variables. If you configure FOO: 'test' in quasar.config.js > build > env, then reference it in your app as console.log(process.env.FOO), on build time it will get replaced and turned into console.log('test'). You can check the final code in dist/* to confirm.
You wouldn't need to use a secret management tool here because all the env variables you want to pass to the client application will be seen by users someplace. If you are passing a secret key or similar, then you are probably doing it wrong. You should handle it in the server where it can stay secret instead.
If you are sure the values that will be accessed in the browser are not secret, and all you just want is just them to change on runtime, then you can implement a runtime variable system. It can be done by:
Making an API request on runtime and getting them.
Storing a JSON file somewhere and reading it.
Doing SSR and assigning the variables into ssrContext on the server side. As an example, on the server side, in an SSR middleware, do ssrContext.someVar = process.env.SOME_VAR(env variables are runtime in server-side because they are Node apps that run on a server), then access ssrContext.someVar in the Vue app when the app is rendering on the server side.
If you have some secret things to do, you can do it inside the SSR middleware and return the non-secret result of it to your app using this method as well. So, if this is the case, you can use a secret manager to keep things only available to the Node application which uses the secrets.

Working with our Devs, we came up with a way to setup and use values from OpenShift secrets as environment variables at RUNTIME(should work for K8s in general). I've seen bits and pieces of this in my searches, hopefully I can lay it out in a cohesive format for others that might have the same application requirement.
PreSetup
Create a .sh script file somewhere in your src directory that defines a "getEnv" function as follows. We created a folder for this at src/service:
env.js
export default function getEnv(name) {
return window?.configs?.[name] || process.env[name];
}
Create another .sh script file that writes a json string to another script file to be used later in your code.
This will create another script file dynamically when the container starts up as you will see in later steps.
get-env-vars.sh
JSON_STRING='window.configs = {
"ENV_VAR1": "'"${SECRET_VAR1}"'",
"ENV_VAR2": "'"${SECRET_VAR2}"'"
}'
echo $JSON_STRING >> src/service/config_vars.js
Implementation
In your Dockerfile, add a COPY layer to copy the get-env-vars.sh script to the /docker-entrypoint.d folder.
If you aren't familiar with the docker-entrypoint.d folder; basically, as the container starts up, it will run any .sh file that is located in this folder.
COPY ./get-config-vars.sh /docker-entrypoint.d
Then, in our main index.html file, add the following in the main <head> section to reference/call the script file created by the get-env-vars.sh script at startup:
<script src="/service/config_vars.js"></script>
At this point, we now have a "windows.config" JSON object variable ready for the getEnv() function to pull values from when called.
Wherever you need to be utilizing any of these variables, import the env.js file created earlier to import getEnv() function.
import getEnv from "../service/env.js"
Then simply use the function like you would a variable anywhere else. getEnv("VAR1")
Summary
As an overview here is the workflow the container executes when it is scheduled/started in your K8s environment
Container is scheduled and executes the get-env-vars.sh script, which creates the config_vars.js file
Application starts up. The index.html file executes the config_vars.js file, creating the window.configs JSON object variable
Where needed, the code imports the getEnv() function by importing the env.js file
Calling the getEnv(<variable_name>) function retrieves the value for the specified environment variable from the JSON object variable
When you need to add/update the key-value pairs in your K8s/OpenShift secret, you can delete/restart your POD, which will start the process over, loading in the updated information.
Hopefully this all makes sense.

Related

How to deal with Jenkins error "Library ***expected to contain at least one of src or vars directories"

Working on my 6th or 7th Jenkins script now - and I already noticed they share a bit of code (essentially just the same groovy subroutines over and over again). I wouldn't like to continue with that and rather learn some best practices.
It seems that "Shared Libraries" are the thing to do. (Or is there a better way when you just want to share groovy code, not script steps etc.?)
Those scripts are part of a larger repo (that contains the source of the entire project, including the other scripts), stored in a subfolder Jenkins/Library with this structure:
Jenkins/Library
+- vars
| common_code.groovy
There is only a vars folder, no src. The documentation said
For Shared Libraries which only define Global Variables (vars/), or a Jenkinsfile which only needs a Global Variable, the annotation pattern #Library('my-shared-library') _ may be useful for keeping code concise. In essence, instead of annotating an unnecessary import statement, the symbol _ is annotated.
so I concluded that I wouldn't need a src folder and can do with vars alone.
The library is made available via "Configure Jenkins" > "Global Pipeline Libraries" with SourcePath set to "/Jenkins/Library/" and is brought in with the statement #Library('{name}') _ as first line of the script.
However, when attempting to use the library, I get the error shown in the subject.
What's the problem? (I already searched around and found this instance of the problem, but that doesn't seem to fit for my issue - unless I misunderstood something.)
To specify a name of the library you should set the same name in your jenkins settings:
Name.
An identifier you pick for this library, to be used in the #Library
annotation. An environment variable library.THIS_NAME.version will
also be set to the version loaded for a build (whether that comes from
the Default version here, or from an annotation after the #
separator).
Your '{name}' parameter inside of #Library() means you should add a library with the same name. Because it's not a variable like "${name}" which is not a built in variable and undefined.
If you wish to set up your library with the same name as your jenkins pipleine you could use env.JOB_NAME variable, or check the all environment and pre-defined variables:
println env.getEnvironment()
Or check job parameters only:
println params
Now step-by-step instructions:
Create your library, for example from Git SCM as shown on the screenshot.
Put your library code to the project, e.g: <project_root_folder>/vars/common_code.groovy. You don't need your additional path Jenkins/Library. Also you have named your file in 'snake case' style, which is not usual for groovy:
The vars directory hosts scripts that define global variables
accessible from Pipeline. The basename of each *.groovy file should be
a Groovy (~ Java) identifier, conventionally camelCased.
So your file in 'camel case' should looks CommonCode.groovy.
Write your library code:
// vars/commonCode.groovy
// Define your method
def call() {
// do some stuff
return 'Some message'
}
Write your pipeline. Example of scripted pipeline:
#!/usr/bin/env groovy
// yourPipeline.groovy file in your project
#Library('jenkins-shared-library') _
// Get the message from the method in your library
def messageText = commonCode() as String
println messageText
If you wish to define some global variables this answer also may help you.
PS: Using 'vars' folder allows you to load everything from your vars folder once at the same time. If you wish to load dynamically use import from src folder.

How to use environment variables in CloudFlare Worker in local development environment

I have a CloudFlare Worker where I have environment variables set in the CF Settings..Environment Variables interface. I also have this wrangler.toml
In my worker's index.js I have code reading the variable REGISTRATION_API_URL. If the code is running in a deployed environment then it injects the value from the CF Settings into REGISTRATION_API_URL just fine.
But if I run
wrangler dev
or
wrangler dev --env local
then REGISTRATION_API_URL is undefined.
Originally I expected that the variable would be populated by the CF Settings values, but they aren't. So I tried the two vars setting in the wrangler.toml I show here but no difference. And I have spent a lot of time searching the docs and the greater web.
Are environment variables supported in a local dev environment? Any workarounds that people have come up with? Currently I am looking for undefined and defining the variable with a hard-coded value, but this is not a great answer.
Using wrangler 1.16.0
Thanks.
The docs could be more clear but if you are using the newer module syntax, the variables will not be available as global variables.
Environmental variables with module workers
When deploying a Module Worker, any bindings will not be available as global runtime variables. Instead, they are passed to the handler as a parameter – refer to the FetchEvent documentation for further comparisons and examples .
Here's an example.
export default {
async fetch(request, env, context) {
return new Response(env.MY_VAR);
},
};
KV namespaces are also available in the same object.
Maybe a bit late, but: no I don't think you can
But: you can always use self["YOUR_ENV_VARIABLE"] to get the value and then go from there (unfortunately the docs don't mention that)
Here is what I personally do in my Workers Site project to get the Release version (usually inserted via pipeline/action and then inserted via HtmlRewriter into the index.html):
const releaseVersion = self["RELEASE_VERSION"] || 'unknown'

How does the core 'php.ini' directive 'memory_limit' is considered as an 'Environment Variable' in an code example from the PHP Manual?

I'm using PHP 7.2.8 on my machine that runs on Windows 10 64-bit Operating System.
I come across the following code example from PHP Manual having some description :
Using environment variables can be used in php.ini as shown below.
Example #1 php.ini Environment Variables
; PHP_MEMORY_LIMIT is taken from environment
memory_limit = ${PHP_MEMORY_LIMIT}
I executed the above code on my machine it gave me the following error messages :
Warning: Use of undefined constant PHP_MEMORY_LIMIT - assumed 'PHP_MEMORY_LIMIT' (this will throw an Error in a future version of PHP) in demo.php on line 3
Notice: Undefined variable: PHP_MEMORY_LIMIT in demo.php on line 3
I checked the list of available 'Environment Variables' on my machine but I didn't get such environment variable named $_ENV['PHP_MEMORY_LIMIT']
Then, I checked the php.ini file present on my machine. I found the core php_directive memory_limit=128M
So, my question is why the code example from PHP Manual is considering something similar(${PHP_MEMORY_LIMIT}) to the core 'php.ini' directive as an 'Environment Variable'?
Also, the code written in this code example doesn't work as such environment variable named ${PHP_MEMORY_LIMIT} doesn't exist.
I even checked the latest php.ini from Git as recommended in the PHP Manual but in that file also I found the core php_directive memory_limit=128M and no environment similar to it.
Is the PHP Manual having wrong code example?
Someone please clear my doubts.
Thanks.
The first thing to note is that your example is not a code example, it's a configuration example. So it belongs on php.ini and not on a PHP file.
Environment variables are system dependent and it is up to you to set them. The manual is giving you an example with the aptly named PHP_MEMORY_LIMIT. You could set that variable on your system and then use it on your php.ini. But you can call it whatever you want, that's just an example, it's not based on any specific platform where that variable would be set.

Using custom Environment Variables in JetBrains products for File watcher Arguments

I am trying to use node-sass as File Watcher in WebStorm.
I created a local variable named STYLE with main stylesheet name inside to add it as variable to File Watcher settings everywhere it needed.
But if I add $STYLE$ in a Path I get an error:
/Users/grawl/Sites/sitename/node_modules/node-sass/bin/node-sass app/styles/$STYLE$.scss public/$STYLE$.css
error reading file "app/styles/$STYLE$.scss"
Process finished with exit code 1
IDE just don't interprets my variable.
Also I tried to use %STYLE% but with no luck.
Please do not blame me for direct mapping filenames in File Watcher without using built-in variables like $FileName$ or $FileNameWithoutExtension$ because even WebStorm 9 EAP does not support preprocessor's dependencies except of built-in preprocessors like Sass and Jade.
This case is not only case to use local variables.
For example I want to put into variables my public/ path (that can be dest/ in other projects) and app/ (can be source/). And so on.
So let's figure out this feature.

Getting values from a config file or environment variable in meteor

This would be very useful for storing API keys or other sensitive information. From what I understand, you can use config files locally but they won't work on meteor.com, but I heard a rumor that environment variables were soon to be supported, or are already as of a recent release, but I can't find any examples.
Can someone provide an example of how to retrieve a value from an environment variable or some other safe location?
You can actually access the process object to retrieve environment variables in Meteor. In essence, just do the same as in this solution
After some thought, storing them all in a .js file inside an object literal, adding that file to the .gitignore, and checking in a corresponding .js.sample file with dummy or blank values would do the trick.
There's a much better way to handle environment variables. If you come from Ruby on Rails you're used to setting your environment variables in your .ENV file or in your config/application.yml file.
Meteor handles environment variables in a similar way.
Create settings.json file
Inside your server folder in your project, create a file and name it settings.json. Add this file to your gitignore file.
Inside this JSON file, you can save any environment variables you need.
{
"facebookAppId": "6666667527666666",
"facebookAppSecret": "00004b20dd845637777321cd3c750000",
"amazonS3Bucket": "bucket-name"
}
Loading the environment variables
To use these values inside your app during runtime, start Meteor with a --settings option flag.
$ meteor run --settings server/settings.json
Use the values
To use the values, just call the Meteor.settings object.
ServiceConfiguration.configurations.upsert(
{ service: "facebook" },
{
$set: {
appId: Meteor.settings.facebookAppId,
secret: Meteor.settings.facebookAppSecret
}
}
);
That's all there is to it! Keep your settings safe, and do not commit your keys.

Resources