mirror of
https://github.com/hashicorp/terraform.git
synced 2026-05-28 04:03:27 -04:00
Merge branch 'main' into patch-1
This commit is contained in:
commit
a3948bad06
3660 changed files with 357525 additions and 65346 deletions
0
.changes/1.13.0.md
Normal file
0
.changes/1.13.0.md
Normal file
5
.changes/README.md
Normal file
5
.changes/README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Changelog
|
||||
|
||||
This directory contains changelog entries for each release of Terraform.
|
||||
The only important folder for changes is the `vX.XX` folder corresponding with the Terraform version released from this branch.
|
||||
All other folders are just there to make backports easier. You can remove folders with releases we won't allow backports for.
|
||||
10
.changes/footer-with-experiments.md
Normal file
10
.changes/footer-with-experiments.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
EXPERIMENTS:
|
||||
|
||||
Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases.
|
||||
|
||||
- The new command `terraform rpcapi` exposes some Terraform Core functionality through an RPC interface compatible with [`go-plugin`](https://github.com/hashicorp/go-plugin). The exact RPC API exposed here is currently subject to change at any time, because it's here primarily as a vehicle to support the [Terraform Stacks](https://www.hashicorp.com/blog/terraform-stacks-explained) private preview and so will be broken if necessary to respond to feedback from private preview participants, or possibly for other reasons. Do not use this mechanism yet outside of Terraform Stacks private preview.
|
||||
- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. This experiment is under active development, and so it's not yet useful to participate in this experiment
|
||||
|
||||
## Previous Releases
|
||||
|
||||
For information on prior major and minor releases, refer to their changelogs:
|
||||
3
.changes/footer.md
Normal file
3
.changes/footer.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
## Previous Releases
|
||||
|
||||
For information on prior major and minor releases, refer to their changelogs:
|
||||
18
.changes/previous-releases.md
Normal file
18
.changes/previous-releases.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
- [v1.12](https://github.com/hashicorp/terraform/blob/v1.12/CHANGELOG.md)
|
||||
- [v1.11](https://github.com/hashicorp/terraform/blob/v1.11/CHANGELOG.md)
|
||||
- [v1.10](https://github.com/hashicorp/terraform/blob/v1.10/CHANGELOG.md)
|
||||
- [v1.9](https://github.com/hashicorp/terraform/blob/v1.9/CHANGELOG.md)
|
||||
- [v1.8](https://github.com/hashicorp/terraform/blob/v1.8/CHANGELOG.md)
|
||||
- [v1.7](https://github.com/hashicorp/terraform/blob/v1.7/CHANGELOG.md)
|
||||
- [v1.6](https://github.com/hashicorp/terraform/blob/v1.6/CHANGELOG.md)
|
||||
- [v1.5](https://github.com/hashicorp/terraform/blob/v1.5/CHANGELOG.md)
|
||||
- [v1.4](https://github.com/hashicorp/terraform/blob/v1.4/CHANGELOG.md)
|
||||
- [v1.3](https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md)
|
||||
- [v1.2](https://github.com/hashicorp/terraform/blob/v1.2/CHANGELOG.md)
|
||||
- [v1.1](https://github.com/hashicorp/terraform/blob/v1.1/CHANGELOG.md)
|
||||
- [v1.0](https://github.com/hashicorp/terraform/blob/v1.0/CHANGELOG.md)
|
||||
- [v0.15](https://github.com/hashicorp/terraform/blob/v0.15/CHANGELOG.md)
|
||||
- [v0.14](https://github.com/hashicorp/terraform/blob/v0.14/CHANGELOG.md)
|
||||
- [v0.13](https://github.com/hashicorp/terraform/blob/v0.13/CHANGELOG.md)
|
||||
- [v0.12](https://github.com/hashicorp/terraform/blob/v0.12/CHANGELOG.md)
|
||||
- [v0.11 and earlier](https://github.com/hashicorp/terraform/blob/v0.11/CHANGELOG.md)
|
||||
0
.changes/v1.11/.gitkeep
Normal file
0
.changes/v1.11/.gitkeep
Normal file
5
.changes/v1.11/BUG FIXES-20250402-143931.yaml
Normal file
5
.changes/v1.11/BUG FIXES-20250402-143931.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
kind: BUG FIXES
|
||||
body: 'write-only attributes: internal providers should set write-only attributes to null'
|
||||
time: 2025-04-02T14:39:31.672249+02:00
|
||||
custom:
|
||||
Issue: "36824"
|
||||
0
.changes/v1.12/.gitkeep
Normal file
0
.changes/v1.12/.gitkeep
Normal file
5
.changes/v1.12/ENHANCEMENTS-20250303-171838.yaml
Normal file
5
.changes/v1.12/ENHANCEMENTS-20250303-171838.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
kind: ENHANCEMENTS
|
||||
body: 'backend/oss: Supports more standard environment variables to keep same with provider setting'
|
||||
time: 2025-03-03T17:18:38.679213+08:00
|
||||
custom:
|
||||
Issue: "36581"
|
||||
5
.changes/v1.12/ENHANCEMENTS-20250417-182036.yaml
Normal file
5
.changes/v1.12/ENHANCEMENTS-20250417-182036.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
kind: ENHANCEMENTS
|
||||
body: '`import` blocks: Now support importing a resource via a new identity attribute. This is mutually exclusive with the `id` attribute'
|
||||
time: 2025-04-17T18:20:36.814657+02:00
|
||||
custom:
|
||||
Issue: "36703"
|
||||
5
.changes/v1.12/NEW FEATURES-20250410-154805.yaml
Normal file
5
.changes/v1.12/NEW FEATURES-20250410-154805.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
kind: NEW FEATURES
|
||||
body: Added Terraform backend implementation for OCI Object Storage
|
||||
time: 2025-04-10T15:48:05.919664+05:30
|
||||
custom:
|
||||
Issue: "34465"
|
||||
0
.changes/v1.13/.gitkeep
Normal file
0
.changes/v1.13/.gitkeep
Normal file
5
.changes/v1.13/ENHANCEMENTS-20250508-130135.yaml
Normal file
5
.changes/v1.13/ENHANCEMENTS-20250508-130135.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
kind: ENHANCEMENTS
|
||||
body: Filesystem functions are now checked for consistent results to catch invalid data during apply
|
||||
time: 2025-05-08T13:01:35.450576-04:00
|
||||
custom:
|
||||
Issue: "37001"
|
||||
32
.changie.yaml
Normal file
32
.changie.yaml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
changesDir: .changes
|
||||
unreleasedDir: v1.13
|
||||
versionFooterPath: version_footer.tpl.md
|
||||
changelogPath: CHANGELOG.md
|
||||
versionExt: md
|
||||
versionFormat: '## {{.Version}} ({{.Time.Format "January 2, 2006"}})'
|
||||
kindFormat: "{{.Kind}}:"
|
||||
changeFormat: "* {{.Body}} {{- if .Custom.Issue }} ([#{{.Custom.Issue}}](https://github.com/hashicorp/terraform/issues/{{.Custom.Issue}})){{- end}}"
|
||||
custom:
|
||||
- key: Issue
|
||||
label: Issue/PR Number
|
||||
type: int
|
||||
minInt: 1
|
||||
kinds:
|
||||
- label: NEW FEATURES
|
||||
- label: ENHANCEMENTS
|
||||
- label: BUG FIXES
|
||||
- label: NOTES
|
||||
- label: UPGRADE NOTES
|
||||
- label: BREAKING CHANGES
|
||||
newlines:
|
||||
afterChangelogHeader: 0
|
||||
beforeKind: 1
|
||||
afterKind: 1
|
||||
afterChange: 1
|
||||
afterVersion: 1
|
||||
beforeChangelogVersion: 0
|
||||
endOfVersion: 2
|
||||
envPrefix: CHANGIE_
|
||||
21
.copywrite.hcl
Normal file
21
.copywrite.hcl
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
schema_version = 1
|
||||
|
||||
project {
|
||||
license = "BUSL-1.1"
|
||||
copyright_year = 2024
|
||||
|
||||
# (OPTIONAL) A list of globs that should not have copyright/license headers.
|
||||
# Supports doublestar glob patterns for more flexibility in defining which
|
||||
# files or folders should be ignored
|
||||
header_ignore = [
|
||||
"**/*.tf",
|
||||
"**/testdata/**",
|
||||
"**/*.pb.go",
|
||||
"**/*_string.go",
|
||||
"**/mock*.go",
|
||||
".changes/**",
|
||||
# these directories have their own copywrite config
|
||||
"docs/plugin-protocol/**",
|
||||
"internal/tfplugin*/**"
|
||||
]
|
||||
}
|
||||
124
.github/CONTRIBUTING.md
vendored
124
.github/CONTRIBUTING.md
vendored
|
|
@ -1,26 +1,21 @@
|
|||
# Contributing to Terraform
|
||||
|
||||
This repository contains only Terraform core, which includes the command line interface and the main graph engine. Providers are implemented as plugins that each have their own repository linked from the [Terraform Registry index](https://registry.terraform.io/browse/providers). Instructions for developing each provider are usually in the associated README file. For more information, see [the provider development overview](https://www.terraform.io/docs/plugins/provider.html).
|
||||
|
||||
---
|
||||
|
||||
**Note:** Due to current low staffing on the Terraform Core team at HashiCorp, **we are not routinely reviewing and merging community-submitted pull requests**. We do hope to begin processing them again soon once we're back up to full staffing again, but for the moment we need to ask for patience. Thanks!
|
||||
|
||||
**Additional note:** The intent of the prior comment was to provide clarity for the community around what to expect for a small part of the work related to Terraform. This does not affect other PR reviews, such as those for Terraform providers. We expect that the relevant team will be appropriately staffed within the coming weeks, which should allow us to get back to normal community PR review practices. For the broader context and information on HashiCorp’s continued commitment to and investment in Terraform, see [this blog post](https://www.hashicorp.com/blog/terraform-community-contributions).
|
||||
|
||||
---
|
||||
|
||||
**All communication on GitHub, the community forum, and other HashiCorp-provided communication channels is subject to [the HashiCorp community guidelines](https://www.hashicorp.com/community-guidelines).**
|
||||
|
||||
This document provides guidance on Terraform contribution recommended practices. It covers what we're looking for in order to help set some expectations and help you get the most out of participation in this project.
|
||||
This repository contains Terraform core, which includes the command line interface and the main graph engine.
|
||||
|
||||
To record a bug report, enhancement proposal, or give any other product feedback, please [open a GitHub issue](https://github.com/hashicorp/terraform/issues/new/choose) using the most appropriate issue template. Please do fill in all of the information the issue templates request, because we've seen from experience that this will maximize the chance that we'll be able to act on your feedback.
|
||||
Providers are implemented as plugins that each have their own repository linked from the [Terraform Registry index](https://registry.terraform.io/browse/providers). Instructions for developing each provider are usually in the associated README file. For more information, see [the provider development overview](https://developer.hashicorp.com/terraform/plugin).
|
||||
|
||||
This document provides guidance on Terraform contribution recommended practices. It covers what we're looking for in order to help set expectations and help you get the most out of participation in this project.
|
||||
|
||||
To report a bug, an enhancement proposal, or give any other product feedback, please [open a GitHub issue](https://github.com/hashicorp/terraform/issues/new/choose) using the most appropriate issue template. Please fill in all of the information the issue templates request. This will maximize our ability to act on your feedback.
|
||||
|
||||
---
|
||||
|
||||
<!-- MarkdownTOC autolink="true" -->
|
||||
|
||||
- [Contributing Fixes](#contributing-fixes)
|
||||
- [Introduction](#Introduction)
|
||||
- [Contributing a Pull Request](#contributing-a-pull-request)
|
||||
- [Proposing a Change](#proposing-a-change)
|
||||
- [Caveats & areas of special concern](#caveats--areas-of-special-concern)
|
||||
- [State Storage Backends](#state-storage-backends)
|
||||
|
|
@ -28,6 +23,9 @@ To record a bug report, enhancement proposal, or give any other product feedback
|
|||
- [Maintainers](#maintainers)
|
||||
- [Pull Request Lifecycle](#pull-request-lifecycle)
|
||||
- [Getting Your Pull Requests Merged Faster](#getting-your-pull-requests-merged-faster)
|
||||
- [Changelog entries](#changelog-entries)
|
||||
- [Create a change file using `changie`](#create-a-change-file-using-changie)
|
||||
- [Backport a PR to a past release](#backport-a-pr-to-a-past-release)
|
||||
- [PR Checks](#pr-checks)
|
||||
- [Terraform CLI/Core Development Environment](#terraform-clicore-development-environment)
|
||||
- [Acceptance Tests: Testing interactions with external services](#acceptance-tests-testing-interactions-with-external-services)
|
||||
|
|
@ -36,15 +34,31 @@ To record a bug report, enhancement proposal, or give any other product feedback
|
|||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Contributing Fixes
|
||||
## Introduction
|
||||
|
||||
It can be tempting to want to dive into an open source project and help _build the thing_ you believe you're missing. It's a wonderful and helpful intention. However, Terraform is a complex tool. Many seemingly simple changes can have serious effects on other areas of the code and it can take some time to become familiar with the effects of even basic changes. The Terraform team is not immune to unintended and sometimes undesirable changes. We do take our work seriously, and appreciate the globally diverse community that relies on Terraform for workflows of all sizes and criticality.
|
||||
One of the great things about publicly available source code is that you can dive into the project and help _build the thing_ you believe is missing. It's a wonderful and generous instinct. However, Terraform is a complex tool. Even simple changes can have a serious impact on other areas of the code and it can take some time to become familiar with the effects of even basic changes. The Terraform team is not immune to unintended and sometimes undesirable consequences. We take our work seriously, and appreciate the responsibility of maintaining software for a globally diverse community that relies on Terraform for workflows of all sizes and criticality.
|
||||
|
||||
As a result of Terraform's complexity and high bar for stability, the most straightforward way to start helping with the Terraform project is to pick an existing bug and [get to work](#terraform-clicore-development-environment).
|
||||
As a result of Terraform's complexity and high bar for stability, the most straightforward way to help with the Terraform project is to [file a feature request or bug report](https://github.com/hashicorp/terraform/issues/new/choose), following the template to fully express your desired use case.
|
||||
|
||||
For new contributors we've labeled a few issues with `Good First Issue` as a nod to issues which will help get you familiar with Terraform development, while also providing an onramp to the codebase itself.
|
||||
If you believe you can also implement the solution for your bug or feature, we request that you first discuss the proposed solution with the core maintainer team. This discussion happens in GitHub, on the issue you created to describe the bug or feature. This discussion gives the core team a chance to explore any missing best practices or unintended consequences of the proposed change. Participating in this discussion and getting the go-ahead from a core maintainer is the only way to ensure your code is reviewed for inclusion with the project. It is also possible that the proposed solution is not workable, and will save you time writing code that will not be used due to unforeseen unintended consequences. Please read the section [Proposing a Change](#proposing-a-change) for the full details on this process.
|
||||
|
||||
(As a side note, this is how we work internally at HashiCorp as well. Changes are proposed internally via an RFC process, in which all impacted teams are able to review the proposed changes and give feedback before any code is written. Written communication of changes via the RFC process is a core pillar of our internal coordination.)
|
||||
|
||||
|
||||
## Contributing a Pull Request
|
||||
|
||||
If you are a new contributor to Terraform, or looking to get started committing to the Terraform ecosystem, here are a couple of tips to get started.
|
||||
|
||||
First, the easiest way to get started is to make fixes or improvements to the documentation. This can be done completely within GitHub, no need to even clone the project!
|
||||
|
||||
Beyond documentation improvements, it is easiest to contribute to Terraform on the edges. If you are looking for a good starting place to contribute, finding and resolving issues in the providers is the best first step. These projects have huge breadth of coverage and are always looking for contributors to fix issues that might not otherwise get the attention of a maintainer.
|
||||
|
||||
Closer to home, within the Terraform core repository, working in areas like functions or backends tend to have less harmful unintended interactions with the core of Terraform (but, also, are not currently a high priority to be reviewed, so please discuss any changes with the team before you start.) It gets more difficult to contribute as you get closer to the core functionality (e.g., manipulating the graph and core language features). For these types of changes, please start with the [Proposing a Change](#proposing-a-change) section to understand how we think about managing this process.
|
||||
|
||||
Once you are ready to write code, please see the section [Terraform CLI/Core Development Environment](#terraform-clicore-development-environment) to create your dev environment. Please read the documentation, and don't be afraid to ask questions in our [community forum](https://discuss.hashicorp.com/c/terraform-core/27).
|
||||
|
||||
You may see the `Good First Issue` label on issues in the Terraform repository on GitHub. We use this label to maintain a list of issues for new internal core team members to ramp up the codebase. That said, if you are feeling particularly ambitious, you can follow our process to propose a solution. Other HashiCorp repositories (for example, https://github.com/hashicorp/terraform-provider-aws/) do use the `Good First Issue` to indicate good issues for external contributors to get started.
|
||||
|
||||
Read the documentation, and don't be afraid to [ask questions](https://discuss.hashicorp.com/c/terraform-core/27).
|
||||
|
||||
## Proposing a Change
|
||||
|
||||
|
|
@ -52,13 +66,14 @@ In order to be respectful of the time of community contributors, we aim to discu
|
|||
|
||||
If the bug you wish to fix or enhancement you wish to implement isn't already covered by a GitHub issue that contains feedback from the Terraform team, please do start a discussion (either in [a new GitHub issue](https://github.com/hashicorp/terraform/issues/new/choose) or an existing one, as appropriate) before you invest significant development time. If you mention your intent to implement the change described in your issue, the Terraform team can, as best as possible, prioritize including implementation-related feedback in the subsequent discussion.
|
||||
|
||||
At this time, we do not have a formal process for reviewing outside proposals that significantly change Terraform's workflow, its primary usage patterns, and its language. Additionally, some seemingly simple proposals can have deep effects across Terraform, which is why we strongly suggest starting with an issue-based proposal.
|
||||
At this time, we do not have a formal process for reviewing outside proposals that significantly change Terraform's workflow, its primary usage patterns, and its language. Additionally, some seemingly simple proposals can have deep effects across Terraform, which is why we strongly suggest starting with an issue-based proposal. Also, we do not normally accept minor changes in comments or help text.
|
||||
|
||||
For large proposals that could entail a significant design phase, we wish to be up front with potential contributors that, unfortunately, we are unlikely to be able to give prompt feedback. We are still interested to hear about your use-cases so that we can consider ways to meet them as part of other larger projects.
|
||||
|
||||
Most changes will involve updates to the test suite, and changes to Terraform's documentation. The Terraform team can advise on different testing strategies for specific scenarios, and may ask you to revise the specific phrasing of your proposed documentation prose to match better with the standard "voice" of Terraform's documentation.
|
||||
|
||||
This repository is primarily maintained by a small team at HashiCorp along with their other responsibilities, so unfortunately we cannot always respond promptly to pull requests, particularly if they do not relate to an existing GitHub issue where the Terraform team has already participated and indicated willingness to work on the issue or accept PRs for the proposal. We *are* grateful for all contributions however, and will give feedback on pull requests as soon as we're able.
|
||||
We cannot always respond promptly to pull requests, particularly if they do not relate to an existing GitHub issue where the Terraform team has already participated and indicated willingness to work on the issue or accept PRs for the proposal. We *are* grateful for all contributions however, and will give feedback on pull requests as soon as we are able.
|
||||
|
||||
|
||||
### Caveats & areas of special concern
|
||||
|
||||
|
|
@ -66,13 +81,18 @@ There are some areas of Terraform which are of special concern to the Terraform
|
|||
|
||||
#### State Storage Backends
|
||||
|
||||
The Terraform team is not merging PRs for new state storage backends at the current time. Our priority regarding state storage backends is to find maintainers for existing backends and remove those backends without maintainers.
|
||||
The Terraform team is not merging PRs for new state storage backends. Our priority regarding state storage backends is to find maintainers for existing backends and remove those backends without maintainers.
|
||||
|
||||
Please see the [CODEOWNERS](https://github.com/hashicorp/terraform/blob/main/CODEOWNERS) file for the status of a given backend. Community members with an interest in a particular standard backend are welcome to help maintain it.
|
||||
Please see the [CODEOWNERS](https://github.com/hashicorp/terraform/blob/main/CODEOWNERS) file for the status of a given backend. Community members with an interest in a particular backend are welcome to offer to maintain it.
|
||||
|
||||
Currently, merging state storage backends places a significant burden on the Terraform team. The team must set up an environment and cloud service provider account, or a new database/storage/key-value service, in order to build and test remote state storage backends. The time and complexity of doing so prevents us from moving Terraform forward in other ways.
|
||||
In terms of setting expectations, there are three categories of backends in the Terraform repository: backends maintained by the core team (ex.: http); backends maintained by one of HashiCorp's provider teams (e.g. AWS S3, Azure, etc); and backends maintained by third party maintainers (ex.: Postgres, COS).
|
||||
|
||||
* Backends maintained by the core team are unlikely to see accepted contributions. We are triaging incoming pull requests, but these are not highly prioritized against our other work. The smaller and more-contained the change, the more likely it will be reviewed (please see also [Proposing a Change](#proposing-a-change)).
|
||||
|
||||
* Backends maintained by one of HashiCorp's provider teams review contributions irregularly. There is no official commitment, typically once every few months one of the maintainers will review a number of backend PRs relating to their provider. The S3 and Azure backends tend to see the most on-going development.
|
||||
|
||||
* Backends maintained by third-party maintainers are reviewed at the whim and availability of those maintainers. When the maintainer gives a positive code review to the pull request, the core team will do a review and merge the changes.
|
||||
|
||||
We are working to remove ourselves from the critical path of state storage backends by moving them towards a plugin model. In the meantime, we won't be accepting new remote state backends into Terraform.
|
||||
|
||||
#### Provisioners
|
||||
|
||||
|
|
@ -80,17 +100,18 @@ Provisioners are an area of concern in Terraform for a number of reasons. Chiefl
|
|||
|
||||
There are two main types of provisioners in Terraform, the generic provisioners (`file`,`local-exec`, and `remote-exec`) and the tool-specific provisioners (`chef`, `habbitat`, `puppet` & `salt-masterless`). **The tool-specific provisioners [are deprecated](https://discuss.hashicorp.com/t/notice-terraform-to-begin-deprecation-of-vendor-tool-specific-provisioners-starting-in-terraform-0-13-4/13997).** In practice this means we will not be accepting PRs for these areas of the codebase.
|
||||
|
||||
From our [documentation](https://www.terraform.io/docs/provisioners/index.html):
|
||||
From our [documentation](https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax):
|
||||
|
||||
> ... they [...] add a considerable amount of complexity and uncertainty to Terraform usage.[...] we still recommend attempting to solve it [your problem] using other techniques first, and use provisioners only if there is no other option.
|
||||
|
||||
The Terraform team is in the process of building a way forward which continues to decrease reliance on provisioners. In the mean time however, as our documentation indicates, they are a tool of last resort. As such expect that PRs and issues for provisioners are not high in priority.
|
||||
|
||||
Please see the [CODEOWNERS](https://github.com/hashicorp/terraform/blob/main/CODEOWNERS) file for the status of a given provisioner. Community members with an interest in a particular provisioner are welcome to help maintain it.
|
||||
Please see the [CODEOWNERS](https://github.com/hashicorp/terraform/blob/main/CODEOWNERS) file for the status of a given provisioner.
|
||||
|
||||
|
||||
#### Maintainers
|
||||
|
||||
Maintainers are key contributors to our Open Source project. They contribute their time and expertise and we ask that the community take extra special care to be mindful of this when interacting with them.
|
||||
Maintainers are key contributors to our community project. They contribute their time and expertise and we ask that the community take extra special care to be mindful of this when interacting with them.
|
||||
|
||||
For code that has a listed maintainer or maintainers in our [CODEOWNERS](https://github.com/hashicorp/terraform/blob/main/CODEOWNERS) file, the Terraform team will highlight them for participation in PRs which relate to the area of code they maintain. The expectation is that a maintainer will review the code and work with the PR contributor before the code is merged by the Terraform team.
|
||||
|
||||
|
|
@ -98,14 +119,16 @@ There is no expectation on response time for our maintainers; they may be indisp
|
|||
|
||||
If an an unmaintained area of code interests you and you'd like to become a maintainer, you may simply make a PR against our [CODEOWNERS](https://github.com/hashicorp/terraform/blob/main/CODEOWNERS) file with your github handle attached to the approriate area. If there is a maintainer or team of maintainers for that area, please coordinate with them as necessary.
|
||||
|
||||
|
||||
### Pull Request Lifecycle
|
||||
|
||||
1. You are welcome to submit a [draft pull request](https://github.blog/2019-02-14-introducing-draft-pull-requests/) for commentary or review before it is fully completed. It's also a good idea to include specific questions or items you'd like feedback on.
|
||||
2. Once you believe your pull request is ready to be merged you can create your pull request.
|
||||
3. When time permits Terraform's core team members will look over your contribution and either merge, or provide comments letting you know if there is anything left to do. It may take some time for us to respond. We may also have questions that we need answered about the code, either because something doesn't make sense to us or because we want to understand your thought process. We kindly ask that you do not target specific team members.
|
||||
4. If we have requested changes, you can either make those changes or, if you disagree with the suggested changes, we can have a conversation about our reasoning and agree on a path forward. This may be a multi-step process. Our view is that pull requests are a chance to collaborate, and we welcome conversations about how to do things better. It is the contributor's responsibility to address any changes requested. While reviewers are happy to give guidance, it is unsustainable for us to perform the coding work necessary to get a PR into a mergeable state.
|
||||
5. Once all outstanding comments and checklist items have been addressed, your contribution will be merged! Merged PRs may or may not be included in the next release based on changes the Terraform teams deems as breaking or not. The core team takes care of updating the [CHANGELOG.md](https://github.com/hashicorp/terraform/blob/main/CHANGELOG.md) as they merge.
|
||||
6. In some cases, we might decide that a PR should be closed without merging. We'll make sure to provide clear reasoning when this happens. Following the recommended process above is one of the ways to ensure you don't spend time on a PR we can't or won't merge.
|
||||
3. If your change is user-facing, add a short description in a [changelog entry](#changelog-entries).
|
||||
4. When time permits Terraform's core team members will look over your contribution and either merge, or provide comments letting you know if there is anything left to do. It may take some time for us to respond. We may also have questions that we need answered about the code, either because something doesn't make sense to us or because we want to understand your thought process. We kindly ask that you do not target specific team members.
|
||||
5. If we have requested changes, you can either make those changes or, if you disagree with the suggested changes, we can have a conversation about our reasoning and agree on a path forward. This may be a multi-step process. Our view is that pull requests are a chance to collaborate, and we welcome conversations about how to do things better. It is the contributor's responsibility to address any changes requested. While reviewers are happy to give guidance, it is unsustainable for us to perform the coding work necessary to get a PR into a mergeable state.
|
||||
6. Once all outstanding comments and checklist items have been addressed, your contribution will be merged! Merged PRs may or may not be included in the next release based on changes the Terraform teams deems as breaking or not. The core team takes care of updating the [CHANGELOG.md](https://github.com/hashicorp/terraform/blob/main/CHANGELOG.md) as they merge.
|
||||
7. In some cases, we might decide that a PR should be closed without merging. We'll make sure to provide clear reasoning when this happens. Following the recommended process above is one of the ways to ensure you don't spend time on a PR we can't or won't merge.
|
||||
|
||||
#### Getting Your Pull Requests Merged Faster
|
||||
|
||||
|
|
@ -119,12 +142,45 @@ If we request changes, try to make those changes in a timely manner. Otherwise,
|
|||
|
||||
Even with everyone making their best effort to be responsive, it can be time-consuming to get a PR merged. It can be frustrating to deal with the back-and-forth as we make sure that we understand the changes fully. Please bear with us, and please know that we appreciate the time and energy you put into the project.
|
||||
|
||||
#### Changelog entries
|
||||
|
||||
If your PR's changes are not user-facing add the label `no-changelog-needed`. If this label isn't present and your PR doesn't include any change files a Github Action workflow will prompt you to add whichever is needed.
|
||||
|
||||
If your PR's changes are user-facing then you will need to add a change file in your PR. See the next section for how to create one. The change file will need to be created in the `.changes/v1.XX/` folder that matches the version number present in [version/VERSION on the main branch](https://github.com/hashicorp/terraform/blob/main/version/VERSION).
|
||||
|
||||
This is different if you are backporting your changes to an earlier release version. In that case, put the change file in the `.changes/v1.XX/` folder for the earliest version that the change is being backported into. For example if a PR was labelled 1.11-backport and 1.10-backport then the change file should be created in the `.changes/v1.10/` folder only.
|
||||
|
||||
|
||||
#### Create a change file using `changie`
|
||||
|
||||
If your change is user-facing you can use `npx changie new` to create a new changelog entry via your terminal. The command is interactive and you will need to: select which kind of change you're introducing, provide a short description, and enter either the number of the GitHub issue your PR closes or your PR's number.
|
||||
|
||||
Make sure to select the correct kind of change:
|
||||
|
||||
|
||||
| Change kind | When to use |
|
||||
|------------------|-------------|
|
||||
| NEW FEATURES | Use this if you've added new, separate functionality to Terraform. For example, introduction of ephemeral resources. |
|
||||
| ENHANCEMENTS | Use this if you've improved existing functionality in Terraform. Examples include: adding a new field to a remote-state backend, or adding a new environment variable to use when configuring Terraform. |
|
||||
| BUG FIXES | Use this if you've fixed a user-facing issue. Examples include: crash fixes, improvements to error feedback, regression fixes. |
|
||||
| NOTES | This is used for changes that are unlikely to cause user-facing issues but might have edge cases. For example, changes to how the Terraform binary is built. |
|
||||
| UPGRADE NOTES | Use this if you've introduced a change that forces users to take action when upgrading, or changes Terraform's behaviour notably. For example, deprecating a field on a remote-state backend or changing the output of Terraform operations. |
|
||||
| BREAKING CHANGES | Use this if you've introduced a change that could make a valid Terraform configuration stop working after a user upgrades Terraform versions. This might be paired with an upgrade note change file. Examples include: removing a field on a remote-state backend, changing a builtin function's behavior, making validation stricter. |
|
||||
|
||||
#### Backport a PR to a past release
|
||||
|
||||
PRs can be backported to previous release version as part of preparing a patch release. For example, a fix for a bug could be merged into main but also backported to one or two previous minor versions.
|
||||
|
||||
If you want to backport your PR then the PR needs to have one or more [backport labels](https://github.com/hashicorp/terraform/labels?q=backport) added. The PR reviewer will then ensure that the PR is merged into those versions' release branches, as well as merged into `main`.
|
||||
|
||||
### PR Checks
|
||||
|
||||
The following checks run when a PR is opened:
|
||||
|
||||
- Contributor License Agreement (CLA): If this is your first contribution to Terraform you will be asked to sign the CLA.
|
||||
- Tests: tests include unit tests and acceptance tests, and all tests must pass before a PR can be merged.
|
||||
- Change files: PRs that include user-facing changes should include change files (see [Pull Request Lifecycle](#pull-request-lifecycle)). Automation will verify if PRs are labelled correctly and/or contain appropriate change files.
|
||||
- Vercel: this is an internal tool that does not run correctly for external contributors. We are aware of this and work around it for external contributions.
|
||||
|
||||
----
|
||||
|
||||
|
|
@ -136,7 +192,7 @@ Terraform providers are not maintained in this repository; you can find relevant
|
|||
repository and relevant issue tracker for each provider within the
|
||||
[Terraform Registry index](https://registry.terraform.io/browse/providers).
|
||||
|
||||
This repository also does not include the source code for some other parts of the Terraform product including Terraform Cloud, Terraform Enterprise, and the Terraform Registry. Those components are not open source, though if you have feedback about them (including bug reports) please do feel free to [open a GitHub issue on this repository](https://github.com/hashicorp/terraform/issues/new/choose).
|
||||
This repository also does not include the source code for some other parts of the Terraform product including HCP Terraform, Terraform Enterprise, and the Terraform Registry. The source for those components is not publicly available. If you have feedback about these products, including bug reports, please email [tf-cloud@hashicorp.support](mailto:tf-cloud@hashicorp.support) or [open a support request](https://support.hashicorp.com/hc/en-us/requests/new).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -144,7 +200,7 @@ If you wish to work on the Terraform CLI source code, you'll first need to insta
|
|||
|
||||
At this time the Terraform development environment is targeting only Linux and Mac OS X systems. While Terraform itself is compatible with Windows, unfortunately the unit test suite currently contains Unix-specific assumptions around maximum path lengths, path separators, etc.
|
||||
|
||||
Refer to the file [`.go-version`](https://github.com/hashicorp/terraform/blob/main/.go-version) to see which version of Go Terraform is currently built with. Other versions will often work, but if you run into any build or testing problems please try with the specific Go version indicated. You can optionally simplify the installation of multiple specific versions of Go on your system by installing [`goenv`](https://github.com/syndbg/goenv), which reads `.go-version` and automatically selects the correct Go version.
|
||||
Refer to the file [`.go-version`](https://github.com/hashicorp/terraform/blob/main/.go-version) to see which version of Go Terraform is currently built with. As of Go 1.21, the `go` command (e.g. in `go build`) will automatically install the version of the Go toolchain corresponding to the version specified in `go.mod`, if it is newer than the version you have installed. The version in `go.mod` is considered the _minimum_ compatible Go version for Terraform, while the version in `.go-version` is what the production binary is actually built with.
|
||||
|
||||
Use Git to clone this repository into a location of your choice. Terraform is using [Go Modules](https://blog.golang.org/using-go-modules), and so you should *not* clone it inside your `GOPATH`.
|
||||
|
||||
|
|
@ -180,7 +236,7 @@ go test ./internal/addrs
|
|||
|
||||
Terraform's unit test suite is self-contained, using mocks and local files to help ensure that it can run offline and is unlikely to be broken by changes to outside systems.
|
||||
|
||||
However, several Terraform components interact with external services, such as the automatic provider installation mechanism, the Terraform Registry, Terraform Cloud, etc.
|
||||
However, several Terraform components interact with external services, such as the automatic provider installation mechanism, the Terraform Registry, HCP Terraform, Terraform Enterprise, etc.
|
||||
|
||||
There are some optional tests in the Terraform CLI codebase that *do* interact with external services, which we collectively refer to as "acceptance tests". You can enable these by setting the environment variable `TF_ACC=1` when running the tests. We recommend focusing only on the specific package you are working on when enabling acceptance tests, both because it can help the test run to complete faster and because you are less likely to encounter failures due to drift in systems unrelated to your current goal:
|
||||
|
||||
|
|
|
|||
28
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
28
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -1,3 +1,6 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
name: Bug Report
|
||||
description: Let us know about an unexpected error, a crash, or an incorrect behavior.
|
||||
labels: ["bug", "new"]
|
||||
|
|
@ -9,10 +12,11 @@ body:
|
|||
|
||||
The [hashicorp/terraform](https://github.com/hashicorp/terraform) issue tracker is reserved for bug reports relating to the core Terraform CLI application and configuration language.
|
||||
|
||||
For general usage questions, please see: https://www.terraform.io/community.html.
|
||||
For general usage questions, please see the [Community Forum](https://discuss.hashicorp.com/c/terraform-core/27).
|
||||
|
||||
## If your issue relates to:
|
||||
* **Terraform Cloud/Enterprise**: please email tf-cloud@hashicorp.support or [open a new request](https://support.hashicorp.com/hc/en-us/requests/new).
|
||||
* **HCP Terraform or Terraform Enterprise**: please email tf-cloud@hashicorp.support or [open a new request](https://support.hashicorp.com/hc/en-us/requests/new).
|
||||
* **Terraform Registry**: please email terraform-registry@hashicorp.com.
|
||||
* **AWS Terraform Provider**: Open an issue at [hashicorp/terraform-provider-aws](https://github.com/hashicorp/terraform-provider-aws/issues/new/choose).
|
||||
* **Azure Terraform Provider**: Open an issue at [hashicorp/terraform-provider-azurerm](https://github.com/hashicorp/terraform-provider-azurerm/issues/new/choose).
|
||||
* **Other Terraform Providers**: Please open an issue in the provider's own repository, which can be found by searching the [Terraform Registry](https://registry.terraform.io/browse/providers).
|
||||
|
|
@ -26,7 +30,7 @@ body:
|
|||
* Set defaults on (or omit) any variables. The person reproducing it should not need to invent variable settings
|
||||
* If multiple steps are required, such as running terraform twice, consider scripting it in a simple shell script. Providing a script can be easier than explaining what changes to make to the config between runs.
|
||||
* Omit any unneeded complexity: remove variables, conditional statements, functions, modules, providers, and resources that are not needed to trigger the bug
|
||||
* When possible, use the [null resource](https://www.terraform.io/docs/providers/null/resource.html) provider rather than a real provider in order to minimize external dependencies. We know this isn't always feasible. The Terraform Core team doesn't have deep domain knowledge in every provider, or access to every cloud platform for reproduction cases.
|
||||
* When possible, use the [null resource](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) provider rather than a real provider in order to minimize external dependencies. We know this isn't always feasible. The Terraform Core team doesn't have deep domain knowledge in every provider, or access to every cloud platform for reproduction cases.
|
||||
|
||||
- type: textarea
|
||||
id: tf-version
|
||||
|
|
@ -57,8 +61,11 @@ body:
|
|||
attributes:
|
||||
label: Debug Output
|
||||
description: Full debug output can be obtained by running Terraform with the environment variable `TF_LOG=trace`. Please create a GitHub Gist containing the debug output. Please do _not_ paste the debug output in the issue, since debug output is long. Debug output may contain sensitive information. Please review it before posting publicly.
|
||||
placeholder: ...link to gist...
|
||||
value:
|
||||
placeholder:
|
||||
value: |
|
||||
```
|
||||
...debug output, or link to a gist...
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
|
@ -117,6 +124,17 @@ body:
|
|||
value:
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: tf-genai
|
||||
attributes:
|
||||
label: Generative AI / LLM assisted development?
|
||||
description: |
|
||||
If you used a generative AI / LLM tool to assist in the development of your config, please let us know which tool you used here.
|
||||
ex. ChatGPT 3.5 / CoPilot / AWS Q / etc.
|
||||
placeholder: LLM assistance tool?
|
||||
value:
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
|
|
|||
9
.github/ISSUE_TEMPLATE/config.yml
vendored
9
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -1,8 +1,11 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Terraform Cloud/Enterprise Troubleshooting and Feature Requests
|
||||
- name: HCP Terraform and Terraform Enterprise Troubleshooting and Feature Requests
|
||||
url: https://support.hashicorp.com/hc/en-us/requests/new
|
||||
about: For issues and feature requests related to the Terraform Cloud/Enterprise platform, please submit a HashiCorp support request or email tf-cloud@hashicorp.support
|
||||
about: For issues and feature requests related to HCP Terraform or Terraform Enterprise, please submit a HashiCorp support request or email tf-cloud@hashicorp.support
|
||||
- name: AWS Terraform Provider Feedback and Questions
|
||||
url: https://github.com/hashicorp/terraform-provider-aws
|
||||
about: The AWS Terraform Provider has its own repository, any provider related issues or questions should be directed there.
|
||||
|
|
@ -17,4 +20,4 @@ contact_links:
|
|||
about: Plugin SDK has its own repository, any SDK and provider development related issues or questions should be directed there.
|
||||
- name: Terraform Usage, Language, or Workflow Questions
|
||||
url: https://discuss.hashicorp.com/c/terraform-core
|
||||
about: Please ask and answer language or workflow related questions through the Terraform Core Community Forum.
|
||||
about: Please ask and answer language or workflow related questions through the Terraform Core Community Forum.
|
||||
|
|
|
|||
76
.github/ISSUE_TEMPLATE/documentation_issue.yml
vendored
Normal file
76
.github/ISSUE_TEMPLATE/documentation_issue.yml
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
name: Documentation Issue
|
||||
description: Report an issue or suggest a change in the documentation.
|
||||
labels: ["documentation", "new"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# Thank you for opening a documentation change request.
|
||||
|
||||
Please only use the [hashicorp/terraform](https://github.com/hashicorp/terraform) `Documentation` issue type to report problems with the documentation on [https://developer.hashicorp.com/terraform/docs](). Only technical writers (not engineers) monitor this issue type. Report Terraform bugs or feature requests with the `Bug report` or `Feature Request` issue types instead to get engineering attention.
|
||||
|
||||
For general usage questions, please see the [Community Forum](https://discuss.hashicorp.com/c/terraform-core/27).
|
||||
|
||||
- type: textarea
|
||||
id: tf-version
|
||||
attributes:
|
||||
label: Terraform Version
|
||||
description: Run `terraform version` to show the version, and paste the result below. If you're not using the latest version, please check to see if something related to your request has already been implemented in a later version.
|
||||
render: shell
|
||||
placeholder: ...output of `terraform version`...
|
||||
value:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: tf-affected-pages
|
||||
attributes:
|
||||
label: Affected Pages
|
||||
description: |
|
||||
Link to the pages relevant to your documentation change request.
|
||||
placeholder:
|
||||
value:
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: tf-problem
|
||||
attributes:
|
||||
label: What is the docs issue?
|
||||
description: What problems or suggestions do you have about the documentation?
|
||||
placeholder:
|
||||
value:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: tf-proposal
|
||||
attributes:
|
||||
label: Proposal
|
||||
description: What documentation changes would fix this issue and where would you expect to find them? Are one or more page headings unclear? Do one or more pages need additional context, examples, or warnings? Do we need a new page or section dedicated to a specific topic? Your ideas help us understand what you and other users need from our documentation and how we can improve the content.
|
||||
placeholder:
|
||||
value:
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: tf-references
|
||||
attributes:
|
||||
label: References
|
||||
description: |
|
||||
Are there any other open or closed GitHub issues related to the problem or solution you described? If so, list them below. For example:
|
||||
```
|
||||
- #6017
|
||||
```
|
||||
placeholder:
|
||||
value:
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Note:** If the submit button is disabled and you have filled out all required fields, please check that you did not forget a **Title** for the issue.
|
||||
7
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
7
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
|
|
@ -1,3 +1,6 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
name: Feature Request
|
||||
description: Suggest a new feature or other enhancement.
|
||||
labels: ["enhancement", "new"]
|
||||
|
|
@ -9,10 +12,10 @@ body:
|
|||
|
||||
The [hashicorp/terraform](https://github.com/hashicorp/terraform) issue tracker is reserved for feature requests relating to the core Terraform CLI application and configuration language.
|
||||
|
||||
For general usage questions, please see: https://www.terraform.io/community.html.
|
||||
For general usage questions, please see the [Community Forum](https://discuss.hashicorp.com/c/terraform-core/27).
|
||||
|
||||
## If your feature request relates to:
|
||||
* **Terraform Cloud/Enterprise**: please email tf-cloud@hashicorp.support or [open a new request](https://support.hashicorp.com/hc/en-us/requests/new).
|
||||
* **HCP Terraform or Terraform Enterprise**: please email tf-cloud@hashicorp.support or [open a new request](https://support.hashicorp.com/hc/en-us/requests/new).
|
||||
* **AWS Terraform Provider**: Open an issue at [hashicorp/terraform-provider-aws](https://github.com/hashicorp/terraform-provider-aws/issues/new/choose).
|
||||
* **Azure Terraform Provider**: Open an issue at [hashicorp/terraform-provider-azurerm](https://github.com/hashicorp/terraform-provider-azurerm/issues/new/choose).
|
||||
* **Other Terraform Providers**: Please open an issue in the provider's own repository, which can be found by searching the [Terraform Registry](https://registry.terraform.io/browse/providers).
|
||||
|
|
|
|||
79
.github/actions/equivalence-test/action.yml
vendored
Normal file
79
.github/actions/equivalence-test/action.yml
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
name: equivalence-test
|
||||
description: "Execute the suite of Terraform equivalence tests in testing/equivalence-tests and update the golden files."
|
||||
inputs:
|
||||
target-equivalence-test-version:
|
||||
description: "The version of the Terraform equivalence tests to use."
|
||||
default: "0.3.0"
|
||||
target-os:
|
||||
description: "Current operating system"
|
||||
default: "linux"
|
||||
target-arch:
|
||||
description: "Current architecture"
|
||||
default: "amd64"
|
||||
current-branch:
|
||||
description: "What branch are we currently on?"
|
||||
required: true
|
||||
new-branch:
|
||||
description: "Name of new branch to be created for the review."
|
||||
required: true
|
||||
reviewers:
|
||||
description: "Comma-separated list of GitHub usernames to request review from."
|
||||
required: true
|
||||
message:
|
||||
description: "Message to include in the commit."
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
|
||||
- name: "download equivalence test binary"
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/equivalence-test.sh download_equivalence_test_binary \
|
||||
${{ inputs.target-equivalence-test-version }} \
|
||||
./bin/equivalence-tests \
|
||||
${{ inputs.target-os }} \
|
||||
${{ inputs.target-arch }}
|
||||
|
||||
- name: Build terraform
|
||||
shell: bash
|
||||
run: ./.github/scripts/equivalence-test.sh build_terraform_binary ./bin/terraform
|
||||
|
||||
- name: "run and update equivalence tests"
|
||||
id: execute
|
||||
shell: bash
|
||||
run: |
|
||||
./bin/equivalence-tests update \
|
||||
--tests=testing/equivalence-tests/tests \
|
||||
--goldens=testing/equivalence-tests/outputs \
|
||||
--binary=$(pwd)/bin/terraform
|
||||
|
||||
git add --intent-to-add testing/equivalence-tests/outputs
|
||||
changed=$(git diff --quiet -- testing/equivalence-tests/outputs || echo true)
|
||||
echo "changed=$changed" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: "branch, commit, and push changes"
|
||||
if: steps.execute.outputs.changed == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
git config user.name "hc-github-team-tf-core"
|
||||
git config user.email "github-team-tf-core@hashicorp.com"
|
||||
git checkout -b ${{ inputs.new-branch }}
|
||||
git add testing/equivalence-tests/outputs
|
||||
git commit -m "Update equivalence test golden files."
|
||||
git push --set-upstream origin ${{ inputs.new-branch }}
|
||||
|
||||
- name: "create pull request"
|
||||
if: steps.execute.outputs.changed == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
gh pr create \
|
||||
--draft \
|
||||
--base ${{ inputs.current-branch }} \
|
||||
--head ${{ inputs.new-branch }} \
|
||||
--title "Update equivalence test golden files" \
|
||||
--body '${{ inputs.message }}' \
|
||||
--reviewer ${{ inputs.reviewers }}
|
||||
5
.github/actions/go-version/action.yml
vendored
5
.github/actions/go-version/action.yml
vendored
|
|
@ -1,3 +1,6 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
name: 'Determine Go Toolchain Version'
|
||||
description: 'Uses the .go-version file to determine which Go toolchain to use for any Go-related actions downstream.'
|
||||
outputs:
|
||||
|
|
@ -20,4 +23,4 @@ runs:
|
|||
# complex for automation.
|
||||
run: |
|
||||
echo "Building with Go $(cat .go-version)"
|
||||
echo "::set-output name=version::$(cat .go-version)"
|
||||
echo "version=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
|
|
|
|||
30
.github/dependabot.yml
vendored
Normal file
30
.github/dependabot.yml
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: gomod
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
labels:
|
||||
- dependencies
|
||||
- go
|
||||
- security
|
||||
# Disable regular version updates and only use Dependabot for security updates
|
||||
open-pull-requests-limit: 0
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: monthly
|
||||
labels:
|
||||
- dependencies
|
||||
- build
|
||||
- security
|
||||
reviewers:
|
||||
- hashicorp/terraform-core
|
||||
groups:
|
||||
github-actions-breaking:
|
||||
update-types:
|
||||
- major
|
||||
github-actions-backward-compatible:
|
||||
update-types:
|
||||
- minor
|
||||
- patch
|
||||
46
.github/pull_request_template.md
vendored
Normal file
46
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<!--
|
||||
|
||||
Describe in detail the changes you are proposing, and the rationale.
|
||||
|
||||
See the contributing guide:
|
||||
|
||||
https://github.com/hashicorp/terraform/blob/main/.github/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
||||
<!--
|
||||
|
||||
Link all GitHub issues fixed by this PR, and add references to prior
|
||||
related PRs.
|
||||
|
||||
-->
|
||||
|
||||
Fixes #
|
||||
|
||||
## Target Release
|
||||
|
||||
<!--
|
||||
|
||||
In normal circumstances we only target changes at the upcoming minor
|
||||
release, or as a patch to the current minor version. If you need to
|
||||
port a security fix to an older release, highlight this here by listing
|
||||
all targeted releases.
|
||||
|
||||
If targeting the next patch release, also add the relevant x.y-backport
|
||||
label to enable the backport bot.
|
||||
|
||||
-->
|
||||
|
||||
1.13.x
|
||||
|
||||
## CHANGELOG entry
|
||||
|
||||
<!--
|
||||
|
||||
If your change is user-facing, add a short description in a changelog entry.
|
||||
You can use `npx changie new` to create a new changelog entry or manually create a new file in the .changes/unreleasd directory (or .changes/backported if it's a bug fix that should be backported).
|
||||
|
||||
-->
|
||||
|
||||
- [ ] This change is user-facing and I added a changelog entry.
|
||||
- [ ] This change is not user-facing.
|
||||
18
.github/scripts/e2e_test_linux_darwin.sh
vendored
Executable file
18
.github/scripts/e2e_test_linux_darwin.sh
vendored
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
if [[ $arch == 'arm' || $arch == 'arm64' ]]
|
||||
then
|
||||
export DIR=$(mktemp -d)
|
||||
unzip -d $DIR "${e2e_cache_path}/terraform-e2etest_${os}_${arch}.zip"
|
||||
unzip -d $DIR "./terraform_${version}_${os}_${arch}.zip"
|
||||
sudo chmod +x $DIR/e2etest
|
||||
docker run --platform=linux/arm64 -v $DIR:/src -w /src arm64v8/alpine ./e2etest -test.v
|
||||
else
|
||||
unzip "${e2e_cache_path}/terraform-e2etest_${os}_${arch}.zip"
|
||||
unzip "./terraform_${version}_${os}_${arch}.zip"
|
||||
TF_ACC=1 ./e2etest -test.v
|
||||
fi
|
||||
157
.github/scripts/equivalence-test.sh
vendored
Executable file
157
.github/scripts/equivalence-test.sh
vendored
Executable file
|
|
@ -0,0 +1,157 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
function usage {
|
||||
cat <<-'EOF'
|
||||
Usage: ./equivalence-test.sh <command> [<args>] [<options>]
|
||||
|
||||
Description:
|
||||
This script will handle various commands related to the execution of the
|
||||
Terraform equivalence tests.
|
||||
|
||||
Commands:
|
||||
get_target_branch <version>
|
||||
get_target_branch returns the default target branch for a given Terraform
|
||||
version.
|
||||
|
||||
target_branch=$(./equivalence-test.sh get_target_branch v1.4.3); target_branch=v1.4
|
||||
target_branch=$(./equivalence-test.sh get_target_branch 1.4.3); target_branch=v1.4
|
||||
|
||||
download_equivalence_test_binary <version> <target> <os> <arch>
|
||||
download_equivalence_test_binary downloads the equivalence testing binary
|
||||
for a given version and places it at the target path.
|
||||
|
||||
./equivalence-test.sh download_equivalence_test_binary 0.3.0 ./bin/terraform-equivalence-testing linux amd64
|
||||
|
||||
build_terraform_binary <target>
|
||||
download_terraform_binary builds the Terraform binary and places it at the
|
||||
target path.
|
||||
|
||||
./equivalence-test.sh build_terraform_binary ./bin/terraform
|
||||
EOF
|
||||
}
|
||||
|
||||
function download_equivalence_test_binary {
|
||||
VERSION="${1:-}"
|
||||
TARGET="${2:-}"
|
||||
OS="${3:-}"
|
||||
ARCH="${4:-}"
|
||||
|
||||
if [[ -z "$VERSION" || -z "$TARGET" || -z "$OS" || -z "$ARCH" ]]; then
|
||||
echo "missing at least one of [<version>, <target>, <os>, <arch>] arguments"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
curl \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
"https://api.github.com/repos/hashicorp/terraform-equivalence-testing/releases" > releases.json
|
||||
|
||||
ASSET="terraform-equivalence-testing_v${VERSION}_${OS}_${ARCH}.zip"
|
||||
ASSET_ID=$(jq -r --arg VERSION "v$VERSION" --arg ASSET "$ASSET" '.[] | select(.name == $VERSION) | .assets[] | select(.name == $ASSET) | .id' releases.json)
|
||||
|
||||
mkdir -p zip
|
||||
curl -L \
|
||||
-H "Accept: application/octet-stream" \
|
||||
"https://api.github.com/repos/hashicorp/terraform-equivalence-testing/releases/assets/$ASSET_ID" > "zip/$ASSET"
|
||||
|
||||
mkdir -p bin
|
||||
unzip -p "zip/$ASSET" terraform-equivalence-testing > "$TARGET"
|
||||
chmod u+x "$TARGET"
|
||||
rm -r zip
|
||||
rm releases.json
|
||||
}
|
||||
|
||||
function build_terraform_binary {
|
||||
TARGET="${1:-}"
|
||||
|
||||
if [[ -z "$TARGET" ]]; then
|
||||
echo "target argument"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
go build -o "$TARGET" ./
|
||||
chmod u+x "$TARGET"
|
||||
}
|
||||
|
||||
function get_target_branch {
|
||||
VERSION="${1:-}"
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "missing <version> argument"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Split off the build metadata part, if any
|
||||
# (we won't actually include it in our final version, and handle it only for
|
||||
# completeness against semver syntax.)
|
||||
IFS='+' read -ra VERSION BUILD_META <<< "$VERSION"
|
||||
|
||||
# Separate out the prerelease part, if any
|
||||
IFS='-' read -r BASE_VERSION PRERELEASE <<< "$VERSION"
|
||||
|
||||
# Separate out major, minor and patch versions.
|
||||
IFS='.' read -r MAJOR_VERSION MINOR_VERSION PATCH_VERSION <<< "$BASE_VERSION"
|
||||
|
||||
if [[ "$PRERELEASE" == *"alpha"* ]]; then
|
||||
TARGET_BRANCH=main
|
||||
else
|
||||
if [[ $MAJOR_VERSION = v* ]]; then
|
||||
TARGET_BRANCH=${MAJOR_VERSION}.${MINOR_VERSION}
|
||||
else
|
||||
TARGET_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$TARGET_BRANCH"
|
||||
}
|
||||
|
||||
function main {
|
||||
case "$1" in
|
||||
get_target_branch)
|
||||
if [ "${#@}" != 2 ]; then
|
||||
echo "invalid number of arguments"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_target_branch "$2"
|
||||
|
||||
;;
|
||||
download_equivalence_test_binary)
|
||||
if [ "${#@}" != 5 ]; then
|
||||
echo "invalid number of arguments"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
download_equivalence_test_binary "$2" "$3" "$4" "$5"
|
||||
|
||||
;;
|
||||
build_terraform_binary)
|
||||
if [ "${#@}" != 2 ]; then
|
||||
echo "invalid number of arguments"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build_terraform_binary "$2"
|
||||
|
||||
;;
|
||||
*)
|
||||
echo "unrecognized command $*"
|
||||
usage
|
||||
exit 1
|
||||
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
exit $?
|
||||
41
.github/scripts/get_product_version.sh
vendored
Executable file
41
.github/scripts/get_product_version.sh
vendored
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# Trim the "v" prefix, if any.
|
||||
VERSION="${RAW_VERSION#v}"
|
||||
|
||||
# Split off the build metadata part, if any
|
||||
# (we won't actually include it in our final version, and handle it only for
|
||||
# compleness against semver syntax.)
|
||||
IFS='+' read -ra VERSION BUILD_META <<< "$VERSION"
|
||||
|
||||
# Separate out the prerelease part, if any
|
||||
# (version.go expects it to be in a separate variable)
|
||||
IFS='-' read -r BASE_VERSION PRERELEASE <<< "$VERSION"
|
||||
|
||||
EXPERIMENTS_ENABLED=0
|
||||
if [[ "$PRERELEASE" == alpha* ]]; then
|
||||
EXPERIMENTS_ENABLED=1
|
||||
fi
|
||||
if [[ "$PRERELEASE" == dev* ]]; then
|
||||
EXPERIMENTS_ENABLED=1
|
||||
fi
|
||||
|
||||
LDFLAGS="-w -s"
|
||||
if [[ "$EXPERIMENTS_ENABLED" == 1 ]]; then
|
||||
LDFLAGS="${LDFLAGS} -X 'main.experimentsAllowed=yes'"
|
||||
fi
|
||||
LDFLAGS="${LDFLAGS} -X 'github.com/hashicorp/terraform/version.dev=no'"
|
||||
|
||||
echo "Building Terraform CLI ${VERSION}"
|
||||
if [[ "$EXPERIMENTS_ENABLED" == 1 ]]; then
|
||||
echo "This build allows use of experimental features"
|
||||
fi
|
||||
echo "product-version=${VERSION}" | tee -a "${GITHUB_OUTPUT}"
|
||||
echo "product-version-base=${BASE_VERSION}" | tee -a "${GITHUB_OUTPUT}"
|
||||
echo "product-version-pre=${PRERELEASE}" | tee -a "${GITHUB_OUTPUT}"
|
||||
echo "experiments=${EXPERIMENTS_ENABLED}" | tee -a "${GITHUB_OUTPUT}"
|
||||
echo "go-ldflags=${LDFLAGS}" | tee -a "${GITHUB_OUTPUT}"
|
||||
47
.github/scripts/verify_docker
vendored
Executable file
47
.github/scripts/verify_docker
vendored
Executable file
|
|
@ -0,0 +1,47 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# verify_docker invokes the given Docker image with the argument `version` and inspects its output.
|
||||
# If its output doesn't match the version given, the script will exit 1 and report why it failed.
|
||||
# This is meant to be run as part of the build workflow to verify the built image meets some basic
|
||||
# criteria for validity.
|
||||
#
|
||||
# Because this is meant to be run as the `smoke_test` for the docker-build workflow, the script expects
|
||||
# the image name parameter to be provided by the `IMAGE_NAME` environment variable, rather than a
|
||||
# positional argument.
|
||||
|
||||
function usage {
|
||||
echo "IMAGE_NAME=<image uri> ./verify_docker <expect_version>"
|
||||
}
|
||||
|
||||
function main {
|
||||
local image_name="${IMAGE_NAME:-}"
|
||||
local expect_version="${1:-}"
|
||||
local got_version
|
||||
|
||||
if [[ -z "${image_name}" ]]; then
|
||||
echo "ERROR: IMAGE_NAME is not set"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${expect_version}" ]]; then
|
||||
echo "ERROR: expected version argument is required"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
got_version="$( awk '{print $2}' <(head -n1 <(docker run --rm "${image_name}" version)) )"
|
||||
if [ "${got_version}" != "${expect_version}" ]; then
|
||||
echo "Test FAILED"
|
||||
echo "Got: ${got_version}, Want: ${expect_version}"
|
||||
exit 1
|
||||
fi
|
||||
echo "Test PASSED"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
99
.github/workflows/build-terraform-cli.yml
vendored
Normal file
99
.github/workflows/build-terraform-cli.yml
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
name: build_terraform
|
||||
|
||||
# This workflow is intended to be called by the build workflow. The crt make
|
||||
# targets that are utilized automatically determine build metadata and
|
||||
# handle building and packing Terraform.
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cgo-enabled:
|
||||
type: string
|
||||
default: 0
|
||||
required: true
|
||||
goos:
|
||||
required: true
|
||||
type: string
|
||||
goarch:
|
||||
required: true
|
||||
type: string
|
||||
go-version:
|
||||
type: string
|
||||
package-name:
|
||||
type: string
|
||||
default: terraform
|
||||
product-version:
|
||||
type: string
|
||||
required: true
|
||||
ld-flags:
|
||||
type: string
|
||||
required: true
|
||||
runson:
|
||||
type: string
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ inputs.runson }}
|
||||
name: Terraform ${{ inputs.goos }} ${{ inputs.goarch }} v${{ inputs.product-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ inputs.go-version }}
|
||||
- name: Build Terraform
|
||||
env:
|
||||
GOOS: ${{ inputs.goos }}
|
||||
GOARCH: ${{ inputs.goarch }}
|
||||
GO_LDFLAGS: ${{ inputs.ld-flags }}
|
||||
ACTIONSOS: ${{ inputs.runson }}
|
||||
CGO_ENABLED: ${{ inputs.cgo-enabled }}
|
||||
uses: hashicorp/actions-go-build@37358f6098ef21b09542d84a9814ebb843aa4e3e # v1
|
||||
with:
|
||||
product_name: ${{ inputs.package-name }}
|
||||
product_version: ${{ inputs.product-version }}
|
||||
go_version: ${{ inputs.go-version }}
|
||||
os: ${{ inputs.goos }}
|
||||
arch: ${{ inputs.goarch }}
|
||||
reproducible: nope
|
||||
instructions: |-
|
||||
go build -ldflags "${{ inputs.ld-flags }}" -o "$BIN_PATH" -trimpath -buildvcs=false
|
||||
cp LICENSE "$TARGET_DIR/LICENSE.txt"
|
||||
- name: Copy license file to config_dir
|
||||
if: ${{ inputs.goos == 'linux' }}
|
||||
env:
|
||||
LICENSE_DIR: ".release/linux/package/usr/share/doc/${{ inputs.package-name }}"
|
||||
run: |
|
||||
mkdir -p "$LICENSE_DIR" && cp LICENSE "$LICENSE_DIR/LICENSE.txt"
|
||||
- if: ${{ inputs.goos == 'linux' }}
|
||||
uses: hashicorp/actions-packaging-linux@8d55a640bb30b5508f16757ea908b274564792d4 # v1.9
|
||||
with:
|
||||
name: "terraform"
|
||||
description: "Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned."
|
||||
arch: ${{ inputs.goarch }}
|
||||
version: ${{ inputs.product-version }}
|
||||
maintainer: "HashiCorp"
|
||||
homepage: "https://terraform.io/"
|
||||
license: "BUSL-1.1"
|
||||
binary: "dist/terraform"
|
||||
deb_depends: "git"
|
||||
rpm_depends: "git"
|
||||
config_dir: ".release/linux/package/"
|
||||
- if: ${{ inputs.goos == 'linux' }}
|
||||
name: Determine package file names
|
||||
run: |
|
||||
echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV
|
||||
echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV
|
||||
- if: ${{ inputs.goos == 'linux' }}
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ env.RPM_PACKAGE }}
|
||||
path: out/${{ env.RPM_PACKAGE }}
|
||||
if-no-files-found: error
|
||||
- if: ${{ inputs.goos == 'linux' }}
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ env.DEB_PACKAGE }}
|
||||
path: out/${{ env.DEB_PACKAGE }}
|
||||
if-no-files-found: error
|
||||
500
.github/workflows/build.yml
vendored
500
.github/workflows/build.yml
vendored
|
|
@ -1,31 +1,19 @@
|
|||
name: Build Terraform CLI Packages
|
||||
name: build
|
||||
|
||||
# If you want to test changes to this file before merging to a main branch,
|
||||
# push them up to a branch whose name has the prefix "build-workflow-dev/",
|
||||
# which is a special prefix that triggers this workflow even though it's not
|
||||
# actually a release branch.
|
||||
|
||||
# NOTE: This workflow is currently used only to verify that all commits to a
|
||||
# release branch are buildable. It's set up to generate some artifacts that
|
||||
# might in principle be consumed by a downstream release process, but currently
|
||||
# they are not used in this way and official Terraform CLI releases are instead
|
||||
# built using a separate process maintained elsewhere. We intend to adopt this
|
||||
# new process fully later, once other HashiCorp-internal tooling is ready.
|
||||
#
|
||||
# Currently this process produces what should be working packages but packages
|
||||
# NOT suitable for distribution to end-users as official releases, because it
|
||||
# doesn't include a step to ensure that "terraform version" (and similar) will
|
||||
# report the intended version number. Consequently we can safely use these
|
||||
# results for testing purposes, but not yet for release purposes. See the
|
||||
# "build" job below for a FIXME comment related to version numbers.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'v[0-9]+.[0-9]+'
|
||||
- build-workflow-dev/*
|
||||
- releng/**
|
||||
- tsccr-auto-pinning/**
|
||||
- dependabot/**
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+*'
|
||||
|
||||
|
|
@ -42,71 +30,28 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
product-version: ${{ steps.get-product-version.outputs.product-version }}
|
||||
product-version-base: ${{ steps.get-product-version.outputs.product-version-base }}
|
||||
product-version-pre: ${{ steps.get-product-version.outputs.product-version-pre }}
|
||||
experiments: ${{ steps.get-product-version.outputs.experiments }}
|
||||
go-ldflags: ${{ steps.get-product-version.outputs.go-ldflags }}
|
||||
product-version-base: ${{ steps.get-product-version.outputs.base-product-version }}
|
||||
product-version-pre: ${{ steps.get-product-version.outputs.prerelease-product-version }}
|
||||
experiments: ${{ steps.get-ldflags.outputs.experiments }}
|
||||
go-ldflags: ${{ steps.get-ldflags.outputs.go-ldflags }}
|
||||
pkg-name: ${{ steps.get-pkg-name.outputs.pkg-name }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Git Describe
|
||||
id: git-describe
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Get Package Name
|
||||
id: get-pkg-name
|
||||
run: |
|
||||
# The actions/checkout action tries hard to fetch as little as
|
||||
# possible, to the extent that even with "depth: 0" it fails to
|
||||
# produce enough tag metadata for us to "describe" successfully.
|
||||
# We'll therefore re-fetch the tags here to make sure we will
|
||||
# select the most accurate version number.
|
||||
git fetch origin --force --tags --quiet --unshallow
|
||||
git log --tags --simplify-by-decoration --decorate-refs='refs/tags/v*' --pretty=format:'%h %<|(35)%S %ci' --max-count 15 --topo-order
|
||||
set -e
|
||||
RAW_VERSION=$(git describe --tags --match='v*' ${GITHUB_SHA})
|
||||
echo "
|
||||
|
||||
Raw version is ${RAW_VERSION}"
|
||||
echo "::set-output name=raw-version::${RAW_VERSION}"
|
||||
pkg_name=${{ env.PKG_NAME }}
|
||||
echo "pkg-name=${pkg_name}" | tee -a "${GITHUB_OUTPUT}"
|
||||
- name: Decide version number
|
||||
id: get-product-version
|
||||
shell: bash
|
||||
uses: hashicorp/actions-set-product-version@d9b52fb778068099ca4c5e28e1ca0fee2544e114 # v2
|
||||
- name: Determine experiments
|
||||
id: get-ldflags
|
||||
env:
|
||||
RAW_VERSION: ${{ steps.git-describe.outputs.raw-version }}
|
||||
run: |
|
||||
# Trim the "v" prefix, if any.
|
||||
VERSION="${RAW_VERSION#v}"
|
||||
|
||||
# Split off the build metadata part, if any
|
||||
# (we won't actually include it in our final version, and handle it only for
|
||||
# compleness against semver syntax.)
|
||||
IFS='+' read -ra VERSION BUILD_META <<< "$VERSION"
|
||||
|
||||
# Separate out the prerelease part, if any
|
||||
# (version.go expects it to be in a separate variable)
|
||||
IFS='-' read -r BASE_VERSION PRERELEASE <<< "$VERSION"
|
||||
|
||||
EXPERIMENTS_ENABLED=0
|
||||
if [[ "$PRERELEASE" == alpha* ]]; then
|
||||
EXPERIMENTS_ENABLED=1
|
||||
fi
|
||||
if [[ "$PRERELEASE" == dev* ]]; then
|
||||
EXPERIMENTS_ENABLED=1
|
||||
fi
|
||||
|
||||
LDFLAGS="-w -s"
|
||||
if [[ "$EXPERIMENTS_ENABLED" == 1 ]]; then
|
||||
LDFLAGS="${LDFLAGS} -X 'main.experimentsAllowed=yes'"
|
||||
fi
|
||||
LDFLAGS="${LDFLAGS} -X 'github.com/hashicorp/terraform/version.Version=${BASE_VERSION}'"
|
||||
LDFLAGS="${LDFLAGS} -X 'github.com/hashicorp/terraform/version.Prerelease=${PRERELEASE}'"
|
||||
|
||||
echo "Building Terraform CLI ${VERSION}"
|
||||
if [[ "$EXPERIMENTS_ENABLED" == 1 ]]; then
|
||||
echo "This build allows use of experimental features"
|
||||
fi
|
||||
echo "::set-output name=product-version::${VERSION}"
|
||||
echo "::set-output name=product-version-base::${BASE_VERSION}"
|
||||
echo "::set-output name=product-version-pre::${PRERELEASE}"
|
||||
echo "::set-output name=experiments::${EXPERIMENTS_ENABLED}"
|
||||
echo "::set-output name=go-ldflags::${LDFLAGS}"
|
||||
RAW_VERSION: ${{ steps.get-product-version.outputs.product-version }}
|
||||
shell: bash
|
||||
run: .github/scripts/get_product_version.sh
|
||||
- name: Report chosen version number
|
||||
run: |
|
||||
[ -n "${{steps.get-product-version.outputs.product-version}}" ]
|
||||
|
|
@ -119,7 +64,7 @@ jobs:
|
|||
go-version: ${{ steps.get-go-version.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Determine Go version
|
||||
id: get-go-version
|
||||
uses: ./.github/actions/go-version
|
||||
|
|
@ -132,165 +77,54 @@ jobs:
|
|||
filepath: ${{ steps.generate-metadata-file.outputs.filepath }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Generate package metadata
|
||||
id: generate-metadata-file
|
||||
uses: hashicorp/actions-generate-metadata@v1
|
||||
uses: hashicorp/actions-generate-metadata@fdbc8803a0e53bcbb912ddeee3808329033d6357 # v1.1.1
|
||||
with:
|
||||
version: ${{ needs.get-product-version.outputs.product-version }}
|
||||
product: ${{ env.PKG_NAME }}
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: metadata.json
|
||||
path: ${{ steps.generate-metadata-file.outputs.filepath }}
|
||||
|
||||
build:
|
||||
name: Build for ${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
runs-on: ${{ matrix.runson }}
|
||||
needs:
|
||||
- get-product-version
|
||||
- get-go-version
|
||||
uses: ./.github/workflows/build-terraform-cli.yml
|
||||
with:
|
||||
goarch: ${{ matrix.goarch }}
|
||||
goos: ${{ matrix.goos }}
|
||||
go-version: ${{ needs.get-go-version.outputs.go-version }}
|
||||
package-name: ${{ needs.get-product-version.outputs.pkg-name }}
|
||||
product-version: ${{ needs.get-product-version.outputs.product-version }}
|
||||
ld-flags: ${{ needs.get-product-version.outputs.go-ldflags }}
|
||||
cgo-enabled: ${{ matrix.cgo-enabled }}
|
||||
runson: ${{ matrix.runson }}
|
||||
secrets: inherit
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- {goos: "freebsd", goarch: "386", runson: "ubuntu-latest"}
|
||||
- {goos: "freebsd", goarch: "amd64", runson: "ubuntu-latest"}
|
||||
- {goos: "freebsd", goarch: "arm", runson: "ubuntu-latest"}
|
||||
- {goos: "linux", goarch: "386", runson: "ubuntu-latest"}
|
||||
- {goos: "linux", goarch: "amd64", runson: "ubuntu-latest"}
|
||||
- {goos: "linux", goarch: "arm", runson: "ubuntu-latest"}
|
||||
- {goos: "linux", goarch: "arm64", runson: "ubuntu-latest"}
|
||||
- {goos: "openbsd", goarch: "386", runson: "ubuntu-latest"}
|
||||
- {goos: "openbsd", goarch: "amd64", runson: "ubuntu-latest"}
|
||||
- {goos: "solaris", goarch: "amd64", runson: "ubuntu-latest"}
|
||||
- {goos: "windows", goarch: "386", runson: "ubuntu-latest"}
|
||||
- {goos: "windows", goarch: "amd64", runson: "ubuntu-latest"}
|
||||
- {goos: "darwin", goarch: "amd64", runson: "macos-latest"}
|
||||
- {goos: "darwin", goarch: "arm64", runson: "macos-latest"}
|
||||
- {goos: "freebsd", goarch: "386", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "freebsd", goarch: "amd64", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "freebsd", goarch: "arm", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "linux", goarch: "386", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "linux", goarch: "amd64", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "linux", goarch: "arm", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "linux", goarch: "arm64", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "openbsd", goarch: "386", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "openbsd", goarch: "amd64", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "solaris", goarch: "amd64", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "windows", goarch: "386", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "windows", goarch: "amd64", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "darwin", goarch: "amd64", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
- {goos: "darwin", goarch: "arm64", runson: "ubuntu-latest", cgo-enabled: "0"}
|
||||
fail-fast: false
|
||||
|
||||
env:
|
||||
FULL_VERSION: ${{ needs.get-product-version.outputs.product-version }}
|
||||
BASE_VERSION: ${{ needs.get-product-version.outputs.product-version-base }}
|
||||
VERSION_PRERELEASE: ${{ needs.get-product-version.outputs.product-version-pre }}
|
||||
EXPERIMENTS_ENABLED: ${{ needs.get-product-version.outputs.experiments }}
|
||||
GO_LDFLAGS: ${{ needs.get-product-version.outputs.go-ldflags }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ needs.get-go-version.outputs.go-version }}
|
||||
|
||||
# FIXME: We're not currently setting the hard-coded version string in
|
||||
# version/version.go at any point here, which means that the packages
|
||||
# this process builds are not suitable for release. Once we're using
|
||||
# Go 1.18 we may begin using the version information automatically
|
||||
# embedded by the Go toolchain, at which point we won't need any
|
||||
# special steps during build, but failing that we'll need to rework
|
||||
# the version/version.go package so we can more readily update it
|
||||
# using linker flags rather than direct code modification.
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
ACTIONSOS: ${{ matrix.runson }}
|
||||
run: |
|
||||
mkdir dist out
|
||||
if [ "$ACTIONSOS" == "macos-latest" ] && [ "$GOOS" == "darwin" ]; then
|
||||
# When building for macOS _on_ macOS we must force CGo to get
|
||||
# correct hostname resolution behavior. (This must be conditional
|
||||
# because other cross-compiles won't have suitable headers
|
||||
# available to use CGo; darwin_amd64 has suitable headers to
|
||||
# cross-build for darwin_arm64.)
|
||||
export CGO_ENABLED=1
|
||||
fi
|
||||
set -x
|
||||
go build -ldflags "${GO_LDFLAGS}" -o dist/ .
|
||||
zip -r -j out/${{ env.PKG_NAME }}_${FULL_VERSION}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.PKG_NAME }}_${{ env.FULL_VERSION }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
|
||||
path: out/${{ env.PKG_NAME }}_${{ env.FULL_VERSION }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
|
||||
|
||||
package-linux:
|
||||
name: "Build Linux distro packages for ${{ matrix.arch }}"
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- get-product-version
|
||||
- build
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- {arch: "386"}
|
||||
- {arch: "amd64"}
|
||||
- {arch: "arm"}
|
||||
- {arch: "arm64"}
|
||||
fail-fast: false
|
||||
|
||||
env:
|
||||
os: linux
|
||||
arch: ${{matrix.arch}}
|
||||
version: ${{needs.get-product-version.outputs.product-version}}
|
||||
|
||||
steps:
|
||||
- name: "Download Terraform CLI package"
|
||||
uses: actions/download-artifact@v2
|
||||
id: clipkg
|
||||
with:
|
||||
name: terraform_${{ env.version }}_${{ env.os }}_${{ env.arch }}.zip
|
||||
path: .
|
||||
- name: Extract packages
|
||||
run: |
|
||||
mkdir -p dist
|
||||
(cd dist && unzip "../terraform_${{ env.version }}_${{ env.os }}_${{ env.arch }}.zip")
|
||||
mkdir -p out
|
||||
- name: Build Linux distribution packages
|
||||
uses: hashicorp/actions-packaging-linux@v1
|
||||
with:
|
||||
name: "terraform"
|
||||
description: "Terraform enables you to safely and predictably create, change, and improve infrastructure. It is an open source tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned."
|
||||
arch: ${{ matrix.arch }}
|
||||
version: ${{ env.version }}
|
||||
maintainer: "HashiCorp"
|
||||
homepage: "https://terraform.io/"
|
||||
license: "MPL-2.0"
|
||||
binary: "dist/terraform"
|
||||
deb_depends: "git"
|
||||
rpm_depends: "git"
|
||||
- name: Gather Linux distribution package filenames
|
||||
run: |
|
||||
echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV
|
||||
echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV
|
||||
- name: "Save .rpm package"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.RPM_PACKAGE }}
|
||||
path: out/${{ env.RPM_PACKAGE }}
|
||||
- name: "Save .deb package"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.DEB_PACKAGE }}
|
||||
path: out/${{ env.DEB_PACKAGE }}
|
||||
|
||||
# TODO: homebrew packages for macOS
|
||||
#package-homebrew:
|
||||
# name: Build Homebrew package for darwin_${{ matrix.arch }}
|
||||
# runs-on: macos-latest
|
||||
# needs:
|
||||
# - get-product-version
|
||||
# - build
|
||||
# strategy:
|
||||
# matrix:
|
||||
# arch: ["amd64", "arm64"]
|
||||
# fail-fast: false
|
||||
# ...
|
||||
|
||||
package-docker:
|
||||
name: Build Docker image for linux_${{ matrix.arch }}
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -299,61 +133,64 @@ jobs:
|
|||
- build
|
||||
strategy:
|
||||
matrix:
|
||||
arch: ["amd64"]
|
||||
arch: ["amd64", "386", "arm", "arm64"]
|
||||
fail-fast: false
|
||||
|
||||
env:
|
||||
repo: "terraform"
|
||||
version: ${{needs.get-product-version.outputs.product-version}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Build Docker images
|
||||
uses: hashicorp/actions-docker-build@v1
|
||||
uses: hashicorp/actions-docker-build@11d43ef520c65f58683d048ce9b47d6617893c9a # v2
|
||||
with:
|
||||
pkg_name: "terraform_${{env.version}}"
|
||||
version: ${{env.version}}
|
||||
bin_name: terraform
|
||||
target: default
|
||||
arch: ${{matrix.arch}}
|
||||
dockerfile: .github/workflows/build-Dockerfile
|
||||
dockerfile: build.Dockerfile
|
||||
smoke_test: .github/scripts/verify_docker v${{ env.version }}
|
||||
tags: |
|
||||
docker.io/hashicorp/${{env.repo}}:${{env.version}}
|
||||
986891699432.dkr.ecr.us-east-1.amazonaws.com/hashicorp/${{env.repo}}:${{env.version}}
|
||||
public.ecr.aws/hashicorp/${{env.repo}}:${{env.version}}
|
||||
|
||||
e2etest-build:
|
||||
name: Build e2etest for ${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
e2e-cache-key: ${{ steps.set-cache-values.outputs.e2e-cache-key }}
|
||||
e2e-cache-path: ${{ steps.set-cache-values.outputs.e2e-cache-path }}
|
||||
needs:
|
||||
- get-product-version
|
||||
- get-go-version
|
||||
strategy:
|
||||
matrix:
|
||||
# We build test harnesses only for the v1.0 Compatibility Promises
|
||||
# supported platforms. Even within that set, we can only run on
|
||||
# architectures for which we have GitHub Actions runners available,
|
||||
# which is currently only amd64 (x64).
|
||||
# TODO: GitHub Actions does support _self-hosted_ arm and arm64
|
||||
# runners, so we could potentially run some ourselves to run our
|
||||
# tests there, but at the time of writing there is no documented
|
||||
# support for darwin_arm64 (macOS on Apple Silicon).
|
||||
include:
|
||||
- {goos: "darwin", goarch: "amd64"}
|
||||
#- {goos: "darwin", goarch: "arm64"}
|
||||
- {goos: "darwin", goarch: "arm64"}
|
||||
- {goos: "windows", goarch: "amd64"}
|
||||
- {goos: "windows", goarch: "386"}
|
||||
- {goos: "linux", goarch: "386"}
|
||||
- {goos: "linux", goarch: "amd64"}
|
||||
#- {goos: "linux", goarch: "arm"}
|
||||
#- {goos: "linux", goarch: "arm64"}
|
||||
- {goos: "linux", goarch: "arm"}
|
||||
- {goos: "linux", goarch: "arm64"}
|
||||
fail-fast: false
|
||||
|
||||
env:
|
||||
build_script: ./internal/command/e2etest/make-archive.sh
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set Cache Values
|
||||
id: set-cache-values
|
||||
run: |
|
||||
cache_key=e2e-cache-${{ github.sha }}
|
||||
cache_path=internal/command/e2etest/build
|
||||
echo "e2e-cache-key=${cache_key}" | tee -a "${GITHUB_OUTPUT}"
|
||||
echo "e2e-cache-path=${cache_path}" | tee -a "${GITHUB_OUTPUT}"
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ needs.get-go-version.outputs.go-version }}
|
||||
|
||||
|
|
@ -369,15 +206,15 @@ jobs:
|
|||
# that "terraform version" is returning that version number.
|
||||
bash ./internal/command/e2etest/make-archive.sh
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
- name: Save test harness to cache
|
||||
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
name: terraform-e2etest_${{ matrix.goos }}_${{ matrix.goarch }}.zip
|
||||
path: internal/command/e2etest/build/terraform-e2etest_${{ matrix.goos }}_${{ matrix.goarch }}.zip
|
||||
if-no-files-found: error
|
||||
path: ${{ steps.set-cache-values.outputs.e2e-cache-path }}
|
||||
key: ${{ steps.set-cache-values.outputs.e2e-cache-key }}_${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
|
||||
e2etest-linux:
|
||||
name: e2etest for linux_${{ matrix.goarch }}
|
||||
runs-on: ubuntu-latest
|
||||
e2e-test:
|
||||
name: Run e2e test for ${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
runs-on: ${{ matrix.runson }}
|
||||
needs:
|
||||
- get-product-version
|
||||
- build
|
||||
|
|
@ -385,13 +222,17 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- {goarch: "amd64"}
|
||||
#- {goarch: "arm64"}
|
||||
#- {goarch: "arm"}
|
||||
- { runson: ubuntu-latest, goos: linux, goarch: "amd64" }
|
||||
- { runson: ubuntu-latest, goos: linux, goarch: "386" }
|
||||
- { runson: ubuntu-latest, goos: linux, goarch: "arm" }
|
||||
- { runson: ubuntu-latest, goos: linux, goarch: "arm64" }
|
||||
- { runson: macos-latest, goos: darwin, goarch: "amd64" }
|
||||
- { runson: windows-latest, goos: windows, goarch: "amd64" }
|
||||
- { runson: windows-latest, goos: windows, goarch: "386" }
|
||||
fail-fast: false
|
||||
|
||||
env:
|
||||
os: linux
|
||||
os: ${{ matrix.goos }}
|
||||
arch: ${{ matrix.goarch }}
|
||||
version: ${{needs.get-product-version.outputs.product-version}}
|
||||
|
||||
|
|
@ -402,140 +243,81 @@ jobs:
|
|||
# and e2etest package for this platform. (This helps ensure that we're
|
||||
# really testing the release package and not inadvertently testing a
|
||||
# fresh build from source.)
|
||||
- name: "Download e2etest package"
|
||||
uses: actions/download-artifact@v2
|
||||
- name: Checkout repo
|
||||
if: ${{ (matrix.goos == 'linux') || (matrix.goos == 'darwin') }}
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: "Restore cache"
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
id: e2etestpkg
|
||||
with:
|
||||
name: terraform-e2etest_${{ env.os }}_${{ env.arch }}.zip
|
||||
path: .
|
||||
path: ${{ needs.e2etest-build.outputs.e2e-cache-path }}
|
||||
key: ${{ needs.e2etest-build.outputs.e2e-cache-key }}_${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
fail-on-cache-miss: true
|
||||
enableCrossOsArchive: true
|
||||
- name: "Download Terraform CLI package"
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
id: clipkg
|
||||
with:
|
||||
name: terraform_${{env.version}}_${{ env.os }}_${{ env.arch }}.zip
|
||||
path: .
|
||||
- name: Extract packages
|
||||
if: ${{ matrix.goos == 'windows' }}
|
||||
run: |
|
||||
unzip "./terraform-e2etest_${{ env.os }}_${{ env.arch }}.zip"
|
||||
unzip "${{ needs.e2etest-build.outputs.e2e-cache-path }}/terraform-e2etest_${{ env.os }}_${{ env.arch }}.zip"
|
||||
unzip "./terraform_${{env.version}}_${{ env.os }}_${{ env.arch }}.zip"
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
TF_ACC=1 ./e2etest -test.v
|
||||
|
||||
e2etest-darwin:
|
||||
name: e2etest for darwin_${{ matrix.goarch }}
|
||||
runs-on: macos-latest
|
||||
needs:
|
||||
- get-product-version
|
||||
- build
|
||||
- e2etest-build
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- {goarch: "amd64"}
|
||||
#- {goarch: "arm64"}
|
||||
fail-fast: false
|
||||
|
||||
env:
|
||||
os: darwin
|
||||
arch: ${{ matrix.goarch }}
|
||||
version: ${{needs.get-product-version.outputs.product-version}}
|
||||
|
||||
steps:
|
||||
# NOTE: This intentionally _does not_ check out the source code
|
||||
# for the commit/tag we're building, because by now we should
|
||||
# have everything we need in the combination of CLI release package
|
||||
# and e2etest package for this platform. (This helps ensure that we're
|
||||
# really testing the release package and not inadvertently testing a
|
||||
# fresh build from source.)
|
||||
- name: "Download e2etest package"
|
||||
uses: actions/download-artifact@v2
|
||||
id: e2etestpkg
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
||||
if: ${{ contains(matrix.goarch, 'arm') }}
|
||||
with:
|
||||
name: terraform-e2etest_${{ env.os }}_${{ env.arch }}.zip
|
||||
path: .
|
||||
- name: "Download Terraform CLI package"
|
||||
uses: actions/download-artifact@v2
|
||||
id: clipkg
|
||||
with:
|
||||
name: terraform_${{env.version}}_${{ env.os }}_${{ env.arch }}.zip
|
||||
path: .
|
||||
- name: Extract packages
|
||||
run: |
|
||||
unzip "./terraform-e2etest_${{ env.os }}_${{ env.arch }}.zip"
|
||||
unzip "./terraform_${{env.version}}_${{ env.os }}_${{ env.arch }}.zip"
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
TF_ACC=1 ./e2etest -test.v
|
||||
|
||||
e2etest-windows:
|
||||
name: e2etest for windows_${{ matrix.goarch }}
|
||||
runs-on: windows-latest
|
||||
needs:
|
||||
- get-product-version
|
||||
- build
|
||||
- e2etest-build
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- {goarch: "amd64"}
|
||||
fail-fast: false
|
||||
|
||||
env:
|
||||
os: windows
|
||||
arch: ${{ matrix.goarch }}
|
||||
version: ${{needs.get-product-version.outputs.product-version}}
|
||||
|
||||
steps:
|
||||
# NOTE: This intentionally _does not_ check out the source code
|
||||
# for the commit/tag we're building, because by now we should
|
||||
# have everything we need in the combination of CLI release package
|
||||
# and e2etest package for this platform. (This helps ensure that we're
|
||||
# really testing the release package and not inadvertently testing a
|
||||
# fresh build from source.)
|
||||
- name: "Download e2etest package"
|
||||
uses: actions/download-artifact@v2
|
||||
id: e2etestpkg
|
||||
with:
|
||||
name: terraform-e2etest_${{ env.os }}_${{ env.arch }}.zip
|
||||
path: .
|
||||
- name: "Download Terraform CLI package"
|
||||
uses: actions/download-artifact@v2
|
||||
id: clipkg
|
||||
with:
|
||||
name: terraform_${{env.version}}_${{ env.os }}_${{ env.arch }}.zip
|
||||
path: .
|
||||
- name: Extract packages
|
||||
shell: pwsh
|
||||
run: |
|
||||
Expand-Archive -LiteralPath 'terraform-e2etest_${{ env.os }}_${{ env.arch }}.zip' -DestinationPath '.'
|
||||
Expand-Archive -LiteralPath 'terraform_${{env.version}}_${{ env.os }}_${{ env.arch }}.zip' -DestinationPath '.'
|
||||
- name: Run E2E Tests
|
||||
platforms: all
|
||||
- name: Run E2E Tests (Darwin & Linux)
|
||||
id: get-product-version
|
||||
shell: bash
|
||||
if: ${{ (matrix.goos == 'linux') || (matrix.goos == 'darwin') }}
|
||||
env:
|
||||
e2e_cache_path: ${{ needs.e2etest-build.outputs.e2e-cache-path }}
|
||||
run: .github/scripts/e2e_test_linux_darwin.sh
|
||||
- name: Run E2E Tests (Windows)
|
||||
if: ${{ matrix.goos == 'windows' }}
|
||||
env:
|
||||
TF_ACC: 1
|
||||
shell: cmd
|
||||
run: |
|
||||
e2etest.exe -test.v
|
||||
run: e2etest.exe -test.v
|
||||
|
||||
docs-source-package:
|
||||
name: "Build documentation bundle"
|
||||
|
||||
e2e-test-exec:
|
||||
name: Run terraform-exec test for linux amd64
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- get-product-version
|
||||
- get-go-version
|
||||
- build
|
||||
|
||||
env:
|
||||
os: ${{ matrix.goos }}
|
||||
arch: ${{ matrix.goarch }}
|
||||
version: ${{needs.get-product-version.outputs.product-version}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
# FIXME: We should include some sort of pre-validation step here, to
|
||||
# confirm that the doc content is mechanically valid so that the
|
||||
# publishing pipeline will be able to render all content without errors.
|
||||
- name: "Create documentation source bundle"
|
||||
run: |
|
||||
(cd website && zip -9 -r ../terraform-cli-docs-source_${{ env.version }}.zip .)
|
||||
- uses: actions/upload-artifact@v2
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
name: terraform-cli-docs-source_${{ env.version }}.zip
|
||||
path: terraform-cli-docs-source_${{ env.version }}.zip
|
||||
if-no-files-found: error
|
||||
go-version: ${{ needs.get-go-version.outputs.go-version }}
|
||||
- name: Download Terraform CLI package
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
id: clipkg
|
||||
with:
|
||||
name: terraform_${{ env.version }}_linux_amd64.zip
|
||||
path: .
|
||||
- name: Checkout terraform-exec repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
repository: hashicorp/terraform-exec
|
||||
path: terraform-exec
|
||||
- name: Run terraform-exec end-to-end tests
|
||||
run: |
|
||||
FULL_RELEASE_VERSION="${{ env.version }}"
|
||||
unzip terraform_${FULL_RELEASE_VERSION}_linux_amd64.zip
|
||||
export TFEXEC_E2ETEST_TERRAFORM_PATH="$(pwd)/terraform"
|
||||
cd terraform-exec
|
||||
go test -race -timeout=30m -v ./tfexec/internal/e2etest
|
||||
|
|
|
|||
194
.github/workflows/changelog.yml
vendored
Normal file
194
.github/workflows/changelog.yml
vendored
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
# This workflow makes sure contributors don't forget to add a changelog entry or explicitly opt-out of it.
|
||||
#
|
||||
# Do not extend this workflow to include checking out the code (e.g. for building and testing purposes) while the pull_request_target trigger is used.
|
||||
# Instead, see use of workflow_run in https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/
|
||||
|
||||
name: Changelog
|
||||
|
||||
on:
|
||||
# The pull_request_target trigger event allows PRs raised from forks to have write permissions and access secrets.
|
||||
# We uses it in this workflow to enable writing comments to the PR.
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- synchronize
|
||||
- labeled
|
||||
- unlabeled
|
||||
|
||||
# This workflow runs for not-yet-reviewed external contributions.
|
||||
# Following a pull_request_target trigger the workflow would have write permissions,
|
||||
# so we intentionally restrict the permissions to only include write access on pull-requests.
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
check-changelog-entry:
|
||||
name: "Check Changelog Entry"
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: changelog-${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- name: "Changed files"
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changelog
|
||||
with:
|
||||
filters: |
|
||||
changes:
|
||||
- '.changes/*/*.yaml'
|
||||
changelog:
|
||||
- 'CHANGELOG.md'
|
||||
version:
|
||||
- 'version/VERSION'
|
||||
list-files: json
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
sparse-checkout: |
|
||||
version/VERSION
|
||||
.changie.yaml
|
||||
.changes/
|
||||
sparse-checkout-cone-mode: false
|
||||
ref: ${{ github.ref }} # Ref refers to the target branch of this PR
|
||||
|
||||
- name: "Check for changelog entry"
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
const fs = require("fs");
|
||||
async function createOrUpdateChangelogComment(commentDetails, deleteComment) {
|
||||
const commentStart = "## Changelog Warning"
|
||||
|
||||
const body = commentStart + "\n\n" + commentDetails;
|
||||
const { number: issue_number } = context.issue;
|
||||
const { owner, repo } = context.repo;
|
||||
|
||||
// List all comments
|
||||
const allComments = (await github.rest.issues.listComments({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
})).data;
|
||||
|
||||
const existingComment = allComments.find(c => c.body.startsWith(commentStart));
|
||||
const comment_id = existingComment?.id;
|
||||
|
||||
if (deleteComment) {
|
||||
if (existingComment) {
|
||||
await github.rest.issues.deleteComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
core.setFailed(commentDetails);
|
||||
|
||||
if (existingComment) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id,
|
||||
body,
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number,
|
||||
body,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const changesPresent = ${{steps.changelog.outputs.changes}};
|
||||
const changedChangesFiles = ${{steps.changelog.outputs.changes_files}};
|
||||
const changelogChangesPresent = ${{steps.changelog.outputs.changelog}};
|
||||
const versionChangesPresent = ${{steps.changelog.outputs.version}};
|
||||
|
||||
const prLabels = await github.rest.issues.listLabelsOnIssue({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
const backportLabels = prLabels.data.filter(label => label.name.endsWith("-backport"));
|
||||
const backportVersions = backportLabels.map(label => label.name.split("-")[0]);
|
||||
|
||||
const currentVersionFile = fs.readFileSync("./version/VERSION", "utf-8");
|
||||
const currentVersionParts = currentVersionFile.split(".");
|
||||
currentVersionParts.pop();
|
||||
const currentVersion = currentVersionParts.join(".");
|
||||
|
||||
const allVersions = [currentVersion, ...backportVersions]
|
||||
allVersions.sort((a, b) => {
|
||||
const as = a.split(".").map(Number);
|
||||
const bs = b.split(".").map(Number);
|
||||
|
||||
if (as[0] !== bs[0]) {
|
||||
return as[0] - bs[0];
|
||||
}
|
||||
|
||||
if (as[1] !== bs[1]) {
|
||||
return as[1] - bs[1];
|
||||
}
|
||||
});
|
||||
|
||||
const noChangelogNeededLabel = prLabels.data.find(label => label.name === 'no-changelog-needed');
|
||||
const dependenciesLabel = prLabels.data.find(label => label.name === 'dependencies');
|
||||
|
||||
// We want to prohibit contributors from directly changing the CHANGELOG.md, it's
|
||||
// generated so all changes will be lost during the release process.
|
||||
// Therefore we only allow the changelog to change together with the version.
|
||||
// In very rare cases where we generate changes in the changelog without changing the
|
||||
// version we will just ignore this failing check.
|
||||
if (changelogChangesPresent && !versionChangesPresent) {
|
||||
await createOrUpdateChangelogComment("Please don't edit the CHANGELOG.md manually. We use changie to control the Changelog generation, please use `npx changie new` to create a new changelog entry.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dependenciesLabel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (noChangelogNeededLabel) {
|
||||
if (changesPresent) {
|
||||
await createOrUpdateChangelogComment("Please remove either the 'no-changelog-needed' label or the changelog entry from this PR.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing to complain about, so delete any existing comment
|
||||
await createOrUpdateChangelogComment("", true);
|
||||
return;
|
||||
}
|
||||
|
||||
// We only want to have a changelog entry for the oldest version this PR will
|
||||
// land in.
|
||||
const onlyExpectedChangeVersion = allVersions[0]
|
||||
const missingChangelogEntry = !changedChangesFiles.some(filePath => filePath.includes("/v"+onlyExpectedChangeVersion+"/"))
|
||||
const unexpectedChangelogEntry = changedChangesFiles.filter(filePath => !filePath.includes("/v"+onlyExpectedChangeVersion+"/"))
|
||||
|
||||
|
||||
if (missingChangelogEntry) {
|
||||
await createOrUpdateChangelogComment(`Currently this PR would target a v${onlyExpectedChangeVersion} release. Please add a changelog entry for in the .changes/v${onlyExpectedChangeVersion} folder, or discuss which release you'd like to target with your reviewer. If you believe this change does not need a changelog entry, please add the 'no-changelog-needed' label.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (unexpectedChangelogEntry.length > 0) {
|
||||
await createOrUpdateChangelogComment(`Please remove the changelog entry for the following paths: ${unexpectedChangelogEntry.join(", ")}. If you believe this change does not need a changelog entry, please add the 'no-changelog-needed' label.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing to complain about, so delete any existing comment
|
||||
await createOrUpdateChangelogComment("", true);
|
||||
|
||||
- name: Validate changie fragment is valid
|
||||
uses: miniscruff/changie-action@6dcc2533cac0495148ed4046c438487e4dceaa23 # v2.0.0
|
||||
with:
|
||||
version: latest
|
||||
args: merge -u "." --dry-run
|
||||
91
.github/workflows/checks.yml
vendored
91
.github/workflows/checks.yml
vendored
|
|
@ -17,11 +17,14 @@ name: Quick Checks
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- synchronize
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'v[0-9]+.[0-9]+'
|
||||
- checks-workflow-dev/*
|
||||
- '*'
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+*'
|
||||
|
||||
|
|
@ -38,31 +41,24 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: "Fetch source code"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Determine Go version
|
||||
id: go
|
||||
uses: ./.github/actions/go-version
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ steps.go.outputs.version }}
|
||||
|
||||
# NOTE: This cache is shared so the following step must always be
|
||||
# identical across the unit-tests, e2e-tests, and consistency-checks
|
||||
# jobs, or else weird things could happen.
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "~/go/pkg"
|
||||
key: go-mod-${{ hashFiles('go.sum') }}
|
||||
restore-keys: |
|
||||
go-mod-
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- name: "Unit tests"
|
||||
run: |
|
||||
go test ./...
|
||||
# We run tests for all packages from all modules in this repository.
|
||||
for dir in $(go list -m -f '{{.Dir}}' github.com/hashicorp/terraform/...); do
|
||||
(cd $dir && go test -cover "./...")
|
||||
done
|
||||
|
||||
race-tests:
|
||||
name: "Race Tests"
|
||||
|
|
@ -70,27 +66,17 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: "Fetch source code"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Determine Go version
|
||||
id: go
|
||||
uses: ./.github/actions/go-version
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ steps.go.outputs.version }}
|
||||
|
||||
# NOTE: This cache is shared so the following step must always be
|
||||
# identical across the unit-tests, e2e-tests, and consistency-checks
|
||||
# jobs, or else weird things could happen.
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "~/go/pkg"
|
||||
key: go-mod-${{ hashFiles('go.sum') }}
|
||||
restore-keys: |
|
||||
go-mod-
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
# The race detector add significant time to the unit tests, so only run
|
||||
# it for select packages.
|
||||
|
|
@ -108,27 +94,17 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: "Fetch source code"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Determine Go version
|
||||
id: go
|
||||
uses: ./.github/actions/go-version
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ steps.go.outputs.version }}
|
||||
|
||||
# NOTE: This cache is shared so the following step must always be
|
||||
# identical across the unit-tests, e2e-tests, and consistency-checks
|
||||
# jobs, or else weird things could happen.
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "~/go/pkg"
|
||||
key: go-mod-${{ hashFiles('go.sum') }}
|
||||
restore-keys: |
|
||||
go-mod-
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- name: "End-to-end tests"
|
||||
run: |
|
||||
|
|
@ -140,7 +116,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: "Fetch source code"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0 # We need to do comparisons against the main branch.
|
||||
|
||||
|
|
@ -149,31 +125,24 @@ jobs:
|
|||
uses: ./.github/actions/go-version
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ steps.go.outputs.version }}
|
||||
|
||||
# NOTE: This cache is shared so the following step must always be
|
||||
# identical across the unit-tests, e2e-tests, and consistency-checks
|
||||
# jobs, or else weird things could happen.
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "~/go/pkg"
|
||||
key: go-mod-${{ hashFiles('go.sum') }}
|
||||
restore-keys: |
|
||||
go-mod-
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- name: "go.mod and go.sum consistency check"
|
||||
run: |
|
||||
go mod tidy
|
||||
if [[ -n "$(git status --porcelain)" ]]; then
|
||||
echo >&2 "ERROR: go.mod/go.sum are not up-to-date. Run 'go mod tidy' and then commit the updated files."
|
||||
make syncdeps
|
||||
CHANGED="$(git status --porcelain)"
|
||||
if [[ -n "$CHANGED" ]]; then
|
||||
git diff
|
||||
echo >&2 "ERROR: go.mod/go.sum files are not up-to-date. Run 'make syncdeps' and then commit the updated files."
|
||||
echo >&2 $'Affected files:\n'"$CHANGED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Cache protobuf tools
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
path: "tools/protobuf-compile/.workdir"
|
||||
key: protobuf-tools-${{ hashFiles('tools/protobuf-compile/protobuf-compile.go') }}
|
||||
|
|
@ -182,7 +151,7 @@ jobs:
|
|||
|
||||
- name: "Code consistency checks"
|
||||
run: |
|
||||
make fmtcheck importscheck generate staticcheck exhaustive protobuf
|
||||
make fmtcheck importscheck vetcheck copyright generate staticcheck exhaustive protobuf
|
||||
if [[ -n "$(git status --porcelain)" ]]; then
|
||||
echo >&2 "ERROR: Generated files are inconsistent. Run 'make generate' and 'make protobuf' locally and then commit the updated files."
|
||||
git >&2 status --porcelain
|
||||
|
|
|
|||
73
.github/workflows/equivalence-test-diff.yml
vendored
Normal file
73
.github/workflows/equivalence-test-diff.yml
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
name: equivalence-test-diff
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
- reopened
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
equivalence-test-diff:
|
||||
name: "Equivalence Test Diff"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Fetch source code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Determine Go version
|
||||
id: go
|
||||
uses: ./.github/actions/go-version
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ steps.go.outputs.version }}
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- name: Download testing framework
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/equivalence-test.sh download_equivalence_test_binary \
|
||||
0.5.0 \
|
||||
./bin/equivalence-tests \
|
||||
linux \
|
||||
amd64
|
||||
|
||||
- name: Build terraform
|
||||
shell: bash
|
||||
run: ./.github/scripts/equivalence-test.sh build_terraform_binary ./bin/terraform
|
||||
|
||||
- name: Run equivalence tests
|
||||
id: equivalence-tests
|
||||
shell: bash {0} # we want to capture the exit code
|
||||
run: |
|
||||
./bin/equivalence-tests diff \
|
||||
--tests=testing/equivalence-tests/tests \
|
||||
--goldens=testing/equivalence-tests/outputs \
|
||||
--binary=$(pwd)/bin/terraform
|
||||
echo "exit-code=$?" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Equivalence tests failed
|
||||
if: steps.equivalence-tests.outputs.exit-code == 1 # 1 is the exit code for failure
|
||||
shell: bash
|
||||
run: |
|
||||
gh pr comment ${{ github.event.pull_request.number }} \
|
||||
--body "The equivalence tests failed. Please investigate [here](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
|
||||
exit 1 # fail the job
|
||||
|
||||
- name: Equivalence tests changed
|
||||
if: steps.equivalence-tests.outputs.exit-code == 2 # 2 is the exit code for changed
|
||||
shell: bash
|
||||
run: |
|
||||
gh pr comment ${{ github.event.pull_request.number }} \
|
||||
--body "The equivalence tests will be updated. Please verify the changes [here](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
|
||||
54
.github/workflows/equivalence-test-manual-update.yml
vendored
Normal file
54
.github/workflows/equivalence-test-manual-update.yml
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
name: equivalence-tests-manual
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
target-branch:
|
||||
type: string
|
||||
description: "Which branch should be updated?"
|
||||
required: true
|
||||
new-branch:
|
||||
type: string
|
||||
description: "Name of new branch to be created for the review."
|
||||
required: true
|
||||
equivalence-test-version:
|
||||
type: string
|
||||
description: 'Equivalence testing framework version to use (no v prefix, eg. 0.5.0).'
|
||||
default: "0.5.0"
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
run-equivalence-tests:
|
||||
name: "Run equivalence tests"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ inputs.target-branch }}
|
||||
|
||||
- name: Determine Go version
|
||||
id: go
|
||||
uses: ./.github/actions/go-version
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ steps.go.outputs.version }}
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- uses: ./.github/actions/equivalence-test
|
||||
with:
|
||||
target-equivalence-test-version: ${{ inputs.equivalence-test-version }}
|
||||
target-os: linux
|
||||
target-arch: amd64
|
||||
current-branch: ${{ inputs.target-branch }}
|
||||
new-branch: ${{ inputs.new-branch }}
|
||||
reviewers: ${{ github.actor }}
|
||||
message: "Update equivalence test golden files."
|
||||
69
.github/workflows/equivalence-test-update.yml
vendored
Normal file
69
.github/workflows/equivalence-test-update.yml
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
name: equivalence-test-update
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [ closed ]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: "Should run equivalence tests?"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_run: ${{ steps.target_branch.outputs.should_run }}
|
||||
steps:
|
||||
- name: target_branch
|
||||
id: target_branch
|
||||
run: |
|
||||
merged='${{ github.event.pull_request.merged }}'
|
||||
target_branch='${{ github.event.pull_request.base.ref }}'
|
||||
|
||||
targets_release_branch=false
|
||||
if [ "$target_branch" == "main" ]; then
|
||||
targets_release_branch=true
|
||||
elif [ "$target_branch" =~ ^v[0-9]+\.[0-9]+$ ]; then
|
||||
targets_release_branch=true
|
||||
fi
|
||||
|
||||
should_run=false
|
||||
if [ "$merged" == "true" ] && [ "$targets_release_branch" == "true" ]; then
|
||||
should_run=true
|
||||
fi
|
||||
|
||||
echo "should_run=$should_run" >> ${GITHUB_OUTPUT}
|
||||
run-equivalence-tests:
|
||||
name: "Run equivalence tests"
|
||||
needs:
|
||||
- check
|
||||
if: needs.check.outputs.should_run == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ inputs.target-branch }}
|
||||
|
||||
- name: Determine Go version
|
||||
id: go
|
||||
uses: ./.github/actions/go-version
|
||||
|
||||
- name: Install Go toolchain
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ steps.go.outputs.version }}
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- uses: ./.github/actions/equivalence-test
|
||||
with:
|
||||
target-equivalence-test-version: 0.5.0
|
||||
target-os: linux
|
||||
target-arch: amd64
|
||||
current-branch: ${{ github.event.pull_request.base.ref }}
|
||||
new-branch: equivalence-testing/${{ github.event.pull_request.head.ref }}
|
||||
reviewers: ${{ github.event.pull_request.merged_by.login }}
|
||||
message: "Update equivalence test golden files after ${{ github.event.pull_request.html_url }}."
|
||||
2
.github/workflows/issue-comment-created.yml
vendored
2
.github/workflows/issue-comment-created.yml
vendored
|
|
@ -8,7 +8,7 @@ jobs:
|
|||
issue_comment_triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions-ecosystem/action-remove-labels@v1
|
||||
- uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0
|
||||
with:
|
||||
labels: |
|
||||
stale
|
||||
|
|
|
|||
11
.github/workflows/lock.yml
vendored
11
.github/workflows/lock.yml
vendored
|
|
@ -8,16 +8,17 @@ jobs:
|
|||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v2
|
||||
- uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1
|
||||
with:
|
||||
process-only: 'issues, prs'
|
||||
github-token: ${{ github.token }}
|
||||
issue-lock-comment: >
|
||||
issue-comment: >
|
||||
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
|
||||
|
||||
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
|
||||
issue-lock-inactive-days: '30'
|
||||
pr-lock-comment: >
|
||||
issue-inactive-days: '30'
|
||||
pr-comment: >
|
||||
I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active contributions.
|
||||
|
||||
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
|
||||
pr-lock-inactive-days: '30'
|
||||
pr-inactive-days: '30'
|
||||
|
|
|
|||
18
.github/workflows/main.yml
vendored
18
.github/workflows/main.yml
vendored
|
|
@ -1,16 +1,23 @@
|
|||
---
|
||||
name: Backport Assistant Runner
|
||||
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
|
||||
pull_request:
|
||||
types:
|
||||
- labeled
|
||||
|
||||
permissions:
|
||||
contents: write # to push to a new branch
|
||||
pull-requests: write # to create a new PR
|
||||
|
||||
jobs:
|
||||
backport:
|
||||
if: github.event.pull_request.merged
|
||||
if: github.event.pull_request
|
||||
runs-on: ubuntu-latest
|
||||
container: hashicorpdev/backport-assistant:0.2.1
|
||||
container: hashicorpdev/backport-assistant:0.4.7@sha256:36f9d4fba82b9454f1f62bf76c8078fafe3ab0be71356cb96af6d56ac4482cd8
|
||||
steps:
|
||||
- name: Run Backport Assistant
|
||||
run: |
|
||||
|
|
@ -18,4 +25,5 @@ jobs:
|
|||
env:
|
||||
BACKPORT_LABEL_REGEXP: "(?P<target>\\d+\\.\\d+)-backport"
|
||||
BACKPORT_TARGET_TEMPLATE: "v{{.target}}"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
|
||||
BACKPORT_CREATE_DRAFT_ALWAYS: true
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
|
|
|||
24
.github/workflows/merged-pr.yml
vendored
24
.github/workflows/merged-pr.yml
vendored
|
|
@ -1,24 +0,0 @@
|
|||
name: Merged Pull Request
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
# only trigger on pull request closed events
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [ closed ]
|
||||
|
||||
jobs:
|
||||
merge_job:
|
||||
# this job will only run if the PR has been merged
|
||||
if: github.event.pull_request.merged == true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v5
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: "Reminder for the merging maintainer: if this is a user-visible change, please update the changelog on the appropriate release branch."
|
||||
})
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -18,6 +18,8 @@ website/node_modules
|
|||
*.test
|
||||
*.iml
|
||||
|
||||
go.work*
|
||||
|
||||
/terraform
|
||||
|
||||
website/vendor
|
||||
|
|
@ -25,3 +27,6 @@ vendor/
|
|||
|
||||
# Coverage
|
||||
coverage.txt
|
||||
|
||||
# IDEs
|
||||
.vscode/
|
||||
|
|
@ -1 +1 @@
|
|||
1.19.0
|
||||
1.24.2
|
||||
|
|
|
|||
97
.release/ci.hcl
Normal file
97
.release/ci.hcl
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
schema = "2"
|
||||
|
||||
project "terraform" {
|
||||
// the team key is not used by CRT currently
|
||||
team = "terraform"
|
||||
slack {
|
||||
notification_channel = "C011WJ112MD"
|
||||
}
|
||||
github {
|
||||
organization = "hashicorp"
|
||||
repository = "terraform"
|
||||
|
||||
release_branches = [
|
||||
"main",
|
||||
"release/**",
|
||||
"v**.**",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
event "build" {
|
||||
depends = ["merge"]
|
||||
action "build" {
|
||||
organization = "hashicorp"
|
||||
repository = "terraform"
|
||||
workflow = "build"
|
||||
}
|
||||
}
|
||||
|
||||
// Read more about what the `prepare` workflow does here:
|
||||
// https://hashicorp.atlassian.net/wiki/spaces/RELENG/pages/2489712686/Dec+7th+2022+-+Introducing+the+new+Prepare+workflow
|
||||
event "prepare" {
|
||||
depends = ["build"]
|
||||
|
||||
action "prepare" {
|
||||
organization = "hashicorp"
|
||||
repository = "crt-workflows-common"
|
||||
workflow = "prepare"
|
||||
depends = ["build"]
|
||||
}
|
||||
|
||||
notification {
|
||||
on = "fail"
|
||||
}
|
||||
}
|
||||
|
||||
## These are promotion and post-publish events
|
||||
## they should be added to the end of the file after the verify event stanza.
|
||||
|
||||
event "trigger-staging" {
|
||||
// This event is dispatched by the bob trigger-promotion command
|
||||
// and is required - do not delete.
|
||||
}
|
||||
|
||||
event "promote-staging" {
|
||||
depends = ["trigger-staging"]
|
||||
action "promote-staging" {
|
||||
organization = "hashicorp"
|
||||
repository = "crt-workflows-common"
|
||||
workflow = "promote-staging"
|
||||
config = "release-metadata.hcl"
|
||||
}
|
||||
|
||||
notification {
|
||||
on = "always"
|
||||
}
|
||||
}
|
||||
|
||||
event "trigger-production" {
|
||||
// This event is dispatched by the bob trigger-promotion command
|
||||
// and is required - do not delete.
|
||||
}
|
||||
|
||||
event "promote-production" {
|
||||
depends = ["trigger-production"]
|
||||
action "promote-production" {
|
||||
organization = "hashicorp"
|
||||
repository = "crt-workflows-common"
|
||||
workflow = "promote-production"
|
||||
}
|
||||
|
||||
promotion-events {
|
||||
update-ironbank = true
|
||||
post-promotion {
|
||||
organization = "hashicorp"
|
||||
repository = "terraform-releases"
|
||||
workflow = "crt-hook-tfc-upload"
|
||||
}
|
||||
}
|
||||
|
||||
notification {
|
||||
on = "always"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
url_docker_registry_dockerhub = "https://hub.docker.com/r/hashicorp/terraform"
|
||||
url_docker_registry_ecr = "https://gallery.ecr.aws/hashicorp/terraform"
|
||||
url_license = "https://github.com/hashicorp/terraform/blob/main/LICENSE"
|
||||
|
|
|
|||
16
.release/security-scan.hcl
Normal file
16
.release/security-scan.hcl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
container {
|
||||
dependencies = false
|
||||
alpine_secdb = true
|
||||
secrets = false
|
||||
}
|
||||
|
||||
binary {
|
||||
secrets = true
|
||||
go_modules = true
|
||||
osv = false
|
||||
oss_index = true
|
||||
nvd = false
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ The Terraform Core team has adopted a more structured bug triage process than we
|
|||
|
||||
When a bug report is filed, our goal is to either:
|
||||
1. Get it to a state where it is ready for engineering to fix it in an upcoming Terraform release, or
|
||||
2. Close it explain why, if we can't help
|
||||
2. Close it and explain why, if we can't help
|
||||
|
||||
## Process
|
||||
|
||||
|
|
|
|||
42
BUILDING.md
Normal file
42
BUILDING.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Building from Source
|
||||
|
||||
Pre-built binaries are available for download for a variety of supported platforms through the [HashiCorp Releases website](https://releases.hashicorp.com/terraform/).
|
||||
|
||||
However, if you'd like to build Terraform yourself, you can do so using the Go build toolchain and the options specified in this document.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Ensure you've installed the Go language version specified in [`.go-version`](https://github.com/hashicorp/terraform/blob/main/.go-version).
|
||||
2. Clone this repository to a location of your choice.
|
||||
|
||||
## Terraform Build Options
|
||||
|
||||
Terraform accepts certain options passed using `ldflags` at build time which control the behavior of the resulting binary.
|
||||
|
||||
### Dev Version Reporting
|
||||
|
||||
Terraform will include a `-dev` flag when reporting its own version (ex: 1.5.0-dev) unless `version.dev` is set to `no`:
|
||||
|
||||
```
|
||||
go build -ldflags "-w -s -X 'github.com/hashicorp/terraform/version.dev=no'" -o bin/ .
|
||||
```
|
||||
|
||||
### Experimental Features
|
||||
|
||||
Experimental features of Terraform will be disabled unless `main.experimentsAllowed` is set to `yes`:
|
||||
|
||||
```
|
||||
go build -ldflags "-w -s -X 'main.experimentsAllowed=yes'" -o bin/ .
|
||||
```
|
||||
|
||||
In the official build process for Terraform, experiments are only allowed in alpha release builds. We recommend that third-party distributors follow that convention in order to reduce user confusion.
|
||||
|
||||
## Go Options
|
||||
|
||||
For the most part, the Terraform release process relies on the Go toolchain defaults for the target operating system and processor architecture.
|
||||
|
||||
### `CGO_ENABLED`
|
||||
|
||||
One exception is the `CGO_ENABLED` option, which is set explicitly when building Terraform binaries. For most platforms, we build with `CGO_ENABLED=0` in order to produce a statically linked binary. For MacOS/Darwin operating systems, we build with `CGO_ENABLED=1` to avoid a platform-specific issue with DNS resolution.
|
||||
|
||||
|
||||
96
CHANGELOG.md
96
CHANGELOG.md
|
|
@ -1,82 +1,32 @@
|
|||
## 1.3.0 (Unreleased)
|
||||
## 1.13.0 (Unreleased)
|
||||
|
||||
NEW FEATURES:
|
||||
|
||||
* **Optional attributes for object type constraints:** When declaring an input variable whose type constraint includes an object type, you can now declare individual attributes as optional, and specify a default value to use if the caller doesn't set it. For example:
|
||||
|
||||
```terraform
|
||||
variable "with_optional_attribute" {
|
||||
type = object({
|
||||
a = string # a required attribute
|
||||
b = optional(string) # an optional attribute
|
||||
c = optional(number, 127) # an optional attribute with a default value
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
Assigning `{ a = "foo" }` to this variable will result in the value `{ a = "foo", b = null, c = 127 }`.
|
||||
|
||||
* Added functions: `startswith` and `endswith` allow you to check whether a given string has a specified prefix or suffix. ([#31220](https://github.com/hashicorp/terraform/issues/31220))
|
||||
|
||||
UPGRADE NOTES:
|
||||
|
||||
* `terraform show -json`: Output changes now include more detail about the unknown-ness of the planned value. Previously, a planned output would be marked as either fully known or partially unknown, with the `after_unknown` field having value `false` or `true` respectively. Now outputs correctly expose the full structure of unknownness for complex values, allowing consumers of the JSON output format to determine which values in a collection are known only after apply.
|
||||
* `terraform import`: The `-allow-missing-config` has been removed, and at least an empty configuration block must exist to import a resource.
|
||||
* Consumers of the JSON output format expecting on the `after_unknown` field to be only `false` or `true` should be updated to support [the change representation](https://www.terraform.io/internals/json-format#change-representation) described in the documentation, and as was already used for resource changes. ([#31235](https://github.com/hashicorp/terraform/issues/31235))
|
||||
* AzureRM Backend: This release concludes [the deprecation cycle started in Terraform v1.1](https://www.terraform.io/language/upgrade-guides/1-1#preparation-for-removing-azure-ad-graph-support-in-the-azurerm-backend) for the `azurerm` backend's support of "ADAL" authentication. This backend now supports only "MSAL" (Microsoft Graph) authentication.
|
||||
|
||||
This follows from [Microsoft's own deprecation of Azure AD Graph](https://docs.microsoft.com/en-us/graph/migrate-azure-ad-graph-faq), and so you must follow the migration instructions presented in that Azure documentation to adopt Microsoft Graph and then change your backend configuration to use MSAL authentication before upgrading to Terraform v1.3.
|
||||
* When making requests to HTTPS servers, Terraform will now reject invalid handshakes that have duplicate extensions, as required by RFC 5246 section 7.4.1.4 and RFC 8446 section 4.2. This may cause new errors when interacting with existing buggy or misconfigured TLS servers, but should not affect correct servers.
|
||||
|
||||
This only applies to requests made directly by Terraform CLI, such as provider installation and remote state storage. Terraform providers are separate programs which decide their own policy for handling of TLS handshakes.
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* config: Optional attributes for object type constraints, as described under new features above. ([#31154](https://github.com/hashicorp/terraform/issues/31154))
|
||||
* config: New built-in function `timecmp` allows determining the ordering relationship between two timestamps while taking potentially-different UTC offsets into account. ([#31154](https://github.com/hashicorp/terraform/issues/31154))
|
||||
* `terraform fmt` now accepts multiple target paths, allowing formatting of several individual files at once. ([#31687](https://github.com/hashicorp/terraform/issues/31687))
|
||||
* When reporting an error message related to a function call, Terraform will now include contextual information about the signature of the function that was being called, as an aid to understanding why the call might have failed. ([#31299](https://github.com/hashicorp/terraform/issues/31299))
|
||||
* When reporting an error or warning message that isn't caused by values being unknown or marked as sensitive, Terraform will no longer mention any values having those characteristics in the contextual information presented alongside the error. Terraform will still return this information for the small subset of error messages that are specifically about unknown values or sensitive values being invalid in certain contexts. ([#31299](https://github.com/hashicorp/terraform/issues/31299))
|
||||
* The Terraform CLI now calls `PlanResourceChange` for compatible providers when destroying resource instances. ([#31179](https://github.com/hashicorp/terraform/issues/31179))
|
||||
* The AzureRM Backend now only supports MSAL (and Microsoft Graph) and no longer makes use of ADAL (and Azure Active Directory Graph) for authentication ([#31070](https://github.com/hashicorp/terraform/issues/31070))
|
||||
* The COS backend now supports global acceleration. ([#31425](https://github.com/hashicorp/terraform/issues/31425))
|
||||
* providercache: include host in provider installation error ([#31524](https://github.com/hashicorp/terraform/issues/31524))
|
||||
* refactoring: `moved` blocks can now be used to move resources to and from external modules ([#31556](https://github.com/hashicorp/terraform/issues/31556))
|
||||
* When showing the progress of a remote operation running in Terraform Cloud, Terraform CLI will include information about pre-plan run tasks ([#31617](https://github.com/hashicorp/terraform/issues/31617))
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* config: Terraform was not previously evaluating preconditions and postconditions during the apply phase for resource instances that didn't have any changes pending, which was incorrect because the outcome of a condition can potentially be affected by changes to _other_ objects in the configuration. Terraform will now always check the conditions for every resource instance included in a plan during the apply phase, even for resource instances that have "no-op" changes. This means that some failures that would previously have been detected only by a subsequent run will now be detected during the same run that caused them, thereby giving the feedback at the appropriate time. ([#31491](https://github.com/hashicorp/terraform/issues/31491))
|
||||
* `terraform show -json`: Fixed missing unknown markers in the encoding of partially unknown tuples and sets. ([#31236](https://github.com/hashicorp/terraform/issues/31236))
|
||||
* `terraform output` CLI help documentation is now more consistent with web-based documentation. ([#29354](https://github.com/hashicorp/terraform/issues/29354))
|
||||
* getproviders: account for occasionally missing Host header in errors ([#31542](https://github.com/hashicorp/terraform/issues/31542))
|
||||
* core: Do not create "delete" changes for nonexistent outputs ([#31471](https://github.com/hashicorp/terraform/issues/31471))
|
||||
* configload: validate implied provider names in submodules to avoid crash ([#31573](https://github.com/hashicorp/terraform/issues/31573))
|
||||
* core: `import` fails when resources or modules are expanded with for each, or input from data sources is required ([#31283](https://github.com/hashicorp/terraform/issues/31283))
|
||||
|
||||
EXPERIMENTS:
|
||||
|
||||
* This release concludes the `module_variable_optional_attrs` experiment, which started in Terraform v0.14.0. The final design of the optional attributes feature is similar to the experimental form in the previous releases, but with two major differences:
|
||||
* The `optional` function-like modifier for declaring an optional attribute now accepts an optional second argument for specifying a default value to use when the attribute isn't set by the caller. If not specified, the default value is a null value of the appropriate type as before.
|
||||
* The built-in `defaults` function, previously used to meet the use-case of replacing null values with default values, will not graduate to stable and has been removed. Use the second argument of `optional` inline in your type constraint to declare default values instead.
|
||||
Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases.
|
||||
|
||||
If you have any experimental modules that were participating in this experiment, you will need to remove the experiment opt-in and adopt the new syntax for declaring default values in order to migrate your existing module to the stablized version of this feature. If you are writing a shared module for others to use, we recommend declaring that your module requires Terraform v1.3.0 or later to give specific feedback when using the new feature on older Terraform versions, in place of the previous declaration to use the experimental form of this feature:
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_version = ">= 1.3.0"
|
||||
}
|
||||
```
|
||||
- The new command `terraform rpcapi` exposes some Terraform Core functionality through an RPC interface compatible with [`go-plugin`](https://github.com/hashicorp/go-plugin). The exact RPC API exposed here is currently subject to change at any time, because it's here primarily as a vehicle to support the [Terraform Stacks](https://www.hashicorp.com/blog/terraform-stacks-explained) private preview and so will be broken if necessary to respond to feedback from private preview participants, or possibly for other reasons. Do not use this mechanism yet outside of Terraform Stacks private preview.
|
||||
- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. This experiment is under active development, and so it's not yet useful to participate in this experiment
|
||||
|
||||
## Previous Releases
|
||||
|
||||
For information on prior major and minor releases, see their changelogs:
|
||||
For information on prior major and minor releases, refer to their changelogs:
|
||||
|
||||
* [v1.2](https://github.com/hashicorp/terraform/blob/v1.2/CHANGELOG.md)
|
||||
* [v1.1](https://github.com/hashicorp/terraform/blob/v1.1/CHANGELOG.md)
|
||||
* [v1.0](https://github.com/hashicorp/terraform/blob/v1.0/CHANGELOG.md)
|
||||
* [v0.15](https://github.com/hashicorp/terraform/blob/v0.15/CHANGELOG.md)
|
||||
* [v0.14](https://github.com/hashicorp/terraform/blob/v0.14/CHANGELOG.md)
|
||||
* [v0.13](https://github.com/hashicorp/terraform/blob/v0.13/CHANGELOG.md)
|
||||
* [v0.12](https://github.com/hashicorp/terraform/blob/v0.12/CHANGELOG.md)
|
||||
* [v0.11 and earlier](https://github.com/hashicorp/terraform/blob/v0.11/CHANGELOG.md)
|
||||
- [v1.12](https://github.com/hashicorp/terraform/blob/v1.12/CHANGELOG.md)
|
||||
- [v1.11](https://github.com/hashicorp/terraform/blob/v1.11/CHANGELOG.md)
|
||||
- [v1.10](https://github.com/hashicorp/terraform/blob/v1.10/CHANGELOG.md)
|
||||
- [v1.9](https://github.com/hashicorp/terraform/blob/v1.9/CHANGELOG.md)
|
||||
- [v1.8](https://github.com/hashicorp/terraform/blob/v1.8/CHANGELOG.md)
|
||||
- [v1.7](https://github.com/hashicorp/terraform/blob/v1.7/CHANGELOG.md)
|
||||
- [v1.6](https://github.com/hashicorp/terraform/blob/v1.6/CHANGELOG.md)
|
||||
- [v1.5](https://github.com/hashicorp/terraform/blob/v1.5/CHANGELOG.md)
|
||||
- [v1.4](https://github.com/hashicorp/terraform/blob/v1.4/CHANGELOG.md)
|
||||
- [v1.3](https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md)
|
||||
- [v1.2](https://github.com/hashicorp/terraform/blob/v1.2/CHANGELOG.md)
|
||||
- [v1.1](https://github.com/hashicorp/terraform/blob/v1.1/CHANGELOG.md)
|
||||
- [v1.0](https://github.com/hashicorp/terraform/blob/v1.0/CHANGELOG.md)
|
||||
- [v0.15](https://github.com/hashicorp/terraform/blob/v0.15/CHANGELOG.md)
|
||||
- [v0.14](https://github.com/hashicorp/terraform/blob/v0.14/CHANGELOG.md)
|
||||
- [v0.13](https://github.com/hashicorp/terraform/blob/v0.13/CHANGELOG.md)
|
||||
- [v0.12](https://github.com/hashicorp/terraform/blob/v0.12/CHANGELOG.md)
|
||||
- [v0.11 and earlier](https://github.com/hashicorp/terraform/blob/v0.11/CHANGELOG.md)
|
||||
|
|
|
|||
65
CODEOWNERS
65
CODEOWNERS
|
|
@ -1,27 +1,56 @@
|
|||
# Each line is a file pattern followed by one or more owners.
|
||||
# More on CODEOWNERS files: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
|
||||
|
||||
# Remote-state backend # Maintainer
|
||||
/internal/backend/remote-state/artifactory Unmaintained
|
||||
/internal/backend/remote-state/azure @hashicorp/terraform-azure
|
||||
/internal/backend/remote-state/consul @hashicorp/consul @remilapeyre
|
||||
/internal/backend/remote-state/cos @likexian
|
||||
/internal/backend/remote-state/etcdv2 Unmaintained
|
||||
/internal/backend/remote-state/etcdv3 Unmaintained
|
||||
/internal/backend/remote-state/gcs @hashicorp/terraform-google
|
||||
# The rules are evaluated in order, if a file matches multiple patterns, the last match "wins".
|
||||
# We want to have a default rule for all files
|
||||
* @hashicorp/terraform-core
|
||||
|
||||
# Entries that are commented out have maintainers that are not in the
|
||||
# HashiCorp organization and so cannot be automatically added as reviewers.
|
||||
#
|
||||
# We retain those as documentation of who agreed to maintain, but they
|
||||
# cannot be used automatically by GitHub's pull request workflow and would
|
||||
# make GitHub consider this file invalid if not commented.
|
||||
|
||||
# Remote-state backend # Maintainer
|
||||
/internal/backend/remote-state/azure @hashicorp/terraform-core @hashicorp/terraform-azure
|
||||
#/internal/backend/remote-state/consul Unmaintained
|
||||
#/internal/backend/remote-state/cos @likexian
|
||||
/internal/backend/remote-state/gcs @hashicorp/terraform-core @hashicorp/tf-eco-hybrid-cloud
|
||||
/internal/backend/remote-state/http @hashicorp/terraform-core
|
||||
/internal/backend/remote-state/manta Unmaintained
|
||||
/internal/backend/remote-state/oss @xiaozhu36
|
||||
/internal/backend/remote-state/pg @remilapeyre
|
||||
/internal/backend/remote-state/s3 @hashicorp/terraform-aws
|
||||
/internal/backend/remote-state/swift Unmaintained
|
||||
/internal/backend/remote-state/kubernetes @jrhouston @alexsomesan
|
||||
#/internal/backend/remote-state/oss @xiaozhu36
|
||||
#/internal/backend/remote-state/pg @remilapeyre
|
||||
/internal/backend/remote-state/s3 @hashicorp/terraform-core @hashicorp/terraform-aws
|
||||
/internal/backend/remote-state/kubernetes @hashicorp/terraform-core @hashicorp/tf-eco-hybrid-cloud
|
||||
#/internal/backend/remote-state/oci @ravinitp @pvkrishnachaitanya
|
||||
|
||||
# Cloud backend
|
||||
/internal/backend/remote @hashicorp/terraform-core @hashicorp/tf-core-cloud
|
||||
/internal/cloud @hashicorp/terraform-core @hashicorp/tf-core-cloud
|
||||
|
||||
# Provisioners
|
||||
builtin/provisioners/chef Deprecated
|
||||
builtin/provisioners/file @hashicorp/terraform-core
|
||||
builtin/provisioners/habitat Deprecated
|
||||
builtin/provisioners/local-exec @hashicorp/terraform-core
|
||||
builtin/provisioners/puppet Deprecated
|
||||
builtin/provisioners/remote-exec @hashicorp/terraform-core
|
||||
builtin/provisioners/salt-masterless Deprecated
|
||||
|
||||
# engineering and web presence get notified of, and can approve changes to web tooling, but not content at developer.hashicorp.com/terraform/docs
|
||||
|
||||
/website/ @hashicorp/web-presence @hashicorp/terraform-core
|
||||
/website/data/
|
||||
/website/public/
|
||||
/website/content/
|
||||
|
||||
# education and engineering get notified of, and can approve changes to web content at developer.hashicorp.com/terraform/docs
|
||||
|
||||
/website/data/ @hashicorp/terraform-education @hashicorp/terraform-core
|
||||
/website/docs/ @hashicorp/terraform-education @hashicorp/terraform-core
|
||||
/website/img/ @hashicorp/terraform-education @hashicorp/terraform-core
|
||||
/website/README.md @hashicorp/terraform-education @hashicorp/terraform-core
|
||||
/website/public/ @hashicorp/terraform-education @hashicorp/terraform-core
|
||||
/website/content/ @hashicorp/terraform-education @hashicorp/terraform-core
|
||||
|
||||
# Backend maintainers also get co-ownership of their backend docs pages
|
||||
/website/docs/language/backend/azurerm.mdx @hashicorp/terraform-education @hashicorp/terraform-core @hashicorp/terraform-azure
|
||||
/website/docs/language/backend/gcs.mdx @hashicorp/terraform-education @hashicorp/terraform-core @hashicorp/tf-eco-hybrid-cloud
|
||||
/website/docs/language/backend/kubernetes.mdx @hashicorp/terraform-education @hashicorp/terraform-core @hashicorp/tf-eco-hybrid-cloud
|
||||
/website/docs/language/backend/s3.mdx @hashicorp/terraform-education @hashicorp/terraform-core @hashicorp/terraform-aws
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
# This Dockerfile builds on golang:alpine by building Terraform from source
|
||||
# using the current working directory.
|
||||
#
|
||||
|
|
@ -10,7 +13,7 @@
|
|||
FROM docker.mirror.hashicorp.services/golang:alpine
|
||||
LABEL maintainer="HashiCorp Terraform Team <terraform@hashicorp.com>"
|
||||
|
||||
RUN apk add --no-cache git bash openssh
|
||||
RUN apk add --no-cache git bash openssh ca-certificates
|
||||
|
||||
ENV TF_DEV=true
|
||||
ENV TF_RELEASE=1
|
||||
|
|
|
|||
446
LICENSE
446
LICENSE
|
|
@ -1,354 +1,92 @@
|
|||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
1.1. “Contributor”
|
||||
|
||||
means each individual or legal entity that creates, contributes to the
|
||||
creation of, or owns Covered Software.
|
||||
|
||||
1.2. “Contributor Version”
|
||||
|
||||
means the combination of the Contributions of others (if any) used by a
|
||||
Contributor and that particular Contributor’s Contribution.
|
||||
|
||||
1.3. “Contribution”
|
||||
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. “Covered Software”
|
||||
|
||||
means Source Code Form to which the initial Contributor has attached the
|
||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||
Modifications of such Source Code Form, in each case including portions
|
||||
thereof.
|
||||
|
||||
1.5. “Incompatible With Secondary Licenses”
|
||||
means
|
||||
|
||||
a. that the initial Contributor has attached the notice described in
|
||||
Exhibit B to the Covered Software; or
|
||||
|
||||
b. that the Covered Software was made available under the terms of version
|
||||
1.1 or earlier of the License, but not also under the terms of a
|
||||
Secondary License.
|
||||
|
||||
1.6. “Executable Form”
|
||||
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. “Larger Work”
|
||||
|
||||
means a work that combines Covered Software with other material, in a separate
|
||||
file or files, that is not Covered Software.
|
||||
|
||||
1.8. “License”
|
||||
|
||||
means this document.
|
||||
|
||||
1.9. “Licensable”
|
||||
|
||||
means having the right to grant, to the maximum extent possible, whether at the
|
||||
time of the initial grant or subsequently, any and all of the rights conveyed by
|
||||
this License.
|
||||
|
||||
1.10. “Modifications”
|
||||
|
||||
means any of the following:
|
||||
|
||||
a. any file in Source Code Form that results from an addition to, deletion
|
||||
from, or modification of the contents of Covered Software; or
|
||||
|
||||
b. any new file in Source Code Form that contains any Covered Software.
|
||||
|
||||
1.11. “Patent Claims” of a Contributor
|
||||
|
||||
means any patent claim(s), including without limitation, method, process,
|
||||
and apparatus claims, in any patent Licensable by such Contributor that
|
||||
would be infringed, but for the grant of the License, by the making,
|
||||
using, selling, offering for sale, having made, import, or transfer of
|
||||
either its Contributions or its Contributor Version.
|
||||
|
||||
1.12. “Secondary License”
|
||||
|
||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||
General Public License, Version 2.1, the GNU Affero General Public
|
||||
License, Version 3.0, or any later versions of those licenses.
|
||||
|
||||
1.13. “Source Code Form”
|
||||
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. “You” (or “Your”)
|
||||
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, “You” includes any entity that controls, is
|
||||
controlled by, or is under common control with You. For purposes of this
|
||||
definition, “control” means (a) the power, direct or indirect, to cause
|
||||
the direction or management of such entity, whether by contract or
|
||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||
outstanding shares or beneficial ownership of such entity.
|
||||
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
a. under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or as
|
||||
part of a Larger Work; and
|
||||
|
||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||
sale, have made, import, and otherwise transfer either its Contributions
|
||||
or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution become
|
||||
effective for each Contribution on the date the Contributor first distributes
|
||||
such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under this
|
||||
License. No additional rights or licenses will be implied from the distribution
|
||||
or licensing of Covered Software under this License. Notwithstanding Section
|
||||
2.1(b) above, no patent license is granted by a Contributor:
|
||||
|
||||
a. for any code that a Contributor has removed from Covered Software; or
|
||||
|
||||
b. for infringements caused by: (i) Your and any other third party’s
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
c. under Patent Claims infringed by Covered Software in the absence of its
|
||||
Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks, or
|
||||
logos of any Contributor (except as may be necessary to comply with the
|
||||
notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this License
|
||||
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
||||
under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its Contributions
|
||||
are its original creation(s) or it has sufficient rights to grant the
|
||||
rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under applicable
|
||||
copyright doctrines of fair use, fair dealing, or other equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||
Section 2.1.
|
||||
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under the
|
||||
terms of this License. You must inform recipients that the Source Code Form
|
||||
of the Covered Software is governed by the terms of this License, and how
|
||||
they can obtain a copy of this License. You may not attempt to alter or
|
||||
restrict the recipients’ rights in the Source Code Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
a. such Covered Software must also be made available in Source Code Form,
|
||||
as described in Section 3.1, and You must inform recipients of the
|
||||
Executable Form how they can obtain a copy of such Source Code Form by
|
||||
reasonable means in a timely manner, at a charge no more than the cost
|
||||
of distribution to the recipient; and
|
||||
|
||||
b. You may distribute such Executable Form under the terms of this License,
|
||||
or sublicense it under different terms, provided that the license for
|
||||
the Executable Form does not attempt to limit or alter the recipients’
|
||||
rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for the
|
||||
Covered Software. If the Larger Work is a combination of Covered Software
|
||||
with a work governed by one or more Secondary Licenses, and the Covered
|
||||
Software is not Incompatible With Secondary Licenses, this License permits
|
||||
You to additionally distribute such Covered Software under the terms of
|
||||
such Secondary License(s), so that the recipient of the Larger Work may, at
|
||||
their option, further distribute the Covered Software under the terms of
|
||||
either this License or such Secondary License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices (including
|
||||
copyright notices, patent notices, disclaimers of warranty, or limitations
|
||||
of liability) contained within the Source Code Form of the Covered
|
||||
Software, except that You may alter any license notices to the extent
|
||||
required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on behalf
|
||||
of any Contributor. You must make it absolutely clear that any such
|
||||
warranty, support, indemnity, or liability obligation is offered by You
|
||||
alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this License
|
||||
with respect to some or all of the Covered Software due to statute, judicial
|
||||
order, or regulation then You must: (a) comply with the terms of this License
|
||||
to the maximum extent possible; and (b) describe the limitations and the code
|
||||
they affect. Such description must be placed in a text file included with all
|
||||
distributions of the Covered Software under this License. Except to the
|
||||
extent prohibited by statute or regulation, such description must be
|
||||
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||
understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically if You
|
||||
fail to comply with any of its terms. However, if You become compliant,
|
||||
then the rights granted under this License from a particular Contributor
|
||||
are reinstated (a) provisionally, unless and until such Contributor
|
||||
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
||||
if such Contributor fails to notify You of the non-compliance by some
|
||||
reasonable means prior to 60 days after You have come back into compliance.
|
||||
Moreover, Your grants from a particular Contributor are reinstated on an
|
||||
ongoing basis if such Contributor notifies You of the non-compliance by
|
||||
some reasonable means, this is the first time You have received notice of
|
||||
non-compliance with this License from such Contributor, and You become
|
||||
compliant prior to 30 days after Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions, counter-claims,
|
||||
and cross-claims) alleging that a Contributor Version directly or
|
||||
indirectly infringes any patent, then the rights granted to You by any and
|
||||
all Contributors for the Covered Software under Section 2.1 of this License
|
||||
shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||
license agreements (excluding distributors and resellers) which have been
|
||||
validly granted by You or Your distributors under this License prior to
|
||||
termination shall survive termination.
|
||||
|
||||
6. Disclaimer of Warranty
|
||||
|
||||
Covered Software is provided under this License on an “as is” basis, without
|
||||
warranty of any kind, either expressed, implied, or statutory, including,
|
||||
without limitation, warranties that the Covered Software is free of defects,
|
||||
merchantable, fit for a particular purpose or non-infringing. The entire
|
||||
risk as to the quality and performance of the Covered Software is with You.
|
||||
Should any Covered Software prove defective in any respect, You (not any
|
||||
Contributor) assume the cost of any necessary servicing, repair, or
|
||||
correction. This disclaimer of warranty constitutes an essential part of this
|
||||
License. No use of any Covered Software is authorized under this License
|
||||
except under this disclaimer.
|
||||
|
||||
7. Limitation of Liability
|
||||
|
||||
Under no circumstances and under no legal theory, whether tort (including
|
||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||
distributes Covered Software as permitted above, be liable to You for any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character including, without limitation, damages for lost profits, loss of
|
||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses, even if such party shall have been
|
||||
informed of the possibility of such damages. This limitation of liability
|
||||
shall not apply to liability for death or personal injury resulting from such
|
||||
party’s negligence to the extent applicable law prohibits such limitation.
|
||||
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
||||
consequential damages, so this exclusion and limitation may not apply to You.
|
||||
|
||||
8. Litigation
|
||||
|
||||
Any litigation relating to this License may be brought only in the courts of
|
||||
a jurisdiction where the defendant maintains its principal place of business
|
||||
and such litigation shall be governed by laws of that jurisdiction, without
|
||||
reference to its conflict-of-law provisions. Nothing in this Section shall
|
||||
prevent a party’s ability to bring cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
This License represents the complete agreement concerning the subject matter
|
||||
hereof. If any provision of this License is held to be unenforceable, such
|
||||
provision shall be reformed only to the extent necessary to make it
|
||||
enforceable. Any law or regulation which provides that the language of a
|
||||
contract shall be construed against the drafter shall not be used to construe
|
||||
this License against a Contributor.
|
||||
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version of
|
||||
the License under which You originally received the Covered Software, or
|
||||
under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a modified
|
||||
version of this License if you rename the license and remove any
|
||||
references to the name of the license steward (except to note that such
|
||||
modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file, then
|
||||
You may include the notice in a location (such as a LICENSE file in a relevant
|
||||
directory) where a recipient would be likely to look for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
||||
|
||||
This Source Code Form is “Incompatible
|
||||
With Secondary Licenses”, as defined by
|
||||
the Mozilla Public License, v. 2.0.
|
||||
|
||||
License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.
|
||||
"Business Source License" is a trademark of MariaDB Corporation Ab.
|
||||
|
||||
Parameters
|
||||
|
||||
Licensor: HashiCorp, Inc.
|
||||
Licensed Work: Terraform Version 1.6.0 or later. The Licensed Work is (c) 2024
|
||||
HashiCorp, Inc.
|
||||
Additional Use Grant: You may make production use of the Licensed Work, provided
|
||||
Your use does not include offering the Licensed Work to third
|
||||
parties on a hosted or embedded basis in order to compete with
|
||||
HashiCorp's paid version(s) of the Licensed Work. For purposes
|
||||
of this license:
|
||||
|
||||
A "competitive offering" is a Product that is offered to third
|
||||
parties on a paid basis, including through paid support
|
||||
arrangements, that significantly overlaps with the capabilities
|
||||
of HashiCorp's paid version(s) of the Licensed Work. If Your
|
||||
Product is not a competitive offering when You first make it
|
||||
generally available, it will not become a competitive offering
|
||||
later due to HashiCorp releasing a new version of the Licensed
|
||||
Work with additional capabilities. In addition, Products that
|
||||
are not provided on a paid basis are not competitive.
|
||||
|
||||
"Product" means software that is offered to end users to manage
|
||||
in their own environments or offered as a service on a hosted
|
||||
basis.
|
||||
|
||||
"Embedded" means including the source code or executable code
|
||||
from the Licensed Work in a competitive offering. "Embedded"
|
||||
also means packaging the competitive offering in such a way
|
||||
that the Licensed Work must be accessed or downloaded for the
|
||||
competitive offering to operate.
|
||||
|
||||
Hosting or using the Licensed Work(s) for internal purposes
|
||||
within an organization is not considered a competitive
|
||||
offering. HashiCorp considers your organization to include all
|
||||
of your affiliates under common control.
|
||||
|
||||
For binding interpretive guidance on using HashiCorp products
|
||||
under the Business Source License, please visit our FAQ.
|
||||
(https://www.hashicorp.com/license-faq)
|
||||
Change Date: Four years from the date the Licensed Work is published.
|
||||
Change License: MPL 2.0
|
||||
|
||||
For information about alternative licensing arrangements for the Licensed Work,
|
||||
please contact licensing@hashicorp.com.
|
||||
|
||||
Notice
|
||||
|
||||
Business Source License 1.1
|
||||
|
||||
Terms
|
||||
|
||||
The Licensor hereby grants you the right to copy, modify, create derivative
|
||||
works, redistribute, and make non-production use of the Licensed Work. The
|
||||
Licensor may make an Additional Use Grant, above, permitting limited production use.
|
||||
|
||||
Effective on the Change Date, or the fourth anniversary of the first publicly
|
||||
available distribution of a specific version of the Licensed Work under this
|
||||
License, whichever comes first, the Licensor hereby grants you rights under
|
||||
the terms of the Change License, and the rights granted in the paragraph
|
||||
above terminate.
|
||||
|
||||
If your use of the Licensed Work does not comply with the requirements
|
||||
currently in effect as described in this License, you must purchase a
|
||||
commercial license from the Licensor, its affiliated entities, or authorized
|
||||
resellers, or you must refrain from using the Licensed Work.
|
||||
|
||||
All copies of the original and modified Licensed Work, and derivative works
|
||||
of the Licensed Work, are subject to this License. This License applies
|
||||
separately for each version of the Licensed Work and the Change Date may vary
|
||||
for each version of the Licensed Work released by Licensor.
|
||||
|
||||
You must conspicuously display this License on each original or modified copy
|
||||
of the Licensed Work. If you receive the Licensed Work in original or
|
||||
modified form from a third party, the terms and conditions set forth in this
|
||||
License apply to your use of that work.
|
||||
|
||||
Any use of the Licensed Work in violation of this License will automatically
|
||||
terminate your rights under this License for the current and all other
|
||||
versions of the Licensed Work.
|
||||
|
||||
This License does not grant you any right in any trademark or logo of
|
||||
Licensor or its affiliates (provided that you may use a trademark or logo of
|
||||
Licensor as expressly required by this License).
|
||||
|
||||
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
||||
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
||||
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
||||
TITLE.
|
||||
|
|
|
|||
50
Makefile
50
Makefile
|
|
@ -1,21 +1,3 @@
|
|||
WEBSITE_REPO=github.com/hashicorp/terraform-website
|
||||
VERSION?="0.3.44"
|
||||
PWD=$$(pwd)
|
||||
DOCKER_IMAGE="hashicorp/terraform-website:full"
|
||||
DOCKER_IMAGE_LOCAL="hashicorp-terraform-website-local"
|
||||
DOCKER_RUN_FLAGS=--interactive \
|
||||
--rm \
|
||||
--tty \
|
||||
--workdir "/website" \
|
||||
--volume "$(shell pwd):/website/ext/terraform" \
|
||||
--volume "$(shell pwd)/website:/website/preview" \
|
||||
--publish "3000:3000" \
|
||||
-e "IS_CONTENT_PREVIEW=true" \
|
||||
-e "PREVIEW_FROM_REPO=terraform" \
|
||||
-e "NAV_DATA_DIRNAME=./preview/data" \
|
||||
-e "CONTENT_DIRNAME=./preview/docs" \
|
||||
-e "CURRENT_GIT_BRANCH=$$(git rev-parse --abbrev-ref HEAD)"
|
||||
|
||||
# generate runs `go generate` to build the dynamically generated
|
||||
# source files, except the protobuf stubs which are built instead with
|
||||
# "make protobuf".
|
||||
|
|
@ -38,32 +20,40 @@ fmtcheck:
|
|||
importscheck:
|
||||
"$(CURDIR)/scripts/goimportscheck.sh"
|
||||
|
||||
vetcheck:
|
||||
@echo "==> Checking that the code complies with go vet requirements"
|
||||
@go vet ./...
|
||||
|
||||
staticcheck:
|
||||
"$(CURDIR)/scripts/staticcheck.sh"
|
||||
|
||||
exhaustive:
|
||||
"$(CURDIR)/scripts/exhaustive.sh"
|
||||
|
||||
# Default: run this if working on the website locally to run in watch mode.
|
||||
copyright:
|
||||
"$(CURDIR)/scripts/copyright.sh" --plan
|
||||
|
||||
copyrightfix:
|
||||
"$(CURDIR)/scripts/copyright.sh"
|
||||
|
||||
syncdeps:
|
||||
"$(CURDIR)/scripts/syncdeps.sh"
|
||||
|
||||
# Run this if working on the website locally to run in watch mode.
|
||||
website:
|
||||
@echo "==> Downloading latest Docker image..."
|
||||
@docker pull ${DOCKER_IMAGE}
|
||||
@echo "==> Starting website in Docker..."
|
||||
@docker run ${DOCKER_RUN_FLAGS} ${DOCKER_IMAGE} npm start
|
||||
$(MAKE) -C website website
|
||||
|
||||
# Use this if you have run `website/build-local` to use the locally built image.
|
||||
website/local:
|
||||
@echo "==> Starting website in Docker..."
|
||||
@docker run ${DOCKER_RUN_FLAGS} ${DOCKER_IMAGE_LOCAL} npm start
|
||||
$(MAKE) -C website website/local
|
||||
|
||||
.PHONY: website/build-local
|
||||
# Run this to generate a new local Docker image.
|
||||
website/build-local:
|
||||
@echo "==> Building local Docker image"
|
||||
@docker build https://github.com/hashicorp/terraform-website.git\#master \
|
||||
-t $(DOCKER_IMAGE_LOCAL)
|
||||
$(MAKE) -C website website/build-local
|
||||
|
||||
# disallow any parallelism (-j) for Make. This is necessary since some
|
||||
# commands during the build process create temporary files that collide
|
||||
# under parallel conditions.
|
||||
.NOTPARALLEL:
|
||||
|
||||
.PHONY: fmtcheck importscheck generate protobuf website website-test staticcheck website/local website/build-local
|
||||
.PHONY: fmtcheck importscheck vetcheck generate protobuf staticcheck syncdeps website website/local website/build-local
|
||||
|
|
|
|||
18
README.md
18
README.md
|
|
@ -1,12 +1,12 @@
|
|||
# Terraform
|
||||
|
||||
- Website: https://www.terraform.io
|
||||
- Website: https://developer.hashicorp.com/terraform
|
||||
- Forums: [HashiCorp Discuss](https://discuss.hashicorp.com/c/terraform-core)
|
||||
- Documentation: [https://www.terraform.io/docs/](https://www.terraform.io/docs/)
|
||||
- Tutorials: [HashiCorp's Learn Platform](https://learn.hashicorp.com/terraform)
|
||||
- Documentation: [https://developer.hashicorp.com/terraform/docs](https://developer.hashicorp.com/terraform/docs)
|
||||
- Tutorials: [HashiCorp's Learn Platform](https://developer.hashicorp.com/terraform/tutorials)
|
||||
- Certification Exam: [HashiCorp Certified: Terraform Associate](https://www.hashicorp.com/certification/#hashicorp-certified-terraform-associate)
|
||||
|
||||
<img alt="Terraform" src="https://www.datocms-assets.com/2885/1629941242-logo-terraform-main.svg" width="600px">
|
||||
<img alt="Terraform" src="https://www.datocms-assets.com/2885/1731373310-terraform_white.svg" width="600px">
|
||||
|
||||
Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can manage existing and popular service providers as well as custom in-house solutions.
|
||||
|
||||
|
|
@ -24,10 +24,10 @@ For more information, refer to the [What is Terraform?](https://www.terraform.io
|
|||
|
||||
## Getting Started & Documentation
|
||||
|
||||
Documentation is available on the [Terraform website](https://www.terraform.io):
|
||||
Documentation is available on the [Terraform website](https://developer.hashicorp.com/terraform):
|
||||
|
||||
- [Introduction](https://www.terraform.io/intro)
|
||||
- [Documentation](https://www.terraform.io/docs)
|
||||
- [Introduction](https://developer.hashicorp.com/terraform/intro)
|
||||
- [Documentation](https://developer.hashicorp.com/terraform/docs)
|
||||
|
||||
If you're new to Terraform and want to get started creating infrastructure, please check out our [Getting Started guides](https://learn.hashicorp.com/terraform#getting-started) on HashiCorp's learning platform. There are also [additional guides](https://learn.hashicorp.com/terraform#operations-and-development) to continue your learning.
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ Show off your Terraform knowledge by passing a certification exam. Visit the [ce
|
|||
|
||||
## Developing Terraform
|
||||
|
||||
This repository contains only Terraform core, which includes the command line interface and the main graph engine. Providers are implemented as plugins, and Terraform can automatically download providers that are published on [the Terraform Registry](https://registry.terraform.io). HashiCorp develops some providers, and others are developed by other organizations. For more information, see [Extending Terraform](https://www.terraform.io/docs/extend/index.html).
|
||||
This repository contains only Terraform core, which includes the command line interface and the main graph engine. Providers are implemented as plugins, and Terraform can automatically download providers that are published on [the Terraform Registry](https://registry.terraform.io). HashiCorp develops some providers, and others are developed by other organizations. For more information, refer to [Plugin development](https://developer.hashicorp.com/terraform/plugin).
|
||||
|
||||
- To learn more about compiling Terraform and contributing suggested changes, refer to [the contributing guide](.github/CONTRIBUTING.md).
|
||||
|
||||
|
|
@ -45,4 +45,4 @@ This repository contains only Terraform core, which includes the command line in
|
|||
|
||||
## License
|
||||
|
||||
[Mozilla Public License v2.0](https://github.com/hashicorp/terraform/blob/main/LICENSE)
|
||||
[Business Source License 1.1](https://github.com/hashicorp/terraform/blob/main/LICENSE)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
# This Dockerfile is not intended for general use, but is rather used to
|
||||
# produce our "light" release packages as part of our official release
|
||||
# pipeline.
|
||||
|
|
@ -29,7 +32,22 @@ LABEL version=$PRODUCT_VERSION
|
|||
# Historical Terraform-specific label preserved for backward compatibility.
|
||||
LABEL "com.hashicorp.terraform.version"="${PRODUCT_VERSION}"
|
||||
|
||||
RUN apk add --no-cache git openssh
|
||||
# @see https://specs.opencontainers.org/image-spec/annotations/?v=v1.0.1#pre-defined-annotation-keys
|
||||
LABEL org.opencontainers.image.title=${BIN_NAME} \
|
||||
org.opencontainers.image.description="Terraform enables you to safely and predictably create, change, and improve infrastructure" \
|
||||
org.opencontainers.image.authors="HashiCorp Terraform Team <terraform@hashicorp.com>" \
|
||||
org.opencontainers.image.url="https://www.terraform.io/" \
|
||||
org.opencontainers.image.documentation="https://www.terraform.io/docs" \
|
||||
org.opencontainers.image.source="https://github.com/hashicorp/terraform" \
|
||||
org.opencontainers.image.version=${PRODUCT_VERSION} \
|
||||
org.opencontainers.image.revision=${PRODUCT_REVISION} \
|
||||
org.opencontainers.image.vendor="HashiCorp" \
|
||||
org.opencontainers.image.licenses="BUSL-1.1"
|
||||
|
||||
RUN apk add --no-cache git openssh ca-certificates
|
||||
|
||||
# Copy the license file as per Legal requirement
|
||||
COPY LICENSE "/usr/share/doc/${BIN_NAME}/LICENSE.txt"
|
||||
|
||||
# The hashicorp/actions-docker-build GitHub Action extracts the appropriate
|
||||
# release package for our target architecture into the current working
|
||||
17
catalog-info.yaml
Normal file
17
catalog-info.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
#
|
||||
# Intended for internal HashiCorp use only
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: terraform
|
||||
description: HashiCorp Terraform
|
||||
annotations:
|
||||
github.com/project-slug: hashicorp/terraform
|
||||
jira/project-key: TF
|
||||
jira/label: terraform
|
||||
spec:
|
||||
type: library
|
||||
owner: team-tf-core
|
||||
lifecycle: production
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
|
@ -8,6 +12,7 @@ import (
|
|||
"github.com/hashicorp/go-checkpoint"
|
||||
"github.com/hashicorp/terraform/internal/command"
|
||||
"github.com/hashicorp/terraform/internal/command/cliconfig"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -18,7 +23,7 @@ var checkpointResult chan *checkpoint.CheckResponse
|
|||
|
||||
// runCheckpoint runs a HashiCorp Checkpoint request. You can read about
|
||||
// Checkpoint here: https://github.com/hashicorp/go-checkpoint.
|
||||
func runCheckpoint(c *cliconfig.Config) {
|
||||
func runCheckpoint(ctx context.Context, c *cliconfig.Config) {
|
||||
// If the user doesn't want checkpoint at all, then return.
|
||||
if c.DisableCheckpoint {
|
||||
log.Printf("[INFO] Checkpoint disabled. Not running.")
|
||||
|
|
@ -26,6 +31,10 @@ func runCheckpoint(c *cliconfig.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx, span := tracer.Start(ctx, "HashiCorp Checkpoint")
|
||||
_ = ctx // prevent staticcheck from complaining to avoid a maintenence hazard of having the wrong ctx in scope here
|
||||
defer span.End()
|
||||
|
||||
configDir, err := cliconfig.ConfigDir()
|
||||
if err != nil {
|
||||
log.Printf("[ERR] Checkpoint setup error: %s", err)
|
||||
|
|
@ -52,7 +61,10 @@ func runCheckpoint(c *cliconfig.Config) {
|
|||
})
|
||||
if err != nil {
|
||||
log.Printf("[ERR] Checkpoint error: %s", err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
resp = nil
|
||||
} else {
|
||||
span.SetStatus(codes.Ok, "checkpoint request succeeded")
|
||||
}
|
||||
|
||||
checkpointResult <- resp
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
comment:
|
||||
layout: "flags, files"
|
||||
behavior: default
|
||||
|
|
|
|||
70
commands.go
70
commands.go
|
|
@ -1,15 +1,19 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
|
||||
"github.com/hashicorp/cli"
|
||||
"github.com/hashicorp/go-plugin"
|
||||
svchost "github.com/hashicorp/terraform-svchost"
|
||||
"github.com/hashicorp/terraform-svchost/auth"
|
||||
"github.com/hashicorp/terraform-svchost/disco"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/command"
|
||||
"github.com/hashicorp/terraform/internal/command/cliconfig"
|
||||
|
|
@ -17,6 +21,7 @@ import (
|
|||
"github.com/hashicorp/terraform/internal/command/webbrowser"
|
||||
"github.com/hashicorp/terraform/internal/getproviders"
|
||||
pluginDiscovery "github.com/hashicorp/terraform/internal/plugin/discovery"
|
||||
"github.com/hashicorp/terraform/internal/rpcapi"
|
||||
"github.com/hashicorp/terraform/internal/terminal"
|
||||
)
|
||||
|
||||
|
|
@ -49,6 +54,7 @@ var HiddenCommands map[string]struct{}
|
|||
var Ui cli.Ui
|
||||
|
||||
func initCommands(
|
||||
ctx context.Context,
|
||||
originalWorkingDir string,
|
||||
streams *terminal.Streams,
|
||||
config *cliconfig.Config,
|
||||
|
|
@ -85,7 +91,7 @@ func initCommands(
|
|||
View: views.NewView(streams).SetRunningInAutomation(inAutomation),
|
||||
|
||||
Color: true,
|
||||
GlobalPluginDirs: globalPluginDirs(),
|
||||
GlobalPluginDirs: cliconfig.GlobalPluginDirs(),
|
||||
Ui: Ui,
|
||||
|
||||
Services: services,
|
||||
|
|
@ -95,7 +101,10 @@ func initCommands(
|
|||
CLIConfigDir: configDir,
|
||||
PluginCacheDir: config.PluginCacheDir,
|
||||
|
||||
ShutdownCh: makeShutdownCh(),
|
||||
PluginCacheMayBreakDependencyLockFile: config.PluginCacheMayBreakDependencyLockFile,
|
||||
|
||||
ShutdownCh: makeShutdownCh(),
|
||||
CallerContext: ctx,
|
||||
|
||||
ProviderSource: providerSrc,
|
||||
ProviderDevOverrides: providerDevOverrides,
|
||||
|
|
@ -207,6 +216,24 @@ func initCommands(
|
|||
}, nil
|
||||
},
|
||||
|
||||
"metadata": func() (cli.Command, error) {
|
||||
return &command.MetadataCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"metadata functions": func() (cli.Command, error) {
|
||||
return &command.MetadataFunctionsCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"modules": func() (cli.Command, error) {
|
||||
return &command.ModulesCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"output": func() (cli.Command, error) {
|
||||
return &command.OutputCommand{
|
||||
Meta: meta,
|
||||
|
|
@ -351,6 +378,12 @@ func initCommands(
|
|||
}, nil
|
||||
},
|
||||
|
||||
"state identities": func() (cli.Command, error) {
|
||||
return &command.StateIdentitiesCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"state rm": func() (cli.Command, error) {
|
||||
return &command.StateRmCommand{
|
||||
StateMeta: command.StateMeta{
|
||||
|
|
@ -394,6 +427,25 @@ func initCommands(
|
|||
},
|
||||
}
|
||||
|
||||
if meta.AllowExperimentalFeatures {
|
||||
Commands["cloud"] = func() (cli.Command, error) {
|
||||
return &command.CloudCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// "rpcapi" is handled a bit differently because the whole point of
|
||||
// this interface is to bypass the CLI layer so wrapping automation can
|
||||
// get as-direct-as-possible access to Terraform Core functionality,
|
||||
// without interference from behaviors that are intended for CLI
|
||||
// end-user convenience. We bypass the "command" package entirely
|
||||
// for this command in particular.
|
||||
Commands["rpcapi"] = rpcapi.CLICommandFactory(rpcapi.CommandFactoryOpts{
|
||||
ExperimentsAllowed: meta.AllowExperimentalFeatures,
|
||||
ShutdownCh: meta.ShutdownCh,
|
||||
})
|
||||
}
|
||||
|
||||
PrimaryCommands = []string{
|
||||
"init",
|
||||
"validate",
|
||||
|
|
@ -403,11 +455,11 @@ func initCommands(
|
|||
}
|
||||
|
||||
HiddenCommands = map[string]struct{}{
|
||||
"env": struct{}{},
|
||||
"internal-plugin": struct{}{},
|
||||
"push": struct{}{},
|
||||
"env": {},
|
||||
"internal-plugin": {},
|
||||
"push": {},
|
||||
"rpcapi": {},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// makeShutdownCh creates an interrupt listener and returns a channel.
|
||||
|
|
@ -429,6 +481,6 @@ func makeShutdownCh() <-chan struct{} {
|
|||
}
|
||||
|
||||
func credentialsSource(config *cliconfig.Config) (auth.CredentialsSource, error) {
|
||||
helperPlugins := pluginDiscovery.FindPlugins("credentials", globalPluginDirs())
|
||||
helperPlugins := pluginDiscovery.FindPlugins("credentials", cliconfig.GlobalPluginDirs())
|
||||
return config.CredentialsSource(helperPlugins)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,18 @@ This directory contains some documentation about the Terraform Core codebase,
|
|||
aimed at readers who are interested in making code contributions.
|
||||
|
||||
If you're looking for information on _using_ Terraform, please instead refer
|
||||
to [the main Terraform CLI documentation](https://www.terraform.io/docs/cli/index.html).
|
||||
to [the main Terraform CLI documentation](https://developer.hashicorp.com/terraform/cli).
|
||||
|
||||
## Terraform Core Architecture Documents
|
||||
|
||||
* [Terraform Core Architecture Summary](./architecture.md): an overview of the
|
||||
main components of Terraform Core and how they interact. This is the best
|
||||
starting point if you are diving in to this codebase for the first time.
|
||||
* [Modules Runtime Architecture Summary](./architecture.md): an overview of the
|
||||
main components of Terraform Core related to planning and applying modules.
|
||||
This is the best starting point if you are diving in to this codebase for the
|
||||
first time.
|
||||
|
||||
* [Stacks Runtime Architecture Summary](../internal/stacks/README.md): an
|
||||
overview of the main components of Terraform Core related to planning and
|
||||
applying stack configurations.
|
||||
|
||||
* [Resource Instance Change Lifecycle](./resource-instance-change-lifecycle.md):
|
||||
a description of the steps in validating, planning, and applying a change
|
||||
|
|
@ -21,7 +26,7 @@ to [the main Terraform CLI documentation](https://www.terraform.io/docs/cli/inde
|
|||
SDK and so wish to conform to them.
|
||||
|
||||
(If you are planning to write a new provider using the _official_ SDK then
|
||||
please refer to [the Extend documentation](https://www.terraform.io/docs/extend/index.html)
|
||||
please refer to [the Plugin development documentation](https://developer.hashicorp.com/terraform/plugin)
|
||||
instead; it presents similar information from the perspective of the SDK
|
||||
API, rather than the plugin wire protocol.)
|
||||
|
||||
|
|
@ -31,11 +36,21 @@ to [the main Terraform CLI documentation](https://www.terraform.io/docs/cli/inde
|
|||
This documentation is for SDK developers, and is not necessary reading for
|
||||
those implementing a provider using the official SDK.
|
||||
|
||||
* [Terraform Core RPC API](../internal/rpcapi/README.md): an integration point
|
||||
for external software that needs to integrate Terraform Core functionality.
|
||||
|
||||
* [Upgrading Terraform's Dependencies](./dependency-upgrades.md): guidance on
|
||||
some special details that arise when we upgrade Go Module dependencies, due
|
||||
to this codebase containing Terraform CLI, Terraform Core, and the various
|
||||
remote state backends which all have some overlapping dependencies.
|
||||
|
||||
* [How Terraform Uses Unicode](./unicode.md): an overview of the various
|
||||
features of Terraform that rely on Unicode and how to change those features
|
||||
to adopt new versions of Unicode.
|
||||
|
||||
* [Deadlock-free Promises](../internal/promising/README.md): a utility package
|
||||
used by the Terraform Stacks runtime to coordinate its concurrent work.
|
||||
|
||||
## Contribution Guides
|
||||
|
||||
* [Maintainer Etiquette](./maintainer-etiquette.md): guidelines and expectations
|
||||
for those who serve as Pull Request reviewers, issue triagers, etc.
|
||||
* [Contributing to Terraform](../.github/CONTRIBUTING.md): a complete guideline for those who want to contribute to this project.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ We assume some familiarity with user-facing Terraform concepts like
|
|||
configuration, state, CLI workflow, etc. The Terraform website has
|
||||
documentation on these ideas.
|
||||
|
||||
**Links to Go documentation assume you are running [`pkgsite`](https://pkg.go.dev/golang.org/x/pkgsite/cmd/pkgsite) locally, with the default URL of localhost:8080.**
|
||||
|
||||
## Terraform Request Flow
|
||||
|
||||
The following diagram shows an approximation of how a user command is
|
||||
|
|
@ -23,7 +25,7 @@ in more detail in a corresponding section below.
|
|||
Each time a user runs the `terraform` program, aside from some initial
|
||||
bootstrapping in the root package (not shown in the diagram) execution
|
||||
transfers immediately into one of the "command" implementations in
|
||||
[the `command` package](https://pkg.go.dev/github.com/hashicorp/terraform/internal/command).
|
||||
[the `command` package](http://localhost:8080/github.com/hashicorp/terraform/internal/command).
|
||||
The mapping between the user-facing command names and
|
||||
their corresponding `command` package types can be found in the `commands.go`
|
||||
file in the root of the repository.
|
||||
|
|
@ -35,13 +37,13 @@ but it applies to the main Terraform workflow commands `terraform plan` and
|
|||
For these commands, the role of the command implementation is to read and parse
|
||||
any command line arguments, command line options, and environment variables
|
||||
that are needed for the given command and use them to produce a
|
||||
[`backend.Operation`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/backend#Operation)
|
||||
[`backendrun.Operation`](http://localhost:8080/github.com/hashicorp/terraform/internal/backend/backendrun#Operation)
|
||||
object that describes an action to be taken.
|
||||
|
||||
An _operation_ consists of:
|
||||
|
||||
* The action to be taken (e.g. "plan", "apply").
|
||||
* The name of the [workspace](https://www.terraform.io/docs/state/workspaces.html)
|
||||
* The name of the [workspace](https://developer.hashicorp.com/terraform/language/state/workspaces)
|
||||
where the action will be taken.
|
||||
* Root module input variables to use for the action.
|
||||
* For the "plan" operation, a path to the directory containing the configuration's root module.
|
||||
|
|
@ -50,25 +52,25 @@ An _operation_ consists of:
|
|||
"force" flag, etc.
|
||||
|
||||
The operation is then passed to the currently-selected
|
||||
[backend](https://www.terraform.io/docs/backends/index.html). Each backend name
|
||||
[backend](https://developer.hashicorp.com/terraform/language/backend). Each backend name
|
||||
corresponds to an implementation of
|
||||
[`backend.Backend`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/backend#Backend), using a
|
||||
[`backend.Backend`](http://localhost:8080/github.com/hashicorp/terraform/internal/backend#Backend), using a
|
||||
mapping table in
|
||||
[the `backend/init` package](https://pkg.go.dev/github.com/hashicorp/terraform/internal/backend/init).
|
||||
[the `backend/init` package](http://localhost:8080/github.com/hashicorp/terraform/internal/backend/init).
|
||||
|
||||
Backends that are able to execute operations additionally implement
|
||||
[`backend.Enhanced`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/backend#Enhanced);
|
||||
[`backendrun.OperationsBackend`](http://localhost:8080/github.com/hashicorp/terraform/internal/backend/backendrun#OperationsBackend);
|
||||
the command-handling code calls `Operation` with the operation it has
|
||||
constructed, and then the backend is responsible for executing that action.
|
||||
|
||||
Backends that execute operations, however, do so as an architectural implementation detail and not a
|
||||
general feature of backends. That is, the term 'backend' as a Terraform feature is used to refer to
|
||||
a plugin that determines where Terraform stores its state snapshots - only the default `local`
|
||||
backend and Terraform Cloud's backends (`remote`, `cloud`) perform operations.
|
||||
backend and HCP Terraform's backends (`remote`, `cloud`) perform operations.
|
||||
|
||||
Thus, most backends do _not_ implement this interface, and so the `command` package wraps these
|
||||
backends in an instance of
|
||||
[`local.Local`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/backend/local#Local),
|
||||
[`local.Local`](http://localhost:8080/github.com/hashicorp/terraform/internal/backend/local#Local),
|
||||
causing the operation to be executed locally within the `terraform` process itself.
|
||||
|
||||
## Backends
|
||||
|
|
@ -78,19 +80,19 @@ A _backend_ determines where Terraform should store its state snapshots.
|
|||
As described above, the `local` backend also executes operations on behalf of most other
|
||||
backends. It uses a _state manager_
|
||||
(either
|
||||
[`statemgr.Filesystem`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/states/statemgr#Filesystem) if the
|
||||
[`statemgr.Filesystem`](http://localhost:8080/github.com/hashicorp/terraform/internal/states/statemgr#Filesystem) if the
|
||||
local backend is being used directly, or an implementation provided by whatever
|
||||
backend is being wrapped) to retrieve the current state for the workspace
|
||||
specified in the operation, then uses the _config loader_ to load and do
|
||||
initial processing/validation of the configuration specified in the
|
||||
operation. It then uses these, along with the other settings given in the
|
||||
operation, to construct a
|
||||
[`terraform.Context`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#Context),
|
||||
[`terraform.Context`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#Context),
|
||||
which is the main object that actually performs Terraform operations.
|
||||
|
||||
The `local` backend finally calls an appropriate method on that context to
|
||||
begin execution of the relevant command, such as
|
||||
[`Plan`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#Context.Plan)
|
||||
[`Plan`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#Context.Plan)
|
||||
or
|
||||
[`Apply`](), which in turn constructs a graph using a _graph builder_,
|
||||
described in a later section.
|
||||
|
|
@ -98,21 +100,21 @@ described in a later section.
|
|||
## Configuration Loader
|
||||
|
||||
The top-level configuration structure is represented by model types in
|
||||
[package `configs`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/configs).
|
||||
A whole configuration (the root module plus all of its descendent modules)
|
||||
[package `configs`](http://localhost:8080/github.com/hashicorp/terraform/internal/configs).
|
||||
A whole configuration (the root module plus all of its descendant modules)
|
||||
is represented by
|
||||
[`configs.Config`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/configs#Config).
|
||||
[`configs.Config`](http://localhost:8080/github.com/hashicorp/terraform/internal/configs#Config).
|
||||
|
||||
The `configs` package contains some low-level functionality for constructing
|
||||
configuration objects, but the main entry point is in the sub-package
|
||||
[`configload`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/configs/configload]),
|
||||
[`configload`](http://localhost:8080/github.com/hashicorp/terraform/internal/configs/configload),
|
||||
via
|
||||
[`configload.Loader`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/configs/configload#Loader).
|
||||
[`configload.Loader`](http://localhost:8080/github.com/hashicorp/terraform/internal/configs/configload#Loader).
|
||||
A loader deals with all of the details of installing child modules
|
||||
(during `terraform init`) and then locating those modules again when a
|
||||
configuration is loaded by a backend. It takes the path to a root module
|
||||
and recursively loads all of the child modules to produce a single
|
||||
[`configs.Config`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/configs#Config)
|
||||
[`configs.Config`](http://localhost:8080/github.com/hashicorp/terraform/internal/configs#Config)
|
||||
representing the entire configuration.
|
||||
|
||||
Terraform expects configuration files written in the Terraform language, which
|
||||
|
|
@ -121,37 +123,37 @@ is a DSL built on top of
|
|||
cannot be interpreted until we build and walk the graph, since they depend
|
||||
on the outcome of other parts of the configuration, and so these parts of
|
||||
the configuration remain represented as the low-level HCL types
|
||||
[`hcl.Body`](https://pkg.go.dev/github.com/hashicorp/hcl/v2/#Body)
|
||||
[`hcl.Body`](http://localhost:8080/github.com/hashicorp/hcl/v2/#Body)
|
||||
and
|
||||
[`hcl.Expression`](https://pkg.go.dev/github.com/hashicorp/hcl/v2/#Expression),
|
||||
[`hcl.Expression`](http://localhost:8080/github.com/hashicorp/hcl/v2/#Expression),
|
||||
allowing Terraform to interpret them at a more appropriate time.
|
||||
|
||||
## State Manager
|
||||
|
||||
A _state manager_ is responsible for storing and retrieving snapshots of the
|
||||
[Terraform state](https://www.terraform.io/docs/language/state/index.html)
|
||||
[Terraform state](https://developer.hashicorp.com/terraform/language/state)
|
||||
for a particular workspace. Each manager is an implementation of
|
||||
some combination of interfaces in
|
||||
[the `statemgr` package](https://pkg.go.dev/github.com/hashicorp/terraform/internal/states/statemgr),
|
||||
[the `statemgr` package](http://localhost:8080/github.com/hashicorp/terraform/internal/states/statemgr),
|
||||
with most practical managers implementing the full set of operations
|
||||
described by
|
||||
[`statemgr.Full`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/states/statemgr#Full)
|
||||
[`statemgr.Full`](http://localhost:8080/github.com/hashicorp/terraform/internal/states/statemgr#Full)
|
||||
provided by a _backend_. The smaller interfaces exist primarily for use in
|
||||
other function signatures to be explicit about what actions the function might
|
||||
take on the state manager; there is little reason to write a state manager
|
||||
that does not implement all of `statemgr.Full`.
|
||||
|
||||
The implementation
|
||||
[`statemgr.Filesystem`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/states/statemgr#Filesystem) is used
|
||||
[`statemgr.Filesystem`](http://localhost:8080/github.com/hashicorp/terraform/internal/states/statemgr#Filesystem) is used
|
||||
by default (by the `local` backend) and is responsible for the familiar
|
||||
`terraform.tfstate` local file that most Terraform users start with, before
|
||||
they switch to [remote state](https://www.terraform.io/docs/language/state/remote.html).
|
||||
they switch to [remote state](https://developer.hashicorp.com/terraform/language/state/remote).
|
||||
Other implementations of `statemgr.Full` are used to implement remote state.
|
||||
Each of these saves and retrieves state via a remote network service
|
||||
appropriate to the backend that creates it.
|
||||
|
||||
A state manager accepts and returns a state snapshot as a
|
||||
[`states.State`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/states#State)
|
||||
[`states.State`](http://localhost:8080/github.com/hashicorp/terraform/internal/states#State)
|
||||
object. The state manager is responsible for exactly how that object is
|
||||
serialized and stored, but all state managers at the time of writing use
|
||||
the same JSON serialization format, storing the resulting JSON bytes in some
|
||||
|
|
@ -160,7 +162,7 @@ kind of arbitrary blob store.
|
|||
## Graph Builder
|
||||
|
||||
A _graph builder_ is called by a
|
||||
[`terraform.Context`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#Context)
|
||||
[`terraform.Context`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#Context)
|
||||
method (e.g. `Plan` or `Apply`) to produce the graph that will be used
|
||||
to represent the necessary steps for that operation and the dependency
|
||||
relationships between them.
|
||||
|
|
@ -170,7 +172,7 @@ In most cases, the
|
|||
graphs each represent a specific object in the configuration, or something
|
||||
derived from those configuration objects. For example, each `resource` block
|
||||
in the configuration has one corresponding
|
||||
[`GraphNodeConfigResource`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#GraphNodeConfigResource)
|
||||
[`GraphNodeConfigResource`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#GraphNodeConfigResource)
|
||||
vertex representing it in the "plan" graph. (Terraform Core uses terminology
|
||||
inconsistently, describing graph _vertices_ also as graph _nodes_ in various
|
||||
places. These both describe the same concept.)
|
||||
|
|
@ -187,26 +189,26 @@ graph from the set of changes described in the plan that is being applied.
|
|||
|
||||
The graph builders all work in terms of a sequence of _transforms_, which
|
||||
are implementations of
|
||||
[`terraform.GraphTransformer`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#GraphTransformer).
|
||||
[`terraform.GraphTransformer`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#GraphTransformer).
|
||||
Implementations of this interface just take a graph and mutate it in any
|
||||
way needed, and so the set of available transforms is quite varied. Some
|
||||
important examples include:
|
||||
|
||||
* [`ConfigTransformer`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#ConfigTransformer),
|
||||
* [`ConfigTransformer`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#ConfigTransformer),
|
||||
which creates a graph vertex for each `resource` block in the configuration.
|
||||
|
||||
* [`StateTransformer`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#StateTransformer),
|
||||
* [`StateTransformer`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#StateTransformer),
|
||||
which creates a graph vertex for each resource instance currently tracked
|
||||
in the state.
|
||||
|
||||
* [`ReferenceTransformer`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#ReferenceTransformer),
|
||||
* [`ReferenceTransformer`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#ReferenceTransformer),
|
||||
which analyses the configuration to find dependencies between resources and
|
||||
other objects and creates any necessary "happens after" edges for these.
|
||||
|
||||
* [`ProviderTransformer`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#ProviderTransformer),
|
||||
* [`ProviderTransformer`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#ProviderTransformer),
|
||||
which associates each resource or resource instance with exactly one
|
||||
provider configuration (implementing
|
||||
[the inheritance rules](https://www.terraform.io/docs/language/modules/develop/providers.html))
|
||||
[the inheritance rules](https://developer.hashicorp.com/terraform/language/modules/develop/providers))
|
||||
and then creates "happens after" edges to ensure that the providers are
|
||||
initialized before taking any actions with the resources that belong to
|
||||
them.
|
||||
|
|
@ -217,7 +219,7 @@ builder uses a different subset of these depending on the needs of the
|
|||
operation that is being performed.
|
||||
|
||||
The result of graph building is a
|
||||
[`terraform.Graph`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#Graph), which
|
||||
[`terraform.Graph`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#Graph), which
|
||||
can then be processed using a _graph walker_.
|
||||
|
||||
## Graph Walk
|
||||
|
|
@ -225,17 +227,17 @@ can then be processed using a _graph walker_.
|
|||
The process of walking the graph visits each vertex of that graph in a way
|
||||
which respects the "happens after" edges in the graph. The walk algorithm
|
||||
itself is implemented in
|
||||
[the low-level `dag` package](https://pkg.go.dev/github.com/hashicorp/terraform/internal/dag#AcyclicGraph.Walk)
|
||||
[the low-level `dag` package](http://localhost:8080/github.com/hashicorp/terraform/internal/dag#AcyclicGraph.Walk)
|
||||
(where "DAG" is short for [_Directed Acyclic Graph_](https://en.wikipedia.org/wiki/Directed_acyclic_graph)), in
|
||||
[`AcyclicGraph.Walk`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/dag#AcyclicGraph.Walk).
|
||||
[`AcyclicGraph.Walk`](http://localhost:8080/github.com/hashicorp/terraform/internal/dag#AcyclicGraph.Walk).
|
||||
However, the "interesting" Terraform walk functionality is implemented in
|
||||
[`terraform.ContextGraphWalker`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#ContextGraphWalker),
|
||||
[`terraform.ContextGraphWalker`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#ContextGraphWalker),
|
||||
which implements a small set of higher-level operations that are performed
|
||||
during the graph walk:
|
||||
|
||||
* `EnterPath` is called once for each module in the configuration, taking a
|
||||
module address and returning a
|
||||
[`terraform.EvalContext`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#EvalContext)
|
||||
[`terraform.EvalContext`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#EvalContext)
|
||||
that tracks objects within that module. `terraform.Context` is the _global_
|
||||
context for the entire operation, while `terraform.EvalContext` is a
|
||||
context for processing within a single module, and is the primary means
|
||||
|
|
@ -247,7 +249,7 @@ will evaluate multiple vertices concurrently. Vertex evaluation code must
|
|||
therefore make careful use of concurrency primitives such as mutexes in order
|
||||
to coordinate access to shared objects such as the `states.State` object.
|
||||
In most cases, we use the helper wrapper
|
||||
[`states.SyncState`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/states#SyncState)
|
||||
[`states.SyncState`](http://localhost:8080/github.com/hashicorp/terraform/internal/states#SyncState)
|
||||
to safely implement concurrent reads and writes from the shared state.
|
||||
|
||||
## Vertex Evaluation
|
||||
|
|
@ -280,27 +282,27 @@ a plan operation would include the following high-level steps:
|
|||
this operation.
|
||||
|
||||
Each execution step for a vertex is an implementation of
|
||||
[`terraform.Execute`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/erraform#Execute).
|
||||
[`terraform.GraphNodeExecutable.Execute`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#GraphNodeExecutable.Execute).
|
||||
As with graph transforms, the behavior of these implementations varies widely:
|
||||
whereas graph transforms can take any action against the graph, an `Execute`
|
||||
implementation can take any action against the `EvalContext`.
|
||||
|
||||
The implementation of `terraform.EvalContext` used in real processing
|
||||
(as opposed to testing) is
|
||||
[`terraform.BuiltinEvalContext`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#BuiltinEvalContext).
|
||||
[`terraform.BuiltinEvalContext`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#BuiltinEvalContext).
|
||||
It provides coordinated access to plugins, the current state, and the current
|
||||
plan via the `EvalContext` interface methods.
|
||||
|
||||
In order to be executed, a vertex must implement
|
||||
[`terraform.GraphNodeExecutable`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#GraphNodeExecutable),
|
||||
[`terraform.GraphNodeExecutable`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#GraphNodeExecutable),
|
||||
which has a single `Execute` method that handles. There are numerous `Execute`
|
||||
implementations with different behaviors, but some prominent examples are:
|
||||
|
||||
* [NodePlannableResource.Execute](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#NodePlannableResourceInstance.Execute), which handles the `plan` operation.
|
||||
* [`NodePlannableResource.Execute`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#NodePlannableResourceInstance.Execute), which handles the `plan` operation.
|
||||
|
||||
* [`NodeApplyableResourceInstance.Execute`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#NodeApplyableResourceInstance.Execute), which handles the main `apply` operation.
|
||||
* [`NodeApplyableResourceInstance.Execute`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#NodeApplyableResourceInstance.Execute), which handles the main `apply` operation.
|
||||
|
||||
* [`NodeDestroyResourceInstance.Execute`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#EvalWriteState), which handles the main `destroy` operation.
|
||||
* [`NodeDestroyResourceInstance.Execute`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#EvalWriteState), which handles the main `destroy` operation.
|
||||
|
||||
A vertex must complete successfully before the graph walk will begin evaluation
|
||||
for other vertices that have "happens after" edges. Evaluation can fail with one
|
||||
|
|
@ -320,11 +322,11 @@ The high-level process for expression evaluation is:
|
|||
to. For example, the expression `aws_instance.example[1]` refers to one of
|
||||
the instances created by a `resource "aws_instance" "example"` block in
|
||||
configuration. This analysis is performed by
|
||||
[`lang.References`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/lang#References),
|
||||
[`lang.References`](http://localhost:8080/github.com/hashicorp/terraform/internal/lang#References),
|
||||
or more often one of the helper wrappers around it:
|
||||
[`lang.ReferencesInBlock`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/lang#ReferencesInBlock)
|
||||
[`lang.ReferencesInBlock`](http://localhost:8080/github.com/hashicorp/terraform/internal/lang#ReferencesInBlock)
|
||||
or
|
||||
[`lang.ReferencesInExpr`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/lang#ReferencesInExpr)
|
||||
[`lang.ReferencesInExpr`](http://localhost:8080/github.com/hashicorp/terraform/internal/lang#ReferencesInExpr)
|
||||
|
||||
1. Retrieve from the state the data for the objects that are referred to and
|
||||
create a lookup table of the values from these objects that the
|
||||
|
|
@ -334,18 +336,18 @@ The high-level process for expression evaluation is:
|
|||
them.
|
||||
|
||||
1. Ask HCL to evaluate each attribute's expression (a
|
||||
[`hcl.Expression`](https://pkg.go.dev/github.com/hashicorp/hcl/v2/#Expression)
|
||||
[`hcl.Expression`](http://localhost:8080/github.com/hashicorp/hcl/v2/#Expression)
|
||||
object) against the data and function lookup tables.
|
||||
|
||||
In practice, steps 2 through 4 are usually run all together using one
|
||||
of the methods on [`lang.Scope`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/lang#Scope);
|
||||
of the methods on [`lang.Scope`](http://localhost:8080/github.com/hashicorp/terraform/internal/lang#Scope);
|
||||
most commonly,
|
||||
[`lang.EvalBlock`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/lang#Scope.EvalBlock)
|
||||
[`lang.EvalBlock`](http://localhost:8080/github.com/hashicorp/terraform/internal/lang#Scope.EvalBlock)
|
||||
or
|
||||
[`lang.EvalExpr`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/lang#Scope.EvalExpr).
|
||||
[`lang.EvalExpr`](http://localhost:8080/github.com/hashicorp/terraform/internal/lang#Scope.EvalExpr).
|
||||
|
||||
Expression evaluation produces a dynamic value represented as a
|
||||
[`cty.Value`](https://pkg.go.dev/github.com/zclconf/go-cty/cty#Value).
|
||||
[`cty.Value`](http://localhost:8080/github.com/zclconf/go-cty/cty#Value).
|
||||
This Go type represents values from the Terraform language and such values
|
||||
are eventually passed to provider plugins.
|
||||
|
||||
|
|
@ -367,7 +369,7 @@ known when the main graph is constructed, but become known while evaluating
|
|||
other vertices in the main graph.
|
||||
|
||||
This special behavior applies to vertex objects that implement
|
||||
[`terraform.GraphNodeDynamicExpandable`](https://pkg.go.dev/github.com/hashicorp/terraform/internal/terraform#GraphNodeDynamicExpandable).
|
||||
[`terraform.GraphNodeDynamicExpandable`](http://localhost:8080/github.com/hashicorp/terraform/internal/terraform#GraphNodeDynamicExpandable).
|
||||
Such vertices have their own nested _graph builder_, _graph walk_,
|
||||
and _vertex evaluation_ steps, with the same behaviors as described in these
|
||||
sections for the main graph. The difference is in which graph transforms
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
// Highlight a test's name with your cursor and run this debugger configuration
|
||||
// from the debugger tools in the left-side Activity Bar.
|
||||
// This will result in the equivalent of this command being run using the debugger:
|
||||
// `go test -v -run ^<selected text>$ <the current opened file's folder path>`
|
||||
"name": "Run selected test",
|
||||
"request": "launch",
|
||||
"type": "go",
|
||||
"args": [
|
||||
"-test.v",
|
||||
"-test.run",
|
||||
"^${selectedText}$"
|
||||
],
|
||||
// Environment variables can be set from a file or as key-value pairs in the configuration.
|
||||
// "env": {
|
||||
// "MY_ENV": "my-value",
|
||||
// },
|
||||
// "envFile": "./vscode/private.env",
|
||||
"mode": "auto",
|
||||
"program": "${fileDirname}",
|
||||
"showLog": true // dlv's logs
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
// Runs Terraform using the Terraform configuration specified via the chdir argument
|
||||
"name": "Run Terraform in debug mode",
|
||||
"request": "launch",
|
||||
"type": "go",
|
||||
"args": [
|
||||
"-chdir=<absolute path to a Terraform configuration>",
|
||||
// Change this array to perform different terraform commands with different arguments.
|
||||
"plan",
|
||||
"-var='name=value'"
|
||||
],
|
||||
// "cwd": "<absolute path to a Terraform configuration>", // An alternative to using the -chdir global flag above.
|
||||
// Environment variables can be set from a file or as key-value pairs in the configuration.
|
||||
// "env": {
|
||||
// "MY_ENV": "my-value",
|
||||
// },
|
||||
// "envFile": "./vscode/private.env",
|
||||
"mode": "debug",
|
||||
"program": "${workspaceFolder}",
|
||||
"console": "integratedTerminal", // allows responding to y/n in terminal, e.g. in apply command.
|
||||
"showLog": false // dlv's logs
|
||||
}
|
||||
]
|
||||
}
|
||||
15
docs/debugging-configs/vscode/launch-via-cli/launch.json
Normal file
15
docs/debugging-configs/vscode/launch-via-cli/launch.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Connect to dlv server",
|
||||
"type": "go",
|
||||
"debugAdapter": "dlv-dap",
|
||||
"request": "attach",
|
||||
"mode": "remote",
|
||||
"remotePath": "${workspaceFolder}",
|
||||
"port": 2345,
|
||||
"host": "127.0.0.1",
|
||||
}
|
||||
]
|
||||
}
|
||||
97
docs/debugging.md
Normal file
97
docs/debugging.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# How to Debug Terraform
|
||||
|
||||
Contents:
|
||||
- [Debugging automated tests](#debugging-automated-tests)
|
||||
- [Debugging automated tests in VSCode](#debugging-automated-tests-in-vscode)
|
||||
- [Debugging Terraform operations that use real Terraform configurations](#debugging-terraform-operations-that-use-real-terraform-configurations)
|
||||
- [Launch Terraform with the `dlv` CLI tool](#launch-terraform-with-the-dlv-cli-tool)
|
||||
- [Launch Terraform with VS Code's debugging tool](#launch-terraform-with-vs-codes-debugging-tool)
|
||||
|
||||
|
||||
As Terraform is written in Go you may use [Delve](https://github.com/go-delve/delve) to debug it.
|
||||
|
||||
GoLand includes [debugging features](https://www.jetbrains.com/help/go/debugging-code.html), and the [Go extension for VS Code](https://code.visualstudio.com/docs/languages/go#_debugging) makes it easy to use Delve when debugging Go codebases in VS Code.
|
||||
|
||||
## Debugging automated tests
|
||||
|
||||
Debugging an automated test is often the most straightforward workflow for debugging a section of the codebase. For example, the Go extension for VS Code](https://code.visualstudio.com/docs/languages/go#_debugging) adds `run test | debug test` options above all tests in a `*_test.go` file. These allow debugging without any prior configuration.
|
||||
|
||||
### Debugging automated tests in VSCode
|
||||
|
||||
As described above, debugging tests in VS Code is easily achieved through the Go extension.
|
||||
|
||||
If you need more control over how tests are run while debugging, e.g. environment variable values, look at the [example debugger launch configuration 'Run selected test'](./debugging-configs/vscode/debug-automated-tests/launch.json). You can adapt this example to create your own [launch configuration file](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations).
|
||||
|
||||
When using this launch configuration you must highlight a test's name before starting the debugger:
|
||||
|
||||
<p align="center">
|
||||
<img width="75%" alt="Debugging a single test using the example 'Run selected test' debugger configuration shared in this repository" src="./images/vscode-debugging-test.png"/>
|
||||
</p>
|
||||
|
||||
|
||||
## Debugging Terraform operations that use real Terraform configurations
|
||||
|
||||
### Launch Terraform with the `dlv` CLI tool
|
||||
|
||||
In this workflow you:
|
||||
* Build Terraform using compiler flags.
|
||||
* Start a debug server with a command containing the terraform command you want to debug.
|
||||
* This command is run in the working directory that contains your Terraform configuration.
|
||||
* Connect to the debug server to monitor progress through breakpoints.
|
||||
|
||||
#### 1. Compile & Start Debug Server
|
||||
|
||||
One way to do it is to compile a binary with the [appropriate compiler flags](https://pkg.go.dev/cmd/compile#hdr-Command_Line):
|
||||
|
||||
```sh
|
||||
go install -gcflags="all=-N -l"
|
||||
```
|
||||
|
||||
This enables you to then execute the compiled binary via Delve, pass any arguments and spin up a debug server which you can then connect to:
|
||||
|
||||
```sh
|
||||
# Update the path to the terraform binary if your install directory is influenced by $GOPATH or $GOBIN
|
||||
dlv exec $HOME/go/bin/terraform --headless --listen :2345 --log -- apply
|
||||
```
|
||||
|
||||
#### 2a. Connect via CLI
|
||||
|
||||
You may connect to the headless debug server via Delve CLI
|
||||
|
||||
```sh
|
||||
dlv connect :2345
|
||||
```
|
||||
|
||||
#### 2b. Connect from VS Code
|
||||
|
||||
The repository provides [an example 'Connect to dlv server' launch configuration](./debugging-configs/vscode/launch-via-cli/launch.json), making it possible to use VS Code's native debugging integration via the [Go extension for VS Code](https://code.visualstudio.com/docs/languages/go#_debugging):
|
||||
|
||||
<p align="center">
|
||||
<img width="75%" alt="vscode debugger" src="./images/vscode-debugging.png"/>
|
||||
</p>
|
||||
|
||||
|
||||
### Launch Terraform with VS Code's debugging tool
|
||||
|
||||
In this workflow you:
|
||||
* Update the debugger's launch configuration to point at the directory containing your Terraform configuration.
|
||||
* Start the debugger through VS Code and monitor progress through breakpoints.
|
||||
|
||||
#### 1. Update the debugger's launch configuration
|
||||
|
||||
Look at the [example debugger launch configuration 'Run Terraform in debug mode'](./debugging-configs/vscode/launch-from-vscode-debugger/launch.json). You can adapt this example to create your own [launch configuration file](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations).
|
||||
|
||||
To use this launch configuration:
|
||||
* Prepare a local Terraform project.
|
||||
* Get the absolute path to that directory.
|
||||
* Update the launch configuration to use that path, either in the `-chdir` argument or as a `cwd` attribute in the launch configuration.
|
||||
* Make sure the `args` array's element reflect the command you'd like to debug.
|
||||
* Provide any required environment variables through the `env` or `envFile` attributes.
|
||||
|
||||
#### 2. Run the launch configuration in VS Code
|
||||
|
||||
Navigate to the Run and Debug view in the left-side Activity Bar. After selecting the `Run Terraform in debug mode` configuration in the Run and Debug view from the left-side, press the green arrow.
|
||||
|
||||
This is equivalent to running a Terraform CLI command in the local Terraform project's directory. For example, if you run and debug a plan command that saves a plan file, that plan file will be created.
|
||||
|
||||
This workflow is useful if you need to set up a complicated prior state to replicate a bug or if you want to debug code behaviour given a specific configuration.
|
||||
153
docs/dependency-upgrades.md
Normal file
153
docs/dependency-upgrades.md
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
# Upgrading Terraform's Library Dependencies
|
||||
|
||||
This codebase depends on a variety of external Go modules. At the time of
|
||||
writing, a Terraform CLI build includes the union of all dependencies required
|
||||
by Terraform CLI and Core itself and each of the remote state backends.
|
||||
|
||||
Because the remote state backends have quite a different set of needs than
|
||||
Terraform itself -- special client libraries, in particular -- we've declared
|
||||
them as being separate Go Modules with their own `go.mod` and `go.sum` files,
|
||||
even though we don't intend to ever publish them separately. The goal is just
|
||||
to help track which dependencies are used by each of these components, and to
|
||||
more easily determine which of the components are affected by a particular
|
||||
dependency upgrade so that we can make sure to do the appropriate testing.
|
||||
|
||||
## Dependency Synchronization
|
||||
|
||||
Because all of these components ultimately link into the same executable, there
|
||||
can be only one version of each distinct module and thus all of the modules
|
||||
must agree on which version to use.
|
||||
|
||||
The makefile target `syncdeps` runs a script which synchronizes all of the
|
||||
modules to declare compatible dependencies, selecting the newest version of
|
||||
each external module selected across all of the internal modules:
|
||||
|
||||
```shell
|
||||
make syncdeps
|
||||
```
|
||||
|
||||
After running this, use `git status` to see what's been changed. If you've
|
||||
changed the dependencies of any of the modules then that should typically
|
||||
cause an update to the root module, because that one imports all of the others.
|
||||
|
||||
## Upgrading a Dependency
|
||||
|
||||
To select a newer version of one of the dependencies, use `go get` in the
|
||||
root to specify which version to use:
|
||||
|
||||
```shell
|
||||
go get example.com/foo/bar@v1.0.0
|
||||
```
|
||||
|
||||
Or, if you just want to move to the latest stable release, you can use the
|
||||
`latest` pseudo-version:
|
||||
|
||||
```shell
|
||||
go get example.com/foo/bar@latest
|
||||
```
|
||||
|
||||
Then run `make syncdeps` to update any of the child modules that also use
|
||||
this dependency. The remote state backends use only a subset of the packages
|
||||
in Terraform CLI/Core, so not all dependency updates will affect the remote
|
||||
state backends, and an update might affect only a subset of the backends.
|
||||
|
||||
When you open the pull request for your change, our code owners rules will
|
||||
automatically request review from the team that maintains any affected remote
|
||||
state backend. The affected teams can judge whether the update seems likely
|
||||
to affect their backend and run their acceptance tests if so, before approving
|
||||
the pull request. As usual, these PRs should also be reviewed by at least
|
||||
one member of the Terraform Core team since they are ultimately responsible
|
||||
for the complete set of dependencies used in Terraform CLI releases.
|
||||
|
||||
**Note:** Currently our code owners rules are simplistic and will request
|
||||
review for _any_ change under a remote state backend module directory, but
|
||||
in practice an update that only changes a backend's `go.sum` cannot affect
|
||||
the runtime behavior of the backend, and so those review requests are not
|
||||
strictly required. You should therefore remove the review requests for
|
||||
any backend whose only diff is the `go.sum` file once you've opened the
|
||||
pull request.
|
||||
|
||||
## Dependabot Updates
|
||||
|
||||
When Dependabot automatically opens a pull request to upgrade a dependency,
|
||||
unfortunately it isn't smart enough to automatically synchronize the change
|
||||
across the modules and so the code consistency checks for the change will
|
||||
typically fail.
|
||||
|
||||
To apply the proposed change, you'll need to check out the branch that
|
||||
Dependabot created on your development system, run `make syncdeps`, add
|
||||
all of the files that get modified, and then amend Dependabot's commit using
|
||||
`git commit --amend`.
|
||||
|
||||
After you've done this, use `git push --force` to replace Dependabot's original
|
||||
commit with your new commit, and then wait for GitHub to re-run the PR
|
||||
checks. The code consistency checks should now pass.
|
||||
|
||||
We've configured Dependabot to monitor only the root `go.mod` file for potential
|
||||
upgrades, because that one aggregates the dependencies for all other child
|
||||
modules. Therefore there should never be a Dependabot upgrade targeting a
|
||||
module in a subdirectory. If one _does_ get created somehow, you should close
|
||||
it and perform the same upgrade at the root of the repository instead, using
|
||||
the instructions in [Upgrading a Dependency](#upgrading-a-dependency) above.
|
||||
|
||||
## Dependencies with Special Requirements
|
||||
|
||||
Most of our dependencies can be treated generically, but a few have some
|
||||
special constraints due to how Terraform uses them:
|
||||
|
||||
* HCL, cty, and their indirect dependencies `golang.org/x/text` and
|
||||
`github.com/apparentlymart/go-textseg` all include logic based on Unicode
|
||||
specifications, and so should be updated with care to make sure that
|
||||
Terraform's support for Unicode follows a consistent Unicode version
|
||||
throughout.
|
||||
|
||||
Additionally, each time we adopt a new minor release of Go, we may need to
|
||||
upgrade some or all of these dependencies to match the Unicode version used
|
||||
by the Go standard library.
|
||||
|
||||
For more information, refer to [How Terraform Uses Unicode](unicode.md).
|
||||
|
||||
(This concern does not apply if the new version we're upgrading to is built
|
||||
for the same version of Unicode that Terraform was already using.)
|
||||
|
||||
* `github.com/hashicorp/go-getter` represents a significant part of Terraform
|
||||
CLI's remote module installer, and is the final interpreter of Terraform's
|
||||
module source address syntax. Because the module source address syntax is
|
||||
protected by the Terraform v1.x Compatibility Promises, for each upgrade
|
||||
we must make sure that:
|
||||
|
||||
- The upgrade doesn't expand the source address syntax in a way that is
|
||||
undesirable from a Terraform product standpoint or in a way that we would
|
||||
not feel comfortable supporting indefinitely under the compatibility
|
||||
promises.
|
||||
- The upgrade doesn't break any already-supported source address forms
|
||||
that would therefore cause the next Terraform version to break the
|
||||
v1.x compatibility promises.
|
||||
|
||||
Terraform's use of `go-getter` is all encapsulated in `internal/getmodules`
|
||||
and is set up to try to minimize the possibility that a go-getter upgrade
|
||||
would immediately introduce new functionality, but that encapsulation cannot
|
||||
prevent adoption of changes made to pre-existing functionality that
|
||||
Terraform already exposes.
|
||||
|
||||
* `github.com/hashicorp/go-tfe` -- the client library for the HCP Terraform
|
||||
API -- includes various types corresponding to HCP Terraform API
|
||||
requests and responses. The internal package `internal/cloud` contains mock
|
||||
implementations of some of those types, which may need to be updated when
|
||||
the client library is upgraded.
|
||||
|
||||
These upgrades should typically be done only in conjunction with a project
|
||||
that will somehow use the new features through the Cloud integration, so
|
||||
that the team working on that project can perform any needed updates to
|
||||
the mocks as part of their work.
|
||||
|
||||
* `go.opentelemetry.io/otel` and the other supporting OpenTelemetry modules
|
||||
should typically be upgraded together in lockstep, because some of the
|
||||
modules define interfaces that other modules implement, and strange behavior
|
||||
can emerge if one is upgraded without the other.
|
||||
|
||||
The main modules affected by this rule are the ones under the
|
||||
`go.opentelemetry.io/otel` prefix. The "contrib" packages can be trickier
|
||||
to upgrade because they tend to have dependencies that overlap with ours
|
||||
and so might affect non-telemetry-related behavior, and so it's acceptable
|
||||
for those to lag slightly behind to reduce risk in routine upgrades.
|
||||
BIN
docs/images/vscode-debugging-test.png
Normal file
BIN
docs/images/vscode-debugging-test.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 402 KiB |
BIN
docs/images/vscode-debugging.png
Normal file
BIN
docs/images/vscode-debugging.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 383 KiB |
|
|
@ -1,95 +0,0 @@
|
|||
# Maintainer's Etiquette
|
||||
|
||||
Are you a core maintainer of Terraform? Great! Here's a few notes
|
||||
to help you get comfortable when working on the project.
|
||||
|
||||
This documentation is somewhat outdated since it still includes provider-related
|
||||
information even though providers are now developed in their own separate
|
||||
codebases, but the general information is still valid.
|
||||
|
||||
## Expectations
|
||||
|
||||
We value the time you spend on the project and as such your maintainer status
|
||||
doesn't imply any obligations to do any specific work.
|
||||
|
||||
### Your PRs
|
||||
|
||||
These apply to all contributors, but maintainers should lead by examples! :wink:
|
||||
|
||||
- for `provider/*` PRs it's useful to attach test results & advise on how to run the relevant tests
|
||||
- for `bug` fixes it's useful to attach repro case, ideally in a form of a test
|
||||
|
||||
### PRs/issues from others
|
||||
|
||||
- you're welcomed to triage (attach labels to) other PRs and issues
|
||||
- we generally use 2-label system (= at least 2 labels per issue/PR) where one label is generic and other one API-specific, e.g. `enhancement` & `provider/aws`
|
||||
|
||||
## Merging
|
||||
|
||||
- you're free to review PRs from the community or other HC employees and give :+1: / :-1:
|
||||
- if the PR submitter has push privileges (recognizable via `Collaborator`, `Member` or `Owner` badge) - we expect **the submitter** to merge their own PR after receiving a positive review from either HC employee or another maintainer. _Exceptions apply - see below._
|
||||
- we prefer to use the GitHub's interface or API to do this, just click the green button
|
||||
- squash?
|
||||
- squash when you think the commit history is irrelevant (will not be helpful for any readers in T+6months)
|
||||
- Add the new PR to the **Changelog** if it may affect the user (almost any PR except test changes and docs updates)
|
||||
- we prefer to use the GitHub's web interface to modify the Changelog and use `[GH-12345]` to format the PR number. These will be turned into links as part of the release process. Breaking changes should be always documented separately.
|
||||
|
||||
## Release process
|
||||
|
||||
- HC employees are responsible for cutting new releases
|
||||
- The employee cutting the release will always notify all maintainers via Slack channel before & after each release
|
||||
so you can avoid merging PRs during the release process.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Any PR that is significantly changing or even breaking user experience cross-providers should always get at least one :+1: from a HC employee prior to merge.
|
||||
|
||||
It is generally advisable to leave PRs labelled as `core` for HC employees to review and merge.
|
||||
|
||||
Examples include:
|
||||
- adding/changing/removing a CLI (sub)command or a [flag](https://github.com/hashicorp/terraform/pull/12939)
|
||||
- introduce a new feature like [Environments](https://github.com/hashicorp/terraform/pull/12182) or [Shadow Graph](https://github.com/hashicorp/terraform/pull/9334)
|
||||
- changing config (HCL) like [adding support for lists](https://github.com/hashicorp/terraform/pull/6322)
|
||||
- change of the [build process or test environment](https://github.com/hashicorp/terraform/pull/9355)
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- we always try to avoid breaking changes where possible and/or defer them to the nearest major release
|
||||
- [state migration](https://github.com/hashicorp/terraform/blob/2fe5976aec290f4b53f07534f4cde13f6d877a3f/helper/schema/resource.go#L33-L56) may help you avoid breaking changes, see [example](https://github.com/hashicorp/terraform/blob/351c6bed79abbb40e461d3f7d49fe4cf20bced41/builtin/providers/aws/resource_aws_route53_record_migrate.go)
|
||||
- either way BCs should be clearly documented in special section of the Changelog
|
||||
- Any BC must always receive at least one :+1: from HC employee prior to merge, two :+1:s are advisable
|
||||
|
||||
### Examples of Breaking Changes
|
||||
|
||||
- https://github.com/hashicorp/terraform/pull/12396
|
||||
- https://github.com/hashicorp/terraform/pull/13872
|
||||
- https://github.com/hashicorp/terraform/pull/13752
|
||||
|
||||
## Unsure?
|
||||
|
||||
If you're unsure about anything, ask in the committer's Slack channel.
|
||||
|
||||
## New Providers
|
||||
|
||||
These will require :+1: and some extra effort from HC employee.
|
||||
|
||||
We expect all acceptance tests to be as self-sustainable as possible
|
||||
to keep the bar for running any acceptance test low for anyone
|
||||
outside of HashiCorp or core maintainers team.
|
||||
|
||||
We expect any test to run **in parallel** alongside any other test (even the same test).
|
||||
To ensure this is possible, we need all tests to avoid sharing namespaces or using static unique names.
|
||||
In rare occasions this may require the use of mutexes in the resource code.
|
||||
|
||||
### New Remote-API-based provider (e.g. AWS, Google Cloud, PagerDuty, Atlas)
|
||||
|
||||
We will need some details about who to contact or where to register for a new account
|
||||
and generally we can't merge providers before ensuring we have a way to test them nightly,
|
||||
which usually involves setting up a new account and obtaining API credentials.
|
||||
|
||||
### Local provider (e.g. MySQL, PostgreSQL, Kubernetes, Vault)
|
||||
|
||||
We will need either Terraform configs that will set up the underlying test infrastructure
|
||||
(e.g. GKE cluster for Kubernetes) or Dockerfile(s) that will prepare test environment (e.g. MySQL)
|
||||
and expose the endpoint for testing.
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ their behaviors in a way comparable to the resource instance behaviors.
|
|||
|
||||
This is developer-oriented documentation rather than user-oriented
|
||||
documentation. See
|
||||
[the main Terraform documentation](https://www.terraform.io/docs) for
|
||||
[the main Terraform documentation](https://developer.hashicorp.com/terraform/docs) for
|
||||
information on existing planning behaviors and other behaviors as viewed from
|
||||
an end-user perspective.
|
||||
|
||||
|
|
|
|||
6
docs/plugin-protocol/.copywrite.hcl
Normal file
6
docs/plugin-protocol/.copywrite.hcl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
schema_version = 1
|
||||
|
||||
project {
|
||||
license = "MPL-2.0"
|
||||
copyright_year = 2024
|
||||
}
|
||||
355
docs/plugin-protocol/LICENSE
Normal file
355
docs/plugin-protocol/LICENSE
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
Copyright (c) 2014 HashiCorp, Inc.
|
||||
|
||||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
1.1. “Contributor”
|
||||
|
||||
means each individual or legal entity that creates, contributes to the
|
||||
creation of, or owns Covered Software.
|
||||
|
||||
1.2. “Contributor Version”
|
||||
|
||||
means the combination of the Contributions of others (if any) used by a
|
||||
Contributor and that particular Contributor’s Contribution.
|
||||
|
||||
1.3. “Contribution”
|
||||
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. “Covered Software”
|
||||
|
||||
means Source Code Form to which the initial Contributor has attached the
|
||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||
Modifications of such Source Code Form, in each case including portions
|
||||
thereof.
|
||||
|
||||
1.5. “Incompatible With Secondary Licenses”
|
||||
means
|
||||
|
||||
a. that the initial Contributor has attached the notice described in
|
||||
Exhibit B to the Covered Software; or
|
||||
|
||||
b. that the Covered Software was made available under the terms of version
|
||||
1.1 or earlier of the License, but not also under the terms of a
|
||||
Secondary License.
|
||||
|
||||
1.6. “Executable Form”
|
||||
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. “Larger Work”
|
||||
|
||||
means a work that combines Covered Software with other material, in a separate
|
||||
file or files, that is not Covered Software.
|
||||
|
||||
1.8. “License”
|
||||
|
||||
means this document.
|
||||
|
||||
1.9. “Licensable”
|
||||
|
||||
means having the right to grant, to the maximum extent possible, whether at the
|
||||
time of the initial grant or subsequently, any and all of the rights conveyed by
|
||||
this License.
|
||||
|
||||
1.10. “Modifications”
|
||||
|
||||
means any of the following:
|
||||
|
||||
a. any file in Source Code Form that results from an addition to, deletion
|
||||
from, or modification of the contents of Covered Software; or
|
||||
|
||||
b. any new file in Source Code Form that contains any Covered Software.
|
||||
|
||||
1.11. “Patent Claims” of a Contributor
|
||||
|
||||
means any patent claim(s), including without limitation, method, process,
|
||||
and apparatus claims, in any patent Licensable by such Contributor that
|
||||
would be infringed, but for the grant of the License, by the making,
|
||||
using, selling, offering for sale, having made, import, or transfer of
|
||||
either its Contributions or its Contributor Version.
|
||||
|
||||
1.12. “Secondary License”
|
||||
|
||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||
General Public License, Version 2.1, the GNU Affero General Public
|
||||
License, Version 3.0, or any later versions of those licenses.
|
||||
|
||||
1.13. “Source Code Form”
|
||||
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. “You” (or “Your”)
|
||||
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, “You” includes any entity that controls, is
|
||||
controlled by, or is under common control with You. For purposes of this
|
||||
definition, “control” means (a) the power, direct or indirect, to cause
|
||||
the direction or management of such entity, whether by contract or
|
||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||
outstanding shares or beneficial ownership of such entity.
|
||||
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
a. under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or as
|
||||
part of a Larger Work; and
|
||||
|
||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||
sale, have made, import, and otherwise transfer either its Contributions
|
||||
or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution become
|
||||
effective for each Contribution on the date the Contributor first distributes
|
||||
such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under this
|
||||
License. No additional rights or licenses will be implied from the distribution
|
||||
or licensing of Covered Software under this License. Notwithstanding Section
|
||||
2.1(b) above, no patent license is granted by a Contributor:
|
||||
|
||||
a. for any code that a Contributor has removed from Covered Software; or
|
||||
|
||||
b. for infringements caused by: (i) Your and any other third party’s
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
c. under Patent Claims infringed by Covered Software in the absence of its
|
||||
Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks, or
|
||||
logos of any Contributor (except as may be necessary to comply with the
|
||||
notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this License
|
||||
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
||||
under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its Contributions
|
||||
are its original creation(s) or it has sufficient rights to grant the
|
||||
rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under applicable
|
||||
copyright doctrines of fair use, fair dealing, or other equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||
Section 2.1.
|
||||
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under the
|
||||
terms of this License. You must inform recipients that the Source Code Form
|
||||
of the Covered Software is governed by the terms of this License, and how
|
||||
they can obtain a copy of this License. You may not attempt to alter or
|
||||
restrict the recipients’ rights in the Source Code Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
a. such Covered Software must also be made available in Source Code Form,
|
||||
as described in Section 3.1, and You must inform recipients of the
|
||||
Executable Form how they can obtain a copy of such Source Code Form by
|
||||
reasonable means in a timely manner, at a charge no more than the cost
|
||||
of distribution to the recipient; and
|
||||
|
||||
b. You may distribute such Executable Form under the terms of this License,
|
||||
or sublicense it under different terms, provided that the license for
|
||||
the Executable Form does not attempt to limit or alter the recipients’
|
||||
rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for the
|
||||
Covered Software. If the Larger Work is a combination of Covered Software
|
||||
with a work governed by one or more Secondary Licenses, and the Covered
|
||||
Software is not Incompatible With Secondary Licenses, this License permits
|
||||
You to additionally distribute such Covered Software under the terms of
|
||||
such Secondary License(s), so that the recipient of the Larger Work may, at
|
||||
their option, further distribute the Covered Software under the terms of
|
||||
either this License or such Secondary License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices (including
|
||||
copyright notices, patent notices, disclaimers of warranty, or limitations
|
||||
of liability) contained within the Source Code Form of the Covered
|
||||
Software, except that You may alter any license notices to the extent
|
||||
required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on behalf
|
||||
of any Contributor. You must make it absolutely clear that any such
|
||||
warranty, support, indemnity, or liability obligation is offered by You
|
||||
alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this License
|
||||
with respect to some or all of the Covered Software due to statute, judicial
|
||||
order, or regulation then You must: (a) comply with the terms of this License
|
||||
to the maximum extent possible; and (b) describe the limitations and the code
|
||||
they affect. Such description must be placed in a text file included with all
|
||||
distributions of the Covered Software under this License. Except to the
|
||||
extent prohibited by statute or regulation, such description must be
|
||||
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||
understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically if You
|
||||
fail to comply with any of its terms. However, if You become compliant,
|
||||
then the rights granted under this License from a particular Contributor
|
||||
are reinstated (a) provisionally, unless and until such Contributor
|
||||
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
||||
if such Contributor fails to notify You of the non-compliance by some
|
||||
reasonable means prior to 60 days after You have come back into compliance.
|
||||
Moreover, Your grants from a particular Contributor are reinstated on an
|
||||
ongoing basis if such Contributor notifies You of the non-compliance by
|
||||
some reasonable means, this is the first time You have received notice of
|
||||
non-compliance with this License from such Contributor, and You become
|
||||
compliant prior to 30 days after Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions, counter-claims,
|
||||
and cross-claims) alleging that a Contributor Version directly or
|
||||
indirectly infringes any patent, then the rights granted to You by any and
|
||||
all Contributors for the Covered Software under Section 2.1 of this License
|
||||
shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||
license agreements (excluding distributors and resellers) which have been
|
||||
validly granted by You or Your distributors under this License prior to
|
||||
termination shall survive termination.
|
||||
|
||||
6. Disclaimer of Warranty
|
||||
|
||||
Covered Software is provided under this License on an “as is” basis, without
|
||||
warranty of any kind, either expressed, implied, or statutory, including,
|
||||
without limitation, warranties that the Covered Software is free of defects,
|
||||
merchantable, fit for a particular purpose or non-infringing. The entire
|
||||
risk as to the quality and performance of the Covered Software is with You.
|
||||
Should any Covered Software prove defective in any respect, You (not any
|
||||
Contributor) assume the cost of any necessary servicing, repair, or
|
||||
correction. This disclaimer of warranty constitutes an essential part of this
|
||||
License. No use of any Covered Software is authorized under this License
|
||||
except under this disclaimer.
|
||||
|
||||
7. Limitation of Liability
|
||||
|
||||
Under no circumstances and under no legal theory, whether tort (including
|
||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||
distributes Covered Software as permitted above, be liable to You for any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character including, without limitation, damages for lost profits, loss of
|
||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses, even if such party shall have been
|
||||
informed of the possibility of such damages. This limitation of liability
|
||||
shall not apply to liability for death or personal injury resulting from such
|
||||
party’s negligence to the extent applicable law prohibits such limitation.
|
||||
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
||||
consequential damages, so this exclusion and limitation may not apply to You.
|
||||
|
||||
8. Litigation
|
||||
|
||||
Any litigation relating to this License may be brought only in the courts of
|
||||
a jurisdiction where the defendant maintains its principal place of business
|
||||
and such litigation shall be governed by laws of that jurisdiction, without
|
||||
reference to its conflict-of-law provisions. Nothing in this Section shall
|
||||
prevent a party’s ability to bring cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
This License represents the complete agreement concerning the subject matter
|
||||
hereof. If any provision of this License is held to be unenforceable, such
|
||||
provision shall be reformed only to the extent necessary to make it
|
||||
enforceable. Any law or regulation which provides that the language of a
|
||||
contract shall be construed against the drafter shall not be used to construe
|
||||
this License against a Contributor.
|
||||
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version of
|
||||
the License under which You originally received the Covered Software, or
|
||||
under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a modified
|
||||
version of this License if you rename the license and remove any
|
||||
references to the name of the license steward (except to note that such
|
||||
modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file, then
|
||||
You may include the notice in a location (such as a LICENSE file in a relevant
|
||||
directory) where a recipient would be likely to look for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
||||
|
||||
This Source Code Form is “Incompatible
|
||||
With Secondary Licenses”, as defined by
|
||||
the Mozilla Public License, v. 2.0.
|
||||
|
|
@ -10,7 +10,7 @@ the SDK's API.
|
|||
----
|
||||
|
||||
**If you want to write a plugin for Terraform, please refer to
|
||||
[Extending Terraform](https://www.terraform.io/docs/extend/index.html) instead.**
|
||||
[Plugin development](https://developer.hashicorp.com/terraform/plugin) instead.**
|
||||
|
||||
This documentation is for those who are developing _Terraform SDKs_, rather
|
||||
than those implementing plugins.
|
||||
|
|
@ -56,8 +56,7 @@ do not follow this strategy.
|
|||
|
||||
The authoritative definition for each protocol version is in this directory
|
||||
as a Protocol Buffers (protobuf) service definition. The files follow the
|
||||
naming pattern `tfpluginX.Y.proto`, where X is the major version and Y
|
||||
is the minor version.
|
||||
naming pattern `tfpluginX.proto`, where X is the major version.
|
||||
|
||||
### Major and minor versioning
|
||||
|
||||
|
|
@ -211,3 +210,22 @@ new file in this directory for each new minor version and consider all
|
|||
previously-tagged definitions as immutable. The outdated comments in those
|
||||
files are retained in order to keep the promise of immutability, even though
|
||||
it is now incorrect.
|
||||
|
||||
## Updating the plugin protocol in Terraform core
|
||||
|
||||
> Note: This section's audience is contributors to Terraform, not developers creating a new SDK.
|
||||
|
||||
New features added to Terraform core often require an update to the plugin protocol. These changes are reflected in a new minor version of the plugin protocol.
|
||||
|
||||
A new minor release of Terraform should only introduce one new minor release of the plugin-protocol. The minor release numbers of the plugin protocol and Terraform do not match, but they should have a one-to-one relationship.
|
||||
|
||||
### Add updates to a new plugin protocol minor version
|
||||
|
||||
1) Edit the `.proto` files for Protocol 5 and 6 in `docs/plugin-protocol/`.
|
||||
* If this is the first bigger change after a Terraform release, you may want to increase the minor protocol version in the file header
|
||||
1) Commit your changes.
|
||||
1) Run `make protobuf`.
|
||||
* This will use the symlinks in the `internal/tfplugin*` directories to access the latest minor versions' `.proto` files.
|
||||
* You should see diffs in `internal/tfplugin5/tfplugin5.pb.go` and `internal/tfplugin6/tfplugin6.pb.go`.
|
||||
1) Run `make generate`.
|
||||
* You should see diffs in `internal/plugin/mock_proto/mock.go` and `internal/plugin6/mock_proto/mock.go`.
|
||||
|
|
@ -63,7 +63,7 @@ The key-value pairs representing nested block types have values based on
|
|||
The MessagePack serialization of an attribute value depends on the value of the
|
||||
`type` field of the corresponding `Schema.Attribute` message. The `type` field is
|
||||
a compact JSON serialization of a
|
||||
[Terraform type constraint](https://www.terraform.io/docs/configuration/types.html),
|
||||
[Terraform type constraint](https://developer.hashicorp.com/terraform/language/expressions/type-constraints),
|
||||
which consists either of a single
|
||||
string value (for primitive types) or a two-element array giving a type kind
|
||||
and a type argument.
|
||||
|
|
@ -76,8 +76,7 @@ in the table below, regardless of type:
|
|||
* An unknown value (that is, a placeholder for a value that will be decided
|
||||
only during the apply operation) is represented as a
|
||||
[MessagePack extension](https://github.com/msgpack/msgpack/blob/master/spec.md#extension-types)
|
||||
value whose type identifier is zero and whose value is unspecified and
|
||||
meaningless.
|
||||
value, described in more detail below.
|
||||
|
||||
| `type` Pattern | MessagePack Representation |
|
||||
|---|---|
|
||||
|
|
@ -91,6 +90,64 @@ in the table below, regardless of type:
|
|||
| `["tuple",TYPES]` | A MessagePack array with one element per element described by the `TYPES` array. The element values are constructed by applying these same mapping rules to the corresponding element of `TYPES`. |
|
||||
| `"dynamic"` | A MessagePack array with exactly two elements. The first element is a MessagePack binary value containing a JSON-serialized type constraint in the same format described in this table. The second element is the result of applying these same mapping rules to the value with the type given in the first element. This special type constraint represents values whose types will be decided only at runtime. |
|
||||
|
||||
Unknown values have two possible representations, both using
|
||||
[MessagePack extension](https://github.com/msgpack/msgpack/blob/master/spec.md#extension-types)
|
||||
values.
|
||||
|
||||
The older encoding is for unrefined unknown values and uses an extension
|
||||
code of zero, with the extension value payload completely ignored.
|
||||
|
||||
Newer Terraform versions can produce "refined" unknown values which carry some
|
||||
additional information that constrains the possible range of the final value/
|
||||
Refined unknown values have extension code 12 and then the extension object's
|
||||
payload is a MessagePack-encoded map using integer keys to represent different
|
||||
kinds of refinement:
|
||||
|
||||
* `1` represents "nullness", and the value of that key will be a boolean
|
||||
value that is true if the value is definitely null or false if it is
|
||||
definitely not null. If this key isn't present at all then the value may or
|
||||
may not be null. It's not actually useful to encode that an unknown value
|
||||
is null; use a known null value instead in that case, because there is only
|
||||
one null value of each type.
|
||||
* `2` represents string prefix, and the value is a string that the final
|
||||
value is known to begin with. This is valid only for unknown values of string
|
||||
type.
|
||||
* `3` and `4` represent the lower and upper bounds respectively of a number
|
||||
value, and the value of both is a two-element msgpack array whose
|
||||
first element is a valid encoding of a number (as in the table above)
|
||||
and whose second element is a boolean value that is true for an inclusive
|
||||
bound and false for an exclusive bound. This is valid only for unknown values
|
||||
of number type.
|
||||
* `5` and `6` represent the lower and upper bounds respectively of the length
|
||||
of a collection value. The value of both is an integer representing an
|
||||
inclusive bound. This is valid only for unknown values of the three kinds of
|
||||
collection types: list, set, and map.
|
||||
|
||||
Unknown value refinements are an optional way to reduce the range of possible
|
||||
values for situations where that makes it possible to produce a known result
|
||||
for unknown inputs or where it allows detecting an error during the planning
|
||||
phase that would otherwise be detected only during the apply phase. It's always
|
||||
safe to ignore refinements and just treat an unknown value as wholly unknown,
|
||||
but considering refinements may allow a more precise answer. A provider that
|
||||
produces refined values in its planned new state (from `PlanResourceChange`)
|
||||
_must_ honor those refinements in the final state (from `ApplyResourceChange`).
|
||||
|
||||
Unmarshalling code should ignore refinement map keys that they don't know about,
|
||||
because future versions of the protocol might define additional refinements.
|
||||
|
||||
When encoding an unknown value without any refinements, always use the older
|
||||
format with extension code zero instead of using extension code 12 with an
|
||||
empty refinement map. Any refined unknown value _must_ have at least one
|
||||
refinement map entry. This rule ensures backward compatibility with older
|
||||
implementations that predate the value refinements concept.
|
||||
|
||||
A server implementation of the protocol should treat _any_ MessagePack extension
|
||||
code as representing an unknown value, but should ignore the payload of that
|
||||
extension value entirely unless the extension code is 12 to indicate that
|
||||
the body represents refinements. Future versions of this protocol may define
|
||||
specific formats for other extension codes, but they will always represent
|
||||
unknown values.
|
||||
|
||||
### `Schema.NestedBlock` Mapping Rules for MessagePack
|
||||
|
||||
The MessagePack serialization of a collection of blocks of a particular type
|
||||
|
|
@ -155,7 +212,7 @@ The properties representing nested block types have property values based on
|
|||
The JSON serialization of an attribute value depends on the value of the `type`
|
||||
field of the corresponding `Schema.Attribute` message. The `type` field is
|
||||
a compact JSON serialization of a
|
||||
[Terraform type constraint](https://www.terraform.io/docs/configuration/types.html),
|
||||
[Terraform type constraint](https://developer.hashicorp.com/terraform/language/expressions/type-constraints),
|
||||
which consists either of a single
|
||||
string value (for primitive types) or a two-element array giving a type kind
|
||||
and a type argument.
|
||||
|
|
|
|||
|
|
@ -1,353 +0,0 @@
|
|||
// Terraform Plugin RPC protocol version 5.0
|
||||
//
|
||||
// This file defines version 5.0 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// This file will be updated in-place in the source Terraform repository for
|
||||
// any minor versions of protocol 5, but later minor versions will always be
|
||||
// backwards compatible. Breaking changes, if any are required, will come
|
||||
// in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
|
||||
package tfplugin5;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message Stop {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource, Provider, or Provisioner.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
rpc GetSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc PrepareProviderConfig(PrepareProviderConfig.Request) returns (PrepareProviderConfig.Response);
|
||||
rpc ValidateResourceTypeConfig(ValidateResourceTypeConfig.Request) returns (ValidateResourceTypeConfig.Response);
|
||||
rpc ValidateDataSourceConfig(ValidateDataSourceConfig.Request) returns (ValidateDataSourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc Configure(Configure.Request) returns (Configure.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message PrepareProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue prepared_config = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceTypeConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataSourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message Configure {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
service Provisioner {
|
||||
rpc GetSchema(GetProvisionerSchema.Request) returns (GetProvisionerSchema.Response);
|
||||
rpc ValidateProvisionerConfig(ValidateProvisionerConfig.Request) returns (ValidateProvisionerConfig.Response);
|
||||
rpc ProvisionResource(ProvisionResource.Request) returns (stream ProvisionResource.Response);
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProvisionerSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provisioner = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProvisionerConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ProvisionResource {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
DynamicValue connection = 2;
|
||||
}
|
||||
message Response {
|
||||
string output = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,353 +0,0 @@
|
|||
// Terraform Plugin RPC protocol version 5.1
|
||||
//
|
||||
// This file defines version 5.1 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// This file will be updated in-place in the source Terraform repository for
|
||||
// any minor versions of protocol 5, but later minor versions will always be
|
||||
// backwards compatible. Breaking changes, if any are required, will come
|
||||
// in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
|
||||
package tfplugin5;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message Stop {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource, Provider, or Provisioner.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
rpc GetSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc PrepareProviderConfig(PrepareProviderConfig.Request) returns (PrepareProviderConfig.Response);
|
||||
rpc ValidateResourceTypeConfig(ValidateResourceTypeConfig.Request) returns (ValidateResourceTypeConfig.Response);
|
||||
rpc ValidateDataSourceConfig(ValidateDataSourceConfig.Request) returns (ValidateDataSourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc Configure(Configure.Request) returns (Configure.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message PrepareProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue prepared_config = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceTypeConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataSourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message Configure {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
service Provisioner {
|
||||
rpc GetSchema(GetProvisionerSchema.Request) returns (GetProvisionerSchema.Response);
|
||||
rpc ValidateProvisionerConfig(ValidateProvisionerConfig.Request) returns (ValidateProvisionerConfig.Response);
|
||||
rpc ProvisionResource(ProvisionResource.Request) returns (stream ProvisionResource.Response);
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProvisionerSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provisioner = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProvisionerConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ProvisionResource {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
DynamicValue connection = 2;
|
||||
}
|
||||
message Response {
|
||||
string output = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,369 +0,0 @@
|
|||
// Terraform Plugin RPC protocol version 5.2
|
||||
//
|
||||
// This file defines version 5.2 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// This file will not be updated. Any minor versions of protocol 5 to follow
|
||||
// should copy this file and modify the copy while maintaing backwards
|
||||
// compatibility. Breaking changes, if any are required, will come
|
||||
// in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/hashicorp/terraform/internal/tfplugin5";
|
||||
|
||||
package tfplugin5;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message Stop {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
enum StringKind {
|
||||
PLAIN = 0;
|
||||
MARKDOWN = 1;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource, Provider, or Provisioner.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
string description = 4;
|
||||
StringKind description_kind = 5;
|
||||
bool deprecated = 6;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
StringKind description_kind = 8;
|
||||
bool deprecated = 9;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
rpc GetSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc PrepareProviderConfig(PrepareProviderConfig.Request) returns (PrepareProviderConfig.Response);
|
||||
rpc ValidateResourceTypeConfig(ValidateResourceTypeConfig.Request) returns (ValidateResourceTypeConfig.Response);
|
||||
rpc ValidateDataSourceConfig(ValidateDataSourceConfig.Request) returns (ValidateDataSourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc Configure(Configure.Request) returns (Configure.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
Schema provider_meta = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message PrepareProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue prepared_config = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceTypeConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataSourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message Configure {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
DynamicValue provider_meta = 4;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
DynamicValue provider_meta = 3;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
service Provisioner {
|
||||
rpc GetSchema(GetProvisionerSchema.Request) returns (GetProvisionerSchema.Response);
|
||||
rpc ValidateProvisionerConfig(ValidateProvisionerConfig.Request) returns (ValidateProvisionerConfig.Response);
|
||||
rpc ProvisionResource(ProvisionResource.Request) returns (stream ProvisionResource.Response);
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProvisionerSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provisioner = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProvisionerConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ProvisionResource {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
DynamicValue connection = 2;
|
||||
}
|
||||
message Response {
|
||||
string output = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,381 +0,0 @@
|
|||
// Terraform Plugin RPC protocol version 5.3
|
||||
//
|
||||
// This file defines version 5.3 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// This file will not be updated. Any minor versions of protocol 5 to follow
|
||||
// should copy this file and modify the copy while maintaing backwards
|
||||
// compatibility. Breaking changes, if any are required, will come
|
||||
// in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/hashicorp/terraform/internal/tfplugin5";
|
||||
|
||||
package tfplugin5;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message Stop {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
enum StringKind {
|
||||
PLAIN = 0;
|
||||
MARKDOWN = 1;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource, Provider, or Provisioner.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
string description = 4;
|
||||
StringKind description_kind = 5;
|
||||
bool deprecated = 6;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
StringKind description_kind = 8;
|
||||
bool deprecated = 9;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
rpc GetSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc PrepareProviderConfig(PrepareProviderConfig.Request) returns (PrepareProviderConfig.Response);
|
||||
rpc ValidateResourceTypeConfig(ValidateResourceTypeConfig.Request) returns (ValidateResourceTypeConfig.Response);
|
||||
rpc ValidateDataSourceConfig(ValidateDataSourceConfig.Request) returns (ValidateDataSourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc Configure(Configure.Request) returns (Configure.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
Schema provider_meta = 5;
|
||||
ServerCapabilities server_capabilities = 6;
|
||||
}
|
||||
|
||||
|
||||
// ServerCapabilities allows providers to communicate extra information
|
||||
// regarding supported protocol features. This is used to indicate
|
||||
// availability of certain forward-compatible changes which may be optional
|
||||
// in a major protocol version, but cannot be tested for directly.
|
||||
message ServerCapabilities {
|
||||
// The plan_destroy capability signals that a provider expects a call
|
||||
// to PlanResourceChange when a resource is going to be destroyed.
|
||||
bool plan_destroy = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message PrepareProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue prepared_config = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceTypeConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataSourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message Configure {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
DynamicValue provider_meta = 4;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
DynamicValue provider_meta = 3;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
service Provisioner {
|
||||
rpc GetSchema(GetProvisionerSchema.Request) returns (GetProvisionerSchema.Response);
|
||||
rpc ValidateProvisionerConfig(ValidateProvisionerConfig.Request) returns (ValidateProvisionerConfig.Response);
|
||||
rpc ProvisionResource(ProvisionResource.Request) returns (stream ProvisionResource.Response);
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProvisionerSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provisioner = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProvisionerConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ProvisionResource {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
DynamicValue connection = 2;
|
||||
}
|
||||
message Response {
|
||||
string output = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
813
docs/plugin-protocol/tfplugin5.proto
Normal file
813
docs/plugin-protocol/tfplugin5.proto
Normal file
|
|
@ -0,0 +1,813 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
// Terraform Plugin RPC protocol version 5.9
|
||||
//
|
||||
// This file defines version 5.9 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// Any minor versions of protocol 5 to follow should modify this file while
|
||||
// maintaining backwards compatibility. Breaking changes, if any are required,
|
||||
// will come in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/hashicorp/terraform/internal/tfplugin5";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
package tfplugin5;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message FunctionError {
|
||||
string text = 1;
|
||||
// The optional function_argument records the index position of the
|
||||
// argument which caused the error.
|
||||
optional int64 function_argument = 2;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message Stop {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
enum StringKind {
|
||||
PLAIN = 0;
|
||||
MARKDOWN = 1;
|
||||
}
|
||||
|
||||
// ResourceIdentitySchema represents the structure and types of data used to identify
|
||||
// a managed resource type. Effectively, resource identity is a versioned object
|
||||
// that can be used to compare resources, whether already managed and/or being
|
||||
// discovered.
|
||||
message ResourceIdentitySchema {
|
||||
// IdentityAttribute represents one value of data within resource identity. These
|
||||
// are always used in resource identity comparisons.
|
||||
message IdentityAttribute {
|
||||
// name is the identity attribute name
|
||||
string name = 1;
|
||||
|
||||
// type is the identity attribute type
|
||||
bytes type = 2;
|
||||
|
||||
// required_for_import when enabled signifies that this attribute must be
|
||||
// defined for ImportResourceState to complete successfully
|
||||
bool required_for_import = 3;
|
||||
|
||||
// optional_for_import when enabled signifies that this attribute is not
|
||||
// required for ImportResourceState, because it can be supplied by the
|
||||
// provider. It is still possible to supply this attribute during import.
|
||||
bool optional_for_import = 4;
|
||||
|
||||
// description is a human-readable description of the attribute in Markdown
|
||||
string description = 5;
|
||||
}
|
||||
|
||||
// version is the identity version and separate from the Schema version.
|
||||
// Any time the structure or format of identity_attributes changes, this version
|
||||
// should be incremented. Versioning implicitly starts at 0 and by convention
|
||||
// should be incremented by 1 each change.
|
||||
//
|
||||
// When comparing identity_attributes data, differing versions should always be treated
|
||||
// as inequal.
|
||||
int64 version = 1;
|
||||
|
||||
// identity_attributes are the individual value definitions which define identity data
|
||||
// for a managed resource type. This information is used to decode DynamicValue of
|
||||
// identity data.
|
||||
//
|
||||
// These attributes are intended for permanent identity data and must be wholly
|
||||
// representative of all data necessary to compare two managed resource instances
|
||||
// with no other data. This generally should include account, endpoint, location,
|
||||
// and automatically generated identifiers. For some resources, this may include
|
||||
// configuration-based data, such as a required name which must be unique.
|
||||
repeated IdentityAttribute identity_attributes = 2;
|
||||
}
|
||||
|
||||
message ResourceIdentityData {
|
||||
// identity_data is the resource identity data for the given definition. It should
|
||||
// be decoded using the identity schema.
|
||||
//
|
||||
// This data is considered permanent for the identity version and suitable for
|
||||
// longer-term storage.
|
||||
DynamicValue identity_data = 1;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource, Provider, or Provisioner.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
string description = 4;
|
||||
StringKind description_kind = 5;
|
||||
bool deprecated = 6;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
StringKind description_kind = 8;
|
||||
bool deprecated = 9;
|
||||
bool write_only = 10;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
// ServerCapabilities allows providers to communicate extra information
|
||||
// regarding supported protocol features. This is used to indicate
|
||||
// availability of certain forward-compatible changes which may be optional
|
||||
// in a major protocol version, but cannot be tested for directly.
|
||||
message ServerCapabilities {
|
||||
// The plan_destroy capability signals that a provider expects a call
|
||||
// to PlanResourceChange when a resource is going to be destroyed.
|
||||
bool plan_destroy = 1;
|
||||
|
||||
// The get_provider_schema_optional capability indicates that this
|
||||
// provider does not require calling GetProviderSchema to operate
|
||||
// normally, and the caller can used a cached copy of the provider's
|
||||
// schema.
|
||||
bool get_provider_schema_optional = 2;
|
||||
|
||||
// The move_resource_state capability signals that a provider supports the
|
||||
// MoveResourceState RPC.
|
||||
bool move_resource_state = 3;
|
||||
}
|
||||
|
||||
// ClientCapabilities allows Terraform to publish information regarding
|
||||
// supported protocol features. This is used to indicate availability of
|
||||
// certain forward-compatible changes which may be optional in a major
|
||||
// protocol version, but cannot be tested for directly.
|
||||
message ClientCapabilities {
|
||||
// The deferral_allowed capability signals that the client is able to
|
||||
// handle deferred responses from the provider.
|
||||
bool deferral_allowed = 1;
|
||||
|
||||
// The write_only_attributes_allowed capability signals that the client
|
||||
// is able to handle write_only attributes for managed resources.
|
||||
bool write_only_attributes_allowed = 2;
|
||||
}
|
||||
|
||||
message Function {
|
||||
// parameters is the ordered list of positional function parameters.
|
||||
repeated Parameter parameters = 1;
|
||||
|
||||
// variadic_parameter is an optional final parameter which accepts
|
||||
// zero or more argument values, in which Terraform will send an
|
||||
// ordered list of the parameter type.
|
||||
Parameter variadic_parameter = 2;
|
||||
|
||||
// Return is the function return parameter.
|
||||
Return return = 3;
|
||||
|
||||
// summary is the human-readable shortened documentation for the function.
|
||||
string summary = 4;
|
||||
|
||||
// description is human-readable documentation for the function.
|
||||
string description = 5;
|
||||
|
||||
// description_kind is the formatting of the description.
|
||||
StringKind description_kind = 6;
|
||||
|
||||
// deprecation_message is human-readable documentation if the
|
||||
// function is deprecated.
|
||||
string deprecation_message = 7;
|
||||
|
||||
message Parameter {
|
||||
// name is the human-readable display name for the parameter.
|
||||
string name = 1;
|
||||
|
||||
// type is the type constraint for the parameter.
|
||||
bytes type = 2;
|
||||
|
||||
// allow_null_value when enabled denotes that a null argument value can
|
||||
// be passed to the provider. When disabled, Terraform returns an error
|
||||
// if the argument value is null.
|
||||
bool allow_null_value = 3;
|
||||
|
||||
// allow_unknown_values when enabled denotes that only wholly known
|
||||
// argument values will be passed to the provider. When disabled,
|
||||
// Terraform skips the function call entirely and assumes an unknown
|
||||
// value result from the function.
|
||||
bool allow_unknown_values = 4;
|
||||
|
||||
// description is human-readable documentation for the parameter.
|
||||
string description = 5;
|
||||
|
||||
// description_kind is the formatting of the description.
|
||||
StringKind description_kind = 6;
|
||||
}
|
||||
|
||||
message Return {
|
||||
// type is the type constraint for the function result.
|
||||
bytes type = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Deferred is a message that indicates that change is deferred for a reason.
|
||||
message Deferred {
|
||||
// Reason is the reason for deferring the change.
|
||||
enum Reason {
|
||||
// UNKNOWN is the default value, and should not be used.
|
||||
UNKNOWN = 0;
|
||||
// RESOURCE_CONFIG_UNKNOWN is used when the config is partially unknown and the real
|
||||
// values need to be known before the change can be planned.
|
||||
RESOURCE_CONFIG_UNKNOWN = 1;
|
||||
// PROVIDER_CONFIG_UNKNOWN is used when parts of the provider configuration
|
||||
// are unknown, e.g. the provider configuration is only known after the apply is done.
|
||||
PROVIDER_CONFIG_UNKNOWN = 2;
|
||||
// ABSENT_PREREQ is used when a hard dependency has not been satisfied.
|
||||
ABSENT_PREREQ = 3;
|
||||
}
|
||||
|
||||
// reason is the reason for deferring the change.
|
||||
Reason reason = 1;
|
||||
}
|
||||
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
|
||||
// GetMetadata returns upfront information about server capabilities and
|
||||
// supported resource types without requiring the server to instantiate all
|
||||
// schema information, which may be memory intensive. This RPC is optional,
|
||||
// where clients may receive an unimplemented RPC error. Clients should
|
||||
// ignore the error and call the GetSchema RPC as a fallback.
|
||||
rpc GetMetadata(GetMetadata.Request) returns (GetMetadata.Response);
|
||||
|
||||
// GetSchema returns schema information for the provider, data resources,
|
||||
// and managed resources.
|
||||
rpc GetSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc PrepareProviderConfig(PrepareProviderConfig.Request) returns (PrepareProviderConfig.Response);
|
||||
rpc ValidateResourceTypeConfig(ValidateResourceTypeConfig.Request) returns (ValidateResourceTypeConfig.Response);
|
||||
rpc ValidateDataSourceConfig(ValidateDataSourceConfig.Request) returns (ValidateDataSourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
// GetResourceIdentitySchemas returns the identity schemas for all managed
|
||||
// resources.
|
||||
rpc GetResourceIdentitySchemas(GetResourceIdentitySchemas.Request) returns (GetResourceIdentitySchemas.Response);
|
||||
// UpgradeResourceIdentityData should return the upgraded resource identity
|
||||
// data for a managed resource type.
|
||||
rpc UpgradeResourceIdentity(UpgradeResourceIdentity.Request) returns (UpgradeResourceIdentity.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc Configure(Configure.Request) returns (Configure.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
rpc MoveResourceState(MoveResourceState.Request) returns (MoveResourceState.Response);
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Ephemeral Resource Lifecycle
|
||||
rpc ValidateEphemeralResourceConfig(ValidateEphemeralResourceConfig.Request) returns (ValidateEphemeralResourceConfig.Response);
|
||||
rpc OpenEphemeralResource(OpenEphemeralResource.Request) returns (OpenEphemeralResource.Response);
|
||||
rpc RenewEphemeralResource(RenewEphemeralResource.Request) returns (RenewEphemeralResource.Response);
|
||||
rpc CloseEphemeralResource(CloseEphemeralResource.Request) returns (CloseEphemeralResource.Response);
|
||||
|
||||
// GetFunctions returns the definitions of all functions.
|
||||
rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response);
|
||||
|
||||
//////// Provider-contributed Functions
|
||||
rpc CallFunction(CallFunction.Request) returns (CallFunction.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetMetadata {
|
||||
message Request {
|
||||
}
|
||||
|
||||
message Response {
|
||||
ServerCapabilities server_capabilities = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
repeated DataSourceMetadata data_sources = 3;
|
||||
repeated ResourceMetadata resources = 4;
|
||||
// functions returns metadata for any functions.
|
||||
repeated FunctionMetadata functions = 5;
|
||||
repeated EphemeralMetadata ephemeral_resources = 6;
|
||||
}
|
||||
|
||||
message EphemeralMetadata {
|
||||
string type_name = 1;
|
||||
}
|
||||
|
||||
message FunctionMetadata {
|
||||
// name is the function name.
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message DataSourceMetadata {
|
||||
string type_name = 1;
|
||||
}
|
||||
|
||||
message ResourceMetadata {
|
||||
string type_name = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
map<string, Function> functions = 7;
|
||||
map<string, Schema> ephemeral_resource_schemas = 8;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
Schema provider_meta = 5;
|
||||
ServerCapabilities server_capabilities = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message PrepareProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue prepared_config = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
// Request is the message that is sent to the provider during the
|
||||
// UpgradeResourceState RPC.
|
||||
//
|
||||
// This message intentionally does not include configuration data as any
|
||||
// configuration-based or configuration-conditional changes should occur
|
||||
// during the PlanResourceChange RPC. Additionally, the configuration is
|
||||
// not guaranteed to exist (in the case of resource destruction), be wholly
|
||||
// known, nor match the given prior state, which could lead to unexpected
|
||||
// provider behaviors for practitioners.
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message GetResourceIdentitySchemas {
|
||||
message Request {
|
||||
}
|
||||
|
||||
message Response {
|
||||
// identity_schemas is a mapping of resource type names to their identity schemas.
|
||||
map<string, ResourceIdentitySchema> identity_schemas = 1;
|
||||
|
||||
// diagnostics is the collection of warning and error diagnostics for this request.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceIdentity {
|
||||
message Request {
|
||||
// type_name is the managed resource type name
|
||||
string type_name = 1;
|
||||
|
||||
// version is the version of the resource identity data to upgrade
|
||||
int64 version = 2;
|
||||
|
||||
// raw_identity is the raw identity as stored for the resource. Core does
|
||||
// not have access to the identity schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_identity will be json encoded.
|
||||
RawState raw_identity = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
// upgraded_identity returns the upgraded resource identity data
|
||||
ResourceIdentityData upgraded_identity = 1;
|
||||
|
||||
// diagnostics is the collection of warning and error diagnostics for this request
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceTypeConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
ClientCapabilities client_capabilities = 3;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataSourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateEphemeralResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message Configure {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
ClientCapabilities client_capabilities = 3;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
// Request is the message that is sent to the provider during the
|
||||
// ReadResource RPC.
|
||||
//
|
||||
// This message intentionally does not include configuration data as any
|
||||
// configuration-based or configuration-conditional changes should occur
|
||||
// during the PlanResourceChange RPC. Additionally, the configuration is
|
||||
// not guaranteed to be wholly known nor match the given prior state, which
|
||||
// could lead to unexpected provider behaviors for practitioners.
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
DynamicValue provider_meta = 4;
|
||||
ClientCapabilities client_capabilities = 5;
|
||||
ResourceIdentityData current_identity = 6;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
// deferred is set if the provider is deferring the change. If set the caller
|
||||
// needs to handle the deferral.
|
||||
Deferred deferred = 4;
|
||||
ResourceIdentityData new_identity = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
ClientCapabilities client_capabilities = 7;
|
||||
ResourceIdentityData prior_identity = 8;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 5;
|
||||
|
||||
// deferred is set if the provider is deferring the change. If set the caller
|
||||
// needs to handle the deferral.
|
||||
Deferred deferred = 6;
|
||||
|
||||
ResourceIdentityData planned_identity = 7;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
ResourceIdentityData planned_identity = 7;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 4;
|
||||
|
||||
ResourceIdentityData new_identity = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
ClientCapabilities client_capabilities = 3;
|
||||
ResourceIdentityData identity = 4;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
ResourceIdentityData identity = 4;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
// deferred is set if the provider is deferring the change. If set the caller
|
||||
// needs to handle the deferral.
|
||||
Deferred deferred = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message MoveResourceState {
|
||||
message Request {
|
||||
// The address of the provider the resource is being moved from.
|
||||
string source_provider_address = 1;
|
||||
|
||||
// The resource type that the resource is being moved from.
|
||||
string source_type_name = 2;
|
||||
|
||||
// The schema version of the resource type that the resource is being
|
||||
// moved from.
|
||||
int64 source_schema_version = 3;
|
||||
|
||||
// The raw state of the resource being moved. Only the json field is
|
||||
// populated, as there should be no legacy providers using the flatmap
|
||||
// format that support newly introduced RPCs.
|
||||
RawState source_state = 4;
|
||||
|
||||
// The resource type that the resource is being moved to.
|
||||
string target_type_name = 5;
|
||||
|
||||
// The private state of the resource being moved.
|
||||
bytes source_private = 6;
|
||||
|
||||
// The raw identity of the resource being moved. Only the json field is
|
||||
// populated, as there should be no legacy providers using the flatmap
|
||||
// format that support newly introduced RPCs.
|
||||
RawState source_identity = 7;
|
||||
|
||||
// The identity schema version of the resource type that the resource
|
||||
// is being moved from.
|
||||
int64 source_identity_schema_version = 8;
|
||||
}
|
||||
|
||||
message Response {
|
||||
// The state of the resource after it has been moved.
|
||||
DynamicValue target_state = 1;
|
||||
|
||||
// Any diagnostics that occurred during the move.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
|
||||
// The private state of the resource after it has been moved.
|
||||
bytes target_private = 3;
|
||||
|
||||
ResourceIdentityData target_identity = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
DynamicValue provider_meta = 3;
|
||||
ClientCapabilities client_capabilities = 4;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
// deferred is set if the provider is deferring the change. If set the caller
|
||||
// needs to handle the deferral.
|
||||
Deferred deferred = 3;
|
||||
}
|
||||
}
|
||||
|
||||
service Provisioner {
|
||||
rpc GetSchema(GetProvisionerSchema.Request) returns (GetProvisionerSchema.Response);
|
||||
rpc ValidateProvisionerConfig(ValidateProvisionerConfig.Request) returns (ValidateProvisionerConfig.Response);
|
||||
rpc ProvisionResource(ProvisionResource.Request) returns (stream ProvisionResource.Response);
|
||||
rpc Stop(Stop.Request) returns (Stop.Response);
|
||||
}
|
||||
|
||||
message GetProvisionerSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provisioner = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProvisionerConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ProvisionResource {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
DynamicValue connection = 2;
|
||||
}
|
||||
message Response {
|
||||
string output = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message OpenEphemeralResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
ClientCapabilities client_capabilities = 3;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
optional google.protobuf.Timestamp renew_at = 2;
|
||||
DynamicValue result = 3;
|
||||
optional bytes private = 4;
|
||||
Deferred deferred = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message RenewEphemeralResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
optional bytes private = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
optional google.protobuf.Timestamp renew_at = 2;
|
||||
optional bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message CloseEphemeralResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
optional bytes private = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message GetFunctions {
|
||||
message Request {}
|
||||
|
||||
message Response {
|
||||
// functions is a mapping of function names to definitions.
|
||||
map<string, Function> functions = 1;
|
||||
|
||||
// diagnostics is any warnings or errors.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message CallFunction {
|
||||
message Request {
|
||||
string name = 1;
|
||||
repeated DynamicValue arguments = 2;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue result = 1;
|
||||
FunctionError error = 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,321 +0,0 @@
|
|||
// Terraform Plugin RPC protocol version 6.0
|
||||
//
|
||||
// This file defines version 6.0 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// This file will not be updated. Any minor versions of protocol 6 to follow
|
||||
// should copy this file and modify the copy while maintaing backwards
|
||||
// compatibility. Breaking changes, if any are required, will come
|
||||
// in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/hashicorp/terraform/internal/tfplugin6";
|
||||
|
||||
package tfplugin6;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message StopProvider {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
enum StringKind {
|
||||
PLAIN = 0;
|
||||
MARKDOWN = 1;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource or Provider.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
string description = 4;
|
||||
StringKind description_kind = 5;
|
||||
bool deprecated = 6;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
Object nested_type = 10;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
StringKind description_kind = 8;
|
||||
bool deprecated = 9;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
message Object {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
}
|
||||
|
||||
repeated Attribute attributes = 1;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
rpc GetProviderSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc ValidateProviderConfig(ValidateProviderConfig.Request) returns (ValidateProviderConfig.Response);
|
||||
rpc ValidateResourceConfig(ValidateResourceConfig.Request) returns (ValidateResourceConfig.Response);
|
||||
rpc ValidateDataResourceConfig(ValidateDataResourceConfig.Request) returns (ValidateDataResourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc ConfigureProvider(ConfigureProvider.Request) returns (ConfigureProvider.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc StopProvider(StopProvider.Request) returns (StopProvider.Response);
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
Schema provider_meta = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ConfigureProvider {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
DynamicValue provider_meta = 4;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
DynamicValue provider_meta = 3;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,324 +0,0 @@
|
|||
// Terraform Plugin RPC protocol version 6.1
|
||||
//
|
||||
// This file defines version 6.1 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// This file will not be updated. Any minor versions of protocol 6 to follow
|
||||
// should copy this file and modify the copy while maintaing backwards
|
||||
// compatibility. Breaking changes, if any are required, will come
|
||||
// in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/hashicorp/terraform/internal/tfplugin6";
|
||||
|
||||
package tfplugin6;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message StopProvider {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
enum StringKind {
|
||||
PLAIN = 0;
|
||||
MARKDOWN = 1;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource or Provider.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
string description = 4;
|
||||
StringKind description_kind = 5;
|
||||
bool deprecated = 6;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
Object nested_type = 10;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
StringKind description_kind = 8;
|
||||
bool deprecated = 9;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
message Object {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
}
|
||||
|
||||
repeated Attribute attributes = 1;
|
||||
NestingMode nesting = 3;
|
||||
|
||||
// MinItems and MaxItems were never used in the protocol, and have no
|
||||
// effect on validation.
|
||||
int64 min_items = 4 [deprecated = true];
|
||||
int64 max_items = 5 [deprecated = true];
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
rpc GetProviderSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc ValidateProviderConfig(ValidateProviderConfig.Request) returns (ValidateProviderConfig.Response);
|
||||
rpc ValidateResourceConfig(ValidateResourceConfig.Request) returns (ValidateResourceConfig.Response);
|
||||
rpc ValidateDataResourceConfig(ValidateDataResourceConfig.Request) returns (ValidateDataResourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc ConfigureProvider(ConfigureProvider.Request) returns (ConfigureProvider.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc StopProvider(StopProvider.Request) returns (StopProvider.Response);
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
Schema provider_meta = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ConfigureProvider {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
DynamicValue provider_meta = 4;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
DynamicValue provider_meta = 3;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,350 +0,0 @@
|
|||
// Terraform Plugin RPC protocol version 6.2
|
||||
//
|
||||
// This file defines version 6.2 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// This file will not be updated. Any minor versions of protocol 6 to follow
|
||||
// should copy this file and modify the copy while maintaing backwards
|
||||
// compatibility. Breaking changes, if any are required, will come
|
||||
// in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/hashicorp/terraform/internal/tfplugin6";
|
||||
|
||||
package tfplugin6;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message StopProvider {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
enum StringKind {
|
||||
PLAIN = 0;
|
||||
MARKDOWN = 1;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource or Provider.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
string description = 4;
|
||||
StringKind description_kind = 5;
|
||||
bool deprecated = 6;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
Object nested_type = 10;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
StringKind description_kind = 8;
|
||||
bool deprecated = 9;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
message Object {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
}
|
||||
|
||||
repeated Attribute attributes = 1;
|
||||
NestingMode nesting = 3;
|
||||
|
||||
// MinItems and MaxItems were never used in the protocol, and have no
|
||||
// effect on validation.
|
||||
int64 min_items = 4 [deprecated = true];
|
||||
int64 max_items = 5 [deprecated = true];
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
rpc GetProviderSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc ValidateProviderConfig(ValidateProviderConfig.Request) returns (ValidateProviderConfig.Response);
|
||||
rpc ValidateResourceConfig(ValidateResourceConfig.Request) returns (ValidateResourceConfig.Response);
|
||||
rpc ValidateDataResourceConfig(ValidateDataResourceConfig.Request) returns (ValidateDataResourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc ConfigureProvider(ConfigureProvider.Request) returns (ConfigureProvider.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc StopProvider(StopProvider.Request) returns (StopProvider.Response);
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
Schema provider_meta = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ConfigureProvider {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
DynamicValue provider_meta = 4;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
DynamicValue provider_meta = 3;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,362 +0,0 @@
|
|||
// Terraform Plugin RPC protocol version 6.3
|
||||
//
|
||||
// This file defines version 6.3 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// This file will not be updated. Any minor versions of protocol 6 to follow
|
||||
// should copy this file and modify the copy while maintaing backwards
|
||||
// compatibility. Breaking changes, if any are required, will come
|
||||
// in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/hashicorp/terraform/internal/tfplugin6";
|
||||
|
||||
package tfplugin6;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message StopProvider {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
enum StringKind {
|
||||
PLAIN = 0;
|
||||
MARKDOWN = 1;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource or Provider.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
string description = 4;
|
||||
StringKind description_kind = 5;
|
||||
bool deprecated = 6;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
Object nested_type = 10;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
StringKind description_kind = 8;
|
||||
bool deprecated = 9;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
message Object {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
}
|
||||
|
||||
repeated Attribute attributes = 1;
|
||||
NestingMode nesting = 3;
|
||||
|
||||
// MinItems and MaxItems were never used in the protocol, and have no
|
||||
// effect on validation.
|
||||
int64 min_items = 4 [deprecated = true];
|
||||
int64 max_items = 5 [deprecated = true];
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
rpc GetProviderSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc ValidateProviderConfig(ValidateProviderConfig.Request) returns (ValidateProviderConfig.Response);
|
||||
rpc ValidateResourceConfig(ValidateResourceConfig.Request) returns (ValidateResourceConfig.Response);
|
||||
rpc ValidateDataResourceConfig(ValidateDataResourceConfig.Request) returns (ValidateDataResourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc ConfigureProvider(ConfigureProvider.Request) returns (ConfigureProvider.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc StopProvider(StopProvider.Request) returns (StopProvider.Response);
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
Schema provider_meta = 5;
|
||||
ServerCapabilities server_capabilities = 6;
|
||||
}
|
||||
|
||||
|
||||
// ServerCapabilities allows providers to communicate extra information
|
||||
// regarding supported protocol features. This is used to indicate
|
||||
// availability of certain forward-compatible changes which may be optional
|
||||
// in a major protocol version, but cannot be tested for directly.
|
||||
message ServerCapabilities {
|
||||
// The plan_destroy capability signals that a provider expects a call
|
||||
// to PlanResourceChange when a resource is going to be destroyed.
|
||||
bool plan_destroy = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ConfigureProvider {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
DynamicValue provider_meta = 4;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
DynamicValue provider_meta = 3;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
793
docs/plugin-protocol/tfplugin6.proto
Normal file
793
docs/plugin-protocol/tfplugin6.proto
Normal file
|
|
@ -0,0 +1,793 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
// Terraform Plugin RPC protocol version 6.9
|
||||
//
|
||||
// This file defines version 6.9 of the RPC protocol. To implement a plugin
|
||||
// against this protocol, copy this definition into your own codebase and
|
||||
// use protoc to generate stubs for your target language.
|
||||
//
|
||||
// Any minor versions of protocol 6 to follow should modify this file while
|
||||
// maintaining backwards compatibility. Breaking changes, if any are required,
|
||||
// will come in a subsequent major version with its own separate proto definition.
|
||||
//
|
||||
// Note that only the proto files included in a release tag of Terraform are
|
||||
// official protocol releases. Proto files taken from other commits may include
|
||||
// incomplete changes or features that did not make it into a final release.
|
||||
// In all reasonable cases, plugin developers should take the proto file from
|
||||
// the tag of the most recent release of Terraform, and not from the main
|
||||
// branch or any other development branch.
|
||||
//
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/hashicorp/terraform/internal/tfplugin6";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
package tfplugin6;
|
||||
|
||||
// DynamicValue is an opaque encoding of terraform data, with the field name
|
||||
// indicating the encoding scheme used.
|
||||
message DynamicValue {
|
||||
bytes msgpack = 1;
|
||||
bytes json = 2;
|
||||
}
|
||||
|
||||
message Diagnostic {
|
||||
enum Severity {
|
||||
INVALID = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
}
|
||||
Severity severity = 1;
|
||||
string summary = 2;
|
||||
string detail = 3;
|
||||
AttributePath attribute = 4;
|
||||
}
|
||||
|
||||
message FunctionError {
|
||||
string text = 1;
|
||||
// The optional function_argument records the index position of the
|
||||
// argument which caused the error.
|
||||
optional int64 function_argument = 2;
|
||||
}
|
||||
|
||||
message AttributePath {
|
||||
message Step {
|
||||
oneof selector {
|
||||
// Set "attribute_name" to represent looking up an attribute
|
||||
// in the current object value.
|
||||
string attribute_name = 1;
|
||||
// Set "element_key_*" to represent looking up an element in
|
||||
// an indexable collection type.
|
||||
string element_key_string = 2;
|
||||
int64 element_key_int = 3;
|
||||
}
|
||||
}
|
||||
repeated Step steps = 1;
|
||||
}
|
||||
|
||||
message StopProvider {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
string Error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// RawState holds the stored state for a resource to be upgraded by the
|
||||
// provider. It can be in one of two formats, the current json encoded format
|
||||
// in bytes, or the legacy flatmap format as a map of strings.
|
||||
message RawState {
|
||||
bytes json = 1;
|
||||
map<string, string> flatmap = 2;
|
||||
}
|
||||
|
||||
enum StringKind {
|
||||
PLAIN = 0;
|
||||
MARKDOWN = 1;
|
||||
}
|
||||
|
||||
// ResourceIdentitySchema represents the structure and types of data used to identify
|
||||
// a managed resource type. Effectively, resource identity is a versioned object
|
||||
// that can be used to compare resources, whether already managed and/or being
|
||||
// discovered.
|
||||
message ResourceIdentitySchema {
|
||||
// IdentityAttribute represents one value of data within resource identity. These
|
||||
// are always used in resource identity comparisons.
|
||||
message IdentityAttribute {
|
||||
// name is the identity attribute name
|
||||
string name = 1;
|
||||
|
||||
// type is the identity attribute type
|
||||
bytes type = 2;
|
||||
|
||||
// required_for_import when enabled signifies that this attribute must be
|
||||
// defined for ImportResourceState to complete successfully
|
||||
bool required_for_import = 3;
|
||||
|
||||
// optional_for_import when enabled signifies that this attribute is not
|
||||
// required for ImportResourceState, because it can be supplied by the
|
||||
// provider. It is still possible to supply this attribute during import.
|
||||
bool optional_for_import = 4;
|
||||
|
||||
// description is a human-readable description of the attribute in Markdown
|
||||
string description = 5;
|
||||
}
|
||||
|
||||
// version is the identity version and separate from the Schema version.
|
||||
// Any time the structure or format of identity_attributes changes, this version
|
||||
// should be incremented. Versioning implicitly starts at 0 and by convention
|
||||
// should be incremented by 1 each change.
|
||||
//
|
||||
// When comparing identity_attributes data, differing versions should always be treated
|
||||
// as inequal.
|
||||
int64 version = 1;
|
||||
|
||||
// identity_attributes are the individual value definitions which define identity data
|
||||
// for a managed resource type. This information is used to decode DynamicValue of
|
||||
// identity data.
|
||||
//
|
||||
// These attributes are intended for permanent identity data and must be wholly
|
||||
// representative of all data necessary to compare two managed resource instances
|
||||
// with no other data. This generally should include account, endpoint, location,
|
||||
// and automatically generated identifiers. For some resources, this may include
|
||||
// configuration-based data, such as a required name which must be unique.
|
||||
repeated IdentityAttribute identity_attributes = 2;
|
||||
}
|
||||
|
||||
message ResourceIdentityData {
|
||||
// identity_data is the resource identity data for the given definition. It should
|
||||
// be decoded using the identity schema.
|
||||
//
|
||||
// This data is considered permanent for the identity version and suitable for
|
||||
// longer-term storage.
|
||||
DynamicValue identity_data = 1;
|
||||
}
|
||||
|
||||
// Schema is the configuration schema for a Resource or Provider.
|
||||
message Schema {
|
||||
message Block {
|
||||
int64 version = 1;
|
||||
repeated Attribute attributes = 2;
|
||||
repeated NestedBlock block_types = 3;
|
||||
string description = 4;
|
||||
StringKind description_kind = 5;
|
||||
bool deprecated = 6;
|
||||
}
|
||||
|
||||
message Attribute {
|
||||
string name = 1;
|
||||
bytes type = 2;
|
||||
Object nested_type = 10;
|
||||
string description = 3;
|
||||
bool required = 4;
|
||||
bool optional = 5;
|
||||
bool computed = 6;
|
||||
bool sensitive = 7;
|
||||
StringKind description_kind = 8;
|
||||
bool deprecated = 9;
|
||||
bool write_only = 11;
|
||||
}
|
||||
|
||||
message NestedBlock {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
GROUP = 5;
|
||||
}
|
||||
|
||||
string type_name = 1;
|
||||
Block block = 2;
|
||||
NestingMode nesting = 3;
|
||||
int64 min_items = 4;
|
||||
int64 max_items = 5;
|
||||
}
|
||||
|
||||
message Object {
|
||||
enum NestingMode {
|
||||
INVALID = 0;
|
||||
SINGLE = 1;
|
||||
LIST = 2;
|
||||
SET = 3;
|
||||
MAP = 4;
|
||||
}
|
||||
|
||||
repeated Attribute attributes = 1;
|
||||
NestingMode nesting = 3;
|
||||
|
||||
// MinItems and MaxItems were never used in the protocol, and have no
|
||||
// effect on validation.
|
||||
int64 min_items = 4 [deprecated = true];
|
||||
int64 max_items = 5 [deprecated = true];
|
||||
}
|
||||
|
||||
// The version of the schema.
|
||||
// Schemas are versioned, so that providers can upgrade a saved resource
|
||||
// state when the schema is changed.
|
||||
int64 version = 1;
|
||||
|
||||
// Block is the top level configuration block for this schema.
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
message Function {
|
||||
// parameters is the ordered list of positional function parameters.
|
||||
repeated Parameter parameters = 1;
|
||||
|
||||
// variadic_parameter is an optional final parameter which accepts
|
||||
// zero or more argument values, in which Terraform will send an
|
||||
// ordered list of the parameter type.
|
||||
Parameter variadic_parameter = 2;
|
||||
|
||||
// Return is the function return parameter.
|
||||
Return return = 3;
|
||||
|
||||
// summary is the human-readable shortened documentation for the function.
|
||||
string summary = 4;
|
||||
|
||||
// description is human-readable documentation for the function.
|
||||
string description = 5;
|
||||
|
||||
// description_kind is the formatting of the description.
|
||||
StringKind description_kind = 6;
|
||||
|
||||
// deprecation_message is human-readable documentation if the
|
||||
// function is deprecated.
|
||||
string deprecation_message = 7;
|
||||
|
||||
message Parameter {
|
||||
// name is the human-readable display name for the parameter.
|
||||
string name = 1;
|
||||
|
||||
// type is the type constraint for the parameter.
|
||||
bytes type = 2;
|
||||
|
||||
// allow_null_value when enabled denotes that a null argument value can
|
||||
// be passed to the provider. When disabled, Terraform returns an error
|
||||
// if the argument value is null.
|
||||
bool allow_null_value = 3;
|
||||
|
||||
// allow_unknown_values when enabled denotes that only wholly known
|
||||
// argument values will be passed to the provider. When disabled,
|
||||
// Terraform skips the function call entirely and assumes an unknown
|
||||
// value result from the function.
|
||||
bool allow_unknown_values = 4;
|
||||
|
||||
// description is human-readable documentation for the parameter.
|
||||
string description = 5;
|
||||
|
||||
// description_kind is the formatting of the description.
|
||||
StringKind description_kind = 6;
|
||||
}
|
||||
|
||||
message Return {
|
||||
// type is the type constraint for the function result.
|
||||
bytes type = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ServerCapabilities allows providers to communicate extra information
|
||||
// regarding supported protocol features. This is used to indicate
|
||||
// availability of certain forward-compatible changes which may be optional
|
||||
// in a major protocol version, but cannot be tested for directly.
|
||||
message ServerCapabilities {
|
||||
// The plan_destroy capability signals that a provider expects a call
|
||||
// to PlanResourceChange when a resource is going to be destroyed.
|
||||
bool plan_destroy = 1;
|
||||
|
||||
// The get_provider_schema_optional capability indicates that this
|
||||
// provider does not require calling GetProviderSchema to operate
|
||||
// normally, and the caller can used a cached copy of the provider's
|
||||
// schema.
|
||||
bool get_provider_schema_optional = 2;
|
||||
|
||||
// The move_resource_state capability signals that a provider supports the
|
||||
// MoveResourceState RPC.
|
||||
bool move_resource_state = 3;
|
||||
}
|
||||
|
||||
// ClientCapabilities allows Terraform to publish information regarding
|
||||
// supported protocol features. This is used to indicate availability of
|
||||
// certain forward-compatible changes which may be optional in a major
|
||||
// protocol version, but cannot be tested for directly.
|
||||
message ClientCapabilities {
|
||||
// The deferral_allowed capability signals that the client is able to
|
||||
// handle deferred responses from the provider.
|
||||
bool deferral_allowed = 1;
|
||||
|
||||
// The write_only_attributes_allowed capability signals that the client
|
||||
// is able to handle write_only attributes for managed resources.
|
||||
bool write_only_attributes_allowed = 2;
|
||||
}
|
||||
|
||||
// Deferred is a message that indicates that change is deferred for a reason.
|
||||
message Deferred {
|
||||
// Reason is the reason for deferring the change.
|
||||
enum Reason {
|
||||
// UNKNOWN is the default value, and should not be used.
|
||||
UNKNOWN = 0;
|
||||
// RESOURCE_CONFIG_UNKNOWN is used when the config is partially unknown and the real
|
||||
// values need to be known before the change can be planned.
|
||||
RESOURCE_CONFIG_UNKNOWN = 1;
|
||||
// PROVIDER_CONFIG_UNKNOWN is used when parts of the provider configuration
|
||||
// are unknown, e.g. the provider configuration is only known after the apply is done.
|
||||
PROVIDER_CONFIG_UNKNOWN = 2;
|
||||
// ABSENT_PREREQ is used when a hard dependency has not been satisfied.
|
||||
ABSENT_PREREQ = 3;
|
||||
}
|
||||
|
||||
// reason is the reason for deferring the change.
|
||||
Reason reason = 1;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
//////// Information about what a provider supports/expects
|
||||
|
||||
// GetMetadata returns upfront information about server capabilities and
|
||||
// supported resource types without requiring the server to instantiate all
|
||||
// schema information, which may be memory intensive. This RPC is optional,
|
||||
// where clients may receive an unimplemented RPC error. Clients should
|
||||
// ignore the error and call the GetProviderSchema RPC as a fallback.
|
||||
rpc GetMetadata(GetMetadata.Request) returns (GetMetadata.Response);
|
||||
|
||||
// GetSchema returns schema information for the provider, data resources,
|
||||
// and managed resources.
|
||||
rpc GetProviderSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response);
|
||||
rpc ValidateProviderConfig(ValidateProviderConfig.Request) returns (ValidateProviderConfig.Response);
|
||||
rpc ValidateResourceConfig(ValidateResourceConfig.Request) returns (ValidateResourceConfig.Response);
|
||||
rpc ValidateDataResourceConfig(ValidateDataResourceConfig.Request) returns (ValidateDataResourceConfig.Response);
|
||||
rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response);
|
||||
|
||||
// GetResourceIdentitySchemas returns the identity schemas for all managed
|
||||
// resources.
|
||||
rpc GetResourceIdentitySchemas(GetResourceIdentitySchemas.Request) returns (GetResourceIdentitySchemas.Response);
|
||||
// UpgradeResourceIdentityData should return the upgraded resource identity
|
||||
// data for a managed resource type.
|
||||
rpc UpgradeResourceIdentity(UpgradeResourceIdentity.Request) returns (UpgradeResourceIdentity.Response);
|
||||
|
||||
//////// One-time initialization, called before other functions below
|
||||
rpc ConfigureProvider(ConfigureProvider.Request) returns (ConfigureProvider.Response);
|
||||
|
||||
//////// Managed Resource Lifecycle
|
||||
rpc ReadResource(ReadResource.Request) returns (ReadResource.Response);
|
||||
rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response);
|
||||
rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response);
|
||||
rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response);
|
||||
rpc MoveResourceState(MoveResourceState.Request) returns (MoveResourceState.Response);
|
||||
rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response);
|
||||
|
||||
//////// Ephemeral Resource Lifecycle
|
||||
rpc ValidateEphemeralResourceConfig(ValidateEphemeralResourceConfig.Request) returns (ValidateEphemeralResourceConfig.Response);
|
||||
rpc OpenEphemeralResource(OpenEphemeralResource.Request) returns (OpenEphemeralResource.Response);
|
||||
rpc RenewEphemeralResource(RenewEphemeralResource.Request) returns (RenewEphemeralResource.Response);
|
||||
rpc CloseEphemeralResource(CloseEphemeralResource.Request) returns (CloseEphemeralResource.Response);
|
||||
|
||||
// GetFunctions returns the definitions of all functions.
|
||||
rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response);
|
||||
|
||||
//////// Provider-contributed Functions
|
||||
rpc CallFunction(CallFunction.Request) returns (CallFunction.Response);
|
||||
|
||||
//////// Graceful Shutdown
|
||||
rpc StopProvider(StopProvider.Request) returns (StopProvider.Response);
|
||||
}
|
||||
|
||||
message GetMetadata {
|
||||
message Request {
|
||||
}
|
||||
|
||||
message Response {
|
||||
ServerCapabilities server_capabilities = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
repeated DataSourceMetadata data_sources = 3;
|
||||
repeated ResourceMetadata resources = 4;
|
||||
// functions returns metadata for any functions.
|
||||
repeated FunctionMetadata functions = 5;
|
||||
repeated EphemeralMetadata ephemeral_resources = 6;
|
||||
}
|
||||
|
||||
message EphemeralMetadata {
|
||||
string type_name = 1;
|
||||
}
|
||||
|
||||
message FunctionMetadata {
|
||||
// name is the function name.
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message DataSourceMetadata {
|
||||
string type_name = 1;
|
||||
}
|
||||
|
||||
message ResourceMetadata {
|
||||
string type_name = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message GetProviderSchema {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Schema provider = 1;
|
||||
map<string, Schema> resource_schemas = 2;
|
||||
map<string, Schema> data_source_schemas = 3;
|
||||
map<string, Function> functions = 7;
|
||||
map<string, Schema> ephemeral_resource_schemas = 8;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
Schema provider_meta = 5;
|
||||
ServerCapabilities server_capabilities = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateProviderConfig {
|
||||
message Request {
|
||||
DynamicValue config = 1;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceState {
|
||||
// Request is the message that is sent to the provider during the
|
||||
// UpgradeResourceState RPC.
|
||||
//
|
||||
// This message intentionally does not include configuration data as any
|
||||
// configuration-based or configuration-conditional changes should occur
|
||||
// during the PlanResourceChange RPC. Additionally, the configuration is
|
||||
// not guaranteed to exist (in the case of resource destruction), be wholly
|
||||
// known, nor match the given prior state, which could lead to unexpected
|
||||
// provider behaviors for practitioners.
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
|
||||
// version is the schema_version number recorded in the state file
|
||||
int64 version = 2;
|
||||
|
||||
// raw_state is the raw states as stored for the resource. Core does
|
||||
// not have access to the schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_state will be the json encoded
|
||||
// state, or a legacy flat-mapped format.
|
||||
RawState raw_state = 3;
|
||||
}
|
||||
message Response {
|
||||
// new_state is a msgpack-encoded data structure that, when interpreted with
|
||||
// the _current_ schema for this resource type, is functionally equivalent to
|
||||
// that which was given in prior_state_raw.
|
||||
DynamicValue upgraded_state = 1;
|
||||
|
||||
// diagnostics describes any errors encountered during migration that could not
|
||||
// be safely resolved, and warnings about any possibly-risky assumptions made
|
||||
// in the upgrade process.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message GetResourceIdentitySchemas {
|
||||
message Request {
|
||||
}
|
||||
|
||||
message Response {
|
||||
// identity_schemas is a mapping of resource type names to their identity schemas.
|
||||
map<string, ResourceIdentitySchema> identity_schemas = 1;
|
||||
|
||||
// diagnostics is the collection of warning and error diagnostics for this request.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message UpgradeResourceIdentity {
|
||||
message Request {
|
||||
// type_name is the managed resource type name
|
||||
string type_name = 1;
|
||||
|
||||
// version is the version of the resource identity data to upgrade
|
||||
int64 version = 2;
|
||||
|
||||
// raw_identity is the raw identity as stored for the resource. Core does
|
||||
// not have access to the identity schema of prior_version, so it's the
|
||||
// provider's responsibility to interpret this value using the
|
||||
// appropriate older schema. The raw_identity will be json encoded.
|
||||
RawState raw_identity = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
// upgraded_identity returns the upgraded resource identity data
|
||||
ResourceIdentityData upgraded_identity = 1;
|
||||
|
||||
// diagnostics is the collection of warning and error diagnostics for this request
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
ClientCapabilities client_capabilities = 3;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateDataResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidateEphemeralResourceConfig {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ConfigureProvider {
|
||||
message Request {
|
||||
string terraform_version = 1;
|
||||
DynamicValue config = 2;
|
||||
ClientCapabilities client_capabilities = 3;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadResource {
|
||||
// Request is the message that is sent to the provider during the
|
||||
// ReadResource RPC.
|
||||
//
|
||||
// This message intentionally does not include configuration data as any
|
||||
// configuration-based or configuration-conditional changes should occur
|
||||
// during the PlanResourceChange RPC. Additionally, the configuration is
|
||||
// not guaranteed to be wholly known nor match the given prior state, which
|
||||
// could lead to unexpected provider behaviors for practitioners.
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue current_state = 2;
|
||||
bytes private = 3;
|
||||
DynamicValue provider_meta = 4;
|
||||
ClientCapabilities client_capabilities = 5;
|
||||
ResourceIdentityData current_identity = 6;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
bytes private = 3;
|
||||
// deferred is set if the provider is deferring the change. If set the caller
|
||||
// needs to handle the deferral.
|
||||
Deferred deferred = 4;
|
||||
ResourceIdentityData new_identity = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message PlanResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue proposed_new_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes prior_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
ClientCapabilities client_capabilities = 7;
|
||||
ResourceIdentityData prior_identity = 8;
|
||||
}
|
||||
|
||||
message Response {
|
||||
DynamicValue planned_state = 1;
|
||||
repeated AttributePath requires_replace = 2;
|
||||
bytes planned_private = 3;
|
||||
repeated Diagnostic diagnostics = 4;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 5;
|
||||
|
||||
// deferred is set if the provider is deferring the change. If set the caller
|
||||
// needs to handle the deferral.
|
||||
Deferred deferred = 6;
|
||||
|
||||
ResourceIdentityData planned_identity = 7;
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyResourceChange {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue prior_state = 2;
|
||||
DynamicValue planned_state = 3;
|
||||
DynamicValue config = 4;
|
||||
bytes planned_private = 5;
|
||||
DynamicValue provider_meta = 6;
|
||||
ResourceIdentityData planned_identity = 7;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue new_state = 1;
|
||||
bytes private = 2;
|
||||
repeated Diagnostic diagnostics = 3;
|
||||
|
||||
// This may be set only by the helper/schema "SDK" in the main Terraform
|
||||
// repository, to request that Terraform Core >=0.12 permit additional
|
||||
// inconsistencies that can result from the legacy SDK type system
|
||||
// and its imprecise mapping to the >=0.12 type system.
|
||||
// The change in behavior implied by this flag makes sense only for the
|
||||
// specific details of the legacy SDK type system, and are not a general
|
||||
// mechanism to avoid proper type handling in providers.
|
||||
//
|
||||
// ==== DO NOT USE THIS ====
|
||||
// ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ====
|
||||
// ==== DO NOT USE THIS ====
|
||||
bool legacy_type_system = 4;
|
||||
|
||||
ResourceIdentityData new_identity = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message ImportResourceState {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
string id = 2;
|
||||
ClientCapabilities client_capabilities = 3;
|
||||
ResourceIdentityData identity = 4;
|
||||
}
|
||||
|
||||
message ImportedResource {
|
||||
string type_name = 1;
|
||||
DynamicValue state = 2;
|
||||
bytes private = 3;
|
||||
ResourceIdentityData identity = 4;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated ImportedResource imported_resources = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
// deferred is set if the provider is deferring the change. If set the caller
|
||||
// needs to handle the deferral.
|
||||
Deferred deferred = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message MoveResourceState {
|
||||
message Request {
|
||||
// The address of the provider the resource is being moved from.
|
||||
string source_provider_address = 1;
|
||||
|
||||
// The resource type that the resource is being moved from.
|
||||
string source_type_name = 2;
|
||||
|
||||
// The schema version of the resource type that the resource is being
|
||||
// moved from.
|
||||
int64 source_schema_version = 3;
|
||||
|
||||
// The raw state of the resource being moved. Only the json field is
|
||||
// populated, as there should be no legacy providers using the flatmap
|
||||
// format that support newly introduced RPCs.
|
||||
RawState source_state = 4;
|
||||
|
||||
// The resource type that the resource is being moved to.
|
||||
string target_type_name = 5;
|
||||
|
||||
// The private state of the resource being moved.
|
||||
bytes source_private = 6;
|
||||
|
||||
// The raw identity of the resource being moved. Only the json field is
|
||||
// populated, as there should be no legacy providers using the flatmap
|
||||
// format that support newly introduced RPCs.
|
||||
RawState source_identity = 7;
|
||||
|
||||
// The identity schema version of the resource type that the resource
|
||||
// is being moved from.
|
||||
int64 source_identity_schema_version = 8;
|
||||
}
|
||||
|
||||
message Response {
|
||||
// The state of the resource after it has been moved.
|
||||
DynamicValue target_state = 1;
|
||||
|
||||
// Any diagnostics that occurred during the move.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
|
||||
// The private state of the resource after it has been moved.
|
||||
bytes target_private = 3;
|
||||
|
||||
ResourceIdentityData target_identity = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message ReadDataSource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
DynamicValue provider_meta = 3;
|
||||
ClientCapabilities client_capabilities = 4;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue state = 1;
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
// deferred is set if the provider is deferring the change. If set the caller
|
||||
// needs to handle the deferral.
|
||||
Deferred deferred = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message OpenEphemeralResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
DynamicValue config = 2;
|
||||
ClientCapabilities client_capabilities = 3;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
optional google.protobuf.Timestamp renew_at = 2;
|
||||
DynamicValue result = 3;
|
||||
optional bytes private = 4;
|
||||
Deferred deferred = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message RenewEphemeralResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
optional bytes private = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
optional google.protobuf.Timestamp renew_at = 2;
|
||||
optional bytes private = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message CloseEphemeralResource {
|
||||
message Request {
|
||||
string type_name = 1;
|
||||
optional bytes private = 2;
|
||||
}
|
||||
message Response {
|
||||
repeated Diagnostic diagnostics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message GetFunctions {
|
||||
message Request {}
|
||||
|
||||
message Response {
|
||||
// functions is a mapping of function names to definitions.
|
||||
map<string, Function> functions = 1;
|
||||
|
||||
// diagnostics is any warnings or errors.
|
||||
repeated Diagnostic diagnostics = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message CallFunction {
|
||||
message Request {
|
||||
string name = 1;
|
||||
repeated DynamicValue arguments = 2;
|
||||
}
|
||||
message Response {
|
||||
DynamicValue result = 1;
|
||||
FunctionError error = 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -33,9 +33,11 @@ The various object values used in different parts of this process are:
|
|||
which a provider may use as a starting point for its planning operation.
|
||||
|
||||
The built-in logic primarily deals with the expected behavior for attributes
|
||||
marked in the schema as both "optional" _and_ "computed", which means that
|
||||
the user may either set it or may leave it unset to allow the provider
|
||||
to choose a value instead.
|
||||
marked in the schema as "computed". If an attribute is only "computed",
|
||||
Terraform expects the value to only be chosen by the provider and it will
|
||||
preserve any Prior State. If an attribute is marked as "computed" and
|
||||
"optional", this means that the user may either set it or may leave it
|
||||
unset to allow the provider to choose a value.
|
||||
|
||||
Terraform Core therefore constructs the proposed new state by taking the
|
||||
attribute value from Configuration if it is non-null, and then using the
|
||||
|
|
@ -245,6 +247,8 @@ information as the **Previous Run State** but does so in a way that conforms
|
|||
to the current version of the resource type schema, which therefore allows
|
||||
Terraform Core to interact with the data fully for subsequent steps.
|
||||
|
||||
No unknown values are permitted in the **Updated State**.
|
||||
|
||||
### ReadResource
|
||||
|
||||
Although Terraform typically expects to have exclusive control over any remote
|
||||
|
|
@ -287,7 +291,7 @@ following two situations for each attribute:
|
|||
|
||||
This operation returns the **Prior State** to use for the next call to
|
||||
`PlanResourceChange`, thus completing the circle and beginning this process
|
||||
over again.
|
||||
over again. No unknown values are permitted in the **Prior State**.
|
||||
|
||||
## Handling of Nested Blocks in Configuration
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,31 @@ The other subsystems described below should always be set up to match
|
|||
themselves with `unicode.Version` and generate an error if they cannot, but
|
||||
that isn't true of all of them.
|
||||
|
||||
## Unicode Identifier Rules in HCL
|
||||
|
||||
_Identifier and Pattern Syntax_ (TF31) is a Unicode standards annex which
|
||||
describe a set of rules for tokenizing "identifiers", such as variable names
|
||||
in a programming language.
|
||||
|
||||
HCL uses a superset of that specification for its own identifier tokenization
|
||||
rules, and so it includes some code derived from the TF31 data tables that
|
||||
describe which characters belong to the "ID_Start" and "ID_Continue" classes.
|
||||
|
||||
Since Terraform is the primary user of HCL, it's typically Terraform's adoption
|
||||
of a new Unicode version which drives HCL to adopt one. To update the Unicode
|
||||
tables to a new version:
|
||||
* Edit `hclsyntax/generate.go`'s line which runs `unicode2ragel.rb` to specify
|
||||
the URL of the `DerivedCoreProperties.txt` data file for the intended Unicode
|
||||
version.
|
||||
* Run `go generate ./hclsyntax` to run the generation code to update both
|
||||
`unicode_derived.rl` and, indirectly, `scan_tokens.go`. (You will need both
|
||||
a Ruby interpreter and the Ragel state machine compiler on your system in
|
||||
order to complete this step.)
|
||||
* Run all the tests to check for regressions: `go test ./...`
|
||||
* If all looks good, commit all of the changes and open a PR to HCL.
|
||||
* Once that PR is merged and released, update Terraform to use the new version
|
||||
of HCL.
|
||||
|
||||
## Unicode Text Segmentation
|
||||
|
||||
_Text Segmentation_ (TR29) is a Unicode standards annex which describes
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package main
|
||||
|
||||
// experimentsAllowed can be set to any non-empty string using Go linker
|
||||
|
|
|
|||
404
go.mod
404
go.mod
|
|
@ -1,195 +1,337 @@
|
|||
module github.com/hashicorp/terraform
|
||||
|
||||
go 1.24.2
|
||||
|
||||
godebug winsymlink=0
|
||||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.10.0
|
||||
github.com/Azure/azure-sdk-for-go v59.2.0+incompatible
|
||||
github.com/Azure/go-autorest/autorest v0.11.24
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2
|
||||
github.com/ProtonMail/go-crypto v1.1.3
|
||||
github.com/agext/levenshtein v1.2.3
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1501
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190103054945-8205d1f41e70
|
||||
github.com/aliyun/aliyun-tablestore-go-sdk v4.1.2+incompatible
|
||||
github.com/apparentlymart/go-cidr v1.1.0
|
||||
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0
|
||||
github.com/apparentlymart/go-shquot v0.0.1
|
||||
github.com/apparentlymart/go-userdirs v0.0.0-20200915174352-b0c018a67c13
|
||||
github.com/apparentlymart/go-versions v1.0.1
|
||||
github.com/apparentlymart/go-versions v1.0.2
|
||||
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
|
||||
github.com/aws/aws-sdk-go v1.42.35
|
||||
github.com/bgentry/speakeasy v0.1.0
|
||||
github.com/bmatcuk/doublestar v1.1.5
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/dylanmei/winrmtest v0.0.0-20210303004826-fbc9ae56efb6
|
||||
github.com/go-test/deep v1.0.3
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-cmp v0.5.8
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/gophercloud/gophercloud v0.10.1-0.20200424014253-c3bfe50899e5
|
||||
github.com/gophercloud/utils v0.0.0-20200423144003-7c72efc7435d
|
||||
github.com/hashicorp/aws-sdk-go-base v0.7.1
|
||||
github.com/hashicorp/consul/api v1.9.1
|
||||
github.com/hashicorp/consul/sdk v0.8.0
|
||||
github.com/hashicorp/errwrap v1.1.0
|
||||
github.com/hashicorp/go-azure-helpers v0.31.1
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/hashicorp/cli v1.1.7
|
||||
github.com/hashicorp/go-checkpoint v0.5.0
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2
|
||||
github.com/hashicorp/go-getter v1.6.2
|
||||
github.com/hashicorp/go-hclog v0.15.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/go-plugin v1.4.3
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1
|
||||
github.com/hashicorp/go-tfe v1.7.0
|
||||
github.com/hashicorp/go-getter v1.7.8
|
||||
github.com/hashicorp/go-hclog v1.6.3
|
||||
github.com/hashicorp/go-plugin v1.6.3
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7
|
||||
github.com/hashicorp/go-slug v0.16.3
|
||||
github.com/hashicorp/go-tfe v1.74.1
|
||||
github.com/hashicorp/go-uuid v1.0.3
|
||||
github.com/hashicorp/go-version v1.6.0
|
||||
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f
|
||||
github.com/hashicorp/hcl/v2 v2.13.0
|
||||
github.com/hashicorp/terraform-config-inspect v0.0.0-20210209133302-4fd17a0faac2
|
||||
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c
|
||||
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734
|
||||
github.com/jmespath/go-jmespath v0.4.0
|
||||
github.com/joyent/triton-go v0.0.0-20180313100802-d8f9c0314926
|
||||
github.com/hashicorp/go-version v1.7.0
|
||||
github.com/hashicorp/hcl v1.0.0
|
||||
github.com/hashicorp/hcl/v2 v2.23.1-0.20250203194505-ba0759438da2
|
||||
github.com/hashicorp/jsonapi v1.3.2
|
||||
github.com/hashicorp/terraform-registry-address v0.2.4
|
||||
github.com/hashicorp/terraform-svchost v0.1.1
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/azure v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/consul v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/cos v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/gcs v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/kubernetes v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/oci v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/oss v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/pg v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/backend/remote-state/s3 v0.0.0-00010101000000-000000000000
|
||||
github.com/hashicorp/terraform/internal/legacy v0.0.0-00010101000000-000000000000
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
|
||||
github.com/lib/pq v1.10.3
|
||||
github.com/lusis/go-artifactory v0.0.0-20160115162124-7e4ce345df82
|
||||
github.com/manicminer/hamilton v0.44.0
|
||||
github.com/masterzen/winrm v0.0.0-20200615185753-c42b5136ff88
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/mattn/go-shellwords v1.0.4
|
||||
github.com/mitchellh/cli v1.1.4
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db
|
||||
github.com/mitchellh/copystructure v1.2.0
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/go-linereader v0.0.0-20190213213312-1b945b3263eb
|
||||
github.com/mitchellh/go-wordwrap v1.0.1
|
||||
github.com/mitchellh/gox v1.0.1
|
||||
github.com/mitchellh/mapstructure v1.1.2
|
||||
github.com/mitchellh/reflectwalk v1.0.2
|
||||
github.com/nishanths/exhaustive v0.7.11
|
||||
github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db
|
||||
github.com/pkg/browser v0.0.0-20201207095918-0426ae3fba23
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/nishanths/exhaustive v0.12.0
|
||||
github.com/packer-community/winrmcp v0.0.0-20221126162354-6e900dd2c68f
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||
github.com/posener/complete v1.2.3
|
||||
github.com/spf13/afero v1.2.2
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.232
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.233
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.29
|
||||
github.com/tombuildsstuff/giovanni v0.15.1
|
||||
github.com/xanzy/ssh-agent v0.3.1
|
||||
github.com/spf13/afero v1.9.5
|
||||
github.com/xanzy/ssh-agent v0.3.3
|
||||
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
|
||||
github.com/zclconf/go-cty v1.11.0
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b
|
||||
github.com/zclconf/go-cty-yaml v1.0.2
|
||||
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
||||
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
|
||||
golang.org/x/text v0.3.7
|
||||
golang.org/x/tools v0.1.11
|
||||
google.golang.org/api v0.44.0-impersonate-preview
|
||||
google.golang.org/grpc v1.47.0
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
honnef.co/go/tools v0.3.0
|
||||
k8s.io/api v0.23.4
|
||||
k8s.io/apimachinery v0.23.4
|
||||
k8s.io/client-go v0.23.4
|
||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed
|
||||
github.com/zclconf/go-cty v1.16.2
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940
|
||||
github.com/zclconf/go-cty-yaml v1.1.0
|
||||
go.opentelemetry.io/contrib/exporters/autoexport v0.45.0
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1
|
||||
go.opentelemetry.io/otel v1.34.0
|
||||
go.opentelemetry.io/otel/sdk v1.31.0
|
||||
go.opentelemetry.io/otel/trace v1.34.0
|
||||
go.uber.org/mock v0.4.0
|
||||
golang.org/x/crypto v0.36.0
|
||||
golang.org/x/mod v0.24.0
|
||||
golang.org/x/net v0.38.0
|
||||
golang.org/x/oauth2 v0.27.0
|
||||
golang.org/x/sys v0.31.0
|
||||
golang.org/x/term v0.30.0
|
||||
golang.org/x/text v0.23.0
|
||||
golang.org/x/tools v0.31.0
|
||||
golang.org/x/tools/cmd/cover v0.1.0-deprecated
|
||||
google.golang.org/grpc v1.69.4
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0
|
||||
google.golang.org/protobuf v1.36.5
|
||||
honnef.co/go/tools v0.6.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.81.0 // indirect
|
||||
cloud.google.com/go v0.110.10 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.2 // indirect
|
||||
cloud.google.com/go/iam v1.1.5 // indirect
|
||||
cloud.google.com/go/storage v1.30.1 // indirect
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.4 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.30 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.24 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.1 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.2 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.1 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
||||
github.com/BurntSushi/toml v0.4.1 // indirect
|
||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
|
||||
github.com/ChrisTrenkamp/goxpath v0.0.0-20190607011252-c5096ec8773d // indirect
|
||||
github.com/Masterminds/goutils v1.1.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
||||
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Microsoft/go-winio v0.5.2 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1501 // indirect
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190103054945-8205d1f41e70 // indirect
|
||||
github.com/aliyun/aliyun-tablestore-go-sdk v4.1.2+incompatible // indirect
|
||||
github.com/antchfx/xmlquery v1.3.5 // indirect
|
||||
github.com/antchfx/xpath v1.1.10 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.122 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.57 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.39.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.38.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.75.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.33.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sqs v1.37.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.12 // indirect
|
||||
github.com/aws/smithy-go v1.22.2 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d // indirect
|
||||
github.com/creack/pty v1.1.18 // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.11.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/clbanning/mxj v1.8.4 // indirect
|
||||
github.com/cli/go-gh/v2 v2.11.2 // indirect
|
||||
github.com/cli/safeexec v1.0.1 // indirect
|
||||
github.com/cloudflare/circl v1.4.0 // indirect
|
||||
github.com/creack/pty v1.1.17 // indirect
|
||||
github.com/dylanmei/iso8601 v0.1.0 // indirect
|
||||
github.com/fatih/color v1.9.0 // indirect
|
||||
github.com/go-logr/logr v1.2.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/errors v0.22.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/gofrs/flock v0.10.0 // indirect
|
||||
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/go-github/v45 v45.2.0 // indirect
|
||||
github.com/google/go-github/v62 v62.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
|
||||
github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.62 // indirect
|
||||
github.com/hashicorp/consul/api v1.13.0 // indirect
|
||||
github.com/hashicorp/copywrite v0.20.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-azure-helpers v0.72.0 // indirect
|
||||
github.com/hashicorp/go-azure-sdk/resource-manager v0.20250131.1134653 // indirect
|
||||
github.com/hashicorp/go-azure-sdk/sdk v0.20250131.1134653 // indirect
|
||||
github.com/hashicorp/go-cty v1.4.1 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0 // indirect
|
||||
github.com/hashicorp/go-msgpack v0.5.4 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-slug v0.9.1 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.1 // indirect
|
||||
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d // indirect
|
||||
github.com/hashicorp/serf v0.9.5 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||
github.com/hashicorp/serf v0.9.6 // indirect
|
||||
github.com/hashicorp/terraform-plugin-go v0.26.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.36.1 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackofallops/giovanni v0.28.0 // indirect
|
||||
github.com/jedib0t/go-pretty v4.3.0+incompatible // indirect
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.9 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/jstemmer/go-junit-report v0.9.1 // indirect
|
||||
github.com/klauspost/compress v1.11.2 // indirect
|
||||
github.com/kr/pretty v0.2.1 // indirect
|
||||
github.com/manicminer/hamilton-autorest v0.2.0 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/knadh/koanf v1.5.0 // indirect
|
||||
github.com/lib/pq v1.10.3 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect
|
||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.0.4 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mergestat/timediff v0.0.3 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/iochan v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mozillazg/go-httpheader v0.3.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||
github.com/oklog/run v1.0.0 // indirect
|
||||
github.com/satori/go.uuid v1.2.0 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/oracle/oci-go-sdk/v65 v65.89.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/samber/lo v1.47.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sony/gobreaker v0.5.0 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.1.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.8 // indirect
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
|
||||
github.com/vmihailenco/tagparser v0.1.1 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.588 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.588 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.233 // indirect
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.42 // indirect
|
||||
github.com/thanhpk/randstr v1.0.6 // indirect
|
||||
github.com/ulikunitz/xz v0.5.10 // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
go.mongodb.org/mongo-driver v1.16.1 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.59.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.155.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/klog/v2 v2.30.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
k8s.io/api v0.25.5 // indirect
|
||||
k8s.io/apimachinery v0.25.5 // indirect
|
||||
k8s.io/client-go v0.25.5 // indirect
|
||||
k8s.io/klog/v2 v2.70.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||
software.sslmate.com/src/go-pkcs12 v0.4.0 // indirect
|
||||
)
|
||||
|
||||
go 1.18
|
||||
// Some of the packages in this codebase are split into separate Go modules
|
||||
// just so that we can more easily determine how dependency updates might
|
||||
// affect components with different code ownership. These modules are never
|
||||
// actually published separately from the toplevel module, and so we exclusively
|
||||
// use the "pseudo-revisions" generated by the Go toolchain to describe them
|
||||
// in go.mod files.
|
||||
//
|
||||
// If you change the dependencies of any one of these components, use
|
||||
// "make syncdeps" to resynchronize the others. That will then make sure that
|
||||
// your updates will be visible to the code owners of each affected component.
|
||||
//
|
||||
// In the long run we want to make each of these either move to another codebase
|
||||
// or get deleted entirely, but as long as we keep maintaining this all together
|
||||
// in one codebase this is a pragmatic compromise to help us understand the
|
||||
// impact of and responsibilities for dependency upgrades.
|
||||
//
|
||||
// We don't expect to add any new modules here because the ones that are here
|
||||
// are here just as technical debt. If you _do_ end up adding another one,
|
||||
// you'll need to add similar replace directives to each of the other modules
|
||||
// so that they all agree with each other that we're never publishing any of
|
||||
// these modules as a separate unit. (But please add to this only as a last
|
||||
// resort!)
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/azure => ./internal/backend/remote-state/azure
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/consul => ./internal/backend/remote-state/consul
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/cos => ./internal/backend/remote-state/cos
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/gcs => ./internal/backend/remote-state/gcs
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/kubernetes => ./internal/backend/remote-state/kubernetes
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/oss => ./internal/backend/remote-state/oss
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/pg => ./internal/backend/remote-state/pg
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/s3 => ./internal/backend/remote-state/s3
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/backend/remote-state/oci => ./internal/backend/remote-state/oci
|
||||
|
||||
replace github.com/hashicorp/terraform/internal/legacy => ./internal/legacy
|
||||
|
||||
tool (
|
||||
github.com/hashicorp/copywrite
|
||||
github.com/nishanths/exhaustive/cmd/exhaustive
|
||||
go.uber.org/mock/mockgen
|
||||
golang.org/x/tools/cmd/cover
|
||||
golang.org/x/tools/cmd/goimports
|
||||
golang.org/x/tools/cmd/stringer
|
||||
honnef.co/go/tools/cmd/staticcheck
|
||||
)
|
||||
|
|
|
|||
7
help.go
7
help.go
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
@ -7,7 +10,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/cli"
|
||||
)
|
||||
|
||||
// helpFunc is a cli.HelpFunc that can be used to output the help CLI instructions for Terraform.
|
||||
|
|
@ -57,7 +60,7 @@ All other commands:
|
|||
Global options (use these before the subcommand, if any):
|
||||
-chdir=DIR Switch to a different working directory before executing the
|
||||
given subcommand.
|
||||
-help Show this help output, or the help for a specified subcommand.
|
||||
-help Show this help output or the help for a specified subcommand.
|
||||
-version An alias for the "version" subcommand.
|
||||
`, listCommands(commands, PrimaryCommands, maxKeyLen), listCommands(commands, otherCommands, maxKeyLen))
|
||||
|
||||
|
|
|
|||
329
internal/addrs/action.go
Normal file
329
internal/addrs/action.go
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package addrs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Action is an address for an action block within configuration, which
|
||||
// contains potentially-multiple action instances if that configuration
|
||||
// block uses "count" or "for_each".
|
||||
type Action struct {
|
||||
referenceable
|
||||
Type string
|
||||
Name string
|
||||
}
|
||||
|
||||
func (a Action) String() string {
|
||||
return fmt.Sprintf("action.%s.%s", a.Type, a.Name)
|
||||
}
|
||||
|
||||
func (a Action) Equal(o Action) bool {
|
||||
return a.Name == o.Name && a.Type == o.Type
|
||||
}
|
||||
|
||||
func (a Action) Less(o Action) bool {
|
||||
switch {
|
||||
case a.Type != o.Type:
|
||||
return a.Type < o.Type
|
||||
|
||||
case a.Name != o.Name:
|
||||
return a.Name < o.Name
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (a Action) UniqueKey() UniqueKey {
|
||||
return a // An Action is its own UniqueKey
|
||||
}
|
||||
|
||||
func (a Action) uniqueKeySigil() {}
|
||||
|
||||
// Instance produces the address for a specific instance of the receiver
|
||||
// that is identified by the given key.
|
||||
func (a Action) Instance(key InstanceKey) ActionInstance {
|
||||
return ActionInstance{
|
||||
Action: a,
|
||||
Key: key,
|
||||
}
|
||||
}
|
||||
|
||||
// Absolute returns an AbsAction from the receiver and the given module
|
||||
// instance address.
|
||||
func (a Action) Absolute(module ModuleInstance) AbsAction {
|
||||
return AbsAction{
|
||||
Module: module,
|
||||
Action: a,
|
||||
}
|
||||
}
|
||||
|
||||
// InModule returns a ConfigAction from the receiver and the given module
|
||||
// address.
|
||||
func (a Action) InModule(module Module) ConfigAction {
|
||||
return ConfigAction{
|
||||
Module: module,
|
||||
Action: a,
|
||||
}
|
||||
}
|
||||
|
||||
// ImpliedProvider returns the implied provider type name, for e.g. the "aws" in
|
||||
// "aws_instance"
|
||||
func (a Action) ImpliedProvider() string {
|
||||
typeName := a.Type
|
||||
if under := strings.Index(typeName, "_"); under != -1 {
|
||||
typeName = typeName[:under]
|
||||
}
|
||||
|
||||
return typeName
|
||||
}
|
||||
|
||||
// ActionInstance is an address for a specific instance of an action.
|
||||
// When an action is defined in configuration with "count" or "for_each" it
|
||||
// produces zero or more instances, which can be addressed using this type.
|
||||
type ActionInstance struct {
|
||||
referenceable
|
||||
Action Action
|
||||
Key InstanceKey
|
||||
}
|
||||
|
||||
func (a ActionInstance) ContainingAction() Action {
|
||||
return a.Action
|
||||
}
|
||||
|
||||
func (a ActionInstance) String() string {
|
||||
if a.Key == NoKey {
|
||||
return a.Action.String()
|
||||
}
|
||||
return a.Action.String() + a.Key.String()
|
||||
}
|
||||
|
||||
func (a ActionInstance) Equal(o ActionInstance) bool {
|
||||
return a.Key == o.Key && a.Action.Equal(o.Action)
|
||||
}
|
||||
|
||||
func (a ActionInstance) Less(o ActionInstance) bool {
|
||||
if !a.Action.Equal(o.Action) {
|
||||
return a.Action.Less(o.Action)
|
||||
}
|
||||
|
||||
if a.Key != o.Key {
|
||||
return InstanceKeyLess(a.Key, o.Key)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (a ActionInstance) UniqueKey() UniqueKey {
|
||||
return a // An ActionInstance is its own UniqueKey
|
||||
}
|
||||
|
||||
func (a ActionInstance) uniqueKeySigil() {}
|
||||
|
||||
// Absolute returns an AbsActionInstance from the receiver and the given module
|
||||
// instance address.
|
||||
func (a ActionInstance) Absolute(module ModuleInstance) AbsActionInstance {
|
||||
return AbsActionInstance{
|
||||
Module: module,
|
||||
Action: a,
|
||||
}
|
||||
}
|
||||
|
||||
// AbsAction is an absolute address for an action under a given module path.
|
||||
type AbsAction struct {
|
||||
Module ModuleInstance
|
||||
Action Action
|
||||
}
|
||||
|
||||
// Action returns the address of a particular action within the receiver.
|
||||
func (m ModuleInstance) Action(typeName string, name string) AbsAction {
|
||||
return AbsAction{
|
||||
Module: m,
|
||||
Action: Action{
|
||||
Type: typeName,
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Instance produces the address for a specific instance of the receiver that is
|
||||
// identified by the given key.
|
||||
func (a AbsAction) Instance(key InstanceKey) AbsActionInstance {
|
||||
return AbsActionInstance{
|
||||
Module: a.Module,
|
||||
Action: a.Action.Instance(key),
|
||||
}
|
||||
}
|
||||
|
||||
// Config returns the unexpanded ConfigAction for this AbsAction.
|
||||
func (a AbsAction) Config() ConfigAction {
|
||||
return ConfigAction{
|
||||
Module: a.Module.Module(),
|
||||
Action: a.Action,
|
||||
}
|
||||
}
|
||||
|
||||
func (a AbsAction) String() string {
|
||||
if len(a.Module) == 0 {
|
||||
return a.Action.String()
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", a.Module.String(), a.Action.String())
|
||||
}
|
||||
|
||||
// AffectedAbsAction returns the AbsAction.
|
||||
func (a AbsAction) AffectedAbsAction() AbsAction {
|
||||
return a
|
||||
}
|
||||
|
||||
func (a AbsAction) Equal(o AbsAction) bool {
|
||||
return a.Module.Equal(o.Module) && a.Action.Equal(o.Action)
|
||||
}
|
||||
|
||||
func (a AbsAction) Less(o AbsAction) bool {
|
||||
if !a.Module.Equal(o.Module) {
|
||||
return a.Module.Less(o.Module)
|
||||
}
|
||||
|
||||
if !a.Action.Equal(o.Action) {
|
||||
return a.Action.Less(o.Action)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type absActionKey string
|
||||
|
||||
func (a absActionKey) uniqueKeySigil() {}
|
||||
|
||||
func (a AbsAction) UniqueKey() UniqueKey {
|
||||
return absActionKey(a.String())
|
||||
}
|
||||
|
||||
// AbsActionInstance is an absolute address for an action instance under a
|
||||
// given module path.
|
||||
type AbsActionInstance struct {
|
||||
Module ModuleInstance
|
||||
Action ActionInstance
|
||||
}
|
||||
|
||||
// ActionInstance returns the address of a particular action instance within the receiver.
|
||||
func (m ModuleInstance) ActionInstance(typeName string, name string, key InstanceKey) AbsActionInstance {
|
||||
return AbsActionInstance{
|
||||
Module: m,
|
||||
Action: ActionInstance{
|
||||
Action: Action{
|
||||
Type: typeName,
|
||||
Name: name,
|
||||
},
|
||||
Key: key,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ContainingAction returns the address of the action that contains the
|
||||
// receiving action instance. In other words, it discards the key portion of the
|
||||
// address to produce an AbsAction value.
|
||||
func (a AbsActionInstance) ContainingAction() AbsAction {
|
||||
return AbsAction{
|
||||
Module: a.Module,
|
||||
Action: a.Action.ContainingAction(),
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigAction returns the address of the configuration block that declared
|
||||
// this instance.
|
||||
func (a AbsActionInstance) ConfigAction() ConfigAction {
|
||||
return ConfigAction{
|
||||
Module: a.Module.Module(),
|
||||
Action: a.Action.Action,
|
||||
}
|
||||
}
|
||||
|
||||
func (a AbsActionInstance) String() string {
|
||||
if len(a.Module) == 0 {
|
||||
return a.Action.String()
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", a.Module.String(), a.Action.String())
|
||||
}
|
||||
|
||||
// AffectedAbsAction returns the AbsAction for the instance.
|
||||
func (a AbsActionInstance) AffectedAbsAction() AbsAction {
|
||||
return AbsAction{
|
||||
Module: a.Module,
|
||||
Action: a.Action.Action,
|
||||
}
|
||||
}
|
||||
|
||||
func (a AbsActionInstance) Equal(o AbsActionInstance) bool {
|
||||
return a.Module.Equal(o.Module) && a.Action.Equal(o.Action)
|
||||
}
|
||||
|
||||
// Less returns true if the receiver should sort before the given other value
|
||||
// in a sorted list of addresses.
|
||||
func (a AbsActionInstance) Less(o AbsActionInstance) bool {
|
||||
if !a.Module.Equal(o.Module) {
|
||||
return a.Module.Less(o.Module)
|
||||
}
|
||||
|
||||
if !a.Action.Equal(o.Action) {
|
||||
return a.Action.Less(o.Action)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type absActionInstanceKey string
|
||||
|
||||
func (a AbsActionInstance) UniqueKey() UniqueKey {
|
||||
return absActionInstanceKey(a.String())
|
||||
}
|
||||
|
||||
func (r absActionInstanceKey) uniqueKeySigil() {}
|
||||
|
||||
// ConfigAction is the address for an action within the configuration.
|
||||
type ConfigAction struct {
|
||||
Module Module
|
||||
Action Action
|
||||
}
|
||||
|
||||
// Action returns the address of a particular action within the module.
|
||||
func (m Module) Action(typeName string, name string) ConfigAction {
|
||||
return ConfigAction{
|
||||
Module: m,
|
||||
Action: Action{
|
||||
Type: typeName,
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Absolute produces the address for the receiver within a specific module instance.
|
||||
func (a ConfigAction) Absolute(module ModuleInstance) AbsAction {
|
||||
return AbsAction{
|
||||
Module: module,
|
||||
Action: a.Action,
|
||||
}
|
||||
}
|
||||
|
||||
func (a ConfigAction) String() string {
|
||||
if len(a.Module) == 0 {
|
||||
return a.Action.String()
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", a.Module.String(), a.Action.String())
|
||||
}
|
||||
|
||||
func (a ConfigAction) Equal(o ConfigAction) bool {
|
||||
return a.Module.Equal(o.Module) && a.Action.Equal(o.Action)
|
||||
}
|
||||
|
||||
func (a ConfigAction) UniqueKey() UniqueKey {
|
||||
return configActionKey(a.String())
|
||||
}
|
||||
|
||||
type configActionKey string
|
||||
|
||||
func (k configActionKey) uniqueKeySigil() {}
|
||||
343
internal/addrs/action_test.go
Normal file
343
internal/addrs/action_test.go
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package addrs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestActionEqual(t *testing.T) {
|
||||
actions := []Action{
|
||||
{Type: "foo", Name: "bar"},
|
||||
{Type: "the", Name: "bloop"},
|
||||
}
|
||||
for _, r := range actions {
|
||||
t.Run(r.String(), func(t *testing.T) {
|
||||
if !r.Equal(r) {
|
||||
t.Fatalf("expected %#v to be equal to itself", r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// not equal
|
||||
testCases := []struct {
|
||||
right Action
|
||||
left Action
|
||||
}{
|
||||
{
|
||||
Action{Type: "a", Name: "b"},
|
||||
Action{Type: "b", Name: "b"},
|
||||
},
|
||||
{
|
||||
Action{Type: "a", Name: "b"},
|
||||
Action{Type: "a", Name: "c"},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("%s = %s", tc.left, tc.right), func(t *testing.T) {
|
||||
if tc.left.Equal(tc.right) {
|
||||
t.Fatalf("expected %#v not to be equal to %#v", tc.left, tc.right)
|
||||
}
|
||||
|
||||
if tc.right.Equal(tc.left) {
|
||||
t.Fatalf("expected %#v not to be equal to %#v", tc.right, tc.left)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionInstanceEqual(t *testing.T) {
|
||||
actions := []ActionInstance{
|
||||
{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: NoKey,
|
||||
},
|
||||
{
|
||||
Action: Action{Type: "the", Name: "bloop"},
|
||||
Key: StringKey("fish"),
|
||||
},
|
||||
}
|
||||
for _, r := range actions {
|
||||
t.Run(r.String(), func(t *testing.T) {
|
||||
if !r.Equal(r) {
|
||||
t.Fatalf("expected %#v to be equal to itself", r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// not equal
|
||||
testCases := []struct {
|
||||
right ActionInstance
|
||||
left ActionInstance
|
||||
}{
|
||||
{
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: NoKey,
|
||||
},
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: IntKey(1),
|
||||
},
|
||||
},
|
||||
{
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: NoKey,
|
||||
},
|
||||
ActionInstance{
|
||||
Action: Action{Type: "baz", Name: "bat"},
|
||||
Key: IntKey(1),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("%s = %s", tc.left, tc.right), func(t *testing.T) {
|
||||
if tc.left.Equal(tc.right) {
|
||||
t.Fatalf("expected %#v not to be equal to %#v", tc.left, tc.right)
|
||||
}
|
||||
|
||||
if tc.right.Equal(tc.left) {
|
||||
t.Fatalf("expected %#v not to be equal to %#v", tc.right, tc.left)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAbsActionInstanceEqual(t *testing.T) {
|
||||
actions := []AbsActionInstance{
|
||||
{
|
||||
RootModuleInstance,
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: NoKey,
|
||||
},
|
||||
},
|
||||
{
|
||||
mustParseModuleInstanceStr("module.child"),
|
||||
ActionInstance{
|
||||
Action: Action{Type: "the", Name: "bloop"},
|
||||
Key: StringKey("fish"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, r := range actions {
|
||||
t.Run(r.String(), func(t *testing.T) {
|
||||
if !r.Equal(r) {
|
||||
t.Fatalf("expected %#v to be equal to itself", r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// not equal
|
||||
testCases := []struct {
|
||||
right AbsActionInstance
|
||||
left AbsActionInstance
|
||||
}{
|
||||
{ // different keys
|
||||
AbsActionInstance{
|
||||
RootModuleInstance,
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: NoKey,
|
||||
},
|
||||
},
|
||||
AbsActionInstance{
|
||||
RootModuleInstance,
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: IntKey(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{ // different module
|
||||
AbsActionInstance{
|
||||
RootModuleInstance,
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: NoKey,
|
||||
},
|
||||
},
|
||||
AbsActionInstance{
|
||||
mustParseModuleInstanceStr("module.child[1]"),
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: NoKey,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{ // totally different
|
||||
AbsActionInstance{
|
||||
RootModuleInstance,
|
||||
ActionInstance{
|
||||
Action: Action{Type: "oof", Name: "rab"},
|
||||
Key: NoKey,
|
||||
},
|
||||
},
|
||||
AbsActionInstance{
|
||||
mustParseModuleInstanceStr("module.foo"),
|
||||
ActionInstance{
|
||||
Action: Action{Type: "foo", Name: "bar"},
|
||||
Key: IntKey(11),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("%s = %s", tc.left, tc.right), func(t *testing.T) {
|
||||
if tc.left.Equal(tc.right) {
|
||||
t.Fatalf("expected %#v not to be equal to %#v", tc.left, tc.right)
|
||||
}
|
||||
|
||||
if tc.right.Equal(tc.left) {
|
||||
t.Fatalf("expected %#v not to be equal to %#v", tc.right, tc.left)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestConfigActionEqual
|
||||
func TestConfigActionEqual(t *testing.T) {
|
||||
actions := []ConfigAction{
|
||||
{
|
||||
RootModule,
|
||||
Action{Type: "foo", Name: "bar"},
|
||||
},
|
||||
{
|
||||
Module{"child"},
|
||||
Action{Type: "the", Name: "bloop"},
|
||||
},
|
||||
}
|
||||
for _, r := range actions {
|
||||
t.Run(r.String(), func(t *testing.T) {
|
||||
if !r.Equal(r) {
|
||||
t.Fatalf("expected %#v to be equal to itself", r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// not equal
|
||||
testCases := []struct {
|
||||
right ConfigAction
|
||||
left ConfigAction
|
||||
}{
|
||||
{ // different name
|
||||
ConfigAction{
|
||||
RootModule,
|
||||
Action{Type: "foo", Name: "bar"},
|
||||
},
|
||||
ConfigAction{
|
||||
RootModule,
|
||||
Action{Type: "foo", Name: "baz"},
|
||||
},
|
||||
},
|
||||
// different type
|
||||
{
|
||||
ConfigAction{
|
||||
RootModule,
|
||||
Action{Type: "foo", Name: "bar"},
|
||||
},
|
||||
ConfigAction{
|
||||
RootModule,
|
||||
Action{Type: "baz", Name: "bar"},
|
||||
},
|
||||
},
|
||||
// different Module
|
||||
{
|
||||
ConfigAction{
|
||||
RootModule,
|
||||
Action{Type: "foo", Name: "bar"},
|
||||
},
|
||||
ConfigAction{
|
||||
Module{"mod"},
|
||||
Action{Type: "foo", Name: "bar"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("%s = %s", tc.left, tc.right), func(t *testing.T) {
|
||||
if tc.left.Equal(tc.right) {
|
||||
t.Fatalf("expected %#v not to be equal to %#v", tc.left, tc.right)
|
||||
}
|
||||
|
||||
if tc.right.Equal(tc.left) {
|
||||
t.Fatalf("expected %#v not to be equal to %#v", tc.right, tc.left)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestAbsActionUniqueKey
|
||||
func TestAbsActionUniqueKey(t *testing.T) {
|
||||
actionAddr1 := Action{
|
||||
Type: "a",
|
||||
Name: "b1",
|
||||
}.Absolute(RootModuleInstance)
|
||||
actionAddr2 := Action{
|
||||
Type: "a",
|
||||
Name: "b2",
|
||||
}.Absolute(RootModuleInstance)
|
||||
actionAddr3 := Action{
|
||||
Type: "a",
|
||||
Name: "in_module",
|
||||
}.Absolute(RootModuleInstance.Child("boop", NoKey))
|
||||
|
||||
tests := []struct {
|
||||
Receiver AbsAction
|
||||
Other UniqueKeyer
|
||||
WantEqual bool
|
||||
}{
|
||||
{
|
||||
actionAddr1,
|
||||
actionAddr1,
|
||||
true,
|
||||
},
|
||||
{
|
||||
actionAddr1,
|
||||
actionAddr2,
|
||||
false,
|
||||
},
|
||||
{
|
||||
actionAddr1,
|
||||
actionAddr3,
|
||||
false,
|
||||
},
|
||||
{
|
||||
actionAddr3,
|
||||
actionAddr3,
|
||||
true,
|
||||
},
|
||||
{
|
||||
actionAddr1,
|
||||
actionAddr1.Instance(NoKey),
|
||||
false, // no-key instance key is distinct from its resource even though they have the same String result
|
||||
},
|
||||
{
|
||||
actionAddr1,
|
||||
actionAddr1.Instance(IntKey(1)),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("%s matches %T %s?", test.Receiver, test.Other, test.Other), func(t *testing.T) {
|
||||
rKey := test.Receiver.UniqueKey()
|
||||
oKey := test.Other.UniqueKey()
|
||||
|
||||
gotEqual := rKey == oKey
|
||||
if gotEqual != test.WantEqual {
|
||||
t.Errorf(
|
||||
"wrong result\nreceiver: %s\nother: %s (%T)\ngot: %t\nwant: %t",
|
||||
test.Receiver, test.Other, test.Other,
|
||||
gotEqual, test.WantEqual,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,251 +1,134 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package addrs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
import "fmt"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
|
||||
// Check is the address of a check rule within a checkable object.
|
||||
// Check is the address of a check block within a module.
|
||||
//
|
||||
// This represents the check rule globally within a configuration, and is used
|
||||
// during graph evaluation to identify a condition result object to update with
|
||||
// the result of check rule evaluation.
|
||||
//
|
||||
// The check address is not distinct from resource traversals, and check rule
|
||||
// values are not intended to be available to the language, so the address is
|
||||
// not Referenceable.
|
||||
//
|
||||
// Note also that the check address is only relevant within the scope of a run,
|
||||
// as reordering check blocks between runs will result in their addresses
|
||||
// changing. Check is therefore for internal use only and should not be exposed
|
||||
// in durable artifacts such as state snapshots.
|
||||
// For now, checks do not support meta arguments such as "count" or "for_each"
|
||||
// so this address uniquely describes a single check within a module.
|
||||
type Check struct {
|
||||
Container Checkable
|
||||
Type CheckType
|
||||
Index int
|
||||
}
|
||||
|
||||
func NewCheck(container Checkable, typ CheckType, index int) Check {
|
||||
return Check{
|
||||
Container: container,
|
||||
Type: typ,
|
||||
Index: index,
|
||||
}
|
||||
referenceable
|
||||
Name string
|
||||
}
|
||||
|
||||
func (c Check) String() string {
|
||||
container := c.Container.String()
|
||||
switch c.Type {
|
||||
case ResourcePrecondition:
|
||||
return fmt.Sprintf("%s.precondition[%d]", container, c.Index)
|
||||
case ResourcePostcondition:
|
||||
return fmt.Sprintf("%s.postcondition[%d]", container, c.Index)
|
||||
case OutputPrecondition:
|
||||
return fmt.Sprintf("%s.precondition[%d]", container, c.Index)
|
||||
default:
|
||||
// This should not happen
|
||||
return fmt.Sprintf("%s.condition[%d]", container, c.Index)
|
||||
return fmt.Sprintf("check.%s", c.Name)
|
||||
}
|
||||
|
||||
// InModule returns a ConfigCheck from the receiver and the given module
|
||||
// address.
|
||||
func (c Check) InModule(modAddr Module) ConfigCheck {
|
||||
return ConfigCheck{
|
||||
Module: modAddr,
|
||||
Check: c,
|
||||
}
|
||||
}
|
||||
|
||||
// Absolute returns an AbsCheck from the receiver and the given module instance
|
||||
// address.
|
||||
func (c Check) Absolute(modAddr ModuleInstance) AbsCheck {
|
||||
return AbsCheck{
|
||||
Module: modAddr,
|
||||
Check: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (c Check) Equal(o Check) bool {
|
||||
return c.Name == o.Name
|
||||
}
|
||||
|
||||
func (c Check) UniqueKey() UniqueKey {
|
||||
return checkKey{
|
||||
ContainerKey: c.Container.UniqueKey(),
|
||||
Type: c.Type,
|
||||
Index: c.Index,
|
||||
}
|
||||
return c // A Check is its own UniqueKey
|
||||
}
|
||||
|
||||
type checkKey struct {
|
||||
ContainerKey UniqueKey
|
||||
Type CheckType
|
||||
Index int
|
||||
}
|
||||
func (c Check) uniqueKeySigil() {}
|
||||
|
||||
func (k checkKey) uniqueKeySigil() {}
|
||||
|
||||
// CheckType describes a category of check. We use this only to establish
|
||||
// uniqueness for Check values, and do not expose this concept of "check types"
|
||||
// (which is subject to change in future) in any durable artifacts such as
|
||||
// state snapshots.
|
||||
// ConfigCheck is an address for a check block within a configuration.
|
||||
//
|
||||
// (See [CheckableKind] for an enumeration that we _do_ use externally, to
|
||||
// describe the type of object being checked rather than the type of the check
|
||||
// itself.)
|
||||
type CheckType int
|
||||
// This contains a Check address and a Module address, meaning this describes
|
||||
// a check block within the entire configuration.
|
||||
type ConfigCheck struct {
|
||||
Module Module
|
||||
Check Check
|
||||
}
|
||||
|
||||
//go:generate go run golang.org/x/tools/cmd/stringer -type=CheckType check.go
|
||||
var _ ConfigCheckable = ConfigCheck{}
|
||||
|
||||
const (
|
||||
InvalidCondition CheckType = 0
|
||||
ResourcePrecondition CheckType = 1
|
||||
ResourcePostcondition CheckType = 2
|
||||
OutputPrecondition CheckType = 3
|
||||
)
|
||||
func (c ConfigCheck) UniqueKey() UniqueKey {
|
||||
return configCheckUniqueKey(c.String())
|
||||
}
|
||||
|
||||
// Description returns a human-readable description of the check type. This is
|
||||
// presented in the user interface through a diagnostic summary.
|
||||
func (c CheckType) Description() string {
|
||||
switch c {
|
||||
case ResourcePrecondition:
|
||||
return "Resource precondition"
|
||||
case ResourcePostcondition:
|
||||
return "Resource postcondition"
|
||||
case OutputPrecondition:
|
||||
return "Module output value precondition"
|
||||
default:
|
||||
// This should not happen
|
||||
return "Condition"
|
||||
func (c ConfigCheck) configCheckableSigil() {}
|
||||
|
||||
func (c ConfigCheck) CheckableKind() CheckableKind {
|
||||
return CheckableCheck
|
||||
}
|
||||
|
||||
func (c ConfigCheck) String() string {
|
||||
if len(c.Module) == 0 {
|
||||
return c.Check.String()
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", c.Module, c.Check)
|
||||
}
|
||||
|
||||
// Checkable is an interface implemented by all address types that can contain
|
||||
// condition blocks.
|
||||
type Checkable interface {
|
||||
UniqueKeyer
|
||||
|
||||
checkableSigil()
|
||||
|
||||
// Check returns the address of an individual check rule of a specified
|
||||
// type and index within this checkable container.
|
||||
Check(CheckType, int) Check
|
||||
|
||||
// ConfigCheckable returns the address of the configuration construct that
|
||||
// this Checkable belongs to.
|
||||
//
|
||||
// Checkable objects can potentially be dynamically declared during a
|
||||
// plan operation using constructs like resource for_each, and so
|
||||
// ConfigCheckable gives us a way to talk about the static containers
|
||||
// those dynamic objects belong to, in case we wish to group together
|
||||
// dynamic checkable objects into their static checkable for reporting
|
||||
// purposes.
|
||||
ConfigCheckable() ConfigCheckable
|
||||
|
||||
CheckableKind() CheckableKind
|
||||
String() string
|
||||
}
|
||||
|
||||
var (
|
||||
_ Checkable = AbsResourceInstance{}
|
||||
_ Checkable = AbsOutputValue{}
|
||||
)
|
||||
|
||||
// CheckableKind describes the different kinds of checkable objects.
|
||||
type CheckableKind rune
|
||||
|
||||
//go:generate go run golang.org/x/tools/cmd/stringer -type=CheckableKind check.go
|
||||
|
||||
const (
|
||||
CheckableKindInvalid CheckableKind = 0
|
||||
CheckableResource CheckableKind = 'R'
|
||||
CheckableOutputValue CheckableKind = 'O'
|
||||
)
|
||||
|
||||
// ConfigCheckable is an interfaces implemented by address types that represent
|
||||
// configuration constructs that can have Checkable addresses associated with
|
||||
// them.
|
||||
// AbsCheck is an absolute address for a check block under a given module path.
|
||||
//
|
||||
// This address type therefore in a sense represents a container for zero or
|
||||
// more checkable objects all declared by the same configuration construct,
|
||||
// so that we can talk about these groups of checkable objects before we're
|
||||
// ready to decide how many checkable objects belong to each one.
|
||||
type ConfigCheckable interface {
|
||||
UniqueKeyer
|
||||
|
||||
configCheckableSigil()
|
||||
|
||||
CheckableKind() CheckableKind
|
||||
String() string
|
||||
// This contains an actual ModuleInstance address (compared to the Module within
|
||||
// a ConfigCheck), meaning this uniquely describes a check block within the
|
||||
// entire configuration after any "count" or "foreach" meta arguments have been
|
||||
// evaluated on the containing module.
|
||||
type AbsCheck struct {
|
||||
Module ModuleInstance
|
||||
Check Check
|
||||
}
|
||||
|
||||
var (
|
||||
_ ConfigCheckable = ConfigResource{}
|
||||
_ ConfigCheckable = ConfigOutputValue{}
|
||||
)
|
||||
var _ Checkable = AbsCheck{}
|
||||
|
||||
// ParseCheckableStr attempts to parse the given string as a Checkable address
|
||||
// of the given kind.
|
||||
func (c AbsCheck) UniqueKey() UniqueKey {
|
||||
return absCheckUniqueKey(c.String())
|
||||
}
|
||||
|
||||
func (c AbsCheck) checkableSigil() {}
|
||||
|
||||
// CheckRule returns an address for a given rule type within the check block.
|
||||
//
|
||||
// This should be the opposite of Checkable.String for any Checkable address
|
||||
// type, as long as "kind" is set to the value returned by the address's
|
||||
// CheckableKind method.
|
||||
//
|
||||
// We do not typically expect users to write out checkable addresses as input,
|
||||
// but we use them as part of some of our wire formats for persisting check
|
||||
// results between runs.
|
||||
func ParseCheckableStr(kind CheckableKind, src string) (Checkable, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(src), "", hcl.InitialPos)
|
||||
diags = diags.Append(parseDiags)
|
||||
if parseDiags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
path, remain, diags := parseModuleInstancePrefix(traversal)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
if remain.IsRelative() {
|
||||
// (relative means that there's either nothing left or what's next isn't an identifier)
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid checkable address",
|
||||
Detail: "Module path must be followed by either a resource instance address or an output value address.",
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
// We use "kind" to disambiguate here because unfortunately we've
|
||||
// historically never reserved "output" as a possible resource type name
|
||||
// and so it is in principle possible -- albeit unlikely -- that there
|
||||
// might be a resource whose type is literally "output".
|
||||
switch kind {
|
||||
case CheckableResource:
|
||||
riAddr, moreDiags := parseResourceInstanceUnderModule(path, remain)
|
||||
diags = diags.Append(moreDiags)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
return riAddr, diags
|
||||
|
||||
case CheckableOutputValue:
|
||||
if len(remain) != 2 {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid checkable address",
|
||||
Detail: "Output address must have only one attribute part after the keyword 'output', giving the name of the output value.",
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
return nil, diags
|
||||
}
|
||||
if remain.RootName() != "output" {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid checkable address",
|
||||
Detail: "Output address must follow the module address with the keyword 'output'.",
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
return nil, diags
|
||||
}
|
||||
if step, ok := remain[1].(hcl.TraverseAttr); !ok {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid checkable address",
|
||||
Detail: "Output address must have only one attribute part after the keyword 'output', giving the name of the output value.",
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
return nil, diags
|
||||
} else {
|
||||
return OutputValue{Name: step.Name}.Absolute(path), diags
|
||||
}
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported CheckableKind %s", kind))
|
||||
// There will be at most one CheckDataResource rule within a check block (with
|
||||
// an index of 0). There will be at least one, but potentially many,
|
||||
// CheckAssertion rules within a check block.
|
||||
func (c AbsCheck) CheckRule(typ CheckRuleType, i int) CheckRule {
|
||||
return CheckRule{
|
||||
Container: c,
|
||||
Type: typ,
|
||||
Index: i,
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigCheckable returns the ConfigCheck address for this absolute reference.
|
||||
func (c AbsCheck) ConfigCheckable() ConfigCheckable {
|
||||
return ConfigCheck{
|
||||
Module: c.Module.Module(),
|
||||
Check: c.Check,
|
||||
}
|
||||
}
|
||||
|
||||
func (c AbsCheck) CheckableKind() CheckableKind {
|
||||
return CheckableCheck
|
||||
}
|
||||
|
||||
func (c AbsCheck) String() string {
|
||||
if len(c.Module) == 0 {
|
||||
return c.Check.String()
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", c.Module, c.Check)
|
||||
}
|
||||
|
||||
type configCheckUniqueKey string
|
||||
|
||||
func (k configCheckUniqueKey) uniqueKeySigil() {}
|
||||
|
||||
type absCheckUniqueKey string
|
||||
|
||||
func (k absCheckUniqueKey) uniqueKeySigil() {}
|
||||
|
|
|
|||
117
internal/addrs/check_rule.go
Normal file
117
internal/addrs/check_rule.go
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package addrs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// CheckRule is the address of a check rule within a checkable object.
|
||||
//
|
||||
// This represents the check rule globally within a configuration, and is used
|
||||
// during graph evaluation to identify a condition result object to update with
|
||||
// the result of check rule evaluation.
|
||||
//
|
||||
// The check address is not distinct from resource traversals, and check rule
|
||||
// values are not intended to be available to the language, so the address is
|
||||
// not Referenceable.
|
||||
//
|
||||
// Note also that the check address is only relevant within the scope of a run,
|
||||
// as reordering check blocks between runs will result in their addresses
|
||||
// changing. CheckRule is therefore for internal use only and should not be
|
||||
// exposed in durable artifacts such as state snapshots.
|
||||
type CheckRule struct {
|
||||
Container Checkable
|
||||
Type CheckRuleType
|
||||
Index int
|
||||
}
|
||||
|
||||
func NewCheckRule(container Checkable, typ CheckRuleType, index int) CheckRule {
|
||||
return CheckRule{
|
||||
Container: container,
|
||||
Type: typ,
|
||||
Index: index,
|
||||
}
|
||||
}
|
||||
|
||||
func (c CheckRule) String() string {
|
||||
container := c.Container.String()
|
||||
switch c.Type {
|
||||
case ResourcePrecondition:
|
||||
return fmt.Sprintf("%s.precondition[%d]", container, c.Index)
|
||||
case ResourcePostcondition:
|
||||
return fmt.Sprintf("%s.postcondition[%d]", container, c.Index)
|
||||
case OutputPrecondition:
|
||||
return fmt.Sprintf("%s.precondition[%d]", container, c.Index)
|
||||
case CheckDataResource:
|
||||
return fmt.Sprintf("%s.data[%d]", container, c.Index)
|
||||
case CheckAssertion:
|
||||
return fmt.Sprintf("%s.assert[%d]", container, c.Index)
|
||||
case InputValidation:
|
||||
return fmt.Sprintf("%s.validation[%d]", container, c.Index)
|
||||
default:
|
||||
// This should not happen
|
||||
return fmt.Sprintf("%s.condition[%d]", container, c.Index)
|
||||
}
|
||||
}
|
||||
|
||||
func (c CheckRule) UniqueKey() UniqueKey {
|
||||
return checkRuleKey{
|
||||
ContainerKey: c.Container.UniqueKey(),
|
||||
Type: c.Type,
|
||||
Index: c.Index,
|
||||
}
|
||||
}
|
||||
|
||||
type checkRuleKey struct {
|
||||
ContainerKey UniqueKey
|
||||
Type CheckRuleType
|
||||
Index int
|
||||
}
|
||||
|
||||
func (k checkRuleKey) uniqueKeySigil() {}
|
||||
|
||||
// CheckRuleType describes a category of check. We use this only to establish
|
||||
// uniqueness for Check values, and do not expose this concept of "check types"
|
||||
// (which is subject to change in future) in any durable artifacts such as
|
||||
// state snapshots.
|
||||
//
|
||||
// (See [CheckableKind] for an enumeration that we _do_ use externally, to
|
||||
// describe the type of object being checked rather than the type of the check
|
||||
// itself.)
|
||||
type CheckRuleType int
|
||||
|
||||
//go:generate go tool golang.org/x/tools/cmd/stringer -type=CheckRuleType check_rule.go
|
||||
|
||||
const (
|
||||
InvalidCondition CheckRuleType = 0
|
||||
ResourcePrecondition CheckRuleType = 1
|
||||
ResourcePostcondition CheckRuleType = 2
|
||||
OutputPrecondition CheckRuleType = 3
|
||||
CheckDataResource CheckRuleType = 4
|
||||
CheckAssertion CheckRuleType = 5
|
||||
InputValidation CheckRuleType = 6
|
||||
)
|
||||
|
||||
// Description returns a human-readable description of the check type. This is
|
||||
// presented in the user interface through a diagnostic summary.
|
||||
func (c CheckRuleType) Description() string {
|
||||
switch c {
|
||||
case ResourcePrecondition:
|
||||
return "Resource precondition"
|
||||
case ResourcePostcondition:
|
||||
return "Resource postcondition"
|
||||
case OutputPrecondition:
|
||||
return "Module output value precondition"
|
||||
case CheckDataResource:
|
||||
return "Check block data resource"
|
||||
case CheckAssertion:
|
||||
return "Check block assertion"
|
||||
case InputValidation:
|
||||
return "Input variable validation"
|
||||
default:
|
||||
// This should not happen
|
||||
return "Condition"
|
||||
}
|
||||
}
|
||||
73
internal/addrs/check_rule_diagnostic.go
Normal file
73
internal/addrs/check_rule_diagnostic.go
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package addrs
|
||||
|
||||
import "github.com/hashicorp/terraform/internal/tfdiags"
|
||||
|
||||
// DiagnosticExtraCheckRule provides an interface for diagnostic ExtraInfo to
|
||||
// retrieve an embedded CheckRule from within a tfdiags.Diagnostic.
|
||||
type DiagnosticExtraCheckRule interface {
|
||||
// DiagnosticOriginatesFromCheckRule returns the CheckRule that the
|
||||
// surrounding diagnostic originated from.
|
||||
DiagnosticOriginatesFromCheckRule() CheckRule
|
||||
}
|
||||
|
||||
// DiagnosticOriginatesFromCheckRule checks if the provided diagnostic contains
|
||||
// a CheckRule as ExtraInfo and returns that CheckRule and true if it does. This
|
||||
// function returns an empty CheckRule and false if the diagnostic does not
|
||||
// contain a CheckRule.
|
||||
func DiagnosticOriginatesFromCheckRule(diag tfdiags.Diagnostic) (CheckRule, bool) {
|
||||
maybe := tfdiags.ExtraInfo[DiagnosticExtraCheckRule](diag)
|
||||
if maybe == nil {
|
||||
return CheckRule{}, false
|
||||
}
|
||||
return maybe.DiagnosticOriginatesFromCheckRule(), true
|
||||
}
|
||||
|
||||
// CheckRuleDiagnosticExtra is an object that can be attached to diagnostics
|
||||
// that originate from check rules.
|
||||
//
|
||||
// It implements the DiagnosticExtraCheckRule interface for retrieving the
|
||||
// concrete CheckRule that spawned the diagnostic.
|
||||
//
|
||||
// It also implements the tfdiags.DiagnosticExtraDoNotConsolidate interface, to
|
||||
// stop diagnostics created by check blocks being consolidated.
|
||||
//
|
||||
// It also implements the tfdiags.DiagnosticExtraUnwrapper interface, as nested
|
||||
// data blocks will attach this struct but do want to lose any extra info
|
||||
// embedded in the original diagnostic.
|
||||
type CheckRuleDiagnosticExtra struct {
|
||||
CheckRule CheckRule
|
||||
|
||||
wrapped interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
_ DiagnosticExtraCheckRule = (*CheckRuleDiagnosticExtra)(nil)
|
||||
_ tfdiags.DiagnosticExtraDoNotConsolidate = (*CheckRuleDiagnosticExtra)(nil)
|
||||
_ tfdiags.DiagnosticExtraUnwrapper = (*CheckRuleDiagnosticExtra)(nil)
|
||||
_ tfdiags.DiagnosticExtraWrapper = (*CheckRuleDiagnosticExtra)(nil)
|
||||
)
|
||||
|
||||
func (c *CheckRuleDiagnosticExtra) UnwrapDiagnosticExtra() interface{} {
|
||||
return c.wrapped
|
||||
}
|
||||
|
||||
func (c *CheckRuleDiagnosticExtra) WrapDiagnosticExtra(inner interface{}) {
|
||||
if c.wrapped != nil {
|
||||
// This is a logical inconsistency, the caller should know whether they
|
||||
// have already wrapped an extra or not.
|
||||
panic("Attempted to wrap a diagnostic extra into a CheckRuleDiagnosticExtra that is already wrapping a different extra. This is a bug in Terraform, please report it.")
|
||||
}
|
||||
c.wrapped = inner
|
||||
}
|
||||
|
||||
func (c *CheckRuleDiagnosticExtra) DoNotConsolidateDiagnostic() bool {
|
||||
// Do not consolidate warnings from check blocks.
|
||||
return c.CheckRule.Container.CheckableKind() == CheckableCheck
|
||||
}
|
||||
|
||||
func (c *CheckRuleDiagnosticExtra) DiagnosticOriginatesFromCheckRule() CheckRule {
|
||||
return c.CheckRule
|
||||
}
|
||||
111
internal/addrs/check_rule_diagnostic_test.go
Normal file
111
internal/addrs/check_rule_diagnostic_test.go
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package addrs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
|
||||
func TestCheckRuleDiagnosticExtra_WrapsExtra(t *testing.T) {
|
||||
var originals tfdiags.Diagnostics
|
||||
originals = originals.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "original error",
|
||||
Detail: "this is an error",
|
||||
Extra: "extra",
|
||||
})
|
||||
|
||||
overridden := tfdiags.OverrideAll(originals, tfdiags.Warning, func() tfdiags.DiagnosticExtraWrapper {
|
||||
return &CheckRuleDiagnosticExtra{}
|
||||
})
|
||||
|
||||
if overridden[0].ExtraInfo().(*CheckRuleDiagnosticExtra).wrapped.(string) != "extra" {
|
||||
t.Errorf("unexpected extra info: %v", overridden[0].ExtraInfo())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckRuleDiagnosticExtra_Unwraps(t *testing.T) {
|
||||
var originals tfdiags.Diagnostics
|
||||
originals = originals.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "original error",
|
||||
Detail: "this is an error",
|
||||
Extra: "extra",
|
||||
})
|
||||
|
||||
overridden := tfdiags.OverrideAll(originals, tfdiags.Warning, func() tfdiags.DiagnosticExtraWrapper {
|
||||
return &CheckRuleDiagnosticExtra{}
|
||||
})
|
||||
|
||||
result := tfdiags.ExtraInfo[string](overridden[0])
|
||||
if result != "extra" {
|
||||
t.Errorf("unexpected extra info: %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckRuleDiagnosticExtra_DoNotConsolidate(t *testing.T) {
|
||||
var diags tfdiags.Diagnostics
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "original error",
|
||||
Detail: "this is an error",
|
||||
Extra: &CheckRuleDiagnosticExtra{
|
||||
CheckRule: NewCheckRule(AbsOutputValue{
|
||||
Module: RootModuleInstance,
|
||||
OutputValue: OutputValue{
|
||||
Name: "output",
|
||||
},
|
||||
}, OutputPrecondition, 0),
|
||||
},
|
||||
})
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "original error",
|
||||
Detail: "this is an error",
|
||||
Extra: &CheckRuleDiagnosticExtra{
|
||||
CheckRule: NewCheckRule(AbsCheck{
|
||||
Module: RootModuleInstance,
|
||||
Check: Check{
|
||||
Name: "check",
|
||||
},
|
||||
}, CheckAssertion, 0),
|
||||
},
|
||||
})
|
||||
|
||||
if tfdiags.DoNotConsolidateDiagnostic(diags[0]) {
|
||||
t.Errorf("first diag should be consolidated but was not")
|
||||
}
|
||||
|
||||
if !tfdiags.DoNotConsolidateDiagnostic(diags[1]) {
|
||||
t.Errorf("second diag should not be consolidated but was")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestDiagnosticOriginatesFromCheckRule_Passes(t *testing.T) {
|
||||
var diags tfdiags.Diagnostics
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "original error",
|
||||
Detail: "this is an error",
|
||||
})
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "original error",
|
||||
Detail: "this is an error",
|
||||
Extra: &CheckRuleDiagnosticExtra{},
|
||||
})
|
||||
|
||||
if _, ok := DiagnosticOriginatesFromCheckRule(diags[0]); ok {
|
||||
t.Errorf("first diag did not originate from check rule but thinks it did")
|
||||
}
|
||||
|
||||
if _, ok := DiagnosticOriginatesFromCheckRule(diags[1]); !ok {
|
||||
t.Errorf("second diag did originate from check rule but this it did not")
|
||||
}
|
||||
}
|
||||
194
internal/addrs/checkable.go
Normal file
194
internal/addrs/checkable.go
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package addrs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
|
||||
// Checkable is an interface implemented by all address types that can contain
|
||||
// condition blocks.
|
||||
type Checkable interface {
|
||||
UniqueKeyer
|
||||
|
||||
checkableSigil()
|
||||
|
||||
// CheckRule returns the address of an individual check rule of a specified
|
||||
// type and index within this checkable container.
|
||||
CheckRule(CheckRuleType, int) CheckRule
|
||||
|
||||
// ConfigCheckable returns the address of the configuration construct that
|
||||
// this Checkable belongs to.
|
||||
//
|
||||
// Checkable objects can potentially be dynamically declared during a
|
||||
// plan operation using constructs like resource for_each, and so
|
||||
// ConfigCheckable gives us a way to talk about the static containers
|
||||
// those dynamic objects belong to, in case we wish to group together
|
||||
// dynamic checkable objects into their static checkable for reporting
|
||||
// purposes.
|
||||
ConfigCheckable() ConfigCheckable
|
||||
|
||||
CheckableKind() CheckableKind
|
||||
String() string
|
||||
}
|
||||
|
||||
var (
|
||||
_ Checkable = AbsResourceInstance{}
|
||||
_ Checkable = AbsOutputValue{}
|
||||
)
|
||||
|
||||
// CheckableKind describes the different kinds of checkable objects.
|
||||
type CheckableKind rune
|
||||
|
||||
//go:generate go tool golang.org/x/tools/cmd/stringer -type=CheckableKind checkable.go
|
||||
|
||||
const (
|
||||
CheckableKindInvalid CheckableKind = 0
|
||||
CheckableResource CheckableKind = 'R'
|
||||
CheckableOutputValue CheckableKind = 'O'
|
||||
CheckableCheck CheckableKind = 'C'
|
||||
CheckableInputVariable CheckableKind = 'I'
|
||||
)
|
||||
|
||||
// ConfigCheckable is an interfaces implemented by address types that represent
|
||||
// configuration constructs that can have Checkable addresses associated with
|
||||
// them.
|
||||
//
|
||||
// This address type therefore in a sense represents a container for zero or
|
||||
// more checkable objects all declared by the same configuration construct,
|
||||
// so that we can talk about these groups of checkable objects before we're
|
||||
// ready to decide how many checkable objects belong to each one.
|
||||
type ConfigCheckable interface {
|
||||
UniqueKeyer
|
||||
|
||||
configCheckableSigil()
|
||||
|
||||
CheckableKind() CheckableKind
|
||||
String() string
|
||||
}
|
||||
|
||||
var (
|
||||
_ ConfigCheckable = ConfigResource{}
|
||||
_ ConfigCheckable = ConfigOutputValue{}
|
||||
)
|
||||
|
||||
// ParseCheckableStr attempts to parse the given string as a Checkable address
|
||||
// of the given kind.
|
||||
//
|
||||
// This should be the opposite of Checkable.String for any Checkable address
|
||||
// type, as long as "kind" is set to the value returned by the address's
|
||||
// CheckableKind method.
|
||||
//
|
||||
// We do not typically expect users to write out checkable addresses as input,
|
||||
// but we use them as part of some of our wire formats for persisting check
|
||||
// results between runs.
|
||||
func ParseCheckableStr(kind CheckableKind, src string) (Checkable, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(src), "", hcl.InitialPos)
|
||||
diags = diags.Append(parseDiags)
|
||||
if parseDiags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
path, remain, diags := parseModuleInstancePrefix(traversal, false)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
if remain.IsRelative() {
|
||||
// (relative means that there's either nothing left or what's next isn't an identifier)
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid checkable address",
|
||||
Detail: "Module path must be followed by either a resource instance address or an output value address.",
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
getCheckableName := func(keyword string, descriptor string) (string, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
var name string
|
||||
|
||||
if len(remain) != 2 {
|
||||
diags = diags.Append(hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid checkable address",
|
||||
Detail: fmt.Sprintf("%s address must have only one attribute part after the keyword '%s', giving the name of the %s.", cases.Title(language.English, cases.NoLower).String(keyword), keyword, descriptor),
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
if remain.RootName() != keyword {
|
||||
diags = diags.Append(hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid checkable address",
|
||||
Detail: fmt.Sprintf("%s address must follow the module address with the keyword '%s'.", cases.Title(language.English, cases.NoLower).String(keyword), keyword),
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
}
|
||||
if step, ok := remain[1].(hcl.TraverseAttr); !ok {
|
||||
diags = diags.Append(hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid checkable address",
|
||||
Detail: fmt.Sprintf("%s address must have only one attribute part after the keyword '%s', giving the name of the %s.", cases.Title(language.English, cases.NoLower).String(keyword), keyword, descriptor),
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
} else {
|
||||
name = step.Name
|
||||
}
|
||||
|
||||
return name, diags
|
||||
}
|
||||
|
||||
// We use "kind" to disambiguate here because unfortunately we've
|
||||
// historically never reserved "output" as a possible resource type name
|
||||
// and so it is in principle possible -- albeit unlikely -- that there
|
||||
// might be a resource whose type is literally "output".
|
||||
switch kind {
|
||||
case CheckableResource:
|
||||
riAddr, moreDiags := parseResourceInstanceUnderModule(path, false, remain)
|
||||
diags = diags.Append(moreDiags)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
return riAddr, diags
|
||||
|
||||
case CheckableOutputValue:
|
||||
name, nameDiags := getCheckableName("output", "output value")
|
||||
diags = diags.Append(nameDiags)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
return OutputValue{Name: name}.Absolute(path), diags
|
||||
|
||||
case CheckableCheck:
|
||||
name, nameDiags := getCheckableName("check", "check block")
|
||||
diags = diags.Append(nameDiags)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
return Check{Name: name}.Absolute(path), diags
|
||||
|
||||
case CheckableInputVariable:
|
||||
name, nameDiags := getCheckableName("var", "variable value")
|
||||
diags = diags.Append(nameDiags)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
return InputVariable{Name: name}.Absolute(path), diags
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported CheckableKind %s", kind))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by "stringer -type=CheckableKind check.go"; DO NOT EDIT.
|
||||
// Code generated by "stringer -type=CheckableKind checkable.go"; DO NOT EDIT.
|
||||
|
||||
package addrs
|
||||
|
||||
|
|
@ -11,22 +11,30 @@ func _() {
|
|||
_ = x[CheckableKindInvalid-0]
|
||||
_ = x[CheckableResource-82]
|
||||
_ = x[CheckableOutputValue-79]
|
||||
_ = x[CheckableCheck-67]
|
||||
_ = x[CheckableInputVariable-73]
|
||||
}
|
||||
|
||||
const (
|
||||
_CheckableKind_name_0 = "CheckableKindInvalid"
|
||||
_CheckableKind_name_1 = "CheckableOutputValue"
|
||||
_CheckableKind_name_2 = "CheckableResource"
|
||||
_CheckableKind_name_1 = "CheckableCheck"
|
||||
_CheckableKind_name_2 = "CheckableInputVariable"
|
||||
_CheckableKind_name_3 = "CheckableOutputValue"
|
||||
_CheckableKind_name_4 = "CheckableResource"
|
||||
)
|
||||
|
||||
func (i CheckableKind) String() string {
|
||||
switch {
|
||||
case i == 0:
|
||||
return _CheckableKind_name_0
|
||||
case i == 79:
|
||||
case i == 67:
|
||||
return _CheckableKind_name_1
|
||||
case i == 82:
|
||||
case i == 73:
|
||||
return _CheckableKind_name_2
|
||||
case i == 79:
|
||||
return _CheckableKind_name_3
|
||||
case i == 82:
|
||||
return _CheckableKind_name_4
|
||||
default:
|
||||
return "CheckableKind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
|
|
|
|||
29
internal/addrs/checkruletype_string.go
Normal file
29
internal/addrs/checkruletype_string.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Code generated by "stringer -type=CheckRuleType check_rule.go"; DO NOT EDIT.
|
||||
|
||||
package addrs
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[InvalidCondition-0]
|
||||
_ = x[ResourcePrecondition-1]
|
||||
_ = x[ResourcePostcondition-2]
|
||||
_ = x[OutputPrecondition-3]
|
||||
_ = x[CheckDataResource-4]
|
||||
_ = x[CheckAssertion-5]
|
||||
_ = x[InputValidation-6]
|
||||
}
|
||||
|
||||
const _CheckRuleType_name = "InvalidConditionResourcePreconditionResourcePostconditionOutputPreconditionCheckDataResourceCheckAssertionInputValidation"
|
||||
|
||||
var _CheckRuleType_index = [...]uint8{0, 16, 36, 57, 75, 92, 106, 121}
|
||||
|
||||
func (i CheckRuleType) String() string {
|
||||
if i < 0 || i >= CheckRuleType(len(_CheckRuleType_index)-1) {
|
||||
return "CheckRuleType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _CheckRuleType_name[_CheckRuleType_index[i]:_CheckRuleType_index[i+1]]
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// Code generated by "stringer -type=CheckType check.go"; DO NOT EDIT.
|
||||
|
||||
package addrs
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[InvalidCondition-0]
|
||||
_ = x[ResourcePrecondition-1]
|
||||
_ = x[ResourcePostcondition-2]
|
||||
_ = x[OutputPrecondition-3]
|
||||
}
|
||||
|
||||
const _CheckType_name = "InvalidConditionResourcePreconditionResourcePostconditionOutputPrecondition"
|
||||
|
||||
var _CheckType_index = [...]uint8{0, 16, 36, 57, 75}
|
||||
|
||||
func (i CheckType) String() string {
|
||||
if i < 0 || i >= CheckType(len(_CheckType_index)-1) {
|
||||
return "CheckType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _CheckType_name[_CheckType_index[i]:_CheckType_index[i+1]]
|
||||
}
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package addrs
|
||||
|
||||
// CountAttr is the address of an attribute of the "count" object in
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
// Package addrs contains types that represent "addresses", which are
|
||||
// references to specific objects within a Terraform configuration or
|
||||
// state.
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue