Skip to content

Commit 51a44db

Browse files
committed
helper/schema: move InternalValidate to schemaMap
1 parent e5e4437 commit 51a44db

4 files changed

Lines changed: 178 additions & 156 deletions

File tree

helper/schema/resource.go

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package schema
22

33
import (
44
"errors"
5-
"fmt"
65

76
"github.com/hashicorp/terraform/terraform"
87
)
@@ -53,42 +52,5 @@ func (r *Resource) InternalValidate() error {
5352
return errors.New("resource is nil")
5453
}
5554

56-
for k, v := range r.Schema {
57-
if v.Type == TypeInvalid {
58-
return fmt.Errorf("%s: Type must be specified", k)
59-
}
60-
61-
if v.Optional && v.Required {
62-
return fmt.Errorf("%s: Optional or Required must be set, not both", k)
63-
}
64-
65-
if v.Required && v.Computed {
66-
return fmt.Errorf("%s: Cannot be both Required and Computed", k)
67-
}
68-
69-
if len(v.ComputedWhen) > 0 && !v.Computed {
70-
return fmt.Errorf("%s: ComputedWhen can only be set with Computed", k)
71-
}
72-
73-
if v.Type == TypeList {
74-
if v.Elem == nil {
75-
return fmt.Errorf("%s: Elem must be set for lists", k)
76-
}
77-
78-
switch t := v.Elem.(type) {
79-
case *Resource:
80-
if err := t.InternalValidate(); err != nil {
81-
return err
82-
}
83-
case *Schema:
84-
bad := t.Computed || t.Optional || t.Required
85-
if bad {
86-
return fmt.Errorf(
87-
"%s: Elem must have only Type set", k)
88-
}
89-
}
90-
}
91-
}
92-
93-
return nil
55+
return schemaMap(r.Schema).InternalValidate()
9456
}

helper/schema/resource_test.go

Lines changed: 0 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -27,123 +27,6 @@ func TestResourceInternalValidate(t *testing.T) {
2727
},
2828
true,
2929
},
30-
31-
// Missing Type
32-
{
33-
&Resource{
34-
Schema: map[string]*Schema{
35-
"foo": &Schema{
36-
Required: true,
37-
},
38-
},
39-
},
40-
true,
41-
},
42-
43-
// Required but computed
44-
{
45-
&Resource{
46-
Schema: map[string]*Schema{
47-
"foo": &Schema{
48-
Type: TypeInt,
49-
Required: true,
50-
Computed: true,
51-
},
52-
},
53-
},
54-
true,
55-
},
56-
57-
// Looks good
58-
{
59-
&Resource{
60-
Schema: map[string]*Schema{
61-
"foo": &Schema{
62-
Type: TypeString,
63-
Required: true,
64-
},
65-
},
66-
},
67-
false,
68-
},
69-
70-
// List element not set
71-
{
72-
&Resource{
73-
Schema: map[string]*Schema{
74-
"foo": &Schema{
75-
Type: TypeList,
76-
},
77-
},
78-
},
79-
true,
80-
},
81-
82-
// List element computed
83-
{
84-
&Resource{
85-
Schema: map[string]*Schema{
86-
"foo": &Schema{
87-
Type: TypeList,
88-
Elem: &Schema{
89-
Type: TypeInt,
90-
Computed: true,
91-
},
92-
},
93-
},
94-
},
95-
true,
96-
},
97-
98-
// Required but computed
99-
{
100-
&Resource{
101-
Schema: map[string]*Schema{
102-
"foo": &Schema{
103-
Type: TypeInt,
104-
Required: true,
105-
ComputedWhen: []string{"foo"},
106-
},
107-
},
108-
},
109-
true,
110-
},
111-
112-
// Sub-resource invalid
113-
{
114-
&Resource{
115-
Schema: map[string]*Schema{
116-
"foo": &Schema{
117-
Type: TypeList,
118-
Elem: &Resource{
119-
Schema: map[string]*Schema{
120-
"foo": new(Schema),
121-
},
122-
},
123-
},
124-
},
125-
},
126-
true,
127-
},
128-
129-
// Sub-resource valid
130-
{
131-
&Resource{
132-
Schema: map[string]*Schema{
133-
"foo": &Schema{
134-
Type: TypeList,
135-
Elem: &Resource{
136-
Schema: map[string]*Schema{
137-
"foo": &Schema{
138-
Type: TypeInt,
139-
},
140-
},
141-
},
142-
},
143-
},
144-
},
145-
false,
146-
},
14730
}
14831

14932
for i, tc := range cases {

helper/schema/schema.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,50 @@ func (m schemaMap) Validate(c *terraform.ResourceConfig) ([]string, []error) {
136136
return m.validateObject("", m, c)
137137
}
138138

139+
// InternalValidate validates the format of this schema. This should be called
140+
// from a unit test (and not in user-path code) to verify that a schema
141+
// is properly built.
142+
func (m schemaMap) InternalValidate() error {
143+
for k, v := range m {
144+
if v.Type == TypeInvalid {
145+
return fmt.Errorf("%s: Type must be specified", k)
146+
}
147+
148+
if v.Optional && v.Required {
149+
return fmt.Errorf("%s: Optional or Required must be set, not both", k)
150+
}
151+
152+
if v.Required && v.Computed {
153+
return fmt.Errorf("%s: Cannot be both Required and Computed", k)
154+
}
155+
156+
if len(v.ComputedWhen) > 0 && !v.Computed {
157+
return fmt.Errorf("%s: ComputedWhen can only be set with Computed", k)
158+
}
159+
160+
if v.Type == TypeList {
161+
if v.Elem == nil {
162+
return fmt.Errorf("%s: Elem must be set for lists", k)
163+
}
164+
165+
switch t := v.Elem.(type) {
166+
case *Resource:
167+
if err := t.InternalValidate(); err != nil {
168+
return err
169+
}
170+
case *Schema:
171+
bad := t.Computed || t.Optional || t.Required
172+
if bad {
173+
return fmt.Errorf(
174+
"%s: Elem must have only Type set", k)
175+
}
176+
}
177+
}
178+
}
179+
180+
return nil
181+
}
182+
139183
func (m schemaMap) diff(
140184
k string,
141185
schema *Schema,

helper/schema/schema_test.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,139 @@ func TestSchemaMap_Diff(t *testing.T) {
568568
}
569569
}
570570

571+
func TestSchemaMap_InternalValidate(t *testing.T) {
572+
cases := []struct {
573+
In map[string]*Schema
574+
Err bool
575+
}{
576+
{
577+
nil,
578+
false,
579+
},
580+
581+
// No optional and no required
582+
{
583+
map[string]*Schema{
584+
"foo": &Schema{
585+
Type: TypeInt,
586+
Optional: true,
587+
Required: true,
588+
},
589+
},
590+
true,
591+
},
592+
593+
// Missing Type
594+
{
595+
map[string]*Schema{
596+
"foo": &Schema{
597+
Required: true,
598+
},
599+
},
600+
true,
601+
},
602+
603+
// Required but computed
604+
{
605+
map[string]*Schema{
606+
"foo": &Schema{
607+
Type: TypeInt,
608+
Required: true,
609+
Computed: true,
610+
},
611+
},
612+
true,
613+
},
614+
615+
// Looks good
616+
{
617+
map[string]*Schema{
618+
"foo": &Schema{
619+
Type: TypeString,
620+
Required: true,
621+
},
622+
},
623+
false,
624+
},
625+
626+
// List element not set
627+
{
628+
map[string]*Schema{
629+
"foo": &Schema{
630+
Type: TypeList,
631+
},
632+
},
633+
true,
634+
},
635+
636+
// List element computed
637+
{
638+
map[string]*Schema{
639+
"foo": &Schema{
640+
Type: TypeList,
641+
Elem: &Schema{
642+
Type: TypeInt,
643+
Computed: true,
644+
},
645+
},
646+
},
647+
true,
648+
},
649+
650+
// Required but computed
651+
{
652+
map[string]*Schema{
653+
"foo": &Schema{
654+
Type: TypeInt,
655+
Required: true,
656+
ComputedWhen: []string{"foo"},
657+
},
658+
},
659+
true,
660+
},
661+
662+
// Sub-resource invalid
663+
{
664+
map[string]*Schema{
665+
"foo": &Schema{
666+
Type: TypeList,
667+
Elem: &Resource{
668+
Schema: map[string]*Schema{
669+
"foo": new(Schema),
670+
},
671+
},
672+
},
673+
},
674+
true,
675+
},
676+
677+
// Sub-resource valid
678+
{
679+
map[string]*Schema{
680+
"foo": &Schema{
681+
Type: TypeList,
682+
Elem: &Resource{
683+
Schema: map[string]*Schema{
684+
"foo": &Schema{
685+
Type: TypeInt,
686+
},
687+
},
688+
},
689+
},
690+
},
691+
false,
692+
},
693+
}
694+
695+
for i, tc := range cases {
696+
err := schemaMap(tc.In).InternalValidate()
697+
if (err != nil) != tc.Err {
698+
t.Fatalf("%d: bad: %s", i, err)
699+
}
700+
}
701+
702+
}
703+
571704
func TestSchemaMap_Validate(t *testing.T) {
572705
cases := []struct {
573706
Schema map[string]*Schema

0 commit comments

Comments
 (0)