forked from TrueCloudLab/rclone
337 lines
7.9 KiB
Go
337 lines
7.9 KiB
Go
// +build codegen
|
|
|
|
package endpoints
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"reflect"
|
|
"strings"
|
|
"text/template"
|
|
"unicode"
|
|
)
|
|
|
|
// A CodeGenOptions are the options for code generating the endpoints into
|
|
// Go code from the endpoints model definition.
|
|
type CodeGenOptions struct {
|
|
// Options for how the model will be decoded.
|
|
DecodeModelOptions DecodeModelOptions
|
|
}
|
|
|
|
// Set combines all of the option functions together
|
|
func (d *CodeGenOptions) Set(optFns ...func(*CodeGenOptions)) {
|
|
for _, fn := range optFns {
|
|
fn(d)
|
|
}
|
|
}
|
|
|
|
// CodeGenModel given a endpoints model file will decode it and attempt to
|
|
// generate Go code from the model definition. Error will be returned if
|
|
// the code is unable to be generated, or decoded.
|
|
func CodeGenModel(modelFile io.Reader, outFile io.Writer, optFns ...func(*CodeGenOptions)) error {
|
|
var opts CodeGenOptions
|
|
opts.Set(optFns...)
|
|
|
|
resolver, err := DecodeModel(modelFile, func(d *DecodeModelOptions) {
|
|
*d = opts.DecodeModelOptions
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tmpl := template.Must(template.New("tmpl").Funcs(funcMap).Parse(v3Tmpl))
|
|
if err := tmpl.ExecuteTemplate(outFile, "defaults", resolver); err != nil {
|
|
return fmt.Errorf("failed to execute template, %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func toSymbol(v string) string {
|
|
out := []rune{}
|
|
for _, c := range strings.Title(v) {
|
|
if !(unicode.IsNumber(c) || unicode.IsLetter(c)) {
|
|
continue
|
|
}
|
|
|
|
out = append(out, c)
|
|
}
|
|
|
|
return string(out)
|
|
}
|
|
|
|
func quoteString(v string) string {
|
|
return fmt.Sprintf("%q", v)
|
|
}
|
|
|
|
func regionConstName(p, r string) string {
|
|
return toSymbol(p) + toSymbol(r)
|
|
}
|
|
|
|
func partitionGetter(id string) string {
|
|
return fmt.Sprintf("%sPartition", toSymbol(id))
|
|
}
|
|
|
|
func partitionVarName(id string) string {
|
|
return fmt.Sprintf("%sPartition", strings.ToLower(toSymbol(id)))
|
|
}
|
|
|
|
func listPartitionNames(ps partitions) string {
|
|
names := []string{}
|
|
switch len(ps) {
|
|
case 1:
|
|
return ps[0].Name
|
|
case 2:
|
|
return fmt.Sprintf("%s and %s", ps[0].Name, ps[1].Name)
|
|
default:
|
|
for i, p := range ps {
|
|
if i == len(ps)-1 {
|
|
names = append(names, "and "+p.Name)
|
|
} else {
|
|
names = append(names, p.Name)
|
|
}
|
|
}
|
|
return strings.Join(names, ", ")
|
|
}
|
|
}
|
|
|
|
func boxedBoolIfSet(msg string, v boxedBool) string {
|
|
switch v {
|
|
case boxedTrue:
|
|
return fmt.Sprintf(msg, "boxedTrue")
|
|
case boxedFalse:
|
|
return fmt.Sprintf(msg, "boxedFalse")
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func stringIfSet(msg, v string) string {
|
|
if len(v) == 0 {
|
|
return ""
|
|
}
|
|
|
|
return fmt.Sprintf(msg, v)
|
|
}
|
|
|
|
func stringSliceIfSet(msg string, vs []string) string {
|
|
if len(vs) == 0 {
|
|
return ""
|
|
}
|
|
|
|
names := []string{}
|
|
for _, v := range vs {
|
|
names = append(names, `"`+v+`"`)
|
|
}
|
|
|
|
return fmt.Sprintf(msg, strings.Join(names, ","))
|
|
}
|
|
|
|
func endpointIsSet(v endpoint) bool {
|
|
return !reflect.DeepEqual(v, endpoint{})
|
|
}
|
|
|
|
func serviceSet(ps partitions) map[string]struct{} {
|
|
set := map[string]struct{}{}
|
|
for _, p := range ps {
|
|
for id := range p.Services {
|
|
set[id] = struct{}{}
|
|
}
|
|
}
|
|
|
|
return set
|
|
}
|
|
|
|
var funcMap = template.FuncMap{
|
|
"ToSymbol": toSymbol,
|
|
"QuoteString": quoteString,
|
|
"RegionConst": regionConstName,
|
|
"PartitionGetter": partitionGetter,
|
|
"PartitionVarName": partitionVarName,
|
|
"ListPartitionNames": listPartitionNames,
|
|
"BoxedBoolIfSet": boxedBoolIfSet,
|
|
"StringIfSet": stringIfSet,
|
|
"StringSliceIfSet": stringSliceIfSet,
|
|
"EndpointIsSet": endpointIsSet,
|
|
"ServicesSet": serviceSet,
|
|
}
|
|
|
|
const v3Tmpl = `
|
|
{{ define "defaults" -}}
|
|
// Code generated by aws/endpoints/v3model_codegen.go. DO NOT EDIT.
|
|
|
|
package endpoints
|
|
|
|
import (
|
|
"regexp"
|
|
)
|
|
|
|
{{ template "partition consts" . }}
|
|
|
|
{{ range $_, $partition := . }}
|
|
{{ template "partition region consts" $partition }}
|
|
{{ end }}
|
|
|
|
{{ template "service consts" . }}
|
|
|
|
{{ template "endpoint resolvers" . }}
|
|
{{- end }}
|
|
|
|
{{ define "partition consts" }}
|
|
// Partition identifiers
|
|
const (
|
|
{{ range $_, $p := . -}}
|
|
{{ ToSymbol $p.ID }}PartitionID = {{ QuoteString $p.ID }} // {{ $p.Name }} partition.
|
|
{{ end -}}
|
|
)
|
|
{{- end }}
|
|
|
|
{{ define "partition region consts" }}
|
|
// {{ .Name }} partition's regions.
|
|
const (
|
|
{{ range $id, $region := .Regions -}}
|
|
{{ ToSymbol $id }}RegionID = {{ QuoteString $id }} // {{ $region.Description }}.
|
|
{{ end -}}
|
|
)
|
|
{{- end }}
|
|
|
|
{{ define "service consts" }}
|
|
// Service identifiers
|
|
const (
|
|
{{ $serviceSet := ServicesSet . -}}
|
|
{{ range $id, $_ := $serviceSet -}}
|
|
{{ ToSymbol $id }}ServiceID = {{ QuoteString $id }} // {{ ToSymbol $id }}.
|
|
{{ end -}}
|
|
)
|
|
{{- end }}
|
|
|
|
{{ define "endpoint resolvers" }}
|
|
// DefaultResolver returns an Endpoint resolver that will be able
|
|
// to resolve endpoints for: {{ ListPartitionNames . }}.
|
|
//
|
|
// Use DefaultPartitions() to get the list of the default partitions.
|
|
func DefaultResolver() Resolver {
|
|
return defaultPartitions
|
|
}
|
|
|
|
// DefaultPartitions returns a list of the partitions the SDK is bundled
|
|
// with. The available partitions are: {{ ListPartitionNames . }}.
|
|
//
|
|
// partitions := endpoints.DefaultPartitions
|
|
// for _, p := range partitions {
|
|
// // ... inspect partitions
|
|
// }
|
|
func DefaultPartitions() []Partition {
|
|
return defaultPartitions.Partitions()
|
|
}
|
|
|
|
var defaultPartitions = partitions{
|
|
{{ range $_, $partition := . -}}
|
|
{{ PartitionVarName $partition.ID }},
|
|
{{ end }}
|
|
}
|
|
|
|
{{ range $_, $partition := . -}}
|
|
{{ $name := PartitionGetter $partition.ID -}}
|
|
// {{ $name }} returns the Resolver for {{ $partition.Name }}.
|
|
func {{ $name }}() Partition {
|
|
return {{ PartitionVarName $partition.ID }}.Partition()
|
|
}
|
|
var {{ PartitionVarName $partition.ID }} = {{ template "gocode Partition" $partition }}
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ define "default partitions" }}
|
|
func DefaultPartitions() []Partition {
|
|
return []partition{
|
|
{{ range $_, $partition := . -}}
|
|
// {{ ToSymbol $partition.ID}}Partition(),
|
|
{{ end }}
|
|
}
|
|
}
|
|
{{ end }}
|
|
|
|
{{ define "gocode Partition" -}}
|
|
partition{
|
|
{{ StringIfSet "ID: %q,\n" .ID -}}
|
|
{{ StringIfSet "Name: %q,\n" .Name -}}
|
|
{{ StringIfSet "DNSSuffix: %q,\n" .DNSSuffix -}}
|
|
RegionRegex: {{ template "gocode RegionRegex" .RegionRegex }},
|
|
{{ if EndpointIsSet .Defaults -}}
|
|
Defaults: {{ template "gocode Endpoint" .Defaults }},
|
|
{{- end }}
|
|
Regions: {{ template "gocode Regions" .Regions }},
|
|
Services: {{ template "gocode Services" .Services }},
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "gocode RegionRegex" -}}
|
|
regionRegex{
|
|
Regexp: func() *regexp.Regexp{
|
|
reg, _ := regexp.Compile({{ QuoteString .Regexp.String }})
|
|
return reg
|
|
}(),
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "gocode Regions" -}}
|
|
regions{
|
|
{{ range $id, $region := . -}}
|
|
"{{ $id }}": {{ template "gocode Region" $region }},
|
|
{{ end -}}
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "gocode Region" -}}
|
|
region{
|
|
{{ StringIfSet "Description: %q,\n" .Description -}}
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "gocode Services" -}}
|
|
services{
|
|
{{ range $id, $service := . -}}
|
|
"{{ $id }}": {{ template "gocode Service" $service }},
|
|
{{ end }}
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "gocode Service" -}}
|
|
service{
|
|
{{ StringIfSet "PartitionEndpoint: %q,\n" .PartitionEndpoint -}}
|
|
{{ BoxedBoolIfSet "IsRegionalized: %s,\n" .IsRegionalized -}}
|
|
{{ if EndpointIsSet .Defaults -}}
|
|
Defaults: {{ template "gocode Endpoint" .Defaults -}},
|
|
{{- end }}
|
|
{{ if .Endpoints -}}
|
|
Endpoints: {{ template "gocode Endpoints" .Endpoints }},
|
|
{{- end }}
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "gocode Endpoints" -}}
|
|
endpoints{
|
|
{{ range $id, $endpoint := . -}}
|
|
"{{ $id }}": {{ template "gocode Endpoint" $endpoint }},
|
|
{{ end }}
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "gocode Endpoint" -}}
|
|
endpoint{
|
|
{{ StringIfSet "Hostname: %q,\n" .Hostname -}}
|
|
{{ StringIfSet "SSLCommonName: %q,\n" .SSLCommonName -}}
|
|
{{ StringSliceIfSet "Protocols: []string{%s},\n" .Protocols -}}
|
|
{{ StringSliceIfSet "SignatureVersions: []string{%s},\n" .SignatureVersions -}}
|
|
{{ if or .CredentialScope.Region .CredentialScope.Service -}}
|
|
CredentialScope: credentialScope{
|
|
{{ StringIfSet "Region: %q,\n" .CredentialScope.Region -}}
|
|
{{ StringIfSet "Service: %q,\n" .CredentialScope.Service -}}
|
|
},
|
|
{{- end }}
|
|
{{ BoxedBoolIfSet "HasDualStack: %s,\n" .HasDualStack -}}
|
|
{{ StringIfSet "DualStackHostname: %q,\n" .DualStackHostname -}}
|
|
|
|
}
|
|
{{- end }}
|
|
`
|