Skip to content
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

Regression: Specifying subnet filter without network fails when it previously did not #993

Closed
mdbooth opened this issue Sep 13, 2021 · 2 comments · Fixed by #994
Closed
Labels
kind/bug Categorizes issue or PR as related to a bug.

Comments

@mdbooth
Copy link
Contributor

mdbooth commented Sep 13, 2021

/kind bug

What steps did you take and what happened:
In OpenShift we add default networks to machines by subnet tag, e.g.:

      networks:
      - filter: {}
        subnets:
        - filter:
            name: cluster-dsal-59p8x-nodes
            tags: openshiftClusterID=cluster-dsal-59p8x

This now returns an error. It previously succeeded.

What did you expect to happen:

We should find the requested subnet in any network, which was the previous behaviour.

Anything else you would like to add:

This was regressed by #935 in an interesting way. It turns out that the previous behaviour in this case was to list networks with an empty filter, which returns all networks, then execute a separate subnet query per-network and add all matches subnets. This worked, but was obviously also incredibly inefficient.

#935 was principally about adding a mock interface, but incidentally also modified GetSubnetsByFilter and GetNetworksByFilter to return an error if there were no results. This breaks us, because we're querying every network individually, but only one of them contains the subnet we're looking for. The first network we query which doesn't contain the target subnet will return an error.

I'm not 100% convinced this is a desirable change, but it did highlight a very inefficient use of the OpenStack REST API. We can address this just by making a more efficient API call.

Environment:

  • Cluster API Provider OpenStack version (Or git rev-parse HEAD if manually built): ac9c503
@macaptain
Copy link
Contributor

Here's the old GetNetworksByFilter on the parent of #935's merge commit on master:

// GetSubnetsByFilter gets the id of a subnet by querying openstack with filters.
func (s *Service) GetSubnetsByFilter(opts subnets.ListOptsBuilder) ([]subnets.Subnet, error) {
if opts == nil {
return []subnets.Subnet{}, fmt.Errorf("no Filters were passed")
}
mc := metrics.NewMetricPrometheusContext("subnet", "list")
pager := subnets.List(s.client, opts)
var snets []subnets.Subnet
err := pager.EachPage(func(page pagination.Page) (bool, error) {
subnetList, err := subnets.ExtractSubnets(page)
if mc.ObserveRequest(err) != nil {
return false, err
} else if len(subnetList) == 0 {
return false, fmt.Errorf("no subnets could be found with the filters provided")
}
snets = append(snets, subnetList...)
return true, nil
})
if err != nil {
return []subnets.Subnet{}, err
}
return snets, nil
}

On line 354, if subnetList extracted from the current page has length zero, we return false, fmt.Errorf(...), which stops iteration of pager.EachPage. Then on line 361 the function returns that error. So I think we also used to return an error here when listing subnets with no results before #935, but I'm squinting at the code here, haven't tested it and could be mistaken.

In any case, I don't think it matters how, when or why this stopped working. Sounds like we should support this use case to find a subnet without specifying its network, and even better when there's both API usage efficiency gains and the unit tests to guard against this getting missed in future.

@mdbooth
Copy link
Contributor Author

mdbooth commented Sep 14, 2021

Ouch! That code's a headscratcher.

You may well be right. It definitely did regress, but I may have git blamed the wrong person 🙄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Categorizes issue or PR as related to a bug.
Projects
None yet
3 participants