Skip to content

Commit b5e5ce3

Browse files
wadhervgithub-actions[bot]npalmBrend-Smits
authored andcommitted
feat(control-plane): tag control plane created SSM Parameters (github-aws-runners#4833) (github-aws-runners#4834)
Introducing a new variable `parameter_store_tags` to add tags for all the SSM Parameter Store resources created via Scale-Up and Pool lambda function. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Niek Palm <npalm@users.noreply.github.com> Co-authored-by: Brend Smits <brend.smits@philips.com>
1 parent 1e8f899 commit b5e5ce3

File tree

16 files changed

+84
-3
lines changed

16 files changed

+84
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ Join our discord community via [this invite link](https://discord.gg/bxgXW8jJGh)
165165
| <a name="input_matcher_config_parameter_store_tier"></a> [matcher\_config\_parameter\_store\_tier](#input\_matcher\_config\_parameter\_store\_tier) | The tier of the parameter store for the matcher configuration. Valid values are `Standard`, and `Advanced`. | `string` | `"Standard"` | no |
166166
| <a name="input_metrics"></a> [metrics](#input\_metrics) | Configuration for metrics created by the module, by default disabled to avoid additional costs. When metrics are enable all metrics are created unless explicit configured otherwise. | <pre>object({<br/> enable = optional(bool, false)<br/> namespace = optional(string, "GitHub Runners")<br/> metric = optional(object({<br/> enable_github_app_rate_limit = optional(bool, true)<br/> enable_job_retry = optional(bool, true)<br/> enable_spot_termination_warning = optional(bool, true)<br/> }), {})<br/> })</pre> | `{}` | no |
167167
| <a name="input_minimum_running_time_in_minutes"></a> [minimum\_running\_time\_in\_minutes](#input\_minimum\_running\_time\_in\_minutes) | The time an ec2 action runner should be running at minimum before terminated, if not busy. | `number` | `null` | no |
168+
| <a name="input_parameter_store_tags"></a> [parameter\_store\_tags](#input\_parameter\_store\_tags) | Map of tags that will be added to all the SSM Parameter Store parameters created by the Lambda function. | `map(string)` | `{}` | no |
168169
| <a name="input_pool_config"></a> [pool\_config](#input\_pool\_config) | The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for weekdays to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1. Use `schedule_expression_timezone` to override the schedule time zone (defaults to UTC). | <pre>list(object({<br/> schedule_expression = string<br/> schedule_expression_timezone = optional(string)<br/> size = number<br/> }))</pre> | `[]` | no |
169170
| <a name="input_pool_lambda_memory_size"></a> [pool\_lambda\_memory\_size](#input\_pool\_lambda\_memory\_size) | Memory size limit for scale-up lambda. | `number` | `512` | no |
170171
| <a name="input_pool_lambda_reserved_concurrent_executions"></a> [pool\_lambda\_reserved\_concurrent\_executions](#input\_pool\_lambda\_reserved\_concurrent\_executions) | Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | `1` | no |

lambdas/functions/control-plane/src/pool/pool.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { bootTimeExceeded, listEC2Runners } from '../aws/runners';
66
import { RunnerList } from '../aws/runners.d';
77
import { createGithubAppAuth, createGithubInstallationAuth, createOctokitClient } from '../github/auth';
88
import { createRunners, getGitHubEnterpriseApiUrl } from '../scale-runners/scale-up';
9+
import { validateSsmParameterStoreTags } from '../scale-runners/scale-up';
910

1011
const logger = createChildLogger('pool');
1112

@@ -41,6 +42,10 @@ export async function adjust(event: PoolEvent): Promise<void> {
4142
const onDemandFailoverOnError = process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS
4243
? (JSON.parse(process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS) as [string])
4344
: [];
45+
const ssmParameterStoreTags: { Key: string; Value: string }[] =
46+
process.env.SSM_PARAMETER_STORE_TAGS && process.env.SSM_PARAMETER_STORE_TAGS.trim() !== ''
47+
? validateSsmParameterStoreTags(process.env.SSM_PARAMETER_STORE_TAGS)
48+
: [];
4449
const scaleErrors = JSON.parse(process.env.SCALE_ERRORS) as [string];
4550

4651
const { ghesApiUrl, ghesBaseUrl } = getGitHubEnterpriseApiUrl();
@@ -82,6 +87,7 @@ export async function adjust(event: PoolEvent): Promise<void> {
8287
disableAutoUpdate: disableAutoUpdate,
8388
ssmTokenPath,
8489
ssmConfigPath,
90+
ssmParameterStoreTags,
8591
},
8692
{
8793
ec2instanceCriteria: {

lambdas/functions/control-plane/src/scale-runners/scale-up.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ interface CreateGitHubRunnerConfig {
5151
disableAutoUpdate: boolean;
5252
ssmTokenPath: string;
5353
ssmConfigPath: string;
54+
ssmParameterStoreTags: { Key: string; Value: string }[];
5455
}
5556

5657
interface CreateEC2RunnerConfig {
@@ -90,6 +91,37 @@ function generateRunnerServiceConfig(githubRunnerConfig: CreateGitHubRunnerConfi
9091
return config;
9192
}
9293

94+
export function validateSsmParameterStoreTags(tagsJson: string): { Key: string; Value: string }[] {
95+
try {
96+
const tags = JSON.parse(tagsJson);
97+
98+
if (!Array.isArray(tags)) {
99+
throw new Error('Tags must be an array');
100+
}
101+
102+
if (tags.length === 0) {
103+
return [];
104+
}
105+
106+
tags.forEach((tag, index) => {
107+
if (typeof tag !== 'object' || tag === null) {
108+
throw new Error(`Tag at index ${index} must be an object`);
109+
}
110+
if (!tag.Key || typeof tag.Key !== 'string' || tag.Key.trim() === '') {
111+
throw new Error(`Tag at index ${index} has missing or invalid 'Key' property`);
112+
}
113+
if (!Object.prototype.hasOwnProperty.call(tag, 'Value') || typeof tag.Value !== 'string') {
114+
throw new Error(`Tag at index ${index} has missing or invalid 'Value' property`);
115+
}
116+
});
117+
118+
return tags;
119+
} catch (err) {
120+
logger.error('Invalid SSM_PARAMETER_STORE_TAGS format', { error: err });
121+
throw new Error(`Failed to parse SSM_PARAMETER_STORE_TAGS: ${(err as Error).message}`);
122+
}
123+
}
124+
93125
async function getGithubRunnerRegistrationToken(githubRunnerConfig: CreateGitHubRunnerConfig, ghClient: Octokit) {
94126
const registrationToken =
95127
githubRunnerConfig.runnerType === 'Org'
@@ -183,6 +215,9 @@ async function getRunnerGroupId(githubRunnerConfig: CreateGitHubRunnerConfig, gh
183215
`${githubRunnerConfig.ssmConfigPath}/runner-group/${githubRunnerConfig.runnerGroup}`,
184216
runnerGroupId.toString(),
185217
false,
218+
{
219+
tags: githubRunnerConfig.ssmParameterStoreTags,
220+
},
186221
);
187222
} catch (err) {
188223
logger.debug('Error storing runner group id in SSM Parameter Store', err as Error);
@@ -256,6 +291,10 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
256291
const onDemandFailoverOnError = process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS
257292
? (JSON.parse(process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS) as [string])
258293
: [];
294+
const ssmParameterStoreTags: { Key: string; Value: string }[] =
295+
process.env.SSM_PARAMETER_STORE_TAGS && process.env.SSM_PARAMETER_STORE_TAGS.trim() !== ''
296+
? validateSsmParameterStoreTags(process.env.SSM_PARAMETER_STORE_TAGS)
297+
: [];
259298
const scaleErrors = JSON.parse(process.env.SCALE_ERRORS) as [string];
260299

261300
const { ghesApiUrl, ghesBaseUrl } = getGitHubEnterpriseApiUrl();
@@ -419,6 +458,7 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
419458
disableAutoUpdate,
420459
ssmTokenPath,
421460
ssmConfigPath,
461+
ssmParameterStoreTags,
422462
},
423463
{
424464
ec2instanceCriteria: {
@@ -513,7 +553,7 @@ async function createRegistrationTokenConfig(
513553

514554
for (const instance of instances) {
515555
await putParameter(`${githubRunnerConfig.ssmTokenPath}/${instance}`, runnerServiceConfig.join(' '), true, {
516-
tags: [{ Key: 'InstanceId', Value: instance }],
556+
tags: [{ Key: 'InstanceId', Value: instance }, ...githubRunnerConfig.ssmParameterStoreTags],
517557
});
518558
if (isDelay) {
519559
// Delay to prevent AWS ssm rate limits by being within the max throughput limit
@@ -571,7 +611,7 @@ async function createJitConfig(githubRunnerConfig: CreateGitHubRunnerConfig, ins
571611
instance: instance,
572612
});
573613
await putParameter(`${githubRunnerConfig.ssmTokenPath}/${instance}`, runnerConfig.data.encoded_jit_config, true, {
574-
tags: [{ Key: 'InstanceId', Value: instance }],
614+
tags: [{ Key: 'InstanceId', Value: instance }, ...githubRunnerConfig.ssmParameterStoreTags],
575615
});
576616
if (isDelay) {
577617
// Delay to prevent AWS ssm rate limits by being within the max throughput limit

main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ module "runners" {
232232
runner_log_files = var.runner_log_files
233233
runner_group_name = var.runner_group_name
234234
runner_name_prefix = var.runner_name_prefix
235+
parameter_store_tags = var.parameter_store_tags
235236

236237
scale_up_reserved_concurrent_executions = var.scale_up_reserved_concurrent_executions
237238

modules/multi-runner/README.md

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

modules/multi-runner/runners.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ module "runners" {
8181
runner_log_files = each.value.runner_config.runner_log_files
8282
runner_group_name = each.value.runner_config.runner_group_name
8383
runner_name_prefix = each.value.runner_config.runner_name_prefix
84+
parameter_store_tags = var.parameter_store_tags
8485

8586
scale_up_reserved_concurrent_executions = each.value.runner_config.scale_up_reserved_concurrent_executions
8687

modules/multi-runner/variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,3 +752,9 @@ variable "lambda_event_source_mapping_maximum_batching_window_in_seconds" {
752752
type = number
753753
default = 0
754754
}
755+
756+
variable "parameter_store_tags" {
757+
description = "Map of tags that will be added to all the SSM Parameter Store parameters created by the Lambda function."
758+
type = map(string)
759+
default = {}
760+
}

modules/runners/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ yarn run dist
192192
| <a name="input_metrics"></a> [metrics](#input\_metrics) | Configuration for metrics created by the module, by default metrics are disabled to avoid additional costs. When metrics are enable all metrics are created unless explicit configured otherwise. | <pre>object({<br/> enable = optional(bool, false)<br/> namespace = optional(string, "GitHub Runners")<br/> metric = optional(object({<br/> enable_github_app_rate_limit = optional(bool, true)<br/> enable_job_retry = optional(bool, true)<br/> enable_spot_termination_warning = optional(bool, true)<br/> }), {})<br/> })</pre> | `{}` | no |
193193
| <a name="input_minimum_running_time_in_minutes"></a> [minimum\_running\_time\_in\_minutes](#input\_minimum\_running\_time\_in\_minutes) | The time an ec2 action runner should be running at minimum before terminated if non busy. If not set the default is calculated based on the OS. | `number` | `null` | no |
194194
| <a name="input_overrides"></a> [overrides](#input\_overrides) | This map provides the possibility to override some defaults. The following attributes are supported: `name_sg` overrides the `Name` tag for all security groups created by this module. `name_runner_agent_instance` overrides the `Name` tag for the ec2 instance defined in the auto launch configuration. `name_docker_machine_runners` overrides the `Name` tag spot instances created by the runner agent. | `map(string)` | <pre>{<br/> "name_runner": "",<br/> "name_sg": ""<br/>}</pre> | no |
195+
| <a name="input_parameter_store_tags"></a> [parameter\_store\_tags](#input\_parameter\_store\_tags) | Map of tags that will be added to all the SSM Parameter Store parameters created by the Lambda function. | `map(string)` | `{}` | no |
195196
| <a name="input_placement"></a> [placement](#input\_placement) | The placement options for the instance. See https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#placement for details. | <pre>object({<br/> affinity = optional(string)<br/> availability_zone = optional(string)<br/> group_id = optional(string)<br/> group_name = optional(string)<br/> host_id = optional(string)<br/> host_resource_group_arn = optional(string)<br/> spread_domain = optional(string)<br/> tenancy = optional(string)<br/> partition_number = optional(number)<br/> })</pre> | `null` | no |
196197
| <a name="input_pool_config"></a> [pool\_config](#input\_pool\_config) | The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for week days to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1. Use `schedule_expression_timezone ` to override the schedule time zone (defaults to UTC). | <pre>list(object({<br/> schedule_expression = string<br/> schedule_expression_timezone = optional(string)<br/> size = number<br/> }))</pre> | `[]` | no |
197198
| <a name="input_pool_lambda_memory_size"></a> [pool\_lambda\_memory\_size](#input\_pool\_lambda\_memory\_size) | Lambda Memory size limit in MB for pool lambda | `number` | `512` | no |

modules/runners/local.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
locals {
2+
parameter_store_tags = jsonencode([
3+
for key, value in merge(var.tags, var.parameter_store_tags) : {
4+
Key = key
5+
Value = value
6+
}
7+
])
8+
}

modules/runners/pool.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module "pool" {
3333
runtime = var.lambda_runtime
3434
timeout = var.pool_lambda_timeout
3535
zip = local.lambda_zip
36+
parameter_store_tags = local.parameter_store_tags
3637
}
3738
pool = var.pool_config
3839
role_path = local.role_path

0 commit comments

Comments
 (0)