diff --git a/internal/ibmcloud-janitor/resources/types.go b/internal/ibmcloud-janitor/resources/types.go index 8fe8e82f..e77e963f 100644 --- a/internal/ibmcloud-janitor/resources/types.go +++ b/internal/ibmcloud-janitor/resources/types.go @@ -45,6 +45,7 @@ var PowervsResources = []Resource{ var VpcResources = []Resource{ VPCInstance{}, + VPCLoadBalancer{}, VPCNetwork{}, VPCs{}, } @@ -74,6 +75,8 @@ type VPC interface { GetSubnetPublicGateway(options *vpcv1.GetSubnetPublicGatewayOptions) (*vpcv1.PublicGateway, *core.DetailedResponse, error) DeletePublicGateway(options *vpcv1.DeletePublicGatewayOptions) (*core.DetailedResponse, error) UnsetSubnetPublicGateway(options *vpcv1.UnsetSubnetPublicGatewayOptions) (*core.DetailedResponse, error) + DeleteLoadBalancer(options *vpcv1.DeleteLoadBalancerOptions) (*core.DetailedResponse, error) + ListLoadBalancers(options *vpcv1.ListLoadBalancersOptions) (*vpcv1.LoadBalancerCollection, *core.DetailedResponse, error) } type ServiceIDClient interface { diff --git a/internal/ibmcloud-janitor/resources/util.go b/internal/ibmcloud-janitor/resources/util.go new file mode 100644 index 00000000..da58f4e0 --- /dev/null +++ b/internal/ibmcloud-janitor/resources/util.go @@ -0,0 +1,67 @@ +/* +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 resources + +import ( + "net/url" + + "github.com/pkg/errors" +) + +// pagingHelper is used while listing resources. It parses and fetches the start token for +// getting the next set of resources if nextURL is returned by func f. +// func f has start as a parameter and returns the following: +// isDone bool - true denotes that iterating is not needed as there is no next set of resources +// nextURL string - denotes a URL for a page of resources which is parsed for fetching start token for next iteration +// e error - will break and return error if e is not nil +func pagingHelper(f func(string) (bool, string, error)) (err error) { + start := "" + + getStartToken := func(nextURL string) (string, error) { + url, err := url.Parse(nextURL) + if err != nil || url == nil { + return "", errors.Wrapf(err, "failed to parse next url for getting next resources") + } + + start := url.Query().Get("start") + return start, nil + } + + for { + isDone, nextURL, e := f(start) + + if e != nil { + err = e + break + } + + if isDone { + break + } + + if nextURL != "" { + start, err = getStartToken(nextURL) + if err != nil { + break + } + } else { + break + } + } + + return +} diff --git a/internal/ibmcloud-janitor/resources/vpc_client.go b/internal/ibmcloud-janitor/resources/vpc_client.go index 30e446dd..012c529b 100644 --- a/internal/ibmcloud-janitor/resources/vpc_client.go +++ b/internal/ibmcloud-janitor/resources/vpc_client.go @@ -78,6 +78,14 @@ func (c *IBMVPCClient) UnsetSubnetPublicGateway(options *vpcv1.UnsetSubnetPublic return c.vpcService.UnsetSubnetPublicGateway(options) } +func (c *IBMVPCClient) DeleteLoadBalancer(options *vpcv1.DeleteLoadBalancerOptions) (*core.DetailedResponse, error) { + return c.vpcService.DeleteLoadBalancer(options) +} + +func (c *IBMVPCClient) ListLoadBalancers(options *vpcv1.ListLoadBalancersOptions) (*vpcv1.LoadBalancerCollection, *core.DetailedResponse, error) { + return c.vpcService.ListLoadBalancers(options) +} + // Creates a new VPC Client func NewVPCClient(options *CleanupOptions) (*IBMVPCClient, error) { client := &IBMVPCClient{} diff --git a/internal/ibmcloud-janitor/resources/vpc_lbs.go b/internal/ibmcloud-janitor/resources/vpc_lbs.go new file mode 100644 index 00000000..6a905824 --- /dev/null +++ b/internal/ibmcloud-janitor/resources/vpc_lbs.go @@ -0,0 +1,71 @@ +/* +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 resources + +import ( + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +type VPCLoadBalancer struct{} + +// Cleans up the load balancers in a given region +func (VPCLoadBalancer) cleanup(options *CleanupOptions) error { + resourceLogger := logrus.WithFields(logrus.Fields{"resource": options.Resource.Name}) + resourceLogger.Info("Cleaning up the load balancers") + client, err := NewVPCClient(options) + if err != nil { + return errors.Wrap(err, "couldn't create VPC client") + } + + f := func(start string) (bool, string, error) { + listLbOpts := &vpcv1.ListLoadBalancersOptions{} + if start != "" { + listLbOpts.Start = &start + } + + loadBalancers, _, err := client.ListLoadBalancers(listLbOpts) + if err != nil { + return false, "", errors.Wrap(err, "failed to list the load balancers") + } + + if loadBalancers == nil || len(loadBalancers.LoadBalancers) <= 0 { + resourceLogger.Info("there are no available load balancers to delete") + return true, "", nil + } + + for _, lb := range loadBalancers.LoadBalancers { + if lb.ResourceGroup.ID == &client.ResourceGroupID { + _, err := client.DeleteLoadBalancer(&vpcv1.DeleteLoadBalancerOptions{ + ID: lb.ID, + }) + if err != nil { + return false, "", errors.Wrapf(err, "failed to delete the load balancer %q", *lb.Name) + } + } + } + + if loadBalancers.Next != nil && *loadBalancers.Next.Href != "" { + return false, *loadBalancers.Next.Href, nil + } + resourceLogger.Info("Successfully deleted the load balancers") + return true, "", nil + } + + return pagingHelper(f) +}