Skip to content

Commit

Permalink
fix(appconfig-alpha): extensions always create cdk diff (#28264)
Browse files Browse the repository at this point in the history
Fixing extensions CDK diff since before it would always generate a new diff even if nothing changed.

Closes #27676.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
chenjane-dev authored Dec 9, 2023
1 parent d64a85b commit 2075559
Show file tree
Hide file tree
Showing 14 changed files with 889 additions and 467 deletions.
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-appconfig-alpha/lib/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ export class Application extends ApplicationBase {
resourceName: this.applicationId,
});

this.extensible = new ExtensibleBase(scope, this.applicationArn, this.name);
this.extensible = new ExtensibleBase(this, this.applicationArn, this.name);
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-appconfig-alpha/lib/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ export class HostedConfiguration extends ConfigurationBase {
resource: 'application',
resourceName: `${this.applicationId}/configurationprofile/${this.configurationProfileId}`,
});
this.extensible = new ExtensibleBase(scope, this.configurationProfileArn, this.name);
this.extensible = new ExtensibleBase(this, this.configurationProfileArn, this.name);

this.content = props.content.content;
this.contentType = props.content.contentType;
Expand Down Expand Up @@ -617,7 +617,7 @@ export class SourcedConfiguration extends ConfigurationBase {
resource: 'application',
resourceName: `${this.applicationId}/configurationprofile/${this.configurationProfileId}`,
});
this.extensible = new ExtensibleBase(scope, this.configurationProfileArn, this.name);
this.extensible = new ExtensibleBase(this, this.configurationProfileArn, this.name);

this.addExistingEnvironmentsToApplication();
this.deployConfigToEnvironments();
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ export class Environment extends EnvironmentBase {
resource: 'application',
resourceName: `${this.applicationId}/environment/${this.environmentId}`,
});
this.extensible = new ExtensibleBase(scope, this.environmentArn, this.name);
this.extensible = new ExtensibleBase(this, this.environmentArn, this.name);

this.application.addExistingEnvironment(this);
}
Expand Down
59 changes: 37 additions & 22 deletions packages/@aws-cdk/aws-appconfig-alpha/lib/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ export class LambdaDestination implements IEventDestination {
this.policyDocument = new iam.PolicyDocument({
statements: [policy],
});

if (!func.permissionsNode.tryFindChild('AppConfigPermission')) {
func.addPermission('AppConfigPermission', {
principal: new iam.ServicePrincipal('appconfig.amazonaws.com'),
});
}
}
}

Expand Down Expand Up @@ -500,21 +506,19 @@ export class Extension extends Resource implements IExtension {
this.parameters = props.parameters;

const resource = new CfnExtension(this, 'Resource', {
actions: this.actions.reduce((acc: {[key: string]: {[key: string]: string}[]}, cur: Action) => {
actions: this.actions.reduce((acc: {[key: string]: {[key: string]: string}[]}, cur: Action, index: number) => {
const extensionUri = cur.eventDestination.extensionUri;
const sourceType = cur.eventDestination.type;
this.executionRole = cur.executionRole;
const name = cur.name ?? `${this.name}-${index}`;
cur.actionPoints.forEach((actionPoint) => {
acc[actionPoint] = [
{
Name: cur.name || Names.uniqueResourceName(this, {
maxLength: 64,
separator: '-',
}),
Name: name,
Uri: extensionUri,
...(sourceType === SourceType.EVENTS || cur.invokeWithoutExecutionRole
? {}
: { RoleArn: this.executionRole?.roleArn || this.getExecutionRole(cur.eventDestination).roleArn }),
: { RoleArn: this.executionRole?.roleArn || this.getExecutionRole(cur.eventDestination, name).roleArn }),
...(cur.description ? { Description: cur.description } : {}),
},
];
Expand Down Expand Up @@ -543,8 +547,10 @@ export class Extension extends Resource implements IExtension {
});
}

private getExecutionRole(eventDestination: IEventDestination): iam.IRole {
this.executionRole = new iam.Role(this, `Role${getHash(eventDestination.extensionUri)}`, {
private getExecutionRole(eventDestination: IEventDestination, actionName: string): iam.IRole {
const versionNumber = this.latestVersionNumber ? this.latestVersionNumber + 1 : 1;
const combinedObjects = stringifyObjects(this.name, versionNumber, actionName);
this.executionRole = new iam.Role(this, `Role${getHash(combinedObjects)}`, {
roleName: PhysicalName.GENERATE_IF_NEEDED,
assumedBy: new iam.ServicePrincipal('appconfig.amazonaws.com'),
inlinePolicies: {
Expand Down Expand Up @@ -652,13 +658,13 @@ export class ExtensibleBase implements IExtensible {
}

public addExtension(extension: IExtension) {
this.addExtensionAssociation(extension, {
parameters: extension.parameters,
});
this.addExtensionAssociation(extension);
}

private getExtensionForActionPoint(eventDestination: IEventDestination, actionPoint: ActionPoint, options?: ExtensionOptions) {
const extension = new Extension(this.scope, `Extension${this.getExtensionHash(eventDestination, actionPoint, options)}`, {
const name = options?.name || this.getExtensionDefaultName();
const versionNumber = options?.latestVersionNumber ? options?.latestVersionNumber + 1 : 1;
const extension = new Extension(this.scope, `Extension${this.getExtensionHash(name, versionNumber)}`, {
actions: [
new Action({
eventDestination,
Expand All @@ -667,20 +673,22 @@ export class ExtensibleBase implements IExtensible {
],
}),
],
name,
...(options?.description ? { description: options.description } : {}),
...(options?.latestVersionNumber ? { latestVersionNumber: options.latestVersionNumber } : {}),
...(options?.name ? { name: options.name } : {}),
...(options?.parameters ? { parameters: options.parameters } : {}),
});
this.addExtensionAssociation(extension, options);
this.addExtensionAssociation(extension);
}

private addExtensionAssociation(extension: IExtension, options?: ExtensionOptions) {
new CfnExtensionAssociation(this.scope, `AssociationResource${this.getExtensionAssociationHash(extension)}`, {
private addExtensionAssociation(extension: IExtension) {
const versionNumber = extension?.latestVersionNumber ? extension?.latestVersionNumber + 1 : 1;
const name = extension.name ?? this.getExtensionDefaultName();
new CfnExtensionAssociation(this.scope, `AssociationResource${this.getExtensionAssociationHash(name, versionNumber)}`, {
extensionIdentifier: extension.extensionId,
resourceIdentifier: this.resourceArn,
extensionVersionNumber: extension.extensionVersionNumber,
parameters: options?.parameters?.reduce((acc: {[key: string]: string}, cur: Parameter) => {
parameters: extension.parameters?.reduce((acc: {[key: string]: string}, cur: Parameter) => {
if (cur.value) {
acc[cur.name] = cur.value;
}
Expand All @@ -689,16 +697,23 @@ export class ExtensibleBase implements IExtensible {
});
}

private getExtensionHash(eventDestination: IEventDestination, actionPoint: ActionPoint, options?: ExtensionOptions) {
const combinedString = stringifyObjects(eventDestination, actionPoint, options);
private getExtensionHash(name: string, versionNumber: number) {
const combinedString = stringifyObjects(name, versionNumber);
return getHash(combinedString);
}

private getExtensionAssociationHash(extension: IExtension) {
const resourceIdentifier = this.resourceName ? this.resourceName : this.resourceArn;
const combinedString = stringifyObjects(resourceIdentifier, extension.name, extension.extensionVersionNumber);
private getExtensionAssociationHash(name: string, versionNumber: number) {
const resourceIdentifier = this.resourceName ?? this.resourceArn;
const combinedString = stringifyObjects(resourceIdentifier, name, versionNumber);
return getHash(combinedString);
}

private getExtensionDefaultName() {
return Names.uniqueResourceName(this.scope, {
maxLength: 54,
separator: '-',
}) + '-Extension';
}
}

/**
Expand Down
Loading

0 comments on commit 2075559

Please sign in to comment.