From 1a583246894c80217be11a1213c4cc9ecec54d6b Mon Sep 17 00:00:00 2001 From: jaakko Date: Wed, 8 Apr 2026 10:29:42 +0300 Subject: [PATCH] Tofuist-agentti: OpenTofu/IaC-asiantuntija gecko-avatarilla MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Uusi agentti: Tofuist (gecko-avatar, oranssinkulta #e3a336) - System prompt: HCL-koodi, moduulit, lifecycle, state encryption - docs-kenttä: lataa automaattisesti /docs/tofu-cheatsheet.md referenssiksi - kpnRun: tukee nyt agentin docs-kenttää (haetaan kerran, cachetetaan) - OpenTofu-dokumentaatio haettu GitHubista + tiivistetty cheatsheet - Avatar, gallery-head, värimapit ja pipeline-tuet lisätty Co-Authored-By: Claude Opus 4.6 (1M context) --- network-poc/static/avatars/gecko_notext.png | Bin 0 -> 133307 bytes network-poc/static/docs/README.md | 43 + network-poc/static/docs/architecture.md | 374 ++++++ network-poc/static/docs/destroying.md | 361 ++++++ network-poc/static/docs/diagnostics.md | 495 ++++++++ network-poc/static/docs/glossary.md | 78 ++ .../docs/images/architecture-overview.png | Bin 0 -> 233067 bytes .../docs/images/destroy_then_update.png | Bin 0 -> 8741 bytes .../static/docs/images/replace_all.png | Bin 0 -> 12463 bytes .../static/docs/images/replace_all_cbd.png | Bin 0 -> 12469 bytes .../docs/images/replace_all_cbd_dep.png | Bin 0 -> 13707 bytes .../docs/images/replace_cbd_incorrect.png | Bin 0 -> 12577 bytes .../docs/images/replace_dep_cbd_dep.png | Bin 0 -> 13303 bytes .../static/docs/images/replace_one.png | Bin 0 -> 13026 bytes .../resource-instance-change-lifecycle.png | Bin 0 -> 199031 bytes .../static/docs/images/simple_create.png | Bin 0 -> 5254 bytes .../static/docs/images/simple_destroy.png | Bin 0 -> 5921 bytes .../static/docs/images/simple_update.png | Bin 0 -> 8256 bytes .../static/docs/images/update_destroy_cbd.png | Bin 0 -> 8734 bytes network-poc/static/docs/planning-behaviors.md | 294 +++++ .../static/docs/plugin-protocol/README.md | 213 ++++ .../plugin-protocol/object-wire-format.md | 267 ++++ .../plugin-protocol/releasing-new-version.md | 53 + .../docs/plugin-protocol/tfplugin5.0.proto | 358 ++++++ .../docs/plugin-protocol/tfplugin5.1.proto | 358 ++++++ .../docs/plugin-protocol/tfplugin5.10.proto | 953 +++++++++++++++ .../docs/plugin-protocol/tfplugin5.2.proto | 374 ++++++ .../docs/plugin-protocol/tfplugin5.3.proto | 403 ++++++ .../docs/plugin-protocol/tfplugin5.4.proto | 409 +++++++ .../docs/plugin-protocol/tfplugin5.5.proto | 591 +++++++++ .../docs/plugin-protocol/tfplugin5.6.proto | 637 ++++++++++ .../docs/plugin-protocol/tfplugin5.7.proto | 700 +++++++++++ .../docs/plugin-protocol/tfplugin5.8.proto | 707 +++++++++++ .../docs/plugin-protocol/tfplugin5.9.proto | 826 +++++++++++++ .../docs/plugin-protocol/tfplugin6.0.proto | 326 +++++ .../docs/plugin-protocol/tfplugin6.1.proto | 329 +++++ .../docs/plugin-protocol/tfplugin6.10.proto | 1078 +++++++++++++++++ .../docs/plugin-protocol/tfplugin6.2.proto | 355 ++++++ .../docs/plugin-protocol/tfplugin6.3.proto | 384 ++++++ .../docs/plugin-protocol/tfplugin6.4.proto | 390 ++++++ .../docs/plugin-protocol/tfplugin6.5.proto | 572 +++++++++ .../docs/plugin-protocol/tfplugin6.6.proto | 618 ++++++++++ .../docs/plugin-protocol/tfplugin6.7.proto | 682 +++++++++++ .../docs/plugin-protocol/tfplugin6.8.proto | 691 +++++++++++ .../docs/plugin-protocol/tfplugin6.9.proto | 809 +++++++++++++ .../static/docs/provider-references.md | 398 ++++++ .../resource-instance-change-lifecycle.md | 372 ++++++ network-poc/static/docs/state_encryption.md | 309 +++++ network-poc/static/docs/tofu-cheatsheet.md | 102 ++ network-poc/static/docs/tracing.md | 147 +++ network-poc/static/docs/unicode.md | 142 +++ network-poc/static/index.html | 30 +- 52 files changed, 16220 insertions(+), 8 deletions(-) create mode 100644 network-poc/static/avatars/gecko_notext.png create mode 100644 network-poc/static/docs/README.md create mode 100644 network-poc/static/docs/architecture.md create mode 100644 network-poc/static/docs/destroying.md create mode 100644 network-poc/static/docs/diagnostics.md create mode 100644 network-poc/static/docs/glossary.md create mode 100644 network-poc/static/docs/images/architecture-overview.png create mode 100644 network-poc/static/docs/images/destroy_then_update.png create mode 100644 network-poc/static/docs/images/replace_all.png create mode 100644 network-poc/static/docs/images/replace_all_cbd.png create mode 100644 network-poc/static/docs/images/replace_all_cbd_dep.png create mode 100644 network-poc/static/docs/images/replace_cbd_incorrect.png create mode 100644 network-poc/static/docs/images/replace_dep_cbd_dep.png create mode 100644 network-poc/static/docs/images/replace_one.png create mode 100644 network-poc/static/docs/images/resource-instance-change-lifecycle.png create mode 100644 network-poc/static/docs/images/simple_create.png create mode 100644 network-poc/static/docs/images/simple_destroy.png create mode 100644 network-poc/static/docs/images/simple_update.png create mode 100644 network-poc/static/docs/images/update_destroy_cbd.png create mode 100644 network-poc/static/docs/planning-behaviors.md create mode 100644 network-poc/static/docs/plugin-protocol/README.md create mode 100644 network-poc/static/docs/plugin-protocol/object-wire-format.md create mode 100644 network-poc/static/docs/plugin-protocol/releasing-new-version.md create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.0.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.1.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.10.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.2.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.3.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.4.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.5.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.6.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.7.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.8.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin5.9.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.0.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.1.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.10.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.2.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.3.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.4.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.5.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.6.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.7.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.8.proto create mode 100644 network-poc/static/docs/plugin-protocol/tfplugin6.9.proto create mode 100644 network-poc/static/docs/provider-references.md create mode 100644 network-poc/static/docs/resource-instance-change-lifecycle.md create mode 100644 network-poc/static/docs/state_encryption.md create mode 100644 network-poc/static/docs/tofu-cheatsheet.md create mode 100644 network-poc/static/docs/tracing.md create mode 100644 network-poc/static/docs/unicode.md diff --git a/network-poc/static/avatars/gecko_notext.png b/network-poc/static/avatars/gecko_notext.png new file mode 100644 index 0000000000000000000000000000000000000000..8968876253f67608438803fa70041f8b50667502 GIT binary patch literal 133307 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 uP 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 L(*Q=tzlHw;gRi c [dir=back]; + a -> b [dir=back]; + } +} +--> + +Order of operations: +1. `A` is created +1. `B` is created +1. `C` is created + +## Resource Updates + +An existing resource may be updated with references to a newly created +resource. The ordering here is exactly the same as one would expect for +creation. + +![Simple Resource Updates](./images/simple_update.png) + + +Order of operations: +1. `A` is created +1. `B` is created +1. `C` is created + +## Simple Resource Destruction + +The order for destroying resource is exactly the inverse used to create them. +This example shows the graph for the destruction of the same nodes defined +above. While destroy nodes will not contain attribute references, we will +continue to use the inverted edges showing dependencies for destroy, so the +operational ordering is still opposite the flow of the arrows. + +![Simple Resource Destruction](./images/simple_destroy.png) + + +Order of operations: +1. `C` is destroyed +1. `B` is destroyed +1. `A` is Destroyed + +## Resource Replacement + +Resource replacement is the logical combination of the above scenarios. Here we +will show the replacement steps involved when `B` depends on `A`. + +In this first example, we simultaneously replace both `A` and `B`. Here `B` is +destroyed before `A`, then `A` is recreated before `B`. + +![Replace All](./images/replace_all.png) + + +Order of operations: +1. `B` is destroyed +1. `A` is destroyed +1. `A` is created +1. `B` is created + + +This second example replaces only `A`, while updating `B`. Resource `B` is only +updated once `A` has been destroyed and recreated. + +![Replace Dependency](./images/replace_one.png) + + +Order of operations: +1. `A` is destroyed +1. `A` is created +1. `B` is updated + + +While the dependency edge from `B update` to `A destroy` isn't necessary in +these examples, it is shown here as an implementation detail which will be +mentioned later on. + +A final example based on the replacement graph; starting with the above +configuration where `B` depends on `A`. The graph is reduced to an update of +`A` while only destroying `B`. The interesting feature here is the remaining +dependency of `A update` on `B destroy`. We can derive this ordering of +operations from the full replacement example above, by replacing `A create` +with `A update` and removing the unused nodes. + +![Replace All](./images/destroy_then_update.png) + +## Create Before Destroy + +Currently, the only user-controllable method for changing the ordering of +create and destroy operations is with the `create_before_destroy` resource +`lifecycle` attribute. This has the obvious effect of causing a resource to be +created before it is destroyed when replacement is required, but has a couple +of other effects we will detail here. + +Taking the previous replacement examples, we can change the behavior of `A` to +be that of `create_before_destroy`. + +![Replace all, dependency is create_before_destroy](./images/replace_all_cbd_dep.png) + + + +Order of operations: +1. `B` is destroyed +2. `A` is created +1. `B` is created +1. `A` is destroyed + +Note that in this first example, the creation of `B` is inserted in between the +creation of `A` and the destruction of `A`. This becomes more important in the +update example below. + + +![Replace dependency, dependency is create_before_destroy](./images/replace_dep_cbd_dep.png) + + +Order of operations: +1. `A` is created +1. `B` is updated +1. `A` is destroyed + +Here we can see clearly how `B` is updated after the creation of `A` and before +the destruction of the _deposed_ resource `A`. (The prior resource `A` is +sometimes referred to as "deposed" before it is destroyed, to disambiguate it +from the newly created `A`.) This ordering is important for resource that +"register" other resources, and require updating before the dependent resource +can be destroyed. + +The transformation used to create these graphs is also where we use the extra +edges mentioned above connecting `B` to `A destroy`. The algorithm to change a +resource from the default ordering to `create_before_destroy` simply inverts +any incoming edges from other resources, which automatically creates the +necessary dependency ordering for dependent updates. This also ensures that +reduced versions of this example still adhere to the same ordering rules, such +as when the dependency is only being removed: + +![Update a destroyed create_before_destroy dependency](./images/update_destroy_cbd.png) + + +Order of operations: +1. `B` is updated +1. `A` is destroyed + +### Forced Create Before Destroy + +In the previous examples, only resource `A` was being used as is it were +`create_before_destroy`. The minimal graphs used show that it works in +isolation, but that is only when the `create_before_destroy` resource has no +dependencies of it own. When a `create_before_resource` depends on another +resource, that dependency is "infected" by the `create_before_destroy` +lifecycle attribute. + +This example demonstrates why forcing `create_before_destroy` is necessary. `B` +has `create_before_destroy` while `A` does not. If we only invert the ordering +for `B`, we can see that results in a cycle. + +![Incorrect create_before_destroy replacement](./images/replace_cbd_incorrect.png) + + +In order to resolve these cycles, all resources that precede a resource +with `create_before_destroy` must in turn be handled in the same manner. +Reversing the incoming edges to `A destroy` resolves the problem: + +![Correct create_before_destroy replacement](./images/replace_all_cbd.png) + + +Order of operations: +1. `A` is created +1. `B` is created +1. `B` is destroyed +1. `A` is destroyed + +This also demonstrates why `create_before_destroy` cannot be overridden when +it is inherited; changing the behavior here isn't possible without removing +the initial reason for `create_before_destroy`; otherwise cycles are always +introduced into the graph. diff --git a/network-poc/static/docs/diagnostics.md b/network-poc/static/docs/diagnostics.md new file mode 100644 index 0000000..46a5ffe --- /dev/null +++ b/network-poc/static/docs/diagnostics.md @@ -0,0 +1,495 @@ +# OpenTofu Diagnostics Guide + +"Diagnostics" is the general term we use to describe the error and warning +messages that OpenTofu returns when there are problems with the configuration, +or when interactions with external systems fail. + +This document is an overview of how we typically use diagnostics in OpenTofu. +It includes both some technical information about how we represent diagnostics +in code, and some more subjective information about the writing style we most +often use in diagnostic messages. + +## Diagnostics in Code + +Diagnostics are modelled using the types from +[the `tfdiags` package](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags). + +In particular: +- [`tfdiags.Diagnostics`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Diagnostics) + represents a set of zero or more diagnostics. + + A total lack of diagnostics is usually represented by a `nil` value of this + type. + + When constructing sets of diagnostics to return we typically don't worry + about the order they are returned in, even though we return them using a + slice type. The UI-layer code uses + [`tfdiags.Diagnostics.Sort`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Diagnostics.Sort) + to place all of the collected diagnostics into a predictable order before + rendering them, and so that function effectively turns the set of + diagnostics into an ordered list of diagnostics _just in time_. + +- [`tfdiags.Diagnostic`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Diagnostic) + is an interface type that all diagnostic values implement. + + In practice values of this type are often created automatically as an + implementation detail of [`Diagnostics.Append`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Diagnostics.Append), + which accepts various types that _don't_ directly implement + `Diagnostic` and then automatically wraps them in a type that does. + In particular: + + - We often use [`hcl.Diagnostic`](https://pkg.go.dev/github.com/hashicorp/hcl/v2#Diagnostic) + to describe problems related to the configuration or operations that are + strongly related to parts of the configuration, because it is the most + fully-fledged type of diagnostic we allow including support for source + ranges and relevant expressions as described later. + + It's also acceptable to append a whole `hcl.Diagnostics` (the HCL + equivalent of `tfdiags.Diagnostics`) in which case each diagnostic + will be wrapped and appended in turn. This is common when calling + HCL's own functions and passing on its diagnostics verbatim. + - Normal `error` values can be appended to a `tfdiags.Diagnostics`, but + that's mainly for historical reasons -- adapting code that was present + before the diagnostic models were added -- and should not be used in new + code because it typically results in low-quality diagnostics that don't + meet the style guidelines later in this document. + + One exception is for "should never happen" cases: we sometimes use + `error` directly in that case to avoid overwhelming the surrounding + code with the construction of a full diagnostic. + + Package `tfdiags` also includes some functions for constructing other kinds + of diagnostics, including: + + - [`tfdiags.Sourceless`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Sourceless) + is good for diagnostics that don't relate to any part of the configuration, + such as when reporting incorrect usage of a command line argument. + - [`tfdiags.AttributeValue`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#AttributeValue) and + [`tfdiags.WholeContainingBody`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#WholeContainingBody) + produce special "contextual diagnostics" that must be transformed by + calling [`InConfigBody`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Diagnostics.InConfigBody) + on the resulting `Diagnostics` value. This is a special mechanism used + when the subsystem generating the diagnostic does not have direct access + to the configuration itself, such as when a provider returns a diagnostic + via the provider wire protocol. +- [`tfdiags.Severity`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Severity) + (and its HCL equivalent [`hcl.DiagnosticSeverity`](https://pkg.go.dev/github.com/hashicorp/hcl/v2#DiagnosticSeverity)) + are how we distinguish between "error" and "warning" diagnostics. + + The `tfdiags.Diagnostics.HasErrors` method returns true if the diagnostics + contains at least one with the severity `tfdiags.Error`. + +The most common pattern for handling diagnostics in code is: +1. Declare `var diags tfdiags.Diagnostics` at the very start of a function. +2. During the function's body, whenever calling another function that might + produce its own diagnostics, capture them into a separate variable + (often called `moreDiags`, or `hclDiags` if the return type is + `hcl.Diagnostics`) and then immediately append them to the main `diags` + using `tfdiags.Diagnostics.Append`. + + If subsequent code depends on the success of the call, check + `moreDiags.HasErrors()` (or similar) and return early if it returns `true`. +3. If the function generates any diagnostics of its own, append them directly + to `diags`. +4. At all exit points of the function, return `diags` regardless of whether + it has been assigned to or whether it contains errors. This ensures that + we always return any warnings that might have been produced and avoids + the risk of missing certain return paths under future maintenance if we + introduce additional diagnostics later. + +Here's a code-example version of the above advice: + +```go +func Example() (anything, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics + + somethingElse, moreDiags := otherFunction() + diags = diags.Append(moreDiags) + if moreDiags.HasErrors() { + // NOTE: it isn't _always_ necessary to return immediately when there + // are errors, as long as the callee clearly documents what it + // guarantees about an errored result and the caller is able to + // work within those limitations. Collecting multiple errors to + // return together is often desirable. + // + // If the caller cannot continue at all though, or if continuing is + // likely to cause redundant errors that just restate the same problem + // in more confusing terms, then... + return nil, diags + } + if isProblematic(somethingElse) { + // A function might need to generate its own diagnostics if it detects + // a problem directly. + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + // ... + }) + return nil, diags + } + + // ... + + // The final return statement should include diags even if no errors + // were detected along the way, because it might contain warnings. + return something, diags +} +``` + +Some functions diverge from this pattern for special reasons, such as capturing +multiple sets of child function diagnostics and then using some logic to decide +which ones to append, or processing multiple items in a loop and appending +new diagnostics for each iteration. The above is just a general example of the +most common case, not a fixed template to follow in all cases. + +## Information in a Diagnostic + +The general model of `tfdiags.Diagnostic` has the following parts, though not +all implementations of the interface make use of all of them: + +- Severity: either `tfdiags.Error` or `tfdiags.Warning`. +- Description: the main human-readable text describing the problem. This + has the following fields: + + - Summary: A short, terse description of the general type of problem + that has occurred. + - Detail: A longer description of the problem, sometimes including multiple + paragraphs of information. + - Address: The address of some object that the error relates to, which + is most often a resource instance address. + + OpenTofu does not currently have a localized UI, so built-in diagnostics + always have their summary and detail written in US English. There's more + subjective guidance about the content of these fields in sections below. +- Source location information: optional references to parts of the configuration + that the problem relates to. This has the following fields: + + - Subject: source range for the part of the configuration that caused the + problem or that the problem is directly about. + - Context: optional source range of a larger section of configuration that + might make the cause of the problem easier to quickly understand if + included in the diagnostic message. The Context source range must always + contain the Subject source range within it. + + The UI uses the context and subject together to display a source code + snippet. The lines of code included in the snippet cover both the context + and the subject, and then the subject itself is rendered with an underline + if we're rendering into a terminal that supports that style. + + We don't use "context" very often, but it can be useful if the problem + we're describing is that just one part of a larger source element is + problematic. For example, if one of the operands to the `+` operator + isn't a number then that operand would be the "subject" but the entire + addition operation could be returned as "context", so that both of the + operands and the `+` symbol will definitely be included in the rendered + diagnostic too. +- Expression-related information: optional information about an expression whose + evaluation cause the problem. This has the following fields: + + - Expression: The `hcl.Expression` representing the expression itself. + - EvalContext: The `hcl.EvalContext` that the expression was being evaluated + in. + + The diagnostic renderer for the UI uses this information, when available, + to offer some extra hints about the values of any symbols that were used + in the expression, because it's often the dynamic values that cause a + problem, rather than the syntax used to obtain them. +- Extra info: this is a rather underspecified collection of assorted other + information that's only relevant in very specific contexts. Refer to the + `tfdiags` package documentation for more information. + + There's _some_ guidance on this later in this document, but it's focused + only on a few main cases. + +## Diagnostic Description Writing Style + +Although there is some variation in diagnostic writing style, particularly in +parts of the system like state storage backends which were originally written by +third-parties, most of the _built-in_ diagnostics follow a relatively consistent +writing style that is in turn based on the writing style used by HCL itself in +its own diagnostics, because HCL and OpenTofu diagnostics often mix together +in the same set of problems. + +The "summary" should typically be a very short and concise description of +what was wrong and what was wrong about it. Our summaries typically don't +include any user-chosen information such as symbol names, because that means a +particular kind of problem is always described using the same text and so +readers can become familiar enough with the summaries of problems they see +frequently to skip reading the rest of the diagnostic when skimming. + +The following are some real examples of summaries currently used across both +HCL and OpenTofu: + +- Unsupported operator +- Duplicate argument +- Invalid index +- Unexpected end of template +- Invalid template interpolation value +- Invalid default value for variable +- Required variable not set +- Invalid "count" attribute + +The "detail" text is where we tend to put most of the information, and so +there's a lot more variation here but ideally a good diagnostic detail +should mention the following information, usually in the following order: + +- What was wrong and what was wrong about it: similar to the summary but this + time including information about specifically what was wrong, such as the + name of the input variable whose default value was invalid. +- Why the situation is problematic, if knowing that relies on some + characteristic of OpenTofu's design that might not be obvious to a newcomer. +- What should be done to fix it, or (if it's unclear what the author's intention + was) a question-sentence that implies a _possible_ solution, often starting + with the words "Did you mean" and ending with a question mark. + +While the summary message is often terse and uses only minimal punctuation, +the detail message should always be written in full sentences including +end-of-sentence punctuation (`.`, `?`). If "what was wrong about it" is +coming from the string representation of an `error` value, we typically +present it with a prefix ending with a colon and then append a period `.` +after the error string, and format the error itself using `tfdiags.FormatError`, +like this: + +```go + Detail: fmt.Sprintf("Unsuitable value for thingy: %s.", tfdiags.FormatError(err)) +``` + +If the second and third items in the above take more than a few words, it's +helpful to split them into their own paragraphs for easier scanning. When +writing multiple paragraphs in a detail message they should be separated by +`\n\n` -- two newline characters. + +In many cases our diagnostics only include a subset of this information because +either the reason why it's problematic is relatively clear or because we don't +have any specific suggestion for how to solve the problem, but the following +is an example of a real diagnostic message from OpenTofu at the time of writing +this documentation which includes all of these parts: + +``` +Error: Invalid for_each argument + +The "for_each" map includes keys derived from resource attributes that cannot +be determined until apply, and so OpenTofu cannot determine the full set of keys +that will identify the instances of this resource. + +When working with unknown values in for_each, it's better to define the map keys +statically in your configuration and place apply-time results only in the map +values. + +Alternatively, you could use the planning option -exclude=aws_instance.example +to first apply without this object, and then apply normally to converge. +``` + +The text immediately after "Error:" above is the summary for this diagnostic. +The paragraphs that follow are all a single "detail" string. + +That was a particularly extreme diagnostic message with lots of information to +communicate. Most diagnostics are not so complicated; the following is an +example with less information to communicate: + +``` +Error: Invalid value for input variable + +The given value is not suitable for var.example declared +at example.tf:12,1: a string is required. +``` + +This example also illustrates a situation where there are two different source +locations that could be relevant: the input variable's declaration or the +expression that's used to define its value. Because this message is talking +about a problem with the _value_, the diagnostic should have the source +"Subject" set to the expression that defined it, but it also mentions the +location of the declaration as part of the detail text as some additional +context. + +Some other notes about some other specific situations that arise sometimes: + +- If a diagnostic message includes a suggestion for a shell command to run + or a URL to visit for more information, use a paragraph that ends with a + colon, followed by a single newline, four spaces for indentation, and then the + command or URL: + + ``` + To view the root module output values, run: + tofu output + ``` + + The goal of this formatting is to make it very clear what part of the + message is intended to be copied and used elsewhere, by placing it on a + line of its own without any surrounding punctuation. The indented text + should ideally be formatted so that the user can copy it _verbatim_ into + whatever place it will be used. + + The diagnostic renderer also has a special case where it will not try to + word-wrap a line that begins with spaces, and so this layout has the + useful side-effect of avoiding introducing extra newline characters into + a command line that is intended to be copied. + +- There are some terminology choices we use to refer to some OpenTofu-specific + ideas and concepts that disagree slightly with terminology used in the code. + These differences are the result of learning from feedback from folks who + had been confused by the original terminology, even though the code still + often uses the original terminology: + + - Instead of referring to "unknown values" or "computed values" we say that + values are "known after apply" or "cannot be determined until apply". + - In HCL the word "variable" means anything that's available to refer to + in the current evaluation context, which is confusing because OpenTofu + itself uses that word to refer only to input variables. + + Sometimes messages are generated by HCL itself and so it's unavoidably + confusing, but when we're generating messages _inside OpenTofu_ we + use the two words "input variable" to refer to an input variable, + and "symbol" or "object" (depending on whether we're talking about + the name itself or what the name refers to) as the general word for + something you can refer to in an expression. + - For consistency with our use of "input variable" to distinguish from + HCL's more general meaning of "variable", we also tend to write + "local value" and "output value" when referring to those concepts, rather + than using the shorthands "locals" and "outputs". + - HCL distinguishes between "attributes" meaning the named keys inside an + object type, and "arguments" meaning the names used for individual + settings inside a configuration block. + + OpenTofu itself uses those words a little more interchangeably because + in _many_ cases the configuration arguments in a block directly + correspond to the attributes of an object created by evaluating that + block. + + However, if a particular error message is talking about a configuration + setting inside a block it's better to use "argument" rather than + "attribute" because that's then consistent with error messages that + HCL itself might generate. + + Go uses the term "field" to describe an element of a struct type, and + JavaScript and JSON use the word "property" to describe an element of + an object type. We don't use either of those words in OpenTofu: the + elements of an object are its _attributes_, and the settings available + in a configuration block are its _arguments_. The string values that + identify elements of a map are called "keys". + - The `cty` terminology "marks" or "value marks" refers to an implementation + detail that should never be mentioned directly in an error message. + + Instead, we use specific terminology related to what each mark type + is representing: "sensitive values", "ephemeral values", etc. + - `aws_instance` is an example of a "resource _type_", not of a "resource", + even though the provider protocol uses the single noun "resource" to refer + to both ideas. + + A "resource" is what's declared by a `resource`, `data`, or `ephemeral` + block. A "resource _instance_" is what such a block can declare zero + or more of, when using the `count`, `for_each`, or `enabled` arguments. + - Although there are certainly some historical diagnostic messages that + predate this adjustment of terminology, new error messages should use + "managed resource" to refer to the kind of resource that's declared + using a `resource` block, "data resource" for `data` blocks, and + "ephemeral resource" for an `ephemeral` block. + + In the code we refer to these three as "resource _modes_", but that is + internal terminology that should never appear in a diagnostic message. +- When a file or directory path appears as part of a diagnostic message, it + should typically be presented relative to the current working directory and + should use the syntax conventions of the platform where OpenTofu is running. + + In particular, we return paths using backslashes as the separator when we + are running on Windows, but normal slashes otherwise. Using the Go + `filepath` package is a good way to get this right, though you might need + to add some complexity to your tests to make them pass on all platforms. +- If an error message is describing a "should never happen" case, we typically + end the detail string with the sentence "This is a bug in OpenTofu.". This + hopefully prompts the reader that this wasn't directly caused by something + they did, and so they should probably open a bug report in the + OpenTofu repository instead of just trying to solve it themselves. + + For this kind of error message we often relax our preference against + mentioning implementation details in the error message, because the most + likely next step is for the user to copy-paste the entire message into their + bug report text and so the final reader of the message is OpenTofu + maintainers rather than OpenTofu users. + + For example, it can be okay to use internal terminology like "cty marks" and + use the `GoString` representations of values in a "This is a bug in + OpenTofu" detail message, if that's the most concise way to capture the + information the OpenTofu maintainers would need to debug the problem. + +## Diagnostics caused by unknown or sensitive values + +When a diagnostic has expression information associated with it, the diagnostic +renderer for the UI includes some additional information about the values +that were in scope, like this: + +``` + var.greeting is "Hello" + var.items is list of string with 5 elements +``` + +By default, this renderer will not mention any symbol which refers to an unknown +or sensitive value. That was not historically true: originally, this could +say something like "var.example is a string, known only after apply". + +Those who are less familiar with these concepts often misunderstood the +"known only after apply" part of the message as being _the problem itself_, +rather than just context to help diagnose the problem, and so the UI no longer +mentions "unknown-ness" or "sensitive-ness" in most cases. + +However, there are some diagnostics messages that _are_ directly caused by the +presence of an unknown or sensitive value, in which case it's helpful to +mention that in the summary of values that were in scope. + +To allow for this, we set the "extra info" field of a diagnostic to contain +an implementation of one of the following interfaces: + +- [`tfdiags.DiagnosticExtraBecauseUnknown`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#DiagnosticExtraBecauseUnknown) + for a problem that's caused by an unknown value. + + (Remember that the _text_ of the error message should refer to this as "known + only after apply", or similar.) +- [`tfdiags.DiagnosticExtraBecauseSensitive`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#DiagnosticExtraBecauseSensitive) + for situations where a sensitive value was used in a location that OpenTofu + cannot permit it, such as in the instance key of a resource instance. + +These extra markers should be used only when mentioning the unknown or sensitive +values in the diagnostic message is likely to help with debugging a problem. +If the problem is not directly caused by unknown or sensitive values then +neither of these should be used, to avoid creating a distracting +[red herring](https://en.wikipedia.org/wiki/Red_herring) for the reader. + +## Consolidation of Diagnostics + +The UI layer has some special rules for finding sets of similar diagnostics +and showing them as just a single diagnostic referring to the first example +of a problem, with a short extra note about how many other similar diagnostics +there are. + +``` +(and 2 similar warnings elsewhere) +``` + +The main implementation of this behavior is in +[`tfdiags.Diagnostics.Consolidate`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Diagnostics.Consolidate), +but we allow end-users to customize (using command line options) whether this +consolidation applies to errors or warnings separately. By default, we +consolidate only warnings. + +For a severity that is subject to consolidation, the main behavior is to group +together diagnostics that have the same "summary" text, and this is part of +why we tend to use terse, fixed strings in the summary field. + +There are two extra mechanisms for customizing this behavior for specific +diagnostic messages: + +- If the "extra info" of a diagnostic contains an implementation of + [`tfdiags.DiagnosticExtraDoNotConsolidate`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#DiagnosticExtraDoNotConsolidate) + then that diagnostic is not eligible for consolidation at all, regardless + of how similar it might be to other diagnostics in the same set. +- If the "extra info" of a diagnostic contains an implementation of + [`tfdiags.Keyable`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tfdiags#Keyable) + then the string returned by its `ExtraInfoKey` method is used _in addition to_ + the summary text for deciding what to consolidate. + + For example, if there were three warnings with the same summary text but + two of them have the same `ExtraInfoKey` and the third has a different + one then only the first two would be able to consolidate. + + The `ExtraInfoKey` is an internal key used for comparison only and is never + exposed in the UI, so it can be set to whatever makes sense to define + separate consolidation groups for diagnostics with a specific summary. diff --git a/network-poc/static/docs/glossary.md b/network-poc/static/docs/glossary.md new file mode 100644 index 0000000..b94cd0f --- /dev/null +++ b/network-poc/static/docs/glossary.md @@ -0,0 +1,78 @@ +# OpenTofu glossary +This document is intended for anyone who wants to gain more knowledge about the terms and vocabulary used to talk about different concepts in OpenTofu. + +> [!NOTE] +> This was created with the intent of gathering more knowledge over time. +> The state that you find this in right now could be incomplete. +> Once you discover and learn about a new concept that would benefit others, +> feel free to open a PR to update this. + +> [!NOTE] +> When adding new content to this document, try to place it in such a way to match the alphabetical order of the already existing content. +> +> Optionally, also add a reference link if possible (GitHub conversation, issue, other docs, etc). + +## OpenTofu +### Attribute/argument/field +* Attribute - a named key inside an object type. +* Argument - a name used for an individual setting inside a configuration block. + +It is recommended to avoid using popular programming language terms such as "field" or "property" to describe an element of an object in OpenTofu. + +Reference: [link](./diagnostics.md#diagnostic-description-writing-style) + +### Data sources/data resource +* Data source - the remote thing that the data resource reads from. +* Data resource - refers to a block of type `data`, and the associated object it declares. +* Data resource type - is what is represented by the first label in a `data` block header, and the associated declarations and code for it in the provider plugin. + +Reference: [link](https://github.com/opentofu/opentofu/pull/3389#discussion_r2440264786) + +### Diagnostic +"Diagnostic" is the general term we use to describe the error or warning +message that OpenTofu returns when there are problems with the configuration, +or when interactions with external systems fail. + +Reference: [link](./diagnostics.md) + +### Mark/value mark +OpenTofu uses cty.Value to represent the result of expressions (and other data). +Occasionally, we will want to annotate that data with additional properties, without actually modifying the underlying value. +Marks are used for that purpose and are the preferred method of doing so with go-cty. + +### Resource/resource instance/resource type +* Resource - is what is declared by a `resource`, `data` or `ephemeral` block. +* Resource instance - is what such a block can declare zero or more of, when using the `count`, `for_each`, or `enabled` arguments. +* Resource type - the type of a "resource". E.g., `aws_instance` is a "resource type". + +It is recommended to use the following terms when discussing about "resource" blocks: +* managed resource - a block declared as `resource "type" "name" {}` +* data resource - a block declared as `data "type" "name" {}` +* ephemeral resource - a block declared as `ephemeral "type" "name" {}` + +Reference: [link](./diagnostics.md#diagnostic-description-writing-style) + +### Unknown value/Computed value +* Unknown value - Unknown values are the result of expressions that have unknown inputs. E.g.: a value that will not be known until a resource is created. + Right now the main source of this type of values is resources, but we are considering adding others like unknown inputs. + Another place where an unknown value can be encountered is from using some of the built-in functions like `timestamp`, `bcrypt` and `uuid`. +* Computed value - Computed is more of a resource specific concept that a provider can specify in its resource schema. + When set to true, the provider does not expect a value and may instead produce one that may or may not be unknown. + With other flags, the actual functionality is a bit more subtle. + +References: [link](https://github.com/opentofu/opentofu/blob/490762343322eff42c0586f7a4c267b579fe80ef/internal/configs/configschema/schema.go#L65), [link](https://github.com/opentofu/opentofu/blob/490762343322eff42c0586f7a4c267b579fe80ef/internal/lang/functions.go#L22) +## HCL +### Evaluation context (HCL) +A set of already known functions, input values, local values, resources, etc. that is used to evaluate an expression that can reference any of the concepts listed above. + +The list of concepts above, in the context of HCL evaluation, are called [variables](#variable-hcl). + +### Expression +An expression is any right hand side of an assignment that will be evaluated to generate the value that will be associated with key on the left hand side of the assignment. +The simplest expressions are just literal values, like "hello" or 5, but the OpenTofu language also allows more complex +expressions such as references to data exported by resources, arithmetic, conditional evaluation, and a number of built-in and provider-defined functions. + +Reference: [link](https://opentofu.org/docs/language/expressions/) + +### Variable (HCL) +Anything that's available to refer to in the current evaluation context. \ No newline at end of file diff --git a/network-poc/static/docs/images/architecture-overview.png b/network-poc/static/docs/images/architecture-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..146cc48010b178541dfe4a604fa48c256021c700 GIT binary patch literal 233067 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%0AazJVqp1-5}mB%@BIYm2;FF;g86%_lgmE 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

e3V2qs@tL{ zm5)$?uR);KBL4jm;-^6oMckJ{`YoR}Uv+k(C!{93k7nUnZG+x8)IgccbC>0G?nvTC z%WcMWqsuL1-col_r@Rt&Xi0Ck&`b4pwoy2>xQHPkVCoICAwZ`@-!H--`Fe?uB(=?-5Fln7YI zuf?RhYyTc(a{TSb2hAnXE?WY>Lu+y+-`S6_*?U8

tWC@fISY=TS2REO_sEr`~c^ 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 P0i~*V2U8;d=+*xLrDoGG literal 0 HcmV?d00001 diff --git a/network-poc/static/docs/images/replace_all_cbd.png b/network-poc/static/docs/images/replace_all_cbd.png new file mode 100644 index 0000000000000000000000000000000000000000..da72fe483f60836c389bd952e303411b71e6dcbb GIT binary patch literal 12469 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 B>5l*a literal 0 HcmV?d00001 diff --git a/network-poc/static/docs/images/replace_all_cbd_dep.png b/network-poc/static/docs/images/replace_all_cbd_dep.png new file mode 100644 index 0000000000000000000000000000000000000000..98bdbde68a0640affdfa97c7877267774077c5a2 GIT binary patch literal 13707 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 literal 0 HcmV?d00001 diff --git a/network-poc/static/docs/images/replace_cbd_incorrect.png b/network-poc/static/docs/images/replace_cbd_incorrect.png new file mode 100644 index 0000000000000000000000000000000000000000..72591d0362bba96d88a21e224e3d6434ad188250 GIT binary patch literal 12577 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 literal 0 HcmV?d00001 diff --git a/network-poc/static/docs/images/replace_one.png b/network-poc/static/docs/images/replace_one.png new file mode 100644 index 0000000000000000000000000000000000000000..fe1aa1dbf37ba9a34c5127246ee0a597d313a36c GIT binary patch literal 13026 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 UlZE>6p%s$aDQ$AD;>FwlA4-{uMF0Q* literal 0 HcmV?d00001 diff --git a/network-poc/static/docs/images/resource-instance-change-lifecycle.png b/network-poc/static/docs/images/resource-instance-change-lifecycle.png new file mode 100644 index 0000000000000000000000000000000000000000..b6cf16e4fa5b894acb44eaf9cd5c9b45d9086a7f GIT binary patch literal 199031 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 OLbtRGHNUFcz5E|pOo9af literal 0 HcmV?d00001 diff --git a/network-poc/static/docs/images/simple_destroy.png b/network-poc/static/docs/images/simple_destroy.png new file mode 100644 index 0000000000000000000000000000000000000000..be2e8fcd4c4025507f6a0afce04231b86e4beca0 GIT binary patch literal 5921 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 Xj*Ovboh=x2-Vkkd1GO?$+pzxuDyETM literal 0 HcmV?d00001 diff --git a/network-poc/static/docs/images/simple_update.png b/network-poc/static/docs/images/simple_update.png new file mode 100644 index 0000000000000000000000000000000000000000..ada18b270dc1646a612068819938a08304ad131f GIT binary patch literal 8256 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 AS^xk5 literal 0 HcmV?d00001 diff --git a/network-poc/static/docs/planning-behaviors.md b/network-poc/static/docs/planning-behaviors.md new file mode 100644 index 0000000..0fcd0a9 --- /dev/null +++ b/network-poc/static/docs/planning-behaviors.md @@ -0,0 +1,294 @@ +# Planning Behaviors + +A key design tenet for OpenTofu is that any actions with externally-visible +side-effects should be carried out via the standard process of creating a +plan and then applying it. Any new features should typically fit within this +model. + +There are also some historical exceptions to this rule, which we hope to +supplement with plan-and-apply-based equivalents over time. + +This document describes the default planning behavior of OpenTofu in the +absence of any special instructions, and also describes the three main +design approaches we can choose from when modelling non-default behaviors that +require additional information from outside OpenTofu Core. + +This document focuses primarily on actions relating to _resource instances_, +because that is OpenTofu's main concern. However, these design principles can +potentially generalize to other externally-visible objects, if we can describe +their behaviors in a way comparable to the resource instance behaviors. + +This is developer-oriented documentation rather than user-oriented +documentation. See +[the main OpenTofu documentation](https://opentofu.org/docs) for +information on existing planning behaviors and other behaviors as viewed from +an end-user perspective. + +## Default Planning Behavior + +When given no explicit information to the contrary, OpenTofu Core will +automatically propose taking the following actions in the appropriate +situations: + +- **Create**, if either of the following are true: + - There is a `resource` block in the configuration that has no corresponding + managed resource in the prior state. + - There is a `resource` block in the configuration that is recorded in the + prior state but whose `count` or `for_each` argument (or lack thereof) + describes an instance key that is not tracked in the prior state. +- **Delete**, if either of the following are true: + - There is a managed resource tracked in the prior state which has no + corresponding `resource` block in the configuration. + - There is a managed resource tracked in the prior state which has a + corresponding `resource` block in the configuration _but_ its `count` + or `for_each` argument (or lack thereof) lacks an instance key that is + tracked in the prior state. +- **Update**, if there is a corresponding resource instance both declared in the + configuration (in a `resource` block) and recorded in the prior state + (unless it's marked as "tainted") but there are differences between the prior + state and the configuration which the corresponding provider doesn't + explicitly classify as just being normalization. +- **Replace**, if there is a corresponding resource instance both declared in + the configuration (in a `resource` block) and recorded in the prior state + _marked as "tainted"_. The special "tainted" status means that the process + of creating the object failed partway through and so the existing object does + not necessarily match the configuration, so OpenTofu plans to replace it + in order to ensure that the resulting object is complete. +- **Read**, if there is a `data` block in the configuration. + - If possible, OpenTofu will eagerly perform this action during the planning + phase, rather than waiting until the apply phase. + - If the configuration contains at least one unknown value, or if the + data resource directly depends on a managed resource that has any change + proposed elsewhere in the plan, OpenTofu will instead delay this action + to the apply phase so that it can react to the completion of modification + actions on other objects. +- **No-op**, to explicitly represent that OpenTofu considered a particular + resource instance but concluded that no action was required. + +The **Replace** action described above is really a sort of "meta-action", which +OpenTofu expands into separate **Create** and **Delete** operations. There are +two possible orderings, and the first one is the default planning behavior +unless overridden by a special planning behavior as described later. The +two possible lowerings of **Replace** are: +1. **Delete** then **Create**: first delete the existing object bound to an + instance, and then create a new object at the same address based on the + current configuration. +2. **Create** then **Delete**: mark the existing object bound to an instance as + "deposed" (still exists but not current), create a new current object at the + same address based on the current configuration, and then delete the deposed + object. + +## Special Planning Behaviors + +For the sake of this document, a "special" planning behavior is one where +OpenTofu Core will select a different action than the defaults above, +based on explicit instructions given either by a module author, an operator, +or a provider. + +There are broadly three different design patterns for special planning +behaviors, and so each "special" use-case will typically be met by one or more +of the following depending on which stakeholder is activating the behavior: + +- [Configuration-driven Behaviors](#configuration-driven-behaviors) are + activated by additional annotations given in the source code of a module. + + This design pattern is good for situations where the behavior relates to + a particular module and so should be activated for anyone using that + module. These behaviors are therefore specified by the module author, such + that any caller of the module will automatically benefit with no additional + work. +- [Provider-driven Behaviors](#provider-driven-behaviors) are activated by + optional fields in a provider's response when asked to help plan one of the + default actions given above. + + This design pattern is good for situations where the behavior relates to + the behavior of the remote system that a provider is wrapping, and so from + the perspective of a user of the provider the behavior should appear + "automatic". + + Because these special behaviors are activated by values in the provider's + response to the planning request from OpenTofu Core, behaviors of this + sort will typically represent "tweaks" to or variants of the default + planning behaviors, rather than entirely different behaviors. +- [Single-run Behaviors](#single-run-behaviors) are activated by explicitly + setting additional "plan options" when calling OpenTofu Core's plan + operation. + + This design pattern is good for situations where the direct operator of + OpenTofu needs to do something exceptional or one-off, such as when the + configuration is correct but the real system has become degraded or damaged + in a way that OpenTofu cannot automatically understand. + + However, this design pattern has the disadvantage that each new single-run + behavior type requires custom work in every wrapping UI or automaton around + OpenTofu Core, in order provide the user of that wrapper some way + to directly activate the special option, or to offer an "escape hatch" to + use OpenTofu CLI directly and bypass the wrapping automation for a + particular change. + +We've also encountered use-cases that seem to call for a hybrid between these +different patterns. For example, a configuration construct might cause OpenTofu +Core to _invite_ a provider to activate a special behavior, but let the +provider make the final call about whether to do it. Or conversely, a provider +might advertise the possibility of a special behavior but require the user to +specify something in the configuration to activate it. The above are just +broad categories to help us think through potential designs; some problems +will require more creative combinations of these patterns than others. + +### Configuration-driven Behaviors + +Within the space of configuration-driven behaviors, we've encountered two +main sub-categories: +- Resource-specific behaviors, whose effect is scoped to a particular resource. + The configuration for these often lives inside the `resource` or `data` + block that declares the resource. +- Global behaviors, whose effect can span across more than one resource and + sometimes between resources in different modules. The configuration for + these often lives in a separate location in a module, such as a separate + top-level block which refers to other resources using the typical address + syntax. + +The following is a non-exhaustive list of existing examples of +configuration-driven behaviors, selected to illustrate some different variations +that might be useful inspiration for new designs: + +- The `ignore_changes` argument inside `resource` block `lifecycle` blocks + tells OpenTofu that if there is an existing object bound to a particular + resource instance address then OpenTofu should ignore the configured value + for a particular argument and use the corresponding value from the prior + state instead. + + This can therefore potentially cause what would've been an **Update** to be + a **No-op** instead. +- The `replace_triggered_by` argument inside `resource` block `lifecycle` + blocks can use a proposed change elsewhere in a module to force OpenTofu + to propose one of the two **Replace** variants for a particular resource. +- The `create_before_destroy` argument inside `resource` block `lifecycle` + blocks only takes effect if a particular resource instance has a proposed + **Replace** action. If not set or set to `false`, OpenTofu will decompose + it to **Destroy** then **Create**, but if set to `true` OpenTofu will use + the inverted ordering. + + Because OpenTofu Core will never select a **Replace** action automatically + by itself, this is an example of a hybrid design where the config-driven + `create_before_destroy` combines with any other behavior (config-driven or + otherwise) that might cause **Replace** to customize exactly what that + **Replace** will mean. +- Top-level `moved` blocks in a module activate a special behavior during the + planning phase, where OpenTofu will first try to change the bindings of + existing objects in the prior state to attach to new addresses before running + the normal planning process. This therefore allows a module author to + document certain kinds of refactoring so that OpenTofu can update the + state automatically once users upgrade to a new version of the module. + + This special behavior is interesting because it doesn't _directly_ change + what actions OpenTofu will propose, but instead it adds an extra + preparation step before the typical planning process which changes the + addresses that the planning process will consider. It can therefore + _indirectly_ cause different proposed actions for affected resource + instances, such as transforming what by default might've been a **Delete** + of one instance and a **Create** of another into just a **No-op** or + **Update** of the second instance. + + This one is an example of a "global behavior", because at minimum it + affects two resource instance addresses and, if working with whole resource + or whole module addresses, can potentially affect a large number of resource + instances all at once. + +### Provider-driven Behaviors + +Providers get an opportunity to activate some special behaviors for a particular +resource instance when they respond to the `PlanResourceChange` function of +the provider plugin protocol. + +When OpenTofu Core executes this RPC, it has already selected between +**Create**, **Delete**, or **Update** actions for the particular resource +instance, and so the special behaviors a provider may activate will typically +serve as modifiers or tweaks to that base action, and will not allow +the provider to select another base action altogether. The provider wire +protocol does not talk about the action types explicitly, and instead only +implies them via other content of the request and response, with OpenTofu Core +making the final decision about how to react to that information. + +The following is a non-exhaustive list of existing examples of +provider-driven behaviors, selected to illustrate some different variations +that might be useful inspiration for new designs: + +- When the base action is **Update**, a provider may optionally return one or + more paths to attributes which have changes that the provider cannot + implement as an in-place update due to limitations of the remote system. + + In that case, OpenTofu Core will replace the **Update** action with one of + the two **Replace** variants, which means that from the provider's + perspective the apply phase will really be two separate calls for the + decomposed **Create** and **Delete** actions (in either order), rather + than **Update** directly. +- When the base action is **Update**, a provider may optionally return a + proposed new object where one or more of the arguments has its value set + to what was in the prior state rather than what was set in the configuration. + This represents any situation where a remote system supports multiple + different serializations of the same value that are all equivalent, and + so changing from one to another doesn't represent a real change in the + remote system. + + If all of those taken together causes the new object to match the prior + state, OpenTofu Core will treat the update as a **No-op** instead. + +Of the three genres of special behaviors, provider-driven behaviors is the one +we've made the least use of historically but one that seems to have a lot of +opportunities for future exploration. Provider-driven behaviors can often be +ideal because their effects appear as if they are built in to OpenTofu so +that "it just works", with OpenTofu automatically deciding and explaining what +needs to happen and why, without any special effort on the user's part. + +### Single-run Behaviors + +OpenTofu Core's "plan" operation takes a set of arguments that we collectively +call "plan options", that can modify OpenTofu's planning behavior on a per-run +basis without any configuration changes or special provider behaviors. + +As noted above, this particular genre of designs is the most burdensome to +implement because any wrapping software that can ask OpenTofu Core to create +a plan must ideally offer some way to set all of the available planning options, +or else some part of OpenTofu's functionality won't be available to anyone +using that wrapper. + +However, we've seen various situations where single-run behaviors really are the +most appropriate way to handle a particular use-case, because the need for the +behavior originates in some process happening outside of the scope of any +particular OpenTofu module or provider. + +The following is a non-exhaustive list of existing examples of +single-run behaviors, selected to illustrate some different variations +that might be useful inspiration for new designs: + +- The "replace" planning option specifies zero or more resource instance + addresses. + + For any resource instance specified, OpenTofu Core will transform any + **Update** or **No-op** action for that instance into one of the + **Replace** actions, thereby allowing an operator to respond to something + having become degraded in a way that OpenTofu and providers cannot + automatically detect and force OpenTofu to replace that object with + a new one that will hopefully function correctly. +- The "refresh only" planning mode ("planning mode" is a single planning option + that selects between a few mutually-exclusive behaviors) forces OpenTofu + to treat every resource instance as **No-op**, regardless of what is bound + to that address in state or present in the configuration. + +## Legacy Operations + +Some of the legacy operations OpenTofu CLI offers that _aren't_ integrated +with the plan and apply flow could be thought of as various degenerate kinds +of single-run behaviors. Most don't offer any opportunity to preview an effect +before applying it, but do meet a similar set of use-cases where an operator +needs to take some action to respond to changes to the context OpenTofu is +in rather than to the OpenTofu configuration itself. + +Most of these legacy operations could therefore most readily be translated to +single-run behaviors, but before doing so it's worth researching whether people +are using them as a workaround for missing configuration-driven and/or +provider-driven behaviors. A particular legacy operation might be better +replaced with a different sort of special behavior, or potentially by multiple +different special behaviors of different genres if it's currently serving as +a workaround for many different unmet needs. diff --git a/network-poc/static/docs/plugin-protocol/README.md b/network-poc/static/docs/plugin-protocol/README.md new file mode 100644 index 0000000..65fda33 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/README.md @@ -0,0 +1,213 @@ +# OpenTofu Plugin Protocol + +This directory contains documentation about the physical wire protocol that +OpenTofu Core uses to communicate with provider plugins. + +Most providers are not written directly against this protocol. Instead, prefer +to use an SDK that implements this protocol and write the provider against +the SDK's API. + +---- + +**If you want to write a plugin for OpenTofu, please refer to +[Extending OpenTofu](https://github.com/hashicorp/terraform-docs-common) instead.** + +This documentation is for those who are developing _OpenTofu SDKs_, rather +than those implementing plugins. + +---- + +From OpenTofu v0.12.0 onwards, OpenTofu's plugin protocol is built on +[gRPC](https://grpc.io/). This directory contains `.proto` definitions of +different versions of OpenTofu's protocol. + +Only `.proto` files published as part of OpenTofu release tags are actually +official protocol versions. If you are reading this directory on the `main` +branch or any other development branch then it may contain protocol definitions +that are not yet finalized and that may change before final release. + +## RPC Plugin Model + +OpenTofu plugins are normal executable programs that, when launched, expose +gRPC services on a server accessed via the loopback interface. OpenTofu Core +discovers and launches plugins, waits for a handshake to be printed on the +plugin's `stdout`, and then connects to the indicated port number as a +gRPC client. + +For this reason, we commonly refer to OpenTofu Core itself as the plugin +"client" and the plugin program itself as the plugin "server". Both of these +processes run locally, with the server process appearing as a child process +of the client. OpenTofu Core controls the lifecycle of these server processes +and will terminate them when they are no longer required. + +The startup and handshake protocol is not currently documented. We hope to +document it here or to link to external documentation on it in future. + +## Versioning Strategy + +The Plugin Protocol uses a versioning strategy that aims to allow gradual +enhancements to the protocol while retaining compatibility, but also to allow +more significant breaking changes from time to time while allowing old and +new plugins to be used together for some period. + +The versioning strategy described below was introduced with protocol version +5.0 in OpenTofu v0.12. Prior versions of OpenTofu and prior protocol versions +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. + +### Major and minor versioning + +The minor version increases for each change introducing optional new +functionality that can be ignored by implementations of prior versions. For +example, if a new field were added to an response message, it could be a minor +release as long as OpenTofu Core can provide some default behavior when that +field is not populated. + +The major version increases for any significant change to the protocol where +compatibility is broken. However, OpenTofu Core and an SDK may both choose +to support multiple major versions at once: the plugin handshake includes a +negotiation step where client and server can work together to select a +mutually-supported major version. + +The major version number is encoded into the protobuf package name: major +version 5 uses the package name `tfplugin5`, and one day major version 6 +will switch to `tfplugin6`. This change of name allows a plugin server to +implement multiple major versions at once, by exporting multiple gRPC services. +Minor version differences rely instead on feature-detection mechanisms, so they +are not represented directly on the wire and exist primarily as a human +communication tool to help us easily talk about which software supports which +features. + +## Version compatibility for Core, SDK, and Providers + +A particular version of OpenTofu Core has both a minimum minor version it +requires and a maximum major version that it supports. A particular version of +OpenTofu Core may also be able to optionally use a newer minor version when +available, but fall back on older behavior when that functionality is not +available. + +Likewise, each provider plugin release is compatible with a set of versions. +The compatible versions for a provider are a list of major and minor version +pairs, such as "4.0", "5.2", which indicates that the provider supports the +baseline features of major version 4 and supports major version 5 including +the enhancements from both minor versions 1 and 2. This provider would +therefore be compatible with a OpenTofu Core release that supports only +protocol version 5.0, since major version 5 is supported and the optional +5.1 and 5.2 enhancements will be ignored. + +If OpenTofu Core and the plugin do not have at least one mutually-supported +major version, OpenTofu Core will return an error from `tofu init` +during plugin installation: + +``` +Provider "aws" v1.0.0 is not compatible with OpenTofu v0.12.0. + +Provider version v2.0.0 is the earliest compatible version. +Select it with the following version constraint: + + version = "~> 2.0.0" +``` + +``` +Provider "aws" v3.0.0 is not compatible with OpenTofu v0.12.0. +Provider version v2.34.0 is the latest compatible version. Select +it with the following constraint: + + version = "~> 2.34.0" + +Alternatively, upgrade to the latest version of OpenTofu for compatibility with newer provider releases. +``` + +The above messages are for plugins installed via `tofu init` from a +OpenTofu registry, where the registry API allows OpenTofu Core to recognize +the protocol compatibility for each provider release. For plugins that are +installed manually to a local plugin directory, OpenTofu Core has no way to +suggest specific versions to upgrade or downgrade to, and so the error message +is more generic: + +``` +The installed version of provider "example" is not compatible with OpenTofu v0.12.0. + +This provider was loaded from: + /usr/local/bin/terraform-provider-example_v0.1.0 +``` + +## Adding/removing major version support in SDK and Providers + +The set of supported major versions is decided by the SDK used by the plugin. +Over time, SDKs will add support for new major versions and phase out support +for older major versions. + +In doing so, the SDK developer passes those capabilities and constraints on to +any provider using their SDK, and that will in turn affect the compatibility +of the plugin in ways that affect its semver-based version numbering: + +- If an SDK upgrade adds support for a new provider protocol, that will usually + be considered a new feature and thus warrant a new minor version. +- If an SDK upgrade removes support for an old provider protocol, that is + always a breaking change and thus requires a major release of the provider. + +For this reason, SDK developers must be clear in their release notes about +the addition and removal of support for major versions. + +OpenTofu Core also makes an assumption about major version support when +it produces actionable error messages for users about incompatibilities: +a particular protocol major version is supported for a single consecutive +range of provider releases, with no "gaps". + +## Using the protobuf specifications in an SDK + +If you wish to build an SDK for OpenTofu plugins, an early step will be to +copy one or more `.proto` files from this directory into your own repository +(depending on which protocol versions you intend to support) and use the +`protoc` protocol buffers compiler (with gRPC extensions) to generate suitable +RPC stubs and types for your target language. + +For example, if you happen to be targeting Python, you might generate the +stubs using a command like this: + +``` +protoc --python_out=. --grpc_python_out=. tfplugin5.1.proto +``` + +You can find out more about the tool usage for each target language in +[the gRPC Quick Start guides](https://grpc.io/docs/quickstart/). + +The protobuf specification for a version is immutable after it has been +included in at least one OpenTofu release. Any changes will be documented in +a new `.proto` file establishing a new protocol version. + +The protocol buffer compiler will produce some sort of library object appropriate +for the target language, which depending on the language might be called a +module, or a package, or something else. We recommend to include the protocol +major version in your module or package name so that you can potentially +support multiple versions concurrently in future. For example, if you are +targeting major version 5 you might call your package or module `tfplugin5`. + +To upgrade to a newer minor protocol version, copy the new `.proto` file +from this directory into the same location as your previous version, delete +the previous version, and then run the protocol buffers compiler again +against the new `.proto` file. Because minor releases are backward-compatible, +you can simply update your previous stubs in-place rather than creating a +new set alongside. + +To support a new _major_ protocol version, create a new package or module +and copy the relevant `.proto` file into it, creating a separate set of stubs +that can in principle allow your SDK to support both major versions at the +same time. We recommend supporting both the previous and current major versions +together for a while across a major version upgrade so that users can avoid +having to upgrade both OpenTofu Core and all of their providers at the same +time, but you can delete the previous major version stubs once you remove +support for that version. + +**Note:** Some of the `.proto` files contain statements about being updated +in-place for minor versions. This reflects an earlier version management +strategy which is no longer followed. The current process is to create a +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. diff --git a/network-poc/static/docs/plugin-protocol/object-wire-format.md b/network-poc/static/docs/plugin-protocol/object-wire-format.md new file mode 100644 index 0000000..4aa854c --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/object-wire-format.md @@ -0,0 +1,267 @@ +# Wire Format for OpenTofu Objects and Associated Values + +The provider wire protocol (as of major version 5) includes a protobuf message +type `DynamicValue` which OpenTofu uses to represent values from the OpenTofu +Language type system, which result from evaluating the content of `resource`, +`data`, and `provider` blocks, based on a schema defined by the corresponding +provider. + +Because the structure of these values is determined at runtime, `DynamicValue` +uses one of two possible dynamic serialization formats for the values +themselves: MessagePack or JSON. OpenTofu most commonly uses MessagePack, +because it offers a compact binary representation of a value. However, a server +implementation of the provider protocol should fall back to JSON if the +MessagePack field is not populated, in order to support both formats. + +The remainder of this document describes how OpenTofu translates from its own +type system into the type system of the two supported serialization formats. +A server implementation of the OpenTofu provider protocol can use this +information to decode `DynamicValue` values from incoming messages into +whatever representation is convenient for the provider implementation. + +A server implementation must also be able to _produce_ `DynamicValue` messages +as part of various response messages. When doing so, servers should always +use MessagePack encoding, because OpenTofu does not consistently support +JSON responses across all request types and all OpenTofu versions. + +Both the MessagePack and JSON serializations are driven by information the +provider previously returned in a `Schema` message. OpenTofu will encode each +value depending on the type constraint given for it in the corresponding schema, +using the closest possible MessagePack or JSON type to the OpenTofu language +type. Therefore a server implementation can decode a serialized value using a +standard MessagePack or JSON library and assume it will conform to the +serialization rules described below. + +## MessagePack Serialization Rules + +The MessagePack types referenced in this section are those defined in +[The MessagePack type system specification](https://github.com/msgpack/msgpack/blob/master/spec.md#type-system). + +Note that MessagePack defines several possible serialization formats for each +type, and OpenTofu may choose any of the formats of a specified type. +The exact serialization chosen for a given value may vary between OpenTofu +versions, but the types given here are contractual. + +Conversely, server implementations that are _producing_ MessagePack-encoded +values are free to use any of the valid serialization formats for a particular +type. However, we recommend choosing the most compact format that can represent +the value without a loss of range. + +### `Schema.Block` Mapping Rules for MessagePack + +To represent the content of a block as MessagePack, OpenTofu constructs a +MessagePack map that contains one key-value pair per attribute and one +key-value pair per distinct nested block described in the `Schema.Block` message. + +The key-value pairs representing attributes have values based on +[the `Schema.Attribute` mapping rules](#Schema.Attribute-mapping-rules-for-messagepack). +The key-value pairs representing nested block types have values based on +[the `Schema.NestedBlock` mapping rules](#Schema.NestedBlock-mapping-rules-for-messagepack). + +### `Schema.Attribute` Mapping Rules for MessagePack + +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 +[OpenTofu type constraint](https://opentofu.org/docs/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. + +The following table describes the type-specific mapping rules. Along with those +type-specific rules there are two special rules that override the mappings +in the table below, regardless of type: + +* A null value is represented as a MessagePack nil value. +* 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, described in more detail below. + +| `type` Pattern | MessagePack Representation | +|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `"string"` | A MessagePack string containing the Unicode characters from the string value serialized as normalized UTF-8. | +| `"number"` | Either MessagePack integer, MessagePack float, or MessagePack string representing the number. If a number is represented as a string then the string contains a decimal representation of the number which may have a larger mantissa than can be represented by a 64-bit float. | +| `"bool"` | A MessagePack boolean value corresponding to the value. | +| `["list",T]` | A MessagePack array with the same number of elements as the list value, each of which is represented by the result of applying these same mapping rules to the nested type `T`. | +| `["set",T]` | Identical in representation to `["list",T]`, but the order of elements is undefined because OpenTofu sets are unordered. | +| `["map",T]` | A MessagePack map with one key-value pair per element of the map value, where the element key is serialized as the map key (always a MessagePack string) and the element value is represented by a value constructed by applying these same mapping rules to the nested type `T`. | +| `["object",ATTRS]` | A MessagePack map with one key-value pair per attribute defined in the `ATTRS` object. The attribute name is serialized as the map key (always a MessagePack string) and the attribute value is represented by a value constructed by applying these same mapping rules to each attribute's own 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 OpenTofu 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 +depends on the `nesting` field of the corresponding `Schema.NestedBlock` message. +The `nesting` field is a value from the `Schema.NestingBlock.NestingMode` +enumeration. + +All `nesting` values cause the individual blocks of a type to be represented +by applying +[the `Schema.Block` mapping rules](#Schema.Block-mapping-rules-for-messagepack) +to the block's contents based on the `block` field, producing what we'll call +a _block value_ in the table below. + +The `nesting` value then in turn defines how OpenTofu will collect all of the +individual block values together to produce a single property value representing +the nested block type. For all `nesting` values other than `MAP`, blocks may +not have any labels. For the `nesting` value `MAP`, blocks must have exactly +one label, which is a string we'll call a _block label_ in the table below. + +| `nesting` Value | MessagePack Representation | +|---|---| +| `SINGLE` | The block value of the single block of this type, or nil if there is no block of that type. | +| `LIST` | A MessagePack array of all of the block values, preserving the order of definition of the blocks in the configuration. | +| `SET` | A MessagePack array of all of the block values in no particular order. | +| `MAP` | A MessagePack map with one key-value pair per block value, where the key is the block label and the value is the block value. | +| `GROUP` | The same as with `SINGLE`, except that if there is no block of that type OpenTofu will synthesize a block value by pretending that all of the declared attributes are null and that there are zero blocks of each declared block type. | + +For the `LIST` and `SET` nesting modes, OpenTofu guarantees that the +MessagePack array will have a number of elements between the `min_items` and +`max_items` values given in the schema, _unless_ any of the block values contain +nested unknown values. When unknown values are present, OpenTofu considers +the value to be potentially incomplete and so OpenTofu defers validation of +the number of blocks. For example, if the configuration includes a `dynamic` +block whose `for_each` argument is unknown then the final number of blocks is +not predictable until the apply phase. + +## JSON Serialization Rules + +The JSON serialization is a secondary representation for `DynamicValue`, with +MessagePack preferred due to its ability to represent unknown values via an +extension. + +The JSON encoding described in this section is also used for the `json` field +of the `RawValue` message that forms part of an `UpgradeResourceState` request. +However, in that case the data is serialized per the schema of the provider +version that created it, which won't necessarily match the schema of the +_current_ version of that provider. + +### `Schema.Block` Mapping Rules for JSON + +To represent the content of a block as JSON, OpenTofu constructs a +JSON object that contains one property per attribute and one property per +distinct nested block described in the `Schema.Block` message. + +The properties representing attributes have property values based on +[the `Schema.Attribute` mapping rules](#Schema.Attribute-mapping-rules-for-json). +The properties representing nested block types have property values based on +[the `Schema.NestedBlock` mapping rules](#Schema.NestedBlock-mapping-rules-for-json). + +### `Schema.Attribute` Mapping Rules for JSON + +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 +[OpenTofu type constraint](https://opentofu.org/docs/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. + +The following table describes the type-specific mapping rules. Along with those +type-specific rules there is one special rule that overrides the rules in the +table regardless of type: + +* A null value is always represented as JSON `null`. + +| `type` Pattern | JSON Representation | +|---|---| +| `"string"` | A JSON string containing the Unicode characters from the string value. | +| `"number"` | A JSON number representing the number value. OpenTofu numbers are arbitrary-precision floating point, so the value may have a larger mantissa than can be represented by a 64-bit float. | +| `"bool"` | Either JSON `true` or JSON `false`, depending on the boolean value. | +| `["list",T]` | A JSON array with the same number of elements as the list value, each of which is represented by the result of applying these same mapping rules to the nested type `T`. | +| `["set",T]` | Identical in representation to `["list",T]`, but the order of elements is undefined because OpenTofu sets are unordered. | +| `["map",T]` | A JSON object with one property per element of the map value, where the element key is serialized as the property name string and the element value is represented by a property value constructed by applying these same mapping rules to the nested type `T`. | +| `["object",ATTRS]` | A JSON object with one property per attribute defined in the `ATTRS` object. The attribute name is serialized as the property name string and the attribute value is represented by a property value constructed by applying these same mapping rules to each attribute's own type. | +| `["tuple",TYPES]` | A JSON 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 JSON object with two properties: `"type"` specifying one of the `type` patterns described in this table in-band, giving the exact runtime type of the value, and `"value"` specifying the result of applying these same mapping rules to the table for the specified runtime type. This special type constraint represents values whose types will be decided only at runtime. | + +### `Schema.NestedBlock` Mapping Rules for JSON + +The JSON serialization of a collection of blocks of a particular type depends +on the `nesting` field of the corresponding `Schema.NestedBlock` message. +The `nesting` field is a value from the `Schema.NestingBlock.NestingMode` +enumeration. + +All `nesting` values cause the individual blocks of a type to be represented +by applying +[the `Schema.Block` mapping rules](#Schema.Block-mapping-rules-for-json) +to the block's contents based on the `block` field, producing what we'll call +a _block value_ in the table below. + +The `nesting` value then in turn defines how OpenTofu will collect all of the +individual block values together to produce a single property value representing +the nested block type. For all `nesting` values other than `MAP`, blocks may +not have any labels. For the `nesting` value `MAP`, blocks must have exactly +one label, which is a string we'll call a _block label_ in the table below. + +| `nesting` Value | JSON Representation | +|---|---| +| `SINGLE` | The block value of the single block of this type, or `null` if there is no block of that type. | +| `LIST` | A JSON array of all of the block values, preserving the order of definition of the blocks in the configuration. | +| `SET` | A JSON array of all of the block values in no particular order. | +| `MAP` | A JSON object with one property per block value, where the property name is the block label and the value is the block value. | +| `GROUP` | The same as with `SINGLE`, except that if there is no block of that type OpenTofu will synthesize a block value by pretending that all of the declared attributes are null and that there are zero blocks of each declared block type. | + +For the `LIST` and `SET` nesting modes, OpenTofu guarantees that the JSON +array will have a number of elements between the `min_items` and `max_items` +values given in the schema. diff --git a/network-poc/static/docs/plugin-protocol/releasing-new-version.md b/network-poc/static/docs/plugin-protocol/releasing-new-version.md new file mode 100644 index 0000000..22373ae --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/releasing-new-version.md @@ -0,0 +1,53 @@ +# Releasing a New Version of the Protocol + +OpenTofu's plugin protocol is the contract between OpenTofu's plugins and +OpenTofu, and as such releasing a new version requires some coordination +between those pieces. This document is intended to be a checklist to consult +when adding a new major version of the protocol (X in X.Y) to ensure that +everything that needs to be is aware of it. + +## New Protobuf File + +The protocol is defined in protobuf files that live in the opentofu/opentofu +repository. Adding a new version of the protocol involves creating a new +`.proto` file in that directory. It is recommended that you copy the latest +protocol file, and modify it accordingly. + +## New terraform-plugin-go Package + +The +[hashicorp/terraform-plugin-go](https://github.com/hashicorp/terraform-plugin-go) +repository serves as the foundation for OpenTofu's plugin ecosystem. It needs +to know about the new major protocol version. Either open an issue in that repo +to have the Plugin SDK team add the new package, or if you would like to +contribute it yourself, open a PR. It is recommended that you copy the package +for the latest protocol version and modify it accordingly. + +## Update the Registry's List of Allowed Versions + +The OpenTofu Registry validates the protocol versions a provider advertises +support for when ingesting providers. Providers will not be able to advertise +support for the new protocol version until it is added to that list. + +## Update OpenTofu's Version Constraints + +OpenTofu only downloads providers that speak protocol versions it is +compatible with from the Registry during `tofu init`. When adding support +for a new protocol, you need to tell OpenTofu it knows that protocol version. +Modify the `SupportedPluginProtocols` variable in opentofu/opentofu's +`internal/getproviders/registry_client.go` file to include the new protocol. + +## Test Running a Provider With the Test Framework + +Use the provider test framework to test a provider written with the new +protocol. This end-to-end test ensures that providers written with the new +protocol work correctly with the test framework, especially in communicating +the protocol version between the test framework and OpenTofu. + +## Test Retrieving and Running a Provider From the Registry + +Publish a provider, either to the public registry or to the staging registry, +and test running `tofu init` and `tofu apply`, along with exercising +any of the new functionality the protocol version introduces. This end-to-end +test ensures that all the pieces needing to be updated before practitioners can +use providers built with the new protocol have been updated. diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.0.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.0.proto new file mode 100644 index 0000000..dc94639 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.0.proto @@ -0,0 +1,358 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.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 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 resource_schemas = 2; + map 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.1.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.1.proto new file mode 100644 index 0000000..4dc9ca1 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.1.proto @@ -0,0 +1,358 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.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 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 resource_schemas = 2; + map 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.10.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.10.proto new file mode 100644 index 0000000..a0731a3 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.10.proto @@ -0,0 +1,953 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 5.10 +// +// This file defines version 5.10 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/opentofu/opentofu/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 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; +} + +// ActionSchema defines the schema for an action that can be invoked by Terraform. +message ActionSchema { + Schema schema = 1; // of the action itself +} + +// 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; + string deprecation_message = 7; + } + + 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; + string deprecation_message = 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; + } + + // 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; + + // The generate_resource_config capability signals that a provider supports + // GenerateResourceConfig. + bool generate_resource_config = 4; +} + +// 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 method is CURRENTLY UNUSED and it serves mostly for convenience + // of code generation inside of terraform-plugin-mux. + 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); + rpc GenerateResourceConfig(GenerateResourceConfig.Request) returns (GenerateResourceConfig.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); + + /////// List + rpc ListResource(ListResource.Request) returns (stream ListResource.Event); + rpc ValidateListResourceConfig(ValidateListResourceConfig.Request) returns (ValidateListResourceConfig.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); + + //////// Actions + rpc PlanAction(PlanAction.Request) returns (PlanAction.Response); + rpc InvokeAction(InvokeAction.Request) returns (stream InvokeAction.Event); + rpc ValidateActionConfig(ValidateActionConfig.Request) returns (ValidateActionConfig.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; + repeated ListResourceMetadata list_resources = 7; + repeated ActionMetadata actions = 8; + } + + 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 ListResourceMetadata { + string type_name = 1; + } + + message ActionMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + map functions = 7; + map ephemeral_resource_schemas = 8; + map list_resource_schemas = 9; + reserved 10; // Field number 10 is used by state stores in version 6 + map action_schemas = 11; + 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 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 GenerateResourceConfig { + message Request { + string type_name = 1; + DynamicValue state = 2; + } + + message Response { + // config is the provided state modified such that it represents a valid resource configuration value. + DynamicValue config = 1; + repeated Diagnostic diagnostics = 2; + } +} + +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 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; + } +} + +message ListResource { + message Request { + // type_name is the list resource type name. + string type_name = 1; + + // configuration is the list ConfigSchema-based configuration data. + DynamicValue config = 2; + + // when include_resource_object is set to true, the provider should + // include the full resource object for each result + bool include_resource_object = 3; + + // The maximum number of results that Terraform is expecting. + // The stream will stop, once this limit is reached. + int64 limit = 4; + } + + message Event { + // identity is the resource identity data of the resource instance. + ResourceIdentityData identity = 1; + + // display_name can be displayed in a UI to make it easier for humans to identify a resource + string display_name = 2; + + // optional resource object which can be useful when combining list blocks in configuration + optional DynamicValue resource_object = 3; + + // A warning or error diagnostics for this event + repeated Diagnostic diagnostic = 4; + } +} + +message ValidateListResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + DynamicValue include_resource_object = 3; + DynamicValue limit = 4; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message PlanAction { + message Request { + string action_type = 1; + // config of the action, based on the schema of the actual action + DynamicValue config = 2; + // metadata + ClientCapabilities client_capabilities = 3; + } + + message Response { + repeated Diagnostic diagnostics = 1; + // metadata + Deferred deferred = 2; + } +} + +message InvokeAction { + message Request { + string action_type = 1; + // response from the plan + DynamicValue config = 2; + // metadata + ClientCapabilities client_capabilities = 3; + } + + message Event { + message Progress { + // message to be printed in the console / HCPT + string message = 1; + } + message Completed { + repeated Diagnostic diagnostics = 1; + } + + oneof type { + Progress progress = 1; + Completed completed = 2; + } + } +} + +message ValidateActionConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.2.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.2.proto new file mode 100644 index 0000000..f7e921a --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.2.proto @@ -0,0 +1,374 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.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 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/opentofu/opentofu/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 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 resource_schemas = 2; + map 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.3.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.3.proto new file mode 100644 index 0000000..eb9f682 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.3.proto @@ -0,0 +1,403 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.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 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/opentofu/opentofu/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 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 resource_schemas = 2; + map 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 { + // 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 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 { + // 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; + } + 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.4.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.4.proto new file mode 100644 index 0000000..fc91152 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.4.proto @@ -0,0 +1,409 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 5.4 +// +// This file defines version 5.4 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 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/opentofu/opentofu/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 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 resource_schemas = 2; + map 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; + + // 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; + } +} + +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 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 { + // 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; + } + 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.5.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.5.proto new file mode 100644 index 0000000..2ee2534 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.5.proto @@ -0,0 +1,591 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 5.5 +// +// This file defines version 5.5 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 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/opentofu/opentofu/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 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 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; +} + +// 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; +} + +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 result. + 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; + } +} + +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); + + //////// 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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; + } + + 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 resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + } +} + +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 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 { + // 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; + } + 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 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; + } + + 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; + } +} + +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; + } +} + +message GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any error from the function logic. + FunctionError error = 2; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.6.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.6.proto new file mode 100644 index 0000000..1818550 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.6.proto @@ -0,0 +1,637 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 5.6 +// +// This file defines version 5.6 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/opentofu/opentofu/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 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 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; +} + +// 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; +} + +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 result. + 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); + + //////// 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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; + } + + 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 resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + } +} + +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 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; + 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; + } + 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; + } +} + +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; + } + + 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; + } +} + +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; + ClientCapabilities client_capabilities = 3; + } + + message ImportedResource { + string type_name = 1; + DynamicValue state = 2; + bytes private = 3; + } + + 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; + } + + 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; + } +} + +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 GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any error from the function logic. + FunctionError error = 2; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.7.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.7.proto new file mode 100644 index 0000000..137b765 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.7.proto @@ -0,0 +1,700 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 5.7 +// +// This file defines version 5.7 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/opentofu/opentofu/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 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; +} + +// 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; +} + +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 result. + 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); + + //////// 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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 EphemeralResourceMetadata ephemeral_resources = 6; + } + + message FunctionMetadata { + // name is the function name. + string name = 1; + } + + message DataSourceMetadata { + string type_name = 1; + } + + message ResourceMetadata { + string type_name = 1; + } + + message EphemeralResourceMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + map ephemeral_resource_schemas = 8; + } +} + +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 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; + 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; + } + 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; + } +} + +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; + } + + 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; + } +} + +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; + ClientCapabilities client_capabilities = 3; + } + + message ImportedResource { + string type_name = 1; + DynamicValue state = 2; + bytes private = 3; + } + + 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; + } + + 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; + } +} + +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 GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any error from the function logic. + FunctionError error = 2; + } +} + +message ValidateEphemeralResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +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 is set if the provider is deferring the change. If set the caller + // needs to handle the deferral. + 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; + } +} \ No newline at end of file diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.8.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.8.proto new file mode 100644 index 0000000..e671656 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.8.proto @@ -0,0 +1,707 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 5.8 +// +// This file defines version 5.8 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/opentofu/opentofu/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 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; + // write_only indicates that the attribute value will be provided via + // configuration and must be omitted from state. write_only must be + // combined with optional or required, and is only valid for managed + // resource schemas. + 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 result. + 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); + + //////// 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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 EphemeralResourceMetadata ephemeral_resources = 6; + } + + message FunctionMetadata { + // name is the function name. + string name = 1; + } + + message DataSourceMetadata { + string type_name = 1; + } + + message ResourceMetadata { + string type_name = 1; + } + + message EphemeralResourceMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + map ephemeral_resource_schemas = 8; + } +} + +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 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 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; + } + 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; + } +} + +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; + } + + 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; + } +} + +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; + ClientCapabilities client_capabilities = 3; + } + + message ImportedResource { + string type_name = 1; + DynamicValue state = 2; + bytes private = 3; + } + + 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; + } + + 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; + } +} + +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 GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any error from the function logic. + FunctionError error = 2; + } +} + +message ValidateEphemeralResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +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 is set if the provider is deferring the change. If set the caller + // needs to handle the deferral. + 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; + } +} \ No newline at end of file diff --git a/network-poc/static/docs/plugin-protocol/tfplugin5.9.proto b/network-poc/static/docs/plugin-protocol/tfplugin5.9.proto new file mode 100644 index 0000000..f4dcd0b --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin5.9.proto @@ -0,0 +1,826 @@ +// 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. +// +// 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/opentofu/opentofu/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 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; + // write_only indicates that the attribute value will be provided via + // configuration and must be omitted from state. write_only must be + // combined with optional or required, and is only valid for managed + // resource schemas. + 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; +} + +// 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; +} + +// ResourceIdentityData is a separate message for better extensibility +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; +} + +// 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 result. + 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); + // GetResourceIdentitySchemas returns the identity schemas for all managed + // resources. + rpc GetResourceIdentitySchemas(GetResourceIdentitySchemas.Request) returns (GetResourceIdentitySchemas.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); + // 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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 EphemeralResourceMetadata ephemeral_resources = 6; + } + + message FunctionMetadata { + // name is the function name. + string name = 1; + } + + message DataSourceMetadata { + string type_name = 1; + } + + message ResourceMetadata { + string type_name = 1; + } + + message EphemeralResourceMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + map ephemeral_resource_schemas = 8; + } +} + +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 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 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 GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any error from the function logic. + FunctionError error = 2; + } +} + +message ValidateEphemeralResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +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 is set if the provider is deferring the change. If set the caller + // needs to handle the deferral. + 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; + } +} + +// Returns resource identity schemas for all resources +message GetResourceIdentitySchemas { + message Request { + } + message Response { + // identity_schemas is a mapping of resource type names to their identity schemas. + map 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.0.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.0.proto new file mode 100644 index 0000000..81eeb3e --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.0.proto @@ -0,0 +1,326 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.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 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/opentofu/opentofu/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 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 resource_schemas = 2; + map 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.1.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.1.proto new file mode 100644 index 0000000..c5ff41c --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.1.proto @@ -0,0 +1,329 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.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 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/opentofu/opentofu/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 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 resource_schemas = 2; + map 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.10.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.10.proto new file mode 100644 index 0000000..bcc4f2f --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.10.proto @@ -0,0 +1,1078 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 6.10 +// +// This file defines version 6.10 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/opentofu/opentofu/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 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; +} + +// ActionSchema defines the schema for an action that can be invoked by Terraform. +message ActionSchema { + Schema schema = 1; // of the action itself +} + +// 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; + string deprecation_message = 7; + } + + 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; + string deprecation_message = 12; + } + + 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; + + // The generate_resource_config capability signals that a provider supports + // GenerateResourceConfig. + bool generate_resource_config = 4; +} + +// 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 method is CURRENTLY UNUSED and it serves mostly for convenience + // of code generation inside of terraform-plugin-mux. + 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); + rpc GenerateResourceConfig(GenerateResourceConfig.Request) returns (GenerateResourceConfig.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); + + /////// List + rpc ListResource(ListResource.Request) returns (stream ListResource.Event); + rpc ValidateListResourceConfig(ValidateListResourceConfig.Request) returns (ValidateListResourceConfig.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); + + // ValidateStateStoreConfig performs configuration validation + rpc ValidateStateStoreConfig(ValidateStateStore.Request) returns (ValidateStateStore.Response); + // ConfigureStateStore configures the state store, such as S3 connection in the context of already configured provider + rpc ConfigureStateStore(ConfigureStateStore.Request) returns (ConfigureStateStore.Response); + + // ReadStateBytes streams byte chunks of a given state file from a state store + rpc ReadStateBytes(ReadStateBytes.Request) returns (stream ReadStateBytes.Response); + // WriteStateBytes streams byte chunks of a given state file into a state store + rpc WriteStateBytes(stream WriteStateBytes.RequestChunk) returns (WriteStateBytes.Response); + + // LockState locks a given state (i.e. CE workspace) + rpc LockState(LockState.Request) returns (LockState.Response); + // UnlockState unlocks a given state (i.e. CE workspace) + rpc UnlockState(UnlockState.Request) returns (UnlockState.Response); + + // GetStates returns a list of all states (i.e. CE workspaces) managed by a given state store + rpc GetStates(GetStates.Request) returns (GetStates.Response); + // DeleteState instructs a given state store to delete a specific state (i.e. a CE workspace) + rpc DeleteState(DeleteState.Request) returns (DeleteState.Response); + + //////// Actions + rpc PlanAction(PlanAction.Request) returns (PlanAction.Response); + rpc InvokeAction(InvokeAction.Request) returns (stream InvokeAction.Event); + rpc ValidateActionConfig(ValidateActionConfig.Request) returns (ValidateActionConfig.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; + repeated ListResourceMetadata list_resources = 7; + repeated StateStoreMetadata state_stores = 8; + repeated ActionMetadata actions = 9; + } + + 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 ListResourceMetadata { + string type_name = 1; + } + + message StateStoreMetadata { + string type_name = 1; + } + + message ActionMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + map functions = 7; + map ephemeral_resource_schemas = 8; + map list_resource_schemas = 9; + map state_store_schemas = 10; + map action_schemas = 11; + 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 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 GenerateResourceConfig { + message Request { + string type_name = 1; + DynamicValue state = 2; + } + + message Response { + // config is the provided state modified such that it represents a valid resource configuration value. + DynamicValue config = 1; + repeated Diagnostic diagnostics = 2; + } +} + +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 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; + } +} + +message ListResource { + message Request { + // type_name is the list resource type name. + string type_name = 1; + + // configuration is the list ConfigSchema-based configuration data. + DynamicValue config = 2; + + // when include_resource_object is set to true, the provider should + // include the full resource object for each result + bool include_resource_object = 3; + + // The maximum number of results that Terraform is expecting. + // The stream will stop, once this limit is reached. + int64 limit = 4; + } + + message Event { + // identity is the resource identity data of the resource instance. + ResourceIdentityData identity = 1; + + // display_name can be displayed in a UI to make it easier for humans to identify a resource + string display_name = 2; + + // optional resource object which can be useful when combining list blocks in configuration + optional DynamicValue resource_object = 3; + + // A warning or error diagnostics for this event + repeated Diagnostic diagnostic = 4; + } +} + +message ValidateListResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + DynamicValue include_resource_object = 3; + DynamicValue limit = 4; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message ValidateStateStore { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message ConfigureStateStore { + message Request { + string type_name = 1; + DynamicValue config = 2; + StateStoreClientCapabilities capabilities = 3; + } + message Response { + repeated Diagnostic diagnostics = 1; + StateStoreServerCapabilities capabilities = 2; + } +} + +message StateStoreClientCapabilities { + int64 chunk_size = 1; // suggested chunk size by Core +} + +message StateStoreServerCapabilities { + int64 chunk_size = 1; // chosen chunk size by plugin +} + +message ReadStateBytes { + message Request { + string type_name = 1; + string state_id = 2; + } + message Response { + bytes bytes = 1; + // total_length is the overall size of all of the state byte chunks that will be received + int64 total_length = 2; + StateRange range = 3; + repeated Diagnostic diagnostics = 4; + } +} + +message WriteStateBytes { + message RequestChunk { + // meta is sent with the first chunk only + optional RequestChunkMeta meta = 1; + + bytes bytes = 2; + // total_length is the overall size of all of the state byte chunks that will be sent. + int64 total_length = 3; + StateRange range = 4; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message RequestChunkMeta { + string type_name = 1; + string state_id = 2; +} + +message StateRange { + // start is the starting byte index for a chunk of state byte data. + // This index is in relation to the entire byte array that will be sent or received. + int64 start = 1; + // end is the ending byte index for a chunk of state byte data. + // This index is in relation to the entire byte array that will be sent or received. + int64 end = 2; +} + +message LockState { + message Request { + string type_name = 1; + string state_id = 2; + // operation represents an ongoing operation due to which lock is held (e.g. refresh, plan, apply) + string operation = 3; + } + message Response { + string lock_id = 1; + repeated Diagnostic diagnostics = 2; + } +} + +message UnlockState { + message Request { + string type_name = 1; + string state_id = 2; + string lock_id = 3; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message GetStates { + message Request { + string type_name = 1; + } + message Response { + repeated string state_id = 1; + repeated Diagnostic diagnostics = 2; + } +} + +message DeleteState { + message Request { + string type_name = 1; + string state_id = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message PlanAction { + message Request { + string action_type = 1; + // config of the action, based on the schema of the actual action + DynamicValue config = 2; + // metadata + ClientCapabilities client_capabilities = 3; + } + + message Response { + repeated Diagnostic diagnostics = 1; + // metadata + Deferred deferred = 2; + } +} + +message InvokeAction { + message Request { + string action_type = 1; + // response from the plan + DynamicValue config = 2; + // metadata + ClientCapabilities client_capabilities = 3; + } + + message Event { + message Progress { + // message to be printed in the console / HCPT + string message = 1; + } + + message Completed { + repeated Diagnostic diagnostics = 1; + } + + oneof type { + Progress progress = 1; + Completed completed = 2; + } + } +} + +message ValidateActionConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.2.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.2.proto new file mode 100644 index 0000000..1ce3b0e --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.2.proto @@ -0,0 +1,355 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.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 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/opentofu/opentofu/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 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 resource_schemas = 2; + map 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.3.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.3.proto new file mode 100644 index 0000000..182609c --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.3.proto @@ -0,0 +1,384 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.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 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/opentofu/opentofu/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 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 resource_schemas = 2; + map 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 { + // 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 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 { + // 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; + } + 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.4.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.4.proto new file mode 100644 index 0000000..609569c --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.4.proto @@ -0,0 +1,390 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 6.4 +// +// This file defines version 6.4 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 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/opentofu/opentofu/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 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 resource_schemas = 2; + map 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; + + // 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; + } +} + +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 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 { + // 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; + } + 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; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.5.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.5.proto new file mode 100644 index 0000000..93ad967 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.5.proto @@ -0,0 +1,572 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 6.5 +// +// This file defines version 6.5 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 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/opentofu/opentofu/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 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 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; +} + +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 result. + 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; +} + +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); + + //////// 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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; + } + + 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 resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + } +} + +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 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 { + // 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; + } + 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 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; + } + + 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; + } +} + +message ReadDataSource { + message Request { + string type_name = 1; + DynamicValue config = 2; + DynamicValue provider_meta = 3; + } + message Response { + DynamicValue state = 1; + repeated Diagnostic diagnostics = 2; + } +} + +message GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any errors from the function logic. + FunctionError error = 2; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.6.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.6.proto new file mode 100644 index 0000000..6820bdf --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.6.proto @@ -0,0 +1,618 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 6.6 +// +// This file defines version 6.6 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/opentofu/opentofu/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 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 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; +} + +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 result. + 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; +} + +// 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); + + //////// 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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; + } + + 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 resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + } +} + +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 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; + 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; + } + 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; + } +} + +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; + } + + 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; + } +} + +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; + ClientCapabilities client_capabilities = 3; + } + + message ImportedResource { + string type_name = 1; + DynamicValue state = 2; + bytes private = 3; + } + + 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; + } + + 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; + } +} + +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 GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any errors from the function logic. + FunctionError error = 2; + } +} diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.7.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.7.proto new file mode 100644 index 0000000..dd175c7 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.7.proto @@ -0,0 +1,682 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 6.7 +// +// This file defines version 6.7 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/opentofu/opentofu/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 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; +} + +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 result. + 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; +} + +// 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); + + //////// 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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 EphemeralResourceMetadata ephemeral_resources = 6; + } + + message FunctionMetadata { + // name is the function name. + string name = 1; + } + + message DataSourceMetadata { + string type_name = 1; + } + + message ResourceMetadata { + string type_name = 1; + } + + message EphemeralResourceMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + map ephemeral_resource_schemas = 8; + } +} + +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 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; + 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; + } + 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; + } +} + +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; + } + + 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; + } +} + +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; + ClientCapabilities client_capabilities = 3; + } + + message ImportedResource { + string type_name = 1; + DynamicValue state = 2; + bytes private = 3; + } + + 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; + } + + 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; + } +} + +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 GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any error from the function logic. + FunctionError error = 2; + } +} + +message ValidateEphemeralResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +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 is set if the provider is deferring the change. If set the caller + // needs to handle the deferral. + 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; + } +} \ No newline at end of file diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.8.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.8.proto new file mode 100644 index 0000000..1a38463 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.8.proto @@ -0,0 +1,691 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Terraform Plugin RPC protocol version 6.8 +// +// This file defines version 6.8 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/opentofu/opentofu/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 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; + // write_only indicates that the attribute value will be provided via + // configuration and must be omitted from state. write_only must be + // combined with optional or required, and is only valid for managed + // resource schemas. + 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 result. + 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); + + //////// 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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 EphemeralResourceMetadata ephemeral_resources = 6; + } + + message FunctionMetadata { + // name is the function name. + string name = 1; + } + + message DataSourceMetadata { + string type_name = 1; + } + + message ResourceMetadata { + string type_name = 1; + } + + message EphemeralResourceMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + map ephemeral_resource_schemas = 8; + } +} + +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 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 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; + } + 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; + } +} + +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; + } + + 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; + } +} + +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; + ClientCapabilities client_capabilities = 3; + } + + message ImportedResource { + string type_name = 1; + DynamicValue state = 2; + bytes private = 3; + } + + 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; + } + + 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; + } +} + +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 GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any error from the function logic. + FunctionError error = 2; + } +} + +message ValidateEphemeralResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +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 is set if the provider is deferring the change. If set the caller + // needs to handle the deferral. + 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; + } +} \ No newline at end of file diff --git a/network-poc/static/docs/plugin-protocol/tfplugin6.9.proto b/network-poc/static/docs/plugin-protocol/tfplugin6.9.proto new file mode 100644 index 0000000..6b61662 --- /dev/null +++ b/network-poc/static/docs/plugin-protocol/tfplugin6.9.proto @@ -0,0 +1,809 @@ +// 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. +// +// This file will not be updated. Any minor versions of protocol 6 to follow +// should copy this file and modify the copy 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/opentofu/opentofu/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 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; + // write_only indicates that the attribute value will be provided via + // configuration and must be omitted from state. write_only must be + // combined with optional or required, and is only valid for managed + // resource schemas. + 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; +} + +// 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; +} + +// ResourceIdentityData is a separate message for better extensibility +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; +} + + +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 result. + 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); + // GetResourceIdentitySchemas returns the identity schemas for all managed + // resources. + rpc GetResourceIdentitySchemas(GetResourceIdentitySchemas.Request) returns (GetResourceIdentitySchemas.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); + // 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); + + // Functions + + // GetFunctions returns the definitions of all functions. + rpc GetFunctions(GetFunctions.Request) returns (GetFunctions.Response); + + // CallFunction runs the provider-defined function logic and returns + // the result with any diagnostics. + 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 EphemeralResourceMetadata ephemeral_resources = 6; + } + + message FunctionMetadata { + // name is the function name. + string name = 1; + } + + message DataSourceMetadata { + string type_name = 1; + } + + message ResourceMetadata { + string type_name = 1; + } + + message EphemeralResourceMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + + // functions is a mapping of function names to definitions. + map functions = 7; + map ephemeral_resource_schemas = 8; + } +} + +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 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 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 GetFunctions { + message Request {} + + message Response { + // functions is a mapping of function names to definitions. + map functions = 1; + + // diagnostics is any warnings or errors. + repeated Diagnostic diagnostics = 2; + } +} + +message CallFunction { + message Request { + // name is the name of the function being called. + string name = 1; + + // arguments is the data of each function argument value. + repeated DynamicValue arguments = 2; + } + + message Response { + // result is result value after running the function logic. + DynamicValue result = 1; + + // error is any error from the function logic. + FunctionError error = 2; + } +} + +message ValidateEphemeralResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +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 is set if the provider is deferring the change. If set the caller + // needs to handle the deferral. + 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; + } +} + +// Returns resource identity schemas for all resources +message GetResourceIdentitySchemas { + message Request { + } + message Response { + // identity_schemas is a mapping of resource type names to their identity schemas. + map 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; + } +} diff --git a/network-poc/static/docs/provider-references.md b/network-poc/static/docs/provider-references.md new file mode 100644 index 0000000..d117856 --- /dev/null +++ b/network-poc/static/docs/provider-references.md @@ -0,0 +1,398 @@ +# Provider References Through the OpenTofu Language, Codebase and State + +The concept of Providers has changed and evolved over the lifetime of OpenTofu, with many of the legacy configuration options still supported today. This document aims to walk through examples and map them to structures within OpenTofu's code. + +## Existing Documentation + +It is recommended that you have the following open when reading through the rest of this document: +* https://opentofu.org/docs/language/providers/ +* https://opentofu.org/docs/language/providers/requirements/ +* https://opentofu.org/docs/language/providers/configuration/ + +## What is a Provider? + +In general terms, a provider is a piece of code which interfaces OpenTofu with resources. For example, the AWS provider describes what resources it is able to read/manage, such as s3 buckets and ec2 instances. + +In most cases providers live in a registry, are downloaded into the local path, and executed to provide a versioned GRPC server to OpenTofu. They could potentially be dynamically loaded directly into the running OpenTofu application, but a distinct process helps with fault tolerance and potential isolation issues. + +Providers also may define functions that can be called from the OpenTofu configuration. See [Provider Functions](#Provider-Functions) below for more information. + +It is HIGHLY recommended to vet all providers you execute locally as they are not sandboxed at all. There are discussions ongoing on how to improve safety in that respect. + +Providers also may be configured with values in a HCL block. This allows the provider have some "global" configuration that does not need to be passed in every resource/data instance, a common example being credentials. + + +## Language References + +### History and Addressing of Providers + +Provider references and configuration have an interesting history, which leads to the system we have today. Note: some of this history has been summarized or omitted for clarity. + +#### Provider Type + +Prior to v0.10.0, providers were built directly into the binary and not released/versioned separately. They only had a single identifier, which we now call "Provider Type". + +Example: +```hcl +provider "aws" { + region = "us-east-1" +} + +resource "aws_s3_bucket" "foo" { + bucket_name = "foo" +} +``` + +This requires the `addrs.Provider{Type = "aws"}` provider, gives it some configuration, and then creates a `s3_bucket` with it due to the type prefix of `aws`. This provider also is referenceable via `addrs.LocalProviderConfig{LocalName = "aws"}`. Note: the Type and LocalName used to be the same field. These are distinct concepts that diverge in later examples. + + +#### Provider Alias + +You also may need to have multiple configurations of the "aws" provider, perhaps with different credentials or regions. These configurations are distinguished by "Provider Alias". + + +Example: +```hcl +provider "aws" { + region = "us-east-1" + alias = "default" +} + +resource "aws_s3_bucket" "foo" { + bucket_name = "foo" + provider = aws.default +} +``` + +As with the previous example, this requires the `addrs.Provider{Type = "aws"}` provider, gives it some configuration under the alias "default". The `s3_bucket` resource now refers to the provider explicitly via `addrs.LocalProviderConfig{LocalName = "aws", Alias = "default"}`. Note: the `addrs.Provider{Type = "aws"}` reference is still partially used due to some odd legacy interactions. + + +#### Provider Versions + +Since v0.10.0, providers are distributed via a registry. This allows provider versions to be decoupled from the main application version. Provider bugfixes and new features can be released independently of the main application. All providers/configs with the same `addrs.Provider` must use the same binary and must have compatible version constraints. + +```hcl +provider "aws" { + region = "us-east-1" + alias = "default" + version = 0.124 # Deprecated by required_providers +} + +resource "aws_s3_bucket" "foo" { + bucket_name = "foo" + provider = aws.default +} +``` + +The result is identical to the previous case, except now the version constraint is tracked in the `config.Module` structure, with `addrs.Provider{Type = "aws"}` as the key. Once all constraints are known, `tofu init` downloads the providers from the registry into a local cache for later execution. + +#### Module Provider References + +Prior to 0.11.0, modules would share/override provider configurations. There was no distinction between configuration of parent or child module's providers. This implicit inheritance caused a variety of issues and limitations. The `module -> providers` map field was introduced to allow explicit passing of provider configurations to child modules. + +```hcl +# main.tf + +provider "aws" { + region = "us-east-1" + alias = "default" + version = 0.124 # Deprecated by required_providers +} + +module "my_mod" { + source = "./mod" + # Only the "unaliased" providers are passed if this is omitted. + providers = { + aws = aws.default + } +} +``` + +```hcl +# ./mod/mod.tf +provider "aws" { # Deprecated by required_providers + version = ">= 0.1" # Deprecated by required_providers +} + +resource "aws_s3_bucket" "foo" { + bucket_name = "foo" + provider = aws +} +``` + +In the root module (main configuration), we require the `addrs.Provider{Type = "aws"}` with a version constraint of "0.124". A configuration for that provider exists at `addrs.LocalProviderConfig{LocalName = "aws", Alias = "default"}` within the root module and is not automatically accessible from the child module. A new reference is introduced, which can be used globally: `addrs.AbsProviderConfig{Module: Root, Provider: addrs.Provider{Type = "aws"}, Alias = "default"}`. + +The child module is passed the `addrs.AbsProviderConfig` and is internally referenceable within the module under `addrs.LocalProviderConfig{LocalName: "aws"}`. That global configuration is copied and merged with the configuration within that module, which in this case adds an additional version constraint. + +Within that module, `addrs.LocalProviderConfig{LocalName: "aws"}` now refers to `addrs.Provider{Type = "aws"}` and the merged configuration for that provider. + +If multiple instances of the same provider are needed, the alias can be provided in the module's "providers" block + +```hcl +# main.tf + +provider "aws" { + region = "us-east-1" + alias = "default" + version = 0.124 # Deprecated by required_providers +} + +module "my_mod" { + source = "./mod" + # Only the "unaliased" providers are passed if this is omitted. + providers = { + aws.foo = aws.default + } +} +``` + +```hcl +# ./mod/mod.tf +provider "aws" { # Deprecated by required_providers + version = ">= 0.1" # Deprecated by required_providers + alias = "foo" +} + +resource "aws_s3_bucket" "foo" { + bucket_name = "foo" + provider = aws.foo +} +``` + +The root module's explanation is nearly identical, the primary change is to the addressing in the child module. + +The child module is passed the `addrs.AbsProviderConfig` and is internally referenceable within the module under `addrs.LocalProviderConfig{LocalName: "aws", Alias = "foo"}`. That global configuration is copied and merged with the configuration within that module, which in this case adds an additional version constraint. + +Within that module, `addrs.LocalProviderConfig{LocalName: "aws", Alias = "foo"}` now refers to `addrs.Provider{Type = "aws"}` and the merged configuration for that provider. + +#### Required Providers (Legacy) + +With the change in 0.11.0 adding the `providers` field, it is still unclear when a child module's provider is "incorrectly configured" or if the parent module has forgotten an entry in the `providers` field. + +To solve this, `terraform -> required_providers` was introduced. The initial version of this feature was a direct mapping between "Provider Type" and "Provider Version Constraint". + +```hcl +terraform { + required_providers { + aws = "0.124" + } +} + +provider "aws" { + region = "us-east-1" + alias = "default" +} + +module "my_mod" { + source = "./mod" + providers = { + aws = aws.default + } +} +``` + +```hcl +# ./mod/mod.tf +terraform { + required_providers { + aws = ">= 0.1" + } +} + +resource "aws_s3_bucket" "foo" { + bucket_name = "foo" + provider = aws +} +``` + +The references are unchanged, except for the dependencies are now more explicit. This form of `required_providers` is no longer supported. + + +#### Provider Names / Namespaces / Registries + +Other organizations started to create providers over time (along with their own registries) and the concept of referencing a provider needed to be expanded. In v0.13.0 the concept of `addrs.Provider` was expanded to include `Namespace` and `Hostname`. + +Previously, all providers within the registry had global names "aws", "datadog", "gcp", etc... As forks were introduced and the authoring of providers took off, the `Namespace` concept was introduced. It usually maps to the GitHub user/org that owns it, but it is not a strict requirement (especially in third-party registries). + +Organizations also wanted more control over their providers for both development and security purposes. The providers registry hostname was included in the spec. + +Additionally, the previous understanding of "datadog" may refer to "datadog/datadog" or "user/datadog" and is unclear if they are both included in the project. By decoupling `addrs.Provider.Type` and `addrs.LocalProviderConfig.LocalName`, both could be used in the same module under different names. Additionally the same concept can be used to have the LocalName "datadog" refer to "user/datadog-fork" without having to rewrite the whole project's config. + + +```hcl +terraform { + required_providers { + awsname = { # name added for clarity, usually Type == LocalName + #source = "aws" + #source = "hashicorp/aws" + source = "registry.opentofu.org/hashicorp/aws" + version = "0.124" + } + } +} + +provider "awsname" { + region = "us-east-1" + alias = "default" +} + +module "my_mod" { + source = "./mod" + providers = { + modaws = awsname.default + } +} +``` + +```hcl +# ./mod/mod.tf +terraform { + required_providers { + modaws = { + source = "aws" + version = ">= 0.1" + } + } +} + + +resource "aws_s3_bucket" "foo" { + bucket_name = "foo" + provider = modaws +} +``` + +The required_providers "source" field in the root module decomposed into `addrs.Provider{Type="aws", Namespace="hashicorp", Hostname="registry.opentofu.org"}`. As the default namespace is "hashicorp" and the default hostname is "registry.opentofu.org", we will continue to use the shorthand `addrs.Provider{Type="aws"}`. Next `addrs.LocalProviderConfig{LocalName: "aws_name"}` is created and within the root module maps to `addrs.Provider{Type="aws"}`. This provider local name is then used in all subsequent references within the root module. The configuration is then mapped to `addrs.AbsProviderConfig{Module: Root, Provider: addrs.Provider{Type = "aws"}, Alias = "default"}` globally. + +The child module is passed the `addrs.AbsProviderConfig` and is internally referenceable within the module under `addrs.LocalProviderConfig{LocalName: "modaws"}`. + +Within that module, `addrs.LocalProviderConfig{LocalName: "modaws"}` now points at `addrs.Provider{Type = "aws"}` and is effectively replaced with `addrs.AbsProviderConfig{Module: Root, Provider: addrs.Provider{Type = "aws"}, Alias = "default"}` at runtime. This optimizes running as few provider instances as possible. + +If a new provider configuration were added to the module: +```hcl +provider "modaws" { + region = "us-west-2" +} +``` +This would negate the override / deduplication above and result in `addrs.AbsProviderConfig{Module: MyMod, Provider: addrs.Provider{Type = "aws"}}`. + +#### Multiple Provider Aliases + +Multiple provider aliases can be supplied in required_providers via `configuration_aliases`. This requires that a caller of the module provide the requested aliases explicitly. + +Example: + +```hcl +terraform { + required_providers { + awsname = { # name added for clarity, usually Type == LocalName + source = "registry.opentofu.org/hashicorp/aws" + version = "0.124" + } + } +} + +provider "awsname" { + region = "us-east-1" + alias = "default" +} + +module "my_mod" { + source = "./mod" + providers = { + modaws.foo = awsname.default + modaws.bar = awsname + } +} +``` + +```hcl +# ./mod/mod.tf +terraform { + required_providers { + modaws = { + source = "aws" + version = ">= 0.1" + configuration_aliases = [ modaws.foo, modaws.bar ] + } + } +} +``` + +### Multiple Provider Instances + +In OpenTofu 1.9.0, we introduced the concept of a "provider instance". This allows an aliased provider to have multiple instances based on the same configuration differentiated by a for_each expression. + +```hcl +# main.tofu + +provider "cloudflare" { + alias = "by_account" + for_each = local.cloudflare_accounts + account_id = each.key + auth_key = each.value +} + +locals { + enabled_cloudflare_accounts = { + for acct, cfg in local.cloudflare_accounts : acct => cfg + if cfg.enabled + } +} + +module "my_mod" { + source = "./foo" + for_each = local.enabled_cloudflare_accounts + account_id = each.key + + providers { + cloudflare = cloudflare.by_account[each.key] + } +} + +resource "cloudflare_r2_bucket" "bucket" { + for_each = local.cloudflare_accounts + account_id = each.key + provider = cloudflare.by_account[each.key] +} +``` + +### Representation in State + +Resources in the state file note the `addrs.AbsProviderConfig` required to modify them. + +Prior to 1.9.0, all instances (for_each/count) of a resource must use the same provider and would have the provider stored in a single field at the resource level, not resource instance level. + +After 1.9.0 (provider iteration), the "provider" field can now exist on either the resource or the resource instance and can include a "provider instance key" appended to the `addrs.AbsProviderConfig`. + * If provider config instances differ per resource instance, the "provider" field will exist only on the resource instances. + - Although the provider instance key may vary between resource instances of the same resource, the `addrs.AbsProviderConfig` component must be identical. + * If the provider config instances are identical per resource instance, the provider field will only exist on the resource. + +Note: This section should be expanded with examples. + +Note: `tofu show -json` and the internal statefile format are different and do not always line up one-to-one. + +## Provider Workflow + +When `config.Module` is built from `config.Files`, each module maintains: +* ProviderConfigs: map of `provider_name.provider_alias -> config.Provider` from provider config blocks in the parsed config +* ProviderRequirements: map of `provider_local_name -> config.RequiredProvider` from `terraform -> required_providers` +* ProviderLocalNames: map of `addrs.Provider -> provider_name` + +The full list of required provider types is collated, downloaded, hashed and cached in the .terraform directory during init. + +Providers are then added to the graph in a few transformers: +* ProviderConfigTransformer: Adds configured providers to the graph +* MissingProviderTransformer: Adds unconfigured but required providers to the graph +* ProviderTransformer: Links provider nodes to self reported nodes that require them +* ProviderFunctionTransformer: Links provider nodes to other nodes by inspecting their "OpenTofu Function References" +* ProviderPruneTransformer: Removes provider nodes that are not in use by other nodes + +Providers are then managed and scoped by the EvalContextBuiltin where the actual `provider.Interface`s are created and attached to resources. + + +## Provider Functions + +Providers also may supply functions, either unconfigured or configured. +* `providers::aws::arn_parse(var.arn)` +* `providers::aws::us::arn_parse(var.arn)` diff --git a/network-poc/static/docs/resource-instance-change-lifecycle.md b/network-poc/static/docs/resource-instance-change-lifecycle.md new file mode 100644 index 0000000..6357521 --- /dev/null +++ b/network-poc/static/docs/resource-instance-change-lifecycle.md @@ -0,0 +1,372 @@ +# OpenTofu Resource Instance Change Lifecycle + +This document describes the relationships between the different operations +called on a OpenTofu Provider to handle a change to a resource instance. + +![](https://user-images.githubusercontent.com/20180/172506401-777597dc-3e6e-411d-9580-b192fd34adba.png) + +The resource instance operations all both consume and produce objects that +conform to the schema of the selected resource type. + +The overall goal of this process is to take a **Configuration** and a +**Previous Run State**, merge them together using resource-type-specific +planning logic to produce a **Planned State**, and then change the remote +system to match that planned state before finally producing the **New State** +that will be saved in order to become the **Previous Run State** for the next +operation. + +The various object values used in different parts of this process are: + +* **Configuration**: Represents the values the user wrote in the configuration, + after any automatic type conversions to match the resource type schema. + + Any attributes not defined by the user appear as null in the configuration + object. If an argument value is derived from an unknown result of another + resource instance, its value in the configuration object could also be + unknown. + +* **Prior State**: The provider's representation of the current state of the + remote object at the time of the most recent read. + +* **Proposed New State**: OpenTofu Core uses some built-in logic to perform + an initial basic merger of the **Configuration** and the **Prior State** + 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 "computed". If an attribute is only "computed", + OpenTofu 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. + + OpenTofu Core therefore constructs the proposed new state by taking the + attribute value from Configuration if it is non-null, and then using the + Prior State as a fallback otherwise, thereby helping a provider to + preserve its previously-chosen value for the attribute where appropriate. + +* **Initial Planned State** and **Final Planned State** are both descriptions + of what the associated remote object ought to look like after completing + the planned action. + + There will often be parts of the object that the provider isn't yet able to + predict, either because they will be decided by the remote system during + the apply step or because they are derived from configuration values from + other resource instances that are themselves not yet known. The provider + must mark these by including unknown values in the state objects. + + The distinction between the _Initial_ and _Final_ planned states is that + the initial one is created during OpenTofu Core's planning phase based + on a possibly-incomplete configuration, whereas the final one is created + during the apply step once all of the dependencies have already been + updated and so the configuration should then be wholly known. + +* **New State** is a representation of the result of whatever modifications + were made to the remote system by the provider during the apply step. + + The new state must always be wholly known, because it represents the + actual state of the system, rather than a hypothetical future state. + +* **Previous Run State** is the same object as the **New State** from + the previous run of OpenTofu. This is exactly what the provider most + recently returned, and so it will not take into account any changes that + may have been made outside of OpenTofu in the meantime, and it may conform + to an earlier version of the resource type schema and therefore be + incompatible with the _current_ schema. + +* **Upgraded State** is derived from **Previous Run State** by using some + provider-specified logic to upgrade the existing data to the latest schema. + However, it still represents the remote system as it was at the end of the + last run, and so still doesn't take into account any changes that may have + been made outside of OpenTofu. + +* The **Import ID** and **Import Stub State** are both details of the special + process of importing pre-existing objects into a OpenTofu state, and so + we'll wait to discuss those in a later section on importing. + + +## Provider Protocol API Functions + +The following sections describe the three provider API functions that are +called to plan and apply a change, including the expectations OpenTofu Core +enforces for each. + +For historical reasons, the original OpenTofu SDK is exempt from error +messages produced when certain assumptions are violated, but violating them +will often cause downstream errors nonetheless, because OpenTofu's workflow +depends on these contracts being met. + +The following section uses the word "attribute" to refer to the named +attributes described in the resource type schema. A schema may also include +nested blocks, which contain their _own_ set of attributes; the constraints +apply recursively to these nested attributes too. + +The following are the function names used in provider protocol version 6. +Protocol version 5 has the same set of operations but uses some +marginally-different names for them, because we used protocol version 6 as an +opportunity to tidy up some names that had been awkward before. + +### ValidateResourceConfig + +`ValidateResourceConfig` takes the **Configuration** object alone, and +may return error or warning diagnostics in response to its attribute values. + +`ValidateResourceConfig` is the provider's opportunity to apply custom +validation rules to the schema, allowing for constraints that could not be +expressed via schema alone. + +In principle a provider can make any rule it wants here, although in practice +providers should typically avoid reporting errors for values that are unknown. +OpenTofu Core will call this function multiple times at different phases +of evaluation, and guarantees to _eventually_ call with a wholly-known +configuration so that the provider will have an opportunity to belatedly catch +problems related to values that are initially unknown during planning. + +If a provider intends to choose a default value for a particular +optional+computed attribute when left as null in the configuration, the +provider _must_ tolerate that attribute being unknown in the configuration in +order to get an opportunity to choose the default value during the later +plan or apply phase. + +The validation step does not produce a new object itself and so it cannot +modify the user's supplied configuration. + +### PlanResourceChange + +The purpose of `PlanResourceChange` is to predict the approximate effect of +a subsequent apply operation, allowing OpenTofu to render the plan for the +user and to propagate the predictable subset of results downstream through +expressions in the configuration. + +This operation can base its decision on any combination of **Configuration**, +**Prior State**, and **Proposed New State**, as long as its result fits the +following constraints: + +* Any attribute that was non-null in the configuration must either preserve + the exact configuration value or return the corresponding attribute value + from the prior state. (Do the latter if you determine that the change is not + functionally significant, such as if the value is a JSON string that has + changed only in the positioning of whitespace.) + +* Any attribute that is marked as computed in the schema _and_ is null in the + configuration may be set by the provider to any arbitrary value of the + expected type. + +* If a computed attribute has any _known_ value in the planned new state, the + provider will be required to ensure that it is unchanged in the new state + returned by `ApplyResourceChange`, or return an error explaining why it + changed. Set an attribute to an unknown value to indicate that its final + result will be determined during `ApplyResourceChange`. + +`PlanResourceChange` is actually called twice per run for each resource type. + +The first call is during the planning phase, before OpenTofu prints out a +diff to the user for confirmation. Because no changes at all have been applied +at that point, the given **Configuration** may contain unknown values as +placeholders for the results of expressions that derive from unknown values +of other resource instances. The result of this initial call is the +**Initial Planned State**. + +If the user accepts the plan, OpenTofu will call `PlanResourceChange` a +second time during the apply step, and that call is guaranteed to have a +wholly-known **Configuration** with any values from upstream dependencies +taken into account already. The result of this second call is the +**Final Planned State**. + +OpenTofu Core compares the final with the initial planned state, enforcing +the following additional constraints along with those listed above: + +* Any attribute that had a known value in the **Initial Planned State** must + have an identical value in the **Final Planned State**. + +* Any attribute that had an unknown value in the **Initial Planned State** may + either remain unknown in the second _or_ take on any known value that + conforms to the unknown value's type constraint. + +The **Final Planned State** is what passes to `ApplyResourceChange`, as +described in the following section. + +### ApplyResourceChange + +The `ApplyResourceChange` function is responsible for making calls into the +remote system to make remote objects match the **Final Planned State**. During +that operation, the provider should decide on final values for any attributes +that were left unknown in the **Final Planned State**, and thus produce the +**New State** object. + +`ApplyResourceChange` also receives the **Prior State** so that it can use it +to potentially implement more "surgical" changes to particular parts of +the remote objects by detecting portions that are unchanged, in cases where the +remote API supports partial-update operations. + +The **New State** object returned from the provider must meet the following +constraints: + +* Any attribute that had a known value in the **Final Planned State** must have + an identical value in the new state. In particular, if the remote API + returned a different serialization of the same value then the provider must + preserve the form the user wrote in the configuration, and _must not_ return + the normalized form produced by the provider. + +* Any attribute that had an unknown value in the **Final Planned State** must + take on a known value whose type conforms to the type constraint of the + unknown value. No unknown values are permitted in the **New State**. + +After calling `ApplyResourceChange` for each resource instance in the plan, +and dealing with any other bookkeeping to return the results to the user, +a single OpenTofu run is complete. OpenTofu Core saves the **New State** +in a state snapshot for the entire configuration, so it'll be preserved for +use on the next run. + +When the user subsequently runs OpenTofu again, the **New State** becomes +the **Previous Run State** verbatim, and passes into `UpgradeResourceState`. + +### UpgradeResourceState + +Because the state values for a particular resource instance persist in a +saved state snapshot from one run to the next, OpenTofu Core must deal with +the possibility that the user has upgraded to a newer version of the provider +since the last run, and that the new provider version has an incompatible +schema for the relevant resource type. + +OpenTofu Core therefore begins by calling `UpgradeResourceState` and passing +the **Previous Run State** in a _raw_ form, which in current protocol versions +is the raw JSON data structure as was stored in the state snapshot. OpenTofu +Core doesn't have access to the previous schema versions for a provider's +resource types, so the provider itself must handle the data decoding in this +upgrade function. + +The provider can then use whatever logic is appropriate to update the shape +of the data to conform to the current schema for the resource type. Although +OpenTofu Core has no way to enforce it, a provider should only change the +shape of the data structure and should _not_ change the meaning of the data. +In particular, it should not try to update the state data to capture any +changes made to the corresponding remote object outside of OpenTofu. + +This function then returns the **Upgraded State**, which captures the same +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 +OpenTofu Core to interact with the data fully for subsequent steps. + +### ReadResource + +Although OpenTofu typically expects to have exclusive control over any remote +object that is bound to a resource instance, in practice users may make changes +to those objects outside of OpenTofu, causing OpenTofu's records of the +object to become stale. + +The `ReadResource` function asks the provider to make a best effort to detect +any such external changes and describe them so that OpenTofu Core can use +an up-to-date **Prior State** as the input to the next `PlanResourceChange` +call. + +This is always a best effort operation because there are various reasons why +a provider might not be able to detect certain changes. For example: +* Some remote objects have write-only attributes, which means that there is + no way to determine what value is currently stored in the remote system. +* There may be new features of the underlying API which the current provider + version doesn't know how to ask about. + +OpenTofu Core expects a provider to carefully distinguish between the +following two situations for each attribute: +* **Normalization**: the remote API has returned some data in a different form + than was recorded in the **Previous Run State**, but the meaning is unchanged. + + In this case, the provider should return the exact value from the + **Previous Run State**, thereby preserving the value as it was written by + the user in the configuration and thus avoiding unwanted cascading changes to + elsewhere in the configuration. +* **Drift**: the remote API returned data that is materially different from + what was recorded in the **Previous Run State**, meaning that the remote + system's behavior no longer matches what the configuration previously + requested. + + In this case, the provider should return the value from the remote system, + thereby discarding the value from the **Previous Run State**. When a + provider does this, OpenTofu _may_ report it to the user as a change + made outside of OpenTofu, if OpenTofu Core determined that the detected + change was a possible cause of another planned action for a downstream + resource instance. + +This operation returns the **Prior State** to use for the next call to +`PlanResourceChange`, thus completing the circle and beginning this process +over again. + +## Handling of Nested Blocks in Configuration + +Nested blocks are a configuration-only construct and so the number of blocks +cannot be changed on the fly during planning or during apply: each block +represented in the configuration must have a corresponding nested object in +the planned new state and new state, or OpenTofu Core will raise an error. + +If a provider wishes to report about new instances of the sub-object type +represented by nested blocks that are created implicitly during the apply +operation -- for example, if a compute instance gets a default network +interface created when none are explicitly specified -- this must be done via +separate "computed" attributes alongside the nested blocks. This could be list +or map of objects that includes a mixture of the objects described by the +nested blocks in the configuration and any additional objects created implicitly +by the remote system. + +Provider protocol version 6 introduced the new idea of structural-typed +attributes, which are a hybrid of attribute-style syntax but nested-block-style +interpretation. For providers that use structural-typed attributes, they must +follow the same rules as for a nested block type of the same nesting mode. + +## Import Behavior + +The main resource instance change lifecycle is concerned with objects whose +entire lifecycle is driven through OpenTofu, including the initial creation +of the object. + +As an aid to those who are adopting OpenTofu as a replacement for existing +processes or software, OpenTofu also supports adopting pre-existing objects +to bring them under OpenTofu's management without needing to recreate them +first. + +When using this facility, the user provides the address of the resource +instance they wish to bind the existing object to, and a string representation +of the identifier of the existing object to be imported in a syntax defined +by the provider on a per-resource-type basis, which we'll call the +**Import ID**. + +The import process trades the user's **Import ID** for a special +**Import Stub State**, which behaves as a placeholder for the +**Previous Run State** pretending as if a previous OpenTofu run is what had +created the object. + +### ImportResourceState + +The `ImportResourceState` operation takes the user's given **Import ID** and +uses it to verify that the given object exists and, if so, to retrieve enough +data about it to produce the **Import Stub State**. + +OpenTofu Core will always pass the returned **Import Stub State** to the +normal `ReadResource` operation after `ImportResourceState` returns it, so +in practice the provider may populate only the minimal subset of attributes +that `ReadResource` will need to do its work, letting the normal function +deal with populating the rest of the data to match what is currently set in +the remote system. + +For the same reasons that `ReadResource` is only a _best effort_ at detecting +changes outside of OpenTofu, a provider may not be able to fully support +importing for all resource types. In that case, the provider developer must +choose between the following options: + +* Perform only a partial import: the provider may choose to leave certain + attributes set to `null` in the **Prior State** after both + `ImportResourceState` and the subsequent `ReadResource` have completed. + + In this case, the user can provide the missing value in the configuration + and thus cause the next `PlanResourceChange` to plan to update that value + to match the configuration. The provider's `PlanResourceChange` function + must be ready to deal with the attribute being `null` in the + **Prior State** and handle that appropriately. +* Return an error explaining why importing isn't possible. + + This is a last resort because of course it will then leave the user unable + to bring the existing object under OpenTofu's management. However, if a + particular object's design doesn't suit importing then it can be a better + user experience to be clear and honest that the user must replace the object + as part of adopting OpenTofu, rather than to perform an import that will + leave the object in a situation where OpenTofu cannot meaningfully manage + it. diff --git a/network-poc/static/docs/state_encryption.md b/network-poc/static/docs/state_encryption.md new file mode 100644 index 0000000..e173971 --- /dev/null +++ b/network-poc/static/docs/state_encryption.md @@ -0,0 +1,309 @@ +# State encryption + +This document details our intended implementation of the state and plan encryption feature. + +## Notes + +This document mentions `HCL` as a short-form for OpenTofu code. Unless otherwise specified, everything written also applies to the [JSON-equivalent of the HCL code](https://opentofu.org/docs/language/syntax/json/). + +## Goals + +The goal of this feature is to allow OpenTofu users to fully encrypt state files when they are stored on the local disk or transferred to a remote backend. The feature should also allow reading from an encrypted remote backend using the `terraform_remote_state` data source. The encrypted version should still be a valid JSON file, but not necessarily a valid state file. + +Furthermore, this feature should allow users to encrypt plan files when they are stored. However, plan files are not JSON, they are undocumented binary files and should be treated as such. + +For the encryption key, users should be able to specify a key directly, use a remote key provider (such as AWS KMS, etc.), or create derivative keys from another key source. The primary encryption method should be AES-GCM, but the implementation should be open to different encryption methods. The user should also have the ability to decrypt a state or plan file with one (older) key and then re-encrypt data with a newer key. Multiple fallbacks should be avoided in the implementation. + +To enable use cases where multiple teams need to collaborate, the user should be able to specify separate encryption methods and keys for individual uses, especially for the `terraform_remote_state` data source. However, to simplify configuration, the user should be able to specify a default configuration for all remote state data sources. + +It is the goal of this feature to let users specify their encryption configuration both in (HCL) code and in environment variables. The latter is necessary to allow users the reuse of code for both encrypted and unencrypted state storage. + +Finally, it is the goal of the encryption feature to make available a library that third party tooling can use to encrypt and decrypt state. This may be implemented as a package within the OpenTofu repository, or as a standalone repository. + +## Possible future goals + +This section describes possible future goals. However, these goals are merely aspirations, and we may or may not implement them, or implement them differently based on community feedback. We describe these aspirations here to make clear which features we intentionally left out of scope for the current implementation. + +Users use CI/CD systems or security scanners that need to read the state or plan files, but may not fully trust these systems. In the future, the user should be able to specify partial encryption. This encryption type would only encrypt sensitive values instead of the whole state file. + +At this time, due to the limitations on passing providers through to modules, encryption configuration is global. However, in the future, the user should be able to create a module that carries along their own encryption method and how it relates to the `terraform_remote_state` data sources. This is important so individual teams can ship ready-to-use modules to other teams that access their state. However, due to the constraints on passing resources to modules this is currently out of scope for this proposal. + +Finally, it is a future goal to enable providers to provide their own key providers and encryption methods. Users may also want to create additional, encryption-related, such as merely signing plan files, which this functionality would enable. + +## Non-goals + +In this section we describe the features that are out of scope for state and plan encryption. We do not aspire to solve these problems with the same implementation, and they must be addressed separately if the community chooses to support these endeavours. + +The primary goal of this feature is to protect state and plan files **at rest**. It is not the goal of this feature to protect other channels secrets may be accessed through, such as the JSON output. As such, it is not a goal of this feature to encrypt any output on the standard output, or file output that is not a state or plan file. + +Furthermore, it is not a goal of this feature to *authenticate* that the user is running an up-to-date plan file. It does not protect against, among others, replay attacks where a malicious actor replaces a current plan or state file with an old one. + +It is also not a goal of this feature to protect the state file against the operator of the device running `tofu`. The operator already has access to the encryption key and can decrypt the data without the `tofu` binary being present if they so chose. + +## User-facing effects + +Unless the user explicitly specifies encryption options, no encryption will take place and OpenTofu will continue to function as before. No forced encryption will take place. Furthermore, regardless of the encryption status, other functionality, such as state management CLI functions, JSON output, etc. remain unaffected and will be readable in plain text if they were readable as plain text before. Only state and plan files will be affected by the encryption. + +Users will be able to specify their encryption configuration both in code and via environment variables. Both configurations are equivalent and will be merged at execution time. For more details, see the [environment configuration](#environment-configuration) section below. + +When a user wants to enable encryption, they must specify the following block: + +```hcl2 +terraform { + encryption { + // Encryption options + } +} +``` + +The mere presence of the `encryption` block alone should not enable encryption because the user should explicitly specify what key and method to use. The implementation should error and alert the user if the encryption block is present but has no configuration. + +The encryption relies on an encryption key, or a composite encryption key, which the user can provide directly or via a key management system. The user must provide at least one `key_provider` block with the settings described below. These key providers serve the purpose of creating or providing the encryption key. For example, the user could hard-code a static key named foo: + +```hcl2 +terraform { + encryption { + key_provider "static" "foo" { + key = "6f6f706830656f67686f6834616872756f3751756165686565796f6f72653169" + } + } +} +``` + +> [!NOTE] +> The user is responsible for keeping this key safe and follow disaster recovery best practices. OpenTofu is a read-only consumer for the key the user provided and will not perform tasks on the key management system like key rotation. + +The user also has to specify at least one encryption method referencing the key provider. This encryption method determines how the encryption takes place. It is the user's responsibility to make sure that they provided a key that is suitable for the encryption method. + +```hcl2 +terraform { + encryption { + //... + method "aes_gcm" "bar" { + key_provider = key_provider.static.foo + } + } +} +``` + +Finally, the user must reference the method for use in their state file, plan file, etc. This enables creating a different configuration for different purposes. + +```hcl2 +terraform { + encryption { + //... + state { + method = method.aes_gcm.abc + } + plan { + method = method.aes_gcm.cde + } + remote_state_data_sources { + default { + method = method.aes_gcm.ghi + } + remote_state_data_source "some_module.remote_data_source.foo" { + method = method.aes_gcm.ijk + } + } + } +} +``` + +To facilitate key and method rollover, the user can specify a fallback configuration for state and plan decryption. When the user specifies a `fallback` block, `tofu` will first attempt to decrypt any state or plan it reads with the primary method and then fall back to the `fallback` method. When `tofu` writes a state or plan, it will not use the `fallback` method and always writes with the primary method. + +```hcl2 +terraform { + encryption { + //... + state { + method = method.aes_gcm.bar + fallback { + method = method.aes_gcm.baz + } + } + } +} +``` + +> [!NOTE] +> The `fallback` is a block because the future goals may require adding additional options. + +> [!NOTE] +> Multiple `fallback` blocks should not be supported or should be discouraged because they would be detrimental to performance and encourage keeping old encryption keys in the configuration. + +In the situation where `enforce` is not set to true, and no `method` or `fallback` is specified, no encryption will take place. If the user does not specify a method, but specifies a fallback, the next apply command will disable the encryption given that `enforce` is not set to true. This is to allow the user to disable encryption without removing the encryption configuration from the code. + +### Composite keys + +When a user desires to create a composite key, such as for creating a passphrase-based derivative key or a shared custody key, they may avail themselves of a key provider that supports multiple inputs. The user can chain key providers together: + +```hcl2 +terraform { + encryption { + key_provider "static" "my_passphrase" { + key = "this is my encryption key" + } + key_provider "some_derivative_key_provider" "my_derivative_key" { + key_providers = [key_provider.static.my_passphrase] + } + method "aes_gcm" "foo" { + key_provider = key_provider.some_derivative_key_provider.my_derivative_key + } + //... + } +} +``` + +> [!NOTE] +> The specific implementation of the derivative key must pay attention to combine the keys securely if it supports multiple key providers as inputs, such as using HMAC to combine keys. + +### Environment configuration + +As mentioned above, users can configure encryption in environment variables, either as HCL or JSON. To do this, the user has to specify the encryption configuration fragment in either of the two formats. The following two examples are equivalent: + +```hcl2 +key_provider "static" "my_key" { + key = "this is my encryption key" +} +method "aes_gcm" "foo" { + key_provider = key_provider.static.my_key +} +state { + method = method.aes_gcm.foo +} +``` + +```json +{ + "key_provider" : { + "static": { + "my_key": { + "key": "this is my encryption key" + } + } + }, + "method": { + "aes_gcm": { + "foo": { + "key_provider": "${key_provider.static.my_key}" + } + } + }, + "state": { + "method": "${method.aes_gcm.foo}" + } +} +``` + +The user can set either of these structures in the `TF_ENCRYPTION` environment variable: + +```bash +export TF_ENCRYPTION='{"key_provider":{...},"method":{...},"state":{...}}' +``` + +When the user specifies both an environment and a code configuration, `tofu` merges the two configurations. If two values conflict, the environment configuration takes precedence. + +To ensure that the encryption cannot be accidentally forgotten or disabled and the data stored unencrypted, the user can specify the `enforced` option in the HCL configuration: + +```hcl2 +terraform { + encryption { + //... + state { + enforced = true + } + plan { + enforced = true + } + } +} +``` + +> [!NOTE] +> The `enforced` option is also available in the environment configuration and works as intended, but doesn't make much sense because its primary purpose is to guard against environment variable omission. + +## Encrypted state format + +When `tofu` encrypts a state file, the encrypted state is still a JSON file. Any implementations can distinguish encrypted files by the `encryption` key being present in the JSON structure. However, there may be other keys in the state file depending on the encryption method and type. + +For example (not final): + +```json +{ + "encryption": { + "method": "aes_gcm", + "key_provider": "static.my_key" + }, + // ... Additional keys here +} +``` + +> [!WARNING] +> Tools working with state files should not make assumptions about the type or structure of the `encryption` field as it may vary from implementation to implementation. + +## Encrypted plan format + +An unencrypted plan file in OpenTofu is an opaque binary. This specification makes no rules for how the encrypted format should look like and all non-encryption routines should treat the value as opaque. + +## Implementation + +When implementing the encryption tooling, the implementation should be split in two parts: the library and the OpenTofu implementation. The library should rely on the cty types and hcl as a means to specify schema, but should not be otherwise tied to the OpenTofu codebase. This is necessary to enable encryption capabilities for third party tooling that may need to work with state and plan files. + +### Library implementation + +The encryption library should create an interface that other projects and OpenTofu itself can use to encrypt and decrypt state. The library should express its schema needs (e.g. for key provider config) using [cty](https://github.com/zclconf/go-cty) and [hcl](https://github.com/hashicorp/hcl), but be otherwise independent of the OpenTofu codebase. Ideally, the OpenTofu project should provide this library as a standalone dependency that does not pull in the entire OpenTofu dependency tree. + +#### Encryption interface + +The main component of the library should be the `Encryption` interface. This interface should provide methods to request an encryption tool for each individual purpose, such as: + +```go +type Encryption interface { + State() StateEncryption + Plan() PlanEncryption + RemoteState(string) StateEncryption +} +``` + +Each of the returned encryption tools should provide methods to encrypt the data of the specified purpose, such as: + +```go +type StateEncryption interface { + DecryptState([]byte) ([]byte, error) + EncryptState([]byte) ([]byte, error) +} +``` + +The encryption routines should assume that they get passed a valid state or plan file and encrypt it as described in this document. Conversely, the decryption routines should assume that their input will be an encrypted state or plan file and should attempt to decrypt. The state decryption function should follow the fallback process described in this document. + +#### Key providers + +The main responsibility of a key provider is providing a key in a `[]byte`. It may consume structured configuration, which may also include references to other key providers. However, an implementation of a key provider should never have to deal with resolving these dependencies. Instead, the library should correctly resolve the key provider order and look up the keys in the right order and pass the already-resolved data in as [configuration](#configuration). + +In addition to the encryption key, key providers may also emit additional metadata. The library must store this metadata alongside the encrypted data and pass it to the key provider when initializing the key provider for decryption in a subsequent run. The key provider is responsible for ensuring that no sensitive data is stored in the metadata. + +> [!NOTE] +> Since a user can chain key providers, the library must make sure to store metadata from all key providers in the encrypted form. However, when the user renames the key provider the library may fail to decrypt the state or plan files if the user fails to provide an adequate fallback with the correct naming. The documentation for this feature should encourage users to create new key providers if they change the parameters in a backwards-incompatible manner, and they want to decrypt older state or plan files. + +#### Methods + +The responsibility of a method is to encrypt and decrypt an opaque block of data. The method is not responsible for understanding the structure of the data. Instead, the library core should take care of traversing the state or plan files and deciding specifically what to encrypt. A method must implement the encrypted format in such a way that it can determine if a subsequent decryption failed or not. Methods that cannot decide on decryption success without validating the underlying data, such as rot13, are not supported. + +Similar to [key providers](#key-providers), the method may need configuration but should not have to deal with lookup up key providers itself. + +#### Registering key providers and methods + +The library should be modular. Anyone using the library, including OpenTofu, should be able to add new key providers and methods and read the configuration for these without modifying the library code. To that end, the library should provide a registry for key providers and methods. + +The library should also not force any included key providers or methods onto its user, so the registry should not be global. Instead, every library user should configure their own registry. However, the library should provide a way to obtain a preconfigured registry with built-in key providers and methods. + +#### Configuration + +In order to ensure consistency between OpenTofu and other library users, the library should provide a method to parse an HCL or JSON block and turn it into configuration structures. In parallel, the library should also make it as simple as possible for implementers to safely provide new key providers and methods, which is why the library should also use struct tags in Go to convert the incoming configuration. + +```go +type Config struct { + Key string `hcl:"key"` +} +``` diff --git a/network-poc/static/docs/tofu-cheatsheet.md b/network-poc/static/docs/tofu-cheatsheet.md new file mode 100644 index 0000000..8446095 --- /dev/null +++ b/network-poc/static/docs/tofu-cheatsheet.md @@ -0,0 +1,102 @@ +# OpenTofu Quick Reference + +## Core Architecture +- Graph-based execution: resources form a DAG, parallel where possible +- Provider plugins communicate via gRPC (plugin protocol v5/v6) +- State tracks resource → real-world mapping (JSON format) +- Plan → Apply workflow: always preview before changing + +## HCL Essentials +```hcl +terraform { + required_providers { + aws = { source = "hashicorp/aws", version = "~> 5.0" } + } +} + +provider "aws" { region = "eu-north-1" } + +resource "aws_instance" "web" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t3.micro" + tags = { Name = "web-server" } +} + +variable "env" { + type = string + default = "dev" +} + +output "ip" { value = aws_instance.web.public_ip } + +data "aws_ami" "latest" { + most_recent = true + owners = ["amazon"] + filter { + name = "name" + values = ["al2023-ami-*-x86_64"] + } +} +``` + +## Resource Lifecycle +- create_before_destroy: new resource before destroying old +- prevent_destroy: block accidental deletion +- ignore_changes: skip drift on specified attributes +- replace_triggered_by: force replacement when dependency changes + +## Destroy Order +- Destroy runs in reverse dependency order +- ForceDestroy needed for resources with dependencies +- Deposed instances cleaned up automatically + +## State Encryption (OpenTofu-specific) +```hcl +terraform { + encryption { + key_provider "pbkdf2" "main" { + passphrase = var.state_passphrase + } + method "aes_gcm" "main" { + keys = key_provider.pbkdf2.main + } + state { + method = method.aes_gcm.main + enforced = true + } + } +} +``` + +## Module Structure +``` +modules/ + vpc/ + main.tf + variables.tf + outputs.tf + app/ + main.tf + variables.tf + outputs.tf +main.tf # root module +variables.tf +outputs.tf +terraform.tfvars +``` + +## Key Commands +- tofu init: initialize providers and modules +- tofu plan: preview changes +- tofu apply: execute changes +- tofu destroy: remove all resources +- tofu state list/show/mv/rm: state management +- tofu import: bring existing resource under management + +## Best Practices +- Always use required_providers with version constraints +- Use variables for environment-specific values +- State encryption for sensitive data (OpenTofu feature) +- Modules for reusable infrastructure patterns +- Remote state backend for team collaboration +- Plan file for CI/CD: tofu plan -out=plan.bin && tofu apply plan.bin diff --git a/network-poc/static/docs/tracing.md b/network-poc/static/docs/tracing.md new file mode 100644 index 0000000..16e118b --- /dev/null +++ b/network-poc/static/docs/tracing.md @@ -0,0 +1,147 @@ +# OpenTofu Tracing Guide + +This document describes how to use and implement tracing in OpenTofu Core using OpenTelemetry. + +There's background information on OpenTofu's tracing implementation in [the OpenTelemetry Tracing RFC](https://github.com/opentofu/opentofu/blob/main/rfc/20250129-Tracing-For-Extra-Context.md) + +> [!WARNING] +> If you change which version of the `go.opentelemetry.io/otel/sdk` we have selected in our `go.mod`, you **must** make sure that `internal/tracing/traceattrs/semconv.go` imports the same subpackage of `go.opentelemetry.io/otel/semconv/*` that is used by the selected version of `go.opentelemetry.io/otel/sdk`. +> +> This is important because our tracing setup uses a blend of directly-constructed `semconv` attributes and attributes chosen indirectly through the `resource` package, and they must all be using the same version of the semantic conventions schema or there will be a "conflicting Schema URL" error at runtime. +> +> (Problems of this sort should be detected both by a unit test in `internal/tracing/traceattrs` and an end-to-end test that executes OpenTofu with tracing enabled.) + +## Overview + +OpenTofu provides distributed tracing capabilities via OpenTelemetry to help end users understand the execution flow and performance characteristics of OpenTofu operations. Tracing is particularly useful for: + +- Debugging performance issues (e.g., "Why is my plan taking so long?") +- Understanding time spent in different operations +- Visualizing the execution flow across providers and modules +- Diagnosing issues in CI/CD pipelines + +Tracing in OpenTofu is **strictly opt-in** and disabled by default. It's designed to have minimal overhead when disabled and to provide valuable insights when enabled. + +> [!IMPORTANT] +> OpenTofu's tracing functionality refers only to OpenTelemetry traces for local debugging and analysis. +> No telemetry or usage data is sent to external servers, and no data leaves your environment unless you explicitly configure an external collector. + +## Enabling Tracing + +To enable tracing in OpenTofu: + +1. Set the environment variable `OTEL_TRACES_EXPORTER=otlp` +2. Configure the OpenTelemetry exporter using standard OpenTelemetry environment variables + +Example configuration for a local Jaeger collector: + +```bash +export OTEL_TRACES_EXPORTER=otlp +export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 +export OTEL_EXPORTER_OTLP_INSECURE=true +``` + +For a complete list of configuration options, refer to the [OpenTelemetry Documentation](https://opentelemetry.io/docs/specs/otel/protocol/exporter/). + +## Quick Start with Jaeger + +To quickly spin up a local Jaeger instance with OTLP support: + +```bash +docker run -d --rm --name jaeger \ + -p 16686:16686 \ + -p 4317:4317 \ + -p 4318:4318 \ + -p 5778:5778 \ + -p 9411:9411 \ + jaegertracing/jaeger:2.5.0 +``` + +Then configure OpenTofu as shown above and access the Jaeger UI at http://localhost:16686. + +## Adding Tracing to OpenTofu Code + +> [!NOTE] +> **For Contributors**: When adding tracing to OpenTofu, remember that the primary audience is **end users** who need to understand performance, not OpenTofu developers. Add spans sparingly to avoid polluting traces with too much detail. + +### Basic Span Creation + +```go +import ( + "github.com/opentofu/opentofu/internal/tracing" + "github.com/opentofu/opentofu/internal/tracing/traceattrs" +) + +func SomeFunction(ctx context.Context) error { + // Create a new span + ctx, span := tracing.Tracer().Start(ctx, "Human readable operation name", + tracing.SpanAttributes( + traceattrs.String("opentofu.some_attribute", "value") + ), + ) + defer span.End() + + // Optionally add additional attributes after the span is created, if + // they only need to appear in certain cases. + span.SetAttributes(traceattrs.String("opentofu.some_other_attribute", "value")) + + // Use the more specific attribute-construction helpers from package + // traceattrs where they are relevant, to ensure we follow consistent + // semantic conventions for cross-cutting concerns. + span.SetAttributes(traceattrs.OpenTofuProviderAddress("hashicorp/aws")) + + // Your function logic here... + + // If an error occurs + if err != nil { + tracing.SetSpanError(span, err) + return err + } + + return nil +} +``` + +OpenTelemetry has many different packages spread across a variety of different Go modules, and those different modules often need to be upgraded together to ensure consistent behavior and avoid errors at runtime. + +Therefore we prefer to directly import `go.opentelemetry.io/otel/*` packages only from our packages under `internal/tracing`, and then reexport certain functions from our own packages so that we can manage all of the OpenTelemetry dependencies in a centralized place to minimize "dependency hell" problems when upgrading. Packages under `go.opentelemetry.io/contrib/instrumentation/*` are an exception because they tend to be more tightly-coupled to whatever they are instrumenting than to the other OpenTelemetry packages, and so it's better to import those from the same file that's importing whatever other package the instrumentation is being applied to. + +> [!WARNING] +> Don't import `go.opentelemetry.io/otel/semconv/*` packages from anywhere except `internal/tracing/traceattrs/semconv.go`! +> +> If you want to use standard OpenTelemetry semantic conventions from other packages, use them indirectly through reexports in `package traceattrs` instead, so we can make sure there's only one file in OpenTofu deciding which version of semconv we are currently depending on. + +### Tracing Conventions + +#### Span Naming + +- Use human-readable, action-oriented names that describe operations from a user perspective +- Prefer names like "Provider installation" over internal function names like "InstallProvider" +- Use consistent terminology from the OpenTofu CLI and documentation +- Span names should represent UX-level concepts, not internal code structure + +#### Attributes + +- Prefer standard [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) where applicable, using helper functions from [`internal/tracing/traceattrs`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tracing/traceattrs). +- Use `OpenTofu`-prefixed functions in [`internal/tracing/traceattrs`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tracing/traceattrs) for OpenTofu-specific cross-cutting concerns. +- It's okay to use one-off inline strings for attribute names specific to a single span, but make sure to still follow the [OpenTelemetry attribute naming conventions](https://opentelemetry.io/docs/specs/semconv/general/naming/) and use the `opentofu.` prefix for anything that is not a standardized semantic convention. +- If a particular subsystem of OpenTofu has some repeated conventions for attribute names, consider creating unexported string constants or attribute construction helper functions in the same package to centralize those naming conventions. + +#### Error Handling + +Use the `tracing.SetSpanError` helper to consistently record errors: + +```go +if err != nil { + tracing.SetSpanError(span, err) + return err +} +``` + +This helper supports various error types including standard errors, strings, and OpenTofu diagnostics. + +### Instrumentation Guidelines + +1. **Focus on Key Operations**: Instrument high-level operations that are meaningful to end users rather than every internal function. +2. **Include Valuable Context**: Add attributes that help identify resources, modules, or operations. +3. **Respect Performance**: Avoid expensive computations solely for tracing. diff --git a/network-poc/static/docs/unicode.md b/network-poc/static/docs/unicode.md new file mode 100644 index 0000000..1660d4c --- /dev/null +++ b/network-poc/static/docs/unicode.md @@ -0,0 +1,142 @@ +# How OpenTofu Uses Unicode + +The OpenTofu language uses the Unicode standards as the basis of various +different features. The Unicode Consortium publishes new versions of those +standards periodically, and we aim to adopt those new versions in new +minor releases of OpenTofu in order to support additional characters added +in those new versions. + +Unfortunately due to those features being implemented by relying on a number +of external libraries, adopting a new version of Unicode is not as simple as +just updating a version number somewhere. This document aims to describe the +various steps required to adopt a new version of Unicode in OpenTofu. + +We typically aim to be consistent across all of these dependencies as to which +major version of Unicode we currently conform to. The usual initial driver +for a Unicode upgrade is switching to new version of the Go runtime library +which itself uses a new version of Unicode, because Go itself does not provide +any way to select Unicode versions independently from Go versions. Therefore +we typically upgrade to a new Unicode version only in conjunction with +upgrading to a new Go version. + +## Unicode tables in the Go standard library + +Several OpenTofu language features are implemented in terms of functions in +[the Go `strings` package](https://pkg.go.dev/strings), +[the Go `unicode` package](https://pkg.go.dev/unicode), and other supporting +packages in the Go standard library. + +The Go team maintains the Go standard library features to support a particular +Unicode version for each Go version. The specific Unicode version for a +particular Go version is available in +[`unicode.Version`](https://pkg.go.dev/unicode#Version). + +We adopt a new version of Go by editing the `go.mod` file in the root +of this repository. Although it's typically possible to build OpenTofu with +other versions of Go, that file documents the version we intend to use for +official releases and thus the primary version we use for development and +testing. Adopting a new Go version typically also implies other behavior +changes inherited from the Go standard library, so it's important to review the +relevant version changelog(s) to note any behavior changes we'll need to pass +on to our own users via the OpenTofu changelog. + +The other subsystems described below should always be set up to match +`unicode.Version`. In some cases those libraries automatically try to align +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 OpenTofu is the primary user of HCL, it's typically OpenTofu'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 OpenTofu to use the new version + of HCL. + +## Unicode Text Segmentation + +_Text Segmentation_ (TR29) is a Unicode standards annex which describes +algorithms for breaking strings into smaller units such as sentences, words, +and grapheme clusters. + +Several OpenTofu language features make use of the _grapheme cluster_ +algorithm in particular, because it provides a practical definition of +individual visible characters, taking into account combining sequences such +as Latin letters with separate diacritics or Emoji characters with gender +presentation and skin tone modifiers. + +The text segmentation algorithms rely on supplementary data tables that are +not part of the core set encoded in the Go standard library's `unicode` +packages, and so instead we rely on the third-party module +[`github.com/apparentlymart/go-textseg`](http://pkg.go.dev/github.com/apparentlymart/go-textseg) +to provide those tables and a Go implementation of the grapheme cluster +segmentation algorithm in terms of the tables. + +The `go-textseg` library is designed to allow calling programs to potentially +support multiple Unicode versions at once, by offering a separate module major +version for each Unicode major version. For example, the full module path for +the Unicode 13 implementation is `github.com/apparentlymart/go-textseg/v13`. + +If that external library doesn't yet have support for the Unicode version we +intend to adopt then we'll first need to open a pull request to contribute +new language support. The details of how to do this will unfortunately vary +depending on how significantly the Text Segmentation annex has changed since +the most recently-supported Unicode version, but in many cases it can be +just a matter of editing that library's `make_tables.go`, `make_test_tables.go`, +and `generate.go` files to point to the URLs where the Unicode consortium +published new tables and then run `go generate` to rebuild the files derived +from those data sources. As long as the new Unicode version has only changed +the data tables and not also changed the algorithm, often no further changes +are needed. + +Once a new Unicode version is included, the maintainer of that library will +typically publish a new major version that we can depend on. Two different +codebases included in OpenTofu all depend directly on the `go-textseg` module +for parts of their functionality: + +* [`hashicorp/hcl`](https://github.com/hashicorp/hcl) uses text + segmentation as part of producing visual column offsets in source ranges + returned by the tokenizer and parser. OpenTofu in turn uses that library + for the underlying syntax of the OpenTofu language, and so it passes on + those source ranges to the end-user as part of diagnostic messages. +* The third-party module [`github.com/zclconf/go-cty`](https://github.com/zclconf/go-cty) + provides several of the OpenTofu language built in functions, including + functions like `substr` and `length` which need to count grapheme clusters + as part of their implementation. + +As part of upgrading OpenTofu's Unicode support we therefore typically also +open pull requests against these other codebases, and then adopt the new +versions that produces. OpenTofu work often drives the adoption of new Unicode +versions in those codebases, with other dependencies following along when they +next upgrade. + +At the time of writing OpenTofu itself doesn't _directly_ depend on +`go-textseg`, and so there are no specific changes required in this OpenTofu +codebase aside from the `go.sum` file update that always follows from +changes to transitive dependencies. + +The `go-textseg` library does have a different "auto-version" mechanism which +selects an appropriate module version based on the current Go language version, +but neither HCL nor cty use that because the auto-version package will not +compile for any Go version that doesn't have a corresponding Unicode version +explicitly recorded in that repository, and so that would be too harsh a +constraint for libraries like HCL which have many callers, many of which don't +care strongly about Unicode support, that may wish to upgrade Go before the +text segmentation library has been updated. diff --git a/network-poc/static/index.html b/network-poc/static/index.html index 15bca38..2191d1a 100644 --- a/network-poc/static/index.html +++ b/network-poc/static/index.html @@ -1057,6 +1057,10 @@ DevOps

DevOps
+
+ Tofuist +
Tofuist
+
Tarkkailija
Tarkkailija
@@ -1091,6 +1095,7 @@ +
@@ -1159,6 +1164,7 @@ data: { name: 'Data-Agentti — System Prompt', model: 'qwen-coder', default: 'Olet tietokanta-asiantuntija. Vastaat skeemojen suunnittelusta, SQL-kyselyiden optimoinnista ja datamalleista.' }, qa: { name: 'QA — System Prompt', model: 'qwen-coder', default: 'Olet laadunvarmistaja (QA). Kirjoitat testejä, etsit virheitä ja varmistat, että kaikki reunatapaukset on huomioitu.' }, tester: { name: 'DevOps — System Prompt', model: 'qwen-coder', default: 'Olet DevOps-insinööri. Kirjoitat Dockerfile- ja docker-compose.yml-tiedostot, README:t ja käynnistysohjeet. Käytä aina multi-stage Docker buildia ja docker compose -orkestrointia.' }, + tofuist: { name: 'Tofuist — System Prompt', model: 'qwen-coder', docs: '/docs/tofu-cheatsheet.md', default: 'You are an OpenTofu/Terraform IaC specialist. You write HCL infrastructure code: providers, resources, modules, variables, outputs, state management, and encryption. You follow OpenTofu best practices: use planning behaviors before apply, handle resource lifecycle (create_before_destroy, prevent_destroy), configure state encryption for sensitive data, and structure code with clear module boundaries. Always output valid HCL code. Use provider references correctly (required_providers block). Prefer data sources over hardcoded values.' }, }; const selectedAgents = new Set(); let sharedPrompt = localStorage.getItem('kpn-shared-prompt') || ''; @@ -1386,7 +1392,7 @@ const title = document.getElementById('prompt-modal-title'); const fields = document.getElementById('prompt-modal-fields'); - const agentNames = { manager: 'Manageri', coder: 'Koodari', tester: 'DevOps', qa: 'QA', data: 'Data' }; + const agentNames = { manager: 'Manageri', coder: 'Koodari', tester: 'DevOps', qa: 'QA', data: 'Data', tofuist: 'Tofuist' }; title.textContent = `${agentNames[agent] || agent} — ${label}`; fields.innerHTML = modalPromptParts.map((f, i) => ` @@ -2054,6 +2060,14 @@ IMPORTANT: Include get_db() dependency for FastAPI` }, const parts = []; if (sharedPrompt) parts.push(sharedPrompt); if (agent && agent.prompt) parts.push(agent.prompt); + // Ladataan agentin docs-referenssi (esim. OpenTofu cheatsheet) + if (agent && agent.docs && !agent._docsCache) { + try { + const r = await fetch(agent.docs); + if (r.ok) agent._docsCache = await r.text(); + } catch(e) { /* docs ei saatavilla */ } + } + if (agent && agent._docsCache) parts.push('Reference:\n' + agent._docsCache); parts.push(prompt); const fullPrompt = parts.join('\n\n'); @@ -2140,7 +2154,7 @@ IMPORTANT: Include get_db() dependency for FastAPI` }, } renderPipelineSteps(); // Päivitetään agentin avatar tooltip + vilahdus - const avatarMap = { manager: 'avatar-kpn', coder: 'avatar-coder', tester: 'avatar-tester', qa: 'avatar-qa', data: 'avatar-data' }; + const avatarMap = { manager: 'avatar-kpn', coder: 'avatar-coder', tester: 'avatar-tester', qa: 'avatar-qa', data: 'avatar-data', tofuist: 'avatar-tofuist' }; const avatarId = avatarMap[agent]; if (avatarId) { const el = document.getElementById(avatarId); @@ -2170,7 +2184,7 @@ IMPORTANT: Include get_db() dependency for FastAPI` }, if (pipelineSteps.length === 0) { container.style.display = 'none'; return; } container.style.display = 'flex'; container.innerHTML = pipelineSteps.map((s, i) => { - const colors = { manager: '#d29922', coder: '#3fb950', tester: '#58a6ff', qa: '#a371f7', data: '#d2a8ff' }; + const colors = { manager: '#d29922', coder: '#3fb950', tester: '#58a6ff', qa: '#a371f7', data: '#d2a8ff', tofuist: '#e3a336' }; const color = colors[s.agent] || '#8b949e'; const icon = s.status === 'done' ? '✓' : s.status === 'active' ? '◷' : '◯'; const iconColor = s.status === 'done' ? '#3fb950' : s.status === 'active' ? '#d29922' : '#8b949e'; @@ -2837,8 +2851,8 @@ ${fixableFiles}`; function generateProjectReport(task, files, steps, staticIssues) { const fileEntries = Object.entries(files); - const agentNames = { manager: 'Manageri', coder: 'Koodari', tester: 'DevOps', qa: 'QA', data: 'Data' }; - const agentColors = { manager: '#d29922', coder: '#3fb950', tester: '#58a6ff', qa: '#a371f7', data: '#d2a8ff' }; + const agentNames = { manager: 'Manageri', coder: 'Koodari', tester: 'DevOps', qa: 'QA', data: 'Data', tofuist: 'Tofuist' }; + const agentColors = { manager: '#d29922', coder: '#3fb950', tester: '#58a6ff', qa: '#a371f7', data: '#d2a8ff', tofuist: '#e3a336' }; // Syntaksikorostus: kevyt regex-pohjainen highlighter function highlightCode(code, filename) { @@ -2948,9 +2962,9 @@ ${filesHtml} } function generateWorkflowSwimlane(steps) { - const agentLabels = { manager: 'Manageri', coder: 'Koodari', tester: 'DevOps', qa: 'QA', data: 'Data' }; - const agentColors = { manager: '#d29922', coder: '#3fb950', tester: '#58a6ff', qa: '#a371f7', data: '#d2a8ff' }; - const agentBgs = { manager: '#1c1206', coder: '#0d1a0d', tester: '#0d1520', qa: '#170d22', data: '#1a0d22' }; + const agentLabels = { manager: 'Manageri', coder: 'Koodari', tester: 'DevOps', qa: 'QA', data: 'Data', tofuist: 'Tofuist' }; + const agentColors = { manager: '#d29922', coder: '#3fb950', tester: '#58a6ff', qa: '#a371f7', data: '#d2a8ff', tofuist: '#e3a336' }; + const agentBgs = { manager: '#1c1206', coder: '#0d1a0d', tester: '#0d1520', qa: '#170d22', data: '#1a0d22', tofuist: '#1a1506' }; const stepDescs = { 'Suunnittelu': 'Jakaa projektin tiedostoiksi', 'Review': 'Tarkistaa koodin laadun', 'Testit': 'Kirjoittaa pytest-testit', 'Dockerfile': 'Generoi Docker-imagen', 'Compose': 'Palvelumääritys', 'README': 'Käyttöohjeet', 'Validointi': 'Tarkistaa yhteensopivuuden', 'Korjaukset': 'Korjaa löydetyt ongelmat' }; var agents = [];