diff --git a/pkg/cloudprovider/providers/gce/gce_routes.go b/pkg/cloudprovider/providers/gce/gce_routes.go index 87184aef11..34c0e3c06a 100644 --- a/pkg/cloudprovider/providers/gce/gce_routes.go +++ b/pkg/cloudprovider/providers/gce/gce_routes.go @@ -17,95 +17,75 @@ limitations under the License. package gce import ( + "context" "fmt" "net/http" "path" - "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/cloudprovider" - "github.com/golang/glog" compute "google.golang.org/api/compute/v1" + "k8s.io/apimachinery/pkg/types" + + "k8s.io/kubernetes/pkg/cloudprovider" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) func newRoutesMetricContext(request string) *metricContext { return newGenericMetricContext("routes", request, unusedMetricLabel, unusedMetricLabel, computeV1Version) } +// ListRoutes in the cloud environment. func (gce *GCECloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) { - var routes []*cloudprovider.Route - pageToken := "" - page := 0 - for ; page == 0 || (pageToken != "" && page < maxPages); page++ { - mc := newRoutesMetricContext("list_page") - listCall := gce.service.Routes.List(gce.NetworkProjectID()) - - prefix := truncateClusterName(clusterName) - // Filter for routes starting with clustername AND belonging to the - // relevant gcp network AND having description = "k8s-node-route". - filter := "(name eq " + prefix + "-.*) " - filter = filter + "(network eq " + gce.NetworkURL() + ") " - filter = filter + "(description eq " + k8sNodeRouteTag + ")" - listCall = listCall.Filter(filter) - if pageToken != "" { - listCall = listCall.PageToken(pageToken) - } - res, err := listCall.Do() - mc.Observe(err) - if err != nil { - glog.Errorf("Error getting routes from GCE: %v", err) - return nil, err - } - pageToken = res.NextPageToken - for _, r := range res.Items { - target := path.Base(r.NextHopInstance) - // TODO: Should we lastComponent(target) this? - targetNodeName := types.NodeName(target) // NodeName == Instance Name on GCE - routes = append(routes, &cloudprovider.Route{Name: r.Name, TargetNode: targetNodeName, DestinationCIDR: r.DestRange}) - } + mc := newRoutesMetricContext("list") + prefix := truncateClusterName(clusterName) + f := filter.Regexp("name", prefix+"-.*").AndRegexp("network", gce.NetworkURL()).AndRegexp("description", k8sNodeRouteTag) + routes, err := gce.c.Routes().List(context.Background(), f) + if err != nil { + return nil, mc.Observe(err) } - if page >= maxPages { - glog.Errorf("ListRoutes exceeded maxPages=%d for Routes.List; truncating.", maxPages) + var croutes []*cloudprovider.Route + for _, r := range routes { + target := path.Base(r.NextHopInstance) + // TODO: Should we lastComponent(target) this? + targetNodeName := types.NodeName(target) // NodeName == Instance Name on GCE + croutes = append(croutes, &cloudprovider.Route{ + Name: r.Name, + TargetNode: targetNodeName, + DestinationCIDR: r.DestRange, + }) } - return routes, nil + return croutes, mc.Observe(nil) } +// CreateRoute in the cloud environment. func (gce *GCECloud) CreateRoute(clusterName string, nameHint string, route *cloudprovider.Route) error { - routeName := truncateClusterName(clusterName) + "-" + nameHint - - instanceName := mapNodeNameToInstanceName(route.TargetNode) - targetInstance, err := gce.getInstanceByName(instanceName) - if err != nil { - return err - } - mc := newRoutesMetricContext("create") - insertOp, err := gce.service.Routes.Insert(gce.NetworkProjectID(), &compute.Route{ - Name: routeName, + + targetInstance, err := gce.getInstanceByName(mapNodeNameToInstanceName(route.TargetNode)) + if err != nil { + return mc.Observe(err) + } + cr := &compute.Route{ + Name: truncateClusterName(clusterName) + "-" + nameHint, DestRange: route.DestinationCIDR, NextHopInstance: fmt.Sprintf("zones/%s/instances/%s", targetInstance.Zone, targetInstance.Name), Network: gce.NetworkURL(), Priority: 1000, Description: k8sNodeRouteTag, - }).Do() - if err != nil { - if isHTTPErrorCode(err, http.StatusConflict) { - glog.Infof("Route %v already exists.", routeName) - return nil - } else { - return mc.Observe(err) - } } - return gce.waitForGlobalOpInProject(insertOp, gce.NetworkProjectID(), mc) + err = gce.c.Routes().Insert(context.Background(), meta.GlobalKey(cr.Name), cr) + if isHTTPErrorCode(err, http.StatusConflict) { + glog.Infof("Route %q already exists.", cr.Name) + err = nil + } + return mc.Observe(err) } +// DeleteRoute from the cloud environment. func (gce *GCECloud) DeleteRoute(clusterName string, route *cloudprovider.Route) error { mc := newRoutesMetricContext("delete") - deleteOp, err := gce.service.Routes.Delete(gce.NetworkProjectID(), route.Name).Do() - if err != nil { - return mc.Observe(err) - } - return gce.waitForGlobalOpInProject(deleteOp, gce.NetworkProjectID(), mc) + return mc.Observe(gce.c.Routes().Delete(context.Background(), meta.GlobalKey(route.Name))) } func truncateClusterName(clusterName string) string {