From 58cac5aa1a14988a8f42e9962e8859ecc5ab0878 Mon Sep 17 00:00:00 2001 From: Emilio Garcia Date: Mon, 1 Mar 2021 15:03:27 -0500 Subject: [PATCH 1/2] Users can add tags to ports created by CAPO based on the network or subnet they are attached to --- .../openstackproviderconfig/v1alpha1/types.go | 5 +++++ pkg/cloud/openstack/clients/machineservice.go | 17 +++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/pkg/apis/openstackproviderconfig/v1alpha1/types.go b/pkg/apis/openstackproviderconfig/v1alpha1/types.go index 6091075e6d..aab270bbe0 100644 --- a/pkg/apis/openstackproviderconfig/v1alpha1/types.go +++ b/pkg/apis/openstackproviderconfig/v1alpha1/types.go @@ -132,6 +132,8 @@ type NetworkParam struct { Subnets []SubnetParam `json:"subnets,omitempty"` // NoAllowedAddressPairs disables creation of allowed address pairs for the network ports NoAllowedAddressPairs bool `json:"noAllowedAddressPairs,omitempty"` + // PortTags allows users to specify a list of tags to add to ports created in a given network + PortTags []string `json:"portTags,omitempty"` } type Filter struct { @@ -159,6 +161,9 @@ type SubnetParam struct { // Filters for optional network query Filter SubnetFilter `json:"filter,omitempty"` + + // PortTags are tags that are added to ports created on this subnet + PortTags []string `json:"portTags,omitempty"` } type SubnetFilter struct { diff --git a/pkg/cloud/openstack/clients/machineservice.go b/pkg/cloud/openstack/clients/machineservice.go index 07316242f0..9366076f6d 100644 --- a/pkg/cloud/openstack/clients/machineservice.go +++ b/pkg/cloud/openstack/clients/machineservice.go @@ -96,6 +96,7 @@ type Instance struct { type ServerNetwork struct { networkID string subnetID string + portTags []string } type InstanceListOpts struct { // Name of the image in URL format. @@ -421,21 +422,25 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust if net.Subnets == nil { nets = append(nets, ServerNetwork{ networkID: netID, + portTags: net.PortTags, }) } - for _, snet := range net.Subnets { - sopts := subnets.ListOpts(snet.Filter) - sopts.ID = snet.UUID + for _, snetParam := range net.Subnets { + sopts := subnets.ListOpts(snetParam.Filter) + sopts.ID = snetParam.UUID sopts.NetworkID = netID - snets, err := getSubnetsByFilter(is, &sopts) + + // Query for all subnets that match filters + snetResults, err := getSubnetsByFilter(is, &sopts) if err != nil { return nil, err } - for _, snet := range snets { + for _, snet := range snetResults { nets = append(nets, ServerNetwork{ networkID: snet.NetworkID, subnetID: snet.ID, + portTags: append(net.PortTags, snetParam.PortTags...), }) } } @@ -499,7 +504,7 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust } _, err = attributestags.ReplaceAll(is.networkClient, "ports", port.ID, attributestags.ReplaceAllOpts{ - Tags: machineTags}).Extract() + Tags: append(machineTags, port.Tags...)}).Extract() if err != nil { return nil, fmt.Errorf("Tagging port for server err: %v", err) } From 6f630692309d14c6819bb663e7f64f47d584a470 Mon Sep 17 00:00:00 2001 From: Emilio Garcia Date: Mon, 1 Mar 2021 16:54:40 -0500 Subject: [PATCH 2/2] prevent duplicate port tags --- pkg/cloud/openstack/clients/machineservice.go | 21 +++++++++++- .../openstack/clients/machineservice_test.go | 34 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/pkg/cloud/openstack/clients/machineservice.go b/pkg/cloud/openstack/clients/machineservice.go index 9366076f6d..dca7cabdf6 100644 --- a/pkg/cloud/openstack/clients/machineservice.go +++ b/pkg/cloud/openstack/clients/machineservice.go @@ -503,8 +503,9 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust port = portList[0] } + portTags := deduplicateList(append(machineTags, port.Tags...)) _, err = attributestags.ReplaceAll(is.networkClient, "ports", port.ID, attributestags.ReplaceAllOpts{ - Tags: append(machineTags, port.Tags...)}).Extract() + Tags: portTags}).Extract() if err != nil { return nil, fmt.Errorf("Tagging port for server err: %v", err) } @@ -737,6 +738,24 @@ func createServerGroup(computeClient *gophercloud.ServiceClient, name string) (* }).Extract() } +// deduplicateList removes all duplicate entries from a slice of strings in place +func deduplicateList(list []string) []string { + m := map[string]bool{} + for _, element := range list { + if _, ok := m[element]; !ok { + m[element] = true + } + } + + dedupedList := make([]string, len(m)) + i := 0 + for k := range m { + dedupedList[i] = k + i++ + } + return dedupedList +} + func getServerGroupsByName(computeClient *gophercloud.ServiceClient, name string) ([]servergroups.ServerGroup, error) { pages, err := servergroups.List(computeClient).AllPages() if err != nil { diff --git a/pkg/cloud/openstack/clients/machineservice_test.go b/pkg/cloud/openstack/clients/machineservice_test.go index 757eadb83f..31d15f341c 100644 --- a/pkg/cloud/openstack/clients/machineservice_test.go +++ b/pkg/cloud/openstack/clients/machineservice_test.go @@ -27,3 +27,37 @@ func TestMachineServiceInstance(t *testing.T) { t.Errorf("Couldn't create instance service: %v", err) } } + +func TestDeduplicateLists(t *testing.T) { + list1 := []string{"1", "2", "3", "a", "b", "c"} + list2 := []string{"1", "c"} + + // Case 1: Lists with no duplicates has same elements + result := deduplicateList(list1) + if !equal(result, list1) { + t.Errorf("List with no duplicates should contain the same elements. \n\tExpected:%v\n\tGot:%v", list1, result) + } + + // Case 2: Lists with duplicates have coppies of elements removed + dupe1 := append(list1, list2...) + result = deduplicateList(dupe1) + if !equal(list1, result) { + t.Errorf("List with duplicates should have coppies of elements removed.\n\tExpected:%v\n\tGot:%v", list1, result) + } +} + +func equal(a, b []string) bool { + if len(a) != len(b) { + return false + } + m := map[string]bool{} + for _, v := range a { + m[v] = true + } + for _, v := range b { + if _, ok := m[v]; !ok { + return false + } + } + return true +}