Skip to content

Commit

Permalink
feat: make cluster region and account agnostic and use context variab…
Browse files Browse the repository at this point in the history
…les (#2)
  • Loading branch information
twelvemo committed Apr 11, 2023
1 parent a2c3ea7 commit bb17915
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 45 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
# Dev cluster on AWS via AWS CDK and Cloudformation
# Dev cluster on AWS via AWS CDK and Cloudformation

## Inputs

* domain e.g. dev.marketplace.sys.garden
* hosted zone id
```
aws route53 list-hosted-zones-by-name --dns-name dev.marketplace.sys.garden
```
* user arns or role arn to add to the aws-auth configmap
7 changes: 6 additions & 1 deletion cdk.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"app": "npx ts-node main.ts",
"context": {}
"context": {
"hostedZoneId": "Z028702323WOQ31QJAJJP",
"subdomainName": "dev.marketplace.sys.garden",
"iamUsers": "",
"iamRole": "arn:aws:sts::049586690729:assumed-role/AWSReservedSSO_AdministratorAccess_b3c1cae6dc09120a"
}
}
69 changes: 46 additions & 23 deletions cluster.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import * as blueprints from "@aws-quickstart/eks-blueprints";
import {
GlobalResources,
utils,
ImportHostedZoneProvider,
} from "@aws-quickstart/eks-blueprints";
import { Construct } from "constructs";
import { TeamPlatform } from "./teams";
import * as cdk from "aws-cdk-lib";
import * as eks from "aws-cdk-lib/aws-eks";
import * as iam from "aws-cdk-lib/aws-iam";
import { ECRRepository } from "./ecr";
import { KubernetesVersion } from "aws-cdk-lib/aws-eks";
import { DeployImagePullSecret } from "./pullsecret";

//const burnhamManifestDir = './lib/teams/team-burnham/'
//const rikerManifestDir = './lib/teams/team-riker/'
//const teamManifestDirList = [burnhamManifestDir, rikerManifestDir]
import { ArnPrincipal } from "aws-cdk-lib/aws-iam";
import { StackProps } from "aws-cdk-lib";

const accountID = process.env.CDK_DEFAULT_ACCOUNT!;
const gitUrl = "https://github.com/aws-samples/eks-blueprints-workloads.git";
Expand All @@ -24,34 +20,61 @@ const gitUrl = "https://github.com/aws-samples/eks-blueprints-workloads.git";
* See docs/patterns/nginx.md for mode details on the setup.
*/
export default class DevCluster extends cdk.Stack {
async eksCluster(scope: Construct, id: string) {
const repoNames: string[] = ["api", "result", "vote", "worker"];
// new ECRRepository(repoNames, this, 'garden-repo')
async eksCluster(scope: Construct, id: string, props: StackProps) {
const accountId = cdk.Stack.of(this).account
const region = cdk.Stack.of(this).region

const teams: Array<blueprints.Team> = [new TeamPlatform(accountID)];

const subdomain: string = utils.valueFromContext(
scope,
"dev.marketplace",
"sys.garden"
);
const subdomainName = new cdk.CfnParameter(this, "subdomain", {
type: "String",
description: "The subdomain that can be used for ingress to the development environments\
e.g. garden.mycompany.com. \
Needs to be a hosted domain in Route53RecordTarget."}).valueAsString;

blueprints.HelmAddOn.validateHelmVersions = false;
//unfortunately we can't use this lookup for env agnostic stacks (need to specify region)
// https://docs.aws.amazon.com/cdk/v2/guide/resources.html#resources_external
// const domainID = route53.HostedZone.fromLookup(this, id, {domainName: subdomainName})

const hostedZoneId = new cdk.CfnParameter(this, "hostedZoneId", {
type: "AWS::Route53::HostedZone::Id",
description: "The ID of the Route53 hosted zone with the domain that can be used for ingress\
to the development environments"}).valueAsString;

const iamUsers = new cdk.CfnParameter(this, "iamUsers", {
type: "CommaDelimitedList",
default: "",
description: "Comma delimited list of IAM users principal ARNs that should get access to the dev cluster\
e.g. \"arn:aws:iam::123456789012:user/JohnDoe,arn:aws:iam::123456789012:user/Alice\""}).valueAsList;

const iamRole = new cdk.CfnParameter(this, "iamRole", {
type: "String",
default: "arn:aws:sts::049586690729:assumed-role/AWSReservedSSO_AdministratorAccess_b3c1cae6dc09120a",
description: "A role that should get access to the dev cluster e.g.\
\"arn:aws:iam::123456789023:role/AWSReservedSSO_PlatformEngineers_4ed12acae0543\""}).valueAsString;

// use context variables for now because we cannot use CfnParameters
// for these values since we are manipulating the values in the code
const iamUsersArnsCtx = this.node.tryGetContext('iamUsers').split(",").map((item: string) => new ArnPrincipal(item))
const iamRoleArnCtx = this.node.tryGetContext('iamRole')
const subdomainNameCtx = this.node.tryGetContext('subdomainName')
const hostedZoneIdCtx = this.node.tryGetContext('hostedZoneId')
const teams: Array<blueprints.Team> = [new TeamPlatform({userRoleArn: iamRoleArnCtx, users: iamUsersArnsCtx})];

blueprints.HelmAddOn.validateHelmVersions = false;
const cluster = await blueprints.EksBlueprint.builder()
.account("049586690729")
.region("eu-central-1")
.account(accountId)
.region(region)
.version(KubernetesVersion.V1_24)
.teams(...teams)
.resourceProvider(
GlobalResources.HostedZone,
new ImportHostedZoneProvider("Z028702323WOQ31QJAJJP", subdomain)
new ImportHostedZoneProvider(hostedZoneIdCtx, subdomainNameCtx)
)
.resourceProvider(
GlobalResources.Certificate,
new blueprints.CreateCertificateProvider(
"wildcard-cert",
"*.dev.marketplace.sys.garden",
`*${subdomainNameCtx}`,
GlobalResources.HostedZone
)
)
Expand All @@ -61,19 +84,19 @@ export default class DevCluster extends cdk.Stack {
new blueprints.CertManagerAddOn(),
new blueprints.AwsLoadBalancerControllerAddOn(),
new blueprints.ExternalDnsAddOn({
hostedZoneResources: [blueprints.GlobalResources.HostedZone], // you can add more if you register resource providers
hostedZoneResources: [blueprints.GlobalResources.HostedZone],
}),
new blueprints.NginxAddOn({
version: "0.15.2",
internetFacing: true,
backendProtocol: "tcp",
externalDnsHostname: subdomain,
externalDnsHostname: subdomainNameCtx,
crossZoneEnabled: false,
certificateResourceName: GlobalResources.Certificate,
}),
new blueprints.SecretsStoreAddOn({ rotationPollInterval: "120s" }),
new blueprints.ClusterAutoScalerAddOn(),
new DeployImagePullSecret(),
new DeployImagePullSecret({accountId: accountId, region: region}),
new blueprints.NestedStackAddOn({
builder: ECRRepository.builder(),
id: "ecr-nested-stack"
Expand Down
5 changes: 0 additions & 5 deletions ecr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ export class ECRRepository extends cdk.NestedStack {
encryption: ecr.RepositoryEncryption.KMS,
imageScanOnPush: true,
}));
this.ecrRepos.push(new ecr.Repository(this, `${repo}/cache`, {
repositoryName: `garden-demo/${repo}/cache`,
encryption: ecr.RepositoryEncryption.KMS,
imageScanOnPush: true,
}));
}
}
}
5 changes: 1 addition & 4 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@ import { HelmAddOn } from "@aws-quickstart/eks-blueprints";
import DevCluster from "./cluster";

const app = new cdk.App();
const account = "049586690729";
const region = "eu-central-1";
const env: cdk.Environment = { account: account, region: region };
HelmAddOn.validateHelmVersions = false;

new DevCluster().eksCluster(app, `dev-cluster`).catch(() => {
new DevCluster().eksCluster(app, `dev-cluster`, {crossRegionReferences: true}).catch(() => {
logger.info("Error setting up dev cluster");
});
15 changes: 10 additions & 5 deletions pullsecret.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { KubernetesManifest } from "aws-cdk-lib/aws-eks";
import { ClusterAddOn, ClusterInfo } from "@aws-quickstart/eks-blueprints";
import * as blueprints from "@aws-quickstart/eks-blueprints";


export interface ImagePullSecretAddOnProps{
readonly accountId: string
readonly region: string
}
export class DeployImagePullSecret implements ClusterAddOn {
readonly imagePullSecretAddOnProps: ImagePullSecretAddOnProps;
constructor(imagePullSecretAddOnProps: ImagePullSecretAddOnProps){
this.imagePullSecretAddOnProps = imagePullSecretAddOnProps
};
deploy(clusterInfo: ClusterInfo): void {
const accountID = process.env.CDK_DEFAULT_ACCOUNT!;
const cluster = clusterInfo.cluster;
const region = "eu-central-1"
const ecrURL = `${accountID}.dkr.ecr.${region}.amazonaws.com`
const ecrURL = `${this.imagePullSecretAddOnProps.accountId}.dkr.ecr.${this.imagePullSecretAddOnProps.region}.amazonaws.com`
let secretValue = {
credHelpers: {
[ecrURL]: "ecr-login"
Expand Down
32 changes: 26 additions & 6 deletions teams.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
import { PlatformTeam } from "@aws-quickstart/eks-blueprints";
import { PlatformTeam, TeamProps } from "@aws-quickstart/eks-blueprints";
import { ArnPrincipal } from "aws-cdk-lib/aws-iam";

interface TeamPlatformProps {
userRoleArn?: string
users?: ArnPrincipal[]
}
export class TeamPlatform extends PlatformTeam {
constructor(accountID: string) {
super({
name: "platform",
userRoleArn: `arn:aws:iam::${accountID}:role/AWSReservedSSO_AdministratorAccess_b3c1cae6dc09120a`,
});
constructor(teamPlatformProps: TeamPlatformProps) {
if (teamPlatformProps.userRoleArn && teamPlatformProps.users){
super({
name: "platform",
userRoleArn: teamPlatformProps.userRoleArn,
users: teamPlatformProps.users
});
}
if (!teamPlatformProps.userRoleArn && teamPlatformProps.users){
super({
name: "platform",
users: teamPlatformProps.users
});
}
if (teamPlatformProps.userRoleArn && !teamPlatformProps.users){
super({
name: "platform",
userRoleArn: teamPlatformProps.userRoleArn
});
}
}
}

0 comments on commit bb17915

Please sign in to comment.