github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/builtin/providers/terraform/resource_data.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hashicorp/go-uuid"
     7  	"github.com/hashicorp/terraform/internal/configs/configschema"
     8  	"github.com/hashicorp/terraform/internal/providers"
     9  	"github.com/hashicorp/terraform/internal/tfdiags"
    10  	"github.com/zclconf/go-cty/cty"
    11  	ctyjson "github.com/zclconf/go-cty/cty/json"
    12  )
    13  
    14  func dataStoreResourceSchema() providers.Schema {
    15  	return providers.Schema{
    16  		Block: &configschema.Block{
    17  			Attributes: map[string]*configschema.Attribute{
    18  				"input":            {Type: cty.DynamicPseudoType, Optional: true},
    19  				"output":           {Type: cty.DynamicPseudoType, Computed: true},
    20  				"triggers_replace": {Type: cty.DynamicPseudoType, Optional: true},
    21  				"id":               {Type: cty.String, Computed: true},
    22  			},
    23  		},
    24  	}
    25  }
    26  
    27  func validateDataStoreResourceConfig(req providers.ValidateResourceConfigRequest) (resp providers.ValidateResourceConfigResponse) {
    28  	if req.Config.IsNull() {
    29  		return resp
    30  	}
    31  
    32  	// Core does not currently validate computed values are not set in the
    33  	// configuration.
    34  	for _, attr := range []string{"id", "output"} {
    35  		if !req.Config.GetAttr(attr).IsNull() {
    36  			resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf(`%q attribute is read-only`, attr))
    37  		}
    38  	}
    39  	return resp
    40  }
    41  
    42  func upgradeDataStoreResourceState(req providers.UpgradeResourceStateRequest) (resp providers.UpgradeResourceStateResponse) {
    43  	ty := dataStoreResourceSchema().Block.ImpliedType()
    44  	val, err := ctyjson.Unmarshal(req.RawStateJSON, ty)
    45  	if err != nil {
    46  		resp.Diagnostics = resp.Diagnostics.Append(err)
    47  		return resp
    48  	}
    49  
    50  	resp.UpgradedState = val
    51  	return resp
    52  }
    53  
    54  func readDataStoreResourceState(req providers.ReadResourceRequest) (resp providers.ReadResourceResponse) {
    55  	resp.NewState = req.PriorState
    56  	return resp
    57  }
    58  
    59  func planDataStoreResourceChange(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
    60  	if req.ProposedNewState.IsNull() {
    61  		// destroy op
    62  		resp.PlannedState = req.ProposedNewState
    63  		return resp
    64  	}
    65  
    66  	planned := req.ProposedNewState.AsValueMap()
    67  
    68  	input := req.ProposedNewState.GetAttr("input")
    69  	trigger := req.ProposedNewState.GetAttr("triggers_replace")
    70  
    71  	switch {
    72  	case req.PriorState.IsNull():
    73  		// Create
    74  		// Set the id value to unknown.
    75  		planned["id"] = cty.UnknownVal(cty.String)
    76  
    77  		// Output type must always match the input, even when it's null.
    78  		if input.IsNull() {
    79  			planned["output"] = input
    80  		} else {
    81  			planned["output"] = cty.UnknownVal(input.Type())
    82  		}
    83  
    84  		resp.PlannedState = cty.ObjectVal(planned)
    85  		return resp
    86  
    87  	case !req.PriorState.GetAttr("triggers_replace").RawEquals(trigger):
    88  		// trigger changed, so we need to replace the entire instance
    89  		resp.RequiresReplace = append(resp.RequiresReplace, cty.GetAttrPath("triggers_replace"))
    90  		planned["id"] = cty.UnknownVal(cty.String)
    91  
    92  		// We need to check the input for the replacement instance to compute a
    93  		// new output.
    94  		if input.IsNull() {
    95  			planned["output"] = input
    96  		} else {
    97  			planned["output"] = cty.UnknownVal(input.Type())
    98  		}
    99  
   100  	case !req.PriorState.GetAttr("input").RawEquals(input):
   101  		// only input changed, so we only need to re-compute output
   102  		planned["output"] = cty.UnknownVal(input.Type())
   103  	}
   104  
   105  	resp.PlannedState = cty.ObjectVal(planned)
   106  	return resp
   107  }
   108  
   109  var testUUIDHook func() string
   110  
   111  func applyDataStoreResourceChange(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) {
   112  	if req.PlannedState.IsNull() {
   113  		resp.NewState = req.PlannedState
   114  		return resp
   115  	}
   116  
   117  	newState := req.PlannedState.AsValueMap()
   118  
   119  	if !req.PlannedState.GetAttr("output").IsKnown() {
   120  		newState["output"] = req.PlannedState.GetAttr("input")
   121  	}
   122  
   123  	if !req.PlannedState.GetAttr("id").IsKnown() {
   124  		idString, err := uuid.GenerateUUID()
   125  		// Terraform would probably never get this far without a good random
   126  		// source, but catch the error anyway.
   127  		if err != nil {
   128  			diag := tfdiags.AttributeValue(
   129  				tfdiags.Error,
   130  				"Error generating id",
   131  				err.Error(),
   132  				cty.GetAttrPath("id"),
   133  			)
   134  
   135  			resp.Diagnostics = resp.Diagnostics.Append(diag)
   136  		}
   137  
   138  		if testUUIDHook != nil {
   139  			idString = testUUIDHook()
   140  		}
   141  
   142  		newState["id"] = cty.StringVal(idString)
   143  	}
   144  
   145  	resp.NewState = cty.ObjectVal(newState)
   146  
   147  	return resp
   148  }
   149  
   150  // TODO: This isn't very useful even for examples, because terraform_data has
   151  // no way to refresh the full resource value from only the import ID. This
   152  // minimal implementation allows the import to succeed, and can be extended
   153  // once the configuration is available during import.
   154  func importDataStore(req providers.ImportResourceStateRequest) (resp providers.ImportResourceStateResponse) {
   155  	schema := dataStoreResourceSchema()
   156  	v := cty.ObjectVal(map[string]cty.Value{
   157  		"id": cty.StringVal(req.ID),
   158  	})
   159  	state, err := schema.Block.CoerceValue(v)
   160  	resp.Diagnostics = resp.Diagnostics.Append(err)
   161  
   162  	resp.ImportedResources = []providers.ImportedResource{
   163  		{
   164  			TypeName: req.TypeName,
   165  			State:    state,
   166  		},
   167  	}
   168  	return resp
   169  }