]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go
Merge branch 'fix_read_test' of github.com:alexandreFre/terraform-provider-statuscake
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / aws / aws-sdk-go / aws / endpoints / v3model.go
CommitLineData
bae9f6d2
JC
1package endpoints
2
3import (
4 "fmt"
5 "regexp"
6 "strconv"
7 "strings"
8)
9
10type partitions []partition
11
12func (ps partitions) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
13 var opt Options
14 opt.Set(opts...)
15
16 for i := 0; i < len(ps); i++ {
17 if !ps[i].canResolveEndpoint(service, region, opt.StrictMatching) {
18 continue
19 }
20
21 return ps[i].EndpointFor(service, region, opts...)
22 }
23
24 // If loose matching fallback to first partition format to use
25 // when resolving the endpoint.
26 if !opt.StrictMatching && len(ps) > 0 {
27 return ps[0].EndpointFor(service, region, opts...)
28 }
29
30 return ResolvedEndpoint{}, NewUnknownEndpointError("all partitions", service, region, []string{})
31}
32
33// Partitions satisfies the EnumPartitions interface and returns a list
34// of Partitions representing each partition represented in the SDK's
35// endpoints model.
36func (ps partitions) Partitions() []Partition {
37 parts := make([]Partition, 0, len(ps))
38 for i := 0; i < len(ps); i++ {
39 parts = append(parts, ps[i].Partition())
40 }
41
42 return parts
43}
44
45type partition struct {
46 ID string `json:"partition"`
47 Name string `json:"partitionName"`
48 DNSSuffix string `json:"dnsSuffix"`
49 RegionRegex regionRegex `json:"regionRegex"`
50 Defaults endpoint `json:"defaults"`
51 Regions regions `json:"regions"`
52 Services services `json:"services"`
53}
54
55func (p partition) Partition() Partition {
56 return Partition{
57 id: p.ID,
58 p: &p,
59 }
60}
61
62func (p partition) canResolveEndpoint(service, region string, strictMatch bool) bool {
63 s, hasService := p.Services[service]
64 _, hasEndpoint := s.Endpoints[region]
65
66 if hasEndpoint && hasService {
67 return true
68 }
69
70 if strictMatch {
71 return false
72 }
73
74 return p.RegionRegex.MatchString(region)
75}
76
77func (p partition) EndpointFor(service, region string, opts ...func(*Options)) (resolved ResolvedEndpoint, err error) {
78 var opt Options
79 opt.Set(opts...)
80
81 s, hasService := p.Services[service]
82 if !(hasService || opt.ResolveUnknownService) {
83 // Only return error if the resolver will not fallback to creating
84 // endpoint based on service endpoint ID passed in.
85 return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services))
86 }
87
88 e, hasEndpoint := s.endpointForRegion(region)
89 if !hasEndpoint && opt.StrictMatching {
90 return resolved, NewUnknownEndpointError(p.ID, service, region, endpointList(s.Endpoints))
91 }
92
93 defs := []endpoint{p.Defaults, s.Defaults}
94 return e.resolve(service, region, p.DNSSuffix, defs, opt), nil
95}
96
97func serviceList(ss services) []string {
98 list := make([]string, 0, len(ss))
99 for k := range ss {
100 list = append(list, k)
101 }
102 return list
103}
104func endpointList(es endpoints) []string {
105 list := make([]string, 0, len(es))
106 for k := range es {
107 list = append(list, k)
108 }
109 return list
110}
111
112type regionRegex struct {
113 *regexp.Regexp
114}
115
116func (rr *regionRegex) UnmarshalJSON(b []byte) (err error) {
117 // Strip leading and trailing quotes
118 regex, err := strconv.Unquote(string(b))
119 if err != nil {
120 return fmt.Errorf("unable to strip quotes from regex, %v", err)
121 }
122
123 rr.Regexp, err = regexp.Compile(regex)
124 if err != nil {
125 return fmt.Errorf("unable to unmarshal region regex, %v", err)
126 }
127 return nil
128}
129
130type regions map[string]region
131
132type region struct {
133 Description string `json:"description"`
134}
135
136type services map[string]service
137
138type service struct {
139 PartitionEndpoint string `json:"partitionEndpoint"`
140 IsRegionalized boxedBool `json:"isRegionalized,omitempty"`
141 Defaults endpoint `json:"defaults"`
142 Endpoints endpoints `json:"endpoints"`
143}
144
145func (s *service) endpointForRegion(region string) (endpoint, bool) {
146 if s.IsRegionalized == boxedFalse {
147 return s.Endpoints[s.PartitionEndpoint], region == s.PartitionEndpoint
148 }
149
150 if e, ok := s.Endpoints[region]; ok {
151 return e, true
152 }
153
154 // Unable to find any matching endpoint, return
155 // blank that will be used for generic endpoint creation.
156 return endpoint{}, false
157}
158
159type endpoints map[string]endpoint
160
161type endpoint struct {
162 Hostname string `json:"hostname"`
163 Protocols []string `json:"protocols"`
164 CredentialScope credentialScope `json:"credentialScope"`
165
166 // Custom fields not modeled
167 HasDualStack boxedBool `json:"-"`
168 DualStackHostname string `json:"-"`
169
170 // Signature Version not used
171 SignatureVersions []string `json:"signatureVersions"`
172
173 // SSLCommonName not used.
174 SSLCommonName string `json:"sslCommonName"`
175}
176
177const (
178 defaultProtocol = "https"
179 defaultSigner = "v4"
180)
181
182var (
183 protocolPriority = []string{"https", "http"}
184 signerPriority = []string{"v4", "v2"}
185)
186
187func getByPriority(s []string, p []string, def string) string {
188 if len(s) == 0 {
189 return def
190 }
191
192 for i := 0; i < len(p); i++ {
193 for j := 0; j < len(s); j++ {
194 if s[j] == p[i] {
195 return s[j]
196 }
197 }
198 }
199
200 return s[0]
201}
202
203func (e endpoint) resolve(service, region, dnsSuffix string, defs []endpoint, opts Options) ResolvedEndpoint {
204 var merged endpoint
205 for _, def := range defs {
206 merged.mergeIn(def)
207 }
208 merged.mergeIn(e)
209 e = merged
210
211 hostname := e.Hostname
212
213 // Offset the hostname for dualstack if enabled
214 if opts.UseDualStack && e.HasDualStack == boxedTrue {
215 hostname = e.DualStackHostname
216 }
217
218 u := strings.Replace(hostname, "{service}", service, 1)
219 u = strings.Replace(u, "{region}", region, 1)
220 u = strings.Replace(u, "{dnsSuffix}", dnsSuffix, 1)
221
222 scheme := getEndpointScheme(e.Protocols, opts.DisableSSL)
223 u = fmt.Sprintf("%s://%s", scheme, u)
224
225 signingRegion := e.CredentialScope.Region
226 if len(signingRegion) == 0 {
227 signingRegion = region
228 }
15c0b25d 229
bae9f6d2 230 signingName := e.CredentialScope.Service
15c0b25d 231 var signingNameDerived bool
bae9f6d2
JC
232 if len(signingName) == 0 {
233 signingName = service
15c0b25d 234 signingNameDerived = true
bae9f6d2
JC
235 }
236
237 return ResolvedEndpoint{
15c0b25d
AP
238 URL: u,
239 SigningRegion: signingRegion,
240 SigningName: signingName,
241 SigningNameDerived: signingNameDerived,
242 SigningMethod: getByPriority(e.SignatureVersions, signerPriority, defaultSigner),
bae9f6d2
JC
243 }
244}
245
246func getEndpointScheme(protocols []string, disableSSL bool) string {
247 if disableSSL {
248 return "http"
249 }
250
251 return getByPriority(protocols, protocolPriority, defaultProtocol)
252}
253
254func (e *endpoint) mergeIn(other endpoint) {
255 if len(other.Hostname) > 0 {
256 e.Hostname = other.Hostname
257 }
258 if len(other.Protocols) > 0 {
259 e.Protocols = other.Protocols
260 }
261 if len(other.SignatureVersions) > 0 {
262 e.SignatureVersions = other.SignatureVersions
263 }
264 if len(other.CredentialScope.Region) > 0 {
265 e.CredentialScope.Region = other.CredentialScope.Region
266 }
267 if len(other.CredentialScope.Service) > 0 {
268 e.CredentialScope.Service = other.CredentialScope.Service
269 }
270 if len(other.SSLCommonName) > 0 {
271 e.SSLCommonName = other.SSLCommonName
272 }
273 if other.HasDualStack != boxedBoolUnset {
274 e.HasDualStack = other.HasDualStack
275 }
276 if len(other.DualStackHostname) > 0 {
277 e.DualStackHostname = other.DualStackHostname
278 }
279}
280
281type credentialScope struct {
282 Region string `json:"region"`
283 Service string `json:"service"`
284}
285
286type boxedBool int
287
288func (b *boxedBool) UnmarshalJSON(buf []byte) error {
289 v, err := strconv.ParseBool(string(buf))
290 if err != nil {
291 return err
292 }
293
294 if v {
295 *b = boxedTrue
296 } else {
297 *b = boxedFalse
298 }
299
300 return nil
301}
302
303const (
304 boxedBoolUnset boxedBool = iota
305 boxedFalse
306 boxedTrue
307)