github.com/rmenn/terraform@v0.3.8-0.20150225065417-fc84b3a78802/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 return nil, &EvalValidateError{ 53 Errors: errs, 54 } 55 } 56 57 // EvalValidateProvider is an EvalNode implementation that validates 58 // the configuration of a resource. 59 type EvalValidateProvider struct { 60 ProviderName string 61 Provider *ResourceProvider 62 Config **ResourceConfig 63 } 64 65 func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) { 66 provider := *n.Provider 67 config := *n.Config 68 69 // Get the parent configuration if there is one 70 if parent := ctx.ParentProviderConfig(n.ProviderName); parent != nil { 71 merged := parent.raw.Merge(config.raw) 72 config = NewResourceConfig(merged) 73 } 74 75 warns, errs := provider.Validate(config) 76 if len(warns) == 0 && len(errs) == 0 { 77 return nil, nil 78 } 79 80 return nil, &EvalValidateError{ 81 Warnings: warns, 82 Errors: errs, 83 } 84 } 85 86 // EvalValidateProvisioner is an EvalNode implementation that validates 87 // the configuration of a resource. 88 type EvalValidateProvisioner struct { 89 Provisioner *ResourceProvisioner 90 Config **ResourceConfig 91 } 92 93 func (n *EvalValidateProvisioner) Eval(ctx EvalContext) (interface{}, error) { 94 provisioner := *n.Provisioner 95 config := *n.Config 96 warns, errs := provisioner.Validate(config) 97 if len(warns) == 0 && len(errs) == 0 { 98 return nil, nil 99 } 100 101 return nil, &EvalValidateError{ 102 Warnings: warns, 103 Errors: errs, 104 } 105 } 106 107 // EvalValidateResource is an EvalNode implementation that validates 108 // the configuration of a resource. 109 type EvalValidateResource struct { 110 Provider *ResourceProvider 111 Config **ResourceConfig 112 ResourceName string 113 ResourceType string 114 } 115 116 func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) { 117 // TODO: test 118 119 provider := *n.Provider 120 cfg := *n.Config 121 warns, errs := provider.ValidateResource(n.ResourceType, cfg) 122 123 // If the resouce name doesn't match the name regular 124 // expression, show a warning. 125 if !config.NameRegexp.Match([]byte(n.ResourceName)) { 126 warns = append(warns, fmt.Sprintf( 127 "%s: resource name can only contain letters, numbers, "+ 128 "dashes, and underscores.\n"+ 129 "This will be an error in Terraform 0.4", 130 n.ResourceName)) 131 } 132 133 if len(warns) == 0 && len(errs) == 0 { 134 return nil, nil 135 } 136 137 return nil, &EvalValidateError{ 138 Warnings: warns, 139 Errors: errs, 140 } 141 }