@aws-cdk/aws-redshift-alpha
Version:
The CDK Construct Library for AWS::Redshift
622 lines • 90.9 kB
JavaScript
"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