Last active
August 20, 2017 21:49
-
-
Save JeanMertz/9fabe929cddfa7cf155ab9c72b61d140 to your computer and use it in GitHub Desktop.
Automated Kubernetes Google Cloud Platform routes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"time" | |
"golang.org/x/net/context" | |
"golang.org/x/oauth2/google" | |
compute "google.golang.org/api/compute/v1" | |
apiv1 "k8s.io/api/core/v1" | |
"k8s.io/apimachinery/pkg/apis/meta/v1" | |
"k8s.io/client-go/kubernetes" | |
"k8s.io/client-go/rest" | |
) | |
// RouteRule dictates if an existing rule is valid or not. | |
type RouteRule struct { | |
Valid bool | |
Route *compute.Route | |
} | |
var ( | |
computeService *compute.Service | |
clientset *kubernetes.Clientset | |
project = "" | |
destRange = "xxx.xxx.xxx.xxx/20" | |
network = "default" | |
zone = "europe-west1-d" | |
routeName = "%s-serviceip" | |
description = "gke-serviceip-route" | |
ctx = context.Background() | |
) | |
func main() { | |
var err error | |
computeService, err = newComputeClient() | |
if err != nil { | |
panic(err.Error()) | |
} | |
clientset, err = newKubernetesClient() | |
if err != nil { | |
panic(err.Error()) | |
} | |
for { | |
err = validateRoutes() | |
if err != nil { | |
log.Println(err.Error()) | |
} | |
time.Sleep(60 * time.Second) | |
} | |
} | |
func validateRoutes() error { | |
rules, err := newRules() | |
if err != nil { | |
return err | |
} | |
nodes, err := clientset.Nodes().List(v1.ListOptions{}) | |
if err != nil { | |
return err | |
} | |
for _, n := range nodes.Items { | |
var match bool | |
for _, r := range rules { | |
if fmt.Sprintf(routeName, n.Name) == r.Route.Name { | |
match = true | |
r.Valid = true | |
} | |
} | |
if match { | |
continue | |
} | |
err := createRoute(n) | |
if err != nil { | |
return err | |
} | |
} | |
return deleteInvalidRoutes(rules) | |
} | |
func createRoute(node apiv1.Node) error { | |
route := &compute.Route{ | |
Description: description, | |
DestRange: destRange, | |
Name: fmt.Sprintf(routeName, node.Name), | |
Network: fmt.Sprintf("projects/%s/global/networks/%s", project, network), | |
NextHopInstance: fmt.Sprintf("projects/%s/zones/%s/instances/%s", project, zone, node.Name), | |
} | |
_, err := computeService.Routes.Insert(project, route).Context(ctx).Do() | |
return err | |
} | |
func deleteRoute(route *compute.Route) error { | |
_, err := computeService.Routes.Delete(project, route.Name).Context(ctx).Do() | |
return err | |
} | |
func deleteInvalidRoutes(rules []*RouteRule) error { | |
for _, r := range rules { | |
if r.Valid { | |
continue | |
} | |
err := deleteRoute(r.Route) | |
if err != nil { | |
return err | |
} | |
} | |
return nil | |
} | |
func newRules() ([]*RouteRule, error) { | |
var rules []*RouteRule | |
filter := fmt.Sprintf("description eq ", description) | |
routeList, err := computeService.Routes.List(project).Filter(filter).Context(ctx).Do() | |
if err != nil { | |
return rules, err | |
} | |
for _, r := range routeList.Items { | |
rules = append(rules, &RouteRule{Route: r}) | |
} | |
return rules, nil | |
} | |
func newComputeClient() (*compute.Service, error) { | |
c, err := google.DefaultClient(ctx, compute.ComputeScope) | |
if err != nil { | |
return nil, err | |
} | |
return compute.New(c) | |
} | |
func newKubernetesClient() (*kubernetes.Clientset, error) { | |
config, err := rest.InClusterConfig() | |
if err != nil { | |
return nil, err | |
} | |
return kubernetes.NewForConfig(config) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment