equinix-labs / metal-go

[Deprecated] Golang client for Equinix Metal
https://deploy.equinix.com/labs/equinix-sdk-go/
MIT License
3 stars 2 forks source link

feat: add functions to automatically navigate device pages #135

Closed ctreatma closed 1 year ago

ctreatma commented 1 year ago

This serves as an example of how we could implement automatic page navigation, similar to what was done in packngo.

Relates to #131

t0mk commented 1 year ago

@displague @ctreatma I have tried to implement pagination with the mustache templates of openapi generator today. there are several issues:

This was my template that would generate files like api_device_paginated_lister.go.

templates/api_paginated_lister.mustache:

{{>partial_header}}
package {{packageName}}

{{#operations}}
import (
    "bytes"
    "context"
    "io"
    "net/http"
    "net/url"
{{#imports}}    "{{import}}"
{{/imports}}
)

{{#operation}}

{{isPaginated}}

// The code is just a placeholder, I wanted to know if it's emitted only on paginated methods

func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) {

    var items []{{returnType}}

    pageNumber := int32(1)

    // classname {{classname}}, {{&classname}}

    for {
        page, _, err := r.Page(pageNumber).Execute()
        if err != nil {
            return nil, err
        }

        items = append(items, page.Devices...)
        if page.Meta.GetLastPage() <= page.Meta.GetCurrentPage() {
            break
        }
    }

    return items, nil
}
{{/isPaginated}}

{{/operation}}
{{/operations}}

To consider the templates, we must have config.yaml as

templateDir: /local/templates
files:
  api_paginated_lister.mustache:
    templateType: API
    destinationFilename: _paginated_lister.go

.. and -c config.yaml to the openapi-cli call.

t0mk commented 1 year ago

I also tried to come up with an yq expression that would add a boolean flag isPaginated to ["paths"]["/projects{id}/devices"]["get"]. I came up with

yq 'with(.paths[].get | select(.parameters[].name == "page"); .isPaginated=true)' < $1 > $2

.. but it's not completely correct.

displague commented 1 year ago

@t0mk The Path syntax is well defined, you can't add arbitrary fields unless they follow the x- format.

displague commented 1 year ago

@t0mk page.Devices would also need to be template-ified in your example. I don't presume determining the proper plural is trivial.

t0mk commented 1 year ago

@displague Thanks for the tip on the x- properties, it couldn't a fix for my problem. https://swagger.io/specification/#paths-object

As for the the plural, I think it can be worked out from the template variables. It might not be gramtatically correct, but I don't think it will conflict.

ctreatma commented 1 year ago

Closing in favor of #150, which will generate the changes in this PR for all paginated endpoints using a combination of vendor extensions and custom templates.