Open damienpontifex opened 3 years ago
I was chatting with @jsteinich about this yesterday... I was going to open an issue this morning, but you beat me to it :)
Not sure if you're seeing the exact same thing as me, but there are situations where the cdktf-cli hangs when Terraform prompts about workspaces. Here's an example:
$ CDKTF_LOG_LEVEL=DEBUG TF_WORKSPACE=qa cdktf deploy
[2020-09-17T15:40:32.112] [DEBUG] default - Terraform v0.12.29
[2020-09-17T15:40:32.578] [DEBUG] default - + provider.aws v2.70.0
[2020-09-17T15:40:32.579] [DEBUG] default -
Your version of Terraform is out of date! The latest version
is 0.13.2. You can update by downloading from https://www.terraform.io/downloads.html
⠼ synthesizing ...
[2020-09-17T15:40:34.689] [DEBUG] default - REGION is not set. Defaulting to "us-east-1".
⠹ initializing my-stack-qa-us-east-1...
[2020-09-17T15:40:35.369] [DEBUG] default - 2020/09/17 15:40:35 [DEBUG] Using modified User-Agent: Terraform/0.12.29 cdktf/0.0.17 (+https://github.com/hashicorp/terraform-cdk)
2020/09/17 15:40:35 [DEBUG] Using modified User-Agent: Terraform/0.12.29 cdktf/0.0.17 (+https://github.com/hashicorp/te⠸ initializing my-stack-qa-us-east-1...
[2020-09-17T15:40:35.389] [DEBUG] default -
[2020-09-17T15:40:35.389] [DEBUG] default - Initializing the backend...
⠸ initializing my-stack-qa-us-east-1...
[2020-09-17T15:40:37.103] [DEBUG] default -
[2020-09-17T15:40:37.103] [DEBUG] default - The currently selected workspace (qa) does not exist.
This is expected behavior when the selected workspace did not have an
[2020-09-17T15:40:37.103] [DEBUG] default - existing non-empty state. Please enter a number to select a workspace:
1. default
[2020-09-17T15:40:37.103] [DEBUG] default -
⠴ initializing my-stack-qa-us-east-1...
# This hangs...
Sorry to conflate these, but I think this is generally related to another problem I've seen initializing state with cdktf deploy
- if there are changes to the state, Terraform prompts and cdktf-cli hangs on this too:
[2020-09-17T15:39:22.236] [DEBUG] default - Do you want to copy existing state to the new backend?
[2020-09-17T15:39:22.236] [DEBUG] default - Pre-existing state was found while migrating the previous "s3" backend to the
[2020-09-17T15:39:22.236] [DEBUG] default - newly configured "s3" backend. No existing state was found in the newly
[2020-09-17T15:39:22.236] [DEBUG] default - configured "s3" backend. Do you want to copy this state to the new "s3"
[2020-09-17T15:39:22.236] [DEBUG] default - backend? Enter "yes" to copy and "no" to start with an empty state.
# This hangs
@cmclaughlin
Sorry to conflate these, but I think this is generally related to another problem I've seen initializing state with
cdktf deploy
- if there are changes to the state, Terraform prompts and cdktf-cli hangs on this too:
Hm, I thought -input=false
should have fixed these kind of issues (see here https://github.com/hashicorp/terraform-cdk/pull/343)
Which version are you running?
@damienpontifex
Searching around and I couldn't find an equivalent for Current Workspace Interpolation in terraform-cdk. Currently we use this in terraform for environment suffixes and would be nice to transfer that capability across to our usage with cdktf
The interpolation itself should just work:
new Instance(this, 'aws instance', {
name: "web - ${terraform.workspace}"
})
Could you elaborate on the use-case you're trying to solve?
Debug output shows I was using:
[DEBUG] Using modified User-Agent: Terraform/0.12.29 cdktf/0.0.17
Debug output shows I was using:
[DEBUG] Using modified User-Agent: Terraform/0.12.29 cdktf/0.0.17
Hm, interesting. Well, that's something to investigate then, but it's probably a separate issue?
@skorfmann I understand the interpolation - maybe it's just that I couldn't find the terraform
variable/global as appropriate to access this property as ${terraform.workspace}
.
My workaround was that I was setting up the RemoteBackend
as below and if custom workspace needing run it as WORKSPACE=ponti-dev cdktf deploy
const workspaceName = process.env.WORKSPACE || 'dev'
new Instance(this, 'aws instance', {
name: "web - ${workspaceName}"
})
new RemoteBackend(stack, {
organization: 'pontifex',
workspaces: {
name: workspaceName
},
});
Then I can reuse the workspaceName
local. This works fine for our use cases. Probably I was looking to how some of our existing code would translate.
Just seeing if this was the current recommended? Or similar to how we would do terraform workspace select ponti-dev && terraform apply
is there an equivalent with cdktf
@damienpontifex TF_WORKSPACE
is supported by Terraform, but as @cmclaughlin noted, there are currently some issues with it.
@damienpontifex what you're looking for is 1st class support Terraform workspaces in cdktf
?
Something like that @skorfmann.
We use workspace naming to differentiate developer environments from UAT and prod etc so use the naming for unique suffixes across resources. So we could adapt the terraform.workspace
variable that's available in HCL terraform to something different here, just looking to see what was the recommended approach in Typescript. It might be that we do something like const workspaceName = process.env.TF_WORKSPACE
if that's the recommended approach with cdktf
We are using the following approach to access workspace in the code:
const workspace = Token.asString("${terraform.workspace}");
new Instance(this, `${workspace}-app-instance`, {
name: "Application instance"
})
This would be pretty simple to add after #525 is completed.
We are using the following approach to access workspace in the code:
const workspace = Token.asString("${terraform.workspace}"); new Instance(this, `${workspace}-app-instance`, { name: "Application instance" })
Hi, on which folder are you executing the cdk synth command?, I mean in the cdktf.out folder or if you have an example about the folder structure to have this approach, I tried but the workspace that I'm getting is default
Hi, on which folder are you executing the cdk synth command?, I mean in the cdktf.out folder or if you have an example about the folder structure to have this approach, I tried but the workspace that I'm getting is default
cdktf synth
won't actually know the workspace. It will just generate access to the interpolation. cdktf diff/deploy
will be able to access it (assuming the workspace already exists), but it can be a bit tricky to setup. The simplest approach is probably using the TF_WORKSPACE
environment variable (if workspace exists from elsewhere), or running Terraform commands directly if the workspace doesn't exist. Note that when running Terraform commands directly, you'll need to navigate to the specific stack directory.
I think this is something that would be good to have better built in support for, but I'm not aware of any planned work as of yet. @javier-caylent how are you hoping to use workspaces?
We are using the following approach to access workspace in the code:
const workspace = Token.asString("${terraform.workspace}"); new Instance(this, `${workspace}-app-instance`, { name: "Application instance" })
Hi, on which folder are you executing the cdk synth command?, I mean in the cdktf.out folder or if you have an example about the folder structure to have this approach, I tried but the workspace that I'm getting is default
Hi @javier-caylent! Since CDKTF generate stack to run it with terraform it's important in which folder to run command to switch workspace, for example terraform workspace new my_workspace
. Terraform put generated stacks in cdktf.out/stacks
. For example if you have stack my_stack
you can find generated assets in cdktf.out/stacks/my_stack
, hence if you want to change workspace for my_stack
you should navigate to cdktf.out/stacks/my_stack
and switch to required workspace in this folder. After changing workspace you should see cdktf.out/stacks/my_stack/.terraform/environment
following file created.
The full flow:
cdktf synth
- generate stackcd cdktf.out/stacks/my_stack
- navigate to stack folderterraform workspace new my_workspace
- switch to required workspacecdktf deploy my_stack
Awesome, You help me a lot with this information. Thank you very much!!! @nick0lay.
Awesome, You help me a lot with this information. Thank you very much!!! @nick0lay.
Welcome!
There is one more thing which you might be aware of. Even though that you have access to workspace in cdktf
, workspaces works differently in terraform
and cdktf
in terms of state isolation.
Terrafrom
If you switch workspace to my_workspace
terraform will save state to terraform.tfstate.d/my_workspace/terraform.tfstate
it you switch workspace to my_new_workspace
hence new state will be saved to project_root/terraform.tfstate.d/my_new_workspace/terraform.tfstate
CDKTF
For this case workspaces works a bit differently. If you switch workspace you will be able to see folder project_root/cdktf.out/stacks/cdktf_example/terraform.tfstate.d/my_workspace
but terraform.tfstate
won't be there. Instead cdktf
create it in the following place project_root/terraform.cdktf_example.tfstate
where cdktf_example
is stack name.
const app = new App();
new MyStack(app, "cdktf_example");
app.synth();
Hence when you use cdktf
it's better separate states by creating different stacks rather than use workspaces. For example:
const app = new App();
new MyStack(app, "cdktf_example_stack");
new MyStack(app, "cdktf_example_test_stack");
app.synth();
But switching workspace still might be useful if you use cdktf
with terraform
modules which rely on workspace variable ${terraform.workspace}
inside it.
Hi @nick0lay
hmm, got it, I think that we can "emulate" the ${terraform.workspace}, sending the environment for each stack and get the variables values in the same way.
I'll test it and see, how works this approach and the s3 remote state (S3Backend) and where will be store the tfstate file for each stack.
from imports.my_compute_module import MyComputeModule
from variables import Variables
class MyStackConfig(object):
def __init__(self, environment: str, region: str):
self.environment = environment
self.region = region
class MyStack(TerraformStack):
def __init__(self, scope: Construct, ns: str, config: MyStackConfig):
myec2 = MyComputeModule(self,
'my-ec2',
ami = Variables.get("ami").get(config.environment),
instance_type = Variables.get("instance_type").get(config.environment),
vpc_security_group_ids = Variables.get("vpc_security_group_ids").get(config.environment),
subnet_id = Variables.get("vpc").get("public_subnets_ids").get(config.environment),
key_name = Variables.get("key_name").get(config.environment),
additional_tags = { "Name": f"python-{config.environment}" }
)
app = App();
MyStack(app, "cdktf_example_dev", {"environment": "dev", "region": "us-east-1"});
MyStack(app, "cdktf_example_stg", {"environment": "stg", "region": "us-east-1"});
app.synth();
Community Note
Description
Searching around and I couldn't find an equivalent for Current Workspace Interpolation in terraform-cdk. Currently we use this in terraform for environment suffixes and would be nice to transfer that capability across to our usage with cdktf