-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a ListOpts helper #190
base: main
Are you sure you want to change the base?
Conversation
6704277
to
433c29e
Compare
I think this give us exactly what we need. My only concern is that it sacrifices compile-type parameter checking, which is a substantial part of the value of gophercloud. I wonder if we could write something with strongly-typed arguments. If we were keen enough I'm pretty sure it could also be generated from base ListOpts argument. |
It would be nice to be able to easily merge an existing ListOpts object with this |
or maybe that's a bad idea. Being able to merge a ListOpts with this would give the impression that you can have "this set of properties" OR "this property", while it will just merge the common properties instead. |
I would be inclined to add a new struct explicitly for each resource which can use it, alongside the existing ListOpts. Maybe (ports|subnets|networks).ListOptsMulti? Little bit more boilerplate, but at least we wouldn't be accidentally adding support where we shouldn't. |
433c29e
to
ef70c17
Compare
With `query.ListOpts`, it should be easier to list resources based on repeated properties. For example: get information about multiple ports by ID with a single call. ListOpts is currently implemented for three Network resources: * ports * networks * subnets
ef70c17
to
1fe62ca
Compare
Can you give me an example of what you mean? |
I have added a bit of reflection. This gives a minimal (runtime) type check that may or may not add some safety. |
and @spjmurray if you happen to pass by! |
Yup, this looks pretty good to me. |
Firstly I don't think we are adding support where we shouldn't because we need to implement the relevant interfaces for each point of use, specifically It feels a bit smelly to have this here. If we can successfully make it generic I would probably put it somewhere like However, this is really an actual part of the API. I feel like it should live in https://github.com/gophercloud/gophercloud/blob/master/openstack/networking/v2/networks/requests.go alongside |
Ah yes, this is what we need! Just for discussion purposes we could actually get this working today with something like: import (
"fmt"
"net/url"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
)
type MyListOpts struct {
ports.ListOpts
Name []string `q:"name"`
}
func BuildCompositeQueryString(opts, base interface{}) (url.Values, error) {
baseURL, err := gophercloud.BuildQueryString(base)
if err != nil {
return nil, err
}
optsURL, err := gophercloud.BuildQueryString(opts)
if err != nil {
return nil, err
}
baseQuery := baseURL.Query()
for parameter, values := range optsURL.Query() {
baseQuery.Del(parameter)
for _, value := range values {
baseQuery.Add(parameter, value)
}
}
return baseQuery, nil
}
func (opts MyListOpts) ToPortListQuery() (string, error) {
values, err := BuildCompositeQueryString(opts, opts.ListOpts)
return values.Encode(), err
}
func main() {
opts := MyListOpts{
ListOpts: ports.ListOpts{
Status: "detached",
Name: "ignored, hopefully",
},
Name: []string{
"port1",
"port2",
},
}
query, err := opts.ToPortListQuery()
if err != nil {
fmt.Println("fail", err)
}
fmt.Println(query)
} Kinda ugly though! The obvious other way would be to have: type MultiOpts struct {
Name []string `q:"name"`
}
type ListOpts struct {
Name string `q:"name"`
MultiOpts MultiOpts
} |
Here I propose a builder for List queries that allows "OR" clauses.
With
query.New
, it should be easier to list resources based on repeated properties. For example: get information about multiple ports by ID with a single call.The properties that can be passed with the method
.And(property string, values ...interface{})
are guarded by the fields taggedq:
in the base filter. For example: when callingAnd()
onquery.New(nertworks.ListOpts{})
, theAnd
property name must be one of those defined in thenetwork.ListOpts
filter.For example:
ListOpts is currently implemented for three Network resources: