smithy-go icon indicating copy to clipboard operation
smithy-go copied to clipboard

Adds code generation of Smithy modeled endpoint metadata

Open jasdel opened this issue 3 years ago • 1 comments

Issue #, if available:

Description of changes:

Adds support for generating endpoint metadata from API model.

TODO:

  • [x] Parameters can have default values, need to assign before validation
  • [x] Generate modeled endpoint tests
  • [x] Implement remaining builtin functions
  • [x] Parameter option docstrings are not getting generated correct
  • [x] Modeled test endpoint generator duplicates options of regular endpoint generation. This should be simplified.
  • [ ] Better logging of ErrorCollector
  • [ ] Endpoint properties should be use typed keys not string
    • [ ] AuthScheme key should should private to the API client module
    • [ ] Consider any new Properties key add to set of generated struct in endpoint package.
  • [x] Document endpoint/builtin types
  • [x] ~builtin.SubString is defined as returning an Optional value, but the valid-rules/substring.json and s3 rules use the result as value not optional.~
  • [x] Option<T> results when used in conditionals are will always cause conditional statements to be false. Not clear if this applies to other use cases as well.
  • [ ] Some rules include duplicate return statements
service/s3/internal/endpoints/smithy_endpoints.go:687:6: unreachable code
service/s3/internal/endpoints/smithy_endpoints.go:3304:4: unreachable code
  • [ ] test_case_12/TestEndpointCase7 expects 0x7F, non-printable character DEL, to be valid for SubString. This seems odd. Need to clarify behavior.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

jasdel avatar Sep 08 '22 22:09 jasdel

Example generated output
// Code generated by smithy-go-codegen DO NOT EDIT.

package test_suite_3

import (
	"fmt"
	smithy "github.com/aws/smithy-go"
	"github.com/aws/smithy-go/endpoint/builtin"
	smithytransport "github.com/aws/smithy-go/transport"
	"log"
	"strings"
)

type ReterminusOptions struct {
	// AWS::Region
	Region *string

	// Option is required.
	EndpointId *string

	// Option is required.
	//
	// AWS::UseDualStack
	UseDualStackEndpoint *bool

	// Option is required.
	//
	// AWS::UseFIPS
	UseFIPSEndpoint *bool
}

func (p ReterminusOptions) ValidateRequired() error {
	if p.Region == nil {
		return fmt.Errorf("parameter Region is required")
	}

	return nil
}

type ReterminusResolver struct{}

func (r ReterminusResolver) ResolveEndpoint(params ReterminusOptions) (
	endpoint smithytransport.Endpoint, err error,
) {
	if err = params.ValidateRequired(); err != nil {
		return endpoint, fmt.Errorf("endpoint parameters are not valid, %w", err)
	}
	_region := *params.Region

	ec := builtin.NewErrorCollector()
	defer func() {
		if !ec.IsEmpty() {
			log.Println("Endpoint resolution had errors,", ec)
		}
	}()

	if exprVal := builtin.AWSPartition(_region, ec); exprVal != nil {
		_partitionResult := *exprVal
		_ = _partitionResult
		if exprVal := params.EndpointId; exprVal != nil {
			_endpointId := *exprVal
			_ = _endpointId
			if exprVal := params.UseFIPSEndpoint; exprVal != nil {
				_useFIPSEndpoint := *exprVal
				_ = _useFIPSEndpoint
				if _useFIPSEndpoint == true {
					return endpoint, fmt.Errorf("endpoint rule error, %s", "FIPS endpoints not supported with multi-region endpoints")
				}
			}
			if !(params.UseFIPSEndpoint != nil) {
				if exprVal := params.UseDualStackEndpoint; exprVal != nil {
					_useDualStackEndpoint := *exprVal
					_ = _useDualStackEndpoint
					if _useDualStackEndpoint == true {
						return smithytransport.Endpoint{
							URI: func() string {
								var out strings.Builder
								out.WriteString("https://")
								out.WriteString(_endpointId)
								out.WriteString(".endpoint.events.")
								out.WriteString(_partitionResult.DualStackDnsSuffix)
								return out.String()
							}(),

							Properties: func() smithy.Properties {
								var out smithy.Properties
								out.Set("authSchemes", []interface{}{
									map[string]interface{}{
										"signingRegionSet": []interface{}{
											"*",
										},
										"name":        "sigv4a",
										"signingName": "events",
									},
								})
								return out
							}(),
						}, nil
					}
				}
			}
			return smithytransport.Endpoint{
				URI: func() string {
					var out strings.Builder
					out.WriteString("https://")
					out.WriteString(_endpointId)
					out.WriteString(".endpoint.events.")
					out.WriteString(_partitionResult.DnsSuffix)
					return out.String()
				}(),

				Properties: func() smithy.Properties {
					var out smithy.Properties
					out.Set("authSchemes", []interface{}{
						map[string]interface{}{
							"signingRegionSet": []interface{}{
								"*",
							},
							"name":        "sigv4a",
							"signingName": "events",
						},
					})
					return out
				}(),
			}, nil
		}
		if builtin.IsValidHostLabel(_region, false, ec) {
			if exprVal := params.UseFIPSEndpoint; exprVal != nil {
				_useFIPSEndpoint := *exprVal
				_ = _useFIPSEndpoint
				if _useFIPSEndpoint == true {
					if !(params.UseDualStackEndpoint != nil) {
						return smithytransport.Endpoint{
							URI: func() string {
								var out strings.Builder
								out.WriteString("https://events-fips.")
								out.WriteString(_region)
								out.WriteString(".")
								out.WriteString(_partitionResult.DnsSuffix)
								return out.String()
							}(),

							Properties: func() smithy.Properties {
								var out smithy.Properties
								out.Set("authSchemes", []interface{}{
									map[string]interface{}{
										"signingRegionSet": []interface{}{
											"*",
										},
										"name":        "sigv4a",
										"signingName": "events",
									},
								})
								return out
							}(),
						}, nil
					}
				}
			}
			if exprVal := params.UseDualStackEndpoint; exprVal != nil {
				_useDualStackEndpoint := *exprVal
				_ = _useDualStackEndpoint
				if _useDualStackEndpoint == true {
					if !(params.UseFIPSEndpoint != nil) {
						return smithytransport.Endpoint{
							URI: func() string {
								var out strings.Builder
								out.WriteString("https://events.")
								out.WriteString(_region)
								out.WriteString(".")
								out.WriteString(_partitionResult.DualStackDnsSuffix)
								return out.String()
							}(),

							Properties: func() smithy.Properties {
								var out smithy.Properties
								out.Set("authSchemes", []interface{}{
									map[string]interface{}{
										"signingRegionSet": []interface{}{
											"*",
										},
										"name":        "sigv4a",
										"signingName": "events",
									},
								})
								return out
							}(),
						}, nil
					}
				}
			}
			if exprVal := params.UseDualStackEndpoint; exprVal != nil {
				_useDualStackEndpoint := *exprVal
				_ = _useDualStackEndpoint
				if exprVal := params.UseFIPSEndpoint; exprVal != nil {
					_useFIPSEndpoint := *exprVal
					_ = _useFIPSEndpoint
					if _useDualStackEndpoint == true {
						if _useFIPSEndpoint == true {
							return smithytransport.Endpoint{
								URI: func() string {
									var out strings.Builder
									out.WriteString("https://events-fips.")
									out.WriteString(_region)
									out.WriteString(".")
									out.WriteString(_partitionResult.DualStackDnsSuffix)
									return out.String()
								}(),

								Properties: func() smithy.Properties {
									var out smithy.Properties
									out.Set("authSchemes", []interface{}{
										map[string]interface{}{
											"signingRegionSet": []interface{}{
												"*",
											},
											"name":        "sigv4a",
											"signingName": "events",
										},
									})
									return out
								}(),
							}, nil
						}
					}
				}
			}
			return smithytransport.Endpoint{
				URI: func() string {
					var out strings.Builder
					out.WriteString("https://events.")
					out.WriteString(_region)
					out.WriteString(".")
					out.WriteString(_partitionResult.DnsSuffix)
					return out.String()
				}(),
			}, nil
		}
		return endpoint, fmt.Errorf("endpoint rule error, %s", func() string {
			var out strings.Builder
			out.WriteString(_region)
			out.WriteString(" is not a valid HTTP host-label")
			return out.String()
		}())
	}
	return endpoint, fmt.Errorf("no rules matched these parameters. This is a bug.")
}

jasdel avatar Sep 08 '22 22:09 jasdel

stale

lucix-aws avatar Aug 07 '23 14:08 lucix-aws