Repository: linode/linode-cloud-controller-manager
Pull request #195 (2024-03-21 19:35:11)

revert PR 184, PR 190 and PR 182
### General:

* [x] Have you removed all sensitive information, including but not limited to access keys and passwords?
* [x] Have you checked to ensure there aren't other open or closed [Pull Requests](../../pulls) for the same bug/feature/question?

### Pull Request Guidelines:

1. [ ] Does your submission pass tests?
1. [ ] Have you added tests? 
1. [ ] Are you addressing a single feature in this PR? 
1. [ ] Are your commits atomic, addressing one change per commit?
1. [ ] Are you following the conventions of the language? 
1. [ ] Have you saved your large formatting changes for a different PR, so we can focus on your work?
1. [ ] Have you explained your rationale for why this feature is needed? 
1. [ ] Have you linked your PR to an [open issue](https://blog.github.com/2013-05-14-closing-issues-via-pull-requests/)




Patch:
diff --git a/README.md b/README.md
index 1c91de3..b3e24a3 100644
--- a/README.md
+++ b/README.md
@@ -126,17 +126,6 @@ Users can create CloudFirewall instances, supply their own rules and attach them
 **Note**<br/>
 If the user supplies a firewall-id, and later switches to using an ACL, the CCM will take over the CloudFirewall Instance. To avoid this, delete the service, and re-create it so the original CloudFirewall is left undisturbed.
 
-#### Routes
-When running k8s clusters within VPC, node specific podCIDRs need to be allowed on the VPC interface. Linode CCM comes with route-controller functionality which can be enabled for automatically adding/deleting routes on VPC interfaces. When installing CCM with helm, make sure to specify routeController settings.
-
-##### Example usage in values.yaml
-```yaml
-routeController:
-  vpcName: <name of VPC>
-  clusterCIDR: 10.0.0.0/8
-  configureCloudRoutes: true
-```
-
 ### Nodes
 Kubernetes Nodes can be configured with the following annotations.
 
diff --git a/cloud/linode/client/client.go b/cloud/linode/client/client.go
index e9d4b15..3b9bb74 100644
--- a/cloud/linode/client/client.go
+++ b/cloud/linode/client/client.go
@@ -16,11 +16,6 @@ type Client interface {
 	ListInstances(context.Context, *linodego.ListOptions) ([]linodego.Instance, error)
 	GetInstanceIPAddresses(context.Context, int) (*linodego.InstanceIPAddressResponse, error)
 
-	ListInstanceConfigs(context.Context, int, *linodego.ListOptions) ([]linodego.InstanceConfig, error)
-	UpdateInstanceConfigInterface(context.Context, int, int, int, linodego.InstanceConfigInterfaceUpdateOptions) (*linodego.InstanceConfigInterface, error)
-
-	ListVPCs(context.Context, *linodego.ListOptions) ([]linodego.VPC, error)
-
 	CreateNodeBalancer(context.Context, linodego.NodeBalancerCreateOptions) (*linodego.NodeBalancer, error)
 	GetNodeBalancer(context.Context, int) (*linodego.NodeBalancer, error)
 	UpdateNodeBalancer(context.Context, int, linodego.NodeBalancerUpdateOptions) (*linodego.NodeBalancer, error)
diff --git a/cloud/linode/cloud.go b/cloud/linode/cloud.go
index 5e9b043..123c203 100644
--- a/cloud/linode/cloud.go
+++ b/cloud/linode/cloud.go
@@ -25,17 +25,14 @@ const (
 // We expect it to be initialized with flags external to this package, likely in
 // main.go
 var Options struct {
-	KubeconfigFlag        *pflag.Flag
-	LinodeGoDebug         bool
-	EnableRouteController bool
-	VPCName               string
+	KubeconfigFlag *pflag.Flag
+	LinodeGoDebug  bool
 }
 
 type linodeCloud struct {
 	client        client.Client
 	instances     cloudprovider.InstancesV2
 	loadbalancers cloudprovider.LoadBalancer
-	routes        cloudprovider.Routes
 }
 
 func init() {
@@ -70,19 +67,12 @@ func newCloud() (cloudprovider.Interface, error) {
 		linodeClient.SetDebug(true)
 	}
 
-	routes, err := newRoutes(linodeClient)
-	if err != nil {
-		return nil, fmt.Errorf("routes client was not created successfully: %w", err)
-	}
-
-	// create struct that satisfies cloudprovider.Interface
-	lcloud := &linodeCloud{
+	// Return struct that satisfies cloudprovider.Interface
+	return &linodeCloud{
 		client:        linodeClient,
 		instances:     newInstances(linodeClient),
 		loadbalancers: newLoadbalancers(linodeClient, region),
-		routes:        routes,
-	}
-	return lcloud, nil
+	}, nil
 }
 
 func (c *linodeCloud) Initialize(clientBuilder cloudprovider.ControllerClientBuilder, stopCh <-chan struct{}) {
@@ -119,9 +109,6 @@ func (c *linodeCloud) Clusters() (cloudprovider.Clusters, bool) {
 }
 
 func (c *linodeCloud) Routes() (cloudprovider.Routes, bool) {
-	if Options.EnableRouteController {
-		return c.routes, true
-	}
 	return nil, false
 }
 
diff --git a/cloud/linode/instances.go b/cloud/linode/instances.go
index ee02742..5536243 100644
--- a/cloud/linode/instances.go
+++ b/cloud/linode/instances.go
@@ -9,72 +9,21 @@ import (
 	"time"
 
 	"github.com/linode/linodego"
-	"golang.org/x/sync/errgroup"
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/types"
 	cloudprovider "k8s.io/cloud-provider"
-	"k8s.io/klog/v2"
 
 	"github.com/linode/linode-cloud-controller-manager/cloud/linode/client"
 	"github.com/linode/linode-cloud-controller-manager/sentry"
 )
 
-type nodeIP struct {
-	ip     string
-	ipType v1.NodeAddressType
-}
-
-type linodeInstance struct {
-	instance *linodego.Instance
-	ips      []nodeIP
-}
-
 type nodeCache struct {
 	sync.RWMutex
-	nodes      map[int]linodeInstance
+	nodes      map[int]*linodego.Instance
 	lastUpdate time.Time
 	ttl        time.Duration
 }
 
-// getInstanceIPv4Addresses returns all ipv4 addresses configured on a linode.
-func (nc *nodeCache) getInstanceIPv4Addresses(ctx context.Context, id int, client client.Client) ([]nodeIP, error) {
-	// Retrieve ipaddresses for the linode
-	addresses, err := client.GetInstanceIPAddresses(ctx, id)
-	if err != nil {
-		return nil, err
-	}
-
-	var ips []nodeIP
-	if len(addresses.IPv4.Public) != 0 {
-		for _, ip := range addresses.IPv4.Public {
-			ips = append(ips, nodeIP{ip: ip.Address, ipType: v1.NodeExternalIP})
-		}
-	}
-
-	// Retrieve instance configs for the linode
-	configs, err := client.ListInstanceConfigs(ctx, id, &linodego.ListOptions{})
-	if err != nil || len(configs) == 0 {
-		return nil, err
-	}
-
-	// Iterate over interfaces in config and find VPC specific ips
-	for _, iface := range configs[0].Interfaces {
-		if iface.VPCID != nil && iface.IPv4.VPC != "" {
-			ips = append(ips, nodeIP{ip: iface.IPv4.VPC, ipType: v1.NodeInternalIP})
-		}
-	}
-
-	// NOTE: We specifically store VPC ips first so that if they exist, they are
-	//       used as internal ip for the nodes than the private ip
-	if len(addresses.IPv4.Private) != 0 {
-		for _, ip := range addresses.IPv4.Private {
-			ips = append(ips, nodeIP{ip: ip.Address, ipType: v1.NodeInternalIP})
-		}
-	}
-
-	return ips, nil
-}
-
 // refreshInstances conditionally loads all instances from the Linode API and caches them.
 // It does not refresh if the last update happened less than `nodeCache.ttl` ago.
 func (nc *nodeCache) refreshInstances(ctx context.Context, client client.Client) error {
@@ -90,29 +39,11 @@ func (nc *nodeCache) refreshInstances(ctx context.Context, client client.Client)
 		return err
 	}
 
-	nc.nodes = make(map[int]linodeInstance, len(instances))
+	nc.nodes = make(map[int]*linodego.Instance)
 
-	mtx := sync.Mutex{}
-	g := new(errgroup.Group)
 	for _, instance := range instances {
 		instance := instance
-		g.Go(func() error {
-			addresses, err := nc.getInstanceIPv4Addresses(ctx, instance.ID, client)
-			if err != nil {
-				klog.Errorf("Failed fetching ip addresses for instance id %d. Error: %s", instance.ID, err.Error())
-				return err
-			}
-			// take lock on map so that concurrent writes are safe
-			mtx.Lock()
-			defer mtx.Unlock()
-			node := linodeInstance{instance: &instance, ips: addresses}
-			nc.nodes[instance.ID] = node
-			return nil
-		})
-	}
-
-	if err := g.Wait(); err != nil {
-		return err
+		nc.nodes[instance.ID] = &instance
 	}
 
 	nc.lastUpdate = time.Now()
@@ -133,10 +64,9 @@ func newInstances(client client.Client) *instances {
 			timeout = t
 		}
 	}
-	klog.V(3).Infof("TTL for nodeCache set to %d", timeout)
 
 	return &instances{client, &nodeCache{
-		nodes: make(map[int]linodeInstance, 0),
+		nodes: make(map[int]*linodego.Instance),
 		ttl:   time.Duration(timeout) * time.Second,
 	}}
 }
@@ -153,8 +83,8 @@ func (i *instances) linodeByName(nodeName types.NodeName) (*linodego.Instance, e
 	i.nodeCache.RLock()
 	defer i.nodeCache.RUnlock()
 	for _, node := range i.nodeCache.nodes {
-		if node.instance.Label == string(nodeName) {
-			return node.instance, nil
+		if node.Label == string(nodeName) {
+			return node, nil
 		}
 	}
 
@@ -164,24 +94,11 @@ func (i *instances) linodeByName(nodeName types.NodeName) (*linodego.Instance, e
 func (i *instances) linodeByID(id int) (*linodego.Instance, error) {
 	i.nodeCache.RLock()
 	defer i.nodeCache.RUnlock()
-	linodeInstance, ok := i.nodeCache.nodes[id]
+	instance, ok := i.nodeCache.nodes[id]
 	if !ok {
 		return nil, cloudprovider.InstanceNotFound
 	}
-	return linodeInstance.instance, nil
-}
-
-// listAllInstances returns all instances in nodeCache
-func (i *instances) listAllInstances(ctx context.Context) ([]linodego.Instance, error) {
-	if err := i.nodeCache.refreshInstances(ctx, i.client); err != nil {
-		return nil, err
-	}
-
-	instances := []linodego.Instance{}
-	for _, linodeInstance := range i.nodeCache.nodes {
-		instances = append(instances, *linodeInstance.instance)
-	}
-	return instances, nil
+	return instance, nil
 }
 
 func (i *instances) lookupLinode(ctx context.Context, node *v1.Node) (*linodego.Instance, error) {
@@ -248,13 +165,7 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
 		return nil, err
 	}
 
-	ips, err := i.getLinodeIPv4Addresses(ctx, node)
-	if err != nil {
-		sentry.CaptureError(ctx, err)
-		return nil, err
-	}
-
-	if len(ips) == 0 {
+	if len(linode.IPv4) == 0 {
 		err := instanceNoIPAddressesError{linode.ID}
 		sentry.CaptureError(ctx, err)
 		return nil, err
@@ -262,8 +173,12 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
 
 	addresses := []v1.NodeAddress{{Type: v1.NodeHostName, Address: linode.Label}}
 
-	for _, ip := range ips {
-		addresses = append(addresses, v1.NodeAddress{Type: ip.ipType, Address: ip.ip})
+	for _, ip := range linode.IPv4 {
+		ipType := v1.NodeExternalIP
+		if ip.IsPrivate() {
+			ipType = v1.NodeInternalIP
+		}
+		addresses = append(addresses, v1.NodeAddress{Type: ipType, Address: ip.String()})
 	}
 
 	// note that Zone is omitted as it's not a thing in Linode
@@ -276,23 +191,3 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
 
 	return meta, nil
 }
-
-func (i *instances) getLinodeIPv4Addresses(ctx context.Context, node *v1.Node) ([]nodeIP, error) {
-	ctx = sentry.SetHubOnContext(ctx)
-	instance, err := i.lookupLinode(ctx, node)
-	if err != nil {
-		sentry.CaptureError(ctx, err)
-		return nil, err
-	}
-
-	i.nodeCache.RLock()
-	defer i.nodeCache.RUnlock()
-	linodeInstance, ok := i.nodeCache.nodes[instance.ID]
-	if !ok || len(linodeInstance.ips) == 0 {
-		err := instanceNoIPAddressesError{instance.ID}
-		sentry.CaptureError(ctx, err)
-		return nil, err
-	}
-
-	return linodeInstance.ips, nil
-}
diff --git a/cloud/linode/node_controller.go b/cloud/linode/node_controller.go
index 461407c..e77eb20 100644
--- a/cloud/linode/node_controller.go
+++ b/cloud/linode/node_controller.go
@@ -127,9 +127,8 @@ func (s *nodeController) handleNode(ctx context.Context, node *v1.Node) error {
 
 	lastUpdate := s.LastMetadataUpdate(node.Name)
 
-	uuid, foundLabel := node.Labels[annotations.AnnLinodeHostUUID]
-	configuredPrivateIP, foundAnnotation := node.Annotations[annotations.AnnLinodeNodePrivateIP]
-	if foundLabel && foundAnnotation && time.Since(lastUpdate) < s.ttl {
+	uuid, ok := node.Labels[annotations.AnnLinodeHostUUID]
+	if ok && time.Since(lastUpdate) < s.ttl {
 		return nil
 	}
 
@@ -139,19 +138,7 @@ func (s *nodeController) handleNode(ctx context.Context, node *v1.Node) error {
 		return err
 	}
 
-	expectedPrivateIP := ""
-	// linode API response for linode will contain only one private ip
-	// if any private ip is configured. If it changes in future or linode
-	// supports other subnets with nodebalancer, this logic needs to be updated.
-	// https://www.linode.com/docs/api/linode-instances/#linode-view
-	for _, addr := range linode.IPv4 {
-		if addr.IsPrivate() {
-			expectedPrivateIP = addr.String()
-			break
-		}
-	}
-
-	if uuid == linode.HostUUID && configuredPrivateIP == expectedPrivateIP {
+	if uuid == linode.HostUUID {
 		s.SetLastMetadataUpdate(node.Name)
 		return nil
 	}
@@ -163,16 +150,13 @@ func (s *nodeController) handleNode(ctx context.Context, node *v1.Node) error {
 			return err
 		}
 
-		// It may be that the UUID label and private ip annotation has been set
-		if n.Labels[annotations.AnnLinodeHostUUID] == linode.HostUUID && n.Annotations[annotations.AnnLinodeNodePrivateIP] == expectedPrivateIP {
+		// It may be that the UUID has been set
+		if n.Labels[annotations.AnnLinodeHostUUID] == linode.HostUUID {
 			return nil
 		}
 
 		// Try to update the node
 		n.Labels[annotations.AnnLinodeHostUUID] = linode.HostUUID
-		if expectedPrivateIP != "" {
-			n.Annotations[annotations.AnnLinodeNodePrivateIP] = expectedPrivateIP
-		}
 		_, err = s.kubeclient.CoreV1().Nodes().Update(ctx, n, metav1.UpdateOptions{})
 		return err
 	}); err != nil {
diff --git a/cloud/linode/route_controller.go b/cloud/linode/route_controller.go
deleted file mode 100644
index dd634c2..0000000
--- a/cloud/linode/route_controller.go
+++ /dev/null
@@ -1,254 +0,0 @@
-package linode
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"strconv"
-	"sync"
-	"time"
-
-	"github.com/linode/linodego"
-	"golang.org/x/sync/errgroup"
-	"golang.org/x/exp/slices"
-	v1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/types"
-	cloudprovider "k8s.io/cloud-provider"
-	"k8s.io/klog/v2"
-
-	"github.com/linode/linode-cloud-controller-manager/cloud/linode/client"
-)
-
-type routeCache struct {
-	sync.RWMutex
-	routes     map[int][]linodego.InstanceConfig
-	lastUpdate time.Time
-	ttl        time.Duration
-}
-
-func (rc *routeCache) refreshRoutes(ctx context.Context, client client.Client) error {
-	rc.Lock()
-	defer rc.Unlock()
-
-	if time.Since(rc.lastUpdate) < rc.ttl {
-		return nil
-	}
-
-	instances, err := client.ListInstances(ctx, nil)
-	if err != nil {
-		return err
-	}
-
-	rc.routes = make(map[int][]linodego.InstanceConfig, len(instances))
-
-	mtx := sync.Mutex{}
-	g := new(errgroup.Group)
-	for _, instance := range instances {
-		id := instance.ID
-		g.Go(func() error {
-			configs, err := client.ListInstanceConfigs(ctx, id, &linodego.ListOptions{})
-			if err != nil {
-				klog.Errorf("Failed fetching instance configs for instance id %d. Error: %s", id, err.Error())
-				return err
-			}
-			// take lock on map so that concurrent writes are safe
-			mtx.Lock()
-			defer mtx.Unlock()
-			rc.routes[id] = configs
-			return nil
-		})
-	}
-
-	if err := g.Wait(); err != nil {
-		return err
-	}
-
-	rc.lastUpdate = time.Now()
-	return nil
-}
-
-type routes struct {
-	vpcid      int
-	client     client.Client
-	instances  *instances
-	routeCache *routeCache
-}
-
-func newRoutes(client client.Client) (cloudprovider.Routes, error) {
-	timeout := 60
-	if raw, ok := os.LookupEnv("LINODE_ROUTES_CACHE_TTL"); ok {
-		if t, _ := strconv.Atoi(raw); t > 0 {
-			timeout = t
-		}
-	}
-	klog.V(3).Infof("TTL for routeCache set to %d", timeout)
-
-	vpcid := 0
-	if Options.EnableRouteController {
-		id, err := getVPCID(client, Options.VPCName)
-		if err != nil {
-			return nil, err
-		}
-		vpcid = id
-	}
-
-	return &routes{
-		vpcid:     vpcid,
-		client:    client,
-		instances: newInstances(client),
-		routeCache: &routeCache{
-			routes: make(map[int][]linodego.InstanceConfig, 0),
-			ttl:    time.Duration(timeout) * time.Second,
-		},
-	}, nil
-}
-
-// instanceConfigsByID returns InstanceConfigs for given instance id
-func (r *routes) instanceConfigsByID(id int) ([]linodego.InstanceConfig, error) {
-	r.routeCache.RLock()
-	defer r.routeCache.RUnlock()
-	instanceConfigs, ok := r.routeCache.routes[id]
-	if !ok {
-		return nil, fmt.Errorf("no configs found for instance %d", id)
-	}
-	return instanceConfigs, nil
-}
-
-// getInstanceConfigs returns InstanceConfigs for given instance id
-// It refreshes routeCache if it has expired
-func (r *routes) getInstanceConfigs(ctx context.Context, id int) ([]linodego.InstanceConfig, error) {
-	if err := r.routeCache.refreshRoutes(ctx, r.client); err != nil {
-		return nil, err
-	}
-
-	return r.instanceConfigsByID(id)
-}
-
-// getInstanceFromName returns linode instance with given name if it exists
-func (r *routes) getInstanceFromName(ctx context.Context, name string) (*linodego.Instance, error) {
-	// create node object
-	node := &v1.Node{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: name,
-		},
-	}
-
-	// fetch instance with specified node name
-	instance, err := r.instances.lookupLinode(ctx, node)
-	if err != nil {
-		klog.Errorf("failed getting linode %s", name)
-		return nil, err
-	}
-	return instance, nil
-}
-
-// CreateRoute adds route's subnet to ip_ranges of target node's VPC interface
-func (r *routes) CreateRoute(ctx context.Context, clusterName string, nameHint string, route *cloudprovider.Route) error {
-	instance, err := r.getInstanceFromName(ctx, string(route.TargetNode))
-	if err != nil {
-		return err
-	}
-
-	// fetch instance configs
-	configs, err := r.getInstanceConfigs(ctx, instance.ID)
-	if err != nil {
-		return err
-	}
-
-	// find VPC interface and add route to it
-	for _, iface := range configs[0].Interfaces {
-		if iface.VPCID == nil || r.vpcid != *iface.VPCID || iface.IPv4.VPC == "" {
-			continue
-		}
-
-		if slices.Contains(iface.IPRanges, route.DestinationCIDR) {
-			klog.V(4).Infof("Route already exists for node %s", route.TargetNode)
-			return nil
-		}
-
-		ipRanges := append(iface.IPRanges, route.DestinationCIDR)
-		interfaceUpdateOptions := linodego.InstanceConfigInterfaceUpdateOptions{
-			IPRanges: ipRanges,
-		}
-		resp, err := r.client.UpdateInstanceConfigInterface(ctx, instance.ID, configs[0].ID, iface.ID, interfaceUpdateOptions)
-		if err != nil {
-			return err
-		}
-		klog.V(4).Infof("Added routes for node %s. Current routes: %v", route.TargetNode, resp.IPRanges)
-		return nil
-	}
-
-	return fmt.Errorf("unable to add route %s for node %s. no valid interface found", route.DestinationCIDR, route.TargetNode)
-}
-
-// DeleteRoute removes route's subnet from ip_ranges of target node's VPC interface
-func (r *routes) DeleteRoute(ctx context.Context, clusterName string, route *cloudprovider.Route) error {
-	instance, err := r.getInstanceFromName(ctx, string(route.TargetNode))
-	if err != nil {
-		return err
-	}
-
-	configs, err := r.getInstanceConfigs(ctx, instance.ID)
-	if err != nil {
-		return err
-	}
-
-	for _, iface := range configs[0].Interfaces {
-		if iface.VPCID == nil || r.vpcid != *iface.VPCID || iface.IPv4.VPC == "" {
-			continue
-		}
-
-		ipRanges := []string{}
-		for _, configured_route := range iface.IPRanges {
-			if configured_route != route.DestinationCIDR {
-				ipRanges = append(ipRanges, configured_route)
-			}
-		}
-
-		interfaceUpdateOptions := linodego.InstanceConfigInterfaceUpdateOptions{
-			IPRanges: ipRanges,
-		}
-		resp, err := r.client.UpdateInstanceConfigInterface(ctx, instance.ID, configs[0].ID, iface.ID, interfaceUpdateOptions)
-		if err != nil {
-			return err
-		}
-		klog.V(4).Infof("Deleted route for node %s. Current routes: %v", route.TargetNode, resp.IPRanges)
-		return nil
-	}
-	return fmt.Errorf("unable to remove route %s for node %s", route.DestinationCIDR, route.TargetNode)
-}
-
-// ListRoutes fetches routes configured on all instances which have VPC interfaces
-func (r *routes) ListRoutes(ctx context.Context, clusterName string) ([]*cloudprovider.Route, error) {
-	klog.V(4).Infof("Fetching routes configured on the cluster")
-	instances, err := r.instances.listAllInstances(ctx)
-	if err != nil {
-		return nil, err
-	}
-
-	var routes []*cloudprovider.Route
-	for _, instance := range instances {
-		configs, err := r.getInstanceConfigs(ctx, instance.ID)
-		if err != nil {
-			klog.Errorf("Failed finding routes for instance id %d. Error: %v", instance.ID, err)
-			continue
-		}
-
-		for _, iface := range configs[0].Interfaces {
-			if iface.VPCID == nil || r.vpcid != *iface.VPCID || iface.IPv4.VPC == "" {
-				continue
-			}
-
-			for _, ipsubnet := range iface.IPRanges {
-				route := &cloudprovider.Route{
-					TargetNode:      types.NodeName(instance.Label),
-					DestinationCIDR: ipsubnet,
-				}
-				klog.V(4).Infof("Found route: node %s, route %s", instance.Label, route.DestinationCIDR)
-				routes = append(routes, route)
-			}
-		}
-	}
-	return routes, nil
-}
diff --git a/cloud/linode/vpc.go b/cloud/linode/vpc.go
deleted file mode 100644
index fd40e73..0000000
--- a/cloud/linode/vpc.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package linode
-
-import (
-	"context"
-	"fmt"
-
-	"github.com/linode/linode-cloud-controller-manager/cloud/linode/client"
-	"github.com/linode/linodego"
-)
-
-type vpcLookupError struct {
-	value string
-}
-
-func (e vpcLookupError) Error() string {
-	return fmt.Sprintf("failed to find VPC: %q", e.value)
-}
-
-// getVPCID returns the VPC id using the VPC label
-func getVPCID(client client.Client, vpcName string) (int, error) {
-	vpcs, err := client.ListVPCs(context.TODO(), &linodego.ListOptions{})
-	if err != nil {
-		return 0, err
-	}
-	for _, vpc := range vpcs {
-		if vpc.Label == vpcName {
-			return vpc.ID, nil
-		}
-	}
-	return 0, vpcLookupError{vpcName}
-}
diff --git a/deploy/chart/templates/daemonset.yaml b/deploy/chart/templates/daemonset.yaml
index 4b2b3d4..6a38e6e 100644
--- a/deploy/chart/templates/daemonset.yaml
+++ b/deploy/chart/templates/daemonset.yaml
@@ -36,15 +36,6 @@ spec:
             {{- if .Values.linodegoDebug }}
             - --linodego-debug={{ .Values.linodegoDebug }}
             {{- end }}
-            {{- if .Values.routeController }}
-            - --enable-route-controller=true
-            - --vpc-name={{ .Values.routeController.vpcName }}
-            - --configure-cloud-routes={{ .Values.routeController.configureCloudRoutes }}
-            - --cluster-cidr={{ .Values.routeController.clusterCIDR }}
-            {{- if .Values.routeController.routeReconciliationPeriod }}
-            - --route-reconciliation-period={{ .Values.routeController.routeReconciliationPeriod }}
-            {{- end }}
-            {{- end }}
           volumeMounts:
             - mountPath: /etc/kubernetes
               name: k8s
diff --git a/deploy/chart/values.yaml b/deploy/chart/values.yaml
index 2df40a1..d8bf72e 100644
--- a/deploy/chart/values.yaml
+++ b/deploy/chart/values.yaml
@@ -44,12 +44,6 @@ tolerations:
     operator: Exists
     effect: NoSchedule
 
-# This section adds ability to enable route-controller for ccm
-# routeController:
-#   vpcName: <name of VPC>
-#   clusterCIDR: 10.0.0.0/8
-#   configureCloudRoutes: true
-
 # This section adds the ability to pass environment variables to adjust CCM defaults
 # https://github.com/linode/linode-cloud-controller-manager/blob/master/cloud/linode/loadbalancers.go
 # LINODE_HOSTNAME_ONLY_INGRESS type bool is supported
diff --git a/main.go b/main.go
index dfcf10b..f82c9e1 100644
--- a/main.go
+++ b/main.go
@@ -76,8 +76,6 @@ func main() {
 
 	// Add Linode-specific flags
 	command.Flags().BoolVar(&linode.Options.LinodeGoDebug, "linodego-debug", false, "enables debug output for the LinodeAPI wrapper")
-	command.Flags().BoolVar(&linode.Options.EnableRouteController, "enable-route-controller", false, "enables route_controller for ccm")
-	command.Flags().StringVar(&linode.Options.VPCName, "vpc-name", "", "vpc name whose routes will be managed by route-controller")
 
 	// Set static flags
 	command.Flags().VisitAll(func(fl *pflag.Flag) {


Test patch:
diff --git a/cloud/linode/client/mock_client_test.go b/cloud/linode/client/mock_client_test.go
index b39dca0..c753589 100644
--- a/cloud/linode/client/mock_client_test.go
+++ b/cloud/linode/client/mock_client_test.go
@@ -226,21 +226,6 @@ func (mr *MockClientMockRecorder) ListFirewallDevices(arg0, arg1, arg2 interface
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListFirewallDevices", reflect.TypeOf((*MockClient)(nil).ListFirewallDevices), arg0, arg1, arg2)
 }
 
-// ListInstanceConfigs mocks base method.
-func (m *MockClient) ListInstanceConfigs(arg0 context.Context, arg1 int, arg2 *linodego.ListOptions) ([]linodego.InstanceConfig, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "ListInstanceConfigs", arg0, arg1, arg2)
-	ret0, _ := ret[0].([]linodego.InstanceConfig)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// ListInstanceConfigs indicates an expected call of ListInstanceConfigs.
-func (mr *MockClientMockRecorder) ListInstanceConfigs(arg0, arg1, arg2 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListInstanceConfigs", reflect.TypeOf((*MockClient)(nil).ListInstanceConfigs), arg0, arg1, arg2)
-}
-
 // ListInstances mocks base method.
 func (m *MockClient) ListInstances(arg0 context.Context, arg1 *linodego.ListOptions) ([]linodego.Instance, error) {
 	m.ctrl.T.Helper()
@@ -301,21 +286,6 @@ func (mr *MockClientMockRecorder) ListNodeBalancers(arg0, arg1 interface{}) *gom
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListNodeBalancers", reflect.TypeOf((*MockClient)(nil).ListNodeBalancers), arg0, arg1)
 }
 
-// ListVPCs mocks base method.
-func (m *MockClient) ListVPCs(arg0 context.Context, arg1 *linodego.ListOptions) ([]linodego.VPC, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "ListVPCs", arg0, arg1)
-	ret0, _ := ret[0].([]linodego.VPC)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// ListVPCs indicates an expected call of ListVPCs.
-func (mr *MockClientMockRecorder) ListVPCs(arg0, arg1 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListVPCs", reflect.TypeOf((*MockClient)(nil).ListVPCs), arg0, arg1)
-}
-
 // RebuildNodeBalancerConfig mocks base method.
 func (m *MockClient) RebuildNodeBalancerConfig(arg0 context.Context, arg1, arg2 int, arg3 linodego.NodeBalancerConfigRebuildOptions) (*linodego.NodeBalancerConfig, error) {
 	m.ctrl.T.Helper()
@@ -346,21 +316,6 @@ func (mr *MockClientMockRecorder) UpdateFirewallRules(arg0, arg1, arg2 interface
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateFirewallRules", reflect.TypeOf((*MockClient)(nil).UpdateFirewallRules), arg0, arg1, arg2)
 }
 
-// UpdateInstanceConfigInterface mocks base method.
-func (m *MockClient) UpdateInstanceConfigInterface(arg0 context.Context, arg1, arg2, arg3 int, arg4 linodego.InstanceConfigInterfaceUpdateOptions) (*linodego.InstanceConfigInterface, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "UpdateInstanceConfigInterface", arg0, arg1, arg2, arg3, arg4)
-	ret0, _ := ret[0].(*linodego.InstanceConfigInterface)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// UpdateInstanceConfigInterface indicates an expected call of UpdateInstanceConfigInterface.
-func (mr *MockClientMockRecorder) UpdateInstanceConfigInterface(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateInstanceConfigInterface", reflect.TypeOf((*MockClient)(nil).UpdateInstanceConfigInterface), arg0, arg1, arg2, arg3, arg4)
-}
-
 // UpdateNodeBalancer mocks base method.
 func (m *MockClient) UpdateNodeBalancer(arg0 context.Context, arg1 int, arg2 linodego.NodeBalancerUpdateOptions) (*linodego.NodeBalancer, error) {
 	m.ctrl.T.Helper()
diff --git a/cloud/linode/instances_test.go b/cloud/linode/instances_test.go
index 2eadd4e..a93711a 100644
--- a/cloud/linode/instances_test.go
+++ b/cloud/linode/instances_test.go
@@ -64,18 +64,6 @@ func TestInstanceExists(t *testing.T) {
 				Type:   "g6-standard-2",
 			},
 		}, nil)
-		client.EXPECT().GetInstanceIPAddresses(gomock.Any(), 123).Times(1).Return(&linodego.InstanceIPAddressResponse{
-			IPv4: &linodego.InstanceIPv4Response{
-				Public: []*linodego.InstanceIP{
-					{Address: "45.76.101.25"},
-				},
-				Private: []*linodego.InstanceIP{
-					{Address: "192.168.133.65"},
-				},
-			},
-			IPv6: nil,
-		}, nil)
-		client.EXPECT().ListInstanceConfigs(gomock.Any(), 123, gomock.Any()).Times(1).Return([]linodego.InstanceConfig{}, nil)
 
 		exists, err := instances.InstanceExists(ctx, node)
 		assert.NoError(t, err)
@@ -90,18 +78,6 @@ func TestInstanceExists(t *testing.T) {
 		client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
 			{ID: 123, Label: name},
 		}, nil)
-		client.EXPECT().GetInstanceIPAddresses(gomock.Any(), 123).Times(1).Return(&linodego.InstanceIPAddressResponse{
-			IPv4: &linodego.InstanceIPv4Response{
-				Public: []*linodego.InstanceIP{
-					{Address: "45.76.101.25"},
-				},
-				Private: []*linodego.InstanceIP{
-					{Address: "192.168.133.65"},
-				},
-			},
-			IPv6: nil,
-		}, nil)
-		client.EXPECT().ListInstanceConfigs(gomock.Any(), 123, gomock.Any()).Times(1).Return([]linodego.InstanceConfig{}, nil)
 
 		exists, err := instances.InstanceExists(ctx, node)
 		assert.NoError(t, err)
@@ -151,27 +127,13 @@ func TestMetadataRetrieval(t *testing.T) {
 		client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
 			{ID: id, Label: name, Type: linodeType, Region: region, IPv4: []*net.IP{&publicIPv4, &privateIPv4}},
 		}, nil)
-		client.EXPECT().GetInstanceIPAddresses(gomock.Any(), id).Times(1).Return(&linodego.InstanceIPAddressResponse{
-			IPv4: &linodego.InstanceIPv4Response{
-				Public: []*linodego.InstanceIP{
-					{Address: "45.76.101.25"},
-				},
-				Private: []*linodego.InstanceIP{
-					{Address: "192.168.133.65"},
-				},
-			},
-			IPv6: nil,
-		}, nil)
-		client.EXPECT().ListInstanceConfigs(gomock.Any(), 123, gomock.Any()).Times(1).Return([]linodego.InstanceConfig{
-			{ID: 123456},
-		}, nil)
 
 		meta, err := instances.InstanceMetadata(ctx, node)
 		assert.NoError(t, err)
 		assert.Equal(t, providerIDPrefix+strconv.Itoa(id), meta.ProviderID)
 		assert.Equal(t, region, meta.Region)
 		assert.Equal(t, linodeType, meta.InstanceType)
-		assert.Equal(t, []v1.NodeAddress{
+		assert.Equal(t, meta.NodeAddresses, []v1.NodeAddress{
 			{
 				Type:    v1.NodeHostName,
 				Address: name,
@@ -184,7 +146,7 @@ func TestMetadataRetrieval(t *testing.T) {
 				Type:    v1.NodeInternalIP,
 				Address: privateIPv4.String(),
 			},
-		}, meta.NodeAddresses)
+		})
 	})
 
 	ipTests := []struct {
@@ -235,24 +197,12 @@ func TestMetadataRetrieval(t *testing.T) {
 			node := nodeWithProviderID(providerID)
 
 			ips := make([]*net.IP, 0, len(test.inputIPs))
-			pubIPs := make([]*linodego.InstanceIP, 0)
-			privIPs := make([]*linodego.InstanceIP, 0)
 			for _, ip := range test.inputIPs {
 				parsed := net.ParseIP(ip)
 				if parsed == nil {
 					t.Fatalf("cannot parse %v as an ipv4", ip)
 				}
 				ips = append(ips, &parsed)
-				if parsed.IsPrivate() {
-					privIPs = append(privIPs, &linodego.InstanceIP{Address: ip})
-				} else {
-					pubIPs = append(pubIPs, &linodego.InstanceIP{Address: ip})
-				}
-			}
-
-			ipv4s := &linodego.InstanceIPv4Response{
-				Public:  pubIPs,
-				Private: privIPs,
 			}
 
 			linodeType := "g6-standard-1"
@@ -260,13 +210,6 @@ func TestMetadataRetrieval(t *testing.T) {
 			client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
 				{ID: id, Label: name, Type: linodeType, Region: region, IPv4: ips},
 			}, nil)
-			client.EXPECT().GetInstanceIPAddresses(gomock.Any(), id).Times(1).Return(&linodego.InstanceIPAddressResponse{
-				IPv4: ipv4s,
-				IPv6: nil,
-			}, nil)
-			client.EXPECT().ListInstanceConfigs(gomock.Any(), id, gomock.Any()).Times(1).Return([]linodego.InstanceConfig{
-				{ID: 123456},
-			}, nil)
 
 			meta, err := instances.InstanceMetadata(ctx, node)
 
@@ -338,16 +281,6 @@ func TestInstanceShutdown(t *testing.T) {
 		client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
 			{ID: id, Label: "offline-linode", Status: linodego.InstanceOffline},
 		}, nil)
-		client.EXPECT().GetInstanceIPAddresses(gomock.Any(), id).Times(1).Return(&linodego.InstanceIPAddressResponse{
-			IPv4: &linodego.InstanceIPv4Response{
-				Public:  []*linodego.InstanceIP{},
-				Private: []*linodego.InstanceIP{},
-			},
-			IPv6: nil,
-		}, nil)
-		client.EXPECT().ListInstanceConfigs(gomock.Any(), id, gomock.Any()).Times(1).Return([]linodego.InstanceConfig{
-			{ID: 123456},
-		}, nil)
 		shutdown, err := instances.InstanceShutdown(ctx, node)
 
 		assert.NoError(t, err)
@@ -361,16 +294,6 @@ func TestInstanceShutdown(t *testing.T) {
 		client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
 			{ID: id, Label: "shutting-down-linode", Status: linodego.InstanceShuttingDown},
 		}, nil)
-		client.EXPECT().GetInstanceIPAddresses(gomock.Any(), id).Times(1).Return(&linodego.InstanceIPAddressResponse{
-			IPv4: &linodego.InstanceIPv4Response{
-				Public:  []*linodego.InstanceIP{},
-				Private: []*linodego.InstanceIP{},
-			},
-			IPv6: nil,
-		}, nil)
-		client.EXPECT().ListInstanceConfigs(gomock.Any(), id, gomock.Any()).Times(1).Return([]linodego.InstanceConfig{
-			{ID: 123456},
-		}, nil)
 		shutdown, err := instances.InstanceShutdown(ctx, node)
 
 		assert.NoError(t, err)
@@ -384,16 +307,6 @@ func TestInstanceShutdown(t *testing.T) {
 		client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
 			{ID: id, Label: "running-linode", Status: linodego.InstanceRunning},
 		}, nil)
-		client.EXPECT().GetInstanceIPAddresses(gomock.Any(), id).Times(1).Return(&linodego.InstanceIPAddressResponse{
-			IPv4: &linodego.InstanceIPv4Response{
-				Public:  []*linodego.InstanceIP{},
-				Private: []*linodego.InstanceIP{},
-			},
-			IPv6: nil,
-		}, nil)
-		client.EXPECT().ListInstanceConfigs(gomock.Any(), id, gomock.Any()).Times(1).Return([]linodego.InstanceConfig{
-			{ID: 123456},
-		}, nil)
 		shutdown, err := instances.InstanceShutdown(ctx, node)
 
 		assert.NoError(t, err)