← Back

Different Environment, Different Variables Values

Published

14 October 2023

Tags

Deployment
AWS Amplify
Kubernetes

Introduction

When developing an app that will be deployed into multiple environments, the developers may need some help from any tools that enable them to store variables that dynamically change based on different environments. From my experience, I have been used to use this kind of feature in my past projects. The implantations are different between projects since the technology that they use are different, one uses AWS Amplify that able to store environment variables and one uses a ConfigMap since it uses Kubernetes.

Environment Variables AWS Amplify

This practice is not much different from using an environment variable inside the codebase. The different is no need to create a .env file for other environment (only needed in local for development purpose), just define the variable in the Amplify App Settings.

Environment variables setup in AWS Amplify AppEnvironment variables setup in AWS Amplify App.

While inside the script of the app, the code to call it is as usual, by using process.env.VARIABLE_NAME. Somehow, when working with UI Framework, it is needed to add a prefix based on the Framework before the variable name, such as process.env.VUE_APP_BUILD_ENV for VueJS.

Reference: Environment variables - AWS Amplify Hosting (amazon.com)

ConfigMap in Kubernetes

Using a ConfigMap in Kubernetes is a bit complex for frontend Developer that has no experience at all on handling Kubernetes since they need to config some steps before it ready to be used in the app. Beside configuration in the Kubernetes, the initiate preparation inside the UI codebase is not much different with in Amplify. You still need a file that stored inside project folder to be used for development purpose only. Thus, in my project, the loaded variables in the ConfigMap are stored in the separated repository.

First of all, we need to add a file named deployment.yaml that stored inside folder BuildConfig/Templates/Kubernetes. Then, the code inside the file is in below:

spec:
  // ...
  template:
    // ...
    spec:
      containers:
        // ...
        volumeMounts:
          - name: config-volume
            mountPath: <ROOT>/<APP_ROOT>/configs/constants.js
            subPath: constants.js

The mountPath should be pointing to the constants.js file that stored inside the ConfigMap repository. For some variable in my past project, the **<ROOT>** is filled by sharable file in nginx folder, /usr/nginx/nginx/html. While the other one is the root for app module (e.g., /app/module). By this way, we should be able to load the constants.js file that stored all of our variables and will override the existing variables in certain environment.

In the UI project, you have to prepare two files: config.js and constants.js, both files are used to store the config map, but in the UI, it will call any created variables from config.js by using window.configs since we register it in global scope variable and more specific with name config. constants.js acts more like a variable database.

These files will be stored inside the <root>/public/configs folder. To be able to use anything inside those two code files, we need to register them inside index.html.

<!-- index.html -->
<html lang="en">
  <head>
    <!-- .... -->
  </head>
  <body>
    <div id="app"></div>
    <script src="<%= BASE_URL %>configs/constants.js"></script>
    <script src="<%= BASE_URL %>configs/config.js"></script>
  </body>
</html>

The <%= BASE_URL %> is coming from base URL config inside the vue.config.js. Next, below is the sample code of two files and how it will be used in components or pages:

// constansts.js
const API_BASE_URL = "https://sampleurl.dev.com/app/public";

// config.js
window.configs = {
  apiBaseUrl: API_BASE_URL
};

// components or pages
const response = await axios.post(window.configs.apiBaseUrl + listingEndpoint, {});
Reference: ConfigMaps | Kubernetes