diff --git a/packages/cdktf/lib/backends/remote-backend.ts b/packages/cdktf/lib/backends/remote-backend.ts index df595775a8..6900ae88cb 100644 --- a/packages/cdktf/lib/backends/remote-backend.ts +++ b/packages/cdktf/lib/backends/remote-backend.ts @@ -19,11 +19,22 @@ export class RemoteBackend extends TerraformBackend { } protected synthesizeAttributes(): { [name: string]: any } { - return keysToSnakeCase({ ...this.props }); + return { + ...keysToSnakeCase({ ...this.props }), + workspaces: this.props.workspaces.toTerraform(), + }; } protected synthesizeHclAttributes(): { [name: string]: any } { - return keysToSnakeCase({ ...this.props }); + return { + ...keysToSnakeCase(this.props), + workspaces: { + value: this.props.workspaces.toHclTerraform(), + isBlock: true, + type: "map", + storageClassType: "stringmap", + }, + }; } public toMetadata() { @@ -53,26 +64,79 @@ export class DataTerraformRemoteState extends TerraformRemoteState { } } +export interface DataRemoteBackendConfig { + readonly hostname?: string; + readonly organization: string; + readonly token?: string; + workspaces: IRemoteWorkspace; +} + export interface RemoteBackendConfig { readonly hostname?: string; readonly organization: string; readonly token?: string; - readonly workspaces: IRemoteWorkspace; + /** + * A nested block that specifies which remote Terraform workspaces to use for the current configuration. + */ + readonly workspaces: NamedRemoteWorkspace | PrefixedRemoteWorkspaces; } // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface IRemoteWorkspace {} +/** + * A cloud workspace can either be a single named workspace, or a list of tagged workspaces. + */ +export abstract class RemoteWorkspace { + public abstract toTerraform(): any; +} + // eslint-disable-next-line jsdoc/require-jsdoc -export class NamedRemoteWorkspace implements IRemoteWorkspace { - public constructor(public name: string) {} +export class NamedRemoteWorkspace extends RemoteWorkspace { + public constructor(public name: string) { + super(); + } + + public toHclTerraform(): any { + return { + name: { + value: this.name, + type: "simple", + storageClassType: "string", + }, + }; + } + + public toTerraform(): any { + return { + name: this.name, + }; + } } // eslint-disable-next-line jsdoc/require-jsdoc -export class PrefixedRemoteWorkspaces implements IRemoteWorkspace { - public constructor(public prefix: string) {} +export class PrefixedRemoteWorkspaces extends RemoteWorkspace { + public constructor(public prefix: string) { + super(); + } + + public toHclTerraform(): any { + return { + prefix: { + value: this.prefix, + type: "simple", + storageClassType: "string", + }, + }; + } + + public toTerraform(): any { + return { + prefix: this.prefix, + }; + } } export interface DataTerraformRemoteStateRemoteConfig extends DataTerraformRemoteStateConfig, - RemoteBackendConfig {} + DataRemoteBackendConfig {} diff --git a/packages/cdktf/test/json-to-hcl.test.ts b/packages/cdktf/test/json-to-hcl.test.ts index 67c369b600..4bd41599d5 100644 --- a/packages/cdktf/test/json-to-hcl.test.ts +++ b/packages/cdktf/test/json-to-hcl.test.ts @@ -663,7 +663,7 @@ describe("backends", () => { `); }); - test("remote", async () => { + test("remote as datasource", async () => { const app = Testing.app(); const stack = new TerraformStack(app, "test"); @@ -676,6 +676,7 @@ describe("backends", () => { }, }); + // Data for terraform_remote_state is different than remote backend configuration expect(Testing.synthHcl(stack)).toMatchInlineSnapshot(` " data "terraform_remote_state" "remote" { @@ -691,6 +692,59 @@ describe("backends", () => { `); }); + test("remote as backend", async () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + + new b.RemoteBackend(stack, { + organization: "test-organization", + workspaces: new b.NamedRemoteWorkspace("test-stack"), + hostname: "test.artifactory.local", + }); + + expect(Testing.synthHcl(stack)).toMatchInlineSnapshot(` + "terraform { + required_providers { + + } + backend "remote" { + organization = "test-organization" + workspaces { + name = "test-stack" + } + hostname = "test.artifactory.local" + } + + + }" + `); + }); + + test("cloud as backend", async () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + + new b.CloudBackend(stack, { + organization: "test-organization", + workspaces: new b.NamedCloudWorkspace("test-stack"), + }); + + expect(Testing.synthHcl(stack)).toMatchInlineSnapshot(` + "terraform { + required_providers { + + } + cloud { + organization = "test-organization" + workspaces { + name = "test-stack" + } + } + + }" + `); + }); + test("azurerm", async () => { const app = Testing.app(); const stack = new TerraformStack(app, "test"); @@ -1264,3 +1318,27 @@ test("import block", () => { }" `); }); + +test("lifecycle ignore", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + + new TestResource(stack, "test", { + name: "test", + lifecycle: { + ignoreChanges: ["tags"], + }, + }); + + expect(Testing.synthHcl(stack)).toMatchInlineSnapshot(` + " + resource "test_resource" "test" { + name = "test" + lifecycle { + ignore_changes = [ + "tags", + ] + } + }" + `); +});