Closed jpSimkins closed 2 years ago
Hey @jpSimkins ,
thanks for reporting the issue. Can you tell me whether you see a AWS::Events::Rule
resource in your template, and show its content if you do?
Thanks, Adam
Hello @skinny85,
This is the resource with AWS::Events::Rule
:
CDKTestBaseRepositoryPipelineTestCDKTestProjectPipeline3CAA437FSourceEventRuleC4D400A3:
Type: AWS::Events::Rule
Properties:
EventPattern:
source:
- aws.ecr
detail-type:
- AWS API Call via CloudTrail
detail:
requestParameters:
repositoryName:
- Ref: CDKTestBaseRepository90CAC7C5
imageTag:
- latest
eventName:
- PutImage
State: ENABLED
Targets:
- Arn:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codepipeline:us-east-1:31120948XXXX:"
- Ref: CDKTestProjectPipeline664B0BF2
Id: Target0
RoleArn:
Fn::GetAtt:
- CDKTestProjectPipelineEventsRoleEBA1D6BA
- Arn
Metadata:
aws:cdk:path: PipelineTest/CDKTestBase/Repository/PipelineTestCDKTestProjectPipeline3CAA437FSourceEventRule/Resource
I notice that eventName has PutImage
. My process is to build the base image, test it, then I have another codeBuild that updates the latest
tag once it is approved using the approval action. Just mentioning in case this matters. Still, this works as expected when I set this up manually.
My process is to build the base image, test it, then I have another codeBuild that updates the
latest
tag once it is approved using the approval action
Sorry, can you clarify this part? What do you mean exactly by "updates the latest
tag"?
Once the testing is done, given this is a base image it needs to be vetted first, I have a manual approval action that will trigger the updated
tag to be added to the image.
Basically, I pull the image, add the latest
tag, then push it. I assume this would still trigger PutImage
but I am not sure if that is the case as this is an existing image just added the latest
tag to it.
The Code may help:
const codebuildProjectUpdateLatestImage = new PipelineProject(this, 'UpdateLatestTag', {
buildSpec: BuildSpec.fromObject({
version: '0.2',
phases: {
install: {
'runtime-versions': {
python: '3.8',
},
},
pre_build: {
commands: [
'echo Defining variables...',
"BUILD_IMAGE=$(cat imageDetail.json | jq '.ImageURI')",
'echo Removing quotes from string... ',
"BUILD_IMAGE=$(sed -e 's/^\"//' -e 's/\"$//' <<< $BUILD_IMAGE)",
'echo $BUILD_IMAGE',
"REPOSITORY_URL=$(cut -d':' -f1 <<< $BUILD_IMAGE)",
'echo $REPOSITORY_URL',
'echo Logging in to Amazon ECR...',
"aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $(cut -d'/' -f1 <<< $REPOSITORY_URL)",
],
},
build: {
commands: [
'echo Build started on `date`',
'echo Pulling the Docker base image...',
'docker pull $BUILD_IMAGE',
'echo Tagging the Docker image...',
'docker tag $BUILD_IMAGE $REPOSITORY_URL:latest',
],
},
post_build: {
commands: [
'echo Pushing the Docker image...',
'docker push $REPOSITORY_URL:latest',
'echo Build completed on `date`',
],
},
},
}),
description: 'Updates the latest tag for the ECR Repo',
environment: {
buildImage: LinuxBuildImage.AMAZON_LINUX_2_3,
computeType: ComputeType.SMALL,
privileged: true, // Needed to run docker build commands
},
projectName: this._id + '-UpdateLatestTag',
role: this._role,
});
// Stage - Build Update Latest Tag
this._codepipelinePipeline.addStage({
stageName: 'UpdateLatestTag',
actions: [
new CodeBuildAction({
actionName: 'UpdateLatestTag',
project: codebuildProjectUpdateLatestImage,
input: this._artifactBaseBuild,
}),
],
});
Seems I am also experiencing the same issue, EcrSourceAction is not triggering the build action when the Image is updated.
I have the same issue, checked CloudWatch events, and found different events. CDK creates an event that doesn't work
CDK created event (it doesn't work):
{
"detail-type": [
"AWS API Call via CloudTrail"
],
"source": [
"aws.ecr"
],
"detail": {
"requestParameters": {
"repositoryName": [
"ecr-repo-name"
],
"imageTag": [
"latest"
]
},
"eventName": [
"PutImage"
]
}
}
Web console created such event (it works well):
{
"source": [
"aws.ecr"
],
"detail": {
"action-type": [
"PUSH"
],
"image-tag": [
"latest"
],
"repository-name": [
"ecr-repo-name"
],
"result": [
"SUCCESS"
]
},
"detail-type": [
"ECR Image Action"
]
}
My fix for this issue (python):
ecr_repo = ecr.Repository.from_repository_name(self, "ecr-repo", settings.backend_ecr_name)
source_output_ecr = pipeline.Artifact()
source_action_ecr = actions.EcrSourceAction(
action_name="ECR",
repository=ecr_repo,
image_tag="latest", # optional, default: 'latest'
output=source_output_ecr
)
rule = events.Rule(
self, "ecr-rule",
event_pattern=events.EventPattern(
source=["aws.ecr"],
detail={
"action-type": [
"PUSH"
],
"image-tag": [
"latest"
],
"repository-name": [
settings.backend_ecr_name
],
"result": [
"SUCCESS"
]
}
),
)
......pipeline_backend creation
rule.add_target(targets.CodePipeline(pipeline_backend))
Did that make the CodePipeline trigger @solovievv ?
@skinny85 Yes, It works well after the fix
I was able to get the base image to trigger the pipeline with Typescript using:
const eventRule = new Rule(this, 'base-ecr-rule', {
eventPattern: {
source: ['aws.ecr'],
detail: {
'action-type': ['PUSH'],
'image-tag': ['latest'],
'repository-name': [this._props.projectSourceEcrRepo.repositoryName],
result: ['SUCCESS'],
},
},
});
eventRule.addTarget(new CodePipelineTarget(this._codepipelinePipeline));
So far, this seems to work as expected.
same issue here!
However, @solovievv workaround fix it.
Good news: the @solovievv's workaround is not anymore needed. Did AWS fix something in Cloudwatch?
Interesting @luca-ferreri... it definitely seemed like this problem was happening only for some customers (I was never able to reproduce myself, for example).
I am experiencing exactly the same issue in typescript. I'm using cdk 107.0. After the fix of @jpSimkins I was able to resolve it.
EventRule generated by the EcrSourceAction
that does not trigger the pipeline
"GraphQlGwEcrservergraphqlgwpipelinedevGraphqlApiECSPipelineD471B6D0SourceEventRuleF2E828D6": {
"Type": "AWS::Events::Rule",
"Properties": {
"EventPattern": {
"source": [
"aws.ecr"
],
"detail-type": [
"AWS API Call via CloudTrail"
],
"detail": {
"requestParameters": {
"repositoryName": [
"server-dev-graphql-gw-ecr"
],
"imageTag": [
"latest"
]
},
"eventName": [
"PutImage"
]
}
},
"State": "ENABLED",
"Targets": [
{
"Arn": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":codepipeline:ap-southeast-1:",
{
"Ref": "AWS::AccountId"
},
":",
{
"Ref": "GraphqlApiECSPipeline4C249FA2"
}
]
]
},
"Id": "Target0",
"RoleArn": {
"Fn::GetAtt": [
"GraphqlApiECSPipelineEventsRole0098D078",
"Arn"
]
}
}
]
},
"Metadata": {
"aws:cdk:path": "server-graphql-gw-pipeline-dev/GraphQlGwEcr/servergraphqlgwpipelinedevGraphqlApiECSPipelineD471B6D0SourceEventRule/Resource"
}
}
EventRule Created by the workaround of @jpSimkins that does trigger the pipeline
"GraphqlGwPutImageRule34EA2A1C": {
"Type": "AWS::Events::Rule",
"Properties": {
"EventPattern": {
"source": [
"aws.ecr"
],
"detail": {
"action-type": [
"PUSH"
],
"image-tag": [
"latest"
],
"repository-name": [
"server-dev-graphql-gw-ecr"
],
"result": [
"SUCCESS"
]
}
},
"State": "ENABLED",
"Targets": [
{
"Arn": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":codepipeline:ap-southeast-1:",
{
"Ref": "AWS::AccountId"
},
":",
{
"Ref": "GraphqlApiECSPipeline4C249FA2"
}
]
]
},
"Id": "Target0",
"RoleArn": {
"Fn::GetAtt": [
"GraphqlApiECSPipelineEventsRole0098D078",
"Arn"
]
}
}
]
},
"Metadata": {
"aws:cdk:path": "server-graphql-gw-pipeline-dev/GraphqlGwPutImageRule/Resource"
}
},
We have exactly the same problem however the workaround suggested @jpSimkins is no working for us. It does create the rule as indicated however the pipeline is not triggered. We have a cross account configuration where ECR
is in AWS Account A
and Codepipeline
in Account B
. After deploying CDK
initially the image is sourced correctly from our ECR
and deployed without any problems. However, any subsequent changes made to the image there after, fails to get deployed. Any idea to what could go wrong? Could it be something related to the Events bus
on different accounts (Rule is listening for changes on Account B bus
which never gets the Event, whereas ECR creates events on Account A's bus), Is anyone ( maybe @skinny85 ? ) clear about how this should work cross account? Our cross account role should work fine as otherwise would not be able to source the image at all (first deployment works).
We have even tried to create a Rule that includes the account
and the region
as additional parameters. As you can see below the CloudFormation is created properly however still not triggering codePipeline
const eventRule = new Rule(this, 'base-ecr-rule', {
ruleName: `CodePipelineTriggerImageChanges-${id}`,
eventPattern: {
source: ['aws.ecr'],
account: [props.registryId],
region: ['ap-southeast-2'],
detail: {
'action-type': ['PUSH'],
'image-tag': [this.imageTag],
'repository-name': [this.ecrImageRepoName],
result: ['SUCCESS'],
},
},
});
eventRule.addTarget(new CodePipeline(this.pipeline));
{
"source": [
"aws.ecr"
],
"detail": {
"repository-name": [
"MyRepo"
],
"result": [
"SUCCESS"
],
"action-type": [
"PUSH"
],
"image-tag": [
"latest"
]
},
"region": [
"ap-southeast-2"
],
"account": [
"AccountA"
]
}
@fasatrix make sure you have CloudTrail configured to deliver these events.
@fasatrix make sure you have CloudTrail configured to deliver these events.
@skinny85 thanks for the prompt answer.. Do you mean configure CloudTrail to send events from Account A to CloudWatch Logs still in Account A or would I have to send those events from Account A to B like this doc
So basically what I am asking here is, will a rule created using EcrSourceAction
be able to listen to events generated in a different account (giving one has the right permissions granted via cross account role) , say Account A (with a conf similar to the one mentioned above -- add account
and region
to the rule) or those events must to be shipped/shared across Accounts too? Thanks again
The EcrSourceAction
should take care of cross-account Events for you - it should create a separate Stack that grants account A (where the repository is) permissions to publish events to account B (where the pipeline is).
It should be a stack with a single resource, AWS::Events::EventBusPolicy
.
The
EcrSourceAction
should take care of cross-account Events for you - it should create a separate Stack that grants account A (where the repository is) permissions to publish events to account B (where the pipeline is).It should be a stack with a single resource,
AWS::Events::EventBusPolicy
.
ok that explains. I cannot find this AWS::Events::EventBusPolicy
in my yaml output.. is this a bug and how can we troubleshoot it?
CDK version we use 1.106
Can you show me how do you set up your EcrSourceAction
in your code?
Can you show me how do you set up your
EcrSourceAction
in your code?
It is part of the following function..
const createImageAction = (
imageRepoName: string,
imageTag?: string,
): CreatePipelineActionResponse<Artifact, EcrSourceAction> => {
const imageArtifact = new Artifact(`ImageArtifact-${id}`);
const imageRepository = Repository.fromRepositoryArn(
this,
'ImageRepository',
`arn:aws:ecr:ap-southeast-2:<MyAWSAccount>:repository/${imageRepoName}`,
);
//latest will be taken as the default image tag
const imageSourceAction = new EcrSourceAction({
actionName: `ImageSource-${id}`,
repository: imageRepository,
imageTag: imageTag ?? 'latest',
output: imageArtifact,
role: Role.fromRoleArn(this, 'CentralEcrAccessRole', props.crossAccountEcrRole),
});
return { artifact: imageArtifact, action: imageSourceAction };
};
Does the Role you use here, with the ARN from props.crossAccountEcrRole
, is in the same account as the ECR Repository, with the ARN arn:aws:ecr:ap-southeast-2:<MyAWSAccount>:repository/${imageRepoName}
?
crossAccountEcrRole
correct, they are from the same account (which is the account that host ECR)
The
EcrSourceAction
should take care of cross-account Events for you - it should create a separate Stack that grants account A (where the repository is) permissions to publish events to account B (where the pipeline is). It should be a stack with a single resource,AWS::Events::EventBusPolicy
.ok that explains. I cannot find this
AWS::Events::EventBusPolicy
in my yaml output.. is this a bug and how can we troubleshoot it? CDK version we use 1.106
@skinny85 it is consistent on our side! Our yaml does not include AWS::Events::EventBusPolicy
out of the box and if we do create a custom policy like the following, everything works just fine.
new CfnEventBusPolicy(this, `EventBusPolicy-${id}`, {
statementId: `EventBusPolicy-${id}`,
statement: {
Effect: 'Allow',
Action: 'events:PutEvents',
Resource: "arn:aws:events:ap-southeast-2:<AccounB>:event-bus/default"
Principal: {
AWS: `arn:aws:iam::<AccountA>:root`,
},
},
});
Does it look like it could be a bug to you?
Yes, it's possible it is. Let me try and reproduce to confirm.
I think I understand the problem now. It's actually a different thing than this issue talks about. Let's move the conversation to a dedicated issue I've created: https://github.com/aws/aws-cdk/issues/16245.
Thanks for you support @skinny85. With your guidance I was able to understand how this lib works..
Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.
When creating a code pipeline and using
EcrSourceAction
, I would expect when thelatest
tag is updated, for this to update the pipeline that is using this as a source. This is how it works when I create this manually but I cannot get the CDK to do this.I am thinking this is a bug because this is not what happens when I build the pipeline manually.
Reproduction Steps
I have a pretty large construct to build our pipeline so I will only post the part I think is relevant to the issue.
This is how I define the source action for the pipeline to use the Repository as a source:
Whenever I update the ECR repo, this does not trigger the pipeline to update at all. Basically, adding this as a source is pointless as the entire purpose is to allow this to update the pipeline when this is changed. Otherwise, I can simply pull the image when the project code is update.
To give a better idea of what I am doing:
latest
and the code from the BitBucket branchThe only part of the pipeline not working is the ECR source does not trigger the pipeline to build when it is updated.
What did you expect to happen?
I expected that when I update the ECR source, for it to trigger the pipeline to build as this is what it does when I build this manually.
What actually happened?
When the ECR source is updated, nothing happens. No errors that I could find, simply nothing. Like it is not aware of the connection to the repo. For me to trigger a change, I need to update the code to force the pipeline to trigger
Environment
This is :bug: Bug Report