github.com/aavshr/aws-sdk-go@v1.41.3/aws/endpoints/v3model_codegen.go (about) 1 //go:build codegen 2 // +build codegen 3 4 package endpoints 5 6 import ( 7 "fmt" 8 "io" 9 "reflect" 10 "strings" 11 "text/template" 12 "unicode" 13 ) 14 15 // A CodeGenOptions are the options for code generating the endpoints into 16 // Go code from the endpoints model definition. 17 type CodeGenOptions struct { 18 // Options for how the model will be decoded. 19 DecodeModelOptions DecodeModelOptions 20 21 // Disables code generation of the service endpoint prefix IDs defined in 22 // the model. 23 DisableGenerateServiceIDs bool 24 } 25 26 // Set combines all of the option functions together 27 func (d *CodeGenOptions) Set(optFns ...func(*CodeGenOptions)) { 28 for _, fn := range optFns { 29 fn(d) 30 } 31 } 32 33 // CodeGenModel given a endpoints model file will decode it and attempt to 34 // generate Go code from the model definition. Error will be returned if 35 // the code is unable to be generated, or decoded. 36 func CodeGenModel(modelFile io.Reader, outFile io.Writer, optFns ...func(*CodeGenOptions)) error { 37 var opts CodeGenOptions 38 opts.Set(optFns...) 39 40 resolver, err := DecodeModel(modelFile, func(d *DecodeModelOptions) { 41 *d = opts.DecodeModelOptions 42 }) 43 if err != nil { 44 return err 45 } 46 47 v := struct { 48 Resolver 49 CodeGenOptions 50 }{ 51 Resolver: resolver, 52 CodeGenOptions: opts, 53 } 54 55 tmpl := template.Must(template.New("tmpl").Funcs(funcMap).Parse(v3Tmpl)) 56 if err := tmpl.ExecuteTemplate(outFile, "defaults", v); err != nil { 57 return fmt.Errorf("failed to execute template, %v", err) 58 } 59 60 return nil 61 } 62 63 func toSymbol(v string) string { 64 out := []rune{} 65 for _, c := range strings.Title(v) { 66 if !(unicode.IsNumber(c) || unicode.IsLetter(c)) { 67 continue 68 } 69 70 out = append(out, c) 71 } 72 73 return string(out) 74 } 75 76 func quoteString(v string) string { 77 return fmt.Sprintf("%q", v) 78 } 79 80 func regionConstName(p, r string) string { 81 return toSymbol(p) + toSymbol(r) 82 } 83 84 func partitionGetter(id string) string { 85 return fmt.Sprintf("%sPartition", toSymbol(id)) 86 } 87 88 func partitionVarName(id string) string { 89 return fmt.Sprintf("%sPartition", strings.ToLower(toSymbol(id))) 90 } 91 92 func listPartitionNames(ps partitions) string { 93 names := []string{} 94 switch len(ps) { 95 case 1: 96 return ps[0].Name 97 case 2: 98 return fmt.Sprintf("%s and %s", ps[0].Name, ps[1].Name) 99 default: 100 for i, p := range ps { 101 if i == len(ps)-1 { 102 names = append(names, "and "+p.Name) 103 } else { 104 names = append(names, p.Name) 105 } 106 } 107 return strings.Join(names, ", ") 108 } 109 } 110 111 func boxedBoolIfSet(msg string, v boxedBool) string { 112 switch v { 113 case boxedTrue: 114 return fmt.Sprintf(msg, "boxedTrue") 115 case boxedFalse: 116 return fmt.Sprintf(msg, "boxedFalse") 117 default: 118 return "" 119 } 120 } 121 122 func stringIfSet(msg, v string) string { 123 if len(v) == 0 { 124 return "" 125 } 126 127 return fmt.Sprintf(msg, v) 128 } 129 130 func stringSliceIfSet(msg string, vs []string) string { 131 if len(vs) == 0 { 132 return "" 133 } 134 135 names := []string{} 136 for _, v := range vs { 137 names = append(names, `"`+v+`"`) 138 } 139 140 return fmt.Sprintf(msg, strings.Join(names, ",")) 141 } 142 143 func endpointIsSet(v endpoint) bool { 144 return !reflect.DeepEqual(v, endpoint{}) 145 } 146 147 func serviceSet(ps partitions) map[string]struct{} { 148 set := map[string]struct{}{} 149 for _, p := range ps { 150 for id := range p.Services { 151 set[id] = struct{}{} 152 } 153 } 154 155 return set 156 } 157 158 var funcMap = template.FuncMap{ 159 "ToSymbol": toSymbol, 160 "QuoteString": quoteString, 161 "RegionConst": regionConstName, 162 "PartitionGetter": partitionGetter, 163 "PartitionVarName": partitionVarName, 164 "ListPartitionNames": listPartitionNames, 165 "BoxedBoolIfSet": boxedBoolIfSet, 166 "StringIfSet": stringIfSet, 167 "StringSliceIfSet": stringSliceIfSet, 168 "EndpointIsSet": endpointIsSet, 169 "ServicesSet": serviceSet, 170 } 171 172 const v3Tmpl = ` 173 {{ define "defaults" -}} 174 // Code generated by aws/endpoints/v3model_codegen.go. DO NOT EDIT. 175 176 package endpoints 177 178 import ( 179 "regexp" 180 ) 181 182 {{ template "partition consts" $.Resolver }} 183 184 {{ range $_, $partition := $.Resolver }} 185 {{ template "partition region consts" $partition }} 186 {{ end }} 187 188 {{ if not $.DisableGenerateServiceIDs -}} 189 {{ template "service consts" $.Resolver }} 190 {{- end }} 191 192 {{ template "endpoint resolvers" $.Resolver }} 193 {{- end }} 194 195 {{ define "partition consts" }} 196 // Partition identifiers 197 const ( 198 {{ range $_, $p := . -}} 199 {{ ToSymbol $p.ID }}PartitionID = {{ QuoteString $p.ID }} // {{ $p.Name }} partition. 200 {{ end -}} 201 ) 202 {{- end }} 203 204 {{ define "partition region consts" }} 205 // {{ .Name }} partition's regions. 206 const ( 207 {{ range $id, $region := .Regions -}} 208 {{ ToSymbol $id }}RegionID = {{ QuoteString $id }} // {{ $region.Description }}. 209 {{ end -}} 210 ) 211 {{- end }} 212 213 {{ define "service consts" }} 214 // Service identifiers 215 const ( 216 {{ $serviceSet := ServicesSet . -}} 217 {{ range $id, $_ := $serviceSet -}} 218 {{ ToSymbol $id }}ServiceID = {{ QuoteString $id }} // {{ ToSymbol $id }}. 219 {{ end -}} 220 ) 221 {{- end }} 222 223 {{ define "endpoint resolvers" }} 224 // DefaultResolver returns an Endpoint resolver that will be able 225 // to resolve endpoints for: {{ ListPartitionNames . }}. 226 // 227 // Use DefaultPartitions() to get the list of the default partitions. 228 func DefaultResolver() Resolver { 229 return defaultPartitions 230 } 231 232 // DefaultPartitions returns a list of the partitions the SDK is bundled 233 // with. The available partitions are: {{ ListPartitionNames . }}. 234 // 235 // partitions := endpoints.DefaultPartitions 236 // for _, p := range partitions { 237 // // ... inspect partitions 238 // } 239 func DefaultPartitions() []Partition { 240 return defaultPartitions.Partitions() 241 } 242 243 var defaultPartitions = partitions{ 244 {{ range $_, $partition := . -}} 245 {{ PartitionVarName $partition.ID }}, 246 {{ end }} 247 } 248 249 {{ range $_, $partition := . -}} 250 {{ $name := PartitionGetter $partition.ID -}} 251 // {{ $name }} returns the Resolver for {{ $partition.Name }}. 252 func {{ $name }}() Partition { 253 return {{ PartitionVarName $partition.ID }}.Partition() 254 } 255 var {{ PartitionVarName $partition.ID }} = {{ template "gocode Partition" $partition }} 256 {{ end }} 257 {{ end }} 258 259 {{ define "default partitions" }} 260 func DefaultPartitions() []Partition { 261 return []partition{ 262 {{ range $_, $partition := . -}} 263 // {{ ToSymbol $partition.ID}}Partition(), 264 {{ end }} 265 } 266 } 267 {{ end }} 268 269 {{ define "gocode Partition" -}} 270 partition{ 271 {{ StringIfSet "ID: %q,\n" .ID -}} 272 {{ StringIfSet "Name: %q,\n" .Name -}} 273 {{ StringIfSet "DNSSuffix: %q,\n" .DNSSuffix -}} 274 RegionRegex: {{ template "gocode RegionRegex" .RegionRegex }}, 275 {{ if EndpointIsSet .Defaults -}} 276 Defaults: {{ template "gocode Endpoint" .Defaults }}, 277 {{- end }} 278 Regions: {{ template "gocode Regions" .Regions }}, 279 Services: {{ template "gocode Services" .Services }}, 280 } 281 {{- end }} 282 283 {{ define "gocode RegionRegex" -}} 284 regionRegex{ 285 Regexp: func() *regexp.Regexp{ 286 reg, _ := regexp.Compile({{ QuoteString .Regexp.String }}) 287 return reg 288 }(), 289 } 290 {{- end }} 291 292 {{ define "gocode Regions" -}} 293 regions{ 294 {{ range $id, $region := . -}} 295 "{{ $id }}": {{ template "gocode Region" $region }}, 296 {{ end -}} 297 } 298 {{- end }} 299 300 {{ define "gocode Region" -}} 301 region{ 302 {{ StringIfSet "Description: %q,\n" .Description -}} 303 } 304 {{- end }} 305 306 {{ define "gocode Services" -}} 307 services{ 308 {{ range $id, $service := . -}} 309 "{{ $id }}": {{ template "gocode Service" $service }}, 310 {{ end }} 311 } 312 {{- end }} 313 314 {{ define "gocode Service" -}} 315 service{ 316 {{ StringIfSet "PartitionEndpoint: %q,\n" .PartitionEndpoint -}} 317 {{ BoxedBoolIfSet "IsRegionalized: %s,\n" .IsRegionalized -}} 318 {{ if EndpointIsSet .Defaults -}} 319 Defaults: {{ template "gocode Endpoint" .Defaults -}}, 320 {{- end }} 321 {{ if .Endpoints -}} 322 Endpoints: {{ template "gocode Endpoints" .Endpoints }}, 323 {{- end }} 324 } 325 {{- end }} 326 327 {{ define "gocode Endpoints" -}} 328 endpoints{ 329 {{ range $id, $endpoint := . -}} 330 "{{ $id }}": {{ template "gocode Endpoint" $endpoint }}, 331 {{ end }} 332 } 333 {{- end }} 334 335 {{ define "gocode Endpoint" -}} 336 endpoint{ 337 {{ StringIfSet "Hostname: %q,\n" .Hostname -}} 338 {{ StringIfSet "SSLCommonName: %q,\n" .SSLCommonName -}} 339 {{ StringSliceIfSet "Protocols: []string{%s},\n" .Protocols -}} 340 {{ StringSliceIfSet "SignatureVersions: []string{%s},\n" .SignatureVersions -}} 341 {{ if or .CredentialScope.Region .CredentialScope.Service -}} 342 CredentialScope: credentialScope{ 343 {{ StringIfSet "Region: %q,\n" .CredentialScope.Region -}} 344 {{ StringIfSet "Service: %q,\n" .CredentialScope.Service -}} 345 }, 346 {{- end }} 347 {{ BoxedBoolIfSet "HasDualStack: %s,\n" .HasDualStack -}} 348 {{ StringIfSet "DualStackHostname: %q,\n" .DualStackHostname -}} 349 350 } 351 {{- end }} 352 `