diff --git a/go.mod b/go.mod index 5d10e976f..bb869e74b 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( k8s.io/client-go v0.28.4 k8s.io/cluster-bootstrap v0.28.4 k8s.io/klog/v2 v2.100.1 - sigs.k8s.io/cluster-api-provider-openstack v0.9.1 + sigs.k8s.io/cluster-api-provider-openstack v0.9.2 sigs.k8s.io/controller-runtime v0.16.3 sigs.k8s.io/yaml v1.4.0 ) diff --git a/go.sum b/go.sum index c76dcf954..4cfe7656f 100644 --- a/go.sum +++ b/go.sum @@ -543,8 +543,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/cluster-api v1.6.0 h1:2bhVSnUbtWI8taCjd9lGiHExsRUpKf7Z1fXqi/IwYx4= sigs.k8s.io/cluster-api v1.6.0/go.mod h1:LB7u/WxiWj4/bbpHNOa1oQ8nq0MQ5iYlD0pGfRSBGLI= -sigs.k8s.io/cluster-api-provider-openstack v0.9.1 h1:rbRJa8G7x/f9/aGrvxxIsxfDPrSJWUgaR/5BY1Ik4iE= -sigs.k8s.io/cluster-api-provider-openstack v0.9.1/go.mod h1:ecR9lx4XbOr3Gg2CGNgM3wguuV6l31Nd5rUccE+xjKs= +sigs.k8s.io/cluster-api-provider-openstack v0.9.2 h1:TGFtclX81HFiCkRJQe0wnWsnT/FBB69gSPFwcxQ+qlM= +sigs.k8s.io/cluster-api-provider-openstack v0.9.2/go.mod h1:ecR9lx4XbOr3Gg2CGNgM3wguuV6l31Nd5rUccE+xjKs= sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/vendor/modules.txt b/vendor/modules.txt index 4069b9a6f..758abf08f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -827,7 +827,7 @@ k8s.io/utils/trace sigs.k8s.io/cluster-api/api/v1beta1 sigs.k8s.io/cluster-api/errors sigs.k8s.io/cluster-api/util/topology -# sigs.k8s.io/cluster-api-provider-openstack v0.9.1 +# sigs.k8s.io/cluster-api-provider-openstack v0.9.2 ## explicit; go 1.20 sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7 sigs.k8s.io/cluster-api-provider-openstack/pkg/clients diff --git a/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock/network.go b/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock/network.go index 091a89f3b..045a93d3b 100644 --- a/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock/network.go +++ b/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock/network.go @@ -546,6 +546,21 @@ func (mr *MockNetworkClientMockRecorder) ListTrunk(arg0 interface{}) *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListTrunk", reflect.TypeOf((*MockNetworkClient)(nil).ListTrunk), arg0) } +// ListTrunkSubports mocks base method. +func (m *MockNetworkClient) ListTrunkSubports(arg0 string) ([]trunks.Subport, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListTrunkSubports", arg0) + ret0, _ := ret[0].([]trunks.Subport) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListTrunkSubports indicates an expected call of ListTrunkSubports. +func (mr *MockNetworkClientMockRecorder) ListTrunkSubports(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListTrunkSubports", reflect.TypeOf((*MockNetworkClient)(nil).ListTrunkSubports), arg0) +} + // RemoveRouterInterface mocks base method. func (m *MockNetworkClient) RemoveRouterInterface(arg0 string, arg1 routers.RemoveInterfaceOptsBuilder) (*routers.InterfaceInfo, error) { m.ctrl.T.Helper() @@ -561,6 +576,20 @@ func (mr *MockNetworkClientMockRecorder) RemoveRouterInterface(arg0, arg1 interf return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveRouterInterface", reflect.TypeOf((*MockNetworkClient)(nil).RemoveRouterInterface), arg0, arg1) } +// RemoveSubports mocks base method. +func (m *MockNetworkClient) RemoveSubports(arg0 string, arg1 trunks.RemoveSubportsOpts) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveSubports", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveSubports indicates an expected call of RemoveSubports. +func (mr *MockNetworkClientMockRecorder) RemoveSubports(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveSubports", reflect.TypeOf((*MockNetworkClient)(nil).RemoveSubports), arg0, arg1) +} + // ReplaceAllAttributesTags mocks base method. func (m *MockNetworkClient) ReplaceAllAttributesTags(arg0, arg1 string, arg2 attributestags.ReplaceAllOptsBuilder) ([]string, error) { m.ctrl.T.Helper() diff --git a/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/networking.go b/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/networking.go index 23ad3c8fd..8967c7b34 100644 --- a/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/networking.go +++ b/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/networking.go @@ -53,6 +53,9 @@ type NetworkClient interface { CreateTrunk(opts trunks.CreateOptsBuilder) (*trunks.Trunk, error) DeleteTrunk(id string) error + ListTrunkSubports(trunkID string) ([]trunks.Subport, error) + RemoveSubports(id string, opts trunks.RemoveSubportsOpts) error + ListRouter(opts routers.ListOpts) ([]routers.Router, error) CreateRouter(opts routers.CreateOptsBuilder) (*routers.Router, error) DeleteRouter(id string) error @@ -238,6 +241,24 @@ func (c networkClient) DeleteTrunk(id string) error { return mc.ObserveRequestIgnoreNotFound(trunks.Delete(c.serviceClient, id).ExtractErr()) } +func (c networkClient) ListTrunkSubports(trunkID string) ([]trunks.Subport, error) { + mc := metrics.NewMetricPrometheusContext("trunk", "listsubports") + subports, err := trunks.GetSubports(c.serviceClient, trunkID).Extract() + if mc.ObserveRequest(err) != nil { + return nil, err + } + return subports, nil +} + +func (c networkClient) RemoveSubports(id string, opts trunks.RemoveSubportsOpts) error { + mc := metrics.NewMetricPrometheusContext("trunk", "deletesubports") + _, err := trunks.RemoveSubports(c.serviceClient, id, opts).Extract() + if mc.ObserveRequest(err) != nil { + return err + } + return nil +} + func (c networkClient) ListTrunk(opts trunks.ListOptsBuilder) ([]trunks.Trunk, error) { mc := metrics.NewMetricPrometheusContext("trunk", "list") allPages, err := trunks.List(c.serviceClient, opts).AllPages() diff --git a/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking/trunk.go b/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking/trunk.go index 6743478ff..374bcb6eb 100644 --- a/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking/trunk.go +++ b/vendor/sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking/trunk.go @@ -31,8 +31,9 @@ import ( ) const ( - timeoutTrunkDelete = 3 * time.Minute - retryIntervalTrunkDelete = 5 * time.Second + timeoutTrunkDelete = 3 * time.Minute + retryIntervalTrunkDelete = 5 * time.Second + retryIntervalSubportDelete = 30 * time.Second ) func (s *Service) GetTrunkSupport() (bool, error) { @@ -77,6 +78,42 @@ func (s *Service) getOrCreateTrunk(eventObject runtime.Object, clusterName, trun return trunk, nil } +func (s *Service) RemoveTrunkSubports(trunkID string) error { + subports, err := s.client.ListTrunkSubports(trunkID) + if err != nil { + return err + } + + if len(subports) == 0 { + return nil + } + + portList := make([]trunks.RemoveSubport, len(subports)) + for i, subport := range subports { + portList[i] = trunks.RemoveSubport{ + PortID: subport.PortID, + } + } + + removeSubportsOpts := trunks.RemoveSubportsOpts{ + Subports: portList, + } + + err = s.client.RemoveSubports(trunkID, removeSubportsOpts) + if err != nil { + return err + } + + for _, subPort := range subports { + err := s.client.DeletePort(subPort.PortID) + if err != nil { + return err + } + } + + return nil +} + func (s *Service) DeleteTrunk(eventObject runtime.Object, portID string) error { listOpts := trunks.ListOpts{ PortID: portID, @@ -88,6 +125,22 @@ func (s *Service) DeleteTrunk(eventObject runtime.Object, portID string) error { if len(trunkInfo) != 1 { return nil } + // Delete sub-ports if trunk is associated with sub-ports + err = wait.PollUntilContextTimeout(context.TODO(), retryIntervalSubportDelete, timeoutTrunkDelete, true, func(_ context.Context) (bool, error) { + if err := s.RemoveTrunkSubports(trunkInfo[0].ID); err != nil { + if capoerrors.IsNotFound(err) || capoerrors.IsConflict(err) || capoerrors.IsRetryable(err) { + return false, nil + } + return false, err + } + return true, nil + }) + if err != nil { + record.Warnf(eventObject, "FailedRemoveTrunkSubports", "Failed to delete sub ports trunk %s with id %s: %v", trunkInfo[0].Name, trunkInfo[0].ID, err) + return err + } + + record.Eventf(eventObject, "SuccessfulRemoveTrunkSubports", "Removed trunk sub ports %s with id %s", trunkInfo[0].Name, trunkInfo[0].ID) err = wait.PollUntilContextTimeout(context.TODO(), retryIntervalTrunkDelete, timeoutTrunkDelete, true, func(_ context.Context) (bool, error) { if err := s.client.DeleteTrunk(trunkInfo[0].ID); err != nil {