github.com/richardbowden/terraform@v0.6.12-0.20160901200758-30ea22c25211/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  
    46  	if count < 0 {
    47  		errs = append(errs, fmt.Errorf(
    48  			"Count is less than zero: %d", count))
    49  	}
    50  
    51  RETURN:
    52  	if len(errs) != 0 {
    53  		err = &EvalValidateError{
    54  			Errors: errs,
    55  		}
    56  	}
    57  	return nil, err
    58  }
    59  
    60  // EvalValidateProvider is an EvalNode implementation that validates
    61  // the configuration of a resource.
    62  type EvalValidateProvider struct {
    63  	Provider *ResourceProvider
    64  	Config   **ResourceConfig
    65  }
    66  
    67  func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) {
    68  	provider := *n.Provider
    69  	config := *n.Config
    70  
    71  	warns, errs := provider.Validate(config)
    72  	if len(warns) == 0 && len(errs) == 0 {
    73  		return nil, nil
    74  	}
    75  
    76  	return nil, &EvalValidateError{
    77  		Warnings: warns,
    78  		Errors:   errs,
    79  	}
    80  }
    81  
    82  // EvalValidateProvisioner is an EvalNode implementation that validates
    83  // the configuration of a resource.
    84  type EvalValidateProvisioner struct {
    85  	Provisioner *ResourceProvisioner
    86  	Config      **ResourceConfig
    87  }
    88  
    89  func (n *EvalValidateProvisioner) Eval(ctx EvalContext) (interface{}, error) {
    90  	provisioner := *n.Provisioner
    91  	config := *n.Config
    92  	warns, errs := provisioner.Validate(config)
    93  	if len(warns) == 0 && len(errs) == 0 {
    94  		return nil, nil
    95  	}
    96  
    97  	return nil, &EvalValidateError{
    98  		Warnings: warns,
    99  		Errors:   errs,
   100  	}
   101  }
   102  
   103  // EvalValidateResource is an EvalNode implementation that validates
   104  // the configuration of a resource.
   105  type EvalValidateResource struct {
   106  	Provider     *ResourceProvider
   107  	Config       **ResourceConfig
   108  	ResourceName string
   109  	ResourceType string
   110  	ResourceMode config.ResourceMode
   111  
   112  	// IgnoreWarnings means that warnings will not be passed through. This allows
   113  	// "just-in-time" passes of validation to continue execution through warnings.
   114  	IgnoreWarnings bool
   115  }
   116  
   117  func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) {
   118  	provider := *n.Provider
   119  	cfg := *n.Config
   120  	var warns []string
   121  	var errs []error
   122  	// Provider entry point varies depending on resource mode, because
   123  	// managed resources and data resources are two distinct concepts
   124  	// in the provider abstraction.
   125  	switch n.ResourceMode {
   126  	case config.ManagedResourceMode:
   127  		warns, errs = provider.ValidateResource(n.ResourceType, cfg)
   128  	case config.DataResourceMode:
   129  		warns, errs = provider.ValidateDataSource(n.ResourceType, cfg)
   130  	}
   131  
   132  	// If the resource name doesn't match the name regular
   133  	// expression, show an error.
   134  	if !config.NameRegexp.Match([]byte(n.ResourceName)) {
   135  		errs = append(errs, fmt.Errorf(
   136  			"%s: resource name can only contain letters, numbers, "+
   137  				"dashes, and underscores.", n.ResourceName))
   138  	}
   139  
   140  	if (len(warns) == 0 || n.IgnoreWarnings) && len(errs) == 0 {
   141  		return nil, nil
   142  	}
   143  
   144  	return nil, &EvalValidateError{
   145  		Warnings: warns,
   146  		Errors:   errs,
   147  	}
   148  }