Skip to content

Instantly share code, notes, and snippets.

@DazWilkin
Created July 25, 2018 22:16
Show Gist options
  • Save DazWilkin/f3513e3bd9409238788d378d1056c60e to your computer and use it in GitHub Desktop.
Save DazWilkin/f3513e3bd9409238788d378d1056c60e to your computer and use it in GitHub Desktop.
Kubernetes All NodePorts
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"sync"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/tools/clientcmd"
"github.com/DazWilkin/useful"
)
func main() {
var kubeconfig *string
if home := homeDir(); home != "" {
kubeconfig = flag.String(
"kubeconfig",
filepath.Join(home, ".kube", "config"),
"(optional) absolute path to the kubeconfig file",
)
} else {
kubeconfig = flag.String(
"kubeconfig",
"",
"absolute path to the kubeconfig file",
)
}
flag.Parse()
// Use current-context (must be set) in kube-config
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
panic(err.Error())
}
// Create the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
// Get all services (all namespaces)
services, err := clientset.CoreV1().Services("").List(metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
log.Printf("Cluster has %d services\n", len(services.Items))
// Create a channel to receive NodePorts
ports := make(chan int32)
result := make(chan []int32)
// No need to WaitGroup this go-routine
// Because it results in a message being put on a channel
// This will block until a reader is created to consume the message
// The reader is created at the end
go func(ports chan int32, result chan []int32) {
// A tree
var t useful.Tree
for port := range ports {
log.Printf("NodePort: %d", port)
t.Insert(port)
}
// Once the channel is closed, we'll walk the tree
log.Println("Walking the tree")
result <- t.Walk()
}(ports, result)
// WaitGroup to await completion of all go-routines
var wg sync.WaitGroup
for _, service := range services.Items {
if service.Spec.Type == "NodePort" {
wg.Add(1)
go func(service v1.Service) {
defer wg.Done()
for _, port := range service.Spec.Ports {
wg.Add(1)
go func(port v1.ServicePort) {
defer wg.Done()
ports <- port.NodePort
}(port)
}
}(service)
}
}
// The writers will complete before the reader can complete
// Block until all NodePorts are enumerated
wg.Wait()
// Then close the channel
close(ports)
// Once the channel closes, finish the reader and walk tree
// Read the sorted slice from the channel
fmt.Println(<-result)
}
func homeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
}
return os.Getenv("USERPROFILE") // windows
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment