diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go new file mode 100644 index 0000000..181ea1f --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go | |||
@@ -0,0 +1,195 @@ | |||
1 | package discovery | ||
2 | |||
3 | // A PluginMetaSet is a set of PluginMeta objects meeting a certain criteria. | ||
4 | // | ||
5 | // Methods on this type allow filtering of the set to produce subsets that | ||
6 | // meet more restrictive criteria. | ||
7 | type PluginMetaSet map[PluginMeta]struct{} | ||
8 | |||
9 | // Add inserts the given PluginMeta into the receiving set. This is a no-op | ||
10 | // if the given meta is already present. | ||
11 | func (s PluginMetaSet) Add(p PluginMeta) { | ||
12 | s[p] = struct{}{} | ||
13 | } | ||
14 | |||
15 | // Remove removes the given PluginMeta from the receiving set. This is a no-op | ||
16 | // if the given meta is not already present. | ||
17 | func (s PluginMetaSet) Remove(p PluginMeta) { | ||
18 | delete(s, p) | ||
19 | } | ||
20 | |||
21 | // Has returns true if the given meta is in the receiving set, or false | ||
22 | // otherwise. | ||
23 | func (s PluginMetaSet) Has(p PluginMeta) bool { | ||
24 | _, ok := s[p] | ||
25 | return ok | ||
26 | } | ||
27 | |||
28 | // Count returns the number of metas in the set | ||
29 | func (s PluginMetaSet) Count() int { | ||
30 | return len(s) | ||
31 | } | ||
32 | |||
33 | // ValidateVersions returns two new PluginMetaSets, separating those with | ||
34 | // versions that have syntax-valid semver versions from those that don't. | ||
35 | // | ||
36 | // Eliminating invalid versions from consideration (and possibly warning about | ||
37 | // them) is usually the first step of working with a meta set after discovery | ||
38 | // has completed. | ||
39 | func (s PluginMetaSet) ValidateVersions() (valid, invalid PluginMetaSet) { | ||
40 | valid = make(PluginMetaSet) | ||
41 | invalid = make(PluginMetaSet) | ||
42 | for p := range s { | ||
43 | if _, err := p.Version.Parse(); err == nil { | ||
44 | valid.Add(p) | ||
45 | } else { | ||
46 | invalid.Add(p) | ||
47 | } | ||
48 | } | ||
49 | return | ||
50 | } | ||
51 | |||
52 | // WithName returns the subset of metas that have the given name. | ||
53 | func (s PluginMetaSet) WithName(name string) PluginMetaSet { | ||
54 | ns := make(PluginMetaSet) | ||
55 | for p := range s { | ||
56 | if p.Name == name { | ||
57 | ns.Add(p) | ||
58 | } | ||
59 | } | ||
60 | return ns | ||
61 | } | ||
62 | |||
63 | // WithVersion returns the subset of metas that have the given version. | ||
64 | // | ||
65 | // This should be used only with the "valid" result from ValidateVersions; | ||
66 | // it will ignore any plugin metas that have a invalid version strings. | ||
67 | func (s PluginMetaSet) WithVersion(version Version) PluginMetaSet { | ||
68 | ns := make(PluginMetaSet) | ||
69 | for p := range s { | ||
70 | gotVersion, err := p.Version.Parse() | ||
71 | if err != nil { | ||
72 | continue | ||
73 | } | ||
74 | if gotVersion.Equal(version) { | ||
75 | ns.Add(p) | ||
76 | } | ||
77 | } | ||
78 | return ns | ||
79 | } | ||
80 | |||
81 | // ByName groups the metas in the set by their Names, returning a map. | ||
82 | func (s PluginMetaSet) ByName() map[string]PluginMetaSet { | ||
83 | ret := make(map[string]PluginMetaSet) | ||
84 | for p := range s { | ||
85 | if _, ok := ret[p.Name]; !ok { | ||
86 | ret[p.Name] = make(PluginMetaSet) | ||
87 | } | ||
88 | ret[p.Name].Add(p) | ||
89 | } | ||
90 | return ret | ||
91 | } | ||
92 | |||
93 | // Newest returns the one item from the set that has the newest Version value. | ||
94 | // | ||
95 | // The result is meaningful only if the set is already filtered such that | ||
96 | // all of the metas have the same Name. | ||
97 | // | ||
98 | // If there isn't at least one meta in the set then this function will panic. | ||
99 | // Use Count() to ensure that there is at least one value before calling. | ||
100 | // | ||
101 | // If any of the metas have invalid version strings then this function will | ||
102 | // panic. Use ValidateVersions() first to filter out metas with invalid | ||
103 | // versions. | ||
104 | // | ||
105 | // If two metas have the same Version then one is arbitrarily chosen. This | ||
106 | // situation should be avoided by pre-filtering the set. | ||
107 | func (s PluginMetaSet) Newest() PluginMeta { | ||
108 | if len(s) == 0 { | ||
109 | panic("can't call NewestStable on empty PluginMetaSet") | ||
110 | } | ||
111 | |||
112 | var first = true | ||
113 | var winner PluginMeta | ||
114 | var winnerVersion Version | ||
115 | for p := range s { | ||
116 | version, err := p.Version.Parse() | ||
117 | if err != nil { | ||
118 | panic(err) | ||
119 | } | ||
120 | |||
121 | if first == true || version.NewerThan(winnerVersion) { | ||
122 | winner = p | ||
123 | winnerVersion = version | ||
124 | first = false | ||
125 | } | ||
126 | } | ||
127 | |||
128 | return winner | ||
129 | } | ||
130 | |||
131 | // ConstrainVersions takes a set of requirements and attempts to | ||
132 | // return a map from name to a set of metas that have the matching | ||
133 | // name and an appropriate version. | ||
134 | // | ||
135 | // If any of the given requirements match *no* plugins then its PluginMetaSet | ||
136 | // in the returned map will be empty. | ||
137 | // | ||
138 | // All viable metas are returned, so the caller can apply any desired filtering | ||
139 | // to reduce down to a single option. For example, calling Newest() to obtain | ||
140 | // the highest available version. | ||
141 | // | ||
142 | // If any of the metas in the set have invalid version strings then this | ||
143 | // function will panic. Use ValidateVersions() first to filter out metas with | ||
144 | // invalid versions. | ||
145 | func (s PluginMetaSet) ConstrainVersions(reqd PluginRequirements) map[string]PluginMetaSet { | ||
146 | ret := make(map[string]PluginMetaSet) | ||
147 | for p := range s { | ||
148 | name := p.Name | ||
149 | allowedVersions, ok := reqd[name] | ||
150 | if !ok { | ||
151 | continue | ||
152 | } | ||
153 | if _, ok := ret[p.Name]; !ok { | ||
154 | ret[p.Name] = make(PluginMetaSet) | ||
155 | } | ||
156 | version, err := p.Version.Parse() | ||
157 | if err != nil { | ||
158 | panic(err) | ||
159 | } | ||
160 | if allowedVersions.Allows(version) { | ||
161 | ret[p.Name].Add(p) | ||
162 | } | ||
163 | } | ||
164 | return ret | ||
165 | } | ||
166 | |||
167 | // OverridePaths returns a new set where any existing plugins with the given | ||
168 | // names are removed and replaced with the single path given in the map. | ||
169 | // | ||
170 | // This is here only to continue to support the legacy way of overriding | ||
171 | // plugin binaries in the .terraformrc file. It treats all given plugins | ||
172 | // as pre-versioning (version 0.0.0). This mechanism will eventually be | ||
173 | // phased out, with vendor directories being the intended replacement. | ||
174 | func (s PluginMetaSet) OverridePaths(paths map[string]string) PluginMetaSet { | ||
175 | ret := make(PluginMetaSet) | ||
176 | for p := range s { | ||
177 | if _, ok := paths[p.Name]; ok { | ||
178 | // Skip plugins that we're overridding | ||
179 | continue | ||
180 | } | ||
181 | |||
182 | ret.Add(p) | ||
183 | } | ||
184 | |||
185 | // Now add the metadata for overriding plugins | ||
186 | for name, path := range paths { | ||
187 | ret.Add(PluginMeta{ | ||
188 | Name: name, | ||
189 | Version: VersionZero, | ||
190 | Path: path, | ||
191 | }) | ||
192 | } | ||
193 | |||
194 | return ret | ||
195 | } | ||