Be more specific when filtering OS instance ports

This adds an additional filter for ports attached to an instance, so
that only ports tagged with the cluster name will be considered.

Basically, this enables adding ports to the server independent from the
provisioning process.

To not break clusters provisioned with older kOps versions, when there
are no tagged ports found it will still consider all the ports of an
instance.
This commit is contained in:
ederst 2022-06-23 21:43:50 +02:00
parent a86cd06376
commit 40a0a7ebab
2 changed files with 129 additions and 0 deletions

View File

@ -116,6 +116,29 @@ func (e *Instance) FindAddresses(context *fi.Context) ([]string, error) {
return nil, nil
}
// filterInstancePorts tries to get all ports of an instance tagged with the cluster name.
// If no tagged ports are found it will return all ports of the instance, to not change the legacy behavior when there weren't tagged ports
func filterInstancePorts(allPorts []ports.Port, clusterName string) []ports.Port {
clusterNameTag := fmt.Sprintf("%s=%s", openstack.TagClusterName, clusterName)
var taggedPorts []ports.Port
for _, port := range allPorts {
for _, tag := range port.Tags {
if tag == clusterNameTag {
taggedPorts = append(taggedPorts, port)
break
}
}
}
if len(taggedPorts) == 0 {
return allPorts
}
return taggedPorts
}
func (e *Instance) Find(c *fi.Context) (*Instance, error) {
if e == nil || e.Name == nil {
return nil, nil
@ -178,6 +201,8 @@ func (e *Instance) Find(c *fi.Context) (*Instance, error) {
return nil, fmt.Errorf("failed to fetch port for instance %v: %v", server.ID, err)
}
ports = filterInstancePorts(ports, fi.StringValue(e.ServerGroup.ClusterName))
if len(ports) == 1 {
port := ports[0]
porttask, err := newPortTaskFromCloud(cloud, e.Lifecycle, &port, nil)

View File

@ -0,0 +1,104 @@
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package openstacktasks
import (
"fmt"
"reflect"
"testing"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
)
func TestFilterPortsReturnsAllPorts(t *testing.T) {
clusterName := "fakeCluster"
allPorts := []ports.Port{
{
ID: "fakeID_1",
},
{
ID: "fakeID_2",
},
}
actualPorts := filterInstancePorts(allPorts, clusterName)
if !reflect.DeepEqual(allPorts, actualPorts) {
t.Fatalf("expected '%+v', but got '%+v", allPorts, actualPorts)
}
}
func TestFilterPortsReturnsOnlyTaggedPort(t *testing.T) {
clusterName := "fakeCluster"
clusterNameTag := fmt.Sprintf("%s=%s", openstack.TagClusterName, clusterName)
allPorts := []ports.Port{
{
ID: "fakeID_1",
},
{
ID: "fakeID_2",
Tags: []string{
clusterNameTag,
},
},
}
expectedPorts := []ports.Port{
allPorts[1],
}
actualPorts := filterInstancePorts(allPorts, clusterName)
if !reflect.DeepEqual(expectedPorts, actualPorts) {
t.Fatalf("expected '%+v', but got '%+v", expectedPorts, actualPorts)
}
}
func TestFilterPortsReturnsOnlyTaggedPorts(t *testing.T) {
clusterName := "fakeCluster"
clusterNameTag := fmt.Sprintf("%s=%s", openstack.TagClusterName, clusterName)
allPorts := []ports.Port{
{
ID: "fakeID_1",
Tags: []string{
clusterNameTag,
},
},
{
ID: "fakeID_2",
},
{
ID: "fakeID_3",
Tags: []string{
clusterNameTag,
},
},
}
expectedPorts := []ports.Port{
allPorts[0],
allPorts[2],
}
actualPorts := filterInstancePorts(allPorts, clusterName)
if !reflect.DeepEqual(expectedPorts, actualPorts) {
t.Fatalf("expected '%+v', but got '%+v", expectedPorts, actualPorts)
}
}