Skip to content

New ephemeral resource cloudint_config - #407

Open
chpag wants to merge 7 commits into
hashicorp:mainfrom
chpag:cloudinit_config_ephemeral
Open

New ephemeral resource cloudint_config#407
chpag wants to merge 7 commits into
hashicorp:mainfrom
chpag:cloudinit_config_ephemeral

Conversation

@chpag

@chpag chpag commented May 6, 2026

Copy link
Copy Markdown

Related Issue

Closes #396

Description

This PR implements an ephemeral resource version of cloudinit_config that enables secure handling of sensitive data (such as secrets from Vault) in cloud-init configurations without storing them in Terraform state.

When released, it would required to add a Write-Only attribute for user_data on different providers (aws, azure, gcp, vsphere, ...) to handle ephemeral cloudinit_config resource

Rollback Plan

  • If a change needs to be reverted, we will roll out an update to the code within 7 days.

Changes to Security Controls

No Change

Output from Acceptance Testing

% make testacc
TF_ACC=1 go test -v -cover -timeout 120m ./...
        github.com/hashicorp/terraform-provider-cloudinit               coverage: 0.0% of statements
=== RUN   TestString
--- PASS: TestString (0.00s)
=== RUN   TestStrings
--- PASS: TestStrings (0.00s)
=== RUN   TestString_positiveIndex
--- PASS: TestString_positiveIndex (0.00s)
PASS
coverage: 70.0% of statements
ok      github.com/hashicorp/terraform-provider-cloudinit/internal/hashcode     (cached)        coverage: 70.0% of statements
=== RUN   TestConfigDataSourceRender
=== RUN   TestConfigDataSourceRender/no_gzip_or_b64_-_basic_content
=== RUN   TestConfigDataSourceRender/no_gzip_or_b64_-_basic_content_-_default_to_text_plain
=== RUN   TestConfigDataSourceRender/no_gzip_or_b64_-_content_with_filename
=== RUN   TestConfigDataSourceRender/no_gzip_or_b64_-_two_parts,_basic_content
=== RUN   TestConfigDataSourceRender/no_gzip_or_b64_-_with_boundary_separator
=== RUN   TestConfigDataSourceRender/no_gzip_or_b64_-_two_parts_-_all_fields
=== RUN   TestConfigDataSourceRender/no_gzip_-_b64_encoded_-_basic_content
=== RUN   TestConfigDataSourceRender/gzip_compression_-_basic_content
=== RUN   TestConfigDataSourceRender/empty_content_field_in_part_block
=== RUN   TestConfigDataSourceRender/empty_content_field_in_one_part_block,_multiple_part_blocks
--- PASS: TestConfigDataSourceRender (4.85s)
    --- PASS: TestConfigDataSourceRender/no_gzip_or_b64_-_basic_content (0.62s)
    --- PASS: TestConfigDataSourceRender/no_gzip_or_b64_-_basic_content_-_default_to_text_plain (0.46s)
    --- PASS: TestConfigDataSourceRender/no_gzip_or_b64_-_content_with_filename (0.46s)
    --- PASS: TestConfigDataSourceRender/no_gzip_or_b64_-_two_parts,_basic_content (0.47s)
    --- PASS: TestConfigDataSourceRender/no_gzip_or_b64_-_with_boundary_separator (0.46s)
    --- PASS: TestConfigDataSourceRender/no_gzip_or_b64_-_two_parts_-_all_fields (0.48s)
    --- PASS: TestConfigDataSourceRender/no_gzip_-_b64_encoded_-_basic_content (0.46s)
    --- PASS: TestConfigDataSourceRender/gzip_compression_-_basic_content (0.49s)
    --- PASS: TestConfigDataSourceRender/empty_content_field_in_part_block (0.47s)
    --- PASS: TestConfigDataSourceRender/empty_content_field_in_one_part_block,_multiple_part_blocks (0.47s)
=== RUN   TestConfigDataSourceRender_handleErrors
=== RUN   TestConfigDataSourceRender_handleErrors/base64_can't_be_false_when_gzip_is_true
=== RUN   TestConfigDataSourceRender_handleErrors/at_least_one_part_is_required
--- PASS: TestConfigDataSourceRender_handleErrors (0.33s)
    --- PASS: TestConfigDataSourceRender_handleErrors/base64_can't_be_false_when_gzip_is_true (0.16s)
    --- PASS: TestConfigDataSourceRender_handleErrors/at_least_one_part_is_required (0.16s)
=== RUN   TestConfigDataSource_UpgradeFromVersion2_2_0
=== RUN   TestConfigDataSource_UpgradeFromVersion2_2_0/multiple_parts_in_cloudinit_config
--- PASS: TestConfigDataSource_UpgradeFromVersion2_2_0 (1.86s)
    --- PASS: TestConfigDataSource_UpgradeFromVersion2_2_0/multiple_parts_in_cloudinit_config (1.86s)
=== RUN   TestConfigDataSource_HandleUnknown
=== RUN   TestConfigDataSource_HandleUnknown/issue_102_-_handle_unknown_in_validate_caused_by_variable
--- PASS: TestConfigDataSource_HandleUnknown (0.45s)
    --- PASS: TestConfigDataSource_HandleUnknown/issue_102_-_handle_unknown_in_validate_caused_by_variable (0.45s)
=== RUN   TestConfigEphemeralResourceBasic
--- PASS: TestConfigEphemeralResourceBasic (0.37s)
=== RUN   TestConfigEphemeralResourceRender_handleErrors
=== RUN   TestConfigEphemeralResourceRender_handleErrors/base64_can't_be_false_when_gzip_is_true
=== RUN   TestConfigEphemeralResourceRender_handleErrors/at_least_one_part_is_required
--- PASS: TestConfigEphemeralResourceRender_handleErrors (0.32s)
    --- PASS: TestConfigEphemeralResourceRender_handleErrors/base64_can't_be_false_when_gzip_is_true (0.16s)
    --- PASS: TestConfigEphemeralResourceRender_handleErrors/at_least_one_part_is_required (0.16s)
=== RUN   TestConfigResourceRender
=== RUN   TestConfigResourceRender/no_gzip_or_b64_-_basic_content
=== RUN   TestConfigResourceRender/no_gzip_or_b64_-_basic_content_-_default_to_text_plain
=== RUN   TestConfigResourceRender/no_gzip_or_b64_-_content_with_filename
=== RUN   TestConfigResourceRender/no_gzip_or_b64_-_two_parts,_basic_content
=== RUN   TestConfigResourceRender/no_gzip_or_b64_-_with_boundary_separator
=== RUN   TestConfigResourceRender/no_gzip_or_b64_-_two_parts_-_all_fields
=== RUN   TestConfigResourceRender/no_gzip_-_b64_encoded_-_basic_content
=== RUN   TestConfigResourceRender/gzip_compression_-_basic_content
=== RUN   TestConfigResourceRender/empty_content_field_in_part_block
=== RUN   TestConfigResourceRender/empty_content_field_in_one_part_block,_multiple_part_blocks
--- PASS: TestConfigResourceRender (6.16s)
    --- PASS: TestConfigResourceRender/no_gzip_or_b64_-_basic_content (0.49s)
    --- PASS: TestConfigResourceRender/no_gzip_or_b64_-_basic_content_-_default_to_text_plain (0.50s)
    --- PASS: TestConfigResourceRender/no_gzip_or_b64_-_content_with_filename (0.49s)
    --- PASS: TestConfigResourceRender/no_gzip_or_b64_-_two_parts,_basic_content (0.50s)
    --- PASS: TestConfigResourceRender/no_gzip_or_b64_-_with_boundary_separator (0.50s)
    --- PASS: TestConfigResourceRender/no_gzip_or_b64_-_two_parts_-_all_fields (0.50s)
    --- PASS: TestConfigResourceRender/no_gzip_-_b64_encoded_-_basic_content (0.49s)
    --- PASS: TestConfigResourceRender/gzip_compression_-_basic_content (0.49s)
    --- PASS: TestConfigResourceRender/empty_content_field_in_part_block (0.49s)
    --- PASS: TestConfigResourceRender/empty_content_field_in_one_part_block,_multiple_part_blocks (1.71s)
=== RUN   TestConfigResourceRender_handleErrors
=== RUN   TestConfigResourceRender_handleErrors/base64_can't_be_false_when_gzip_is_true
=== RUN   TestConfigResourceRender_handleErrors/at_least_one_part_is_required
--- PASS: TestConfigResourceRender_handleErrors (0.32s)
    --- PASS: TestConfigResourceRender_handleErrors/base64_can't_be_false_when_gzip_is_true (0.16s)
    --- PASS: TestConfigResourceRender_handleErrors/at_least_one_part_is_required (0.16s)
=== RUN   TestConfigResource_UpgradeFromVersion2_2_0
=== RUN   TestConfigResource_UpgradeFromVersion2_2_0/multiple_parts_in_cloudinit_config
--- PASS: TestConfigResource_UpgradeFromVersion2_2_0 (2.09s)
    --- PASS: TestConfigResource_UpgradeFromVersion2_2_0/multiple_parts_in_cloudinit_config (2.09s)
=== RUN   TestConfigResource_HandleUnknown
=== RUN   TestConfigResource_HandleUnknown/issue_102_-_handle_unknown_in_validate_caused_by_variable
--- PASS: TestConfigResource_HandleUnknown (0.54s)
    --- PASS: TestConfigResource_HandleUnknown/issue_102_-_handle_unknown_in_validate_caused_by_variable (0.54s)
PASS
coverage: 85.0% of statements
ok      github.com/hashicorp/terraform-provider-cloudinit/internal/provider     (cached)        coverage: 85.0% of statements

chpag and others added 6 commits April 24, 2026 14:44
….yaml

	new file:   examples/ephemeral-resources/cloudinit_config/ephemeral-resource.tf
	new file:   examples/ephemeral-resources/cloudinit_config/hello-script.sh
	new file:   internal/provider/ephemeral_resource_cloudinit_config.go
	new file:   internal/provider/ephemeral_resource_cloudinit_config_test.go
	modified:   internal/provider/provider.go
	new file:   templates/ephemeral-resources/config.md.tmpl
	modified:   templates/ephemeral-resources/config.md.tmpl
	modified:   templates/ephemeral-resources/config.md.tmpl
	modified:   internal/provider/ephemeral_resource_cloudinit_config_test.go
@chpag
chpag requested a review from a team as a code owner May 6, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add cloudinit_config ephemeral resource

1 participant