Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load configuration from external file #6711

Closed
Ismaestro opened this issue Jun 16, 2017 · 4 comments
Closed

Load configuration from external file #6711

Ismaestro opened this issue Jun 16, 2017 · 4 comments

Comments

@Ismaestro
Copy link

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

@filipesilva
Copy link
Contributor

Heya, I have to close and link to #3855 here, in order to keep discussion on this topic on the same FAQ labelled issue.

I appreciate the alternative solution here, it's similar to mine in #3855 (comment) but a bit more specific to your setup.

@cabaji9
Copy link

cabaji9 commented Oct 2, 2017

Thanks works wonderfully yet i added some extra code cause i dont wanna to add all the properties:

`let finalEnviron:any =
{ production: false
};

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;
}
}

function loadVars(finalEnviron){
let environ = loadJSON('/assets/config.json');

for (let key in environ) {
let item = environ[key];
finalEnviron[key] = item;
console.log(key);
}
return finalEnviron;
}

export const environment = loadVars(finalEnviron);`

@Naikno
Copy link

Naikno commented Jul 22, 2019

these solutions not works with aot mode.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants