Created
July 25, 2018 22:16
-
-
Save DazWilkin/f3513e3bd9409238788d378d1056c60e to your computer and use it in GitHub Desktop.
Kubernetes All NodePorts
This file contains hidden or 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 ( | |
"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