Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 72 additions & 8 deletions packages/cdktf/lib/backends/remote-backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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 {}
80 changes: 79 additions & 1 deletion packages/cdktf/test/json-to-hcl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ describe("backends", () => {
`);
});

test("remote", async () => {
test("remote as datasource", async () => {
const app = Testing.app();
const stack = new TerraformStack(app, "test");

Expand All @@ -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" {
Expand All @@ -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");
Expand Down Expand Up @@ -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",
]
}
}"
`);
});