<p>I would like to know if it's possible to override a value in environment.ts files (angular) with a Kubernetes manifest?</p>
<p>I do it for application.properties (spring) but looks like it's not working the same way with Angular.</p>
<p>here's what I do for Spring :</p>
<pre><code>spec:
            containers:
                - name: $(appName)
                  image: ACR/$(image)
                  imagePullPolicy: 
                  ports:
                    - name: http
                      containerPort: 8080
                      protocol: TCP
                  env:
                    - name: SPRING_DATASOURCE_PASSWORD
                      value: &quot;$(datasourcePassword)&quot;
</code></pre>
<p>and the value of the password changes based on what I set for $(datasourcePassword) variable (azure devops variable). If I put a fake password API cannot access DB.</p>
<p>But if I do the same with the manifest I use for Angular :</p>
<pre><code>spec:
            containers:
                - name: $(appName)
                  image: ACR/$(image)
                  imagePullPolicy: 
                  ports:
                    - name: http
                      containerPort: 8181
                      protocol: TCP
                  env:
                    - name: APIENDPOINT
                      value: &quot;$(APIurl)&quot;
</code></pre>
<p>the front still use the value defined by default in the environment.ts :</p>
<pre><code>export const environment = {
  production: true,
  APIEndpoint: 'http://localhost:8080'
};
</code></pre>
<p>where am I doing it wrong?</p>
<p>thanks a lot for the help !</p>

Thibault Pilette
<p>I faced the same issue you described.
A good way I found to solve it, was creating an environment-service-loader where I do a merge between the properties from an env.json file and the properties defined in the environment.ts.</p>
<p>Let me describe each step.</p>
<p><strong>ANGULAR</strong></p>
<p><strong>1. Create in the app.module.ts the two following providers</strong></p>
<pre><code>    import {environment} from '../environments/environment';

    function initEnvironmentServiceFactory(
      envServiceLoader: EnvServiceLoader,
      environmentService: EnvironmentService
    ) {
     return async () =&gt; {
       const envs = await envServiceLoader.loadEnvVariables();
       environmentService.setEnvVariables(envs);
     };
    }

    providers: [
      ....
      {provide: 'environment_prod', useValue: environment},
      {
        provide: APP_INITIALIZER,
        useFactory: initEnvironmentServiceFactory,
        deps: [EnvServiceLoader, EnvironmentService],
        multi: true
      },
      ....
</code></pre>
<p><strong>2. Create the EnvServiceLoader that will &quot;override&quot; the environment.ts and the properties defined in env.json file under assets/json. In this example I defined the key production as uneditable.</strong></p>
<pre><code>    @Injectable({
     providedIn: 'root'
    })
    export class EnvServiceLoader {

      UNEDITABLE_PROPERTIES = ['production'];

      constructor(@Inject('environment_prod') private environment, private 
        httpClient: HttpClient) {
      }

      async loadEnvVariables(): Promise&lt;any&gt; {
        const envJson = await this.getJsonConfig();
        return {...this.environment, ...envJson, ...this.getUneditableConfig(this.environment)};
      };

      private getJsonConfig(): Promise&lt;any&gt; {
        return this.httpClient.get('./assets/json/env.json')
          .pipe(map((res: string) =&gt; JSON.parse(res)),
            catchError(() =&gt; of({})
            )).toPromise();
      }

      private getUneditableConfig(environmentConfig: any) {
        return this.UNEDITABLE_PROPERTIES.reduce((config, key) =&gt; {
          config[key] = environmentConfig[key];
          return config;
        }, {});
      };
    }
</code></pre>
<p><strong>3. Create the EnvironmentService</strong></p>
<pre><code>   @Injectable({
      providedIn: 'root'
   })
   export class EnvironmentService {
      private env;

      setEnvVariables(env): void {
        this.env = env;
      }

      getEnvVariables(): any {
        return this.env;
      }
    }
</code></pre>
<p><strong>KUBERNETES</strong></p>
<p><strong>1. Create a <strong>configmap</strong> in Kuberentes containing the value you want to override through the env.json</strong></p>
<pre><code>  apiVersion: v1
  kind: ConfigMap
  metadata:
    name: client-config
  data:
    env.json: |
      &quot;{\&quot;API_endpoint\&quot;: \&quot;http://localhost:8080\&quot;}
</code></pre>
<p><strong>2. In your Kubernetes Deployment for your client through a volume (named config-volume in this example) you can copy the content of your configmap into the the file env.json under /usr/share/nginx/html/assets/json.</strong></p>
<pre><code>  containers:
  - image: your_client_image
    imagePullPolicy: Always
    name: your_client
    ports:
    - containerPort: 80
      name: http
    volumeMounts:
      - mountPath: /usr/share/nginx/html/assets/json
        name: config-volume
  volumes:
  - configMap:
      name: client-config
    name: config-volume
</code></pre>
