在合成器运行之前,使用 CDK 将属性从一个构造传递到另一个构造
Pass properties over from one Construct to another with CDK before synth runs
我在一个 Stack 中创建了两个 Constructs,在合成过程中我想合并一堆属性并使用合并的结果。
这样做的原因是将资源的创建拆分为堆栈中的特定外观。换句话说,我想在一个堆栈中初始化两个构造,但是当 CDK 部署堆栈时,我希望将两者的属性与在其中一个堆栈中创建的资源合并,(Environment
在我下面的示例中)能够使用来自两个构造的合并属性。
这是我到目前为止所做的,但是当 运行 一个 cdk synth
结果 someProperties
对象不反映我从我的 ExampleThing
在同一堆栈中初始化的构造。
export class IExampleEnvironment extends Construct {
readonly someId?: string;
}
export interface ExampleProps {
readonly environment: Environment;
readonly a: string;
readonly b: string;
}
export class Environment extends IExampleEnvironment {
private someProperties: any;
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id);
new ExampleResourceThatUsesSomeProperties(this, 'Example' {
foo: this.someProperties // this is where I would like to use some properties that are brought in from another Construct (in the same stack as Environment)
});
}
public addSomeProperties(someProps: ExampleProps) {
this.someProperties = { A: someProps.a, B: someProps.b };
}
}
export class ExampleThing extends Construct {
constructor(scope: Construct, id: string, props: ExampleProps) {
super(scope, id);
props.environment.addSomeProperties(props);
}
}
// Creating the Stack...
const environment = new Environment(this, 'Environment', { someId: "123" });
const exampleThing = new ExampleThing(this, 'ExampleThing', props);
目前,我正在使用对发送的 Environment
属性 的引用,然后在其上调用内部 addSomeProperties()
方法,希望这会起作用。我怀疑这是我的问题,但我不确定如何实现。
这里重要的是必须首先创建 Environment
堆栈,因为 ExampleThing
堆栈需要提供 environment
属性 作为其 ExampleProps
并为此传递环境。
有更好的方法吗?
我认为您希望在资源之间创建依赖关系,这里是一个示例
const app = new App();
const myFirstStack = new MyFirstStack(
app,
stackNameone
);
const mySecondStack = new MySecondStack(
app,
stackNametwo
);
mySecondStack.addDependency(myFirstStack, "Depends on resources");
您可以对 CDK 中的大多数资源执行此操作,因此无论您想创建哪个资源,首先将其添加为依赖项,如上例所示。
所以我承认这是一个非常小众的要求,并不是 CDK 的真正用途,但我想让这个非常具体的用例发挥作用。
我深入研究了一下,发现可以通过覆盖 Construct 中的 prepare()
方法来实现。这是我的工作示例,它展示了一个构造如何创建 S3 存储桶,另一个构造如何完全通过创建一个实例并传入另一个实例来更新此实例的 S3 存储桶:
thing.ts:
import { Construct } from "@aws-cdk/core";
import { Foo } from "./foo";
export interface ExampleThingProps {
readonly foo: Foo;
readonly a: string;
readonly b?: string;
}
export class ExampleThing extends Construct {
constructor(scope: Construct, id: string, props: ExampleThingProps) {
super(scope, id);
props.foo.addSomeProperties(props);
}
}
foo.ts:
import { Construct, StackProps } from "@aws-cdk/core";
import * as s3 from "@aws-cdk/aws-s3";
import { ExampleThingProps } from "./thing";
import { IBucket } from "@aws-cdk/aws-s3";
export class IExampleFoo extends Construct {
readonly someId?: string;
}
export interface FooProps {
bucketName: string;
}
export class Foo extends IExampleFoo {
private someProperties: any;
private theBucket: IBucket;
constructor(scope: Construct, id: string, props: FooProps) {
super(scope, id);
this.someProperties = { A: props.bucketName };
this.theBucket = new s3.Bucket(this, 'ExampleBucket', {
bucketName: this.someProperties.A
});
}
prepare() {
const firstBucket = this.node.tryFindChild("ExampleBucket");
if (firstBucket) {
console.log('found first bucket node: ' + firstBucket.node.uniqueId);
const removed = this.node.tryRemoveChild(firstBucket.node.id);
console.log('removed the found node: ' + removed);
}
this.theBucket = new s3.Bucket(this, 'ExampleBucket', {
bucketName: this.someProperties.A
});
}
public addSomeProperties(someProps: ExampleThingProps) {
console.log('updates the existing properties...');
this.someProperties = { A: someProps.a, B: someProps.b };
}
}
用法:
const foo = new Foo(this, 'Foo', {
bucketName: "this-is-the-name-set-from-foo-construction"
});
const thing = new ExampleThing(this, 'Thing', {
foo: foo,
a: "shiny-new-name"
});
如果您不初始化新的 ExampleThing
,则该存储桶将被命名为 this-is-the-name-set-from-foo-construction。
如果你初始化一个新的ExampleThing
,那么bucket的名称将被更改以进行合成(并将应用于cdk diff
或deploy
并被命名为闪亮的新名字.
我在一个 Stack 中创建了两个 Constructs,在合成过程中我想合并一堆属性并使用合并的结果。
这样做的原因是将资源的创建拆分为堆栈中的特定外观。换句话说,我想在一个堆栈中初始化两个构造,但是当 CDK 部署堆栈时,我希望将两者的属性与在其中一个堆栈中创建的资源合并,(Environment
在我下面的示例中)能够使用来自两个构造的合并属性。
这是我到目前为止所做的,但是当 运行 一个 cdk synth
结果 someProperties
对象不反映我从我的 ExampleThing
在同一堆栈中初始化的构造。
export class IExampleEnvironment extends Construct {
readonly someId?: string;
}
export interface ExampleProps {
readonly environment: Environment;
readonly a: string;
readonly b: string;
}
export class Environment extends IExampleEnvironment {
private someProperties: any;
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id);
new ExampleResourceThatUsesSomeProperties(this, 'Example' {
foo: this.someProperties // this is where I would like to use some properties that are brought in from another Construct (in the same stack as Environment)
});
}
public addSomeProperties(someProps: ExampleProps) {
this.someProperties = { A: someProps.a, B: someProps.b };
}
}
export class ExampleThing extends Construct {
constructor(scope: Construct, id: string, props: ExampleProps) {
super(scope, id);
props.environment.addSomeProperties(props);
}
}
// Creating the Stack...
const environment = new Environment(this, 'Environment', { someId: "123" });
const exampleThing = new ExampleThing(this, 'ExampleThing', props);
目前,我正在使用对发送的 Environment
属性 的引用,然后在其上调用内部 addSomeProperties()
方法,希望这会起作用。我怀疑这是我的问题,但我不确定如何实现。
这里重要的是必须首先创建 Environment
堆栈,因为 ExampleThing
堆栈需要提供 environment
属性 作为其 ExampleProps
并为此传递环境。
有更好的方法吗?
我认为您希望在资源之间创建依赖关系,这里是一个示例
const app = new App();
const myFirstStack = new MyFirstStack(
app,
stackNameone
);
const mySecondStack = new MySecondStack(
app,
stackNametwo
);
mySecondStack.addDependency(myFirstStack, "Depends on resources");
您可以对 CDK 中的大多数资源执行此操作,因此无论您想创建哪个资源,首先将其添加为依赖项,如上例所示。
所以我承认这是一个非常小众的要求,并不是 CDK 的真正用途,但我想让这个非常具体的用例发挥作用。
我深入研究了一下,发现可以通过覆盖 Construct 中的 prepare()
方法来实现。这是我的工作示例,它展示了一个构造如何创建 S3 存储桶,另一个构造如何完全通过创建一个实例并传入另一个实例来更新此实例的 S3 存储桶:
thing.ts:
import { Construct } from "@aws-cdk/core";
import { Foo } from "./foo";
export interface ExampleThingProps {
readonly foo: Foo;
readonly a: string;
readonly b?: string;
}
export class ExampleThing extends Construct {
constructor(scope: Construct, id: string, props: ExampleThingProps) {
super(scope, id);
props.foo.addSomeProperties(props);
}
}
foo.ts:
import { Construct, StackProps } from "@aws-cdk/core";
import * as s3 from "@aws-cdk/aws-s3";
import { ExampleThingProps } from "./thing";
import { IBucket } from "@aws-cdk/aws-s3";
export class IExampleFoo extends Construct {
readonly someId?: string;
}
export interface FooProps {
bucketName: string;
}
export class Foo extends IExampleFoo {
private someProperties: any;
private theBucket: IBucket;
constructor(scope: Construct, id: string, props: FooProps) {
super(scope, id);
this.someProperties = { A: props.bucketName };
this.theBucket = new s3.Bucket(this, 'ExampleBucket', {
bucketName: this.someProperties.A
});
}
prepare() {
const firstBucket = this.node.tryFindChild("ExampleBucket");
if (firstBucket) {
console.log('found first bucket node: ' + firstBucket.node.uniqueId);
const removed = this.node.tryRemoveChild(firstBucket.node.id);
console.log('removed the found node: ' + removed);
}
this.theBucket = new s3.Bucket(this, 'ExampleBucket', {
bucketName: this.someProperties.A
});
}
public addSomeProperties(someProps: ExampleThingProps) {
console.log('updates the existing properties...');
this.someProperties = { A: someProps.a, B: someProps.b };
}
}
用法:
const foo = new Foo(this, 'Foo', {
bucketName: "this-is-the-name-set-from-foo-construction"
});
const thing = new ExampleThing(this, 'Thing', {
foo: foo,
a: "shiny-new-name"
});
如果您不初始化新的 ExampleThing
,则该存储桶将被命名为 this-is-the-name-set-from-foo-construction。
如果你初始化一个新的ExampleThing
,那么bucket的名称将被更改以进行合成(并将应用于cdk diff
或deploy
并被命名为闪亮的新名字.