-
Notifications
You must be signed in to change notification settings - Fork 140
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
Prefixes filter improvements #428
base: master
Are you sure you want to change the base?
Conversation
…for IPAM Prefixes List
Phew, this sure is some black magic! Let me think about this a little bit. Usually the code here is very KISS. Explicitly tested, easily extendible. This approach is not. I'm not sure if this kind of logic has a place in a terraform provider. On the other hand, the amount of possible parameters in these APIs is really quite ridiculous and doing it like this spares us lots of work. Things to consider:
Now, while writing this, I kinda warmed up on the approach. I think it needs some more refining and user experience / documentation is definitely something that has to be considered. I would also be very interested in your thoughts about these questions! The bad news is that I'm quite busy lately and I really hate Netbox 3.5 not being supported atm (also this, so I wanted to do that next. Edit: Now I wrote all of this without thanking you for your work and nice MR, so: Thanks for this MR :D |
Thanks for the response. With some distance from this and playing with some other stuff in NetBox, I had the realization that maybe this isnt the right way to handle complex queries. Netbox has a GraphQL API (https://demo.netbox.dev/static/docs/graphql-api/overview/) and there is a GraphQL terraform provider (https://registry.terraform.io/providers/sullivtr/graphql/latest/docs) - which would allow these kind of complex queries with existing providers. The netbox provider could then be used for more simple queries and for actual resource CRUD. I havent had a chance to write up the terraform to confirm this works for my use case, and the GraphQL API doesnt help with Custom Fields (netbox-community/netbox#7598), but that was going to be harder to get working in the netbox provider anyway and can generally be handled via tags instead. I pretty much agree with all of your points, and I do agree this is less of a priority than supporting the latest Netbox Version (as there is a workaround and its probably not a super common use case) |
I think that a terraform provider for netbox should actually be able to handle the filtering. As a user, I would absolutely hate having to use two providers to work with netbox. Another thing I wanted to note: What makes this implementation alluring to me is that it's "just" about filtering in data-sources. In no way would I consider this kind of stuff in a regular resource. I'll mark this as a draft to revisit it later. I would be open to merge this - since it does not seem to break existing functionality - if the change is something you need urgently. |
After having written a new Plural Data Source for "netbox_tags", I actually really like this as a standardised way to add filtering. It would allow for you to: A) Break this out into another utility function that is generic across ALL Plural Data Sources, allowing users to have standard filtering across every Plural Data Source, rather than just "some" filters on "some" Plural Data Sources. B) Provide support for "all" filters, even if they add new filters in the future. If they decided you should be able to filter IP Addresses by ASN or something, there's no need to do a code change. You simply add a test in for this filter, and away you go. For documentation purposes, you can point users to the REST API Documentation, so they can test their "Data Source request" before they even use it. Notably, this also fixes a minor gripe of mine that none of the filtering currently in place actually gives a list of the filtering possibilities. https://registry.terraform.io/providers/e-breuninger/netbox/latest/docs/data-sources/asns tells me nothing about the filters I can use, only that filters have a Name and a Value. That's not useful to the end user, especially if they just want a quick reference. Most of the time, if I want to learn what filtering there is, I do actually go back to the source code so I can see what was implemented in the switch filter. For your 7 questions:
As a matter of fact, I did a simple test. Copied the function from this change, put it in the util file as a new function, set up "VLANs" Data Source to use it with no other changes, and all tests worked as expected. data_source_netbox_vlans.go if filter, ok := d.GetOk("filter"); ok {
filterParams := filter.(*schema.Set)
for _, f := range filterParams.List() {
k := f.(map[string]interface{})["name"]
v := f.(map[string]interface{})["value"]
key := k.(string)
switch key {
case "Hello":
key = "vid_lte"
}
processDataSourceFilterField(params, key, v.(string))
}
} util.go func processDataSourceFilterField(params interface{}, k string, vString string) error {
paramName := strcase.ToCamel(strings.Replace(k, "__n", "n", -1))
paramName = strings.Replace(paramName, "Id", "ID", -1)
params_reflect := reflect.ValueOf(params).Elem()
field := params_reflect.FieldByName(paramName)
if !(field.IsValid()) {
return fmt.Errorf("'%s' is not a supported filter parameter. Netbox go SDK does not have the associated parameter [(%s)]", k, paramName)
}
if field.Kind() == reflect.Slice {
// Param is an array/slice
field.Set(reflect.Append(field, reflect.ValueOf(vString)))
} else if (reflect.PtrTo(field.Type().Elem()).Elem().Kind()) == reflect.Float64 {
// ^ This CANT be the best way to do this, but it works
vFloat, err := strconv.ParseFloat(vString, 64)
if field.Set(reflect.ValueOf(&vFloat)); err != nil {
return fmt.Errorf("failed to set parameter [(%s)] with error [(%s)]", paramName, err)
}
} else {
// Param is a scalar
field.Set(reflect.ValueOf(&vString))
}
return nil
} The chunk of code in if filter, ok := d.GetOk("filter"); ok {
processDataSourceFilterField(params, filter)
} And the function takes care of the rest of it. NOTE: This breaks the custom filtering labels option. |
As mentioned earlier, I like the general approach of this as well. to 6:
Actually, I would gladly get rid of my (openapi2-based, manually back-ported) go-netbox fork once a viable openapi3-based community-managed this-terraform-provider-compatible go-netbox arrives. |
Enables all standard fields in the prefixes API within the data. netbox_prefixes datasource. this also includes allowing multiple tags to be specified.
Notably, custom fields are still not supported, which will be more complex to implement.