import * as ecs from '@aws-cdk/aws-ecs' ; import * as sns from '@aws-cdk/aws-sns' ; import { Service } from '../service' ; import { Container } from './container' ; import { ContainerMutatingHook , ServiceExtension } from './extension-interfaces' ; import { Construct } from '@aws-cdk/core' ; /**
 * An interface that will be implemented by all the resources that can be published events or written data to.
 */ export interface Injectable { environmentVariables ( ) : { [ key ] : string ; } ; } /**
 * An interface that will be implemented by all the injectable resources that need to grant permissions to the task role.
 */ export interface GrantInjectable extends Injectable { grant ( taskDefinition ) : void ; } /**
 * The settings for the `InjectableTopic` class.
 */ export interface InjectableTopicProps { /**
     * The SNS Topic to publish events to.
     */ readonly topic : sns . ITopic ; } /**
 * The `InjectableTopic` class represents SNS Topic resource that can be published events to by the parent service.
 */ export class InjectableTopic implements GrantInjectable { public readonly topic : sns . ITopic ; constructor ( props ) { this . topic = props . topic ; } public grant ( taskDefinition ) { this . topic . grantPublish ( taskDefinition . taskRole ) ; } public environmentVariables ( ) { let environment = { } ; environment [ `${ this . topic . node . id . toUpperCase ( ) }_TOPIC_ARN` ] = this . topic . topicArn ; return environment ; } } /**
 * The settings for the Injecter extension.
 */ export interface InjecterExtensionProps { /**
     * The list of injectable resources for this service.
     */ readonly injectables : Injectable [ ] ; } /**
 * Settings for the hook which mutates the application container
 * to add the injectable resource environment variables.
 */ interface ContainerMutatingProps { /**
     * The resource environment variables to be added to the container environment.
     */ readonly environment : { [ key ] : string ; } ; } /**
 * This hook modifies the application container's environment to
 * add the injectable resource environment variables.
 */ class InjecterExtensionMutatingHook extends ContainerMutatingHook { private environment : { [ key ] : string ; } ; constructor ( props ) { super ( ) ; this . environment = props . environment ; } public mutateContainerDefinition ( props ) { return { ... props , environment : { ... ( props . environment || { } ) , ... this . environment } , } as ecs . ContainerDefinitionOptions ; } } /**
 * This extension accepts a list of `Injectable` resources that the parent service can publish events or write data to.
 * It sets up the corresponding permissions for the task role of the parent service.
 */ export class InjecterExtension extends ServiceExtension { private props : InjecterExtensionProps ; private environment : { [ key ] : string ; } = { } ; constructor ( props ) { super ( 'injecter' ) ; this . props = props ; } public prehook ( service , scope ) { this . parentService = service ; for ( const injectable of this . props . injectables ) { for ( const [ key , val ] of Object . entries ( injectable . environmentVariables ( ) ) ) { this . environment [ key ] = val ; } } } /**
     * Add hooks to the main application extension so that it is modified to
     * add the injectable resource environment variables to the container environment.
     */ public addHooks ( ) { const container = this . parentService . serviceDescription . get ( 'service-container' ) as Container ; if ( ! container ) { throw new Error ( 'Injecter Extension requires an application extension' ) ; } container . addContainerMutatingHook ( new InjecterExtensionMutatingHook ( { environment : this . environment , } ) ) ; } param taskDefinition public useTaskDefinition ( taskDefinition ) { for ( const injectable of this . props . injectables ) { if ( ( injectable as GrantInjectable ) . grant !== undefined ) { ( injectable as GrantInjectable ) . grant ( taskDefinition ) ; } } } }