Skip to content

Commit 219b040

Browse files
authored
Merge pull request aws-samples#2 from aws-samples/feature/usage-tracking
Feature/usage tracking
2 parents b0a0e09 + e137393 commit 219b040

File tree

7 files changed

+142
-132
lines changed

7 files changed

+142
-132
lines changed

.github/workflows/ci.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212

1313
strategy:
1414
matrix:
15-
node-version: [12.18]
15+
node-version: [14]
1616

1717
steps:
1818
- uses: actions/checkout@v2

bin/main.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ new MultiTeamConstruct(app, 'multi-team');
1616
//-------------------------------------------
1717

1818
import MultiRegionConstruct from '../lib/multi-region-construct'
19-
new MultiRegionConstruct(app, 'multi-region');
19+
new MultiRegionConstruct().buildAsync(app, 'multi-region').catch(() => {
20+
console.log("Multi region pattern is not setup due to missing secrets for GitHub access and ArgoCD admin pwd.");
21+
});
2022

2123

2224
//-------------------------------------------
@@ -30,13 +32,16 @@ new FargateConstruct(app, 'fargate');
3032
//-------------------------------------------
3133
// Multiple clusters with deployment pipeline.
3234
//-------------------------------------------
33-
34-
import PipelineStack from '../lib/pipeline-stack'
35-
const account = process.env.CDK_DEFAULT_ACCOUNT
36-
const region = process.env.CDK_DEFAULT_REGION
37-
const env = { account, region }
38-
new PipelineStack(app, 'pipeline', { env });
39-
35+
import PipelineConstruct from '../lib/pipeline-stack';
36+
const account = process.env.CDK_DEFAULT_ACCOUNT;
37+
const region = process.env.CDK_DEFAULT_REGION;
38+
const env = { account, region };
39+
if(account) {
40+
new PipelineConstruct(app, 'pipeline', { env });
41+
}
42+
else {
43+
console.log("Valid AWS credentials are required to synthesize pipeline stack. Please run 'aws configure'");
44+
}
4045

4146
//-------------------------------------------
4247
// Single cluster with Bottlerocket nodes.
@@ -53,5 +58,7 @@ new BottleRocketConstruct(app, 'bottlerocket');
5358
import CustomClusterConstruct from '../lib/custom-cluster-construct'
5459
new CustomClusterConstruct(app, 'custom-cluster');
5560

61+
import ScratchpadConstruct from '../lib/scratchpad'
62+
new ScratchpadConstruct(app, 'scratchpad');
5663

5764

lib/multi-region-construct/index.ts

+53-46
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import * as cdk from '@aws-cdk/core';
22

33
// SSP Lib
4-
import * as ssp from '@shapirov/cdk-eks-blueprint'
5-
import { ArgoCDAddOn } from '@shapirov/cdk-eks-blueprint';
4+
import * as ssp from '@shapirov/cdk-eks-blueprint';
5+
6+
import { getSecretValue } from '@shapirov/cdk-eks-blueprint/dist/utils/secrets-manager-utils';
67

78
// Team implementations
89
import * as team from '../teams'
@@ -15,71 +16,77 @@ import * as team from '../teams'
1516
* - github-ssh-test - containing SSH key for github authentication (plaintext in AWS Secrets manager)
1617
* - argo-admin-secret - containing the initial admin secret for ArgoCD (e.g. CLI and UI access)
1718
*/
18-
export default class MultiRegionConstruct extends cdk.Construct {
19-
constructor(scope: cdk.Construct, id: string) {
20-
super(scope, id);
19+
export default class MultiRegionConstruct {
2120

22-
// Setup platform team
23-
const accountID = process.env.CDK_DEFAULT_ACCOUNT!
24-
const platformTeam = new team.TeamPlatform(accountID)
25-
const teams: Array<ssp.Team> = [
26-
platformTeam,
27-
new team.TeamTroiSetup,
28-
new team.TeamRikerSetup,
29-
new team.TeamBurnhamSetup(scope)
30-
];
21+
static readonly SECRET_GIT_SSH_KEY = 'github-ssh-key';
22+
static readonly SECRET_ARGO_ADMIN_PWD = 'argo-admin-secret';
3123

32-
// AddOns for the cluster.
33-
const addOns: Array<ssp.ClusterAddOn> = [
34-
new ssp.NginxAddOn,
35-
new ssp.CalicoAddOn,
36-
new ssp.MetricsServerAddOn,
37-
new ssp.ClusterAutoScalerAddOn,
38-
new ssp.ContainerInsightsAddOn,
39-
];
24+
async buildAsync(scope: cdk.Construct, id: string) : Promise<ssp.EksBlueprint[]> {
25+
// Setup platform team
26+
const accountID = process.env.CDK_DEFAULT_ACCOUNT!;
27+
const gitUrl = 'https://github.com/aws-samples/ssp-eks-workloads.git';
28+
const gitSecureUrl = '[email protected]:aws-samples/ssp-eks-workloads.git';
4029

41-
const gitUrl = 'https://github.com/aws-samples/ssp-eks-workloads.git'
30+
try {
31+
await getSecretValue(MultiRegionConstruct.SECRET_GIT_SSH_KEY, 'us-east-2');
32+
await getSecretValue(MultiRegionConstruct.SECRET_ARGO_ADMIN_PWD, 'us-west-2');
33+
}
34+
catch(error) {
35+
throw new Error("Both github-ssh-key and argo-admin-secret secrets must be setup for the multi-region pattern to work.");
36+
}
37+
38+
const blueprint = ssp.EksBlueprint.builder()
39+
.account(process.env.CDK_DEFAULT_ACCOUNT!)
40+
.addons(new ssp.NginxAddOn,
41+
new ssp.CalicoAddOn,
42+
new ssp.MetricsServerAddOn,
43+
new ssp.ClusterAutoScalerAddOn,
44+
new ssp.ContainerInsightsAddOn)
45+
.teams( new team.TeamPlatform(accountID),
46+
new team.TeamTroiSetup,
47+
new team.TeamRikerSetup,
48+
new team.TeamBurnhamSetup(scope));
4249

43-
const devBootstrapArgo = new ArgoCDAddOn({
50+
const devBootstrapArgo = new ssp.ArgoCDAddOn({
4451
bootstrapRepo: {
4552
repoUrl: gitUrl,
4653
path: 'envs/dev'
4754
}
4855
});
4956

50-
const testBootstrapArgo = new ArgoCDAddOn({
57+
const testBootstrapArgo = new ssp.ArgoCDAddOn({
5158
bootstrapRepo: {
52-
repoUrl: '[email protected]:aws-samples/ssp-eks-workloads.git',
59+
repoUrl: gitSecureUrl,
5360
path: 'envs/test',
54-
credentialsSecretName: 'github-ssh-key',
61+
credentialsSecretName: MultiRegionConstruct.SECRET_GIT_SSH_KEY,
5562
credentialsType: 'SSH'
5663
},
57-
5864
});
5965

60-
const prodBootstrapArgo = new ArgoCDAddOn({
66+
const prodBootstrapArgo = new ssp.ArgoCDAddOn({
6167
bootstrapRepo: {
62-
repoUrl: '[email protected]:aws-samples/ssp-eks-workloads.git',
68+
repoUrl: gitSecureUrl,
6369
path: 'envs/prod',
64-
credentialsSecretName: 'github-ssh-key',
70+
credentialsSecretName: MultiRegionConstruct.SECRET_GIT_SSH_KEY,
6571
credentialsType: 'SSH'
6672
},
67-
adminPasswordSecretName: 'argo-admin-secret',
68-
});
69-
70-
const east1 = 'us-east-1';
71-
new ssp.EksBlueprint(scope, { id: `${id}-${east1}`, addOns: addOns.concat(devBootstrapArgo), teams }, {
72-
env: { region: east1 }
73-
});
74-
75-
const east2 = 'us-east-2';
76-
new ssp.EksBlueprint(scope, { id: `${id}-${east2}`, addOns: addOns.concat(testBootstrapArgo), teams }, {
77-
env: { region: east2 }
73+
adminPasswordSecretName: MultiRegionConstruct.SECRET_ARGO_ADMIN_PWD,
7874
});
75+
76+
const east1 = await blueprint.clone('us-east-1')
77+
.addons(devBootstrapArgo)
78+
.buildAsync(scope, `${id}-us-east-1`);
79+
80+
const east2 = await blueprint.clone('us-east-2')
81+
.addons(testBootstrapArgo)
82+
.buildAsync(scope, `${id}-us-east-2`);
83+
84+
const west2 = await blueprint.clone('us-west-2')
85+
.addons(prodBootstrapArgo)
86+
.buildAsync(scope, `${id}-us-west-2`);
7987

80-
const west2 = 'us-west-2'
81-
new ssp.EksBlueprint(scope, { id: `${id}-${west2}`, addOns: addOns.concat(prodBootstrapArgo), teams }, {
82-
env: { region: west2 }
83-
});
88+
return [ east1, east2, west2 ];
8489
}
8590
}
91+
92+

lib/pipeline-stack/index.ts

+34-72
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,44 @@
11
import * as cdk from '@aws-cdk/core';
2-
import * as pipelines from '@aws-cdk/pipelines';
3-
import * as codepipeline from '@aws-cdk/aws-codepipeline';
4-
import * as actions from '@aws-cdk/aws-codepipeline-actions';
2+
import { StackProps } from '@aws-cdk/core';
53

64
// SSP Lib
75
import * as ssp from '@shapirov/cdk-eks-blueprint'
86

97
// Team implementations
108
import * as team from '../teams'
119

12-
export default class PipelineStack extends cdk.Stack {
13-
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
14-
super(scope, id)
15-
16-
const pipeline = this.buildPipeline(this)
17-
18-
// Dev cluster.
19-
const stage1 = new ClusterStage(this, 'blueprint-dev')
20-
pipeline.addApplicationStage(stage1);
21-
22-
// Staging cluster
23-
const stage2 = new ClusterStage(this, 'blueprint-staging')
24-
pipeline.addApplicationStage(stage2);
25-
26-
// Production cluster
27-
const stageOpts = { manualApprovals: true }
28-
const stage3 = new ClusterStage(this, 'blueprint-production')
29-
pipeline.addApplicationStage(stage3, stageOpts);
30-
}
31-
32-
private buildPipeline = (scope: cdk.Construct) => {
33-
const sourceArtifact = new codepipeline.Artifact();
34-
const cloudAssemblyArtifact = new codepipeline.Artifact();
35-
36-
const sourceAction = new actions.GitHubSourceAction({
37-
actionName: 'GitHub',
38-
owner: 'aws-quickstart',
39-
repo: 'quickstart-ssp-amazon-eks',
40-
branch: 'main',
41-
output: sourceArtifact,
42-
oauthToken: cdk.SecretValue.secretsManager('github-token'),
43-
})
44-
45-
// Use this if you need a build step (if you're not using ts-node
46-
// or if you have TypeScript Lambdas that need to be compiled).
47-
const synthAction = pipelines.SimpleSynthAction.standardNpmSynth({
48-
sourceArtifact,
49-
cloudAssemblyArtifact,
50-
buildCommand: 'npm run build',
51-
})
52-
53-
return new pipelines.CdkPipeline(scope, 'FactoryPipeline', {
54-
pipelineName: 'FactoryPipeline',
55-
cloudAssemblyArtifact,
56-
sourceAction,
57-
synthAction
58-
});
59-
}
60-
}
61-
62-
export class ClusterStage extends cdk.Stage {
63-
constructor(scope: cdk.Stack, id: string, props?: cdk.StageProps) {
64-
super(scope, id, props);
65-
66-
// Setup platform team
67-
const accountID = props?.env?.account
68-
const platformTeam = new team.TeamPlatform(accountID!)
69-
const teams: Array<ssp.Team> = [platformTeam];
70-
71-
// AddOns for the cluster.
72-
const addOns: Array<ssp.ClusterAddOn> = [
73-
new ssp.NginxAddOn,
74-
new ssp.ArgoCDAddOn,
75-
new ssp.CalicoAddOn,
76-
new ssp.MetricsServerAddOn,
77-
new ssp.ClusterAutoScalerAddOn,
78-
new ssp.ContainerInsightsAddOn,
79-
];
80-
new ssp.EksBlueprint(this, { id: 'eks', addOns, teams }, props);
10+
export default class PipelineConstruct extends cdk.Construct {
11+
12+
constructor(scope: cdk.Construct, id: string, props?: StackProps) {
13+
super(scope, id);
14+
const account = process.env.CDK_DEFAULT_ACCOUNT!;
15+
const blueprint = ssp.EksBlueprint.builder()
16+
.account(account) // the supplied default will fail, but build and synth will pass
17+
.region('us-west-1')
18+
.addons(new ssp.NginxAddOn,
19+
new ssp.ArgoCDAddOn,
20+
new ssp.CalicoAddOn,
21+
new ssp.MetricsServerAddOn,
22+
new ssp.ClusterAutoScalerAddOn,
23+
new ssp.ContainerInsightsAddOn)
24+
.teams(new team.TeamRikerSetup);
25+
26+
ssp.CodePipelineStack.builder()
27+
.name("ssp-eks-pipeline")
28+
.owner("aws-samples")
29+
.repository({
30+
repoUrl: 'ssp-eks-patterns',
31+
credentialsSecretName: 'github-token',
32+
branch: 'feature/usage-tracking'
33+
})
34+
.stage({
35+
id: 'us-west-1-managed-ssp',
36+
stackBuilder: blueprint.clone('us-west-1')
37+
})
38+
.stage({
39+
id: 'us-east-2-managed-ssp',
40+
stackBuilder: blueprint.clone('us-east-2')
41+
})
42+
.build(scope, "ssp-pipeline-stack", props);
8143
}
8244
}

lib/scratchpad/index.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import * as cdk from '@aws-cdk/core';
2+
import {KubernetesVersion} from '@aws-cdk/aws-eks';
3+
4+
// SSP Lib
5+
import * as ssp from '@shapirov/cdk-eks-blueprint';
6+
import { EC2ClusterProvider } from '@shapirov/cdk-eks-blueprint';
7+
8+
9+
export default class ScratchpadConstruct extends cdk.Construct {
10+
constructor(scope: cdk.Construct, id: string) {
11+
super(scope, id);
12+
// AddOns for the cluster.
13+
const addOns: Array<ssp.ClusterAddOn> = [
14+
new ssp.AwsLoadBalancerControllerAddOn,
15+
new ssp.NginxAddOn,
16+
new ssp.MetricsServerAddOn,
17+
new ssp.ClusterAutoScalerAddOn
18+
];
19+
20+
const stackID = `${id}-blueprint`;
21+
22+
const clusterProvider = new EC2ClusterProvider( {
23+
desiredSize: 3,
24+
maxSize: 3,
25+
version: KubernetesVersion.V1_20
26+
});
27+
28+
new ssp.EksBlueprint(scope, { id: stackID, addOns, clusterProvider }, {
29+
env: {
30+
region: 'us-east-2',
31+
},
32+
});
33+
}
34+
}

package.json

+3-4
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@
1414
"lint": "npx eslint . --ext .js,.jsx,.ts,.tsx"
1515
},
1616
"devDependencies": {
17-
"@aws-cdk/assert": "1.113.0",
1817
"@types/jest": "^26.0.10",
1918
"@types/node": "10.17.27",
2019
"@typescript-eslint/eslint-plugin": "^4.23.0",
2120
"@typescript-eslint/parser": "^4.23.0",
22-
"aws-cdk": "1.113.0",
21+
"aws-cdk": "1.119.0",
2322
"copyfiles": "^2.4.1",
2423
"eslint": "^7.26.0",
2524
"jest": "^26.4.2",
@@ -28,8 +27,8 @@
2827
"typescript": "~3.9.7"
2928
},
3029
"dependencies": {
31-
"@aws-cdk/core": "1.113.0",
32-
"@shapirov/cdk-eks-blueprint": "^0.11.1",
30+
"@aws-cdk/core": "1.119.0",
31+
"@shapirov/cdk-eks-blueprint": "0.12.0",
3332
"source-map-support": "^0.5.16"
3433
}
3534
}

tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"dist"
3434
],
3535
"include": [
36-
"lib"
36+
"lib",
37+
"examples"
3738
]
3839
}

0 commit comments

Comments
 (0)