func (action *TfServiceDefinitionV1Action) validateTemplateInputs() (errs *validation.FieldError) {
	inputs := utils.NewStringSet()
	for _, in := range action.PlanInputs {
		inputs.Add(in.FieldName)
	}
	for _, in := range action.UserInputs {
		inputs.Add(in.FieldName)
	}
	for _, in := range action.Computed {
		inputs.Add(in.Name)
	}
	tfModule := wrapper.ModuleDefinition{Definition: action.Template}
	tfIn, err := tfModule.Inputs()
	if err != nil {
		return &validation.FieldError{
			Message: err.Error(),
		}
	}
	missingFields := utils.NewStringSet(tfIn...).Minus(inputs).ToSlice()
	if len(missingFields) > 0 {
		return &validation.FieldError{
			Message: "fields used but not declared",
			Paths:   missingFields,
		}
	}
	return nil
}
validateTemplateInputs checks that all the inputs of the Terraform template
are defined by the service.
package tf
import (
	"fmt"
	"code.cloudfoundry.org/lager"
	"github.com/GoogleCloudPlatform/gcp-service-broker/pkg/broker"
	"github.com/GoogleCloudPlatform/gcp-service-broker/pkg/providers/tf/wrapper"
	"github.com/GoogleCloudPlatform/gcp-service-broker/pkg/validation"
	"github.com/GoogleCloudPlatform/gcp-service-broker/pkg/varcontext"
	"github.com/GoogleCloudPlatform/gcp-service-broker/utils"
	"github.com/pivotal-cf/brokerapi"
	"golang.org/x/oauth2/jwt"
)
type TfServiceDefinitionV1 struct {
	Version           int                         `yaml:"version"`
	Name              string                      `yaml:"name"`
	Id                string                      `yaml:"id"`
	Description       string                      `yaml:"description"`
	DisplayName       string                      `yaml:"display_name"`
	ImageUrl          string                      `yaml:"image_url"`
	DocumentationUrl  string                      `yaml:"documentation_url"`
	SupportUrl        string                      `yaml:"support_url"`
	Tags              []string                    `yaml:"tags,flow"`
	Plans             []TfServiceDefinitionV1Plan `yaml:"plans"`
	ProvisionSettings TfServiceDefinitionV1Action `yaml:"provision"`
	BindSettings      TfServiceDefinitionV1Action `yaml:"bind"`
	Examples          []broker.ServiceExample     `yaml:"examples"`
	Internal bool `yaml:"-"`
}
type TfServiceDefinitionV1Plan struct {
	Name               string                 `yaml:"name"`
	Id                 string                 `yaml:"id"`
	Description        string                 `yaml:"description"`
	DisplayName        string                 `yaml:"display_name"`
	Bullets            []string               `yaml:"bullets,omitempty"`
	Free               bool                   `yaml:"free,omitempty"`
	Properties         map[string]string      `yaml:"properties"`
	ProvisionOverrides map[string]interface{} `yaml:"provision_overrides,omitempty"`
	BindOverrides      map[string]interface{} `yaml:"bind_overrides,omitempty"`
}
var _ validation.Validatable = (*TfServiceDefinitionV1Plan)(nil)
func (plan *TfServiceDefinitionV1Plan) Validate() (errs *validation.FieldError) {
	return errs.Also(
		validation.ErrIfBlank(plan.Name, "name"),
		validation.ErrIfNotUUID(plan.Id, "id"),
		validation.ErrIfBlank(plan.Description, "description"),
		validation.ErrIfBlank(plan.DisplayName, "display_name"),
	)
}
func (plan *TfServiceDefinitionV1Plan) ToPlan() broker.ServicePlan {
	masterPlan := brokerapi.ServicePlan{
		ID:          plan.Id,
		Description: plan.Description,
		Name:        plan.Name,
		Free:        brokerapi.FreeValue(plan.Free),
		Metadata: &brokerapi.ServicePlanMetadata{
			Bullets:     plan.Bullets,
			DisplayName: plan.DisplayName,
		},
	}
	return broker.ServicePlan{
		ServicePlan:        masterPlan,
		ServiceProperties:  plan.Properties,
		ProvisionOverrides: plan.ProvisionOverrides,
		BindOverrides:      plan.BindOverrides,
	}
}
type TfServiceDefinitionV1Action struct {
	PlanInputs []broker.BrokerVariable      `yaml:"plan_inputs"`
	UserInputs []broker.BrokerVariable      `yaml:"user_inputs"`
	Computed   []varcontext.DefaultVariable `yaml:"computed_inputs"`
	Template   string                       `yaml:"template"`
	Outputs    []broker.BrokerVariable      `yaml:"outputs"`
}
var _ validation.Validatable = (*TfServiceDefinitionV1Action)(nil)
func (action *TfServiceDefinitionV1Action) Validate() (errs *validation.FieldError) {
	for i, v := range action.PlanInputs {
		errs = errs.Also(v.Validate().ViaFieldIndex("plan_inputs", i))
	}
	for i, v := range action.UserInputs {
		errs = errs.Also(v.Validate().ViaFieldIndex("user_inputs", i))
	}
	for i, v := range action.Computed {
		errs = errs.Also(v.Validate().ViaFieldIndex("computed_inputs", i))
	}
	errs = errs.Also(
		validation.ErrIfNotHCL(action.Template, "template"),
		action.validateTemplateInputs().ViaField("template"),
		action.validateTemplateOutputs().ViaField("template"),
	)
	for i, v := range action.Outputs {
		errs = errs.Also(v.Validate().ViaFieldIndex("outputs", i))
	}
	return errs
}
func (action *TfServiceDefinitionV1Action) ValidateTemplateIO() (errs *validation.FieldError) {
	return errs.Also(
		action.validateTemplateInputs().ViaField("template"),
		action.validateTemplateOutputs().ViaField("template"),
	)
}