UNPKG

@aws-cdk/aws-redshift-alpha

Version:

The CDK Construct Library for AWS::Redshift

622 lines 90.9 kB
"use strict"; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Cluster = exports.MaintenanceTrackName = exports.ResourceAction = exports.ClusterType = exports.NodeType = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path = require("path"); const ec2 = require("aws-cdk-lib/aws-ec2"); const iam = require("aws-cdk-lib/aws-iam"); const lambda = require("aws-cdk-lib/aws-lambda"); const aws_redshift_1 = require("aws-cdk-lib/aws-redshift"); const secretsmanager = require("aws-cdk-lib/aws-secretsmanager"); const core_1 = require("aws-cdk-lib/core"); const helpers_internal_1 = require("aws-cdk-lib/core/lib/helpers-internal"); const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource"); const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable"); const custom_resources_1 = require("aws-cdk-lib/custom-resources"); const database_secret_1 = require("./database-secret"); const endpoint_1 = require("./endpoint"); const parameter_group_1 = require("./parameter-group"); const subnet_group_1 = require("./subnet-group"); /** * Possible Node Types to use in the cluster * used for defining `ClusterProps.nodeType`. */ var NodeType; (function (NodeType) { /** * ds2.xlarge */ NodeType["DS2_XLARGE"] = "ds2.xlarge"; /** * ds2.8xlarge */ NodeType["DS2_8XLARGE"] = "ds2.8xlarge"; /** * dc1.large */ NodeType["DC1_LARGE"] = "dc1.large"; /** * dc1.8xlarge */ NodeType["DC1_8XLARGE"] = "dc1.8xlarge"; /** * dc2.large */ NodeType["DC2_LARGE"] = "dc2.large"; /** * dc2.8xlarge */ NodeType["DC2_8XLARGE"] = "dc2.8xlarge"; /** * ra3.large */ NodeType["RA3_LARGE"] = "ra3.large"; /** * ra3.xlplus */ NodeType["RA3_XLPLUS"] = "ra3.xlplus"; /** * ra3.4xlarge */ NodeType["RA3_4XLARGE"] = "ra3.4xlarge"; /** * ra3.16xlarge */ NodeType["RA3_16XLARGE"] = "ra3.16xlarge"; })(NodeType || (exports.NodeType = NodeType = {})); /** * What cluster type to use. * Used by `ClusterProps.clusterType` */ var ClusterType; (function (ClusterType) { /** * single-node cluster, the `ClusterProps.numberOfNodes` parameter is not required */ ClusterType["SINGLE_NODE"] = "single-node"; /** * multi-node cluster, set the amount of nodes using `ClusterProps.numberOfNodes` parameter */ ClusterType["MULTI_NODE"] = "multi-node"; })(ClusterType || (exports.ClusterType = ClusterType = {})); /** * The Amazon Redshift operation */ var ResourceAction; (function (ResourceAction) { /** * Pause the cluster */ ResourceAction["PAUSE_CLUSTER"] = "pause-cluster"; /** * Resume the cluster */ ResourceAction["RESUME_CLUSTER"] = "resume-cluster"; /** * Failing over to the other availability zone * * @see https://docs.aws.amazon.com/redshift/latest/mgmt/test-cluster-multi-az.html */ ResourceAction["FAILOVER_PRIMARY_COMPUTE"] = "failover-primary-compute"; })(ResourceAction || (exports.ResourceAction = ResourceAction = {})); /** * The maintenance track for the cluster. * * @see https://docs.aws.amazon.com/redshift/latest/mgmt/managing-cluster-considerations.html#rs-mgmt-maintenance-tracks */ var MaintenanceTrackName; (function (MaintenanceTrackName) { /** * Updated to the most recently certified maintenance release. */ MaintenanceTrackName["CURRENT"] = "current"; /** * Update to the previously certified maintenance release. */ MaintenanceTrackName["TRAILING"] = "trailing"; })(MaintenanceTrackName || (exports.MaintenanceTrackName = MaintenanceTrackName = {})); /** * A new or imported clustered database. */ class ClusterBase extends core_1.Resource { /** * Renders the secret attachment target specifications. */ asSecretAttachmentTarget() { return { targetId: this.clusterName, targetType: secretsmanager.AttachmentTargetType.REDSHIFT_CLUSTER, }; } } /** * Create a Redshift cluster a given number of nodes. * * @resource AWS::Redshift::Cluster */ let Cluster = (() => { let _classDecorators = [prop_injectable_1.propertyInjectable, helpers_internal_1.noBoxStackTraces]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = ClusterBase; let _instanceExtraInitializers = []; let _addRotationSingleUser_decorators; let _addRotationMultiUser_decorators; let _addToParameterGroup_decorators; let _enableRebootForParameterChanges_decorators; let _addDefaultIamRole_decorators; let _addIamRole_decorators; var Cluster = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _addRotationSingleUser_decorators = [(0, metadata_resource_1.MethodMetadata)()]; _addRotationMultiUser_decorators = [(0, metadata_resource_1.MethodMetadata)()]; _addToParameterGroup_decorators = [(0, metadata_resource_1.MethodMetadata)()]; _enableRebootForParameterChanges_decorators = [(0, metadata_resource_1.MethodMetadata)()]; _addDefaultIamRole_decorators = [(0, metadata_resource_1.MethodMetadata)()]; _addIamRole_decorators = [(0, metadata_resource_1.MethodMetadata)()]; __esDecorate(this, null, _addRotationSingleUser_decorators, { kind: "method", name: "addRotationSingleUser", static: false, private: false, access: { has: obj => "addRotationSingleUser" in obj, get: obj => obj.addRotationSingleUser }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(this, null, _addRotationMultiUser_decorators, { kind: "method", name: "addRotationMultiUser", static: false, private: false, access: { has: obj => "addRotationMultiUser" in obj, get: obj => obj.addRotationMultiUser }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(this, null, _addToParameterGroup_decorators, { kind: "method", name: "addToParameterGroup", static: false, private: false, access: { has: obj => "addToParameterGroup" in obj, get: obj => obj.addToParameterGroup }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(this, null, _enableRebootForParameterChanges_decorators, { kind: "method", name: "enableRebootForParameterChanges", static: false, private: false, access: { has: obj => "enableRebootForParameterChanges" in obj, get: obj => obj.enableRebootForParameterChanges }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(this, null, _addDefaultIamRole_decorators, { kind: "method", name: "addDefaultIamRole", static: false, private: false, access: { has: obj => "addDefaultIamRole" in obj, get: obj => obj.addDefaultIamRole }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(this, null, _addIamRole_decorators, { kind: "method", name: "addIamRole", static: false, private: false, access: { has: obj => "addIamRole" in obj, get: obj => obj.addIamRole }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Cluster = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-redshift-alpha.Cluster", version: "2.257.0-alpha.0" }; /** Uniquely identifies this class. */ static PROPERTY_INJECTION_ID = '@aws-cdk.aws-redshift-alpha.Cluster'; /** * Import an existing DatabaseCluster from properties */ static fromClusterAttributes(scope, id, attrs) { try { jsiiDeprecationWarnings._aws_cdk_aws_redshift_alpha_ClusterAttributes(attrs); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromClusterAttributes); } throw error; } class Import extends ClusterBase { connections = new ec2.Connections({ securityGroups: attrs.securityGroups, defaultPort: ec2.Port.tcp(attrs.clusterEndpointPort), }); clusterName = attrs.clusterName; instanceIdentifiers = []; clusterEndpoint = new endpoint_1.Endpoint(attrs.clusterEndpointAddress, attrs.clusterEndpointPort); } return new Import(scope, id); } /** * Identifier of the cluster */ clusterName = __runInitializers(this, _instanceExtraInitializers); /** * The endpoint to use for read/write operations */ clusterEndpoint; /** * Access to the network connections */ connections; /** * The secret attached to this cluster */ secret; singleUserRotationApplication; multiUserRotationApplication; /** * The VPC where the DB subnet group is created. */ vpc; /** * The subnets used by the DB subnet group. */ vpcSubnets; /** * The underlying CfnCluster */ cluster; /** * The cluster's parameter group */ parameterGroup; /** * The ARNs of the roles that will be attached to the cluster. * * **NOTE** Please do not access this directly, use the `addIamRole` method instead. */ roles; constructor(scope, id, props) { super(scope, id); try { jsiiDeprecationWarnings._aws_cdk_aws_redshift_alpha_ClusterProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, Cluster); } throw error; } // Enhanced CDK Analytics Telemetry (0, metadata_resource_1.addConstructMetadata)(this, props); this.vpc = props.vpc; this.vpcSubnets = props.vpcSubnets ?? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, }; this.parameterGroup = props.parameterGroup; this.roles = helpers_internal_1.Box.fromArray(props?.roles ? [...props.roles] : []); const removalPolicy = props.removalPolicy ?? core_1.RemovalPolicy.RETAIN; const subnetGroup = props.subnetGroup ?? new subnet_group_1.ClusterSubnetGroup(this, 'Subnets', { description: `Subnets for ${id} Redshift cluster`, vpc: this.vpc, vpcSubnets: this.vpcSubnets, removalPolicy: removalPolicy, }); const securityGroups = props.securityGroups ?? [new ec2.SecurityGroup(this, 'SecurityGroup', { description: 'Redshift security group', vpc: this.vpc, })]; const securityGroupIds = securityGroups.map(sg => sg.securityGroupId); let secret; if (!props.masterUser.masterPassword) { secret = new database_secret_1.DatabaseSecret(this, 'Secret', { username: props.masterUser.masterUsername, encryptionKey: props.masterUser.encryptionKey, excludeCharacters: props.masterUser.excludeCharacters, }); } const clusterType = props.clusterType || ClusterType.MULTI_NODE; const nodeCount = this.validateNodeCount(clusterType, props.numberOfNodes); if (props.encrypted === false && props.encryptionKey !== undefined) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `EncryptionKeyWithoutEncryption`, 'Cannot set property encryptionKey without enabling encryption!', this); } this.singleUserRotationApplication = secretsmanager.SecretRotationApplication.REDSHIFT_ROTATION_SINGLE_USER; this.multiUserRotationApplication = secretsmanager.SecretRotationApplication.REDSHIFT_ROTATION_MULTI_USER; let loggingProperties; if (props.loggingProperties) { loggingProperties = { bucketName: props.loggingProperties.loggingBucket.bucketName, s3KeyPrefix: props.loggingProperties.loggingKeyPrefix, }; props.loggingProperties.loggingBucket.addToResourcePolicy(new iam.PolicyStatement({ actions: [ 's3:GetBucketAcl', 's3:PutObject', ], resources: [ props.loggingProperties.loggingBucket.arnForObjects('*'), props.loggingProperties.loggingBucket.bucketArn, ], principals: [ new iam.ServicePrincipal('redshift.amazonaws.com'), ], })); } const nodeType = props.nodeType || NodeType.RA3_LARGE; if (props.multiAz) { if (!nodeType.startsWith('ra3')) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `MultiAzUnsupportedNodeType`, `Multi-AZ cluster is only supported for RA3 node types, got: ${props.nodeType}`, this); } if (clusterType === ClusterType.SINGLE_NODE) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `MultiAzUnsupportedClusterType`, 'Multi-AZ cluster is not supported for `clusterType` single-node', this); } } if (props.resourceAction === ResourceAction.FAILOVER_PRIMARY_COMPUTE && !props.multiAz) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `FailoverRequiresMultiAz`, 'ResourceAction.FAILOVER_PRIMARY_COMPUTE can only be used with multi-AZ clusters.', this); } if (props.availabilityZoneRelocation && !nodeType.startsWith('ra3')) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `AvailabilityZoneRelocationUnsupportedNodeType`, `Availability zone relocation is supported for only RA3 node types, got: ${props.nodeType}`, this); } this.cluster = new aws_redshift_1.CfnCluster(this, 'Resource', { // Basic allowVersionUpgrade: true, maintenanceTrackName: props.maintenanceTrackName, automatedSnapshotRetentionPeriod: 1, clusterType, clusterIdentifier: props.clusterName, clusterSubnetGroupName: subnetGroup.clusterSubnetGroupName, vpcSecurityGroupIds: securityGroupIds, port: props.port, clusterParameterGroupName: props.parameterGroup && props.parameterGroup.clusterParameterGroupName, // Admin (unsafeUnwrap here is safe) masterUsername: secret?.secretValueFromJson('username').unsafeUnwrap() ?? props.masterUser.masterUsername, masterUserPassword: secret?.secretValueFromJson('password').unsafeUnwrap() ?? props.masterUser.masterPassword?.unsafeUnwrap() ?? 'default', preferredMaintenanceWindow: props.preferredMaintenanceWindow, nodeType, numberOfNodes: nodeCount, loggingProperties, iamRoles: core_1.Token.asList(this.roles.map(role => role.roleArn)), dbName: props.defaultDatabaseName || 'default_db', publiclyAccessible: props.publiclyAccessible || false, // Encryption kmsKeyId: props.encryptionKey?.keyRef.keyId, encrypted: props.encrypted ?? true, classic: props.classicResizing, elasticIp: props.elasticIp, enhancedVpcRouting: props.enhancedVpcRouting, multiAz: props.multiAz, resourceAction: props.resourceAction, availabilityZoneRelocation: props.availabilityZoneRelocation, }); this.cluster.applyRemovalPolicy(removalPolicy, { applyToUpdateReplacePolicy: true, }); this.clusterName = this.cluster.ref; // create a number token that represents the port of the cluster const portAttribute = core_1.Token.asNumber(this.cluster.attrEndpointPort); this.clusterEndpoint = new endpoint_1.Endpoint(this.cluster.attrEndpointAddress, portAttribute); if (secret) { this.secret = secret.attach(this); } const defaultPort = ec2.Port.tcp(this.clusterEndpoint.port); this.connections = new ec2.Connections({ securityGroups, defaultPort }); if (props.rebootForParameterChanges) { this.enableRebootForParameterChanges(); } // Add default role if specified and also available in the roles list if (props.defaultRole) { if (props.roles?.some(x => x === props.defaultRole)) { this.addDefaultIamRole(props.defaultRole); } else { throw new core_1.ValidationError((0, helpers_internal_1.lit) `DefaultRoleNotInRolesList`, 'Default role must be included in role list.', this); } } } /** * Adds the single user rotation of the master password to this cluster. * * @param [automaticallyAfter=Duration.days(30)] Specifies the number of days after the previous rotation * before Secrets Manager triggers the next automatic rotation. */ addRotationSingleUser(automaticallyAfter) { if (!this.secret) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `NoSecretForRotation`, 'Cannot add single user rotation for a cluster without secret.', this); } const id = 'RotationSingleUser'; const existing = this.node.tryFindChild(id); if (existing) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `SingleUserRotationAlreadyExists`, 'A single user rotation was already added to this cluster.', this); } return new secretsmanager.SecretRotation(this, id, { secret: this.secret, automaticallyAfter, application: this.singleUserRotationApplication, vpc: this.vpc, vpcSubnets: this.vpcSubnets, target: this, }); } /** * Adds the multi user rotation to this cluster. */ addRotationMultiUser(id, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_redshift_alpha_RotationMultiUserOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addRotationMultiUser); } throw error; } if (!this.secret) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `NoSecretForMultiUserRotation`, 'Cannot add multi user rotation for a cluster without secret.', this); } return new secretsmanager.SecretRotation(this, id, { secret: options.secret, masterSecret: this.secret, automaticallyAfter: options.automaticallyAfter, application: this.multiUserRotationApplication, vpc: this.vpc, vpcSubnets: this.vpcSubnets, target: this, }); } validateNodeCount(clusterType, numberOfNodes) { if (clusterType === ClusterType.SINGLE_NODE) { // This property must not be set for single-node clusters; be generous and treat a value of 1 node as undefined. if (numberOfNodes !== undefined && numberOfNodes !== 1) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `InvalidNodeCountForSingleNode`, 'Number of nodes must be not be supplied or be 1 for cluster type single-node', this); } return undefined; } else { if (core_1.Token.isUnresolved(numberOfNodes)) { return numberOfNodes; } const nodeCount = numberOfNodes ?? 2; if (nodeCount < 2 || nodeCount > 100) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `InvalidNodeCountForMultiNode`, 'Number of nodes for cluster type multi-node must be at least 2 and no more than 100', this); } return nodeCount; } } /** * Adds a parameter to the Clusters' parameter group * * @param name the parameter name * @param value the parameter name */ addToParameterGroup(name, value) { if (!this.parameterGroup) { const param = {}; param[name] = value; this.parameterGroup = new parameter_group_1.ClusterParameterGroup(this, 'ParameterGroup', { description: this.cluster.clusterIdentifier ? `Parameter Group for the ${this.cluster.clusterIdentifier} Redshift cluster` : 'Cluster parameter group for family redshift-1.0', parameters: param, }); this.cluster.clusterParameterGroupName = this.parameterGroup.clusterParameterGroupName; } else if (this.parameterGroup instanceof parameter_group_1.ClusterParameterGroup) { this.parameterGroup.addParameter(name, value); } else { throw new core_1.ValidationError((0, helpers_internal_1.lit) `CannotAddParameterToImportedGroup`, 'Cannot add a parameter to an imported parameter group.', this); } } /** * Enables automatic cluster rebooting when changes to the cluster's parameter group require a restart to apply. */ enableRebootForParameterChanges() { if (this.node.tryFindChild('RedshiftClusterRebooterCustomResource')) { return; } const rebootFunction = new lambda.SingletonFunction(this, 'RedshiftClusterRebooterFunction', { uuid: '511e207f-13df-4b8b-b632-c32b30b65ac2', runtime: lambda.determineLatestNodeRuntime(this), code: lambda.Code.fromAsset(path.join(__dirname, '..', 'custom-resource-handlers', 'dist', 'aws-redshift-alpha', 'cluster-parameter-change-reboot-handler')), handler: 'index.handler', timeout: core_1.Duration.seconds(900), }); rebootFunction.addToRolePolicy(new iam.PolicyStatement({ actions: ['redshift:DescribeClusters'], resources: ['*'], })); rebootFunction.addToRolePolicy(new iam.PolicyStatement({ actions: ['redshift:RebootCluster'], resources: [ core_1.Stack.of(this).formatArn({ service: 'redshift', resource: 'cluster', resourceName: this.clusterName, arnFormat: core_1.ArnFormat.COLON_RESOURCE_NAME, }), ], })); const provider = new custom_resources_1.Provider(this, 'ResourceProvider', { onEventHandler: rebootFunction, }); const customResource = new core_1.CustomResource(this, 'RedshiftClusterRebooterCustomResource', { resourceType: 'Custom::RedshiftClusterRebooter', serviceToken: provider.serviceToken, properties: { ClusterId: this.clusterName, ParameterGroupName: core_1.Lazy.string({ produce: () => { if (!this.parameterGroup) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `NoParameterGroupForReboot`, 'Cannot enable reboot for parameter changes when there is no associated ClusterParameterGroup.', this); } return this.parameterGroup.clusterParameterGroupName; }, }), ParametersString: core_1.Lazy.string({ produce: () => { if (!(this.parameterGroup instanceof parameter_group_1.ClusterParameterGroup)) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `ImportedParameterGroupForReboot`, 'Cannot enable reboot for parameter changes when using an imported parameter group.', this); } return JSON.stringify(this.parameterGroup.parameters); }, }), }, }); core_1.Lazy.any({ produce: () => { if (!this.parameterGroup) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `NoParameterGroupForRebootDependency`, 'Cannot enable reboot for parameter changes when there is no associated ClusterParameterGroup.', this); } customResource.node.addDependency(this, this.parameterGroup); }, }); } /** * Adds default IAM role to cluster. The default IAM role must be already associated to the cluster to be added as the default role. * * @param defaultIamRole the IAM role to be set as the default role */ addDefaultIamRole(defaultIamRole) { // Check to see if default role is included in list of cluster IAM roles if (!this.roles.includes(defaultIamRole)) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `DefaultRoleNotAssociated`, 'Default role must be associated to the Redshift cluster to be set as the default role.', this); } // On UPDATE or CREATE define the default IAM role. On DELETE, remove the default IAM role const defaultRoleCustomResource = new custom_resources_1.AwsCustomResource(this, 'default-role', { onUpdate: { service: 'Redshift', action: 'modifyClusterIamRoles', parameters: { ClusterIdentifier: this.cluster.ref, DefaultIamRoleArn: defaultIamRole.roleArn, }, physicalResourceId: custom_resources_1.PhysicalResourceId.of(`${defaultIamRole.roleArn}-${this.cluster.ref}`), }, onDelete: { service: 'Redshift', action: 'modifyClusterIamRoles', parameters: { ClusterIdentifier: this.cluster.ref, DefaultIamRoleArn: '', }, physicalResourceId: custom_resources_1.PhysicalResourceId.of(`${defaultIamRole.roleArn}-${this.cluster.ref}`), }, policy: custom_resources_1.AwsCustomResourcePolicy.fromSdkCalls({ resources: custom_resources_1.AwsCustomResourcePolicy.ANY_RESOURCE, }), installLatestAwsSdk: false, }); defaultIamRole.grantPassRole(defaultRoleCustomResource.grantPrincipal); } /** * Adds a role to the cluster * * @param role the role to add */ addIamRole(role) { if (this.roles.includes(role)) { throw new core_1.ValidationError((0, helpers_internal_1.lit) `RoleAlreadyAttached`, `Role '${role.roleArn}' is already attached to the cluster`, this); } this.roles.push(role); } static { __runInitializers(_classThis, _classExtraInitializers); } }; return Cluster = _classThis; })(); exports.Cluster = Cluster; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsNkJBQTZCO0FBQzdCLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFFM0MsaURBQWlEO0FBQ2pELDJEQUFzRDtBQUV0RCxpRUFBaUU7QUFFakUsMkNBQXFJO0FBRXJJLDRFQUFtRjtBQUNuRiw4RUFBOEY7QUFDOUYsMEVBQTBFO0FBQzFFLG1FQUF3SDtBQUV4SCx1REFBbUQ7QUFDbkQseUNBQXNDO0FBRXRDLHVEQUEwRDtBQUUxRCxpREFBb0Q7QUFFcEQ7OztHQUdHO0FBQ0gsSUFBWSxRQWtEWDtBQWxERCxXQUFZLFFBQVE7SUFDbEI7O09BRUc7SUFDSCxxQ0FBeUIsQ0FBQTtJQUV6Qjs7T0FFRztJQUNILHVDQUEyQixDQUFBO0lBRTNCOztPQUVHO0lBQ0gsbUNBQXVCLENBQUE7SUFFdkI7O09BRUc7SUFDSCx1Q0FBMkIsQ0FBQTtJQUUzQjs7T0FFRztJQUNILG1DQUF1QixDQUFBO0lBRXZCOztPQUVHO0lBQ0gsdUNBQTJCLENBQUE7SUFFM0I7O09BRUc7SUFDSCxtQ0FBdUIsQ0FBQTtJQUV2Qjs7T0FFRztJQUNILHFDQUF5QixDQUFBO0lBRXpCOztPQUVHO0lBQ0gsdUNBQTJCLENBQUE7SUFFM0I7O09BRUc7SUFDSCx5Q0FBNkIsQ0FBQTtBQUMvQixDQUFDLEVBbERXLFFBQVEsd0JBQVIsUUFBUSxRQWtEbkI7QUFFRDs7O0dBR0c7QUFDSCxJQUFZLFdBU1g7QUFURCxXQUFZLFdBQVc7SUFDckI7O09BRUc7SUFDSCwwQ0FBMkIsQ0FBQTtJQUMzQjs7T0FFRztJQUNILHdDQUF5QixDQUFBO0FBQzNCLENBQUMsRUFUVyxXQUFXLDJCQUFYLFdBQVcsUUFTdEI7QUFFRDs7R0FFRztBQUNILElBQVksY0FpQlg7QUFqQkQsV0FBWSxjQUFjO0lBQ3hCOztPQUVHO0lB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SCxDQUFDO1lBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDdkI7O1lBbmJVLHVEQUFPOzs7OztBQUFQLDBCQUFPIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGVjMiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB0eXBlICogYXMga21zIGZyb20gJ2F3cy1jZGstbGliL2F3cy1rbXMnO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgQ2ZuQ2x1c3RlciB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1yZWRzaGlmdCc7XG5pbXBvcnQgdHlwZSAqIGFzIHMzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgKiBhcyBzZWNyZXRzbWF