Skip to content

Commit

Permalink
V3: New API ListZones Endpoint Mapping (#616)
Browse files Browse the repository at this point in the history
# Description

Use the new API ListZones to replace the zone endpoint static mapping.

Renaming of `URL` to `Endpoint` to match the API definition 

Generator support Extension attribute with `x-go-type`

---------

Signed-off-by: Pierre-Emmanuel Jacquier <15922119+pierre-emmanuelJ@users.noreply.github.com>
  • Loading branch information
pierre-emmanuelJ authored Feb 6, 2024
1 parent 2f4651b commit cf4abaf
Show file tree
Hide file tree
Showing 7 changed files with 519 additions and 485 deletions.
76 changes: 41 additions & 35 deletions v3/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 5 additions & 9 deletions v3/generator/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,8 @@ func extractAPIName(s *v3.Server) (string, error) {

// Template use client.tmpl file
type Template struct {
Enum string
Zones string
ServerURL string
Enum string
ServerEndpoint string
}

// renderClient using the client.tmpl template.
Expand All @@ -105,17 +104,14 @@ func renderClient(s *v3.Server) ([]byte, error) {
}

enum := ""
zones := ""
for _, z := range v.Enum {
url := strings.Replace(s.URL, "{zone}", z, 1)
enum += fmt.Sprintf("%s URL = %q\n", helpers.ToCamel(z), url)
zones += fmt.Sprintf("%q: %s,\n", z, helpers.ToCamel(z))
enum += fmt.Sprintf("%s Endpoint = %q\n", helpers.ToCamel(z), url)
}

client = Template{
ServerURL: helpers.ToCamel(v.Default),
Enum: enum,
Zones: zones,
ServerEndpoint: helpers.ToCamel(v.Default),
Enum: enum,
}
}

Expand Down
56 changes: 34 additions & 22 deletions v3/generator/client/client.tmpl
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
// URL represents a zoned url endpoint.
type URL string
// Endpoint represents a zone endpoint.
type Endpoint string

const (
{{ .Enum }}
)

// Zone gets the zone name from the URL.
func (u URL) Zone() (string, bool) {
for zone, url := range Zones {
if url == u {
return zone, true
func (c Client) GetZoneName(ctx context.Context, endpoint Endpoint) (ZoneName, error) {
resp, err := c.ListZones(ctx)
if err != nil {
return "", fmt.Errorf("get zone name: %w", err)
}
for _, zone := range resp.Zones {
if zone.APIEndpoint == endpoint {
return zone.Name, nil
}
}

return "", false
return "", fmt.Errorf("get zone name: no matching zone for %s", endpoint)
}

// Zones represents a list of all Exoscale zone.
var Zones map[string]URL = map[string]URL{
{{ .Zones }}
func (c Client) GetZoneAPIEndpoint(ctx context.Context, zoneName ZoneName) (Endpoint, error) {
resp, err := c.ListZones(ctx)
if err != nil {
return "", fmt.Errorf("get zone api endpoint: %w", err)
}
for _, zone := range resp.Zones {
if zone.Name == zoneName {
return zone.APIEndpoint, nil
}
}

return "", fmt.Errorf("get zone api endpoint: zone name %s not found", zoneName)
}

// Client represents an Exoscale API client.
type Client struct {
apiKey string
apiSecret string
serverURL string
serverEndpoint string
httpClient *http.Client
timeout time.Duration
pollingInterval time.Duration
Expand Down Expand Up @@ -80,10 +92,10 @@ func ClientOptWithValidator(validate *validator.Validate) ClientOpt {
}
}

// ClientOptWithURL returns a ClientOpt With a given zone URL.
func ClientOptWithURL(url URL) ClientOpt {
// ClientOptWithEndpoint returns a ClientOpt With a given zone Endpoint.
func ClientOptWithEndpoint(endpoint Endpoint) ClientOpt {
return func(c *Client) error {
c.serverURL = string(url)
c.serverEndpoint = string(endpoint)
return nil
}
}
Expand Down Expand Up @@ -119,7 +131,7 @@ func NewClient(apiKey, apiSecret string, opts ...ClientOpt) (*Client, error) {
client := &Client{
apiKey: apiKey,
apiSecret: apiSecret,
serverURL: string({{ .ServerURL }}),
serverEndpoint: string({{ .ServerEndpoint }}),
httpClient: http.DefaultClient,
pollingInterval: pollingInterval,
validate: validator.New(),
Expand All @@ -134,12 +146,12 @@ func NewClient(apiKey, apiSecret string, opts ...ClientOpt) (*Client, error) {
return client, nil
}

// WithURL returns a copy of Client with new zone URL.
func (c *Client) WithURL(url URL) *Client {
// WithEndpoint returns a copy of Client with new zone Endpoint.
func (c *Client) WithEndpoint(endpoint Endpoint) *Client {
return &Client{
apiKey: c.apiKey,
apiSecret: c.apiSecret,
serverURL: string(url),
serverEndpoint: string(endpoint),
httpClient: c.httpClient,
requestInterceptors: c.requestInterceptors,
pollingInterval: c.pollingInterval,
Expand All @@ -152,7 +164,7 @@ func (c *Client) WithTrace() *Client {
return &Client{
apiKey: c.apiKey,
apiSecret: c.apiSecret,
serverURL: c.serverURL,
serverEndpoint: c.serverEndpoint,
httpClient: c.httpClient,
requestInterceptors: c.requestInterceptors,
pollingInterval: c.pollingInterval,
Expand All @@ -166,7 +178,7 @@ func (c *Client) WithHttpClient(client *http.Client) *Client {
return &Client{
apiKey: c.apiKey,
apiSecret: c.apiSecret,
serverURL: c.serverURL,
serverEndpoint: c.serverEndpoint,
httpClient: client,
requestInterceptors: c.requestInterceptors,
pollingInterval: c.pollingInterval,
Expand All @@ -179,7 +191,7 @@ func (c *Client) WithRequestInterceptor(f ...RequestInterceptorFn) *Client {
return &Client{
apiKey: c.apiKey,
apiSecret: c.apiSecret,
serverURL: c.serverURL,
serverEndpoint: c.serverEndpoint,
httpClient: c.httpClient,
requestInterceptors: append(c.requestInterceptors, f...),
pollingInterval: c.pollingInterval,
Expand Down
2 changes: 1 addition & 1 deletion v3/generator/operations/request.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ func (c Client) {{ .Name }}({{ .Params }}) {{ .ValueReturn }} {
}
{{ end }}

request, err := http.NewRequestWithContext(ctx, "{{ .HTTPMethod }}", c.serverURL + path, {{ if .BodyRequest }}body{{else}}nil{{end}})
request, err := http.NewRequestWithContext(ctx, "{{ .HTTPMethod }}", c.serverEndpoint + path, {{ if .BodyRequest }}body{{else}}nil{{end}})
if err != nil {
return nil, fmt.Errorf("{{ .Name }}: new request: %w", err)
}
Expand Down
26 changes: 21 additions & 5 deletions v3/generator/schemas/schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ func RenderSchema(schemaName string, s *base.SchemaProxy) ([]byte, error) {
// This function is called if you are sure IsSimpleSchema(s *base.Schema) return true.
// Add more simple type here.
func RenderSimpleType(s *base.Schema) string {
typ, ok := s.Extensions["x-go-type"]
if ok {
t, ok := typ.(string)
if ok {
return t
}

slog.Error(
"invalid x-go-type extension type, fallback on original type",
slog.Any("type", typ),
)
}

if s.Format != "" {
if s.Format == "date-time" {
return "time.Time"
Expand Down Expand Up @@ -318,7 +331,7 @@ func renderObject(typeName string, s *base.Schema, output *bytes.Buffer) (string

tag := fmt.Sprintf(" `json:\"%s,omitempty\"", propName)

required := "*"
pointer := "*"
req := isRequiredField(propName, s)
if req {
tag = fmt.Sprintf(" `json:%q", propName)
Expand All @@ -334,9 +347,12 @@ func renderObject(typeName string, s *base.Schema, output *bytes.Buffer) (string
if properties.IsReference() {
referenceName := helpers.RenderReference(properties.GetReference())
if prop.AdditionalProperties != nil {
required = ""
pointer = ""
}
if !nullable && IsSimpleSchema(prop) {
pointer = ""
}
definition += camelName + " " + required + referenceName + tag + "\n"
definition += camelName + " " + pointer + referenceName + tag + "\n"
return nil
}

Expand Down Expand Up @@ -366,7 +382,7 @@ func renderObject(typeName string, s *base.Schema, output *bytes.Buffer) (string
definition += camelName + " " + RenderSimpleType(prop) + tag + "\n"
return nil
}
definition += camelName + " " + required + RenderSimpleType(prop) + tag + "\n"
definition += camelName + " " + pointer + RenderSimpleType(prop) + tag + "\n"

return nil
}
Expand All @@ -393,7 +409,7 @@ func renderObject(typeName string, s *base.Schema, output *bytes.Buffer) (string
if err := renderSchemaInternal(typeName+camelName, prop, output); err != nil {
return err
}
definition += camelName + " " + required + typeName + camelName + tag + "\n"
definition += camelName + " " + pointer + typeName + camelName + tag + "\n"

return nil
})
Expand Down
Loading

0 comments on commit cf4abaf

Please # to comment.