-
-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature request: attach custom tags to the ec2 #524
Comments
Do you mean tags? |
Yes I mean tags btw 😄 |
I believe it should already be copying the provider tags to the EC2 instance. So you should be able to use |
I would need it more dynamic. |
What data would this Lambda need? Requested labels? The entire webhook? |
The entire webhook to get things like org, repo, job run, step and the labels. |
I'll have to think about the best way to enable such a feature request. For now you can use the environment variables already supplied by the actions runner code. |
Will do. |
I had some time to really understand the solution you propose. Yes this definitely will work but I fear that this could be hard to debug, monitor and to modify. Could it be another option to provide some kind of pre-deployment step in the stepfunction that can be overwritten to select and add tags that can be attached e.g. to the ec2 or other components ? |
I still don't have a good idea of what something like that would look like. For example, one of the big problems is that it can't be generic. Settings tags is only supported natively on EC2 and through some hacks on ECS (RunTask doesn't have an option for tags). Maybe some sort of an escape hatch is in place. Even that I'm not sure how to do elegantly as task objects don't have any option to override until they're rendered and then you have to deal with the entire step function JSON. We would have to take out all of the parameters into an object, pass it to a custom lambda, and then use the results as input for the actual step. But then when this is not used, we just skip the pass and directly pass the parameters? |
But to do it specifically for the ec2 provider could be an option. cdk-github-runners/src/providers/ec2.ts Line 415 in f64d5a4
getStepFunctionTask(parameters: RunnerRuntimeParameters): stepfunctions.IChainable {
// we need to build user data in two steps because passing the template as the first parameter to stepfunctions.JsonPath.format fails on syntax
const params = [
stepfunctions.JsonPath.taskToken,
this.logGroup.logGroupName,
parameters.runnerNamePath,
parameters.githubDomainPath,
parameters.ownerPath,
parameters.repoPath,
parameters.runnerTokenPath,
this.labels.join(','),
parameters.registrationUrl,
];
if (this.customTagsFunction) {
const customTags = new stepfunctions_tasks.LambdaInvoke(
this,
'Get custom tags',
{
lambdaFunction: this.customTagsFunction,
payloadResponseOnly: true,
resultPath: '$.tags',
payload: stepfunctions.TaskInput.fromObject({
runnerName: stepfunctions.JsonPath.stringAt('$$.Execution.Name'),
owner: stepfunctions.JsonPath.stringAt('$.owner'),
repo: stepfunctions.JsonPath.stringAt('$.repo'),
installationId: stepfunctions.JsonPath.numberAt('$.installationId'),
error: stepfunctions.JsonPath.objectAt('$.error'),
}),
},
);
};
const passUserData = new stepfunctions.Pass(this, `${this.labels.join(', ')} data`, {
parameters: {
userdataTemplate: this.ami.os.is(Os.WINDOWS) ? windowsUserDataTemplate : linuxUserDataTemplate,
},
resultPath: stepfunctions.JsonPath.stringAt('$.ec2'),
}); |
It just occurred to me that assigning the tags before a job is assigned to the runner may result in unexpected results. Especially if you're using organization level registration. There is no guarantee the runner will pick up the job you think it will if the labels are shared. If the labels are not shared, each provider can use its own static tags. This won't work right now as the tags come from the launch template which is generated by the image builder. I think that part might be resolved by fleets (#518). My current plan is to move EC2 provider to using fleets with SSM document. It would require the provider to create its own launch template. Once it's the provider creating the launch template, using I still can't get behind a function specifically for tags specifically for EC2 provider. If we could think of a way to make a generic escape hatch where you have a way to edit the step function after being generated, I think that would make more sense. You can technically already do it by overriding the entire JSON. But that's not a realistic method as you'd have to recreate everything. |
I haven`t thought about this - but auto tagging should help me ... https://medium.com/@mithun.kadyada/lambda-function-for-auto-tagging-ec2-instances-cff38c30bdc8 One thing to mention: |
How would the auto-tagging Lambda have access to the webhook info needed to properly tag the instance?
Not sure what you mean by that. Are you asking to have access to the repository or organization where the instance was registered? As in some tag that the Lambda function could later read? |
Yes I would like to have a simple way to read out the relation between the runner and the github org + repo when the runner is started. |
Might this information be available in the state machine log? |
Yes that's true but hard to query for each machine I would assume. I would try to get the information when a new instance is started. And I assume it's easier to read the information from the ec2's instance tags. |
Hey @kichik, I would like to get more overview about the costs. The params are already there: cdk-github-runners/src/providers/ec2.ts Line 407 in f0aebce
Would be great to append them here: cdk-github-runners/src/providers/ec2.ts Line 447 in f0aebce
I could create a PR and test it. |
Turns out all resources do support tags at deploy time. So we should be able to tag with the provider construct path and its labels. The problem is AWS tags don't allow commas. Runner labels don't seem to have any restrictions besides commas, so I'm not sure what's the best solution for that would be. As for tagging with the owner and repo, I still don't see how we can do that in a generic and/or non-clunky way. We can't trust what the step function registers it as because of organization level registration. Adding a separate Lambda to query it from GitHub once the runner is assigned sounds as clunky as reading the log. And it will have limited provider support. At that point I would still prefer the self-tagging route. |
Would #582 help? Would it be enough? |
Thanks that you took the time to write. You're right. In this case I would even prefer a query to Github once the runner is assigned or as you mentioned self-tag the instance. There was a hook available right ? Would mean I could add some custom shell script to self-tag. |
This was basically what I meant but I would need more information. :) and you already delivered the reason why it's a bad idea. |
I guess I would try the github way first. It's easy to change it as stepfunction. |
Yeah. The image builder will set
Sadly, no. Organization is not available during deployment time. We don't know which app/organization/repository/etc. will register with the orchestrator after it's deployed. |
#583 worked for me to assign the owner tag to the ec2 instance. |
I would have a generic proposal: Regarding the hook script solution: (https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/running-scripts-before-or-after-a-job) A basic script This script will be referenced at provider startup when the runner configuration will be done e.g. for linux If somebody wants to overwrite the script (like me to attach ec2-tags :) !) it can be done adding a custom
|
You should already be able to do it. The following worked for me. const builder = Ec2RunnerProvider.imageBuilder(stack, 'builder');
builder.addComponent(
RunnerImageComponent.environmentVariables({
ACTIONS_RUNNER_HOOK_JOB_STARTED: '/home/runner/runner-started.sh',
}),
);
builder.addComponent(
RunnerImageComponent.custom({
name: 'Self-tag',
commands: [
'echo "#!/bin/bash" > /home/runner/runner-started.sh',
'echo \'TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 60")\' >> /home/runner/runner-started.sh',
'echo \'INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)\' >> /home/runner/runner-started.sh',
'echo \'aws ec2 create-tags --resources "$INSTANCE_ID" --tags Key=owner,Value=$GITHUB_REPOSITORY_OWNER Key=repository,Value=$GITHUB_REPOSITORY\' >> /home/runner/runner-started.sh',
'chmod +x /home/runner/runner-started.sh',
],
}),
);
const provider = new Ec2RunnerProvider(stack, 'EC2', {
labels: ['self-tag-provider'],
imageBuilder: builder,
});
provider.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({
actions: ['ec2:CreateTags'],
resources: ['*'],
conditions: {
StringEquals: {
'aws:Resource': 'instance/${ec2:InstanceID}',
},
},
})); |
I'll try it out and will close it for now |
Hey @kichik,
I need the possiblity to attach custom labels to an ec2.
Background: I want to be able to track the costs in cost explorer based on certain labels.
Basically a lambda that I can provide to return back labels in a certain format.
br,
@pharindoko
The text was updated successfully, but these errors were encountered: