github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/terraform/eval_validate.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hashicorp/terraform/config"
     7  )
     8  
     9  // EvalValidateError is the error structure returned if there were
    10  // validation errors.
    11  type EvalValidateError struct {
    12  	Warnings []string
    13  	Errors   []error
    14  }
    15  
    16  func (e *EvalValidateError) Error() string {
    17  	return fmt.Sprintf("Warnings: %s. Errors: %s", e.Warnings, e.Errors)
    18  }
    19  
    20  // EvalValidateCount is an EvalNode implementation that validates
    21  // the count of a resource.
    22  type EvalValidateCount struct {
    23  	Resource *config.Resource
    24  }
    25  
    26  // TODO: test
    27  func (n *EvalValidateCount) Eval(ctx EvalContext) (interface{}, error) {
    28  	var count int
    29  	var errs []error
    30  	var err error
    31  	if _, err := ctx.Interpolate(n.Resource.RawCount, nil); err != nil {
    32  		errs = append(errs, fmt.Errorf(
    33  			"Failed to interpolate count: %s", err))
    34  		goto RETURN
    35  	}
    36  
    37  	count, err = n.Resource.Count()
    38  	if err != nil {
    39  		// If we can't get the count during validation, then
    40  		// just replace it with the number 1.
    41  		c := n.Resource.RawCount.Config()
    42  		c[n.Resource.RawCount.Key] = "1"
    43  		count = 1
    44  	}
    45  	err = nil
    46  
    47  	if count < 0 {
    48  		errs = append(errs, fmt.Errorf(
    49  			"Count is less than zero: %d", count))
    50  	}
    51  
    52  RETURN:
    53  	if len(errs) != 0 {
    54  		err = &EvalValidateError{
    55  			Errors: errs,
    56  		}
    57  	}
    58  	return nil, err
    59  }
    60  
    61  // EvalValidateProvider is an EvalNode implementation that validates
    62  // the configuration of a resource.
    63  type EvalValidateProvider struct {
    64  	Provider *ResourceProvider
    65  	Config   **ResourceConfig
    66  }
    67  
    68  func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) {
    69  	provider := *n.Provider
    70  	config := *n.Config
    71  
    72  	warns, errs := provider.Validate(config)
    73  	if len(warns) == 0 && len(errs) == 0 {
    74  		return nil, nil
    75  	}
    76  
    77  	return nil, &EvalValidateError{
    78  		Warnings: warns,
    79  		Errors:   errs,
    80  	}
    81  }
    82  
    83  // EvalValidateProvisioner is an EvalNode implementation that validates
    84  // the configuration of a resource.
    85  type EvalValidateProvisioner struct {
    86  	Provisioner *ResourceProvisioner
    87  	Config      **ResourceConfig
    88  }
    89  
    90  func (n *EvalValidateProvisioner) Eval(ctx EvalContext) (interface{}, error) {
    91  	provisioner := *n.Provisioner
    92  	config := *n.Config
    93  	warns, errs := provisioner.Validate(config)
    94  	if len(warns) == 0 && len(errs) == 0 {
    95  		return nil, nil
    96  	}
    97  
    98  	return nil, &EvalValidateError{
    99  		Warnings: warns,
   100  		Errors:   errs,
   101  	}
   102  }
   103  
   104  // EvalValidateResource is an EvalNode implementation that validates
   105  // the configuration of a resource.
   106  type EvalValidateResource struct {
   107  	Provider     *ResourceProvider
   108  	Config       **ResourceConfig
   109  	ResourceName string
   110  	ResourceType string
   111  	ResourceMode config.ResourceMode
   112  
   113  	// IgnoreWarnings means that warnings will not be passed through. This allows
   114  	// "just-in-time" passes of validation to continue execution through warnings.
   115  	IgnoreWarnings bool
   116  }
   117  
   118  func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) {
   119  	provider := *n.Provider
   120  	cfg := *n.Config
   121  	var warns []string
   122  	var errs []error
   123  	// Provider entry point varies depending on resource mode, because
   124  	// managed resources and data resources are two distinct concepts
   125  	// in the provider abstraction.
   126  	switch n.ResourceMode {
   127  	case config.ManagedResourceMode:
   128  		warns, errs = provider.ValidateResource(n.ResourceType, cfg)
   129  	case config.DataResourceMode:
   130  		warns, errs = provider.ValidateDataSource(n.ResourceType, cfg)
   131  	}
   132  
   133  	// If the resource name doesn't match the name regular
   134  	// expression, show an error.
   135  	if !config.NameRegexp.Match([]byte(n.ResourceName)) {
   136  		errs = append(errs, fmt.Errorf(
   137  			"%s: resource name can only contain letters, numbers, "+
   138  				"dashes, and underscores.", n.ResourceName))
   139  	}
   140  
   141  	if (len(warns) == 0 || n.IgnoreWarnings) && len(errs) == 0 {
   142  		return nil, nil
   143  	}
   144  
   145  	return nil, &EvalValidateError{
   146  		Warnings: warns,
   147  		Errors:   errs,
   148  	}
   149  }