-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
014db87
commit ffa87cd
Showing
38 changed files
with
9,618 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package tfprotov6 | ||
|
||
import ( | ||
"context" | ||
) | ||
|
||
// DataSourceServer is an interface containing the methods a data source | ||
// implementation needs to fill. | ||
type DataSourceServer interface { | ||
// ValidateDataResourceConfig is called when Terraform is checking that a | ||
// data source's configuration is valid. It is guaranteed to have types | ||
// conforming to your schema, but it is not guaranteed that all values | ||
// will be known. This is your opportunity to do custom or advanced | ||
// validation prior to a plan being generated. | ||
ValidateDataResourceConfig(context.Context, *ValidateDataResourceConfigRequest) (*ValidateDataResourceConfigResponse, error) | ||
|
||
// ReadDataSource is called when Terraform is refreshing a data | ||
// source's state. | ||
ReadDataSource(context.Context, *ReadDataSourceRequest) (*ReadDataSourceResponse, error) | ||
} | ||
|
||
// ValidateDataResourceConfigRequest is the request Terraform sends when it wants | ||
// to validate a data source's configuration. | ||
type ValidateDataResourceConfigRequest struct { | ||
// TypeName is the type of data source Terraform is validating. | ||
TypeName string | ||
|
||
// Config is the configuration the user supplied for that data source. | ||
// See the documentation on `DynamicValue` for more information about | ||
// safely accessing the configuration. | ||
// | ||
// The configuration is represented as a tftypes.Object, with each | ||
// attribute and nested block getting its own key and value. | ||
// | ||
// This configuration may contain unknown values if a user uses | ||
// interpolation or other functionality that would prevent Terraform | ||
// from knowing the value at request time. | ||
Config *DynamicValue | ||
} | ||
|
||
// ValidateDataResourceConfigResponse is the response from the provider about the | ||
// validity of a data source's configuration. | ||
type ValidateDataResourceConfigResponse struct { | ||
// Diagnostics report errors or warnings related to the given | ||
// configuration. Returning an empty slice indicates a successful | ||
// validation with no warnings or errors generated. | ||
Diagnostics []*Diagnostic | ||
} | ||
|
||
// ReadDataSourceRequest is the request Terraform sends when it wants to get | ||
// the latest state for a data source. | ||
type ReadDataSourceRequest struct { | ||
// TypeName is the type of data source Terraform is requesting an | ||
// updated state for. | ||
TypeName string | ||
|
||
// Config is the configuration the user supplied for that data source. | ||
// See the documentation on `DynamicValue` for information about safely | ||
// accessing the configuration. | ||
// | ||
// The configuration is represented as a tftypes.Object, with each | ||
// attribute and nested block getting its own key and value. | ||
// | ||
// This configuration may have unknown values. | ||
Config *DynamicValue | ||
|
||
// ProviderMeta supplies the provider metadata configuration for the | ||
// module this data source is in. Module-specific provider metadata is | ||
// an advanced feature and usage of it should be coordinated with the | ||
// Terraform Core team by raising an issue at | ||
// https://github.com/hashicorp/terraform/issues/new/choose. See the | ||
// documentation on `DynamicValue` for information about safely | ||
// accessing the configuration. | ||
// | ||
// The configuration is represented as a tftypes.Object, with each | ||
// attribute and nested block getting its own key and value. | ||
// | ||
// This configuration will have known values for all fields. | ||
ProviderMeta *DynamicValue | ||
} | ||
|
||
// ReadDataSourceResponse is the response from the provider about the current | ||
// state of the requested data source. | ||
type ReadDataSourceResponse struct { | ||
// State is the current state of the data source, represented as a | ||
// `DynamicValue`. See the documentation on `DynamicValue` for | ||
// information about safely creating the `DynamicValue`. | ||
// | ||
// The state should be represented as a tftypes.Object, with each | ||
// attribute and nested block getting its own key and value. | ||
State *DynamicValue | ||
|
||
// Diagnostics report errors or warnings related to retrieving the | ||
// current state of the requested data source. Returning an empty slice | ||
// indicates a successful validation with no warnings or errors | ||
// generated. | ||
Diagnostics []*Diagnostic | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package tfprotov6 | ||
|
||
import "github.com/hashicorp/terraform-plugin-go/tftypes" | ||
|
||
const ( | ||
// DiagnosticSeverityInvalid is used to indicate an invalid | ||
// `DiagnosticSeverity`. Provider developers should not use it. | ||
DiagnosticSeverityInvalid DiagnosticSeverity = 0 | ||
|
||
// DiagnosticSeverityError is used to indicate that a `Diagnostic` | ||
// represents an error and should halt Terraform execution. | ||
DiagnosticSeverityError DiagnosticSeverity = 1 | ||
|
||
// DiagnosticSeverityWarning is used to indicate that a `Diagnostic` | ||
// represents a warning and should not halt Terraform's execution, but | ||
// it should be surfaced to the user. | ||
DiagnosticSeverityWarning DiagnosticSeverity = 2 | ||
) | ||
|
||
// Diagnostic is used to convey information back the user running Terraform. | ||
type Diagnostic struct { | ||
// Severity indicates how Terraform should handle the Diagnostic. | ||
Severity DiagnosticSeverity | ||
|
||
// Summary is a brief description of the problem, roughly | ||
// sentence-sized, and should provide a concise description of what | ||
// went wrong. For example, a Summary could be as simple as "Invalid | ||
// value.". | ||
Summary string | ||
|
||
// Detail is a lengthier, more complete description of the problem. | ||
// Detail should provide enough information that a user can resolve the | ||
// problem entirely. For example, a Detail could be "Values must be | ||
// alphanumeric and lowercase only." | ||
Detail string | ||
|
||
// Attribute indicates which field, specifically, has the problem. Not | ||
// setting this will indicate the entire resource; setting it will | ||
// indicate that the problem is with a certain field in the resource, | ||
// which helps users find the source of the problem. | ||
Attribute *tftypes.AttributePath | ||
} | ||
|
||
// DiagnosticSeverity represents different classes of Diagnostic which affect | ||
// how Terraform handles the Diagnostics. | ||
type DiagnosticSeverity int32 | ||
|
||
func (d DiagnosticSeverity) String() string { | ||
switch d { | ||
case 0: | ||
return "INVALID" | ||
case 1: | ||
return "ERROR" | ||
case 2: | ||
return "WARNING" | ||
} | ||
return "UNKNOWN" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Package tfprotov6 provides the interfaces and types needed to build a | ||
// Terraform provider server. | ||
// | ||
// All Terraform provider servers should be built on | ||
// these types, to take advantage of the ecosystem and tooling built around | ||
// them. | ||
// | ||
// These types are small wrappers around the Terraform protocol. It is assumed | ||
// that developers using tfprotov6 are familiar with the protocol, its | ||
// requirements, and its semantics. Developers not comfortable working with the | ||
// raw protocol should use the github.com/hashicorp/terraform-plugin-sdk/v2 Go | ||
// module instead, which offers a less verbose, safer way to develop a | ||
// Terraform provider, albeit with less flexibility and power. | ||
// | ||
// Provider developers should start by defining a type that implements the | ||
// `ProviderServer` interface. A struct is recommended, as it will allow you to | ||
// store the configuration information attached to your provider for use in | ||
// requests, but any type is technically possible. | ||
// | ||
// `ProviderServer` implementations will need to implement the composed | ||
// interfaces, `ResourceServer` and `DataSourceServer`. It is recommended, but | ||
// not required, to use an embedded `ResourceRouter` and `DataSourceRouter` in | ||
// your `ProviderServer` to achieve this, which will let you handle requests | ||
// for each resource and data source in a resource-specific or data | ||
// source-specific function. | ||
// | ||
// To serve the `ProviderServer` implementation as a gRPC server that Terraform | ||
// can connect to, use the `tfprotov6/server.Serve` function. | ||
package tfprotov6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package tfprotov6 | ||
|
||
import ( | ||
"bytes" | ||
"errors" | ||
|
||
"github.com/hashicorp/terraform-plugin-go/tftypes" | ||
"github.com/vmihailenco/msgpack" | ||
) | ||
|
||
// ErrUnknownDynamicValueType is returned when a DynamicValue has no MsgPack or | ||
// JSON bytes set. This should never be returned during the normal operation of | ||
// a provider, and indicates one of the following: | ||
// | ||
// 1. terraform-plugin-go is out of sync with the protocol and should be | ||
// updated. | ||
// | ||
// 2. terrafrom-plugin-go has a bug. | ||
// | ||
// 3. The `DynamicValue` was generated or modified by something other than | ||
// terraform-plugin-go and is no longer a valid value. | ||
var ErrUnknownDynamicValueType = errors.New("DynamicValue had no JSON or msgpack data set") | ||
|
||
// NewDynamicValue creates a DynamicValue from a tftypes.Value. You must | ||
// specify the tftype.Type you want to send the value as, and it must be a type | ||
// that is compatible with the Type of the Value. Usually it should just be the | ||
// Type of the Value, but it can also be the DynamicPseudoType. | ||
func NewDynamicValue(t tftypes.Type, v tftypes.Value) (DynamicValue, error) { | ||
b, err := v.MarshalMsgPack(t) //nolint:staticcheck | ||
if err != nil { | ||
return DynamicValue{}, err | ||
} | ||
return DynamicValue{ | ||
MsgPack: b, | ||
}, nil | ||
} | ||
|
||
// DynamicValue represents a nested encoding value that came from the protocol. | ||
// The only way providers should ever interact with it is by calling its | ||
// `Unmarshal` method to retrive a `tftypes.Value`. Although the type system | ||
// allows for other interactions, they are explicitly not supported, and will | ||
// not be considered when evaluating for breaking changes. Treat this type as | ||
// an opaque value, and *only* call its `Unmarshal` method. | ||
type DynamicValue struct { | ||
MsgPack []byte | ||
JSON []byte | ||
} | ||
|
||
// Unmarshal returns a `tftypes.Value` that represents the information | ||
// contained in the DynamicValue in an easy-to-interact-with way. It is the | ||
// main purpose of the DynamicValue type, and is how provider developers should | ||
// obtain config, state, and other values from the protocol. | ||
// | ||
// Pass in the type you want the `Value` to be interpreted as. Terraform's type | ||
// system encodes in a lossy manner, meaning the type information is not | ||
// preserved losslessly when going over the wire. Sets, lists, and tuples all | ||
// look the same, as do user-specified values when the provider has a | ||
// DynamicPseudoType in its schema. Objects and maps all look the same, as | ||
// well, as do DynamicPseudoType values sometimes. Fortunately, the provider | ||
// should already know the type; it should be the type of the schema, or | ||
// PseudoDynamicType if that's what's in the schema. `Unmarshal` will then | ||
// parse the value as though it belongs to that type, if possible, and return a | ||
// `tftypes.Value` with the appropriate information. If the data can't be | ||
// interpreted as that type, an error will be returned saying so. In these | ||
// cases, double check to make sure the schema is declaring the same type being | ||
// passed into `Unmarshal`. | ||
// | ||
// In the event an ErrUnknownDynamicValueType is returned, one of three things | ||
// has happened: | ||
// | ||
// 1. terraform-plugin-go is out of date and out of sync with the protocol, and | ||
// an issue should be opened on its repo to get it updated. | ||
// | ||
// 2. terraform-plugin-go has a bug somewhere, and an issue should be opened on | ||
// its repo to get it fixed. | ||
// | ||
// 3. The provider or a dependency has modified the `DynamicValue` in an | ||
// unsupported way, or has created one from scratch, and should treat it as | ||
// opaque and not modify it, only calling `Unmarshal` on `DynamicValue`s | ||
// received from RPC requests. | ||
func (d DynamicValue) Unmarshal(typ tftypes.Type) (tftypes.Value, error) { | ||
if d.JSON != nil { | ||
return jsonUnmarshal(d.JSON, typ, tftypes.AttributePath{}) | ||
} | ||
if d.MsgPack != nil { | ||
r := bytes.NewReader(d.MsgPack) | ||
dec := msgpack.NewDecoder(r) | ||
return msgpackUnmarshal(dec, typ, tftypes.AttributePath{}) | ||
} | ||
return tftypes.Value{}, ErrUnknownDynamicValueType | ||
} |
Oops, something went wrong.