Description
I will try to explain myself the best I could.
The thing is, I want to load the configuration variables that are in the different environments files, from an external file, and not in compilation time.
For what?
If we have that possibility, we can do configuration changes without change any code, deploy, or build anything.
I've made a solution for my actual company, and I'd like to share it here, and see posible alternatives. We are using docker, dcos and consul.
Here is the solution:
/assets/config.tpl.json
{
"production": ##production##,
"DYNAMIC_VAR": ##DYNAMIC_VAR##
}
This template, is use to replace the values and generate the file which the website reads before load.
/assets/config.json
{
"production": false,
"DYNAMIC_VAR": "DYNAMIC_VAR_VALUE"
}
This file is only used for development in localhost
.angular-cli.json
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.ts"
}
environments/environment.ts
function loadJSON(filePath) {
const json = loadTextFileAjaxSync(filePath, "application/json");
return JSON.parse(json);
}
function loadTextFileAjaxSync(filePath, mimeType) {
const xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filePath, false);
if (mimeType != null) {
if (xmlhttp.overrideMimeType) {
xmlhttp.overrideMimeType(mimeType);
}
}
xmlhttp.send();
if (xmlhttp.status == 200) {
return xmlhttp.responseText;
}
else {
return null;
}
}
export const environment = loadJSON('/assets/config.json');
package.json
"scripts": {
"build": "ng build --prod --aot=false",
},
Dockerfile
...
RUN curl -o /tmp/envconsul_${ENVCONSUL_VERSION}_linux_amd64.zip https://releases.hashicorp.com/envconsul/${ENVCONSUL_VERSION}/envconsul_${ENVCONSUL_VERSION}_linux_amd64.zip
RUN cd /tmp && \
unzip envconsul_${ENVCONSUL_VERSION}_linux_amd64.zip && \
mv envconsul /bin/envconsul && \
rm -rf /tmp/*
...
COPY script/templates/nginx_default.tpl /etc/nginx/sites-available/default
COPY script/entrypoint.sh /entrypoint.sh
COPY script/replace_and_run.sh /replace_and_run.sh
RUN chmod +x /entrypoint.sh
RUN chmod +x /replace_and_run.sh
RUN npm run build && rm -rf /var/www/html/* && cp -R /tmp/app/dist/* /var/www/html/ && rm -rf /tmp/*
ENTRYPOINT ["bash", "/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
/script/entrypoint.sh
#!/usr/bin/env bash
set -e
/bin/envconsul -pristine -consul ${ENVCONSUL_HOST} -prefix ${ENVCONSUL_PREFIX_ENV}${ENVCONSUL_PREFIX_SERVICE} /replace_and_run.sh "$@"
This read from consul the environments variables
/script/replace_and_run.sh
#!/usr/bin/env bash
set -e
cp /var/www/html/assets/config.tpl.json /var/www/html/assets/config.json
unset IFS
for var in $(compgen -e); do
sed -i 's~##'"$var"'##~"'"${!var}"'"~g' /var/www/html/assets/config.json
done
exec "$@"
This replace the variables in the template and generates the final file with the config.
The thing is, now, we can modify an endpoint for example, without do anything, just go to consul, change the variable, and it automatically restart de service and with a reload in the website, we see the changes.
I'm here to clarify the doubts, because it's a complex issue...
Thanks to everybody interested!
BR