Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resource: aws_workspaces_workspace #11608

Merged
merged 3 commits into from
May 12, 2020

Conversation

Tensho
Copy link
Contributor

@Tensho Tensho commented Jan 15, 2020

Community Note

  • Please vote on this pull request by adding a 👍 reaction to the original pull request comment to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for pull request followers and do not help prioritize the request

Release note for CHANGELOG:

New Data Source: aws_workspaces_workspace (#11608)

Example

data "aws_workspaces_directory" "main" {
  directory_id = "d-ten5h0y19"
}

data "aws_workspaces_bundle" "value_windows" {
  bundle_id = "b-ten5h0y19"
}

resource "aws_workspaces_workspace" "jhon.doe" {
  directory_id = "${data.aws_workspaces_directory.main.id}"
  bundle_id = "${data.aws_workspaces_bundle.value_windows.id}"
  user_name = "jhon.doe"

  root_volume_encryption_enabled = true
  user_volume_encryption_enabled = true
  volume_encryption_key = "aws/workspaces"

  workspace_properties {
    compute_type_name = "VALUE" 
    root_volume_size_gib = 80
    running_mode = "AUTO_STOP"
    running_mode_auto_stop_timeout_in_minutes = 120
    user_volume_size_gib = 10
  }
  
  tags = {
    Department = "IT"
  }
}

Acceptance Tests

$ make testacc TEST=./aws TESTARGS='-run=TestAccAwsWorkspacesWorkspace'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccAwsWorkspacesWorkspace -timeout 120m
=== RUN   TestAccAwsWorkspacesWorkspace_basic
--- PASS: TestAccAwsWorkspacesWorkspace_basic (1483.87s)
=== RUN   TestAccAwsWorkspacesWorkspace_Tags
--- PASS: TestAccAwsWorkspacesWorkspace_Tags (1546.16s)
=== RUN   TestAccAwsWorkspacesWorkspace_WorkspaceProperties
--- PASS: TestAccAwsWorkspacesWorkspace_WorkspaceProperties (1667.00s)
=== RUN   TestAccAwsWorkspacesWorkspace_validateRootVolumeSize
--- PASS: TestAccAwsWorkspacesWorkspace_validateRootVolumeSize (2.48s)
=== RUN   TestAccAwsWorkspacesWorkspace_validateUserVolumeSize
--- PASS: TestAccAwsWorkspacesWorkspace_validateUserVolumeSize (3.28s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	4704.253s

Considerations

There is a warning which I'm not sure how I should address:

    The following problems may be the cause of any confusing errors from downstream operations:
      - .volume_encryption_key: was null, but now cty.StringVal("")

What is the general strategy for absent attributes?

References

@Tensho Tensho requested a review from a team January 15, 2020 13:39
@ghost ghost added needs-triage Waiting for first response or review from a maintainer. size/XXL Managed by automation to categorize the size of a PR. documentation Introduces or discusses updates to documentation. provider Pertains to the provider itself, rather than any interaction with AWS. service/workspaces Issues and PRs that pertain to the workspaces service. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure. labels Jan 15, 2020
website/aws.erb Outdated Show resolved Hide resolved
aws/resource_aws_workspace.go Outdated Show resolved Hide resolved
@marcosdiez
Copy link
Contributor

Hey @Tensho, your PR now has a conflict (and fixing it is trivial). Could you please do so, to increase the chances of it getting merged? Thanks!

@ghost ghost added size/XL Managed by automation to categorize the size of a PR. and removed size/XXL Managed by automation to categorize the size of a PR. labels Mar 13, 2020
@Tensho
Copy link
Contributor Author

Tensho commented Mar 13, 2020

Rebased, but still have to sort out defaults for attributes of the Set type. Asked more clarification in #142. Will resolve other issues after that.

Copy link
Contributor

@gdavison gdavison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, @Tensho. I've gone through and added a number of changes that should be made for this.

aws/provider.go Outdated Show resolved Hide resolved
aws/resource_aws_workspace.go Outdated Show resolved Hide resolved
})
}

func testSweepWorkspaces(region string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The aws_workspaces_directory sweeper will probably need to add a dependency on this sweeper

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it? You can build aws_workspaces_directory without needing an aws_workspaces_workspace. Maybe I'm not understanding sweepers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess @gdavison means opposite direction – aws_workspaces_workspace sweeper depends on aws_workspaces_directory one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, when we add a dependency to a sweeper, it means that the other sweeper needs to be run before this one, or it will return an error.

aws/resource_aws_workspace.go Outdated Show resolved Hide resolved
aws/resource_aws_workspace.go Outdated Show resolved Hide resolved
aws/resource_aws_workspace.go Outdated Show resolved Hide resolved
aws/resource_aws_workspace.go Outdated Show resolved Hide resolved
Type: schema.TypeInt,
Optional: true,
Default: 80,
ValidateFunc: validation.IntInSlice([]int{80, 175}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the documentation at https://docs.aws.amazon.com/workspaces/latest/adminguide/modify-workspaces.html, it looks like the valid values for root_volume_size_gib are 80 or 175 to 2000.

  • If root_volume_size_gib is 80, then user_volume_size_gib is one of 10, 50, or 100.
  • If root_volume_size_gib is 175 to 2000, then user_volume_size_gib is 100 to 2000
    Validation should be updated to allow the higher values.
    Also, root and user volumes cannot change size at the same time. The code should deal with that case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't' remember exactly why, but I failed to accomplish this. Will make another attempt and share the feedback. Thanks.

Copy link
Contributor Author

@Tensho Tensho Mar 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gdavison Ah, I remembered, how can I refer to attribute A in the validation func of attribute B? Or should I handle this in resource Update func?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gdavison The question about validation func for dependent attributes is still actual for me. Please could you answer the questions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the ValidateFuncs in the resource schema, you can use validation.Any() to chain together validation functions.

For root_volume_size_gib, this could be

ValidateFunc: validation.Any(
    validation.IntInSlice([]int{80}),
    validation.IntBetween(175, 2000),
)

For final validation that the two fields are compatible, we'll have to let the AWS API handle it.

Copy link
Contributor Author

@Tensho Tensho May 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I've added one acceptance for user volume size validation, but I doubt this is the right way to test all possible cases. Please could you refer me to the good validation unit test example?

aws/resource_aws_workspace_test.go Outdated Show resolved Hide resolved
aws/resource_aws_workspace_test.go Outdated Show resolved Hide resolved
@Tensho
Copy link
Contributor Author

Tensho commented Mar 15, 2020

@gdavison I'll do the changes according to your review this week. Thank you very much 🙇

@ghost ghost added size/XXL Managed by automation to categorize the size of a PR. and removed size/XL Managed by automation to categorize the size of a PR. labels Mar 16, 2020
@Tensho Tensho changed the title New Resource: aws_workspace New Resource: aws_workspaces_workspace Mar 17, 2020
@Tensho
Copy link
Contributor Author

Tensho commented Mar 19, 2020

@gdavison @bflad @ewbankkit I iterate on Update function tests and it takes ages to wait for workspace launch. Could you suggest the way to import already prepared workspace to the state and test only the update phase in the subsequent test case without any destroy after all? I'd consider such a workaround only for debug purposes and remove it in favor of full configuration at the end. I'd expect something like this should work:

Steps: []resource.TestStep{
	{
		Destroy: false,
		ResourceName: "aws_workspaces_workspace.test",
		ImportState:   true,
		ImportStateId: "ws-h16p65ykp", // already prepeared workspace
	},
	{
		Destroy: false,
		Config: testAccWorkspacesWorkspaceConfig(booster),
		Check: resource.ComposeAggregateTestCheckFunc(
                   resource.TestCheckResourceAttr(resourceName, "directory_id", "d-99673d2890"),
                )
...
func testAccWorkspacesWorkspaceConfg() string {
	return fmt.Sprintf(`
resource "aws_workspaces_workspace" "test" {
  bundle_id = "wsb-98rvbl24y" # prepeared bundle
  directory_id = "d-99673d2890" # prepeared directory
  user_name = "andrii.babichev" # prepared user
}
`)
}

However, test framework still creates the resource on the second test case.

What is generally the best way to work on long-launching resources?

BTW, I switched workspace_properties type from TypeSet to TypeList and everything is OK, except the fact I still don't understand the proper case for the Set type 🙂

@Tensho
Copy link
Contributor Author

Tensho commented Mar 26, 2020

@gdavison Good news, I'm on the finish line with this resource, hope to resolve some workspace properties modification snags with AWS Support and then tidy up tests to be self-sufficient. I guess I learned about Terraform providers here much more than from all other resources all together 🙂 Appreciate if you answer the questions left in the discussion 🙇

@gdavison gdavison removed the needs-triage Waiting for first response or review from a maintainer. label May 1, 2020
@Tensho
Copy link
Contributor Author

Tensho commented May 4, 2020

@gdavison @DrFaust92 Thank you for the feedback 🙇 I've made required changes, please check out the current state.

@DrFaust92
Copy link
Collaborator

@Tensho, tagging logic fix is handled by #13089. can you the currently generated functions (this will cause failure but it will be fixed across all workspaces resources with the aforementioned PR)
as seen in https://github.com/terraform-providers/terraform-provider-aws/blob/master/aws/resource_aws_workspaces_directory.go

@DrFaust92
Copy link
Collaborator

alternatively #13089 needs to be merged before this

@Tensho
Copy link
Contributor Author

Tensho commented May 4, 2020

@DrFaust92 I'm pretty fine with prior #13089 merge, just whatever makes this resource public appearance sooner.

@Tensho
Copy link
Contributor Author

Tensho commented May 5, 2020

@bflad @gdavison Please could you take a look? 🙇

Copy link
Contributor

@gdavison gdavison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's looking great! A couple changes to make, and I'm going to merge #13089 first. This might create some merge conflicts

DirectoryId: aws.String(id),
}
err := conn.DescribeWorkspacesPages(input, func(resp *workspaces.DescribeWorkspacesOutput, _ bool) bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The delete function for a resource should only handle deleting itself. Terraform will use the resource dependency graph to handle the order. However, the sweeper for aws_workspaces_directory should add aws_workspaces_workspace to its Dependencies array.

Copy link
Contributor Author

@Tensho Tensho May 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shared knowledge and examples about sweepers and now I understand the concept better. Thank you 🙇 Fixed workspaces_directory sweeper depend on worksapces_workspace.

@@ -33,6 +33,32 @@ resource "aws_workspaces_directory" "main" {
subnet_ids = ["${aws_subnet.private-a.id}", "${aws_subnet.private-b.id}"]
}

data "aws_workspaces_bundle" "value_windows" {
bundle_id = "b-ten5h0y19"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Examples should be runnable with minimal configuration by users. The bundle ID should be a variable, rather than hardcoded.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed to the public "Value with Windows 10 (English)" bundle

Comment on lines 315 to 328
# resource "aws_iam_role" "workspaces-default" {
# name = "workspaces_DefaultRole"
# assume_role_policy = data.aws_iam_policy_document.workspaces.json
# }
#
# resource "aws_iam_role_policy_attachment" "workspaces-default-service-access" {
# role = aws_iam_role.workspaces-default.name
# policy_arn = "arn:aws:iam::aws:policy/AmazonWorkSpacesServiceAccess"
# }
#
# resource "aws_iam_role_policy_attachment" "workspaces-default-self-service-access" {
# role = aws_iam_role.workspaces-default.name
# policy_arn = "arn:aws:iam::aws:policy/AmazonWorkSpacesSelfServiceAccess"
# }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these aren't needed, we can just remove them

Copy link
Contributor Author

@Tensho Tensho May 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that's leaked from git stash. I have to comment out this section every time I run acctests, because the target account already have this role in place. I've compared the current workspaces default role inline policies and found some changed since I started this PR:

  • AmazonWorkSpacesServiceAccess –> SkyLightServiceAccess
  • AmazonWorkSpacesSelfServiceAccess –> SkyLightSelfServiceAccess

However manged policies (starts with AmazonWorkSpace) are still in place and identical to the inline analogs.

Fixed.

Copy link
Contributor Author

@Tensho Tensho May 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are curious as me what does SkyLight mean – it's a AWS workspace agent written in Go 😸

@Tensho
Copy link
Contributor Author

Tensho commented May 6, 2020

@gdavison I've rebased my branch to the lastest upstream master. Don't hesitate to ask for any other changes 🙇

@gdavison
Copy link
Contributor

gdavison commented May 8, 2020

Hi @Tensho, it's looking great. I'm getting some errors in our acceptance test accounts. Something about subnets not being found.

I'll investigate those tomorrow, and we can get this merged!

Copy link
Contributor

@gdavison gdavison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found the issue. It's related to the data source data "aws_subnet" "default" {...}. I'm going to make the fix needed and merge it in once it's done.
I should be able to reuse the set up configuration from https://github.com/terraform-providers/terraform-provider-aws/blob/6cf84739011aa60bb8aa0c501b08dfc280716af7/aws/resource_aws_workspaces_directory_test.go#L370
Thanks for contributing! 🚀

@gdavison gdavison added this to the v2.62.0 milestone May 8, 2020
@Tensho
Copy link
Contributor Author

Tensho commented May 8, 2020

@gdavison Please could you explain the issue with the default subnet? I intentionally switched to default VPC and subnets, because the test environment cleanup (destroy) constantly failed on VPC resources decommission.

@gdavison
Copy link
Contributor

When the code was using the subnets data source, it was failing with a subnet not found error. Possibly because our account doesn't have a default subnet it all AZs in us-west-2.

It took me a while, but I finally tracked down the error when using a new VPC for the test. If the role workspaces_DefaultRole doesn't have the policy arn:aws:iam::aws:policy/AmazonWorkSpacesServiceAccess attached, it can't delete the ENI created for the Workspace. So I added

  depends_on = [
    aws_iam_role_policy_attachment.workspaces-default-service-access,
  ]

@gdavison gdavison merged commit 264edcc into hashicorp:master May 12, 2020
gdavison added a commit that referenced this pull request May 12, 2020
@Tensho Tensho deleted the r-workspaces-workspace branch May 12, 2020 07:28
@Tensho
Copy link
Contributor Author

Tensho commented May 12, 2020

@gdavison Thank you very much for your work and I'm so happy we can finally declare workspaces with Terraform 🙇 Have you found the bug with TF_LOG=DEBUG?

Let me check one moment with you. If I understood you right, workspaces directory and default role have a race due to the parallel destruction. The default role destruction is always faster workspaces directory one, that's why we need explicitly declare dependency. However, I'd expect workspace directory should depend onworkspaces_DefaultRole role instead of workspace depends on the required policy.

resource "aws_iam_role" "workspaces-default" {
  name               = "workspaces_DefaultRole"
  assume_role_policy = data.aws_iam_policy_document.workspaces.json
}

resource "aws_iam_role_policy_attachment" "workspaces-default-service-access" {
  role       = aws_iam_role.workspaces-default.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonWorkSpacesServiceAccess"
}

GOOD
resource "aws_workspaces_workspace" "test" {
  ...
  depends_on = [
    aws_iam_role_policy_attachment.workspaces-default-service-access,
  ]
}

BETTER
resource "aws_workspaces_directory" "test" {
  ...
  depends_on = [
    aws_iam_role.workspaces-default,
  ]
}

What's your take on this?

BTW, I didn't know about composeConfig() func 👍

@ghost
Copy link

ghost commented May 15, 2020

This has been released in version 2.62.0 of the Terraform AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template for triage. Thanks!

@ghost
Copy link

ghost commented Jun 11, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@ghost ghost locked and limited conversation to collaborators Jun 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation Introduces or discusses updates to documentation. provider Pertains to the provider itself, rather than any interaction with AWS. service/workspaces Issues and PRs that pertain to the workspaces service. size/XXL Managed by automation to categorize the size of a PR. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants