Skip to content

Commit 330d6ef

Browse files
committed
feat(lib): Add support for the built-in Terraform data resource
Closes #3142
1 parent 53bec67 commit 330d6ef

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import { Construct } from "constructs";
2+
import * as cdktf from "cdktf";
3+
import { ValidateTerraformVersion } from "./validations/validate-terraform-version";
4+
5+
export interface DataConfig extends cdktf.TerraformMetaArguments {
6+
/**
7+
* (Optional) A value which will be stored in the instance state, and reflected in the output attribute after apply.
8+
* https://developer.hashicorp.com/terraform/language/resources/terraform-data#input
9+
*/
10+
readonly input?: { [key: string]: any };
11+
/**
12+
* (Optional) A value which is stored in the instance state, and will force replacement when the value changes.
13+
* https://developer.hashicorp.com/terraform/language/resources/terraform-data#triggers_replace
14+
*/
15+
readonly triggersReplace?: { [key: string]: any };
16+
}
17+
18+
/**
19+
* The DataResource implements the standard resource lifecycle, but does not directly take any other actions. You can use the DataResource resource without requiring or configuring a provider.
20+
*
21+
* The DataResource resource is useful for storing values which need to follow a manage resource lifecycle, and for triggering provisioners when there is no other logical managed resource in which to place them.
22+
*
23+
* It requires Terraform 1.4 or later.
24+
*
25+
* It is also possible to generate these bindings by adding "terraform.io/builtin/terraform" to the "terraformProviders" key in your cdktf.json file and running "cdktf get".
26+
*
27+
* https://developer.hashicorp.com/terraform/language/resources/terraform-data
28+
*/
29+
export class DataResource extends cdktf.TerraformResource {
30+
// =================
31+
// STATIC PROPERTIES
32+
// =================
33+
public static readonly tfResourceType = "terraform_data";
34+
35+
// ==============
36+
// STATIC Methods
37+
// ==============
38+
/**
39+
* Generates CDKTF code for importing a Data resource upon running "cdktf plan <stack-name>"
40+
* @param scope The scope in which to define this construct
41+
* @param importToId The construct id used in the generated config for the Data to import
42+
* @param importFromId The id of the existing Data that should be imported. Refer to the {@link https://terraform.io/providers/builtin/terraform/latest/docs/resources/data#import import section} in the documentation of this resource for the id to use
43+
* @param provider? Optional instance of the provider where the Data to import is found
44+
*/
45+
public static generateConfigForImport(
46+
scope: Construct,
47+
importToId: string,
48+
importFromId: string,
49+
provider?: cdktf.TerraformProvider
50+
) {
51+
return new cdktf.ImportableResource(scope, importToId, {
52+
terraformResourceType: "terraform_data",
53+
importId: importFromId,
54+
provider,
55+
});
56+
}
57+
58+
// ===========
59+
// INITIALIZER
60+
// ===========
61+
62+
/**
63+
* Create a new TerraformData Resource.
64+
*
65+
* The DataResource resource is useful for storing values which need to follow a manage resource lifecycle, and for triggering provisioners when there is no other logical managed resource in which to place them.
66+
*
67+
* @param scope The scope in which to define this construct
68+
* @param id The scoped construct ID. Must be unique amongst siblings in the same scope
69+
* @param options DataConfig = {}
70+
*/
71+
public constructor(scope: Construct, id: string, config: DataConfig = {}) {
72+
super(scope, id, {
73+
terraformResourceType: "terraform_data",
74+
terraformGeneratorMetadata: {
75+
providerName: "terraform",
76+
},
77+
provider: config.provider,
78+
dependsOn: config.dependsOn,
79+
count: config.count,
80+
lifecycle: config.lifecycle,
81+
provisioners: config.provisioners,
82+
connection: config.connection,
83+
forEach: config.forEach,
84+
});
85+
this._input = config.input;
86+
this._triggersReplace = config.triggersReplace;
87+
this.node.addValidation(
88+
new ValidateTerraformVersion(
89+
">=1.4",
90+
`The built-in Terraform data resource is only supported for Terraform >=1.4. Please upgrade your Terraform version.`
91+
)
92+
);
93+
}
94+
95+
// ==========
96+
// ATTRIBUTES
97+
// ==========
98+
99+
// id - computed: true, optional: false, required: false
100+
public get id() {
101+
return this.getStringAttribute("id");
102+
}
103+
104+
// input - computed: false, optional: true, required: false
105+
private _input?: { [key: string]: any };
106+
public get input() {
107+
return this.getAnyMapAttribute("input");
108+
}
109+
/**
110+
* (Optional) A value which will be stored in the instance state, and reflected in the output attribute after apply.
111+
* https://developer.hashicorp.com/terraform/language/resources/terraform-data#input
112+
*/
113+
public set input(value: { [key: string]: any }) {
114+
this._input = value;
115+
}
116+
public resetInput() {
117+
this._input = undefined;
118+
}
119+
// Temporarily expose input value. Use with caution.
120+
public get inputInput() {
121+
return this._input;
122+
}
123+
124+
// output - computed: true, optional: false, required: false
125+
private _output = new cdktf.AnyMap(this, "output");
126+
public get output() {
127+
return this._output;
128+
}
129+
130+
// triggers_replace - computed: false, optional: true, required: false
131+
private _triggersReplace?: { [key: string]: any };
132+
public get triggersReplace() {
133+
return this.getAnyMapAttribute("triggers_replace");
134+
}
135+
/**
136+
* (Optional) A value which is stored in the instance state, and will force replacement when the value changes.
137+
* https://developer.hashicorp.com/terraform/language/resources/terraform-data#triggers_replace
138+
*/
139+
public set triggersReplace(value: { [key: string]: any }) {
140+
this._triggersReplace = value;
141+
}
142+
public resetTriggersReplace() {
143+
this._triggersReplace = undefined;
144+
}
145+
// Temporarily expose input value. Use with caution.
146+
public get triggersReplaceInput() {
147+
return this._triggersReplace;
148+
}
149+
150+
// =========
151+
// SYNTHESIS
152+
// =========
153+
154+
protected synthesizeAttributes(): { [name: string]: any } {
155+
return {
156+
input: cdktf.hashMapper(cdktf.anyToTerraform)(this._input),
157+
triggers_replace: cdktf.hashMapper(cdktf.anyToTerraform)(
158+
this._triggersReplace
159+
),
160+
};
161+
}
162+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) HashiCorp, Inc
2+
// SPDX-License-Identifier: MPL-2.0
3+
import { Testing, TerraformStack } from "../lib";
4+
import { ref } from "../lib/tfExpression";
5+
import { DataResource } from "../lib/terraform-data-resource";
6+
7+
test("built-in Terraform data resource", () => {
8+
const app = Testing.app();
9+
const stack = new TerraformStack(app, "test");
10+
11+
new DataResource(stack, "test-data", {
12+
input: ref("var.input"),
13+
triggersReplace: [ref("var.triggersReplace1"), ref("var.triggersReplace2")],
14+
});
15+
16+
// Note: the triggers_replace attribute is defined as dynamic in the schema,
17+
// which is treated as an object by the CDKTF provider generation and therefore
18+
// renders the array as a map instead.
19+
expect(Testing.synth(stack)).toMatchInlineSnapshot(`
20+
"{
21+
"resource": {
22+
"terraform_data": {
23+
"test-data": {
24+
"input": "\${var.input}",
25+
"triggers_replace": {
26+
"0": "\${var.triggersReplace1}",
27+
"1": "\${var.triggersReplace2}"
28+
}
29+
}
30+
}
31+
}
32+
}"
33+
`);
34+
});

0 commit comments

Comments
 (0)