Last active
December 16, 2020 06:23
-
-
Save gmorse81/67340239fa2ce01416766826724a74c9 to your computer and use it in GitHub Desktop.
This is an example of how to use the helm v3 go client with a GCP GKE cluster without calling the gcloud CLI or providing a kube config file. This has been cobbled together from many other examples found around the interwebs
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 ( | |
"context" | |
"fmt" | |
"log" | |
"net/http" | |
"golang.org/x/oauth2" | |
"golang.org/x/oauth2/google" | |
"k8s.io/client-go/rest" | |
) | |
var ( | |
googleScopes = []string{ | |
"https://www.googleapis.com/auth/cloud-platform", | |
"https://www.googleapis.com/auth/userinfo.email", | |
} | |
_ rest.AuthProvider = &googleAuthProvider{} | |
) | |
const ( | |
googleAuthPlugin = "google" | |
) | |
func init() { | |
if err := rest.RegisterAuthProviderPlugin(googleAuthPlugin, newGoogleAuthProvider); err != nil { | |
log.Fatalf("Failed to register %s auth plugin: %v", googleAuthPlugin, err) | |
} | |
} | |
type googleAuthProvider struct { | |
tokenSource oauth2.TokenSource | |
} | |
func (g *googleAuthProvider) WrapTransport(rt http.RoundTripper) http.RoundTripper { | |
return &oauth2.Transport{ | |
Base: rt, | |
Source: g.tokenSource, | |
} | |
} | |
func (g *googleAuthProvider) Login() error { return nil } | |
func getTokenSource() (oauth2.TokenSource, error) { | |
// here i am using google.DefaultTokenSource, but other token sources could be used. | |
return google.DefaultTokenSource(context.TODO(), googleScopes...) | |
} | |
func newGoogleAuthProvider(addr string, config map[string]string, persister rest.AuthProviderConfigPersister) (rest.AuthProvider, error) { | |
ts, err := getTokenSource() | |
if err != nil { | |
return nil, fmt.Errorf("failed to create google token source: %+v", err) | |
} | |
return &googleAuthProvider{tokenSource: ts}, nil | |
} |
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 ( | |
"k8s.io/apimachinery/pkg/api/meta" | |
"k8s.io/client-go/discovery" | |
"k8s.io/client-go/discovery/cached/memory" | |
"k8s.io/client-go/rest" | |
"k8s.io/client-go/restmapper" | |
"k8s.io/client-go/tools/clientcmd" | |
) | |
//SimpleRESTClientGetter see RESTClientGetter | |
type SimpleRESTClientGetter struct { | |
Restconf *rest.Config | |
Namespace string | |
} | |
//NewRESTClientGetter see RESTClientGetter | |
func NewRESTClientGetter(r *rest.Config, n string) *SimpleRESTClientGetter { | |
return &SimpleRESTClientGetter{ | |
Restconf: r, | |
Namespace: n, | |
} | |
} | |
//ToRESTConfig see RESTClientGetter | |
func (c *SimpleRESTClientGetter) ToRESTConfig() (*rest.Config, error) { | |
return c.Restconf, nil | |
} | |
//ToDiscoveryClient see RESTClientGetter | |
func (c *SimpleRESTClientGetter) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { | |
config, err := c.ToRESTConfig() | |
if err != nil { | |
return nil, err | |
} | |
config.Burst = 100 | |
discoveryClient, _ := discovery.NewDiscoveryClientForConfig(config) | |
return memory.NewMemCacheClient(discoveryClient), nil | |
} | |
//ToRESTMapper see RESTClientGetter | |
func (c *SimpleRESTClientGetter) ToRESTMapper() (meta.RESTMapper, error) { | |
discoveryClient, err := c.ToDiscoveryClient() | |
if err != nil { | |
return nil, err | |
} | |
mapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) | |
expander := restmapper.NewShortcutExpander(mapper, discoveryClient) | |
return expander, nil | |
} | |
//ToRawKubeConfigLoader see RESTClientGetter | |
func (c *SimpleRESTClientGetter) ToRawKubeConfigLoader() clientcmd.ClientConfig { | |
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() | |
// use the standard defaults for this client command | |
// DEPRECATED: remove and replace with something more accurate | |
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig | |
overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults} | |
overrides.Context.Namespace = c.Namespace | |
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides) | |
} |
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 ( | |
"context" | |
"encoding/base64" | |
"fmt" | |
"log" | |
"os" | |
container "cloud.google.com/go/container/apiv1" | |
"google.golang.org/api/option" | |
containerpb "google.golang.org/genproto/googleapis/container/v1" | |
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | |
"helm.sh/helm/v3/pkg/action" | |
"k8s.io/client-go/rest" | |
) | |
const clusterIdentifierString = "projects/YOURPROJECT/location/YOURREGION/cluster/YOURCLUSTERNAME" | |
func main() { | |
ctx := context.Background() | |
ts, err := getTokenSource() | |
if err != nil { | |
log.Fatalf("failed to create google token source: %+v", err) | |
} | |
c, err := container.NewClusterManagerClient(ctx, option.WithTokenSource(ts)) | |
if err != nil { | |
log.Fatal(err) | |
} | |
req := &containerpb.GetClusterRequest{ | |
Name: clusterIdentifierString, | |
} | |
resp, err := c.GetCluster(ctx, req) | |
if err != nil { | |
log.Fatal(err) | |
} | |
ca, err := base64.StdEncoding.DecodeString(resp.MasterAuth.GetClusterCaCertificate()) | |
config := &rest.Config{ | |
TLSClientConfig: rest.TLSClientConfig{ | |
CAData: ca, | |
}, | |
Host: "https://"+resp.Endpoint, | |
AuthProvider: &clientcmdapi.AuthProviderConfig{ | |
Name: googleAuthPlugin, | |
}, | |
} | |
// this commented code shows that at this point you can use the kube client-go. | |
// clientset, err := kubernetes.NewForConfig(config) | |
// if err != nil { | |
// panic(err.Error()) | |
// } | |
// svcs, err := clientset.CoreV1().Services("").List(ctx, metav1.ListOptions{}) | |
// if err != nil { | |
// panic(err) | |
// } | |
// log.Printf("There are %d servicesin the cluster", len(svcs.Items)) | |
actionConfig := new(action.Configuration) | |
if err := actionConfig.Init(NewRESTClientGetter(config, ""), "", os.Getenv("HELM_DRIVER"), log.Printf); err != nil { | |
log.Printf("%+v", err) | |
os.Exit(1) | |
} | |
client := action.NewList(actionConfig) | |
// Only list deployed | |
client.Deployed = true | |
results, err := client.Run() | |
if err != nil { | |
log.Printf("%+v", err) | |
os.Exit(1) | |
} | |
for _, rel := range results { | |
fmt.Println(rel.Name+" "+rel.Namespace+" "+rel.Info.Status.String()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
credits to:
helm/helm#6910 (comment)
https://gist.github.com/ahmetb/548059cdbf12fb571e4e2f1e29c48997