diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/plugin/convert/schema.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/plugin/convert/schema.go | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/plugin/convert/schema.go b/vendor/github.com/hashicorp/terraform/plugin/convert/schema.go new file mode 100644 index 0000000..6a45f54 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/plugin/convert/schema.go | |||
@@ -0,0 +1,154 @@ | |||
1 | package convert | ||
2 | |||
3 | import ( | ||
4 | "encoding/json" | ||
5 | "reflect" | ||
6 | "sort" | ||
7 | |||
8 | "github.com/hashicorp/terraform/configs/configschema" | ||
9 | proto "github.com/hashicorp/terraform/internal/tfplugin5" | ||
10 | "github.com/hashicorp/terraform/providers" | ||
11 | ) | ||
12 | |||
13 | // ConfigSchemaToProto takes a *configschema.Block and converts it to a | ||
14 | // proto.Schema_Block for a grpc response. | ||
15 | func ConfigSchemaToProto(b *configschema.Block) *proto.Schema_Block { | ||
16 | block := &proto.Schema_Block{} | ||
17 | |||
18 | for _, name := range sortedKeys(b.Attributes) { | ||
19 | a := b.Attributes[name] | ||
20 | attr := &proto.Schema_Attribute{ | ||
21 | Name: name, | ||
22 | Description: a.Description, | ||
23 | Optional: a.Optional, | ||
24 | Computed: a.Computed, | ||
25 | Required: a.Required, | ||
26 | Sensitive: a.Sensitive, | ||
27 | } | ||
28 | |||
29 | ty, err := json.Marshal(a.Type) | ||
30 | if err != nil { | ||
31 | panic(err) | ||
32 | } | ||
33 | |||
34 | attr.Type = ty | ||
35 | |||
36 | block.Attributes = append(block.Attributes, attr) | ||
37 | } | ||
38 | |||
39 | for _, name := range sortedKeys(b.BlockTypes) { | ||
40 | b := b.BlockTypes[name] | ||
41 | block.BlockTypes = append(block.BlockTypes, protoSchemaNestedBlock(name, b)) | ||
42 | } | ||
43 | |||
44 | return block | ||
45 | } | ||
46 | |||
47 | func protoSchemaNestedBlock(name string, b *configschema.NestedBlock) *proto.Schema_NestedBlock { | ||
48 | var nesting proto.Schema_NestedBlock_NestingMode | ||
49 | switch b.Nesting { | ||
50 | case configschema.NestingSingle: | ||
51 | nesting = proto.Schema_NestedBlock_SINGLE | ||
52 | case configschema.NestingGroup: | ||
53 | nesting = proto.Schema_NestedBlock_GROUP | ||
54 | case configschema.NestingList: | ||
55 | nesting = proto.Schema_NestedBlock_LIST | ||
56 | case configschema.NestingSet: | ||
57 | nesting = proto.Schema_NestedBlock_SET | ||
58 | case configschema.NestingMap: | ||
59 | nesting = proto.Schema_NestedBlock_MAP | ||
60 | default: | ||
61 | nesting = proto.Schema_NestedBlock_INVALID | ||
62 | } | ||
63 | return &proto.Schema_NestedBlock{ | ||
64 | TypeName: name, | ||
65 | Block: ConfigSchemaToProto(&b.Block), | ||
66 | Nesting: nesting, | ||
67 | MinItems: int64(b.MinItems), | ||
68 | MaxItems: int64(b.MaxItems), | ||
69 | } | ||
70 | } | ||
71 | |||
72 | // ProtoToProviderSchema takes a proto.Schema and converts it to a providers.Schema. | ||
73 | func ProtoToProviderSchema(s *proto.Schema) providers.Schema { | ||
74 | return providers.Schema{ | ||
75 | Version: s.Version, | ||
76 | Block: ProtoToConfigSchema(s.Block), | ||
77 | } | ||
78 | } | ||
79 | |||
80 | // ProtoToConfigSchema takes the GetSchcema_Block from a grpc response and converts it | ||
81 | // to a terraform *configschema.Block. | ||
82 | func ProtoToConfigSchema(b *proto.Schema_Block) *configschema.Block { | ||
83 | block := &configschema.Block{ | ||
84 | Attributes: make(map[string]*configschema.Attribute), | ||
85 | BlockTypes: make(map[string]*configschema.NestedBlock), | ||
86 | } | ||
87 | |||
88 | for _, a := range b.Attributes { | ||
89 | attr := &configschema.Attribute{ | ||
90 | Description: a.Description, | ||
91 | Required: a.Required, | ||
92 | Optional: a.Optional, | ||
93 | Computed: a.Computed, | ||
94 | Sensitive: a.Sensitive, | ||
95 | } | ||
96 | |||
97 | if err := json.Unmarshal(a.Type, &attr.Type); err != nil { | ||
98 | panic(err) | ||
99 | } | ||
100 | |||
101 | block.Attributes[a.Name] = attr | ||
102 | } | ||
103 | |||
104 | for _, b := range b.BlockTypes { | ||
105 | block.BlockTypes[b.TypeName] = schemaNestedBlock(b) | ||
106 | } | ||
107 | |||
108 | return block | ||
109 | } | ||
110 | |||
111 | func schemaNestedBlock(b *proto.Schema_NestedBlock) *configschema.NestedBlock { | ||
112 | var nesting configschema.NestingMode | ||
113 | switch b.Nesting { | ||
114 | case proto.Schema_NestedBlock_SINGLE: | ||
115 | nesting = configschema.NestingSingle | ||
116 | case proto.Schema_NestedBlock_GROUP: | ||
117 | nesting = configschema.NestingGroup | ||
118 | case proto.Schema_NestedBlock_LIST: | ||
119 | nesting = configschema.NestingList | ||
120 | case proto.Schema_NestedBlock_MAP: | ||
121 | nesting = configschema.NestingMap | ||
122 | case proto.Schema_NestedBlock_SET: | ||
123 | nesting = configschema.NestingSet | ||
124 | default: | ||
125 | // In all other cases we'll leave it as the zero value (invalid) and | ||
126 | // let the caller validate it and deal with this. | ||
127 | } | ||
128 | |||
129 | nb := &configschema.NestedBlock{ | ||
130 | Nesting: nesting, | ||
131 | MinItems: int(b.MinItems), | ||
132 | MaxItems: int(b.MaxItems), | ||
133 | } | ||
134 | |||
135 | nested := ProtoToConfigSchema(b.Block) | ||
136 | nb.Block = *nested | ||
137 | return nb | ||
138 | } | ||
139 | |||
140 | // sortedKeys returns the lexically sorted keys from the given map. This is | ||
141 | // used to make schema conversions are deterministic. This panics if map keys | ||
142 | // are not a string. | ||
143 | func sortedKeys(m interface{}) []string { | ||
144 | v := reflect.ValueOf(m) | ||
145 | keys := make([]string, v.Len()) | ||
146 | |||
147 | mapKeys := v.MapKeys() | ||
148 | for i, k := range mapKeys { | ||
149 | keys[i] = k.Interface().(string) | ||
150 | } | ||
151 | |||
152 | sort.Strings(keys) | ||
153 | return keys | ||
154 | } | ||