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 }