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  `