Skip to content

Instantly share code, notes, and snippets.

@tobstarr
Created September 27, 2016 08:11
Show Gist options
  • Save tobstarr/6765104c764a3a6af8ec894bb5a0028b to your computer and use it in GitHub Desktop.
Save tobstarr/6765104c764a3a6af8ec894bb5a0028b to your computer and use it in GitHub Desktop.
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
"github.com/golang/glog"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"k8s.io/client-go/1.5/kubernetes"
"k8s.io/client-go/1.5/pkg/api"
"k8s.io/client-go/1.5/rest"
"k8s.io/client-go/1.5/tools/clientcmd"
clientcmdapi "k8s.io/client-go/1.5/tools/clientcmd/api"
)
func main() {
l := log.New(os.Stderr, "", 0)
if err := run(l); err != nil {
log.Fatal(err)
}
}
func run(l *log.Logger) error {
err := rest.RegisterAuthProviderPlugin("gcp", newGCPAuthProvider)
if err != nil {
return err
}
ov := &clientcmd.ConfigOverrides{
ClusterInfo: clientcmdapi.Cluster{
InsecureSkipTLSVerify: true,
},
}
path := os.ExpandEnv("$HOME/.kube/config")
info, err := clientcmd.LoadFromFile(path)
if err != nil {
return err
}
dc := clientcmd.NewNonInteractiveClientConfig(*info, "", ov, nil)
c, err := dc.ClientConfig()
if err != nil {
return fmt.Errorf("error building client config: %s", err)
}
client, err := kubernetes.NewForConfig(c)
if err != nil {
return fmt.Errorf("error creating client: %s", err)
}
l.Printf("listing pods")
pods, err := client.Core().Pods("").List(api.ListOptions{})
if err != nil {
return fmt.Errorf("error listing pods: %s", err)
}
l.Printf("loaded %d pods", len(pods.Items))
return nil
}
func newGCPAuthProvider(_ string, gcpConfig map[string]string, persister rest.AuthProviderConfigPersister) (rest.AuthProvider, error) {
ts, err := newCachedTokenSource(gcpConfig["access-token"], gcpConfig["expiry"], persister)
if err != nil {
return nil, err
}
return &gcpAuthProvider{ts, persister}, nil
}
type gcpAuthProvider struct {
tokenSource oauth2.TokenSource
persister rest.AuthProviderConfigPersister
}
func (g *gcpAuthProvider) WrapTransport(rt http.RoundTripper) http.RoundTripper {
return &oauth2.Transport{
Source: g.tokenSource,
Base: rt,
}
}
func (g *gcpAuthProvider) Login() error { return nil }
type cachedTokenSource struct {
source oauth2.TokenSource
accessToken string
expiry time.Time
persister rest.AuthProviderConfigPersister
}
func newCachedTokenSource(accessToken, expiry string, persister rest.AuthProviderConfigPersister) (*cachedTokenSource, error) {
var expiryTime time.Time
if parsedTime, err := time.Parse(time.RFC3339Nano, expiry); err == nil {
expiryTime = parsedTime
}
ts, err := google.DefaultTokenSource(context.Background(), "https://www.googleapis.com/auth/cloud-platform")
if err != nil {
return nil, err
}
return &cachedTokenSource{
source: ts,
accessToken: accessToken,
expiry: expiryTime,
persister: persister,
}, nil
}
func (t *cachedTokenSource) Token() (*oauth2.Token, error) {
log.Printf("loading token")
tok := &oauth2.Token{
AccessToken: t.accessToken,
TokenType: "Bearer",
Expiry: t.expiry,
}
if tok.Valid() && !tok.Expiry.IsZero() {
json.NewEncoder(os.Stdout).Encode(tok)
return tok, nil
}
tok, err := t.source.Token()
if err != nil {
return nil, err
}
if t.persister != nil {
cached := map[string]string{
"access-token": tok.AccessToken,
"expiry": tok.Expiry.Format(time.RFC3339Nano),
}
if err := t.persister.Persist(cached); err != nil {
glog.V(4).Infof("Failed to persist token: %v", err)
}
}
return tok, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment