blob: 0fe69c2744480e803d4f785fe32af5c454d668e0 [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package grpcwrap
import (
"context"
"fmt"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
ctyjson "github.com/zclconf/go-cty/cty/json"
"github.com/zclconf/go-cty/cty/msgpack"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/hashicorp/terraform/internal/plugin6/convert"
"github.com/hashicorp/terraform/internal/providers"
"github.com/hashicorp/terraform/internal/tfplugin6"
)
// New wraps a providers.Interface to implement a grpc ProviderServer using
// plugin protocol v6. This is useful for creating a test binary out of an
// internal provider implementation.
func Provider6(p providers.Interface) tfplugin6.ProviderServer {
return &provider6{
provider: p,
schema: p.GetProviderSchema(),
identitySchemas: p.GetResourceIdentitySchemas(),
}
}
type provider6 struct {
provider providers.Interface
schema providers.GetProviderSchemaResponse
identitySchemas providers.GetResourceIdentitySchemasResponse
}
func (p *provider6) GetMetadata(_ context.Context, req *tfplugin6.GetMetadata_Request) (*tfplugin6.GetMetadata_Response, error) {
return nil, status.Error(codes.Unimplemented, "GetMetadata is not implemented by core")
}
func (p *provider6) GetProviderSchema(_ context.Context, req *tfplugin6.GetProviderSchema_Request) (*tfplugin6.GetProviderSchema_Response, error) {
resp := &tfplugin6.GetProviderSchema_Response{
ResourceSchemas: make(map[string]*tfplugin6.Schema),
DataSourceSchemas: make(map[string]*tfplugin6.Schema),
EphemeralResourceSchemas: make(map[string]*tfplugin6.Schema),
Functions: make(map[string]*tfplugin6.Function),
}
resp.Provider = &tfplugin6.Schema{
Block: &tfplugin6.Schema_Block{},
}
if p.schema.Provider.Body != nil {
resp.Provider.Block = convert.ConfigSchemaToProto(p.schema.Provider.Body)
}
resp.ProviderMeta = &tfplugin6.Schema{
Block: &tfplugin6.Schema_Block{},
}
if p.schema.ProviderMeta.Body != nil {
resp.ProviderMeta.Block = convert.ConfigSchemaToProto(p.schema.ProviderMeta.Body)
}
for typ, res := range p.schema.ResourceTypes {
resp.ResourceSchemas[typ] = &tfplugin6.Schema{
Version: res.Version,
Block: convert.ConfigSchemaToProto(res.Body),
}
}
for typ, dat := range p.schema.DataSources {
resp.DataSourceSchemas[typ] = &tfplugin6.Schema{
Version: int64(dat.Version),
Block: convert.ConfigSchemaToProto(dat.Body),
}
}
for typ, dat := range p.schema.EphemeralResourceTypes {
resp.EphemeralResourceSchemas[typ] = &tfplugin6.Schema{
Version: int64(dat.Version),
Block: convert.ConfigSchemaToProto(dat.Body),
}
}
if decls, err := convert.FunctionDeclsToProto(p.schema.Functions); err == nil {
resp.Functions = decls
} else {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.ServerCapabilities = &tfplugin6.ServerCapabilities{
GetProviderSchemaOptional: p.schema.ServerCapabilities.GetProviderSchemaOptional,
PlanDestroy: p.schema.ServerCapabilities.PlanDestroy,
MoveResourceState: p.schema.ServerCapabilities.MoveResourceState,
}
// include any diagnostics from the original GetSchema call
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, p.schema.Diagnostics)
return resp, nil
}
func (p *provider6) ValidateProviderConfig(_ context.Context, req *tfplugin6.ValidateProviderConfig_Request) (*tfplugin6.ValidateProviderConfig_Response, error) {
resp := &tfplugin6.ValidateProviderConfig_Response{}
ty := p.schema.Provider.Body.ImpliedType()
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
prepareResp := p.provider.ValidateProviderConfig(providers.ValidateProviderConfigRequest{
Config: configVal,
})
// the PreparedConfig value is no longer used
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, prepareResp.Diagnostics)
return resp, nil
}
func (p *provider6) ValidateResourceConfig(_ context.Context, req *tfplugin6.ValidateResourceConfig_Request) (*tfplugin6.ValidateResourceConfig_Response, error) {
resp := &tfplugin6.ValidateResourceConfig_Response{}
ty := p.schema.ResourceTypes[req.TypeName].Body.ImpliedType()
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
validateResp := p.provider.ValidateResourceConfig(providers.ValidateResourceConfigRequest{
TypeName: req.TypeName,
Config: configVal,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, validateResp.Diagnostics)
return resp, nil
}
func (p *provider6) ValidateDataResourceConfig(_ context.Context, req *tfplugin6.ValidateDataResourceConfig_Request) (*tfplugin6.ValidateDataResourceConfig_Response, error) {
resp := &tfplugin6.ValidateDataResourceConfig_Response{}
ty := p.schema.DataSources[req.TypeName].Body.ImpliedType()
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
validateResp := p.provider.ValidateDataResourceConfig(providers.ValidateDataResourceConfigRequest{
TypeName: req.TypeName,
Config: configVal,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, validateResp.Diagnostics)
return resp, nil
}
func (p *provider6) ValidateEphemeralResourceConfig(_ context.Context, req *tfplugin6.ValidateEphemeralResourceConfig_Request) (*tfplugin6.ValidateEphemeralResourceConfig_Response, error) {
resp := &tfplugin6.ValidateEphemeralResourceConfig_Response{}
ty := p.schema.DataSources[req.TypeName].Body.ImpliedType()
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
validateResp := p.provider.ValidateEphemeralResourceConfig(providers.ValidateEphemeralResourceConfigRequest{
TypeName: req.TypeName,
Config: configVal,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, validateResp.Diagnostics)
return resp, nil
}
func (p *provider6) UpgradeResourceState(_ context.Context, req *tfplugin6.UpgradeResourceState_Request) (*tfplugin6.UpgradeResourceState_Response, error) {
resp := &tfplugin6.UpgradeResourceState_Response{}
ty := p.schema.ResourceTypes[req.TypeName].Body.ImpliedType()
upgradeResp := p.provider.UpgradeResourceState(providers.UpgradeResourceStateRequest{
TypeName: req.TypeName,
Version: req.Version,
RawStateJSON: req.RawState.Json,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, upgradeResp.Diagnostics)
if upgradeResp.Diagnostics.HasErrors() {
return resp, nil
}
dv, err := encodeDynamicValue6(upgradeResp.UpgradedState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.UpgradedState = dv
return resp, nil
}
func (p *provider6) ConfigureProvider(_ context.Context, req *tfplugin6.ConfigureProvider_Request) (*tfplugin6.ConfigureProvider_Response, error) {
resp := &tfplugin6.ConfigureProvider_Response{}
ty := p.schema.Provider.Body.ImpliedType()
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
configureResp := p.provider.ConfigureProvider(providers.ConfigureProviderRequest{
TerraformVersion: req.TerraformVersion,
Config: configVal,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, configureResp.Diagnostics)
return resp, nil
}
func (p *provider6) ReadResource(_ context.Context, req *tfplugin6.ReadResource_Request) (*tfplugin6.ReadResource_Response, error) {
resp := &tfplugin6.ReadResource_Response{}
resSchema := p.schema.ResourceTypes[req.TypeName]
ty := resSchema.Body.ImpliedType()
stateVal, err := decodeDynamicValue6(req.CurrentState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
metaTy := p.schema.ProviderMeta.Body.ImpliedType()
metaVal, err := decodeDynamicValue6(req.ProviderMeta, metaTy)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
var currentIdentity cty.Value
if req.CurrentIdentity != nil && req.CurrentIdentity.IdentityData != nil {
if resSchema.Identity == nil {
return resp, fmt.Errorf("identity schema not found for type %s", req.TypeName)
}
currentIdentity, err = decodeDynamicValue6(req.CurrentIdentity.IdentityData, resSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
}
readResp := p.provider.ReadResource(providers.ReadResourceRequest{
TypeName: req.TypeName,
PriorState: stateVal,
Private: req.Private,
ProviderMeta: metaVal,
CurrentIdentity: currentIdentity,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, readResp.Diagnostics)
if readResp.Diagnostics.HasErrors() {
return resp, nil
}
resp.Private = readResp.Private
dv, err := encodeDynamicValue6(readResp.NewState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.NewState = dv
if !readResp.Identity.IsNull() {
if resSchema.Identity == nil {
return resp, fmt.Errorf("identity schema not found for type %s", req.TypeName)
}
newIdentity, err := encodeDynamicValue6(readResp.Identity, resSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.NewIdentity = &tfplugin6.ResourceIdentityData{
IdentityData: newIdentity,
}
}
return resp, nil
}
func (p *provider6) PlanResourceChange(_ context.Context, req *tfplugin6.PlanResourceChange_Request) (*tfplugin6.PlanResourceChange_Response, error) {
resp := &tfplugin6.PlanResourceChange_Response{}
resSchema := p.schema.ResourceTypes[req.TypeName]
ty := resSchema.Body.ImpliedType()
priorStateVal, err := decodeDynamicValue6(req.PriorState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
proposedStateVal, err := decodeDynamicValue6(req.ProposedNewState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
metaTy := p.schema.ProviderMeta.Body.ImpliedType()
metaVal, err := decodeDynamicValue6(req.ProviderMeta, metaTy)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
var priorIdentity cty.Value
if req.PriorIdentity != nil && req.PriorIdentity.IdentityData != nil {
if resSchema.Identity == nil {
return resp, fmt.Errorf("identity schema not found for type %s", req.TypeName)
}
priorIdentity, err = decodeDynamicValue6(req.PriorIdentity.IdentityData, resSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
}
planResp := p.provider.PlanResourceChange(providers.PlanResourceChangeRequest{
TypeName: req.TypeName,
PriorState: priorStateVal,
ProposedNewState: proposedStateVal,
Config: configVal,
PriorPrivate: req.PriorPrivate,
ProviderMeta: metaVal,
PriorIdentity: priorIdentity,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, planResp.Diagnostics)
if planResp.Diagnostics.HasErrors() {
return resp, nil
}
resp.PlannedPrivate = planResp.PlannedPrivate
resp.PlannedState, err = encodeDynamicValue6(planResp.PlannedState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
for _, path := range planResp.RequiresReplace {
resp.RequiresReplace = append(resp.RequiresReplace, convert.PathToAttributePath(path))
}
if !planResp.PlannedIdentity.IsNull() {
if resSchema.Identity == nil {
return resp, fmt.Errorf("identity schema not found for type %s", req.TypeName)
}
plannedIdentityVal, err := encodeDynamicValue6(planResp.PlannedIdentity, resSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.PlannedIdentity = &tfplugin6.ResourceIdentityData{
IdentityData: plannedIdentityVal,
}
}
return resp, nil
}
func (p *provider6) ApplyResourceChange(_ context.Context, req *tfplugin6.ApplyResourceChange_Request) (*tfplugin6.ApplyResourceChange_Response, error) {
resp := &tfplugin6.ApplyResourceChange_Response{}
resSchema := p.schema.ResourceTypes[req.TypeName]
ty := resSchema.Body.ImpliedType()
priorStateVal, err := decodeDynamicValue6(req.PriorState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
plannedStateVal, err := decodeDynamicValue6(req.PlannedState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
metaTy := p.schema.ProviderMeta.Body.ImpliedType()
metaVal, err := decodeDynamicValue6(req.ProviderMeta, metaTy)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
var plannedIdentity cty.Value
if req.PlannedIdentity != nil && req.PlannedIdentity.IdentityData != nil {
if resSchema.Identity == nil {
return resp, fmt.Errorf("identity schema not found for type %s", req.TypeName)
}
plannedIdentity, err = decodeDynamicValue6(req.PlannedIdentity.IdentityData, resSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
}
applyResp := p.provider.ApplyResourceChange(providers.ApplyResourceChangeRequest{
TypeName: req.TypeName,
PriorState: priorStateVal,
PlannedState: plannedStateVal,
Config: configVal,
PlannedPrivate: req.PlannedPrivate,
ProviderMeta: metaVal,
PlannedIdentity: plannedIdentity,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, applyResp.Diagnostics)
if applyResp.Diagnostics.HasErrors() {
return resp, nil
}
resp.Private = applyResp.Private
resp.NewState, err = encodeDynamicValue6(applyResp.NewState, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
if !applyResp.NewIdentity.IsNull() {
if resSchema.Identity == nil {
return resp, fmt.Errorf("identity schema not found for type %s", req.TypeName)
}
newIdentity, err := encodeDynamicValue6(applyResp.NewIdentity, resSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.NewIdentity = &tfplugin6.ResourceIdentityData{
IdentityData: newIdentity,
}
}
return resp, nil
}
func (p *provider6) ImportResourceState(_ context.Context, req *tfplugin6.ImportResourceState_Request) (*tfplugin6.ImportResourceState_Response, error) {
resp := &tfplugin6.ImportResourceState_Response{}
resSchema := p.schema.ResourceTypes[req.TypeName]
var identity cty.Value
var err error
if req.Identity != nil && req.Identity.IdentityData != nil {
if resSchema.Identity == nil {
return resp, fmt.Errorf("identity schema not found for type %s", req.TypeName)
}
identity, err = decodeDynamicValue6(req.Identity.IdentityData, resSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
}
importResp := p.provider.ImportResourceState(providers.ImportResourceStateRequest{
TypeName: req.TypeName,
ID: req.Id,
Identity: identity,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, importResp.Diagnostics)
for _, res := range importResp.ImportedResources {
importSchema := p.schema.ResourceTypes[res.TypeName]
ty := importSchema.Body.ImpliedType()
state, err := encodeDynamicValue6(res.State, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
continue
}
importedResource := &tfplugin6.ImportResourceState_ImportedResource{
TypeName: res.TypeName,
State: state,
Private: res.Private,
}
if !res.Identity.IsNull() {
if importSchema.Identity == nil {
return nil, fmt.Errorf("identity schema not found for type %s", res.TypeName)
}
identity, err := encodeDynamicValue6(res.Identity, importSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
continue
}
importedResource.Identity = &tfplugin6.ResourceIdentityData{
IdentityData: identity,
}
}
resp.ImportedResources = append(resp.ImportedResources, importedResource)
}
return resp, nil
}
func (p *provider6) MoveResourceState(_ context.Context, request *tfplugin6.MoveResourceState_Request) (*tfplugin6.MoveResourceState_Response, error) {
resp := &tfplugin6.MoveResourceState_Response{}
var sourceIdentity []byte
var err error
if request.SourceIdentity != nil && len(request.SourceIdentity.Json) > 0 {
sourceIdentity = request.SourceIdentity.Json
}
moveResp := p.provider.MoveResourceState(providers.MoveResourceStateRequest{
SourceProviderAddress: request.SourceProviderAddress,
SourceTypeName: request.SourceTypeName,
SourceSchemaVersion: request.SourceSchemaVersion,
SourceStateJSON: request.SourceState.Json,
SourcePrivate: request.SourcePrivate,
TargetTypeName: request.TargetTypeName,
SourceIdentity: sourceIdentity,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, moveResp.Diagnostics)
if moveResp.Diagnostics.HasErrors() {
return resp, nil
}
targetSchema := p.schema.ResourceTypes[request.TargetTypeName]
targetType := targetSchema.Body.ImpliedType()
targetState, err := encodeDynamicValue6(moveResp.TargetState, targetType)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
if !moveResp.TargetIdentity.IsNull() {
if targetSchema.Identity == nil {
return resp, fmt.Errorf("identity schema not found for type %s", request.TargetTypeName)
}
targetIdentity, err := encodeDynamicValue6(moveResp.TargetIdentity, targetSchema.Identity.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.TargetIdentity = &tfplugin6.ResourceIdentityData{
IdentityData: targetIdentity,
}
}
resp.TargetState = targetState
resp.TargetPrivate = moveResp.TargetPrivate
return resp, nil
}
func (p *provider6) ReadDataSource(_ context.Context, req *tfplugin6.ReadDataSource_Request) (*tfplugin6.ReadDataSource_Response, error) {
resp := &tfplugin6.ReadDataSource_Response{}
ty := p.schema.DataSources[req.TypeName].Body.ImpliedType()
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
metaTy := p.schema.ProviderMeta.Body.ImpliedType()
metaVal, err := decodeDynamicValue6(req.ProviderMeta, metaTy)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
readResp := p.provider.ReadDataSource(providers.ReadDataSourceRequest{
TypeName: req.TypeName,
Config: configVal,
ProviderMeta: metaVal,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, readResp.Diagnostics)
if readResp.Diagnostics.HasErrors() {
return resp, nil
}
resp.State, err = encodeDynamicValue6(readResp.State, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
return resp, nil
}
func (p *provider6) OpenEphemeralResource(_ context.Context, req *tfplugin6.OpenEphemeralResource_Request) (*tfplugin6.OpenEphemeralResource_Response, error) {
resp := &tfplugin6.OpenEphemeralResource_Response{}
ty := p.schema.EphemeralResourceTypes[req.TypeName].Body.ImpliedType()
configVal, err := decodeDynamicValue6(req.Config, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
openResp := p.provider.OpenEphemeralResource(providers.OpenEphemeralResourceRequest{
TypeName: req.TypeName,
Config: configVal,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, openResp.Diagnostics)
if openResp.Diagnostics.HasErrors() {
return resp, nil
}
resp.Result, err = encodeDynamicValue6(openResp.Result, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.Private = openResp.Private
resp.RenewAt = timestamppb.New(openResp.RenewAt)
return resp, nil
}
func (p *provider6) RenewEphemeralResource(_ context.Context, req *tfplugin6.RenewEphemeralResource_Request) (*tfplugin6.RenewEphemeralResource_Response, error) {
resp := &tfplugin6.RenewEphemeralResource_Response{}
renewResp := p.provider.RenewEphemeralResource(providers.RenewEphemeralResourceRequest{
TypeName: req.TypeName,
Private: req.Private,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, renewResp.Diagnostics)
if renewResp.Diagnostics.HasErrors() {
return resp, nil
}
resp.Private = renewResp.Private
resp.RenewAt = timestamppb.New(renewResp.RenewAt)
return resp, nil
}
func (p *provider6) CloseEphemeralResource(_ context.Context, req *tfplugin6.CloseEphemeralResource_Request) (*tfplugin6.CloseEphemeralResource_Response, error) {
resp := &tfplugin6.CloseEphemeralResource_Response{}
closeResp := p.provider.CloseEphemeralResource(providers.CloseEphemeralResourceRequest{
TypeName: req.TypeName,
Private: req.Private,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, closeResp.Diagnostics)
if closeResp.Diagnostics.HasErrors() {
return resp, nil
}
return resp, nil
}
func (p *provider6) GetFunctions(context.Context, *tfplugin6.GetFunctions_Request) (*tfplugin6.GetFunctions_Response, error) {
panic("unimplemented")
}
func (p *provider6) CallFunction(_ context.Context, req *tfplugin6.CallFunction_Request) (*tfplugin6.CallFunction_Response, error) {
var err error
resp := &tfplugin6.CallFunction_Response{}
funcSchema := p.schema.Functions[req.Name]
var args []cty.Value
if len(req.Arguments) != 0 {
args = make([]cty.Value, len(req.Arguments))
for i, rawArg := range req.Arguments {
idx := int64(i)
var argTy cty.Type
if i < len(funcSchema.Parameters) {
argTy = funcSchema.Parameters[i].Type
} else {
if funcSchema.VariadicParameter == nil {
resp.Error = &tfplugin6.FunctionError{
Text: "too many arguments for non-variadic function",
FunctionArgument: &idx,
}
return resp, nil
}
argTy = funcSchema.VariadicParameter.Type
}
argVal, err := decodeDynamicValue6(rawArg, argTy)
if err != nil {
resp.Error = &tfplugin6.FunctionError{
Text: err.Error(),
FunctionArgument: &idx,
}
return resp, nil
}
args[i] = argVal
}
}
callResp := p.provider.CallFunction(providers.CallFunctionRequest{
FunctionName: req.Name,
Arguments: args,
})
if callResp.Err != nil {
resp.Error = &tfplugin6.FunctionError{
Text: callResp.Err.Error(),
}
if argErr, ok := callResp.Err.(function.ArgError); ok {
idx := int64(argErr.Index)
resp.Error.FunctionArgument = &idx
}
return resp, nil
}
resp.Result, err = encodeDynamicValue6(callResp.Result, funcSchema.ReturnType)
if err != nil {
resp.Error = &tfplugin6.FunctionError{
Text: err.Error(),
}
return resp, nil
}
return resp, nil
}
func (p *provider6) GetResourceIdentitySchemas(_ context.Context, req *tfplugin6.GetResourceIdentitySchemas_Request) (*tfplugin6.GetResourceIdentitySchemas_Response, error) {
resp := &tfplugin6.GetResourceIdentitySchemas_Response{
IdentitySchemas: map[string]*tfplugin6.ResourceIdentitySchema{},
Diagnostics: []*tfplugin6.Diagnostic{},
}
for name, schema := range p.identitySchemas.IdentityTypes {
resp.IdentitySchemas[name] = convert.ResourceIdentitySchemaToProto(schema)
}
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, p.identitySchemas.Diagnostics)
return resp, nil
}
func (p *provider6) UpgradeResourceIdentity(_ context.Context, req *tfplugin6.UpgradeResourceIdentity_Request) (*tfplugin6.UpgradeResourceIdentity_Response, error) {
resp := &tfplugin6.UpgradeResourceIdentity_Response{}
resource, ok := p.identitySchemas.IdentityTypes[req.TypeName]
if !ok {
return nil, fmt.Errorf("resource identity schema not found for type %q", req.TypeName)
}
ty := resource.Body.ImpliedType()
upgradeResp := p.provider.UpgradeResourceIdentity(providers.UpgradeResourceIdentityRequest{
TypeName: req.TypeName,
Version: req.Version,
RawIdentityJSON: req.RawIdentity.Json,
})
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, upgradeResp.Diagnostics)
if upgradeResp.Diagnostics.HasErrors() {
return resp, nil
}
dv, err := encodeDynamicValue6(upgradeResp.UpgradedIdentity, ty)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
resp.UpgradedIdentity = &tfplugin6.ResourceIdentityData{
IdentityData: dv,
}
return resp, nil
}
func (p *provider6) StopProvider(context.Context, *tfplugin6.StopProvider_Request) (*tfplugin6.StopProvider_Response, error) {
resp := &tfplugin6.StopProvider_Response{}
err := p.provider.Stop()
if err != nil {
resp.Error = err.Error()
}
return resp, nil
}
// decode a DynamicValue from either the JSON or MsgPack encoding.
func decodeDynamicValue6(v *tfplugin6.DynamicValue, ty cty.Type) (cty.Value, error) {
// always return a valid value
var err error
res := cty.NullVal(ty)
if v == nil {
return res, nil
}
switch {
case len(v.Msgpack) > 0:
res, err = msgpack.Unmarshal(v.Msgpack, ty)
case len(v.Json) > 0:
res, err = ctyjson.Unmarshal(v.Json, ty)
}
return res, err
}
// encode a cty.Value into a DynamicValue msgpack payload.
func encodeDynamicValue6(v cty.Value, ty cty.Type) (*tfplugin6.DynamicValue, error) {
mp, err := msgpack.Marshal(v, ty)
return &tfplugin6.DynamicValue{
Msgpack: mp,
}, err
}