Skip to content
This repository was archived by the owner on Apr 13, 2020. It is now read-only.

Commit 8e4905a

Browse files
evanlouiebnookala
authored andcommitted
Private Helm Git Repo Repository Support
This PR adds the ability to specify an environment variable `accessTokenVariable` per service tracked in `bedrock.yaml`. This env variable will automatically be injected into `access.yaml` as a the holder of a PAT to use while cloning the value specified in `--helm-config-git` in `hld reconcile`. closes microsoft/bedrock#914
1 parent ee6a8c1 commit 8e4905a

File tree

9 files changed

+221
-104
lines changed

9 files changed

+221
-104
lines changed

guides/auth-private-helm-repos.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Private Helm/Git Repositories -- Authorization/PAT For HLD to Materialized Pipeline
2+
3+
An operator may want to store their Helm charts in a different repository than
4+
their application code. In this scenario, the operators Helm chart git
5+
repository will most likely be private; making the ability to clone it in the
6+
HLD-to-Materialized pipeline an issue. To facilitate the ability to clone the
7+
Helm chart repository, we can piggy back off the ability for
8+
[Fabrikate to consume env variables consuming personal access tokens (PATs)](https://github.com/microsoft/fabrikate/blob/master/docs/auth.md).
9+
10+
## Utilizing The Default PAT (ACCESS_TOKEN_SECRET)
11+
12+
By default, all services created via `spk service create` with the the
13+
`--helm-config-*` family of options will be setup to consume the environment
14+
variable `ACCESS_TOKEN_SECRET` -- The PAT used to clone the application
15+
repository in the HLD-to-Materialized pipeline. So if the PAT used to setup your
16+
HLD-to-Materialized pipeline has full read access to the Azure DevOps
17+
organizations your Helm git repositories are stored, the pipeline is all set to
18+
clone the Helm charts by default.
19+
20+
## Making The Pipeline Aware of Custom Environment Variables
21+
22+
In order to tell the pipeline that it needs to utilize a PAT stored in a user
23+
defined environment variable in the HLD-to-Materialized pipeline, the
24+
environment variable name -- not the PAT itself -- needs to be tracked in the
25+
`bedrock.yaml`. This environment variable will be used to clone the `https` git
26+
URI for the Helm chart git repository.
27+
28+
Visit https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables
29+
for more information on how to add a variables to your pipeline.
30+
31+
### Setting Up At Service Create Time
32+
33+
If you already have a environment variable name in mind you want to consume or
34+
already have it available in your pipeline before you create your service, you
35+
can make it aware of it via the `--helm-config-access-token-variable` flag in
36+
the `spk service create` command.
37+
38+
```sh
39+
spk service create my-service \
40+
--helm-config-git https://dev.azure.com/my-org/my-project/_git/my-repo \
41+
--helm-config-branch master \
42+
--helm-config-path my-service-helm-chart \
43+
--helm-config-access-token-variable MY_ENV_VAR
44+
```
45+
46+
**Note**: it is important that the git URI you pass is an `https` URI and does
47+
NOT contain a username in it. By default, the clone URIs that the Azure DevOps
48+
creates presents in the UI contain your username in them (eg.
49+
`https://<my-username>@dev.azure.com/my-org/my-project/_git/my-repo`). Fabrikate
50+
will not inject the PAT if the username is there as the value contained in place
51+
of the username can be a PAT itself.
52+
53+
`MY_ENV_VAR` will be tracked in the service definition in your `bedrock.yaml`:
54+
55+
```yaml
56+
rings:
57+
master:
58+
isDefault: true
59+
services:
60+
./my-service:
61+
displayName: ""
62+
helm:
63+
chart:
64+
accessTokenVariable: MY_ENV_VAR # Note: this is where the environment variable gets tracked
65+
branch: master
66+
git: "https://dev.azure.com/my-org/my-project/_git/my-repo" # Note: it is important that the HTTPS URI does NOT contain your username
67+
path: my-service-helm-chart
68+
k8sBackend: ""
69+
k8sBackendPort: 80
70+
middlewares: []
71+
pathPrefix: ""
72+
pathPrefixMajorVersion: ""
73+
variableGroups:
74+
- my-var-group
75+
```
76+
77+
### Updating/Changing The Environment Variable
78+
79+
If you want to change the the environment variable used after creating your
80+
service, simply change the value of `accessTokenVariable` in your `bedrock.yaml`
81+
to the target environment variable (and ensure that the environment variable
82+
exists in your HLD-to-Materialized pipeline).

src/commands/hld/reconcile.test.ts

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import path from "path";
12
import { create as createBedrockYaml } from "../../lib/bedrockYaml";
23
import { disableVerboseLogging, enableVerboseLogging } from "../../logger";
3-
4+
import { IBedrockFile, IBedrockServiceConfig } from "../../types";
45
import {
56
addChartToRing,
67
checkForFabrikate,
@@ -21,8 +22,6 @@ import {
2122
} from "./reconcile";
2223
import * as reconcile from "./reconcile";
2324

24-
import { IBedrockFile, IBedrockServiceConfig } from "../../types";
25-
2625
beforeAll(() => {
2726
enableVerboseLogging();
2827
});
@@ -270,21 +269,22 @@ describe("addChartToRing", () => {
270269

271270
const branch = "v1";
272271
const git = "github.com/company/service";
273-
const path = "/charts/service";
272+
const chartPath = "/charts/service";
274273

275274
const serviceConfig: IBedrockServiceConfig = {
276275
helm: {
277276
chart: {
278277
branch,
279278
git,
280-
path
279+
path: chartPath
281280
}
282281
},
283282
k8sBackendPort: 1337
284283
};
285284

286285
/* tslint:disable-next-line: no-string-literal */
287-
const addHelmChartCommand = `fab add chart --source ${git} --path ${path} --branch ${branch} --type helm`;
286+
const addHelmChartCommand = `fab add chart --source ${git} --path ${chartPath} --branch ${branch} --type helm`;
287+
288288
const expectedInvocation = `cd ${ringPath} && ${addHelmChartCommand}`;
289289

290290
await addChartToRing(exec, ringPath, serviceConfig);
@@ -298,21 +298,22 @@ describe("addChartToRing", () => {
298298

299299
const sha = "f8a33e1d";
300300
const git = "github.com/company/service";
301-
const path = "/charts/service";
301+
const chartPath = "/charts/service";
302302

303303
const serviceConfig: IBedrockServiceConfig = {
304304
helm: {
305305
chart: {
306306
git,
307-
path,
307+
path: chartPath,
308308
sha
309309
}
310310
},
311311
k8sBackendPort: 1337
312312
};
313313

314314
/* tslint:disable-next-line: no-string-literal */
315-
const addHelmChartCommand = `fab add chart --source ${git} --path ${path} --version ${sha} --type helm`;
315+
const addHelmChartCommand = `fab add chart --source ${git} --path ${chartPath} --version ${sha} --type helm`;
316+
316317
const expectedInvocation = `cd ${ringPath} && ${addHelmChartCommand}`;
317318

318319
await addChartToRing(exec, ringPath, serviceConfig);
@@ -425,8 +426,8 @@ describe("reconcile tests", () => {
425426
let bedrockYaml: IBedrockFile;
426427
const sha = "f8a33e1d";
427428
const git = "github.com/company/service";
428-
const path = "/charts/service";
429-
429+
const pathToChart = "/charts/service";
430+
const accessTokenVariable = "SECRET_TOKEN";
430431
beforeEach(() => {
431432
dependencies = {
432433
addChartToRing: jest.fn().mockReturnValue(Promise.resolve({})),
@@ -452,12 +453,13 @@ describe("reconcile tests", () => {
452453
prod: {}
453454
},
454455
services: {
455-
"./path/to/svc/": {
456+
"./path/to/a/svc/": {
456457
disableRouteScaffold: false,
457458
helm: {
458459
chart: {
460+
accessTokenVariable,
459461
git,
460-
path,
462+
path: pathToChart,
461463
sha
462464
}
463465
},
@@ -486,6 +488,12 @@ describe("reconcile tests", () => {
486488
expect(dependencies.createStaticComponent).toHaveBeenCalledTimes(2);
487489
expect(dependencies.createMiddlewareForRing).toHaveBeenCalledTimes(2);
488490
expect(dependencies.createIngressRouteForRing).toHaveBeenCalledTimes(2);
491+
expect(dependencies.generateAccessYaml).toHaveBeenCalledTimes(1);
492+
expect(dependencies.generateAccessYaml).toBeCalledWith(
493+
"path/to/hld/service",
494+
git,
495+
accessTokenVariable
496+
);
489497
});
490498

491499
it("should be able to create a HLD without rings, when no rings are provided", async () => {
@@ -519,7 +527,7 @@ describe("reconcile tests", () => {
519527
helm: {
520528
chart: {
521529
git,
522-
path,
530+
path: pathToChart,
523531
sha
524532
}
525533
},
@@ -597,7 +605,7 @@ describe("reconcile tests", () => {
597605
helm: {
598606
chart: {
599607
git,
600-
path,
608+
path: pathToChart,
601609
sha
602610
}
603611
},
@@ -626,7 +634,7 @@ describe("reconcile tests", () => {
626634
helm: {
627635
chart: {
628636
git,
629-
path,
637+
path: pathToChart,
630638
sha
631639
}
632640
},
@@ -659,7 +667,7 @@ describe("reconcile tests", () => {
659667
helm: {
660668
chart: {
661669
git,
662-
path,
670+
path: pathToChart,
663671
sha
664672
}
665673
},
@@ -681,6 +689,43 @@ describe("reconcile tests", () => {
681689
(dependencies.createServiceComponent as jest.Mock).mock.calls[0][2]
682690
).toBe(displayName);
683691
});
692+
693+
it("properly updates access.yaml", async () => {
694+
const anotherGit = "github.com/foobar/baz";
695+
const anotherToken = "MY_FANCY_ENV_VAR";
696+
bedrockYaml.services["another/service"] = {
697+
disableRouteScaffold: false,
698+
helm: {
699+
chart: {
700+
accessTokenVariable: anotherToken,
701+
git: anotherGit,
702+
path: "path/to/chart",
703+
sha: "12345"
704+
}
705+
},
706+
k8sBackendPort: 8888
707+
};
708+
const pathToHLD = "./the/path/to/hld";
709+
const service = "service";
710+
await reconcileHld(
711+
dependencies,
712+
bedrockYaml,
713+
service,
714+
pathToHLD,
715+
"./path/to/app"
716+
);
717+
expect(dependencies.generateAccessYaml).toHaveBeenCalledTimes(2);
718+
expect(dependencies.generateAccessYaml).toHaveBeenCalledWith(
719+
path.join(pathToHLD, service),
720+
git,
721+
accessTokenVariable
722+
);
723+
expect(dependencies.generateAccessYaml).toHaveBeenCalledWith(
724+
path.join(pathToHLD, service),
725+
anotherGit,
726+
anotherToken
727+
);
728+
});
684729
});
685730

686731
describe("normalizedName", () => {

0 commit comments

Comments
 (0)