Skip to content

Commit

Permalink
Jeanschmidt - Add partially multi-region logic && separate VPCs for c…
Browse files Browse the repository at this point in the history
…anary and main (#1089)

* Introduce the core logic for multi-region;
* creates two VPCs with 1 network on each sub-region AZ, instead of one
VPC with 2 networks in each sub-region AZ;
* separates canary and main VPCs;

the `vpc-double` module is not used anymore, but its usage need to be
deprecated in a next commit as current runners still depends on it;
  • Loading branch information
jeanschmidt authored Nov 18, 2022
1 parent 7f8b81d commit e7b07d2
Show file tree
Hide file tree
Showing 19 changed files with 1,009 additions and 467 deletions.
12 changes: 7 additions & 5 deletions terraform-aws-github-runner/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ module "webhook" {
module "runners" {
source = "./modules/runners"

aws_region = var.aws_region
vpc_id = var.vpc_id
subnet_ids = var.subnet_ids
environment = var.environment
tags = local.tags
aws_region = var.aws_region
aws_region_instances = var.aws_region_instances
vpc_ids = var.vpc_ids
subnet_ids = var.subnet_ids
environment = var.environment
tags = local.tags

encryption = {
kms_key_id = local.kms_key_id
encrypt = var.encrypt_secrets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ variable "syncer_lambda_s3_object_version" {
}

variable "lambda_subnet_ids" {
description = "List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`."
description = "List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_ids`."
type = list(string)
default = []
}

variable "lambda_security_group_ids" {
description = "List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`."
description = "List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_ids`."
type = list(string)
default = []
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"build": "ncc build src/lambda.ts -o dist",
"dist": "yarn build && cd dist && zip ../runners.zip index.js",
"format": "prettier --write \"**/*.ts\"",
"format-check": "prettier --check \"**/*.ts\""
"format-check": "prettier --check \"**/*.ts\"",
"commit-check": "yarn format && yarn lint && yarn test && yarn build"
},
"devDependencies": {
"@types/aws-lambda": "^8.10.72",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ describe('Config', () => {
process.env.SCALE_CONFIG_REPO_PATH = '.gh/the.yaml';
process.env.SECRETSMANAGER_SECRETS_ID = 'SECRETSMANAGER_SECRETS_ID';
process.env.SECURITY_GROUP_IDS = 'SECURITY_GROUP_IDS1,SECURITY_GROUP_IDS2,SECURITY_GROUP_IDS3';
process.env.SUBNET_IDS = 'SUBNET_IDS1,SUBNET_IDS2,SUBNET_IDS3';
process.env.SUBNET_IDS =
'AWS_REGION|SUBNET_IDS1,AWS_REGION|SUBNET_IDS2,AWS_REGION_INSTANCES_1|SUBNET_IDS3' +
',AWS_REGION_INSTANCES_2|SUBNET_IDS4';

expect(Config.Instance.awsRegion).toBe('AWS_REGION');
expect(Config.Instance.awsRegionInstances).toEqual([
Expand Down Expand Up @@ -75,10 +77,28 @@ describe('Config', () => {
'SECURITY_GROUP_IDS2',
'SECURITY_GROUP_IDS3',
]);
expect(Config.Instance.shuffledSubnetIds).toContain('SUBNET_IDS1');
expect(Config.Instance.shuffledSubnetIds).toContain('SUBNET_IDS2');
expect(Config.Instance.shuffledSubnetIds).toContain('SUBNET_IDS3');
expect(Config.Instance.subnetIds).toEqual(['SUBNET_IDS1', 'SUBNET_IDS2', 'SUBNET_IDS3']);
expect(Config.Instance.subnetIds.size).toEqual(3);
expect(Config.Instance.subnetIds.keys()).toContain('AWS_REGION');
expect(Config.Instance.subnetIds.keys()).toContain('AWS_REGION_INSTANCES_1');
expect(Config.Instance.subnetIds.keys()).toContain('AWS_REGION_INSTANCES_2');
expect(Config.Instance.subnetIds.get('AWS_REGION')?.size).toEqual(2);
expect(Config.Instance.subnetIds.get('AWS_REGION')).toContain('SUBNET_IDS1');
expect(Config.Instance.subnetIds.get('AWS_REGION')).toContain('SUBNET_IDS2');
expect(Config.Instance.subnetIds.get('AWS_REGION_INSTANCES_1')?.size).toEqual(1);
expect(Config.Instance.subnetIds.get('AWS_REGION_INSTANCES_1')).toContain('SUBNET_IDS3');
expect(Config.Instance.subnetIds.get('AWS_REGION_INSTANCES_2')?.size).toEqual(1);
expect(Config.Instance.subnetIds.get('AWS_REGION_INSTANCES_2')).toContain('SUBNET_IDS4');
expect(Config.Instance.shuffledAwsRegionInstances.length).toEqual(3);
expect(Config.Instance.shuffledAwsRegionInstances).toContain('AWS_REGION');
expect(Config.Instance.shuffledAwsRegionInstances).toContain('AWS_REGION_INSTANCES_2');
expect(Config.Instance.shuffledAwsRegionInstances).toContain('AWS_REGION_INSTANCES_1');
expect(Config.Instance.shuffledSubnetIdsForAwsRegion('AWS_REGION').length).toEqual(2);
expect(Config.Instance.shuffledSubnetIdsForAwsRegion('AWS_REGION')).toContain('SUBNET_IDS1');
expect(Config.Instance.shuffledSubnetIdsForAwsRegion('AWS_REGION')).toContain('SUBNET_IDS2');
expect(Config.Instance.shuffledSubnetIdsForAwsRegion('AWS_REGION_INSTANCES_1').length).toEqual(1);
expect(Config.Instance.shuffledSubnetIdsForAwsRegion('AWS_REGION_INSTANCES_1')).toContain('SUBNET_IDS3');
expect(Config.Instance.shuffledSubnetIdsForAwsRegion('AWS_REGION_INSTANCES_2').length).toEqual(1);
expect(Config.Instance.shuffledSubnetIdsForAwsRegion('AWS_REGION_INSTANCES_2')).toContain('SUBNET_IDS4');
expect(Config.Instance.enableOrganizationRunners).toBeTruthy();
});

Expand Down Expand Up @@ -140,8 +160,7 @@ describe('Config', () => {
expect(Config.Instance.scaleConfigRepoPath).toEqual('.github/scale-config.yml');
expect(Config.Instance.secretsManagerSecretsId).toBeUndefined();
expect(Config.Instance.securityGroupIds.length).toEqual(0);
expect(Config.Instance.shuffledSubnetIds.length).toEqual(0);
expect(Config.Instance.subnetIds.length).toEqual(0);
expect(Config.Instance.shuffledAwsRegionInstances).toEqual(['us-east-1']);
expect(Config.Instance.enableOrganizationRunners).toBeFalsy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class Config {
readonly scaleConfigRepoPath: string;
readonly secretsManagerSecretsId: string | undefined;
readonly securityGroupIds: string[];
readonly subnetIds: string[];
readonly subnetIds: Map<string, Set<string>>;

protected constructor() {
this.awsRegion = process.env.AWS_REGION || 'us-east-1';
Expand Down Expand Up @@ -73,11 +73,34 @@ export class Config {
this.secretsManagerSecretsId = process.env.SECRETSMANAGER_SECRETS_ID;
/* istanbul ignore next */
this.securityGroupIds = process.env.SECURITY_GROUP_IDS?.split(',').filter((w) => w.length > 0) ?? [];
/* istanbul ignore next */
this.subnetIds = process.env.SUBNET_IDS?.split(',').filter((w) => w.length > 0) ?? [];
this.subnetIds = this.getSubnetIdsFromEnv();
this.enableOrganizationRunners = getBoolean(process.env.ENABLE_ORGANIZATION_RUNNERS);
}

protected getSubnetIdsFromEnv(): Map<string, Set<string>> {
const mapSet: Map<string, Set<string>> = new Map();

(process.env.SUBNET_IDS?.split(',').filter((w) => w.length > 0) ?? [])
.map((e) => {
return e.split('|').filter((e) => {
return e.length > 0;
});
})
.filter((e) => {
return e.length == 2;
})
.forEach((keyVal) => {
const [awsRegion, subnetId] = keyVal;
if (!mapSet.has(awsRegion)) {
mapSet.set(awsRegion, new Set<string>([subnetId]));
} else {
mapSet.get(awsRegion)?.add(subnetId);
}
});

return mapSet;
}

static get Instance(): Config {
return this._instance || (this._instance = new this());
}
Expand All @@ -86,13 +109,14 @@ export class Config {
this._instance = undefined;
}

get shuffledSubnetIds(): string[] {
const shuffled = [...this.subnetIds];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
shuffledSubnetIdsForAwsRegion(awsRegion: string): Array<string> {
const arr = Array.from(this.subnetIds.get(awsRegion) ?? []);
return this.shuffleInPlace(arr);
}

get shuffledAwsRegionInstances(): string[] {
const arr = [...this.awsRegionInstances];
return this.shuffleInPlace(arr);
}

get ghesUrlApi(): undefined | string {
Expand All @@ -104,4 +128,12 @@ export class Config {
/* istanbul ignore next */
return this.ghesUrl ?? 'https://github.com';
}

protected shuffleInPlace<T>(arr: T[]): T[] {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
}
Loading

0 comments on commit e7b07d2

Please sign in to comment.