@@ -6,151 +6,127 @@ package cmd
66
77import (
88 "context"
9- "fmt"
9+ "os"
10+ "path/filepath"
1011
1112 "github.com/cockroachdb/errors"
13+ kctx "github.com/gitpod-io/gitpod/previewctl/pkg/k8s/context"
14+ "github.com/gitpod-io/gitpod/previewctl/pkg/k8s/context/gke"
15+ "github.com/gitpod-io/gitpod/previewctl/pkg/k8s/context/harvester"
1216 "github.com/sirupsen/logrus"
1317 "github.com/spf13/cobra"
1418 "k8s.io/client-go/tools/clientcmd"
1519 "k8s.io/client-go/tools/clientcmd/api"
20+ "k8s.io/client-go/util/homedir"
1621
17- "github.com/gitpod-io/gitpod/previewctl/pkg/gcloud"
1822 kube "github.com/gitpod-io/gitpod/previewctl/pkg/k8s"
1923)
2024
2125var (
22- serviceAccountPath string
23- kubeConfigSavePath string
26+ DefaultKubeConfigPath = filepath .Join (homedir .HomeDir (), clientcmd .RecommendedHomeDir , clientcmd .RecommendedFileName )
2427)
2528
2629const (
27- coreDevClusterName = "core-dev"
28- coreDevProjectID = "gitpod-core-dev"
29- coreDevClusterZone = "europe-west1-b"
30- coreDevDesiredContextName = "dev"
30+ coreDevClusterName = "core-dev"
31+ coreDevProjectID = "gitpod-core-dev"
32+ coreDevClusterZone = "europe-west1-b"
3133)
3234
3335type getCredentialsOpts struct {
34- gcpClient * gcloud.Config
35- logger * logrus.Logger
36+ logger * logrus.Logger
3637
37- getCredentialsMap map [ string ] func ( ctx context. Context ) ( * api. Config , error )
38- configMap map [ string ] * api. Config
38+ serviceAccountPath string
39+ kubeConfigSavePath string
3940}
4041
4142func newGetCredentialsCommand (logger * logrus.Logger ) * cobra.Command {
42- var err error
43- var client * gcloud.Config
4443 ctx := context .Background ()
4544 opts := & getCredentialsOpts {
46- logger : logger ,
47- configMap : map [string ]* api.Config {},
45+ logger : logger ,
4846 }
4947
48+ setDefaultKubeConfigPath ()
49+
5050 cmd := & cobra.Command {
5151 Use : "get-credentials" ,
5252 Long : `previewctl get-credentials retrieves the kubernetes configs for core-dev and harvester clusters,
5353merges them with the default config, and outputs them either to stdout or to a file.` ,
54- PersistentPreRunE : func (cmd * cobra.Command , args []string ) error {
55- client , err = gcloud . New (ctx , serviceAccountPath )
54+ RunE : func (cmd * cobra.Command , args []string ) error {
55+ configs , err := opts . getCredentials (ctx )
5656 if err != nil {
5757 return err
5858 }
5959
60- opts .gcpClient = client
61- opts .getCredentialsMap = map [string ]func (ctx context.Context ) (* api.Config , error ){
62- "dev" : opts .getCoreDevKubeConfig ,
63- "harvester" : opts .getHarvesterKubeConfig ,
64- }
65-
66- return nil
67- },
68- RunE : func (cmd * cobra.Command , args []string ) error {
69- for _ , kc := range []string {coreDevDesiredContextName , "harvester" } {
70- if ok := hasAccess (logger , kc ); ! ok {
71- config , err := opts.getCredentialsMap [kc ](ctx )
72- if err != nil {
73- return err
74- }
75-
76- opts .configMap [kc ] = config
77- }
78- }
79-
80- return opts .mergeContexts ()
60+ return kube .OutputContext (opts .kubeConfigSavePath , configs )
8161 },
8262 }
8363
84- cmd .PersistentFlags ().StringVar (& serviceAccountPath , "gcp-service-account" , "" , "path to the GCP service account to use" )
85- cmd .PersistentFlags ().StringVar (& kubeConfigSavePath , "kube-save-path" , "" , "path to save the generated kubeconfig to" )
64+ cmd .PersistentFlags ().StringVar (& opts . serviceAccountPath , "gcp-service-account" , "" , "path to the GCP service account to use" )
65+ cmd .PersistentFlags ().StringVar (& opts . kubeConfigSavePath , "kube-save-path" , DefaultKubeConfigPath , "path to save the generated kubeconfig to" )
8666
8767 return cmd
8868}
8969
90- func hasAccess (logger * logrus.Logger , contextName string ) bool {
91- config , err := kube .NewFromDefaultConfigWithContext (logger , contextName )
92- if err != nil {
93- if errors .Is (err , kube .ErrContextNotExists ) {
94- return false
95- }
96-
97- logger .Fatal (err )
98- }
99-
100- return config .HasAccess ()
101- }
102-
103- func (o * getCredentialsOpts ) mergeContexts () error {
104- var err error
105- configs := make ([]* api.Config , 0 , len (o .configMap ))
106-
107- for _ , config := range o .configMap {
108- configs = append (configs , config )
109- }
70+ func (o * getCredentialsOpts ) getCredentials (ctx context.Context ) (* api.Config , error ) {
71+ gkeLoader , err := gke .New (ctx , gke.ConfigLoaderOpts {
72+ Logger : o .logger ,
73+ ServiceAccountPath : o .serviceAccountPath ,
74+ Name : coreDevClusterName ,
75+ ProjectID : coreDevProjectID ,
76+ Zone : coreDevClusterZone ,
77+ RenamedContextName : gke .DevContextName ,
78+ })
11079
111- finalConfig , err := kube .MergeWithDefaultConfig (configs ... )
11280 if err != nil {
113- return err
81+ return nil , errors . Wrap ( err , "failed to instantiate gke loader" )
11482 }
11583
116- if kubeConfigSavePath != "" {
117- return clientcmd .WriteToFile (* finalConfig , kubeConfigSavePath )
84+ loaderMap := map [string ]kctx.Loader {
85+ gke .DevContextName : gkeLoader ,
86+ harvester .ContextName : & harvester.ConfigLoader {},
11887 }
11988
120- bytes , err := clientcmd .Write (* finalConfig )
121- if err != nil {
122- return err
123- }
89+ for _ , contextName := range []string {gke .DevContextName , harvester .ContextName } {
90+ loader := loaderMap [contextName ]
91+ if kc , err := kube .NewFromDefaultConfigWithContext (o .logger , contextName ); err == nil && kc .HasAccess () {
92+ continue
93+ }
12494
125- fmt .Println (string (bytes ))
95+ kc , err := loader .Load (ctx )
96+ if err != nil {
97+ return nil , err
98+ }
12699
127- return err
128- }
100+ configs , err := kube .MergeContextsWithDefault (kc )
101+ if err != nil {
102+ return nil , err
103+ }
129104
130- func (o * getCredentialsOpts ) getCoreDevKubeConfig (ctx context.Context ) (* api.Config , error ) {
131- coreDevConfig , err := o .gcpClient .GenerateConfig (ctx , coreDevClusterName , coreDevProjectID , coreDevClusterZone , coreDevDesiredContextName )
132- if err != nil {
133- return nil , err
105+ // always save the context at the default path
106+ err = kube .OutputContext (DefaultKubeConfigPath , configs )
107+ if err != nil {
108+ return nil , err
109+ }
134110 }
135111
136- return coreDevConfig , nil
112+ return kube . MergeContextsWithDefault ()
137113}
138114
139- func ( o * getCredentialsOpts ) getHarvesterKubeConfig ( ctx context. Context ) ( * api. Config , error ) {
140- coreDevClientConfig , err := clientcmd . NewNonInteractiveClientConfig ( * o . configMap [ coreDevDesiredContextName ], coreDevDesiredContextName , nil , nil ). ClientConfig ( )
115+ func hasAccess ( logger * logrus. Logger , contextName string ) bool {
116+ config , err := kube . NewFromDefaultConfigWithContext ( logger , contextName )
141117 if err != nil {
142- return nil , err
143- }
118+ if errors .Is (err , kube .ErrContextNotExists ) {
119+ return false
120+ }
144121
145- kubeConfig , err := kube .NewWithConfig (o .logger , coreDevClientConfig )
146- if err != nil {
147- return nil , err
122+ logger .Fatal (err )
148123 }
149124
150- harvesterConfig , err := kubeConfig .GetHarvesterKubeConfig (ctx )
151- if err != nil {
152- return nil , err
153- }
125+ return config .HasAccess ()
126+ }
154127
155- return harvesterConfig , nil
128+ func setDefaultKubeConfigPath () {
129+ if v := os .Getenv ("KUBECONFIG" ); v != "" {
130+ DefaultKubeConfigPath = v
131+ }
156132}
0 commit comments