├── .changes ├── 3.2.1.md ├── 3.2.2.md ├── 3.2.3.md ├── 3.2.4-alpha.2.md ├── 3.2.4-alpha1.md ├── 3.2.4.md └── unreleased │ └── .gitkeep ├── .changie.yaml ├── .copywrite.hcl ├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── Bug_Report.yml │ ├── Feature_Request.yml │ └── config.yml ├── SUPPORT.md ├── dependabot.yml ├── labeler-issue-triage.yml ├── labeler-pull-request-triage.yml ├── pull_request_template.md └── workflows │ ├── build.yml │ ├── cdktf-docs.yml │ ├── ci-changie.yml │ ├── compliance.yml │ ├── issue-comment-triage.yml │ ├── issue-opened.yml │ ├── lock.yml │ ├── pull-request.yml │ └── test.yml ├── .gitignore ├── .golangci.yml ├── .release ├── ci.hcl ├── oss-release-metadata.hcl ├── release-metadata.hcl ├── security-scan.hcl └── terraform-provider-null-artifacts.hcl ├── CHANGELOG.md ├── GNUmakefile ├── LICENSE ├── META.d └── _summary.yaml ├── README.md ├── docs ├── cdktf │ ├── python │ │ ├── data-sources │ │ │ └── data_source.md │ │ ├── guides │ │ │ └── terraform-migration.md │ │ ├── index.md │ │ └── resources │ │ │ └── resource.md │ └── typescript │ │ ├── data-sources │ │ └── data_source.md │ │ ├── guides │ │ └── terraform-migration.md │ │ ├── index.md │ │ └── resources │ │ └── resource.md ├── data-sources │ └── data_source.md ├── guides │ └── terraform-migration.md ├── index.md └── resources │ └── resource.md ├── examples ├── data-sources │ └── null_data_source │ │ └── data-source.tf └── resources │ └── null_resource │ └── resource.tf ├── go.mod ├── go.sum ├── internal ├── planmodifiers │ └── attribute.go └── provider │ ├── data_source.go │ ├── data_source_test.go │ ├── provider.go │ ├── provider_test.go │ ├── resource.go │ └── resource_test.go ├── main.go ├── templates ├── data-sources.md.tmpl ├── guides │ └── terraform-migration.md.tmpl ├── index.md.tmpl └── resources.md.tmpl ├── terraform-registry-manifest.json ├── tools ├── go.mod ├── go.sum └── tools.go └── version └── VERSION /.changes/3.2.1.md: -------------------------------------------------------------------------------- 1 | ## 3.2.1 (November 17, 2022) 2 | 3 | BUG FIXES: 4 | 5 | * provider: Fix random number generation for `id` attributes ([#160](https://github.com/hashicorp/terraform-provider-null/pull/160)) 6 | 7 | ## 3.2.0 (October 25, 2022) 8 | 9 | NOTES: 10 | 11 | * Provider: Rewritten to use the new [`terraform-plugin-framework`](https://www.terraform.io/plugin/framework) ([#150](https://github.com/hashicorp/terraform-provider-null/pull/150)) 12 | 13 | ## 3.1.1 (March 16, 2022) 14 | 15 | NOTES: 16 | 17 | * Updated [terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) to `v0.7.0`: 18 | this improves generated documentation, with attributes now correctly formatted as `code` 19 | and provided with anchors. 20 | * Functionally identical to the previous 3.1.0 release. 21 | 22 | ## 3.1.0 (February 19, 2021) 23 | 24 | Binary releases of this provider now include the darwin-arm64 platform. This version contains no further changes. 25 | 26 | ## 3.0.0 (October 08, 2020) 27 | 28 | Binary releases of this provider now include the linux-arm64 platform. 29 | 30 | BREAKING CHANGES: 31 | 32 | * Upgrade to version 2 of the Terraform Plugin SDK, which drops support for Terraform 0.11. This provider will continue to work as expected for users of Terraform 0.11, which will not download the new version. ([#47](https://github.com/terraform-providers/terraform-provider-null/issues/47)) 33 | 34 | ## 2.1.2 (April 30, 2019) 35 | 36 | * This releases includes another Terraform SDK upgrade intended to align with that being used for other providers as we prepare for the Core v0.12.0 release. It should have no significant changes in behavior for this provider. 37 | 38 | ## 2.1.1 (April 11, 2019) 39 | 40 | * This releases includes only a Terraform SDK upgrade intended to align with that being used for other providers as we prepare for the Core v0.12.0 release. It should have no significant changes in behavior for this provider. 41 | 42 | ## 2.1.0 (February 27, 2019) 43 | 44 | IMPROVEMENTS: 45 | 46 | * The previous release contains an SDK incompatible with TF 0.12. Fortunately 0.12 was not released yet so upgrading the vendored sdk makes this release compatible with 0.12. 47 | 48 | ## 2.0.0 (January 18, 2019) 49 | 50 | IMPROVEMENTS: 51 | 52 | * The provider is now compatible with Terraform v0.12, while retaining compatibility with prior versions. 53 | 54 | ## 1.0.0 (September 26, 2017) 55 | 56 | * No changes from 0.1.0; just adjusting to [the new version numbering scheme](https://www.hashicorp.com/blog/hashicorp-terraform-provider-versioning/). 57 | 58 | ## 0.1.0 (June 21, 2017) 59 | 60 | NOTES: 61 | 62 | * Same functionality as that of Terraform 0.9.8. Repacked as part of [Provider Splitout](https://www.hashicorp.com/blog/upcoming-provider-changes-in-terraform-0-10/) 63 | -------------------------------------------------------------------------------- /.changes/3.2.2.md: -------------------------------------------------------------------------------- 1 | ## 3.2.2 (November 20, 2023) 2 | 3 | NOTES: 4 | 5 | * This release introduces no functional changes. It does however include dependency updates which address upstream CVEs. ([#242](https://github.com/hashicorp/terraform-provider-null/issues/242)) 6 | 7 | -------------------------------------------------------------------------------- /.changes/3.2.3.md: -------------------------------------------------------------------------------- 1 | ## 3.2.3 (September 11, 2024) 2 | 3 | NOTES: 4 | 5 | * all: This release introduces no functional changes. It does however include dependency updates which address upstream CVEs. ([#366](https://github.com/hashicorp/terraform-provider-null/issues/366)) 6 | 7 | -------------------------------------------------------------------------------- /.changes/3.2.4-alpha.2.md: -------------------------------------------------------------------------------- 1 | ## 3.2.4-alpha.2 (March 27, 2025) 2 | 3 | NOTES: 4 | 5 | * all: This release is being used to test new build and release actions. 6 | 7 | -------------------------------------------------------------------------------- /.changes/3.2.4-alpha1.md: -------------------------------------------------------------------------------- 1 | ## 3.2.4-alpha1 (February 19, 2025) 2 | 3 | NOTES: 4 | 5 | * all: This release is being used to test new build and release actions. 6 | 7 | -------------------------------------------------------------------------------- /.changes/3.2.4.md: -------------------------------------------------------------------------------- 1 | ## 3.2.4 (April 21, 2025) 2 | 3 | NOTES: 4 | 5 | * Dependency updates ([#421](https://github.com/hashicorp/terraform-provider-null/issues/421)) 6 | 7 | -------------------------------------------------------------------------------- /.changes/unreleased/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-provider-null/7d54101339c0c4f15a92f7cc2a7f523261eed45a/.changes/unreleased/.gitkeep -------------------------------------------------------------------------------- /.changie.yaml: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - This GitHub Workflow is managed by automation 2 | # https://github.com/hashicorp/terraform-devex-repos 3 | changesDir: .changes 4 | unreleasedDir: unreleased 5 | changelogPath: CHANGELOG.md 6 | versionExt: md 7 | versionFormat: '## {{.Version}} ({{.Time.Format "January 02, 2006"}})' 8 | kindFormat: '{{.Kind}}:' 9 | changeFormat: '* {{.Body}} ([#{{.Custom.Issue}}](https://github.com/hashicorp/terraform-provider-null/issues/{{.Custom.Issue}}))' 10 | custom: 11 | - key: Issue 12 | label: Issue/PR Number 13 | type: int 14 | minInt: 1 15 | kinds: 16 | - label: BREAKING CHANGES 17 | - label: NOTES 18 | - label: FEATURES 19 | - label: ENHANCEMENTS 20 | - label: BUG FIXES 21 | newlines: 22 | afterKind: 1 23 | beforeKind: 1 24 | endOfVersion: 2 25 | -------------------------------------------------------------------------------- /.copywrite.hcl: -------------------------------------------------------------------------------- 1 | schema_version = 1 2 | 3 | project { 4 | license = "MPL-2.0" 5 | copyright_year = 2017 6 | 7 | header_ignore = [ 8 | # internal catalog metadata (prose) 9 | "META.d/**/*.yaml", 10 | 11 | # changie tooling configuration and CHANGELOG entries (prose) 12 | ".changes/unreleased/*.yaml", 13 | ".changie.yaml", 14 | 15 | # examples used within documentation (prose) 16 | "examples/**", 17 | 18 | # GitHub issue template configuration 19 | ".github/ISSUE_TEMPLATE/*.yml", 20 | 21 | # GitHub Actions workflow-specific configurations 22 | ".github/labeler-*.yml", 23 | 24 | # golangci-lint tooling configuration 25 | ".golangci.yml", 26 | 27 | # Release Engineering tooling configuration 28 | ".release/*.hcl", 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @hashicorp/terraform-devex 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | HashiCorp Community Guidelines apply to you when interacting with the community here on GitHub and contributing code. 4 | 5 | Please read the full text at https://www.hashicorp.com/community-guidelines 6 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for investing your time and energy by contributing to our project: please ensure you are familiar 4 | with the [HashiCorp Code of Conduct](https://github.com/hashicorp/.github/blob/master/CODE_OF_CONDUCT.md). 5 | 6 | This provider is a HashiCorp **utility provider**, which means any bug fix and feature 7 | has to be considered in the context of the thousands/millions of configurations in which this provider is used. 8 | This is great as your contribution can have a big positive impact, but we have to assess potential negative impact too 9 | (e.g. breaking existing configurations). _Stability over features_. 10 | 11 | To provide some safety to the wider provider ecosystem, we strictly follow 12 | [semantic versioning](https://semver.org/) and HashiCorp's own 13 | [versioning specification](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#versioning-specification). 14 | Any changes that could be considered as breaking will only be included as part of a major release. 15 | In case multiple breaking changes need to happen, we will group them in the next upcoming major release. 16 | 17 | ## Asking Questions 18 | 19 | For questions, curiosity, or if still unsure what you are dealing with, 20 | please see the HashiCorp [Terraform Providers Discuss](https://discuss.hashicorp.com/c/terraform-providers/31) 21 | forum. 22 | 23 | ## Reporting Vulnerabilities 24 | 25 | Please disclose security vulnerabilities responsibly by following the 26 | [HashiCorp Vulnerability Reporting guidelines](https://www.hashicorp.com/security#vulnerability-reporting). 27 | 28 | ## Understanding the design 29 | 30 | Before proceeding with raising issues or submitting pull requests, it will probably help to familiarise yourself with 31 | the [design principles](../DESIGN.md) of this provider. This will aid your proposals, and help understand 32 | why we took certain decisions during development. 33 | 34 | ## Raising Issues 35 | 36 | We welcome issues of all kinds including feature requests, bug reports or documentation suggestions. 37 | Below are guidelines for well-formed issues of each type. 38 | 39 | ### Bug Reports 40 | 41 | * [ ] **Test against latest release**: Make sure you test against the latest available version of Terraform and the provider. 42 | It is possible we may have already fixed the bug you're experiencing. 43 | * [ ] **Search for duplicates**: It's helpful to keep bug reports consolidated to one thread, so do a quick search 44 | on existing bug reports to check if anybody else has reported the same thing. 45 | You can scope searches by the label `bug` to help narrow things down. 46 | * [ ] **Include steps to reproduce**: Provide steps to reproduce the issue, along with code examples and/or real code, 47 | so we can try to reproduce it. Without this, it makes it much harder (sometimes impossible) to fix the issue. 48 | 49 | ### Feature Requests 50 | 51 | * [ ] **Search for possible duplicate requests**: It's helpful to keep requests consolidated to one thread, 52 | so do a quick search on existing requests to check if anybody else has reported the same thing. 53 | You can scope searches by the label `enhancement` to help narrow things down. 54 | * [ ] **Include a use case description**: In addition to describing the behavior of the feature you'd like to see added, 55 | it's helpful to also make a case for why the feature would be important and how it would benefit 56 | the provider and, potentially, the wider Terraform ecosystem. 57 | 58 | ## New Pull Request 59 | 60 | Thank you for contributing! 61 | 62 | We are happy to review pull requests without associated issues, 63 | but we **highly recommend** starting by describing and discussing 64 | your problem or feature and attaching use cases to an issue first 65 | before raising a pull request. 66 | 67 | * [ ] **Early validation of idea and implementation plan**: provider development is complicated enough that there 68 | are often several ways to implement something, each of which has different implications and tradeoffs. 69 | Working through a plan of attack with the team before you dive into implementation will help ensure that you're 70 | working in the right direction. 71 | * [ ] **Tests**: It may go without saying, but every new patch should be covered by tests wherever possible. 72 | For bug-fixes, tests to prove the fix is valid. For features, tests to exercise the new code paths. 73 | * [ ] **Go Modules**: We use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage and version our dependencies. 74 | Please make sure that you reflect dependency changes in your pull requests appropriately 75 | (e.g. `go get`, `go mod tidy` or other commands). 76 | Refer to the [dependency updates](#dependency-updates) section for more information about how 77 | this project maintains existing dependencies. 78 | * [ ] **Changelog**: Refer to the [changelog](#changelog) section for more information about how to create changelog entries. 79 | * [ ] **License Headers**: All source code requires a license header at the top of the file, refer to [License Headers](#license-headers) for information on how to autogenerate these headers. 80 | 81 | ### Dependency Updates 82 | 83 | Dependency management is performed by [Dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates). 84 | Where possible, dependency updates should occur through that system to ensure all Go module files are appropriately 85 | updated and to prevent duplicated effort of concurrent update submissions. 86 | Once available, updates are expected to be verified and merged to prevent latent technical debt. 87 | 88 | ### Changelog 89 | 90 | HashiCorp’s open-source projects have always maintained user-friendly, readable `CHANGELOG`s that allow 91 | practitioners and developers to tell at a glance whether a release should have any effect on them, 92 | and to gauge the risk of an upgrade. 93 | 94 | We follow Terraform Plugin 95 | [changelog specifications](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#changelog-specification). 96 | 97 | #### Changie Automation Tool 98 | This provider uses the [Changie](https://changie.dev/) automation tool for changelog automation. 99 | To add a new entry to the `CHANGELOG` install Changie using the following [instructions](https://changie.dev/guide/installation/) 100 | and run 101 | ```bash 102 | changie new 103 | ``` 104 | then choose a `kind` of change corresponding to the Terraform Plugin [changelog categories](https://developer.hashicorp.com/terraform/plugin/sdkv2/best-practices/versioning#categorization) 105 | and then fill out the body following the entry format. Changie will then prompt for a Github issue or pull request number. 106 | Repeat this process for any additional changes. The `.yaml` files created in the `.changes/unreleased` folder 107 | should be pushed the repository along with any code changes. 108 | 109 | #### Entry format 110 | 111 | Entries that are specific to _resources_ or _data sources_, they should look like: 112 | 113 | ```markdown 114 | * resource/RESOURCE_NAME: ENTRY DESCRIPTION 115 | 116 | * data-source/DATA-SOURCE_NAME: ENTRY DESCRIPTION 117 | ``` 118 | 119 | 120 | #### Pull Request Types to `CHANGELOG` 121 | 122 | The `CHANGELOG` is intended to show developer-impacting changes to the codebase for a particular version. 123 | If every change or commit to the code resulted in an entry, the `CHANGELOG` would become less useful for developers. 124 | The lists below are general guidelines to decide whether a change should have an entry. 125 | 126 | ##### Changes that should not have a `CHANGELOG` entry 127 | 128 | * Documentation updates 129 | * Testing updates 130 | * Code refactoring 131 | 132 | ##### Changes that may have a `CHANGELOG` entry 133 | 134 | * Dependency updates: If the update contains relevant bug fixes or enhancements that affect developers, 135 | those should be called out. 136 | 137 | ##### Changes that should have a `CHANGELOG` entry 138 | 139 | * Major features 140 | * Bug fixes 141 | * Enhancements 142 | * Deprecations 143 | * Breaking changes and removals 144 | 145 | ### License Headers 146 | 147 | All source code files (excluding autogenerated files like `go.mod`, prose, and files excluded in [.copywrite.hcl](../.copywrite.hcl)) must have a license header at the top. 148 | 149 | This can be autogenerated by running `make generate` or running `go generate ./...` in the [/tools](../tools) directory. 150 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_Report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Something is incorrect or not working as expected. 3 | labels: ["bug"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for taking the time to fill out this bug report! Please note that this issue tracker is only used for bug reports and feature requests. Other issues will be closed. 9 | 10 | If you have a configuration, workflow, or other question, please go back to the issue chooser and select one of the question links. 11 | - type: textarea 12 | id: versions 13 | attributes: 14 | label: Terraform CLI and Provider Versions 15 | description: What versions of Terraform CLI and the provider? 16 | placeholder: Output of `terraform version` from configuration directory 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: terraform-configuration 21 | attributes: 22 | label: Terraform Configuration 23 | description: Please copy and paste any relevant Terraform configuration. This will be automatically formatted into code, so no need for backticks. 24 | render: terraform 25 | validations: 26 | required: true 27 | - type: textarea 28 | id: expected-behavior 29 | attributes: 30 | label: Expected Behavior 31 | description: What did you expect to happen? 32 | placeholder: Description of what should have happened. 33 | validations: 34 | required: true 35 | - type: textarea 36 | id: actual-behavior 37 | attributes: 38 | label: Actual Behavior 39 | description: What actually happened? 40 | placeholder: Description of what actually happened. 41 | validations: 42 | required: true 43 | - type: textarea 44 | id: reproduction-steps 45 | attributes: 46 | label: Steps to Reproduce 47 | description: List of steps to reproduce the issue. 48 | value: | 49 | 1. `terraform apply` 50 | validations: 51 | required: true 52 | - type: dropdown 53 | id: impact 54 | attributes: 55 | label: How much impact is this issue causing? 56 | description: High represents completely not able to use the provider or unexpected destruction of data/infrastructure. Medium represents unable to upgrade provider version or an issue with potential workaround. Low represents minor provider code, configuration, or documentation issues. 57 | options: 58 | - High 59 | - Medium 60 | - Low 61 | validations: 62 | required: true 63 | - type: input 64 | id: logs 65 | attributes: 66 | label: Logs 67 | description: Please provide a link to a [GitHub Gist](https://gist.github.com) containing TRACE log output. [Terraform Debugging Documentation](https://www.terraform.io/internals/debugging) 68 | placeholder: https://gist.github.com/example/12345678 69 | validations: 70 | required: false 71 | - type: textarea 72 | id: additional-information 73 | attributes: 74 | label: Additional Information 75 | description: Are there any additional details about your environment, workflow, or recent changes that might be relevant? Have you discovered a workaround? Are there links to other related issues? 76 | validations: 77 | required: false 78 | - type: checkboxes 79 | id: terms 80 | attributes: 81 | label: Code of Conduct 82 | description: By submitting this issue, you agree to follow our [Community Guidelines](https://www.hashicorp.com/community-guidelines). 83 | options: 84 | - label: I agree to follow this project's Code of Conduct 85 | required: true 86 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_Request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Something is missing or could be improved. 3 | labels: ["enhancement"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for taking the time to fill out this feature request! Please note that this issue tracker is only used for bug reports and feature requests. Other issues will be closed. 9 | 10 | If you have a configuration, workflow, or other question, please go back to the issue chooser and select one of the question links. 11 | - type: textarea 12 | id: versions 13 | attributes: 14 | label: Terraform CLI and Provider Versions 15 | description: What versions of Terraform CLI and the provider? 16 | placeholder: Output of `terraform version` from configuration directory 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: use-case 21 | attributes: 22 | label: Use Cases or Problem Statement 23 | description: What use cases or problems are you trying to solve? 24 | placeholder: Description of use cases or problems. 25 | validations: 26 | required: true 27 | - type: textarea 28 | id: proposal 29 | attributes: 30 | label: Proposal 31 | description: What solutions would you prefer? 32 | placeholder: Description of proposed solutions. 33 | validations: 34 | required: true 35 | - type: dropdown 36 | id: impact 37 | attributes: 38 | label: How much impact is this issue causing? 39 | description: High represents completely not able to use the provider without this. Medium represents unable to solve a specific problem or understand something. Low represents minor provider code, configuration, or documentation issues. 40 | options: 41 | - High 42 | - Medium 43 | - Low 44 | validations: 45 | required: true 46 | - type: textarea 47 | id: additional-information 48 | attributes: 49 | label: Additional Information 50 | description: Are there any additional details about your environment, workflow, or recent changes that might be relevant? Have you discovered a workaround? Are there links to other related issues? 51 | validations: 52 | required: false 53 | - type: checkboxes 54 | id: terms 55 | attributes: 56 | label: Code of Conduct 57 | description: By submitting this issue, you agree to follow our [Community Guidelines](https://www.hashicorp.com/community-guidelines). 58 | options: 59 | - label: I agree to follow this project's Code of Conduct 60 | required: true 61 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Terraform Provider Questions 4 | url: https://discuss.hashicorp.com/c/terraform-providers/31 5 | about: GitHub issues in this repository are only intended for bug reports and feature requests. Other issues will be closed. Please ask and answer questions through the Terraform Provider section of HashiCorp Discuss. 6 | - name: Terraform Language or Workflow Questions 7 | url: https://discuss.hashicorp.com/c/terraform-core 8 | about: Please ask and answer language or workflow related questions through the Terraform Core section of HashiCorp Discuss. 9 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | * Project [README](../README.md) 4 | * Official [Documentation](https://registry.terraform.io/providers/hashicorp/tls/latest/docs) 5 | * Providers [Discuss forums](https://discuss.hashicorp.com/c/terraform-providers/31) 6 | * Terraform [Community](https://www.terraform.io/community.html) page -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # See GitHub's docs for more information on this file: 2 | # https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates 3 | version: 2 4 | updates: 5 | # Maintain dependencies for Go modules 6 | - package-ecosystem: "gomod" 7 | directory: "/" 8 | schedule: 9 | # Check for updates to Go modules every weekday 10 | interval: "daily" 11 | - package-ecosystem: "gomod" 12 | directory: "/tools" 13 | schedule: 14 | interval: "daily" 15 | - package-ecosystem: "github-actions" 16 | directory: "/" 17 | schedule: 18 | interval: "daily" 19 | -------------------------------------------------------------------------------- /.github/labeler-issue-triage.yml: -------------------------------------------------------------------------------- 1 | bug: 2 | - 'panic:' 3 | crash: 4 | - 'panic:' 5 | -------------------------------------------------------------------------------- /.github/labeler-pull-request-triage.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - changed-files: 3 | - any-glob-to-any-file: .github/dependabot.yml 4 | - any-glob-to-any-file: go.mod 5 | - any-glob-to-any-file: go.sum 6 | documentation: 7 | - changed-files: 8 | - any-glob-to-any-file: website/**/* -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Related Issue 2 | 3 | Fixes # 4 | 5 | ## Description 6 | 7 | In plain English, describe your approach to addressing the issue linked above. For example, if you made a particular design decision, let us know why you chose this path instead of another solution. 8 | 9 | 10 | ## Rollback Plan 11 | 12 | - [ ] If a change needs to be reverted, we will roll out an update to the code within 7 days. 13 | 14 | ## Changes to Security Controls 15 | 16 | Are there any changes to security controls (access controls, encryption, logging) in this pull request? If so, explain. 17 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow builds the product for all supported platforms and uploads the resulting 2 | # binaries as Actions artifacts. The workflow also uploads a build metadata file 3 | # (metadata.json) -- and a Terraform Registry manifest file (terraform-registry-manifest.json). 4 | # 5 | # Reference: https://github.com/hashicorp/terraform-provider-crt-example/blob/main/.github/workflows/README.md 6 | 7 | name: build 8 | 9 | # We default to running this workflow on every push to every branch. 10 | # This provides fast feedback when build issues occur, so they can be 11 | # fixed prior to being merged to the main branch. 12 | 13 | on: [workflow_dispatch, push] 14 | 15 | env: 16 | PKG_NAME: "terraform-provider-null" 17 | 18 | jobs: 19 | # Detects the Go toolchain version to use for product builds. 20 | # 21 | # The implementation is inspired by envconsul -- https://go.hashi.co/get-go-version-example 22 | get-go-version: 23 | name: "Detect Go toolchain version" 24 | runs-on: ubuntu-latest 25 | outputs: 26 | go-version: ${{ steps.get-go-version.outputs.go-version }} 27 | steps: 28 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 30 | with: 31 | go-version-file: 'go.mod' 32 | - name: Detect Go version 33 | id: get-go-version 34 | run: | 35 | version="$(go list -f {{.GoVersion}} -m)" 36 | echo "go-version=$version" >> "$GITHUB_OUTPUT" 37 | 38 | # Parses the version/VERSION file. Reference: https://github.com/hashicorp/actions-set-product-version/blob/main/README.md 39 | # 40 | # > This action should be implemented in product repo `build.yml` files. The action is intended to grab the version 41 | # > from the version file at the beginning of the build, then passes those versions (along with metadata, where 42 | # > necessary) to any workflow jobs that need version information. 43 | set-product-version: 44 | name: "Parse version file" 45 | runs-on: ubuntu-latest 46 | outputs: 47 | product-version: ${{ steps.set-product-version.outputs.product-version }} 48 | product-base-version: ${{ steps.set-product-version.outputs.base-product-version }} 49 | product-prerelease-version: ${{ steps.set-product-version.outputs.prerelease-product-version }} 50 | product-minor-version: ${{ steps.set-product-version.outputs.minor-product-version }} 51 | steps: 52 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 53 | - name: Set variables 54 | id: set-product-version 55 | uses: hashicorp/actions-set-product-version@v2 56 | 57 | # Creates metadata.json file containing build metadata for consumption by CRT workflows. 58 | # 59 | # Reference: https://github.com/hashicorp/actions-generate-metadata/blob/main/README.md 60 | generate-metadata-file: 61 | needs: set-product-version 62 | runs-on: ubuntu-latest 63 | outputs: 64 | filepath: ${{ steps.generate-metadata-file.outputs.filepath }} 65 | steps: 66 | - name: "Checkout directory" 67 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 68 | - name: Generate metadata file 69 | id: generate-metadata-file 70 | uses: hashicorp/actions-generate-metadata@v1 71 | with: 72 | version: ${{ needs.set-product-version.outputs.product-version }} 73 | product: ${{ env.PKG_NAME }} 74 | repositoryOwner: "hashicorp" 75 | - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 76 | with: 77 | name: metadata.json 78 | path: ${{ steps.generate-metadata-file.outputs.filepath }} 79 | 80 | # Uploads an Actions artifact named terraform-registry-manifest.json.zip. 81 | # 82 | # The artifact contains a single file with a filename that Terraform Registry expects 83 | # (example: terraform-provider-null_2.3.6-alpha.1_manifest.json). The file contents 84 | # are identical to the terraform-registry-manifest.json file in the source repository. 85 | upload-terraform-registry-manifest-artifact: 86 | needs: set-product-version 87 | runs-on: ubuntu-latest 88 | steps: 89 | - name: "Checkout directory" 90 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 91 | with: 92 | path: ${{ env.PKG_NAME }} 93 | - name: "Copy manifest from checkout directory to a file with the desired name" 94 | id: terraform-registry-manifest 95 | run: | 96 | name="${{ env.PKG_NAME }}" 97 | version="${{ needs.set-product-version.outputs.product-version }}" 98 | 99 | source="${name}/terraform-registry-manifest.json" 100 | destination="${name}_${version}_manifest.json" 101 | 102 | cp "$source" "$destination" 103 | echo "filename=$destination" >> "$GITHUB_OUTPUT" 104 | - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 105 | with: 106 | name: terraform-registry-manifest.json 107 | path: ${{ steps.terraform-registry-manifest.outputs.filename }} 108 | if-no-files-found: error 109 | 110 | # Builds the product for all platforms except macOS. 111 | # 112 | # With `reproducible: report`, this job also reports whether the build is reproducible, 113 | # but does not enforce it. 114 | # 115 | # Reference: https://github.com/hashicorp/actions-go-build/blob/main/README.md 116 | build: 117 | needs: 118 | - get-go-version 119 | - set-product-version 120 | runs-on: ubuntu-latest 121 | strategy: 122 | fail-fast: true 123 | matrix: 124 | goos: [freebsd, windows, linux, darwin] 125 | goarch: ["386", "amd64", "arm", "arm64"] 126 | exclude: 127 | - goos: freebsd 128 | goarch: arm64 129 | - goos: windows 130 | goarch: arm64 131 | - goos: windows 132 | goarch: arm 133 | - goos: darwin 134 | goarch: 386 135 | - goos: darwin 136 | goarch: arm 137 | 138 | name: Go ${{ needs.get-go-version.outputs.go-version }} ${{ matrix.goos }} ${{ matrix.goarch }} build 139 | steps: 140 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 141 | - uses: hashicorp/actions-go-build@v1 142 | env: 143 | CGO_ENABLED: 0 144 | BASE_VERSION: ${{ needs.set-product-version.outputs.product-base-version }} 145 | PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.product-prerelease-version}} 146 | METADATA_VERSION: ${{ env.METADATA }} 147 | with: 148 | bin_name: "${{ env.PKG_NAME }}_v${{ needs.set-product-version.outputs.product-version }}_x5" 149 | product_name: ${{ env.PKG_NAME }} 150 | product_version: ${{ needs.set-product-version.outputs.product-version }} 151 | go_version: ${{ needs.get-go-version.outputs.go-version }} 152 | os: ${{ matrix.goos }} 153 | arch: ${{ matrix.goarch }} 154 | reproducible: report 155 | instructions: | 156 | go build \ 157 | -o "$BIN_PATH" \ 158 | -trimpath \ 159 | -buildvcs=false \ 160 | -ldflags "-s -w" 161 | cp LICENSE "$TARGET_DIR/LICENSE.txt" 162 | 163 | whats-next: 164 | needs: 165 | - build 166 | - generate-metadata-file 167 | - upload-terraform-registry-manifest-artifact 168 | runs-on: ubuntu-latest 169 | name: "What's next?" 170 | steps: 171 | - name: "Write a helpful summary" 172 | run: | 173 | github_dot_com="${{ github.server_url }}" 174 | owner_with_name="${{ github.repository }}" 175 | ref="${{ github.ref }}" 176 | 177 | echo "### What's next?" >> "$GITHUB_STEP_SUMMARY" 178 | echo "#### For a release branch (see \`.release/ci.hcl\`)" >> $GITHUB_STEP_SUMMARY 179 | echo "After this \`build\` workflow run completes succesfully, you can expect the CRT \`prepare\` workflow to begin momentarily." >> "$GITHUB_STEP_SUMMARY" 180 | echo "To find the \`prepare\` workflow run, [view the checks for this commit]($github_dot_com/$owner_with_name/commits/$ref)" >> "$GITHUB_STEP_SUMMARY" 181 | -------------------------------------------------------------------------------- /.github/workflows/cdktf-docs.yml: -------------------------------------------------------------------------------- 1 | name: CDKTF docs 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | cdktfDocs: 7 | runs-on: ubuntu-latest 8 | container: 9 | image: docker.mirror.hashicorp.services/hashicorp/jsii-terraform 10 | env: 11 | CHECKPOINT_DISABLE: "1" 12 | timeout-minutes: 120 13 | steps: 14 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 15 | - name: Get yarn cache directory path 16 | id: global-cache-dir-path 17 | run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT 18 | - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 19 | id: global-cache 20 | with: 21 | path: ${{ steps.global-cache-dir-path.outputs.dir }} 22 | key: ${{ runner.os }}-integration-yarn-${{ hashFiles('**/yarn.lock') }} 23 | 24 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 25 | - name: Set up Go 26 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 27 | with: 28 | go-version-file: go.mod 29 | cache: true 30 | 31 | - run: go mod download 32 | 33 | - name: Build Go binary 34 | run: | 35 | go build -o terraform-provider-null 36 | 37 | - name: Setup Node.js 38 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 39 | with: 40 | node-version: "18.x" 41 | 42 | - name: Install cdktf-registry-docs 43 | run: npm install -g cdktf-registry-docs@1.14.2 44 | 45 | - name: Run conversion 46 | run: | 47 | chmod +x terraform-provider-null 48 | 49 | cdktf-registry-docs convert --language='typescript,python' --parallel-conversions-per-document=2 --provider-from-binary="$(pwd)/terraform-provider-null" --additional-provider-requirements="hashicorp/aws@~> 5.0.0" . 50 | env: 51 | TF_PLUGIN_CACHE_DIR: ${{ steps.global-cache-dir-path.outputs.dir }}/terraform-plugins 52 | 53 | - name: Git push cdktf docs 54 | run: | 55 | git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}" 56 | git config --global user.email "${{ env.CI_COMMIT_EMAIL }}" 57 | git checkout -b "cdktf-docs-${{ github.sha }}" 58 | git add . 59 | git commit -a -m "Update cdktf docs" 60 | git push "https://${{ env.CI_COMMIT_AUTHOR }}:${{ secrets.TF_DEVEX_COMMIT_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" 61 | 62 | - name: Create Pull Request 63 | uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 64 | with: 65 | commit-message: "docs: update cdktf documentation" 66 | title: "docs: update cdktf documentation" 67 | body: "This PR updates the cdktf related documentation based on the current HCL-based documentation. It is automatically created by the cdktf-documentation GitHub action." 68 | token: ${{ secrets.TF_DEVEX_COMMIT_GITHUB_TOKEN }} 69 | -------------------------------------------------------------------------------- /.github/workflows/ci-changie.yml: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - This GitHub Workflow is managed by automation 2 | # https://github.com/hashicorp/terraform-devex-repos 3 | 4 | # Continuous integration handling for changie 5 | name: ci-changie 6 | 7 | on: 8 | pull_request: 9 | paths: 10 | - .changes/unreleased/*.yaml 11 | - .changie.yaml 12 | - .github/workflows/ci-changie.yml 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | check: 19 | runs-on: ubuntu-latest 20 | steps: 21 | # Ensure terraform-devex-repos is updated on version changes. 22 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 23 | # Ensure terraform-devex-repos is updated on version changes. 24 | - uses: miniscruff/changie-action@6dcc2533cac0495148ed4046c438487e4dceaa23 # v2.0.0 25 | with: 26 | version: latest 27 | args: batch patch --dry-run 28 | -------------------------------------------------------------------------------- /.github/workflows/compliance.yml: -------------------------------------------------------------------------------- 1 | name: compliance 2 | 3 | on: 4 | pull_request: 5 | 6 | permissions: 7 | contents: read 8 | 9 | jobs: 10 | # Reference: ENGSRV-059 11 | copywrite: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 15 | - uses: hashicorp/setup-copywrite@32638da2d4e81d56a0764aa1547882fc4d209636 # v1.1.3 16 | - run: copywrite headers --plan 17 | - run: copywrite license --plan 18 | -------------------------------------------------------------------------------- /.github/workflows/issue-comment-triage.yml: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - This GitHub Workflow is managed by automation 2 | # https://github.com/hashicorp/terraform-devex-repos 3 | name: Issue Comment Triage 4 | 5 | on: 6 | issue_comment: 7 | types: [created] 8 | 9 | jobs: 10 | issue_comment_triage: 11 | runs-on: ubuntu-latest 12 | env: 13 | # issue_comment events are triggered by comments on issues and pull requests. Checking the 14 | # value of github.event.issue.pull_request tells us whether the issue is an issue or is 15 | # actually a pull request, allowing us to dynamically set the gh subcommand: 16 | # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment-on-issues-only-or-pull-requests-only 17 | COMMAND: ${{ github.event.issue.pull_request && 'pr' || 'issue' }} 18 | GH_TOKEN: ${{ github.token }} 19 | steps: 20 | - name: 'Remove waiting-response on comment' 21 | run: gh ${{ env.COMMAND }} edit ${{ github.event.issue.html_url }} --remove-label waiting-response 22 | -------------------------------------------------------------------------------- /.github/workflows/issue-opened.yml: -------------------------------------------------------------------------------- 1 | name: Issue Opened Triage 2 | 3 | on: 4 | issues: 5 | types: [opened] 6 | 7 | jobs: 8 | issue_triage: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 12 | - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4 13 | with: 14 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 15 | configuration-path: .github/labeler-issue-triage.yml 16 | enable-versioned-regex: 0 17 | -------------------------------------------------------------------------------- /.github/workflows/lock.yml: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - This GitHub Workflow is managed by automation 2 | # https://github.com/hashicorp/terraform-devex-repos 3 | name: 'Lock Threads' 4 | 5 | on: 6 | schedule: 7 | - cron: '32 11 * * *' 8 | 9 | jobs: 10 | lock: 11 | runs-on: ubuntu-latest 12 | steps: 13 | # NOTE: When TSCCR updates the GitHub action version, update the template workflow file to avoid drift: 14 | # https://github.com/hashicorp/terraform-devex-repos/blob/main/modules/repo/workflows/lock.tftpl 15 | - uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1 16 | with: 17 | github-token: ${{ github.token }} 18 | issue-inactive-days: '30' 19 | issue-lock-reason: resolved 20 | pr-inactive-days: '30' 21 | pr-lock-reason: resolved 22 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Triage" 2 | 3 | on: [pull_request_target] 4 | 5 | permissions: 6 | # CodelyTV/pr-size-labeler uses issues URL for labeling 7 | issues: write 8 | pull-requests: write 9 | 10 | jobs: 11 | triage: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 15 | with: 16 | configuration-path: .github/labeler-pull-request-triage.yml 17 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 18 | - uses: CodelyTV/pr-size-labeler@4ec67706cd878fbc1c8db0a5dcd28b6bb412e85a # v1.10.3 19 | with: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | xs_label: 'size/XS' 22 | xs_max_size: '30' 23 | s_label: 'size/S' 24 | s_max_size: '60' 25 | m_label: 'size/M' 26 | m_max_size: '150' 27 | l_label: 'size/L' 28 | l_max_size: '300' 29 | xl_label: 'size/XL' 30 | message_if_xl: '' 31 | files_to_ignore: 'go.sum' 32 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | paths-ignore: 7 | - 'README.md' 8 | - 'CHANGELOG.md' 9 | - 'website/*' 10 | push: 11 | branches: [ main ] 12 | paths-ignore: 13 | - 'README.md' 14 | - 'CHANGELOG.md' 15 | - 'website/*' 16 | 17 | jobs: 18 | 19 | build: 20 | name: Build 21 | runs-on: ubuntu-latest 22 | timeout-minutes: 5 23 | 24 | steps: 25 | 26 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 28 | with: 29 | go-version-file: 'go.mod' 30 | 31 | - name: Run linters 32 | uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 33 | with: 34 | version: latest 35 | 36 | # We need the latest version of Terraform for our documentation generation to use 37 | - name: Set up Terraform 38 | uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 39 | with: 40 | terraform_wrapper: false 41 | 42 | - name: Generate 43 | run: make generate 44 | 45 | - name: Confirm no diff 46 | run: | 47 | git diff --compact-summary --exit-code || \ 48 | (echo "*** Unexpected differences after code generation. Run 'make generate' and commit."; exit 1) 49 | 50 | - name: Build 51 | run: make build 52 | 53 | test: 54 | name: 'Acc. Tests (OS: ${{ matrix.os }} / TF: ${{ matrix.terraform }})' 55 | needs: build 56 | runs-on: ${{ matrix.os }} 57 | timeout-minutes: 15 58 | 59 | strategy: 60 | fail-fast: false 61 | matrix: 62 | os: 63 | - macos-latest 64 | - windows-latest 65 | - ubuntu-latest 66 | terraform: ${{ fromJSON(vars.TF_VERSIONS_PROTOCOL_V5) }} 67 | 68 | steps: 69 | 70 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 71 | - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 72 | with: 73 | go-version-file: 'go.mod' 74 | 75 | - name: Setup Terraform ${{ matrix.terraform }} 76 | uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 77 | with: 78 | terraform_version: ${{ matrix.terraform }} 79 | terraform_wrapper: false 80 | 81 | - name: Run acceptance test 82 | run: make testacc 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.exe 3 | .DS_Store 4 | example.tf 5 | terraform.tfplan 6 | terraform.tfstate 7 | bin/ 8 | modules-dev/ 9 | /pkg/ 10 | website/.vagrant 11 | website/.bundle 12 | website/build 13 | website/node_modules 14 | .vagrant/ 15 | *.backup 16 | ./*.tfstate 17 | .terraform/ 18 | *.log 19 | *.bak 20 | *~ 21 | .*.swp 22 | .idea 23 | *.iml 24 | *.test 25 | *.iml 26 | 27 | website/vendor 28 | 29 | # Test exclusions 30 | !command/test-fixtures/**/*.tfstate 31 | !command/test-fixtures/**/.terraform/ 32 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | linters: 3 | default: none 4 | enable: 5 | - copyloopvar 6 | - durationcheck 7 | - errcheck 8 | - forcetypeassert 9 | - godot 10 | - govet 11 | - ineffassign 12 | - makezero 13 | - misspell 14 | - nilerr 15 | - predeclared 16 | - staticcheck 17 | - unconvert 18 | - unparam 19 | - unused 20 | - usetesting 21 | exclusions: 22 | generated: lax 23 | presets: 24 | - comments 25 | - common-false-positives 26 | - legacy 27 | - std-error-handling 28 | paths: 29 | - third_party$ 30 | - builtin$ 31 | - examples$ 32 | issues: 33 | max-issues-per-linter: 0 34 | max-same-issues: 0 35 | formatters: 36 | enable: 37 | - gofmt 38 | exclusions: 39 | generated: lax 40 | paths: 41 | - third_party$ 42 | - builtin$ 43 | - examples$ 44 | -------------------------------------------------------------------------------- /.release/ci.hcl: -------------------------------------------------------------------------------- 1 | # Reference: https://github.com/hashicorp/crt-core-helloworld/blob/main/.release/ci.hcl (private repository) 2 | 3 | schema = "2" 4 | 5 | project "terraform-provider-null" { 6 | // team is currently unused and has no meaning 7 | // but is required to be non-empty by CRT orchestator 8 | team = "_UNUSED_" 9 | 10 | slack { 11 | notification_channel = "C02BASDVCDT" // #feed-terraform-sdk 12 | } 13 | 14 | github { 15 | organization = "hashicorp" 16 | repository = "terraform-provider-null" 17 | release_branches = ["main", "release/**"] 18 | } 19 | } 20 | 21 | event "merge" { 22 | } 23 | 24 | event "build" { 25 | action "build" { 26 | depends = ["merge"] 27 | 28 | organization = "hashicorp" 29 | repository = "terraform-provider-null" 30 | workflow = "build" 31 | } 32 | } 33 | 34 | event "prepare" { 35 | # `prepare` is the Common Release Tooling (CRT) artifact processing workflow. 36 | # It prepares artifacts for potential promotion to staging and production. 37 | # For example, it scans and signs artifacts. 38 | 39 | depends = ["build"] 40 | 41 | action "prepare" { 42 | organization = "hashicorp" 43 | repository = "crt-workflows-common" 44 | workflow = "prepare" 45 | depends = ["build"] 46 | } 47 | 48 | notification { 49 | on = "fail" 50 | } 51 | } 52 | 53 | event "trigger-staging" { 54 | } 55 | 56 | event "promote-staging" { 57 | action "promote-staging" { 58 | organization = "hashicorp" 59 | repository = "crt-workflows-common" 60 | workflow = "promote-staging" 61 | depends = null 62 | config = "oss-release-metadata.hcl" 63 | } 64 | 65 | depends = ["trigger-staging"] 66 | 67 | notification { 68 | on = "always" 69 | } 70 | } 71 | 72 | event "trigger-production" { 73 | } 74 | 75 | event "promote-production" { 76 | action "promote-production" { 77 | organization = "hashicorp" 78 | repository = "crt-workflows-common" 79 | workflow = "promote-production" 80 | depends = null 81 | config = "" 82 | } 83 | 84 | depends = ["trigger-production"] 85 | 86 | notification { 87 | on = "always" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /.release/oss-release-metadata.hcl: -------------------------------------------------------------------------------- 1 | url_source_repository = "https://github.com/hashicorp/terraform-provider-null" 2 | url_project_website = "https://registry.terraform.io/providers/hashicorp/null" 3 | url_license = "https://github.com/hashicorp/terraform-provider-null/blob/main/LICENSE" 4 | url_release_notes = "https://github.com/hashicorp/terraform-provider-null/blob/main/CHANGELOG.md" 5 | -------------------------------------------------------------------------------- /.release/release-metadata.hcl: -------------------------------------------------------------------------------- 1 | url_source_repository = "https://github.com/hashicorp/terraform-provider-null" 2 | url_license = "https://github.com/hashicorp/terraform-provider-null/blob/main/LICENSE" 3 | -------------------------------------------------------------------------------- /.release/security-scan.hcl: -------------------------------------------------------------------------------- 1 | # Reference: https://github.com/hashicorp/security-scanner/blob/main/CONFIG.md#binary (private repository) 2 | 3 | binary { 4 | secrets { 5 | all = true 6 | } 7 | go_modules = true 8 | osv = true 9 | oss_index = false 10 | nvd = false 11 | } 12 | -------------------------------------------------------------------------------- /.release/terraform-provider-null-artifacts.hcl: -------------------------------------------------------------------------------- 1 | schema = 1 2 | artifacts { 3 | zip = [ 4 | "terraform-provider-null_${version}_darwin_amd64.zip", 5 | "terraform-provider-null_${version}_darwin_arm64.zip", 6 | "terraform-provider-null_${version}_freebsd_386.zip", 7 | "terraform-provider-null_${version}_freebsd_amd64.zip", 8 | "terraform-provider-null_${version}_freebsd_arm.zip", 9 | "terraform-provider-null_${version}_linux_386.zip", 10 | "terraform-provider-null_${version}_linux_amd64.zip", 11 | "terraform-provider-null_${version}_linux_arm.zip", 12 | "terraform-provider-null_${version}_linux_arm64.zip", 13 | "terraform-provider-null_${version}_windows_386.zip", 14 | "terraform-provider-null_${version}_windows_amd64.zip", 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.2.4 (April 21, 2025) 2 | 3 | NOTES: 4 | 5 | * Dependency updates ([#421](https://github.com/hashicorp/terraform-provider-null/issues/421)) 6 | 7 | ## 3.2.4-alpha1 (February 19, 2025) 8 | 9 | NOTES: 10 | 11 | * all: This release is being used to test new build and release actions. 12 | 13 | ## 3.2.4-alpha.2 (March 27, 2025) 14 | 15 | NOTES: 16 | 17 | * all: This release is being used to test new build and release actions. 18 | 19 | ## 3.2.3 (September 11, 2024) 20 | 21 | NOTES: 22 | 23 | * all: This release introduces no functional changes. It does however include dependency updates which address upstream CVEs. ([#366](https://github.com/hashicorp/terraform-provider-null/issues/366)) 24 | 25 | ## 3.2.2 (November 20, 2023) 26 | 27 | NOTES: 28 | 29 | * This release introduces no functional changes. It does however include dependency updates which address upstream CVEs. ([#242](https://github.com/hashicorp/terraform-provider-null/issues/242)) 30 | 31 | ## 3.2.1 (November 17, 2022) 32 | 33 | BUG FIXES: 34 | 35 | * provider: Fix random number generation for `id` attributes ([#160](https://github.com/hashicorp/terraform-provider-null/pull/160)) 36 | 37 | ## 3.2.0 (October 25, 2022) 38 | 39 | NOTES: 40 | 41 | * Provider: Rewritten to use the new [`terraform-plugin-framework`](https://www.terraform.io/plugin/framework) ([#150](https://github.com/hashicorp/terraform-provider-null/pull/150)) 42 | 43 | ## 3.1.1 (March 16, 2022) 44 | 45 | NOTES: 46 | 47 | * Updated [terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) to `v0.7.0`: 48 | this improves generated documentation, with attributes now correctly formatted as `code` 49 | and provided with anchors. 50 | * Functionally identical to the previous 3.1.0 release. 51 | 52 | ## 3.1.0 (February 19, 2021) 53 | 54 | Binary releases of this provider now include the darwin-arm64 platform. This version contains no further changes. 55 | 56 | ## 3.0.0 (October 08, 2020) 57 | 58 | Binary releases of this provider now include the linux-arm64 platform. 59 | 60 | BREAKING CHANGES: 61 | 62 | * Upgrade to version 2 of the Terraform Plugin SDK, which drops support for Terraform 0.11. This provider will continue to work as expected for users of Terraform 0.11, which will not download the new version. ([#47](https://github.com/terraform-providers/terraform-provider-null/issues/47)) 63 | 64 | ## 2.1.2 (April 30, 2019) 65 | 66 | * This releases includes another Terraform SDK upgrade intended to align with that being used for other providers as we prepare for the Core v0.12.0 release. It should have no significant changes in behavior for this provider. 67 | 68 | ## 2.1.1 (April 11, 2019) 69 | 70 | * This releases includes only a Terraform SDK upgrade intended to align with that being used for other providers as we prepare for the Core v0.12.0 release. It should have no significant changes in behavior for this provider. 71 | 72 | ## 2.1.0 (February 27, 2019) 73 | 74 | IMPROVEMENTS: 75 | 76 | * The previous release contains an SDK incompatible with TF 0.12. Fortunately 0.12 was not released yet so upgrading the vendored sdk makes this release compatible with 0.12. 77 | 78 | ## 2.0.0 (January 18, 2019) 79 | 80 | IMPROVEMENTS: 81 | 82 | * The provider is now compatible with Terraform v0.12, while retaining compatibility with prior versions. 83 | 84 | ## 1.0.0 (September 26, 2017) 85 | 86 | * No changes from 0.1.0; just adjusting to [the new version numbering scheme](https://www.hashicorp.com/blog/hashicorp-terraform-provider-versioning/). 87 | 88 | ## 0.1.0 (June 21, 2017) 89 | 90 | NOTES: 91 | 92 | * Same functionality as that of Terraform 0.9.8. Repacked as part of [Provider Splitout](https://www.hashicorp.com/blog/upcoming-provider-changes-in-terraform-0-10/) 93 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | default: build 2 | 3 | build: 4 | go build -v ./... 5 | 6 | install: build 7 | go install -v ./... 8 | 9 | # See https://golangci-lint.run/ 10 | lint: 11 | golangci-lint run 12 | 13 | # Generate docs and copywrite headers 14 | generate: 15 | cd tools; go generate ./... 16 | 17 | fmt: 18 | gofmt -s -w -e . 19 | 20 | test: 21 | go test -v -cover -timeout=120s -parallel=4 ./... 22 | 23 | testacc: 24 | TF_ACC=1 go test -v -cover -timeout 120m ./... 25 | 26 | .PHONY: build install lint generate fmt test testacc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 HashiCorp, Inc. 2 | 3 | Mozilla Public License Version 2.0 4 | ================================== 5 | 6 | 1. Definitions 7 | -------------- 8 | 9 | 1.1. "Contributor" 10 | means each individual or legal entity that creates, contributes to 11 | the creation of, or owns Covered Software. 12 | 13 | 1.2. "Contributor Version" 14 | means the combination of the Contributions of others (if any) used 15 | by a Contributor and that particular Contributor's Contribution. 16 | 17 | 1.3. "Contribution" 18 | means Covered Software of a particular Contributor. 19 | 20 | 1.4. "Covered Software" 21 | means Source Code Form to which the initial Contributor has attached 22 | the notice in Exhibit A, the Executable Form of such Source Code 23 | Form, and Modifications of such Source Code Form, in each case 24 | including portions thereof. 25 | 26 | 1.5. "Incompatible With Secondary Licenses" 27 | means 28 | 29 | (a) that the initial Contributor has attached the notice described 30 | in Exhibit B to the Covered Software; or 31 | 32 | (b) that the Covered Software was made available under the terms of 33 | version 1.1 or earlier of the License, but not also under the 34 | terms of a Secondary License. 35 | 36 | 1.6. "Executable Form" 37 | means any form of the work other than Source Code Form. 38 | 39 | 1.7. "Larger Work" 40 | means a work that combines Covered Software with other material, in 41 | a separate file or files, that is not Covered Software. 42 | 43 | 1.8. "License" 44 | means this document. 45 | 46 | 1.9. "Licensable" 47 | means having the right to grant, to the maximum extent possible, 48 | whether at the time of the initial grant or subsequently, any and 49 | all of the rights conveyed by this License. 50 | 51 | 1.10. "Modifications" 52 | means any of the following: 53 | 54 | (a) any file in Source Code Form that results from an addition to, 55 | deletion from, or modification of the contents of Covered 56 | Software; or 57 | 58 | (b) any new file in Source Code Form that contains any Covered 59 | Software. 60 | 61 | 1.11. "Patent Claims" of a Contributor 62 | means any patent claim(s), including without limitation, method, 63 | process, and apparatus claims, in any patent Licensable by such 64 | Contributor that would be infringed, but for the grant of the 65 | License, by the making, using, selling, offering for sale, having 66 | made, import, or transfer of either its Contributions or its 67 | Contributor Version. 68 | 69 | 1.12. "Secondary License" 70 | means either the GNU General Public License, Version 2.0, the GNU 71 | Lesser General Public License, Version 2.1, the GNU Affero General 72 | Public License, Version 3.0, or any later versions of those 73 | licenses. 74 | 75 | 1.13. "Source Code Form" 76 | means the form of the work preferred for making modifications. 77 | 78 | 1.14. "You" (or "Your") 79 | means an individual or a legal entity exercising rights under this 80 | License. For legal entities, "You" includes any entity that 81 | controls, is controlled by, or is under common control with You. For 82 | purposes of this definition, "control" means (a) the power, direct 83 | or indirect, to cause the direction or management of such entity, 84 | whether by contract or otherwise, or (b) ownership of more than 85 | fifty percent (50%) of the outstanding shares or beneficial 86 | ownership of such entity. 87 | 88 | 2. License Grants and Conditions 89 | -------------------------------- 90 | 91 | 2.1. Grants 92 | 93 | Each Contributor hereby grants You a world-wide, royalty-free, 94 | non-exclusive license: 95 | 96 | (a) under intellectual property rights (other than patent or trademark) 97 | Licensable by such Contributor to use, reproduce, make available, 98 | modify, display, perform, distribute, and otherwise exploit its 99 | Contributions, either on an unmodified basis, with Modifications, or 100 | as part of a Larger Work; and 101 | 102 | (b) under Patent Claims of such Contributor to make, use, sell, offer 103 | for sale, have made, import, and otherwise transfer either its 104 | Contributions or its Contributor Version. 105 | 106 | 2.2. Effective Date 107 | 108 | The licenses granted in Section 2.1 with respect to any Contribution 109 | become effective for each Contribution on the date the Contributor first 110 | distributes such Contribution. 111 | 112 | 2.3. Limitations on Grant Scope 113 | 114 | The licenses granted in this Section 2 are the only rights granted under 115 | this License. No additional rights or licenses will be implied from the 116 | distribution or licensing of Covered Software under this License. 117 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 118 | Contributor: 119 | 120 | (a) for any code that a Contributor has removed from Covered Software; 121 | or 122 | 123 | (b) for infringements caused by: (i) Your and any other third party's 124 | modifications of Covered Software, or (ii) the combination of its 125 | Contributions with other software (except as part of its Contributor 126 | Version); or 127 | 128 | (c) under Patent Claims infringed by Covered Software in the absence of 129 | its Contributions. 130 | 131 | This License does not grant any rights in the trademarks, service marks, 132 | or logos of any Contributor (except as may be necessary to comply with 133 | the notice requirements in Section 3.4). 134 | 135 | 2.4. Subsequent Licenses 136 | 137 | No Contributor makes additional grants as a result of Your choice to 138 | distribute the Covered Software under a subsequent version of this 139 | License (see Section 10.2) or under the terms of a Secondary License (if 140 | permitted under the terms of Section 3.3). 141 | 142 | 2.5. Representation 143 | 144 | Each Contributor represents that the Contributor believes its 145 | Contributions are its original creation(s) or it has sufficient rights 146 | to grant the rights to its Contributions conveyed by this License. 147 | 148 | 2.6. Fair Use 149 | 150 | This License is not intended to limit any rights You have under 151 | applicable copyright doctrines of fair use, fair dealing, or other 152 | equivalents. 153 | 154 | 2.7. Conditions 155 | 156 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 157 | in Section 2.1. 158 | 159 | 3. Responsibilities 160 | ------------------- 161 | 162 | 3.1. Distribution of Source Form 163 | 164 | All distribution of Covered Software in Source Code Form, including any 165 | Modifications that You create or to which You contribute, must be under 166 | the terms of this License. You must inform recipients that the Source 167 | Code Form of the Covered Software is governed by the terms of this 168 | License, and how they can obtain a copy of this License. You may not 169 | attempt to alter or restrict the recipients' rights in the Source Code 170 | Form. 171 | 172 | 3.2. Distribution of Executable Form 173 | 174 | If You distribute Covered Software in Executable Form then: 175 | 176 | (a) such Covered Software must also be made available in Source Code 177 | Form, as described in Section 3.1, and You must inform recipients of 178 | the Executable Form how they can obtain a copy of such Source Code 179 | Form by reasonable means in a timely manner, at a charge no more 180 | than the cost of distribution to the recipient; and 181 | 182 | (b) You may distribute such Executable Form under the terms of this 183 | License, or sublicense it under different terms, provided that the 184 | license for the Executable Form does not attempt to limit or alter 185 | the recipients' rights in the Source Code Form under this License. 186 | 187 | 3.3. Distribution of a Larger Work 188 | 189 | You may create and distribute a Larger Work under terms of Your choice, 190 | provided that You also comply with the requirements of this License for 191 | the Covered Software. If the Larger Work is a combination of Covered 192 | Software with a work governed by one or more Secondary Licenses, and the 193 | Covered Software is not Incompatible With Secondary Licenses, this 194 | License permits You to additionally distribute such Covered Software 195 | under the terms of such Secondary License(s), so that the recipient of 196 | the Larger Work may, at their option, further distribute the Covered 197 | Software under the terms of either this License or such Secondary 198 | License(s). 199 | 200 | 3.4. Notices 201 | 202 | You may not remove or alter the substance of any license notices 203 | (including copyright notices, patent notices, disclaimers of warranty, 204 | or limitations of liability) contained within the Source Code Form of 205 | the Covered Software, except that You may alter any license notices to 206 | the extent required to remedy known factual inaccuracies. 207 | 208 | 3.5. Application of Additional Terms 209 | 210 | You may choose to offer, and to charge a fee for, warranty, support, 211 | indemnity or liability obligations to one or more recipients of Covered 212 | Software. However, You may do so only on Your own behalf, and not on 213 | behalf of any Contributor. You must make it absolutely clear that any 214 | such warranty, support, indemnity, or liability obligation is offered by 215 | You alone, and You hereby agree to indemnify every Contributor for any 216 | liability incurred by such Contributor as a result of warranty, support, 217 | indemnity or liability terms You offer. You may include additional 218 | disclaimers of warranty and limitations of liability specific to any 219 | jurisdiction. 220 | 221 | 4. Inability to Comply Due to Statute or Regulation 222 | --------------------------------------------------- 223 | 224 | If it is impossible for You to comply with any of the terms of this 225 | License with respect to some or all of the Covered Software due to 226 | statute, judicial order, or regulation then You must: (a) comply with 227 | the terms of this License to the maximum extent possible; and (b) 228 | describe the limitations and the code they affect. Such description must 229 | be placed in a text file included with all distributions of the Covered 230 | Software under this License. Except to the extent prohibited by statute 231 | or regulation, such description must be sufficiently detailed for a 232 | recipient of ordinary skill to be able to understand it. 233 | 234 | 5. Termination 235 | -------------- 236 | 237 | 5.1. The rights granted under this License will terminate automatically 238 | if You fail to comply with any of its terms. However, if You become 239 | compliant, then the rights granted under this License from a particular 240 | Contributor are reinstated (a) provisionally, unless and until such 241 | Contributor explicitly and finally terminates Your grants, and (b) on an 242 | ongoing basis, if such Contributor fails to notify You of the 243 | non-compliance by some reasonable means prior to 60 days after You have 244 | come back into compliance. Moreover, Your grants from a particular 245 | Contributor are reinstated on an ongoing basis if such Contributor 246 | notifies You of the non-compliance by some reasonable means, this is the 247 | first time You have received notice of non-compliance with this License 248 | from such Contributor, and You become compliant prior to 30 days after 249 | Your receipt of the notice. 250 | 251 | 5.2. If You initiate litigation against any entity by asserting a patent 252 | infringement claim (excluding declaratory judgment actions, 253 | counter-claims, and cross-claims) alleging that a Contributor Version 254 | directly or indirectly infringes any patent, then the rights granted to 255 | You by any and all Contributors for the Covered Software under Section 256 | 2.1 of this License shall terminate. 257 | 258 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 259 | end user license agreements (excluding distributors and resellers) which 260 | have been validly granted by You or Your distributors under this License 261 | prior to termination shall survive termination. 262 | 263 | ************************************************************************ 264 | * * 265 | * 6. Disclaimer of Warranty * 266 | * ------------------------- * 267 | * * 268 | * Covered Software is provided under this License on an "as is" * 269 | * basis, without warranty of any kind, either expressed, implied, or * 270 | * statutory, including, without limitation, warranties that the * 271 | * Covered Software is free of defects, merchantable, fit for a * 272 | * particular purpose or non-infringing. The entire risk as to the * 273 | * quality and performance of the Covered Software is with You. * 274 | * Should any Covered Software prove defective in any respect, You * 275 | * (not any Contributor) assume the cost of any necessary servicing, * 276 | * repair, or correction. This disclaimer of warranty constitutes an * 277 | * essential part of this License. No use of any Covered Software is * 278 | * authorized under this License except under this disclaimer. * 279 | * * 280 | ************************************************************************ 281 | 282 | ************************************************************************ 283 | * * 284 | * 7. Limitation of Liability * 285 | * -------------------------- * 286 | * * 287 | * Under no circumstances and under no legal theory, whether tort * 288 | * (including negligence), contract, or otherwise, shall any * 289 | * Contributor, or anyone who distributes Covered Software as * 290 | * permitted above, be liable to You for any direct, indirect, * 291 | * special, incidental, or consequential damages of any character * 292 | * including, without limitation, damages for lost profits, loss of * 293 | * goodwill, work stoppage, computer failure or malfunction, or any * 294 | * and all other commercial damages or losses, even if such party * 295 | * shall have been informed of the possibility of such damages. This * 296 | * limitation of liability shall not apply to liability for death or * 297 | * personal injury resulting from such party's negligence to the * 298 | * extent applicable law prohibits such limitation. Some * 299 | * jurisdictions do not allow the exclusion or limitation of * 300 | * incidental or consequential damages, so this exclusion and * 301 | * limitation may not apply to You. * 302 | * * 303 | ************************************************************************ 304 | 305 | 8. Litigation 306 | ------------- 307 | 308 | Any litigation relating to this License may be brought only in the 309 | courts of a jurisdiction where the defendant maintains its principal 310 | place of business and such litigation shall be governed by laws of that 311 | jurisdiction, without reference to its conflict-of-law provisions. 312 | Nothing in this Section shall prevent a party's ability to bring 313 | cross-claims or counter-claims. 314 | 315 | 9. Miscellaneous 316 | ---------------- 317 | 318 | This License represents the complete agreement concerning the subject 319 | matter hereof. If any provision of this License is held to be 320 | unenforceable, such provision shall be reformed only to the extent 321 | necessary to make it enforceable. Any law or regulation which provides 322 | that the language of a contract shall be construed against the drafter 323 | shall not be used to construe this License against a Contributor. 324 | 325 | 10. Versions of the License 326 | --------------------------- 327 | 328 | 10.1. New Versions 329 | 330 | Mozilla Foundation is the license steward. Except as provided in Section 331 | 10.3, no one other than the license steward has the right to modify or 332 | publish new versions of this License. Each version will be given a 333 | distinguishing version number. 334 | 335 | 10.2. Effect of New Versions 336 | 337 | You may distribute the Covered Software under the terms of the version 338 | of the License under which You originally received the Covered Software, 339 | or under the terms of any subsequent version published by the license 340 | steward. 341 | 342 | 10.3. Modified Versions 343 | 344 | If you create software not governed by this License, and you want to 345 | create a new license for such software, you may create and use a 346 | modified version of this License if you rename the license and remove 347 | any references to the name of the license steward (except to note that 348 | such modified license differs from this License). 349 | 350 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 351 | Licenses 352 | 353 | If You choose to distribute Source Code Form that is Incompatible With 354 | Secondary Licenses under the terms of this version of the License, the 355 | notice described in Exhibit B of this License must be attached. 356 | 357 | Exhibit A - Source Code Form License Notice 358 | ------------------------------------------- 359 | 360 | This Source Code Form is subject to the terms of the Mozilla Public 361 | License, v. 2.0. If a copy of the MPL was not distributed with this 362 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 363 | 364 | If it is not possible or desirable to put the notice in a particular 365 | file, then You may include the notice in a location (such as a LICENSE 366 | file in a relevant directory) where a recipient would be likely to look 367 | for such a notice. 368 | 369 | You may add additional accurate notices of copyright ownership. 370 | 371 | Exhibit B - "Incompatible With Secondary Licenses" Notice 372 | --------------------------------------------------------- 373 | 374 | This Source Code Form is "Incompatible With Secondary Licenses", as 375 | defined by the Mozilla Public License, v. 2.0. 376 | -------------------------------------------------------------------------------- /META.d/_summary.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: 1.1 3 | 4 | partition: tf-ecosystem 5 | 6 | summary: 7 | owner: team-tf-core-plugins 8 | description: | 9 | Utility provider that provides constructs that intentionally do nothing, useful in various situations to help orchestrate tricky behavior or work around limitations. 10 | visibility: public 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform Provider: Null 2 | 3 | The Null provider is a rather-unusual provider that has constructs that intentionally do nothing. This may sound strange, and indeed these constructs do not need to be used in most cases, but they can be useful in various situations to help orchestrate tricky behavior or work around limitations. 4 | 5 | ## Requirements 6 | 7 | * [Terraform](https://www.terraform.io/downloads) 8 | * [Go](https://go.dev/doc/install) (1.23) 9 | * [GNU Make](https://www.gnu.org/software/make/) 10 | * [golangci-lint](https://golangci-lint.run/usage/install/#local-installation) (optional) 11 | 12 | ## Documentation, questions and discussions 13 | Official documentation on how to use this provider can be found on the 14 | [Terraform Registry](https://registry.terraform.io/providers/hashicorp/null/latest/docs). 15 | In case of specific questions or discussions, please use the 16 | HashiCorp [Terraform Providers Discuss forums](https://discuss.hashicorp.com/c/terraform-providers/31), 17 | in accordance with HashiCorp [Community Guidelines](https://www.hashicorp.com/community-guidelines). 18 | 19 | We also provide: 20 | 21 | * [Support](.github/SUPPORT.md) page for help when using the provider 22 | * [Contributing](.github/CONTRIBUTING.md) guidelines in case you want to help this project 23 | 24 | ## Compatibility 25 | 26 | Compatibility table between this provider, the [Terraform Plugin Protocol](https://www.terraform.io/plugin/how-terraform-works#terraform-plugin-protocol) 27 | version it implements, and Terraform: 28 | 29 | | Null Provider | Terraform Plugin Protocol | Terraform | 30 | |:-------------:|:-------------------------:|:---------:| 31 | | `>= 3.0.x` | `5` | `>= 0.12` | 32 | | `>= 2.1.x` | `4` and `5` | `>= 0.12` | 33 | | `>= 2.x.x` | `4` | `<= 0.12` | 34 | | `>= 1.x.x` | `4` | `<= 0.12` | 35 | | `>= 0.1.x` | `4` | `<= 0.12` | 36 | 37 | Details can be found querying the [Registry API](https://www.terraform.io/internals/provider-registry-protocol#list-available-versions) 38 | that return all the details about which version are currently available for a particular provider. 39 | [Here](https://registry.terraform.io/v1/providers/hashicorp/null/versions) are the details for Time (JSON response). 40 | 41 | 42 | ## Development 43 | 44 | ### Building 45 | 46 | 1. `git clone` this repository and `cd` into its directory 47 | 2. `make` will trigger the Golang build 48 | 49 | The provided `GNUmakefile` defines additional commands generally useful during development, 50 | like for running tests, generating documentation, code formatting and linting. 51 | Taking a look at it's content is recommended. 52 | 53 | ### Testing 54 | 55 | In order to test the provider, you can run 56 | 57 | * `make test` to run provider tests 58 | * `make testacc` to run provider acceptance tests 59 | 60 | It's important to note that acceptance tests (`testacc`) will actually spawn 61 | `terraform` and the provider. Read more about they work on the 62 | [official page](https://www.terraform.io/plugin/sdkv2/testing/acceptance-tests). 63 | 64 | ### Generating documentation 65 | 66 | This provider uses [terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs/) 67 | to generate documentation and store it in the `docs/` directory. 68 | Once a release is cut, the Terraform Registry will download the documentation from `docs/` 69 | and associate it with the release version. Read more about how this works on the 70 | [official page](https://www.terraform.io/registry/providers/docs). 71 | 72 | Use `make generate` to ensure the documentation is regenerated with any changes. 73 | 74 | ### Using a development build 75 | 76 | If [running tests and acceptance tests](#testing) isn't enough, it's possible to set up a local terraform configuration 77 | to use a development builds of the provider. This can be achieved by leveraging the Terraform CLI 78 | [configuration file development overrides](https://www.terraform.io/cli/config/config-file#development-overrides-for-provider-developers). 79 | 80 | First, use `make install` to place a fresh development build of the provider in your 81 | [`${GOBIN}`](https://pkg.go.dev/cmd/go#hdr-Compile_and_install_packages_and_dependencies) 82 | (defaults to `${GOPATH}/bin` or `${HOME}/go/bin` if `${GOPATH}` is not set). Repeat 83 | this every time you make changes to the provider locally. 84 | 85 | Then, setup your environment following [these instructions](https://www.terraform.io/plugin/debugging#terraform-cli-development-overrides) 86 | to make your local terraform use your local build. 87 | 88 | ### Testing GitHub Actions 89 | 90 | This project uses [GitHub Actions](https://docs.github.com/en/actions/automating-builds-and-tests) to realize its CI. 91 | 92 | Sometimes it might be helpful to locally reproduce the behaviour of those actions, 93 | and for this we use [act](https://github.com/nektos/act). Once installed, you can _simulate_ the actions executed 94 | when opening a PR with: 95 | 96 | ```shell 97 | # List of workflows for the 'pull_request' action 98 | $ act -l pull_request 99 | 100 | # Execute the workflows associated with the `pull_request' action 101 | $ act pull_request 102 | ``` 103 | 104 | ## Releasing 105 | 106 | The releasable builds are generated from the [build GH workflow](./.github/workflows/build.yml) and the release/promotion process 107 | is completed via internal HashiCorp deployment tooling. Prior to release, the changelog should be updated in `main` with 108 | the changie tool, example: 109 | 110 | ```sh 111 | changie batch 3.2.4 && changie merge 112 | ``` 113 | 114 | ## License 115 | 116 | [Mozilla Public License v2.0](./LICENSE) 117 | -------------------------------------------------------------------------------- /docs/cdktf/python/data-sources/data_source.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | 4 | # generated by https://github.com/hashicorp/terraform-plugin-docs 5 | page_title: "null_data_source Data Source - terraform-provider-null" 6 | subcategory: "" 7 | description: |- 8 | The null_data_source data source implements the standard data source lifecycle but does not 9 | interact with any external APIs. 10 | Historically, the null_data_source was typically used to construct intermediate values to re-use elsewhere in configuration. The 11 | same can now be achieved using locals https://developer.hashicorp.com/terraform/language/values/locals or the terraform_data resource type https://developer.hashicorp.com/terraform/language/resources/terraform-data in Terraform 1.4 and later. 12 | --- 13 | 14 | # null_data_source 15 | 16 | The `null_data_source` data source implements the standard data source lifecycle but does not 17 | interact with any external APIs. 18 | 19 | Historically, the `null_data_source` was typically used to construct intermediate values to re-use elsewhere in configuration. The 20 | same can now be achieved using [locals](https://developer.hashicorp.com/terraform/language/values/locals) or the [terraform_data resource type](https://developer.hashicorp.com/terraform/language/resources/terraform-data) in Terraform 1.4 and later. 21 | 22 | ## Example Usage 23 | 24 | ```python 25 | # DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 26 | from constructs import Construct 27 | from cdktf import Token, TerraformCount, Fn, TerraformOutput, TerraformStack 28 | # 29 | # Provider bindings are generated by running `cdktf get`. 30 | # See https://cdk.tf/provider-generation for more details. 31 | # 32 | from imports.aws.elb import Elb 33 | from imports.aws.instance import Instance 34 | from imports.null.data_null_data_source import DataNullDataSource 35 | class MyConvertedCode(TerraformStack): 36 | def __init__(self, scope, name): 37 | super().__init__(scope, name) 38 | # In most cases loops should be handled in the programming language context and 39 | # not inside of the Terraform context. If you are looping over something external, e.g. a variable or a file input 40 | # you should consider using a for loop. If you are looping over something only known to Terraform, e.g. a result of a data source 41 | # you need to keep this like it is. 42 | blue_count = TerraformCount.of(Token.as_number("3")) 43 | blue = Instance(self, "blue", 44 | ami="ami-0dcc1e21636832c5d", 45 | instance_type="m5.large", 46 | count=blue_count 47 | ) 48 | # In most cases loops should be handled in the programming language context and 49 | # not inside of the Terraform context. If you are looping over something external, e.g. a variable or a file input 50 | # you should consider using a for loop. If you are looping over something only known to Terraform, e.g. a result of a data source 51 | # you need to keep this like it is. 52 | green_count = TerraformCount.of(Token.as_number("3")) 53 | green = Instance(self, "green", 54 | ami="ami-0dcc1e21636832c5d", 55 | instance_type="m5.large", 56 | count=green_count 57 | ) 58 | values = DataNullDataSource(self, "values", 59 | inputs={ 60 | "all_server_ids": Token.as_string( 61 | Fn.concat([ 62 | Fn.lookup_nested(green, ["*", "id"]), 63 | Fn.lookup_nested(blue, ["*", "id"]) 64 | ])), 65 | "all_server_ips": Token.as_string( 66 | Fn.concat([ 67 | Fn.lookup_nested(green, ["*", "private_ip"]), 68 | Fn.lookup_nested(blue, ["*", "private_ip"]) 69 | ])) 70 | } 71 | ) 72 | TerraformOutput(self, "all_server_ids", 73 | value=Fn.lookup_nested(values.outputs, ["\"all_server_ids\""]) 74 | ) 75 | TerraformOutput(self, "all_server_ips", 76 | value=Fn.lookup_nested(values.outputs, ["\"all_server_ips\""]) 77 | ) 78 | Elb(self, "main", 79 | instances=Token.as_list( 80 | Fn.lookup_nested(values.outputs, ["\"all_server_ids\""])), 81 | listener=[ElbListener( 82 | instance_port=8000, 83 | instance_protocol="http", 84 | lb_port=80, 85 | lb_protocol="http" 86 | ) 87 | ] 88 | ) 89 | ``` 90 | 91 | 92 | ## Schema 93 | 94 | ### Optional 95 | 96 | - `has_computed_default` (String) If set, its literal value will be stored and returned. If not, its value defaults to `"default"`. This argument exists primarily for testing and has little practical use. 97 | - `inputs` (Map of String) A map of arbitrary strings that is copied into the `outputs` attribute, and accessible directly for interpolation. 98 | 99 | ### Read-Only 100 | 101 | - `id` (String, Deprecated) This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version. 102 | - `outputs` (Map of String) After the data source is "read", a copy of the `inputs` map. 103 | - `random` (String) A random value. This is primarily for testing and has little practical use; prefer the [hashicorp/random provider](https://registry.terraform.io/providers/hashicorp/random) for more practical random number use-cases. 104 | 105 | 106 | -------------------------------------------------------------------------------- /docs/cdktf/python/guides/terraform-migration.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "terraform_data Migration Guide" 3 | description: |- 4 | Migration guide for moving `null_resource` resources to `terraform_data` 5 | --- 6 | 7 | 8 | 9 | # terraform_data Migration Guide 10 | 11 | Terraform 1.4 introduced the [`terraform_data` managed resource](https://developer.hashicorp.com/terraform/language/resources/terraform-data) as a built-in replacement for the `null_resource` managed resource. 12 | 13 | The built-in `terraform_data` managed resource is designed similar to the `null_resource` managed resource with added benefits: 14 | 15 | * The `hashicorp/null` provider is no longer required to be downloaded and installed. 16 | * Resource replacement trigger configuration supports any value type. 17 | * Optional data storage. 18 | 19 | Use `terraform_data` instead of `null_resource` with all new Terraform configurations running on Terraform 1.4 and later. 20 | 21 | ## Migrating existing configurations 22 | 23 | -> Migrating from the `null_resource` managed resource to the `terraform_data` managed resource with the `moved` configuration block requires Terraform 1.9 and later. 24 | 25 | ### Without triggers 26 | 27 | Use the [`moved` configuration block](https://developer.hashicorp.com/terraform/language/moved) to migrate from `null_resource` to `terraform_data`. 28 | 29 | Given this example configuration with a `null_resource` managed resource: 30 | 31 | ```python 32 | # DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 33 | from cdktf import FileProvisioner 34 | from constructs import Construct 35 | from cdktf import TerraformStack 36 | # 37 | # Provider bindings are generated by running `cdktf get`. 38 | # See https://cdk.tf/provider-generation for more details. 39 | # 40 | from imports.null.resource import Resource 41 | class MyConvertedCode(TerraformStack): 42 | def __init__(self, scope, name): 43 | super().__init__(scope, name) 44 | Resource(self, "example", 45 | provisioners=[FileProvisioner( 46 | type="local-exec", 47 | command="echo 'Hello, World!'" 48 | ) 49 | ] 50 | ) 51 | ``` 52 | 53 | Replace this configuration with a `terraform_data` managed resource and `moved` configuration: 54 | 55 | ```python 56 | # DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 57 | from cdktf import FileProvisioner 58 | from constructs import Construct 59 | from cdktf import DataResource, TerraformStack 60 | class MyConvertedCode(TerraformStack): 61 | def __init__(self, scope, name): 62 | super().__init__(scope, name) 63 | DataResource(self, "example", 64 | provisioners=[FileProvisioner( 65 | type="local-exec", 66 | command="echo 'Hello, World!'" 67 | ) 68 | ] 69 | ) 70 | ``` 71 | 72 | Run a plan operation, such as `terraform plan`, to verify that the move will occur as expected. 73 | 74 | Example output with no changes: 75 | 76 | ```console 77 | $ terraform plan 78 | terraform_data.example: Refreshing state... [id=892002337455008838] 79 | 80 | Terraform will perform the following actions: 81 | 82 | # null_resource.example has moved to terraform_data.example 83 | resource "terraform_data" "example" { 84 | id = "892002337455008838" 85 | } 86 | 87 | Plan: 0 to add, 0 to change, 0 to destroy. 88 | ``` 89 | 90 | Run an apply operation, such as `terraform apply`, to move the resource and complete the migration. Remove the `moved` configuration block at any time afterwards. 91 | 92 | ### With triggers 93 | 94 | Use the [`moved` configuration block](https://developer.hashicorp.com/terraform/language/moved) to migrate from `null_resource` to `terraform_data`. Replace the `null_resource` managed resource `triggers` argument with the `terraform_data` managed resource `triggers_replace` argument when moving. 95 | 96 | Given this example configuration with a `null_resource` managed resource that includes the `triggers` argument: 97 | 98 | ```python 99 | # DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 100 | from cdktf import FileProvisioner 101 | from constructs import Construct 102 | from cdktf import TerraformStack 103 | # 104 | # Provider bindings are generated by running `cdktf get`. 105 | # See https://cdk.tf/provider-generation for more details. 106 | # 107 | from imports.null.resource import Resource 108 | class MyConvertedCode(TerraformStack): 109 | def __init__(self, scope, name): 110 | super().__init__(scope, name) 111 | Resource(self, "example", 112 | triggers=[{ 113 | "examplekey": "examplevalue" 114 | } 115 | ], 116 | provisioners=[FileProvisioner( 117 | type="local-exec", 118 | command="echo 'Hello, World!'" 119 | ) 120 | ] 121 | ) 122 | ``` 123 | 124 | Replace this configuration with the following `terraform_data` managed resource and `moved` configuration: 125 | 126 | ```python 127 | # DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 128 | from cdktf import FileProvisioner 129 | from constructs import Construct 130 | from cdktf import DataResource, TerraformStack 131 | class MyConvertedCode(TerraformStack): 132 | def __init__(self, scope, name): 133 | super().__init__(scope, name) 134 | DataResource(self, "example", 135 | triggers_replace=[{ 136 | "examplekey": "examplevalue" 137 | } 138 | ], 139 | provisioners=[FileProvisioner( 140 | type="local-exec", 141 | command="echo 'Hello, World!'" 142 | ) 143 | ] 144 | ) 145 | ``` 146 | 147 | Run a plan operation, such as `terraform plan`, to verify that the move will occur as expected. 148 | 149 | Example output with no changes: 150 | 151 | ```console 152 | $ terraform plan 153 | terraform_data.example: Refreshing state... [id=1651348367769440250] 154 | 155 | Terraform will perform the following actions: 156 | 157 | # null_resource.example has moved to terraform_data.example 158 | resource "terraform_data" "example" { 159 | id = "1651348367769440250" 160 | # (1 unchanged attribute hidden) 161 | } 162 | 163 | Plan: 0 to add, 0 to change, 0 to destroy. 164 | ``` 165 | 166 | Run an apply operation, such as `terraform apply`, to move the resource and complete the migration. Remove the `moved` configuration block at any time afterwards. 167 | 168 | -------------------------------------------------------------------------------- /docs/cdktf/python/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "Provider: Null" 3 | description: |- 4 | The null provider provides no-op constructs that can be useful helpers in tricky cases. 5 | --- 6 | 7 | 8 | 9 | # Null Provider 10 | 11 | The `null` provider is a rather-unusual provider that has constructs that 12 | intentionally do nothing. This may sound strange, and indeed these constructs 13 | do not need to be used in most cases, but they can be useful in various 14 | situations to help orchestrate tricky behavior or work around limitations. 15 | 16 | The documentation of each feature of this provider, accessible via the 17 | navigation, gives examples of situations where these constructs may prove 18 | useful. 19 | 20 | Usage of the `null` provider can make a Terraform configuration harder to 21 | understand. While it can be useful in certain cases, it should be applied with 22 | care and other solutions preferred when available. 23 | 24 | 25 | ## Schema 26 | 27 | -------------------------------------------------------------------------------- /docs/cdktf/python/resources/resource.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | 4 | # generated by https://github.com/hashicorp/terraform-plugin-docs 5 | page_title: "null_resource Resource - terraform-provider-null" 6 | subcategory: "" 7 | description: |- 8 | The null_resource resource implements the standard resource lifecycle but takes no further action. On Terraform 1.4 and later, use the terraform_data resource type https://developer.hashicorp.com/terraform/language/resources/terraform-data instead. Terraform 1.9 and later support the moved configuration block from null_resource to terraform_data. 9 | The triggers argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced. 10 | --- 11 | 12 | # null_resource 13 | 14 | The `null_resource` resource implements the standard resource lifecycle but takes no further action. On Terraform 1.4 and later, use the [`terraform_data` resource type](https://developer.hashicorp.com/terraform/language/resources/terraform-data) instead. Terraform 1.9 and later support the `moved` configuration block from `null_resource` to `terraform_data`. 15 | 16 | The `triggers` argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced. 17 | 18 | ## Example Usage 19 | 20 | ```python 21 | # DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 22 | from cdktf import SSHProvisionerConnection, FileProvisioner 23 | from constructs import Construct 24 | from cdktf import Token, TerraformCount, Fn, TerraformStack 25 | # 26 | # Provider bindings are generated by running `cdktf get`. 27 | # See https://cdk.tf/provider-generation for more details. 28 | # 29 | from imports.null.resource import Resource 30 | from imports.aws.instance import Instance 31 | class MyConvertedCode(TerraformStack): 32 | def __init__(self, scope, name): 33 | super().__init__(scope, name) 34 | # In most cases loops should be handled in the programming language context and 35 | # not inside of the Terraform context. If you are looping over something external, e.g. a variable or a file input 36 | # you should consider using a for loop. If you are looping over something only known to Terraform, e.g. a result of a data source 37 | # you need to keep this like it is. 38 | cluster_count = TerraformCount.of(Token.as_number("3")) 39 | cluster = Instance(self, "cluster", 40 | ami="ami-0dcc1e21636832c5d", 41 | instance_type="m5.large", 42 | count=cluster_count 43 | ) 44 | null_provider_resource_cluster = Resource(self, "cluster_1", 45 | connection=SSHProvisionerConnection( 46 | host=Fn.element(Fn.lookup_nested(cluster, ["*", "public_ip"]), 0) 47 | ), 48 | triggers=[{ 49 | "cluster_instance_ids": Fn.join(",", 50 | Token.as_list(Fn.lookup_nested(cluster, ["*", "id"]))) 51 | } 52 | ], 53 | provisioners=[FileProvisioner( 54 | type="remote-exec", 55 | inline=["bootstrap-cluster.sh " + 56 | Token.as_string( 57 | Fn.join(" ", 58 | Token.as_list(Fn.lookup_nested(cluster, ["*", "private_ip"])))) 59 | ] 60 | ) 61 | ] 62 | ) 63 | # This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match. 64 | null_provider_resource_cluster.override_logical_id("cluster") 65 | ``` 66 | 67 | 68 | ## Schema 69 | 70 | ### Optional 71 | 72 | - `triggers` (Map of String) A map of arbitrary strings that, when changed, will force the null resource to be replaced, re-running any associated provisioners. 73 | 74 | ### Read-Only 75 | 76 | - `id` (String) This is set to a random value at create time. 77 | 78 | 79 | -------------------------------------------------------------------------------- /docs/cdktf/typescript/data-sources/data_source.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | 4 | # generated by https://github.com/hashicorp/terraform-plugin-docs 5 | page_title: "null_data_source Data Source - terraform-provider-null" 6 | subcategory: "" 7 | description: |- 8 | The null_data_source data source implements the standard data source lifecycle but does not 9 | interact with any external APIs. 10 | Historically, the null_data_source was typically used to construct intermediate values to re-use elsewhere in configuration. The 11 | same can now be achieved using locals https://developer.hashicorp.com/terraform/language/values/locals or the terraform_data resource type https://developer.hashicorp.com/terraform/language/resources/terraform-data in Terraform 1.4 and later. 12 | --- 13 | 14 | # null_data_source 15 | 16 | The `null_data_source` data source implements the standard data source lifecycle but does not 17 | interact with any external APIs. 18 | 19 | Historically, the `null_data_source` was typically used to construct intermediate values to re-use elsewhere in configuration. The 20 | same can now be achieved using [locals](https://developer.hashicorp.com/terraform/language/values/locals) or the [terraform_data resource type](https://developer.hashicorp.com/terraform/language/resources/terraform-data) in Terraform 1.4 and later. 21 | 22 | ## Example Usage 23 | 24 | ```typescript 25 | // DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 26 | import { Construct } from "constructs"; 27 | import { 28 | Token, 29 | TerraformCount, 30 | Fn, 31 | TerraformOutput, 32 | TerraformStack, 33 | } from "cdktf"; 34 | /* 35 | * Provider bindings are generated by running `cdktf get`. 36 | * See https://cdk.tf/provider-generation for more details. 37 | */ 38 | import { Elb } from "./.gen/providers/aws/elb"; 39 | import { Instance } from "./.gen/providers/aws/instance"; 40 | import { DataNullDataSource } from "./.gen/providers/null/data-null-data-source"; 41 | class MyConvertedCode extends TerraformStack { 42 | constructor(scope: Construct, name: string) { 43 | super(scope, name); 44 | /*In most cases loops should be handled in the programming language context and 45 | not inside of the Terraform context. If you are looping over something external, e.g. a variable or a file input 46 | you should consider using a for loop. If you are looping over something only known to Terraform, e.g. a result of a data source 47 | you need to keep this like it is.*/ 48 | const blueCount = TerraformCount.of(Token.asNumber("3")); 49 | const blue = new Instance(this, "blue", { 50 | ami: "ami-0dcc1e21636832c5d", 51 | instanceType: "m5.large", 52 | count: blueCount, 53 | }); 54 | /*In most cases loops should be handled in the programming language context and 55 | not inside of the Terraform context. If you are looping over something external, e.g. a variable or a file input 56 | you should consider using a for loop. If you are looping over something only known to Terraform, e.g. a result of a data source 57 | you need to keep this like it is.*/ 58 | const greenCount = TerraformCount.of(Token.asNumber("3")); 59 | const green = new Instance(this, "green", { 60 | ami: "ami-0dcc1e21636832c5d", 61 | instanceType: "m5.large", 62 | count: greenCount, 63 | }); 64 | const values = new DataNullDataSource(this, "values", { 65 | inputs: { 66 | all_server_ids: Token.asString( 67 | Fn.concat([ 68 | Fn.lookupNested(green, ["*", "id"]), 69 | Fn.lookupNested(blue, ["*", "id"]), 70 | ]) 71 | ), 72 | all_server_ips: Token.asString( 73 | Fn.concat([ 74 | Fn.lookupNested(green, ["*", "private_ip"]), 75 | Fn.lookupNested(blue, ["*", "private_ip"]), 76 | ]) 77 | ), 78 | }, 79 | }); 80 | new TerraformOutput(this, "all_server_ids", { 81 | value: Fn.lookupNested(values.outputs, ['"all_server_ids"']), 82 | }); 83 | new TerraformOutput(this, "all_server_ips", { 84 | value: Fn.lookupNested(values.outputs, ['"all_server_ips"']), 85 | }); 86 | new Elb(this, "main", { 87 | instances: Token.asList( 88 | Fn.lookupNested(values.outputs, ['"all_server_ids"']) 89 | ), 90 | listener: [ 91 | { 92 | instancePort: 8000, 93 | instanceProtocol: "http", 94 | lbPort: 80, 95 | lbProtocol: "http", 96 | }, 97 | ], 98 | }); 99 | } 100 | } 101 | 102 | ``` 103 | 104 | 105 | ## Schema 106 | 107 | ### Optional 108 | 109 | - `hasComputedDefault` (String) If set, its literal value will be stored and returned. If not, its value defaults to `"default"`. This argument exists primarily for testing and has little practical use. 110 | - `inputs` (Map of String) A map of arbitrary strings that is copied into the `outputs` attribute, and accessible directly for interpolation. 111 | 112 | ### Read-Only 113 | 114 | - `id` (String, Deprecated) This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version. 115 | - `outputs` (Map of String) After the data source is "read", a copy of the `inputs` map. 116 | - `random` (String) A random value. This is primarily for testing and has little practical use; prefer the [hashicorp/random provider](https://registry.terraform.io/providers/hashicorp/random) for more practical random number use-cases. 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/cdktf/typescript/guides/terraform-migration.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "terraform_data Migration Guide" 3 | description: |- 4 | Migration guide for moving `null_resource` resources to `terraform_data` 5 | --- 6 | 7 | 8 | 9 | # terraform_data Migration Guide 10 | 11 | Terraform 1.4 introduced the [`terraform_data` managed resource](https://developer.hashicorp.com/terraform/language/resources/terraform-data) as a built-in replacement for the `null_resource` managed resource. 12 | 13 | The built-in `terraform_data` managed resource is designed similar to the `null_resource` managed resource with added benefits: 14 | 15 | * The `hashicorp/null` provider is no longer required to be downloaded and installed. 16 | * Resource replacement trigger configuration supports any value type. 17 | * Optional data storage. 18 | 19 | Use `terraform_data` instead of `null_resource` with all new Terraform configurations running on Terraform 1.4 and later. 20 | 21 | ## Migrating existing configurations 22 | 23 | -> Migrating from the `null_resource` managed resource to the `terraform_data` managed resource with the `moved` configuration block requires Terraform 1.9 and later. 24 | 25 | ### Without triggers 26 | 27 | Use the [`moved` configuration block](https://developer.hashicorp.com/terraform/language/moved) to migrate from `null_resource` to `terraform_data`. 28 | 29 | Given this example configuration with a `null_resource` managed resource: 30 | 31 | ```typescript 32 | // DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 33 | import { Construct } from "constructs"; 34 | import { TerraformStack } from "cdktf"; 35 | /* 36 | * Provider bindings are generated by running `cdktf get`. 37 | * See https://cdk.tf/provider-generation for more details. 38 | */ 39 | import { Resource } from "./.gen/providers/null/resource"; 40 | class MyConvertedCode extends TerraformStack { 41 | constructor(scope: Construct, name: string) { 42 | super(scope, name); 43 | new Resource(this, "example", { 44 | provisioners: [ 45 | { 46 | type: "local-exec", 47 | command: "echo 'Hello, World!'", 48 | }, 49 | ], 50 | }); 51 | } 52 | } 53 | 54 | ``` 55 | 56 | Replace this configuration with a `terraform_data` managed resource and `moved` configuration: 57 | 58 | ```typescript 59 | // DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 60 | import { Construct } from "constructs"; 61 | import { DataResource, TerraformStack } from "cdktf"; 62 | class MyConvertedCode extends TerraformStack { 63 | constructor(scope: Construct, name: string) { 64 | super(scope, name); 65 | new DataResource(this, "example", { 66 | provisioners: [ 67 | { 68 | type: "local-exec", 69 | command: "echo 'Hello, World!'", 70 | }, 71 | ], 72 | }); 73 | } 74 | } 75 | 76 | ``` 77 | 78 | Run a plan operation, such as `terraform plan`, to verify that the move will occur as expected. 79 | 80 | Example output with no changes: 81 | 82 | ```console 83 | $ terraform plan 84 | terraform_data.example: Refreshing state... [id=892002337455008838] 85 | 86 | Terraform will perform the following actions: 87 | 88 | # null_resource.example has moved to terraform_data.example 89 | resource "terraform_data" "example" { 90 | id = "892002337455008838" 91 | } 92 | 93 | Plan: 0 to add, 0 to change, 0 to destroy. 94 | ``` 95 | 96 | Run an apply operation, such as `terraform apply`, to move the resource and complete the migration. Remove the `moved` configuration block at any time afterwards. 97 | 98 | ### With triggers 99 | 100 | Use the [`moved` configuration block](https://developer.hashicorp.com/terraform/language/moved) to migrate from `null_resource` to `terraform_data`. Replace the `null_resource` managed resource `triggers` argument with the `terraform_data` managed resource `triggers_replace` argument when moving. 101 | 102 | Given this example configuration with a `null_resource` managed resource that includes the `triggers` argument: 103 | 104 | ```typescript 105 | // DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 106 | import { Construct } from "constructs"; 107 | import { TerraformStack } from "cdktf"; 108 | /* 109 | * Provider bindings are generated by running `cdktf get`. 110 | * See https://cdk.tf/provider-generation for more details. 111 | */ 112 | import { Resource } from "./.gen/providers/null/resource"; 113 | class MyConvertedCode extends TerraformStack { 114 | constructor(scope: Construct, name: string) { 115 | super(scope, name); 116 | new Resource(this, "example", { 117 | triggers: [ 118 | { 119 | examplekey: "examplevalue", 120 | }, 121 | ], 122 | provisioners: [ 123 | { 124 | type: "local-exec", 125 | command: "echo 'Hello, World!'", 126 | }, 127 | ], 128 | }); 129 | } 130 | } 131 | 132 | ``` 133 | 134 | Replace this configuration with the following `terraform_data` managed resource and `moved` configuration: 135 | 136 | ```typescript 137 | // DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 138 | import { Construct } from "constructs"; 139 | import { DataResource, TerraformStack } from "cdktf"; 140 | class MyConvertedCode extends TerraformStack { 141 | constructor(scope: Construct, name: string) { 142 | super(scope, name); 143 | new DataResource(this, "example", { 144 | triggers_replace: [ 145 | { 146 | examplekey: "examplevalue", 147 | }, 148 | ], 149 | provisioners: [ 150 | { 151 | type: "local-exec", 152 | command: "echo 'Hello, World!'", 153 | }, 154 | ], 155 | }); 156 | } 157 | } 158 | 159 | ``` 160 | 161 | Run a plan operation, such as `terraform plan`, to verify that the move will occur as expected. 162 | 163 | Example output with no changes: 164 | 165 | ```console 166 | $ terraform plan 167 | terraform_data.example: Refreshing state... [id=1651348367769440250] 168 | 169 | Terraform will perform the following actions: 170 | 171 | # null_resource.example has moved to terraform_data.example 172 | resource "terraform_data" "example" { 173 | id = "1651348367769440250" 174 | # (1 unchanged attribute hidden) 175 | } 176 | 177 | Plan: 0 to add, 0 to change, 0 to destroy. 178 | ``` 179 | 180 | Run an apply operation, such as `terraform apply`, to move the resource and complete the migration. Remove the `moved` configuration block at any time afterwards. 181 | 182 | -------------------------------------------------------------------------------- /docs/cdktf/typescript/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "Provider: Null" 3 | description: |- 4 | The null provider provides no-op constructs that can be useful helpers in tricky cases. 5 | --- 6 | 7 | 8 | 9 | # Null Provider 10 | 11 | The `null` provider is a rather-unusual provider that has constructs that 12 | intentionally do nothing. This may sound strange, and indeed these constructs 13 | do not need to be used in most cases, but they can be useful in various 14 | situations to help orchestrate tricky behavior or work around limitations. 15 | 16 | The documentation of each feature of this provider, accessible via the 17 | navigation, gives examples of situations where these constructs may prove 18 | useful. 19 | 20 | Usage of the `null` provider can make a Terraform configuration harder to 21 | understand. While it can be useful in certain cases, it should be applied with 22 | care and other solutions preferred when available. 23 | 24 | 25 | ## Schema 26 | 27 | -------------------------------------------------------------------------------- /docs/cdktf/typescript/resources/resource.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | 4 | # generated by https://github.com/hashicorp/terraform-plugin-docs 5 | page_title: "null_resource Resource - terraform-provider-null" 6 | subcategory: "" 7 | description: |- 8 | The null_resource resource implements the standard resource lifecycle but takes no further action. On Terraform 1.4 and later, use the terraform_data resource type https://developer.hashicorp.com/terraform/language/resources/terraform-data instead. Terraform 1.9 and later support the moved configuration block from null_resource to terraform_data. 9 | The triggers argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced. 10 | --- 11 | 12 | # null_resource 13 | 14 | The `null_resource` resource implements the standard resource lifecycle but takes no further action. On Terraform 1.4 and later, use the [`terraform_data` resource type](https://developer.hashicorp.com/terraform/language/resources/terraform-data) instead. Terraform 1.9 and later support the `moved` configuration block from `null_resource` to `terraform_data`. 15 | 16 | The `triggers` argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced. 17 | 18 | ## Example Usage 19 | 20 | ```typescript 21 | // DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug 22 | import { Construct } from "constructs"; 23 | import { Token, TerraformCount, Fn, TerraformStack } from "cdktf"; 24 | /* 25 | * Provider bindings are generated by running `cdktf get`. 26 | * See https://cdk.tf/provider-generation for more details. 27 | */ 28 | import { Resource } from "./.gen/providers/null/resource"; 29 | import { Instance } from "./.gen/providers/aws/instance"; 30 | class MyConvertedCode extends TerraformStack { 31 | constructor(scope: Construct, name: string) { 32 | super(scope, name); 33 | /*In most cases loops should be handled in the programming language context and 34 | not inside of the Terraform context. If you are looping over something external, e.g. a variable or a file input 35 | you should consider using a for loop. If you are looping over something only known to Terraform, e.g. a result of a data source 36 | you need to keep this like it is.*/ 37 | const clusterCount = TerraformCount.of(Token.asNumber("3")); 38 | const cluster = new Instance(this, "cluster", { 39 | ami: "ami-0dcc1e21636832c5d", 40 | instanceType: "m5.large", 41 | count: clusterCount, 42 | }); 43 | const nullProviderResourceCluster = new Resource(this, "cluster_1", { 44 | connection: { 45 | host: Fn.element(Fn.lookupNested(cluster, ["*", "public_ip"]), 0), 46 | }, 47 | triggers: [ 48 | { 49 | cluster_instance_ids: Fn.join( 50 | ",", 51 | Token.asList(Fn.lookupNested(cluster, ["*", "id"])) 52 | ), 53 | }, 54 | ], 55 | provisioners: [ 56 | { 57 | type: "remote-exec", 58 | inline: [ 59 | "bootstrap-cluster.sh " + 60 | Token.asString( 61 | Fn.join( 62 | " ", 63 | Token.asList(Fn.lookupNested(cluster, ["*", "private_ip"])) 64 | ) 65 | ), 66 | ], 67 | }, 68 | ], 69 | }); 70 | /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ 71 | nullProviderResourceCluster.overrideLogicalId("cluster"); 72 | } 73 | } 74 | 75 | ``` 76 | 77 | 78 | ## Schema 79 | 80 | ### Optional 81 | 82 | - `triggers` (Map of String) A map of arbitrary strings that, when changed, will force the null resource to be replaced, re-running any associated provisioners. 83 | 84 | ### Read-Only 85 | 86 | - `id` (String) This is set to a random value at create time. 87 | 88 | 89 | -------------------------------------------------------------------------------- /docs/data-sources/data_source.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "null_data_source Data Source - terraform-provider-null" 4 | subcategory: "" 5 | description: |- 6 | The null_data_source data source implements the standard data source lifecycle but does not 7 | interact with any external APIs. 8 | Historically, the null_data_source was typically used to construct intermediate values to re-use elsewhere in configuration. The 9 | same can now be achieved using locals https://developer.hashicorp.com/terraform/language/values/locals or the terraform_data resource type https://developer.hashicorp.com/terraform/language/resources/terraform-data in Terraform 1.4 and later. 10 | --- 11 | 12 | # null_data_source 13 | 14 | The `null_data_source` data source implements the standard data source lifecycle but does not 15 | interact with any external APIs. 16 | 17 | Historically, the `null_data_source` was typically used to construct intermediate values to re-use elsewhere in configuration. The 18 | same can now be achieved using [locals](https://developer.hashicorp.com/terraform/language/values/locals) or the [terraform_data resource type](https://developer.hashicorp.com/terraform/language/resources/terraform-data) in Terraform 1.4 and later. 19 | 20 | ## Example Usage 21 | 22 | ```terraform 23 | resource "aws_instance" "green" { 24 | count = 3 25 | ami = "ami-0dcc1e21636832c5d" 26 | instance_type = "m5.large" 27 | 28 | # ... 29 | } 30 | 31 | resource "aws_instance" "blue" { 32 | count = 3 33 | ami = "ami-0dcc1e21636832c5d" 34 | instance_type = "m5.large" 35 | 36 | # ... 37 | } 38 | 39 | data "null_data_source" "values" { 40 | inputs = { 41 | all_server_ids = concat( 42 | aws_instance.green[*].id, 43 | aws_instance.blue[*].id, 44 | ) 45 | all_server_ips = concat( 46 | aws_instance.green[*].private_ip, 47 | aws_instance.blue[*].private_ip, 48 | ) 49 | } 50 | } 51 | 52 | resource "aws_elb" "main" { 53 | instances = data.null_data_source.values.outputs["all_server_ids"] 54 | 55 | # ... 56 | listener { 57 | instance_port = 8000 58 | instance_protocol = "http" 59 | lb_port = 80 60 | lb_protocol = "http" 61 | } 62 | } 63 | 64 | output "all_server_ids" { 65 | value = data.null_data_source.values.outputs["all_server_ids"] 66 | } 67 | 68 | output "all_server_ips" { 69 | value = data.null_data_source.values.outputs["all_server_ips"] 70 | } 71 | ``` 72 | 73 | 74 | ## Schema 75 | 76 | ### Optional 77 | 78 | - `has_computed_default` (String) If set, its literal value will be stored and returned. If not, its value defaults to `"default"`. This argument exists primarily for testing and has little practical use. 79 | - `inputs` (Map of String) A map of arbitrary strings that is copied into the `outputs` attribute, and accessible directly for interpolation. 80 | 81 | ### Read-Only 82 | 83 | - `id` (String, Deprecated) This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version. 84 | - `outputs` (Map of String) After the data source is "read", a copy of the `inputs` map. 85 | - `random` (String) A random value. This is primarily for testing and has little practical use; prefer the [hashicorp/random provider](https://registry.terraform.io/providers/hashicorp/random) for more practical random number use-cases. 86 | 87 | -------------------------------------------------------------------------------- /docs/guides/terraform-migration.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "terraform_data Migration Guide" 3 | description: |- 4 | Migration guide for moving `null_resource` resources to `terraform_data` 5 | --- 6 | 7 | # terraform_data Migration Guide 8 | 9 | Terraform 1.4 introduced the [`terraform_data` managed resource](https://developer.hashicorp.com/terraform/language/resources/terraform-data) as a built-in replacement for the `null_resource` managed resource. 10 | 11 | The built-in `terraform_data` managed resource is designed similar to the `null_resource` managed resource with added benefits: 12 | 13 | * The `hashicorp/null` provider is no longer required to be downloaded and installed. 14 | * Resource replacement trigger configuration supports any value type. 15 | * Optional data storage. 16 | 17 | Use `terraform_data` instead of `null_resource` with all new Terraform configurations running on Terraform 1.4 and later. 18 | 19 | ## Migrating existing configurations 20 | 21 | -> Migrating from the `null_resource` managed resource to the `terraform_data` managed resource with the `moved` configuration block requires Terraform 1.9 and later. 22 | 23 | ### Without triggers 24 | 25 | Use the [`moved` configuration block](https://developer.hashicorp.com/terraform/language/moved) to migrate from `null_resource` to `terraform_data`. 26 | 27 | Given this example configuration with a `null_resource` managed resource: 28 | 29 | ```terraform 30 | resource "null_resource" "example" { 31 | provisioner "local-exec" { 32 | command = "echo 'Hello, World!'" 33 | } 34 | } 35 | ``` 36 | 37 | Replace this configuration with a `terraform_data` managed resource and `moved` configuration: 38 | 39 | ```terraform 40 | resource "terraform_data" "example" { 41 | provisioner "local-exec" { 42 | command = "echo 'Hello, World!'" 43 | } 44 | } 45 | 46 | moved { 47 | from = null_resource.example 48 | to = terraform_data.example 49 | } 50 | ``` 51 | 52 | Run a plan operation, such as `terraform plan`, to verify that the move will occur as expected. 53 | 54 | Example output with no changes: 55 | 56 | ```console 57 | $ terraform plan 58 | terraform_data.example: Refreshing state... [id=892002337455008838] 59 | 60 | Terraform will perform the following actions: 61 | 62 | # null_resource.example has moved to terraform_data.example 63 | resource "terraform_data" "example" { 64 | id = "892002337455008838" 65 | } 66 | 67 | Plan: 0 to add, 0 to change, 0 to destroy. 68 | ``` 69 | 70 | Run an apply operation, such as `terraform apply`, to move the resource and complete the migration. Remove the `moved` configuration block at any time afterwards. 71 | 72 | ### With triggers 73 | 74 | Use the [`moved` configuration block](https://developer.hashicorp.com/terraform/language/moved) to migrate from `null_resource` to `terraform_data`. Replace the `null_resource` managed resource `triggers` argument with the `terraform_data` managed resource `triggers_replace` argument when moving. 75 | 76 | Given this example configuration with a `null_resource` managed resource that includes the `triggers` argument: 77 | 78 | ```terraform 79 | resource "null_resource" "example" { 80 | triggers = { 81 | examplekey = "examplevalue" 82 | } 83 | 84 | provisioner "local-exec" { 85 | command = "echo 'Hello, World!'" 86 | } 87 | } 88 | ``` 89 | 90 | Replace this configuration with the following `terraform_data` managed resource and `moved` configuration: 91 | 92 | ```terraform 93 | resource "terraform_data" "example" { 94 | triggers_replace = { 95 | examplekey = "examplevalue" 96 | } 97 | 98 | provisioner "local-exec" { 99 | command = "echo 'Hello, World!'" 100 | } 101 | } 102 | 103 | moved { 104 | from = null_resource.example 105 | to = terraform_data.example 106 | } 107 | ``` 108 | 109 | Run a plan operation, such as `terraform plan`, to verify that the move will occur as expected. 110 | 111 | Example output with no changes: 112 | 113 | ```console 114 | $ terraform plan 115 | terraform_data.example: Refreshing state... [id=1651348367769440250] 116 | 117 | Terraform will perform the following actions: 118 | 119 | # null_resource.example has moved to terraform_data.example 120 | resource "terraform_data" "example" { 121 | id = "1651348367769440250" 122 | # (1 unchanged attribute hidden) 123 | } 124 | 125 | Plan: 0 to add, 0 to change, 0 to destroy. 126 | ``` 127 | 128 | Run an apply operation, such as `terraform apply`, to move the resource and complete the migration. Remove the `moved` configuration block at any time afterwards. 129 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "Provider: Null" 3 | description: |- 4 | The null provider provides no-op constructs that can be useful helpers in tricky cases. 5 | --- 6 | 7 | # Null Provider 8 | 9 | The `null` provider is a rather-unusual provider that has constructs that 10 | intentionally do nothing. This may sound strange, and indeed these constructs 11 | do not need to be used in most cases, but they can be useful in various 12 | situations to help orchestrate tricky behavior or work around limitations. 13 | 14 | The documentation of each feature of this provider, accessible via the 15 | navigation, gives examples of situations where these constructs may prove 16 | useful. 17 | 18 | Usage of the `null` provider can make a Terraform configuration harder to 19 | understand. While it can be useful in certain cases, it should be applied with 20 | care and other solutions preferred when available. 21 | 22 | 23 | ## Schema 24 | -------------------------------------------------------------------------------- /docs/resources/resource.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "null_resource Resource - terraform-provider-null" 4 | subcategory: "" 5 | description: |- 6 | The null_resource resource implements the standard resource lifecycle but takes no further action. On Terraform 1.4 and later, use the terraform_data resource type https://developer.hashicorp.com/terraform/language/resources/terraform-data instead. Terraform 1.9 and later support the moved configuration block from null_resource to terraform_data. 7 | The triggers argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced. 8 | --- 9 | 10 | # null_resource 11 | 12 | The `null_resource` resource implements the standard resource lifecycle but takes no further action. On Terraform 1.4 and later, use the [`terraform_data` resource type](https://developer.hashicorp.com/terraform/language/resources/terraform-data) instead. Terraform 1.9 and later support the `moved` configuration block from `null_resource` to `terraform_data`. 13 | 14 | The `triggers` argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced. 15 | 16 | ## Example Usage 17 | 18 | ```terraform 19 | resource "aws_instance" "cluster" { 20 | count = 3 21 | ami = "ami-0dcc1e21636832c5d" 22 | instance_type = "m5.large" 23 | 24 | # ... 25 | } 26 | 27 | # The primary use-case for the null resource is as a do-nothing container 28 | # for arbitrary actions taken by a provisioner. 29 | # 30 | # In this example, three EC2 instances are created and then a 31 | # null_resource instance is used to gather data about all three 32 | # and execute a single action that affects them all. Due to the triggers 33 | # map, the null_resource will be replaced each time the instance ids 34 | # change, and thus the remote-exec provisioner will be re-run. 35 | resource "null_resource" "cluster" { 36 | # Changes to any instance of the cluster requires re-provisioning 37 | triggers = { 38 | cluster_instance_ids = join(",", aws_instance.cluster[*].id) 39 | } 40 | 41 | # Bootstrap script can run on any instance of the cluster 42 | # So we just choose the first in this case 43 | connection { 44 | host = element(aws_instance.cluster[*].public_ip, 0) 45 | } 46 | 47 | provisioner "remote-exec" { 48 | # Bootstrap script called with private_ip of each node in the cluster 49 | inline = [ 50 | "bootstrap-cluster.sh ${join(" ", 51 | aws_instance.cluster[*].private_ip)}", 52 | ] 53 | } 54 | } 55 | ``` 56 | 57 | 58 | ## Schema 59 | 60 | ### Optional 61 | 62 | - `triggers` (Map of String) A map of arbitrary strings that, when changed, will force the null resource to be replaced, re-running any associated provisioners. 63 | 64 | ### Read-Only 65 | 66 | - `id` (String) This is set to a random value at create time. 67 | 68 | -------------------------------------------------------------------------------- /examples/data-sources/null_data_source/data-source.tf: -------------------------------------------------------------------------------- 1 | resource "aws_instance" "green" { 2 | count = 3 3 | ami = "ami-0dcc1e21636832c5d" 4 | instance_type = "m5.large" 5 | 6 | # ... 7 | } 8 | 9 | resource "aws_instance" "blue" { 10 | count = 3 11 | ami = "ami-0dcc1e21636832c5d" 12 | instance_type = "m5.large" 13 | 14 | # ... 15 | } 16 | 17 | data "null_data_source" "values" { 18 | inputs = { 19 | all_server_ids = concat( 20 | aws_instance.green[*].id, 21 | aws_instance.blue[*].id, 22 | ) 23 | all_server_ips = concat( 24 | aws_instance.green[*].private_ip, 25 | aws_instance.blue[*].private_ip, 26 | ) 27 | } 28 | } 29 | 30 | resource "aws_elb" "main" { 31 | instances = data.null_data_source.values.outputs["all_server_ids"] 32 | 33 | # ... 34 | listener { 35 | instance_port = 8000 36 | instance_protocol = "http" 37 | lb_port = 80 38 | lb_protocol = "http" 39 | } 40 | } 41 | 42 | output "all_server_ids" { 43 | value = data.null_data_source.values.outputs["all_server_ids"] 44 | } 45 | 46 | output "all_server_ips" { 47 | value = data.null_data_source.values.outputs["all_server_ips"] 48 | } 49 | -------------------------------------------------------------------------------- /examples/resources/null_resource/resource.tf: -------------------------------------------------------------------------------- 1 | resource "aws_instance" "cluster" { 2 | count = 3 3 | ami = "ami-0dcc1e21636832c5d" 4 | instance_type = "m5.large" 5 | 6 | # ... 7 | } 8 | 9 | # The primary use-case for the null resource is as a do-nothing container 10 | # for arbitrary actions taken by a provisioner. 11 | # 12 | # In this example, three EC2 instances are created and then a 13 | # null_resource instance is used to gather data about all three 14 | # and execute a single action that affects them all. Due to the triggers 15 | # map, the null_resource will be replaced each time the instance ids 16 | # change, and thus the remote-exec provisioner will be re-run. 17 | resource "null_resource" "cluster" { 18 | # Changes to any instance of the cluster requires re-provisioning 19 | triggers = { 20 | cluster_instance_ids = join(",", aws_instance.cluster[*].id) 21 | } 22 | 23 | # Bootstrap script can run on any instance of the cluster 24 | # So we just choose the first in this case 25 | connection { 26 | host = element(aws_instance.cluster[*].public_ip, 0) 27 | } 28 | 29 | provisioner "remote-exec" { 30 | # Bootstrap script called with private_ip of each node in the cluster 31 | inline = [ 32 | "bootstrap-cluster.sh ${join(" ", 33 | aws_instance.cluster[*].private_ip)}", 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/terraform-providers/terraform-provider-null 2 | 3 | go 1.23.7 4 | 5 | require ( 6 | github.com/hashicorp/terraform-plugin-framework v1.15.0 7 | github.com/hashicorp/terraform-plugin-go v0.28.0 8 | github.com/hashicorp/terraform-plugin-testing v1.13.1 9 | ) 10 | 11 | require ( 12 | github.com/ProtonMail/go-crypto v1.1.6 // indirect 13 | github.com/agext/levenshtein v1.2.2 // indirect 14 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 15 | github.com/cloudflare/circl v1.6.0 // indirect 16 | github.com/fatih/color v1.16.0 // indirect 17 | github.com/golang/protobuf v1.5.4 // indirect 18 | github.com/google/go-cmp v0.7.0 // indirect 19 | github.com/hashicorp/errwrap v1.1.0 // indirect 20 | github.com/hashicorp/go-checkpoint v0.5.0 // indirect 21 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 22 | github.com/hashicorp/go-cty v1.5.0 // indirect 23 | github.com/hashicorp/go-hclog v1.6.3 // indirect 24 | github.com/hashicorp/go-multierror v1.1.1 // indirect 25 | github.com/hashicorp/go-plugin v1.6.3 // indirect 26 | github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 27 | github.com/hashicorp/go-uuid v1.0.3 // indirect 28 | github.com/hashicorp/go-version v1.7.0 // indirect 29 | github.com/hashicorp/hc-install v0.9.2 // indirect 30 | github.com/hashicorp/hcl/v2 v2.23.0 // indirect 31 | github.com/hashicorp/logutils v1.0.0 // indirect 32 | github.com/hashicorp/terraform-exec v0.23.0 // indirect 33 | github.com/hashicorp/terraform-json v0.25.0 // indirect 34 | github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect 35 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 // indirect 36 | github.com/hashicorp/terraform-registry-address v0.2.5 // indirect 37 | github.com/hashicorp/terraform-svchost v0.1.1 // indirect 38 | github.com/hashicorp/yamux v0.1.1 // indirect 39 | github.com/kr/pretty v0.3.0 // indirect 40 | github.com/mattn/go-colorable v0.1.13 // indirect 41 | github.com/mattn/go-isatty v0.0.20 // indirect 42 | github.com/mitchellh/copystructure v1.2.0 // indirect 43 | github.com/mitchellh/go-testing-interface v1.14.1 // indirect 44 | github.com/mitchellh/go-wordwrap v1.0.0 // indirect 45 | github.com/mitchellh/mapstructure v1.5.0 // indirect 46 | github.com/mitchellh/reflectwalk v1.0.2 // indirect 47 | github.com/oklog/run v1.0.0 // indirect 48 | github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect 49 | github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect 50 | github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect 51 | github.com/zclconf/go-cty v1.16.2 // indirect 52 | golang.org/x/crypto v0.38.0 // indirect 53 | golang.org/x/mod v0.24.0 // indirect 54 | golang.org/x/net v0.39.0 // indirect 55 | golang.org/x/sync v0.14.0 // indirect 56 | golang.org/x/sys v0.33.0 // indirect 57 | golang.org/x/text v0.25.0 // indirect 58 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect 59 | google.golang.org/appengine v1.6.8 // indirect 60 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect 61 | google.golang.org/grpc v1.72.1 // indirect 62 | google.golang.org/protobuf v1.36.6 // indirect 63 | ) 64 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= 2 | dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 3 | github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= 4 | github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= 5 | github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= 6 | github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= 7 | github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= 8 | github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 9 | github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= 10 | github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= 11 | github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= 12 | github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= 13 | github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= 14 | github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= 15 | github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= 16 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 17 | github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= 18 | github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= 19 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 20 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 21 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 22 | github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 23 | github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 24 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 25 | github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= 26 | github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 27 | github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= 28 | github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= 29 | github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= 30 | github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= 31 | github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60= 32 | github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k= 33 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 34 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 35 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 36 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 37 | github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= 38 | github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 39 | github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= 40 | github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= 41 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 42 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 43 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 44 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 45 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 46 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 47 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 48 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 49 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 50 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 51 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 52 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 53 | github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= 54 | github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 55 | github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= 56 | github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= 57 | github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 58 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 59 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 60 | github.com/hashicorp/go-cty v1.5.0 h1:EkQ/v+dDNUqnuVpmS5fPqyY71NXVgT5gf32+57xY8g0= 61 | github.com/hashicorp/go-cty v1.5.0/go.mod h1:lFUCG5kd8exDobgSfyj4ONE/dc822kiYMguVKdHGMLM= 62 | github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= 63 | github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= 64 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= 65 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 66 | github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= 67 | github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= 68 | github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= 69 | github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= 70 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 71 | github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= 72 | github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 73 | github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= 74 | github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 75 | github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+OmtO24= 76 | github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I= 77 | github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos= 78 | github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= 79 | github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= 80 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 81 | github.com/hashicorp/terraform-exec v0.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEsiXmzATMW/I= 82 | github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY= 83 | github.com/hashicorp/terraform-json v0.25.0 h1:rmNqc/CIfcWawGiwXmRuiXJKEiJu1ntGoxseG1hLhoQ= 84 | github.com/hashicorp/terraform-json v0.25.0/go.mod h1:sMKS8fiRDX4rVlR6EJUMudg1WcanxCMoWwTLkgZP/vc= 85 | github.com/hashicorp/terraform-plugin-framework v1.15.0 h1:LQ2rsOfmDLxcn5EeIwdXFtr03FVsNktbbBci8cOKdb4= 86 | github.com/hashicorp/terraform-plugin-framework v1.15.0/go.mod h1:hxrNI/GY32KPISpWqlCoTLM9JZsGH3CyYlir09bD/fI= 87 | github.com/hashicorp/terraform-plugin-go v0.28.0 h1:zJmu2UDwhVN0J+J20RE5huiF3XXlTYVIleaevHZgKPA= 88 | github.com/hashicorp/terraform-plugin-go v0.28.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o= 89 | github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= 90 | github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= 91 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 h1:NFPMacTrY/IdcIcnUB+7hsore1ZaRWU9cnB6jFoBnIM= 92 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0/go.mod h1:QYmYnLfsosrxjCnGY1p9c7Zj6n9thnEE+7RObeYs3fA= 93 | github.com/hashicorp/terraform-plugin-testing v1.13.1 h1:0nhSm8lngGTggqXptU4vunFI0S2XjLAhJg3RylC5aLw= 94 | github.com/hashicorp/terraform-plugin-testing v1.13.1/go.mod h1:b/hl6YZLm9fjeud/3goqh/gdqhZXbRfbHMkEiY9dZwc= 95 | github.com/hashicorp/terraform-registry-address v0.2.5 h1:2GTftHqmUhVOeuu9CW3kwDkRe4pcBDq0uuK5VJngU1M= 96 | github.com/hashicorp/terraform-registry-address v0.2.5/go.mod h1:PpzXWINwB5kuVS5CA7m1+eO2f1jKb5ZDIxrOPfpnGkg= 97 | github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= 98 | github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= 99 | github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= 100 | github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= 101 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 102 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 103 | github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= 104 | github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= 105 | github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= 106 | github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 107 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 108 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 109 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 110 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 111 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 112 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 113 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 114 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 115 | github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 116 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 117 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 118 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 119 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 120 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 121 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 122 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 123 | github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= 124 | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= 125 | github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= 126 | github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= 127 | github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= 128 | github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 129 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 130 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 131 | github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= 132 | github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 133 | github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= 134 | github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 135 | github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= 136 | github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= 137 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 138 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 139 | github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= 140 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 141 | github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= 142 | github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= 143 | github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= 144 | github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= 145 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 146 | github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 147 | github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= 148 | github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 149 | github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 150 | github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= 151 | github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 152 | github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= 153 | github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= 154 | github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= 155 | github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= 156 | github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= 157 | github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= 158 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 159 | github.com/zclconf/go-cty v1.16.2 h1:LAJSwc3v81IRBZyUVQDUdZ7hs3SYs9jv0eZJDWHD/70= 160 | github.com/zclconf/go-cty v1.16.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= 161 | github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= 162 | github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= 163 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 164 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 165 | go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= 166 | go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= 167 | go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= 168 | go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= 169 | go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= 170 | go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= 171 | go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= 172 | go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= 173 | go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= 174 | go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= 175 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 176 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 177 | golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= 178 | golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= 179 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 180 | golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= 181 | golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= 182 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 183 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 184 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 185 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 186 | golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= 187 | golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= 188 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 189 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 190 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 191 | golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= 192 | golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 193 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 194 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 195 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 196 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 197 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 198 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 199 | golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 200 | golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 201 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 202 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 203 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 204 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 205 | golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= 206 | golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 207 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 208 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 209 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 210 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 211 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 212 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 213 | golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= 214 | golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= 215 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 216 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 217 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 218 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= 219 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 220 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 221 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 222 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 223 | google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= 224 | google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= 225 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= 226 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= 227 | google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= 228 | google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= 229 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 230 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 231 | google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= 232 | google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 233 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 234 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 235 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 236 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 237 | gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 238 | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 239 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 240 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 241 | -------------------------------------------------------------------------------- /internal/planmodifiers/attribute.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | package planmodifiers 5 | 6 | import ( 7 | "context" 8 | 9 | "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" 10 | ) 11 | 12 | func RequiresReplaceIfValuesNotNull() planmodifier.Map { 13 | return requiresReplaceIfValuesNotNullModifier{} 14 | } 15 | 16 | type requiresReplaceIfValuesNotNullModifier struct{} 17 | 18 | func (r requiresReplaceIfValuesNotNullModifier) PlanModifyMap(ctx context.Context, req planmodifier.MapRequest, resp *planmodifier.MapResponse) { 19 | if req.State.Raw.IsNull() { 20 | // if we're creating the resource, no need to delete and 21 | // recreate it 22 | return 23 | } 24 | 25 | if req.Plan.Raw.IsNull() { 26 | // if we're deleting the resource, no need to delete and 27 | // recreate it 28 | return 29 | } 30 | 31 | // If there are no differences, do not mark the resource for replacement 32 | // and ensure the plan matches the configuration. 33 | if req.ConfigValue.Equal(req.StateValue) { 34 | return 35 | } 36 | 37 | if req.StateValue.IsNull() { 38 | // terraform-plugin-sdk would store maps as null if all keys had null 39 | // values. To prevent unintentional replacement plans when migrating 40 | // to terraform-plugin-framework, only trigger replacement when the 41 | // prior state (map) is null and when there are not null map values. 42 | allNullValues := true 43 | 44 | for _, configValue := range req.ConfigValue.Elements() { 45 | if !configValue.IsNull() { 46 | allNullValues = false 47 | } 48 | } 49 | 50 | if allNullValues { 51 | return 52 | } 53 | } else { 54 | // terraform-plugin-sdk would completely omit storing map keys with 55 | // null values, so this also must prevent unintentional replacement 56 | // in that case as well. 57 | allNewNullValues := true 58 | 59 | configMap := req.ConfigValue 60 | stateMap := req.StateValue 61 | 62 | for configKey, configValue := range configMap.Elements() { 63 | stateValue, ok := stateMap.Elements()[configKey] 64 | 65 | // If the key doesn't exist in state and the config value is 66 | // null, do not trigger replacement. 67 | if !ok && configValue.IsNull() { 68 | continue 69 | } 70 | 71 | // If the state value exists and it is equal to the config value, 72 | // do not trigger replacement. 73 | if configValue.Equal(stateValue) { 74 | continue 75 | } 76 | 77 | allNewNullValues = false 78 | break 79 | } 80 | 81 | for stateKey := range stateMap.Elements() { 82 | _, ok := configMap.Elements()[stateKey] 83 | 84 | // If the key doesn't exist in the config, but there is a state 85 | // value, trigger replacement. 86 | if !ok { 87 | allNewNullValues = false 88 | break 89 | } 90 | } 91 | 92 | if allNewNullValues { 93 | return 94 | } 95 | } 96 | 97 | resp.RequiresReplace = true 98 | } 99 | 100 | // Description returns a human-readable description of the plan modifier. 101 | func (r requiresReplaceIfValuesNotNullModifier) Description(ctx context.Context) string { 102 | return "If the value of this attribute changes, Terraform will destroy and recreate the resource." 103 | } 104 | 105 | // MarkdownDescription returns a markdown description of the plan modifier. 106 | func (r requiresReplaceIfValuesNotNullModifier) MarkdownDescription(ctx context.Context) string { 107 | return "If the value of this attribute changes, Terraform will destroy and recreate the resource." 108 | } 109 | -------------------------------------------------------------------------------- /internal/provider/data_source.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | package provider 5 | 6 | import ( 7 | "context" 8 | "fmt" 9 | "math/rand" 10 | 11 | "github.com/hashicorp/terraform-plugin-framework/datasource" 12 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema" 13 | "github.com/hashicorp/terraform-plugin-framework/types" 14 | ) 15 | 16 | var ( 17 | _ datasource.DataSource = (*nullDataSource)(nil) 18 | ) 19 | 20 | func NewNullDataSource() datasource.DataSource { 21 | return &nullDataSource{} 22 | } 23 | 24 | type nullDataSource struct{} 25 | 26 | func (n *nullDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { 27 | resp.TypeName = req.ProviderTypeName + "_data_source" 28 | } 29 | 30 | func (n *nullDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { 31 | resp.Schema = schema.Schema{ 32 | DeprecationMessage: "The null_data_source was historically used to construct intermediate values to re-use elsewhere " + 33 | "in configuration, the same can now be achieved using locals or the terraform_data resource type in Terraform 1.4 and later.", 34 | Description: `The ` + "`null_data_source`" + ` data source implements the standard data source lifecycle but does not 35 | interact with any external APIs. 36 | 37 | Historically, the ` + "`null_data_source`" + ` was typically used to construct intermediate values to re-use elsewhere in configuration. The 38 | same can now be achieved using [locals](https://developer.hashicorp.com/terraform/language/values/locals) ` + 39 | `or the [terraform_data resource type](https://developer.hashicorp.com/terraform/language/resources/terraform-data) in Terraform 1.4 and later.`, 40 | Attributes: map[string]schema.Attribute{ 41 | "inputs": schema.MapAttribute{ 42 | Description: "A map of arbitrary strings that is copied into the `outputs` attribute, and accessible directly for interpolation.", 43 | ElementType: types.StringType, 44 | Optional: true, 45 | }, 46 | "outputs": schema.MapAttribute{ 47 | Description: "After the data source is \"read\", a copy of the `inputs` map.", 48 | ElementType: types.StringType, 49 | Computed: true, 50 | }, 51 | "random": schema.StringAttribute{ 52 | Description: "A random value. This is primarily for testing and has little practical use; prefer the [hashicorp/random provider](https://registry.terraform.io/providers/hashicorp/random) for more practical random number use-cases.", 53 | Computed: true, 54 | }, 55 | "has_computed_default": schema.StringAttribute{ 56 | Description: "If set, its literal value will be stored and returned. If not, its value defaults to `\"default\"`. This argument exists primarily for testing and has little practical use.", 57 | Optional: true, 58 | Computed: true, 59 | }, 60 | 61 | "id": schema.StringAttribute{ 62 | Description: "This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version.", 63 | Computed: true, 64 | DeprecationMessage: "This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version.", 65 | }, 66 | }, 67 | } 68 | } 69 | 70 | func (n *nullDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { 71 | var config nullDataSourceModelV0 72 | 73 | diags := req.Config.Get(ctx, &config) 74 | resp.Diagnostics.Append(diags...) 75 | if resp.Diagnostics.HasError() { 76 | return 77 | } 78 | 79 | config.Outputs = config.Inputs 80 | config.Random = types.StringValue(fmt.Sprintf("%d", rand.Int())) 81 | 82 | if config.HasComputedDefault.IsNull() { 83 | config.HasComputedDefault = types.StringValue("default") 84 | } 85 | config.ID = types.StringValue("static") 86 | diags = resp.State.Set(ctx, config) 87 | resp.Diagnostics.Append(diags...) 88 | } 89 | 90 | type nullDataSourceModelV0 struct { 91 | Inputs types.Map `tfsdk:"inputs"` 92 | Outputs types.Map `tfsdk:"outputs"` 93 | Random types.String `tfsdk:"random"` 94 | HasComputedDefault types.String `tfsdk:"has_computed_default"` 95 | ID types.String `tfsdk:"id"` 96 | } 97 | -------------------------------------------------------------------------------- /internal/provider/data_source_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | package provider 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/hashicorp/terraform-plugin-testing/helper/resource" 10 | ) 11 | 12 | func TestAccDataSource_basic(t *testing.T) { 13 | dsn := "data.null_data_source.test" 14 | resource.UnitTest(t, resource.TestCase{ 15 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 16 | Steps: []resource.TestStep{ 17 | { 18 | Config: testAccDataSourceConfig_basic, 19 | Check: resource.ComposeTestCheckFunc( 20 | resource.TestCheckResourceAttrSet(dsn, "random"), 21 | resource.TestCheckResourceAttr(dsn, "has_computed_default", "default"), 22 | ), 23 | }, 24 | }, 25 | }) 26 | } 27 | 28 | func TestAccDataSource_inputs(t *testing.T) { 29 | dsn := "data.null_data_source.test" 30 | resource.UnitTest(t, resource.TestCase{ 31 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 32 | Steps: []resource.TestStep{ 33 | { 34 | Config: testAccDataSourceConfig_inputs, 35 | Check: resource.ComposeTestCheckFunc( 36 | resource.TestCheckResourceAttrSet(dsn, "random"), 37 | resource.TestCheckResourceAttr(dsn, "outputs.foo", "bar"), 38 | ), 39 | }, 40 | }, 41 | }) 42 | } 43 | 44 | const testAccDataSourceConfig_basic = ` 45 | data "null_data_source" "test" { 46 | } 47 | ` 48 | 49 | const testAccDataSourceConfig_inputs = ` 50 | data "null_data_source" "test" { 51 | inputs = { 52 | foo = "bar" 53 | } 54 | }` 55 | -------------------------------------------------------------------------------- /internal/provider/provider.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | package provider 5 | 6 | import ( 7 | "context" 8 | 9 | "github.com/hashicorp/terraform-plugin-framework/datasource" 10 | "github.com/hashicorp/terraform-plugin-framework/provider" 11 | "github.com/hashicorp/terraform-plugin-framework/resource" 12 | ) 13 | 14 | var _ provider.Provider = (*nullProvider)(nil) 15 | 16 | func New() provider.Provider { 17 | return &nullProvider{} 18 | } 19 | 20 | type nullProvider struct{} 21 | 22 | func (p *nullProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { 23 | resp.TypeName = "null" 24 | } 25 | 26 | func (p *nullProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { 27 | 28 | } 29 | 30 | func (p *nullProvider) DataSources(ctx context.Context) []func() datasource.DataSource { 31 | return []func() datasource.DataSource{ 32 | NewNullDataSource, 33 | } 34 | } 35 | 36 | func (p *nullProvider) Resources(ctx context.Context) []func() resource.Resource { 37 | return []func() resource.Resource{ 38 | NewNullResource, 39 | } 40 | } 41 | 42 | func (p *nullProvider) Schema(context.Context, provider.SchemaRequest, *provider.SchemaResponse) { 43 | } 44 | -------------------------------------------------------------------------------- /internal/provider/provider_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | package provider 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/hashicorp/terraform-plugin-framework/providerserver" 10 | "github.com/hashicorp/terraform-plugin-go/tfprotov5" 11 | "github.com/hashicorp/terraform-plugin-testing/helper/resource" 12 | "github.com/hashicorp/terraform-plugin-testing/terraform" 13 | ) 14 | 15 | func protoV5ProviderFactories() map[string]func() (tfprotov5.ProviderServer, error) { 16 | return map[string]func() (tfprotov5.ProviderServer, error){ 17 | "null": providerserver.NewProtocol5WithError(New()), 18 | } 19 | } 20 | 21 | func providerVersion311() map[string]resource.ExternalProvider { 22 | return map[string]resource.ExternalProvider{ 23 | "null": { 24 | VersionConstraint: "3.1.1", 25 | Source: "hashicorp/null", 26 | }, 27 | } 28 | } 29 | 30 | func testCheckAttributeValuesDiffer(i *string, j *string) resource.TestCheckFunc { 31 | return func(s *terraform.State) error { 32 | if testStringValue(i) == testStringValue(j) { 33 | return fmt.Errorf("attribute values are the same") 34 | } 35 | 36 | return nil 37 | } 38 | } 39 | 40 | func testCheckAttributeValuesEqual(i *string, j *string) resource.TestCheckFunc { 41 | return func(s *terraform.State) error { 42 | if testStringValue(i) != testStringValue(j) { 43 | return fmt.Errorf("attribute values are different") 44 | } 45 | 46 | return nil 47 | } 48 | } 49 | 50 | //nolint:unparam 51 | func testExtractResourceAttr(resourceName string, attributeName string, attributeValue *string) resource.TestCheckFunc { 52 | return func(s *terraform.State) error { 53 | rs, ok := s.RootModule().Resources[resourceName] 54 | 55 | if !ok { 56 | return fmt.Errorf("resource name %s not found in state", resourceName) 57 | } 58 | 59 | attrValue, ok := rs.Primary.Attributes[attributeName] 60 | 61 | if !ok { 62 | return fmt.Errorf("attribute %s not found in resource %s state", attributeName, resourceName) 63 | } 64 | 65 | *attributeValue = attrValue 66 | 67 | return nil 68 | } 69 | } 70 | 71 | func testStringValue(sPtr *string) string { 72 | if sPtr == nil { 73 | return "" 74 | } 75 | 76 | return *sPtr 77 | } 78 | -------------------------------------------------------------------------------- /internal/provider/resource.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | package provider 5 | 6 | import ( 7 | "context" 8 | "fmt" 9 | "math/rand" 10 | 11 | "github.com/hashicorp/terraform-plugin-framework/path" 12 | "github.com/hashicorp/terraform-plugin-framework/resource" 13 | "github.com/hashicorp/terraform-plugin-framework/resource/schema" 14 | "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" 15 | "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" 16 | "github.com/hashicorp/terraform-plugin-framework/types" 17 | 18 | "github.com/terraform-providers/terraform-provider-null/internal/planmodifiers" 19 | ) 20 | 21 | var ( 22 | _ resource.Resource = (*nullResource)(nil) 23 | ) 24 | 25 | func NewNullResource() resource.Resource { 26 | return &nullResource{} 27 | } 28 | 29 | type nullResource struct{} 30 | 31 | func (n *nullResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { 32 | resp.TypeName = req.ProviderTypeName + "_resource" 33 | } 34 | 35 | func (n *nullResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { 36 | resp.Schema = schema.Schema{ 37 | Description: "The `null_resource` resource implements the standard resource lifecycle but takes no further action. " + 38 | "On Terraform 1.4 and later, use the [`terraform_data` resource type](https://developer.hashicorp.com/terraform/language/resources/terraform-data) instead. " + 39 | "Terraform 1.9 and later support the `moved` configuration block from `null_resource` to `terraform_data`.\n\n" + 40 | "The `triggers` argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced.", 41 | Attributes: map[string]schema.Attribute{ 42 | "triggers": schema.MapAttribute{ 43 | Description: "A map of arbitrary strings that, when changed, will force the null resource to be replaced, re-running any associated provisioners.", 44 | ElementType: types.StringType, 45 | Optional: true, 46 | PlanModifiers: []planmodifier.Map{ 47 | planmodifiers.RequiresReplaceIfValuesNotNull(), 48 | }, 49 | }, 50 | 51 | "id": schema.StringAttribute{ 52 | Description: "This is set to a random value at create time.", 53 | Computed: true, 54 | PlanModifiers: []planmodifier.String{ 55 | stringplanmodifier.UseStateForUnknown(), 56 | }, 57 | }, 58 | }, 59 | } 60 | } 61 | 62 | func (n *nullResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { 63 | var model nullModelV0 64 | 65 | resp.Diagnostics.Append(req.Plan.Get(ctx, &model)...) 66 | 67 | if resp.Diagnostics.HasError() { 68 | return 69 | } 70 | resp.Diagnostics.Append(resp.State.Set(ctx, &model)...) 71 | 72 | diags := resp.State.SetAttribute(ctx, path.Root("id"), fmt.Sprintf("%d", rand.Int())) 73 | resp.Diagnostics.Append(diags...) 74 | } 75 | 76 | func (n *nullResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { 77 | 78 | } 79 | 80 | func (n *nullResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { 81 | var model nullModelV0 82 | 83 | resp.Diagnostics.Append(req.Plan.Get(ctx, &model)...) 84 | 85 | if resp.Diagnostics.HasError() { 86 | return 87 | } 88 | 89 | resp.Diagnostics.Append(resp.State.Set(ctx, &model)...) 90 | } 91 | 92 | func (n *nullResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { 93 | 94 | } 95 | 96 | type nullModelV0 struct { 97 | Triggers types.Map `tfsdk:"triggers"` 98 | ID types.String `tfsdk:"id"` 99 | } 100 | -------------------------------------------------------------------------------- /internal/provider/resource_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | package provider 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/hashicorp/terraform-plugin-testing/helper/resource" 10 | ) 11 | 12 | func TestAccResource_basic(t *testing.T) { 13 | dsn := "null_resource.test" 14 | resource.UnitTest(t, resource.TestCase{ 15 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 16 | Steps: []resource.TestStep{ 17 | { 18 | Config: testAccResourceConfig_basic, 19 | Check: resource.ComposeTestCheckFunc( 20 | resource.TestCheckResourceAttrSet(dsn, "id"), 21 | ), 22 | }, 23 | }, 24 | }) 25 | } 26 | 27 | func TestAccResource_basic_FrameworkMigration(t *testing.T) { 28 | dsn := "null_resource.test" 29 | 30 | resource.Test(t, resource.TestCase{ 31 | Steps: []resource.TestStep{ 32 | { 33 | ExternalProviders: providerVersion311(), 34 | Config: testAccResourceConfig_basic, 35 | Check: resource.ComposeTestCheckFunc( 36 | resource.TestCheckResourceAttrSet(dsn, "id"), 37 | ), 38 | }, 39 | { 40 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 41 | Config: testAccResourceConfig_basic, 42 | PlanOnly: true, 43 | }, 44 | { 45 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 46 | Config: testAccResourceConfig_basic, 47 | Check: resource.ComposeTestCheckFunc( 48 | resource.TestCheckResourceAttrSet(dsn, "id"), 49 | ), 50 | }, 51 | }, 52 | }) 53 | } 54 | 55 | func TestAccResource_Triggers_Keep_EmptyMap(t *testing.T) { 56 | var id1, id2 string 57 | 58 | resource.ParallelTest(t, resource.TestCase{ 59 | Steps: []resource.TestStep{ 60 | { 61 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 62 | Config: `resource "null_resource" "test" { 63 | triggers = {} 64 | }`, 65 | Check: resource.ComposeTestCheckFunc( 66 | testExtractResourceAttr("null_resource.test", "id", &id1), 67 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 68 | ), 69 | }, 70 | { 71 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 72 | Config: `resource "null_resource" "test" { 73 | triggers = {} 74 | }`, 75 | Check: resource.ComposeTestCheckFunc( 76 | testExtractResourceAttr("null_resource.test", "id", &id2), 77 | testCheckAttributeValuesEqual(&id1, &id2), 78 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 79 | ), 80 | }, 81 | }, 82 | }) 83 | } 84 | 85 | func TestAccResource_Triggers_Keep_EmptyMapToNullValue(t *testing.T) { 86 | var id1, id2 string 87 | 88 | resource.ParallelTest(t, resource.TestCase{ 89 | Steps: []resource.TestStep{ 90 | { 91 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 92 | Config: `resource "null_resource" "test" { 93 | triggers = {} 94 | }`, 95 | Check: resource.ComposeTestCheckFunc( 96 | testExtractResourceAttr("null_resource.test", "id", &id1), 97 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 98 | ), 99 | }, 100 | { 101 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 102 | Config: `resource "null_resource" "test" { 103 | triggers = { 104 | "key" = null 105 | } 106 | }`, 107 | Check: resource.ComposeTestCheckFunc( 108 | testExtractResourceAttr("null_resource.test", "id", &id2), 109 | testCheckAttributeValuesEqual(&id1, &id2), 110 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 111 | ), 112 | }, 113 | }, 114 | }) 115 | } 116 | 117 | func TestAccResource_Triggers_Keep_NullMap(t *testing.T) { 118 | var id1, id2 string 119 | 120 | resource.ParallelTest(t, resource.TestCase{ 121 | Steps: []resource.TestStep{ 122 | { 123 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 124 | Config: testAccResourceConfig_basic, 125 | Check: resource.ComposeTestCheckFunc( 126 | testExtractResourceAttr("null_resource.test", "id", &id1), 127 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 128 | ), 129 | }, 130 | { 131 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 132 | Config: testAccResourceConfig_basic, 133 | Check: resource.ComposeTestCheckFunc( 134 | testExtractResourceAttr("null_resource.test", "id", &id2), 135 | testCheckAttributeValuesEqual(&id1, &id2), 136 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 137 | ), 138 | }, 139 | }, 140 | }) 141 | } 142 | 143 | func TestAccResource_Triggers_Keep_NullMapToNullValue(t *testing.T) { 144 | var id1, id2 string 145 | 146 | resource.ParallelTest(t, resource.TestCase{ 147 | Steps: []resource.TestStep{ 148 | { 149 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 150 | Config: testAccResourceConfig_basic, 151 | Check: resource.ComposeTestCheckFunc( 152 | testExtractResourceAttr("null_resource.test", "id", &id1), 153 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 154 | ), 155 | }, 156 | { 157 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 158 | Config: `resource "null_resource" "test" { 159 | triggers = { 160 | "key" = null 161 | } 162 | }`, 163 | Check: resource.ComposeTestCheckFunc( 164 | testExtractResourceAttr("null_resource.test", "id", &id2), 165 | testCheckAttributeValuesEqual(&id1, &id2), 166 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 167 | ), 168 | }, 169 | }, 170 | }) 171 | } 172 | 173 | func TestAccResource_Triggers_Keep_NullValue(t *testing.T) { 174 | var id1, id2 string 175 | 176 | resource.ParallelTest(t, resource.TestCase{ 177 | Steps: []resource.TestStep{ 178 | { 179 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 180 | Config: `resource "null_resource" "test" { 181 | triggers = { 182 | "key" = null 183 | } 184 | }`, 185 | Check: resource.ComposeTestCheckFunc( 186 | testExtractResourceAttr("null_resource.test", "id", &id1), 187 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 188 | ), 189 | }, 190 | { 191 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 192 | Config: `resource "null_resource" "test" { 193 | triggers = { 194 | "key" = null 195 | } 196 | }`, 197 | Check: resource.ComposeTestCheckFunc( 198 | testExtractResourceAttr("null_resource.test", "id", &id2), 199 | testCheckAttributeValuesEqual(&id1, &id2), 200 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 201 | ), 202 | }, 203 | }, 204 | }) 205 | } 206 | 207 | func TestAccResource_Triggers_Keep_NullValues(t *testing.T) { 208 | var id1, id2 string 209 | 210 | resource.ParallelTest(t, resource.TestCase{ 211 | Steps: []resource.TestStep{ 212 | { 213 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 214 | Config: `resource "null_resource" "test" { 215 | triggers = { 216 | "key1" = null 217 | "key2" = null 218 | } 219 | }`, 220 | Check: resource.ComposeTestCheckFunc( 221 | testExtractResourceAttr("null_resource.test", "id", &id1), 222 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "2"), 223 | ), 224 | }, 225 | { 226 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 227 | Config: `resource "null_resource" "test" { 228 | triggers = { 229 | "key1" = null 230 | "key2" = null 231 | } 232 | }`, 233 | Check: resource.ComposeTestCheckFunc( 234 | testExtractResourceAttr("null_resource.test", "id", &id2), 235 | testCheckAttributeValuesEqual(&id1, &id2), 236 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "2"), 237 | ), 238 | }, 239 | }, 240 | }) 241 | } 242 | 243 | func TestAccResource_Triggers_Keep_Value(t *testing.T) { 244 | var id1, id2 string 245 | 246 | resource.ParallelTest(t, resource.TestCase{ 247 | Steps: []resource.TestStep{ 248 | { 249 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 250 | Config: `resource "null_resource" "test" { 251 | triggers = { 252 | "key" = "123" 253 | } 254 | }`, 255 | Check: resource.ComposeTestCheckFunc( 256 | testExtractResourceAttr("null_resource.test", "id", &id1), 257 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 258 | ), 259 | }, 260 | { 261 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 262 | Config: `resource "null_resource" "test" { 263 | triggers = { 264 | "key" = "123" 265 | } 266 | }`, 267 | Check: resource.ComposeTestCheckFunc( 268 | testExtractResourceAttr("null_resource.test", "id", &id2), 269 | testCheckAttributeValuesEqual(&id1, &id2), 270 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 271 | ), 272 | }, 273 | }, 274 | }) 275 | } 276 | 277 | func TestAccResource_Triggers_Keep_Values(t *testing.T) { 278 | var id1, id2 string 279 | 280 | resource.ParallelTest(t, resource.TestCase{ 281 | Steps: []resource.TestStep{ 282 | { 283 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 284 | Config: `resource "null_resource" "test" { 285 | triggers = { 286 | "key1" = "123" 287 | "key2" = "456" 288 | } 289 | }`, 290 | Check: resource.ComposeTestCheckFunc( 291 | testExtractResourceAttr("null_resource.test", "id", &id1), 292 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "2"), 293 | ), 294 | }, 295 | { 296 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 297 | Config: `resource "null_resource" "test" { 298 | triggers = { 299 | "key1" = "123" 300 | "key2" = "456" 301 | } 302 | }`, 303 | Check: resource.ComposeTestCheckFunc( 304 | testExtractResourceAttr("null_resource.test", "id", &id2), 305 | testCheckAttributeValuesEqual(&id1, &id2), 306 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "2"), 307 | ), 308 | }, 309 | }, 310 | }) 311 | } 312 | 313 | func TestAccResource_Triggers_Replace_EmptyMapToValue(t *testing.T) { 314 | var id1, id2 string 315 | 316 | resource.ParallelTest(t, resource.TestCase{ 317 | Steps: []resource.TestStep{ 318 | { 319 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 320 | Config: `resource "null_resource" "test" { 321 | triggers = {} 322 | }`, 323 | Check: resource.ComposeTestCheckFunc( 324 | testExtractResourceAttr("null_resource.test", "id", &id1), 325 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 326 | ), 327 | }, 328 | { 329 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 330 | Config: `resource "null_resource" "test" { 331 | triggers = { 332 | "key" = "123" 333 | } 334 | }`, 335 | Check: resource.ComposeTestCheckFunc( 336 | testExtractResourceAttr("null_resource.test", "id", &id2), 337 | testCheckAttributeValuesDiffer(&id1, &id2), 338 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 339 | ), 340 | }, 341 | }, 342 | }) 343 | } 344 | 345 | func TestAccResource_Triggers_Replace_NullMapToValue(t *testing.T) { 346 | var id1, id2 string 347 | 348 | resource.ParallelTest(t, resource.TestCase{ 349 | Steps: []resource.TestStep{ 350 | { 351 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 352 | Config: testAccResourceConfig_basic, 353 | Check: resource.ComposeTestCheckFunc( 354 | testExtractResourceAttr("null_resource.test", "id", &id1), 355 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 356 | ), 357 | }, 358 | { 359 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 360 | Config: `resource "null_resource" "test" { 361 | triggers = { 362 | "key" = "123" 363 | } 364 | }`, 365 | Check: resource.ComposeTestCheckFunc( 366 | testExtractResourceAttr("null_resource.test", "id", &id2), 367 | testCheckAttributeValuesDiffer(&id1, &id2), 368 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 369 | ), 370 | }, 371 | }, 372 | }) 373 | } 374 | 375 | func TestAccResource_Triggers_Replace_NullValueToValue(t *testing.T) { 376 | var id1, id2 string 377 | 378 | resource.ParallelTest(t, resource.TestCase{ 379 | Steps: []resource.TestStep{ 380 | { 381 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 382 | Config: `resource "null_resource" "test" { 383 | triggers = { 384 | "key" = null 385 | } 386 | }`, 387 | Check: resource.ComposeTestCheckFunc( 388 | testExtractResourceAttr("null_resource.test", "id", &id1), 389 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 390 | ), 391 | }, 392 | { 393 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 394 | Config: `resource "null_resource" "test" { 395 | triggers = { 396 | "key" = "123" 397 | } 398 | }`, 399 | Check: resource.ComposeTestCheckFunc( 400 | testExtractResourceAttr("null_resource.test", "id", &id2), 401 | testCheckAttributeValuesDiffer(&id1, &id2), 402 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 403 | ), 404 | }, 405 | }, 406 | }) 407 | } 408 | 409 | func TestAccResource_Triggers_Replace_ValueToEmptyMap(t *testing.T) { 410 | var id1, id2 string 411 | 412 | resource.ParallelTest(t, resource.TestCase{ 413 | Steps: []resource.TestStep{ 414 | { 415 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 416 | Config: `resource "null_resource" "test" { 417 | triggers = { 418 | "key" = "123" 419 | } 420 | }`, 421 | Check: resource.ComposeTestCheckFunc( 422 | testExtractResourceAttr("null_resource.test", "id", &id1), 423 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 424 | ), 425 | }, 426 | { 427 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 428 | Config: `resource "null_resource" "test" { 429 | triggers = {} 430 | }`, 431 | Check: resource.ComposeTestCheckFunc( 432 | testExtractResourceAttr("null_resource.test", "id", &id2), 433 | testCheckAttributeValuesDiffer(&id1, &id2), 434 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 435 | ), 436 | }, 437 | }, 438 | }) 439 | } 440 | 441 | func TestAccResource_Triggers_Replace_ValueToNullMap(t *testing.T) { 442 | var id1, id2 string 443 | 444 | resource.ParallelTest(t, resource.TestCase{ 445 | Steps: []resource.TestStep{ 446 | { 447 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 448 | Config: `resource "null_resource" "test" { 449 | triggers = { 450 | "key" = "123" 451 | } 452 | }`, 453 | Check: resource.ComposeTestCheckFunc( 454 | testExtractResourceAttr("null_resource.test", "id", &id1), 455 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 456 | ), 457 | }, 458 | { 459 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 460 | Config: testAccResourceConfig_basic, 461 | Check: resource.ComposeTestCheckFunc( 462 | testExtractResourceAttr("null_resource.test", "id", &id2), 463 | testCheckAttributeValuesDiffer(&id1, &id2), 464 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 465 | ), 466 | }, 467 | }, 468 | }) 469 | } 470 | 471 | func TestAccResource_Triggers_Replace_ValueToNullValue(t *testing.T) { 472 | var id1, id2 string 473 | 474 | resource.ParallelTest(t, resource.TestCase{ 475 | Steps: []resource.TestStep{ 476 | { 477 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 478 | Config: `resource "null_resource" "test" { 479 | triggers = { 480 | "key" = "123" 481 | } 482 | }`, 483 | Check: resource.ComposeTestCheckFunc( 484 | testExtractResourceAttr("null_resource.test", "id", &id1), 485 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 486 | ), 487 | }, 488 | { 489 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 490 | Config: `resource "null_resource" "test" { 491 | triggers = { 492 | "key" = null 493 | } 494 | }`, 495 | Check: resource.ComposeTestCheckFunc( 496 | testExtractResourceAttr("null_resource.test", "id", &id2), 497 | testCheckAttributeValuesDiffer(&id1, &id2), 498 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 499 | ), 500 | }, 501 | }, 502 | }) 503 | } 504 | 505 | func TestAccResource_Triggers_Replace_ValueToNewValue(t *testing.T) { 506 | var id1, id2 string 507 | 508 | resource.ParallelTest(t, resource.TestCase{ 509 | Steps: []resource.TestStep{ 510 | { 511 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 512 | Config: `resource "null_resource" "test" { 513 | triggers = { 514 | "key" = "123" 515 | } 516 | }`, 517 | Check: resource.ComposeTestCheckFunc( 518 | testExtractResourceAttr("null_resource.test", "id", &id1), 519 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 520 | ), 521 | }, 522 | { 523 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 524 | Config: `resource "null_resource" "test" { 525 | triggers = { 526 | "key" = "456" 527 | } 528 | }`, 529 | Check: resource.ComposeTestCheckFunc( 530 | testExtractResourceAttr("null_resource.test", "id", &id2), 531 | testCheckAttributeValuesDiffer(&id1, &id2), 532 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 533 | ), 534 | }, 535 | }, 536 | }) 537 | } 538 | 539 | func TestAccResource_Triggers_FrameworkMigration_NullMapToNullValue(t *testing.T) { 540 | var id1, id2 string 541 | 542 | resource.ParallelTest(t, resource.TestCase{ 543 | Steps: []resource.TestStep{ 544 | { 545 | ExternalProviders: providerVersion311(), 546 | Config: `resource "null_resource" "test" { 547 | triggers = { 548 | "key" = null 549 | } 550 | }`, 551 | Check: resource.ComposeTestCheckFunc( 552 | testExtractResourceAttr("null_resource.test", "id", &id1), 553 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 554 | ), 555 | }, 556 | { 557 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 558 | Config: `resource "null_resource" "test" { 559 | triggers = { 560 | "key" = null 561 | } 562 | }`, 563 | Check: resource.ComposeTestCheckFunc( 564 | testExtractResourceAttr("null_resource.test", "id", &id2), 565 | testCheckAttributeValuesEqual(&id1, &id2), 566 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 567 | ), 568 | }, 569 | }, 570 | }) 571 | } 572 | 573 | func TestAccResource_Triggers_FrameworkMigration_NullMapToValue(t *testing.T) { 574 | var id1, id2 string 575 | 576 | resource.ParallelTest(t, resource.TestCase{ 577 | Steps: []resource.TestStep{ 578 | { 579 | ExternalProviders: providerVersion311(), 580 | Config: `resource "null_resource" "test" { 581 | triggers = { 582 | "key" = null 583 | } 584 | }`, 585 | Check: resource.ComposeTestCheckFunc( 586 | testExtractResourceAttr("null_resource.test", "id", &id1), 587 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 588 | ), 589 | }, 590 | { 591 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 592 | Config: `resource "null_resource" "test" { 593 | triggers = { 594 | "key" = "123" 595 | } 596 | }`, 597 | Check: resource.ComposeTestCheckFunc( 598 | testExtractResourceAttr("null_resource.test", "id", &id2), 599 | testCheckAttributeValuesDiffer(&id1, &id2), 600 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 601 | ), 602 | }, 603 | }, 604 | }) 605 | } 606 | 607 | func TestAccResource_Triggers_FrameworkMigration_NullMapToMultipleNullValue(t *testing.T) { 608 | var id1, id2 string 609 | 610 | resource.ParallelTest(t, resource.TestCase{ 611 | Steps: []resource.TestStep{ 612 | { 613 | ExternalProviders: providerVersion311(), 614 | Config: `resource "null_resource" "test" { 615 | triggers = { 616 | "key1" = null 617 | "key2" = null 618 | } 619 | }`, 620 | Check: resource.ComposeTestCheckFunc( 621 | testExtractResourceAttr("null_resource.test", "id", &id1), 622 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 623 | ), 624 | }, 625 | { 626 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 627 | Config: `resource "null_resource" "test" { 628 | triggers = { 629 | "key1" = null 630 | "key2" = null 631 | } 632 | }`, 633 | Check: resource.ComposeTestCheckFunc( 634 | testExtractResourceAttr("null_resource.test", "id", &id2), 635 | testCheckAttributeValuesEqual(&id1, &id2), 636 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "2"), 637 | ), 638 | }, 639 | }, 640 | }) 641 | } 642 | 643 | func TestAccResource_Triggers_FrameworkMigration_NullMapToMultipleValue(t *testing.T) { 644 | var id1, id2 string 645 | 646 | resource.ParallelTest(t, resource.TestCase{ 647 | Steps: []resource.TestStep{ 648 | { 649 | ExternalProviders: providerVersion311(), 650 | Config: `resource "null_resource" "test" { 651 | triggers = { 652 | "key1" = null 653 | "key2" = null 654 | } 655 | }`, 656 | Check: resource.ComposeTestCheckFunc( 657 | testExtractResourceAttr("null_resource.test", "id", &id1), 658 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "0"), 659 | ), 660 | }, 661 | { 662 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 663 | Config: `resource "null_resource" "test" { 664 | triggers = { 665 | "key1" = "123" 666 | "key2" = "456" 667 | } 668 | }`, 669 | Check: resource.ComposeTestCheckFunc( 670 | testExtractResourceAttr("null_resource.test", "id", &id2), 671 | testCheckAttributeValuesDiffer(&id1, &id2), 672 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "2"), 673 | ), 674 | }, 675 | }, 676 | }) 677 | } 678 | 679 | func TestAccResource_Triggers_FrameworkMigration_NullMapValue(t *testing.T) { 680 | var id1, id2 string 681 | 682 | resource.ParallelTest(t, resource.TestCase{ 683 | Steps: []resource.TestStep{ 684 | { 685 | ExternalProviders: providerVersion311(), 686 | Config: `resource "null_resource" "test" { 687 | triggers = { 688 | "key1" = "123" 689 | "key2" = null 690 | } 691 | }`, 692 | Check: resource.ComposeTestCheckFunc( 693 | testExtractResourceAttr("null_resource.test", "id", &id1), 694 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 695 | ), 696 | }, 697 | { 698 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 699 | Config: `resource "null_resource" "test" { 700 | triggers = { 701 | "key1" = "123" 702 | "key2" = null 703 | } 704 | }`, 705 | Check: resource.ComposeTestCheckFunc( 706 | testExtractResourceAttr("null_resource.test", "id", &id2), 707 | testCheckAttributeValuesEqual(&id1, &id2), 708 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "2"), 709 | ), 710 | }, 711 | }, 712 | }) 713 | } 714 | 715 | func TestAccResource_Triggers_FrameworkMigration_NullMapValueToValue(t *testing.T) { 716 | var id1, id2 string 717 | 718 | resource.ParallelTest(t, resource.TestCase{ 719 | Steps: []resource.TestStep{ 720 | { 721 | ExternalProviders: providerVersion311(), 722 | Config: `resource "null_resource" "test" { 723 | triggers = { 724 | "key1" = "123" 725 | "key2" = null 726 | } 727 | }`, 728 | Check: resource.ComposeTestCheckFunc( 729 | testExtractResourceAttr("null_resource.test", "id", &id1), 730 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "1"), 731 | ), 732 | }, 733 | { 734 | ProtoV5ProviderFactories: protoV5ProviderFactories(), 735 | Config: `resource "null_resource" "test" { 736 | triggers = { 737 | "key1" = "123" 738 | "key2" = "456" 739 | } 740 | }`, 741 | Check: resource.ComposeTestCheckFunc( 742 | testExtractResourceAttr("null_resource.test", "id", &id2), 743 | testCheckAttributeValuesDiffer(&id1, &id2), 744 | resource.TestCheckResourceAttr("null_resource.test", "triggers.%", "2"), 745 | ), 746 | }, 747 | }, 748 | }) 749 | } 750 | 751 | const testAccResourceConfig_basic = ` 752 | resource "null_resource" "test" { 753 | } 754 | ` 755 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | package main 5 | 6 | import ( 7 | "context" 8 | "flag" 9 | "log" 10 | 11 | "github.com/hashicorp/terraform-plugin-framework/providerserver" 12 | 13 | "github.com/terraform-providers/terraform-provider-null/internal/provider" 14 | ) 15 | 16 | func main() { 17 | var debug bool 18 | 19 | flag.BoolVar(&debug, "debug", false, "set to true to run the provider with support for debuggers like delve") 20 | flag.Parse() 21 | 22 | err := providerserver.Serve(context.Background(), provider.New, providerserver.ServeOpts{ 23 | Address: "registry.terraform.io/hashicorp/null", 24 | Debug: debug, 25 | ProtocolVersion: 5, 26 | }) 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /templates/data-sources.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" 4 | subcategory: "" 5 | description: |- 6 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }} 7 | --- 8 | 9 | # {{.Name}} 10 | 11 | {{ .Description | trimspace }} 12 | 13 | {{ if .HasExample -}} 14 | ## Example Usage 15 | 16 | {{tffile .ExampleFile }} 17 | {{- end }} 18 | 19 | {{ .SchemaMarkdown | trimspace }} 20 | 21 | {{ if .HasImport -}} 22 | ## Import 23 | 24 | Import is supported using the following syntax: 25 | 26 | {{codefile "shell" .ImportFile }} 27 | {{- end }} -------------------------------------------------------------------------------- /templates/guides/terraform-migration.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "terraform_data Migration Guide" 3 | description: |- 4 | Migration guide for moving `null_resource` resources to `terraform_data` 5 | --- 6 | 7 | # terraform_data Migration Guide 8 | 9 | Terraform 1.4 introduced the [`terraform_data` managed resource](https://developer.hashicorp.com/terraform/language/resources/terraform-data) as a built-in replacement for the `null_resource` managed resource. 10 | 11 | The built-in `terraform_data` managed resource is designed similar to the `null_resource` managed resource with added benefits: 12 | 13 | * The `hashicorp/null` provider is no longer required to be downloaded and installed. 14 | * Resource replacement trigger configuration supports any value type. 15 | * Optional data storage. 16 | 17 | Use `terraform_data` instead of `null_resource` with all new Terraform configurations running on Terraform 1.4 and later. 18 | 19 | ## Migrating existing configurations 20 | 21 | -> Migrating from the `null_resource` managed resource to the `terraform_data` managed resource with the `moved` configuration block requires Terraform 1.9 and later. 22 | 23 | ### Without triggers 24 | 25 | Use the [`moved` configuration block](https://developer.hashicorp.com/terraform/language/moved) to migrate from `null_resource` to `terraform_data`. 26 | 27 | Given this example configuration with a `null_resource` managed resource: 28 | 29 | ```terraform 30 | resource "null_resource" "example" { 31 | provisioner "local-exec" { 32 | command = "echo 'Hello, World!'" 33 | } 34 | } 35 | ``` 36 | 37 | Replace this configuration with a `terraform_data` managed resource and `moved` configuration: 38 | 39 | ```terraform 40 | resource "terraform_data" "example" { 41 | provisioner "local-exec" { 42 | command = "echo 'Hello, World!'" 43 | } 44 | } 45 | 46 | moved { 47 | from = null_resource.example 48 | to = terraform_data.example 49 | } 50 | ``` 51 | 52 | Run a plan operation, such as `terraform plan`, to verify that the move will occur as expected. 53 | 54 | Example output with no changes: 55 | 56 | ```console 57 | $ terraform plan 58 | terraform_data.example: Refreshing state... [id=892002337455008838] 59 | 60 | Terraform will perform the following actions: 61 | 62 | # null_resource.example has moved to terraform_data.example 63 | resource "terraform_data" "example" { 64 | id = "892002337455008838" 65 | } 66 | 67 | Plan: 0 to add, 0 to change, 0 to destroy. 68 | ``` 69 | 70 | Run an apply operation, such as `terraform apply`, to move the resource and complete the migration. Remove the `moved` configuration block at any time afterwards. 71 | 72 | ### With triggers 73 | 74 | Use the [`moved` configuration block](https://developer.hashicorp.com/terraform/language/moved) to migrate from `null_resource` to `terraform_data`. Replace the `null_resource` managed resource `triggers` argument with the `terraform_data` managed resource `triggers_replace` argument when moving. 75 | 76 | Given this example configuration with a `null_resource` managed resource that includes the `triggers` argument: 77 | 78 | ```terraform 79 | resource "null_resource" "example" { 80 | triggers = { 81 | examplekey = "examplevalue" 82 | } 83 | 84 | provisioner "local-exec" { 85 | command = "echo 'Hello, World!'" 86 | } 87 | } 88 | ``` 89 | 90 | Replace this configuration with the following `terraform_data` managed resource and `moved` configuration: 91 | 92 | ```terraform 93 | resource "terraform_data" "example" { 94 | triggers_replace = { 95 | examplekey = "examplevalue" 96 | } 97 | 98 | provisioner "local-exec" { 99 | command = "echo 'Hello, World!'" 100 | } 101 | } 102 | 103 | moved { 104 | from = null_resource.example 105 | to = terraform_data.example 106 | } 107 | ``` 108 | 109 | Run a plan operation, such as `terraform plan`, to verify that the move will occur as expected. 110 | 111 | Example output with no changes: 112 | 113 | ```console 114 | $ terraform plan 115 | terraform_data.example: Refreshing state... [id=1651348367769440250] 116 | 117 | Terraform will perform the following actions: 118 | 119 | # null_resource.example has moved to terraform_data.example 120 | resource "terraform_data" "example" { 121 | id = "1651348367769440250" 122 | # (1 unchanged attribute hidden) 123 | } 124 | 125 | Plan: 0 to add, 0 to change, 0 to destroy. 126 | ``` 127 | 128 | Run an apply operation, such as `terraform apply`, to move the resource and complete the migration. Remove the `moved` configuration block at any time afterwards. 129 | -------------------------------------------------------------------------------- /templates/index.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "Provider: Null" 3 | description: |- 4 | The null provider provides no-op constructs that can be useful helpers in tricky cases. 5 | --- 6 | 7 | # Null Provider 8 | 9 | The `null` provider is a rather-unusual provider that has constructs that 10 | intentionally do nothing. This may sound strange, and indeed these constructs 11 | do not need to be used in most cases, but they can be useful in various 12 | situations to help orchestrate tricky behavior or work around limitations. 13 | 14 | The documentation of each feature of this provider, accessible via the 15 | navigation, gives examples of situations where these constructs may prove 16 | useful. 17 | 18 | Usage of the `null` provider can make a Terraform configuration harder to 19 | understand. While it can be useful in certain cases, it should be applied with 20 | care and other solutions preferred when available. 21 | 22 | {{ .SchemaMarkdown | trimspace }} 23 | -------------------------------------------------------------------------------- /templates/resources.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" 4 | subcategory: "" 5 | description: |- 6 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }} 7 | --- 8 | 9 | # {{.Name}} 10 | 11 | {{ .Description | trimspace }} 12 | 13 | {{ if .HasExample -}} 14 | ## Example Usage 15 | 16 | {{tffile .ExampleFile }} 17 | {{- end }} 18 | 19 | {{ .SchemaMarkdown | trimspace }} 20 | 21 | {{ if .HasImport -}} 22 | ## Import 23 | 24 | Import is supported using the following syntax: 25 | 26 | {{codefile "shell" .ImportFile }} 27 | {{- end }} -------------------------------------------------------------------------------- /terraform-registry-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "metadata": { 4 | "protocol_versions": ["5.0"] 5 | } 6 | } -------------------------------------------------------------------------------- /tools/go.mod: -------------------------------------------------------------------------------- 1 | module tools 2 | 3 | go 1.23.7 4 | 5 | require ( 6 | github.com/hashicorp/copywrite v0.22.0 7 | github.com/hashicorp/terraform-plugin-docs v0.21.0 8 | ) 9 | 10 | require ( 11 | dario.cat/mergo v1.0.1 // indirect 12 | github.com/AlecAivazis/survey/v2 v2.3.7 // indirect 13 | github.com/BurntSushi/toml v1.2.1 // indirect 14 | github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect 15 | github.com/Masterminds/goutils v1.1.1 // indirect 16 | github.com/Masterminds/semver/v3 v3.3.0 // indirect 17 | github.com/Masterminds/sprig/v3 v3.3.0 // indirect 18 | github.com/ProtonMail/go-crypto v1.1.3 // indirect 19 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 20 | github.com/armon/go-radix v1.0.0 // indirect 21 | github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect 22 | github.com/bgentry/speakeasy v0.1.0 // indirect 23 | github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect 24 | github.com/bradleyfalzon/ghinstallation/v2 v2.5.0 // indirect 25 | github.com/cli/go-gh/v2 v2.12.1 // indirect 26 | github.com/cli/safeexec v1.0.0 // indirect 27 | github.com/cloudflare/circl v1.3.7 // indirect 28 | github.com/fatih/color v1.16.0 // indirect 29 | github.com/fsnotify/fsnotify v1.5.4 // indirect 30 | github.com/go-openapi/errors v0.20.2 // indirect 31 | github.com/go-openapi/strfmt v0.21.3 // indirect 32 | github.com/golang-jwt/jwt/v4 v4.5.2 // indirect 33 | github.com/golang/protobuf v1.5.2 // indirect 34 | github.com/google/go-github/v45 v45.2.0 // indirect 35 | github.com/google/go-github/v53 v53.0.0 // indirect 36 | github.com/google/go-querystring v1.1.0 // indirect 37 | github.com/google/uuid v1.6.0 // indirect 38 | github.com/hashicorp/cli v1.1.7 // indirect 39 | github.com/hashicorp/errwrap v1.1.0 // indirect 40 | github.com/hashicorp/go-checkpoint v0.5.0 // indirect 41 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 42 | github.com/hashicorp/go-hclog v1.6.3 // indirect 43 | github.com/hashicorp/go-multierror v1.1.1 // indirect 44 | github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 45 | github.com/hashicorp/go-uuid v1.0.3 // indirect 46 | github.com/hashicorp/go-version v1.7.0 // indirect 47 | github.com/hashicorp/hc-install v0.9.1 // indirect 48 | github.com/hashicorp/hcl v1.0.0 // indirect 49 | github.com/hashicorp/terraform-exec v0.22.0 // indirect 50 | github.com/hashicorp/terraform-json v0.24.0 // indirect 51 | github.com/huandu/xstrings v1.5.0 // indirect 52 | github.com/inconshreveable/mousetrap v1.0.1 // indirect 53 | github.com/jedib0t/go-pretty v4.3.0+incompatible // indirect 54 | github.com/jedib0t/go-pretty/v6 v6.4.6 // indirect 55 | github.com/joho/godotenv v1.3.0 // indirect 56 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect 57 | github.com/knadh/koanf v1.5.0 // indirect 58 | github.com/mattn/go-colorable v0.1.14 // indirect 59 | github.com/mattn/go-isatty v0.0.20 // indirect 60 | github.com/mattn/go-runewidth v0.0.16 // indirect 61 | github.com/mergestat/timediff v0.0.3 // indirect 62 | github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect 63 | github.com/mitchellh/copystructure v1.2.0 // indirect 64 | github.com/mitchellh/go-homedir v1.1.0 // indirect 65 | github.com/mitchellh/mapstructure v1.5.0 // indirect 66 | github.com/mitchellh/reflectwalk v1.0.2 // indirect 67 | github.com/oklog/ulid v1.3.1 // indirect 68 | github.com/posener/complete v1.2.3 // indirect 69 | github.com/rivo/uniseg v0.4.7 // indirect 70 | github.com/samber/lo v1.37.0 // indirect 71 | github.com/shopspring/decimal v1.4.0 // indirect 72 | github.com/spf13/cast v1.7.0 // indirect 73 | github.com/spf13/cobra v1.6.1 // indirect 74 | github.com/spf13/pflag v1.0.5 // indirect 75 | github.com/thanhpk/randstr v1.0.4 // indirect 76 | github.com/yuin/goldmark v1.7.8 // indirect 77 | github.com/yuin/goldmark-meta v1.1.0 // indirect 78 | github.com/zclconf/go-cty v1.16.2 // indirect 79 | go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect 80 | go.mongodb.org/mongo-driver v1.10.0 // indirect 81 | golang.org/x/crypto v0.36.0 // indirect 82 | golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect 83 | golang.org/x/mod v0.22.0 // indirect 84 | golang.org/x/net v0.38.0 // indirect 85 | golang.org/x/oauth2 v0.8.0 // indirect 86 | golang.org/x/sync v0.12.0 // indirect 87 | golang.org/x/sys v0.31.0 // indirect 88 | golang.org/x/term v0.30.0 // indirect 89 | golang.org/x/text v0.23.0 // indirect 90 | google.golang.org/appengine v1.6.7 // indirect 91 | google.golang.org/protobuf v1.33.0 // indirect 92 | gopkg.in/yaml.v2 v2.4.0 // indirect 93 | gopkg.in/yaml.v3 v3.0.1 // indirect 94 | ) 95 | -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) HashiCorp, Inc. 2 | // SPDX-License-Identifier: MPL-2.0 3 | 4 | //go:build generate 5 | 6 | package tools 7 | 8 | import ( 9 | // document generation 10 | _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs" 11 | // copywrite header generation 12 | _ "github.com/hashicorp/copywrite" 13 | ) 14 | 15 | // Generate copyright headers 16 | //go:generate go run github.com/hashicorp/copywrite headers -d .. --config ../.copywrite.hcl 17 | // Format Terraform code for use in documentation. 18 | // If you do not have Terraform installed, you can remove the formatting command, but it is suggested 19 | // to ensure the documentation is formatted properly. 20 | //go:generate terraform fmt -recursive ../examples/ 21 | // Generate documentation. 22 | //go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate --provider-dir .. 23 | -------------------------------------------------------------------------------- /version/VERSION: -------------------------------------------------------------------------------- 1 | 3.2.4 2 | --------------------------------------------------------------------------------