github.com/shipa-corp/ketch@v0.6.0/cmd/ketch/configuration/configuration.go (about) 1 package configuration 2 3 import ( 4 "log" 5 "os" 6 "path/filepath" 7 8 "github.com/BurntSushi/toml" 9 "k8s.io/apimachinery/pkg/runtime" 10 "k8s.io/cli-runtime/pkg/genericclioptions" 11 "k8s.io/client-go/dynamic" 12 "k8s.io/client-go/kubernetes" 13 clientgoscheme "k8s.io/client-go/kubernetes/scheme" 14 cmdutil "k8s.io/kubectl/pkg/cmd/util" 15 "sigs.k8s.io/controller-runtime/pkg/client" 16 17 ketchv1 "github.com/shipa-corp/ketch/internal/api/v1beta1" 18 "github.com/shipa-corp/ketch/internal/controllers" 19 "github.com/shipa-corp/ketch/internal/templates" 20 ) 21 22 var ( 23 scheme = runtime.NewScheme() 24 ) 25 26 func init() { 27 _ = clientgoscheme.AddToScheme(scheme) 28 _ = ketchv1.AddToScheme()(scheme) 29 } 30 31 // Configuration provides methods to get initialized clients. 32 type Configuration struct { 33 cli client.Client 34 storage *templates.Storage 35 } 36 37 // KetchConfig contains all the values present in the config.toml 38 type KetchConfig struct { 39 AdditionalBuilders []AdditionalBuilder `toml:"additional-builders,omitempty"` 40 DefaultBuilder string `toml:"default-builder,omitempty"` 41 } 42 43 // AdditionalBuilder contains the information of any user added builders 44 type AdditionalBuilder struct { 45 Vendor string `toml:"vendor" json:"vendor" yaml:"vendor"` 46 Image string `toml:"image" json:"image" yaml:"image"` 47 Description string `toml:"description" json:"description" yaml:"description"` 48 } 49 50 // Client returns initialized controller-runtime's Client to perform CRUD operations on Kubernetes objects. 51 func (cfg *Configuration) Client() client.Client { 52 if cfg.cli != nil { 53 return cfg.cli 54 } 55 configFlags := genericclioptions.NewConfigFlags(true) 56 factory := cmdutil.NewFactory(configFlags) 57 kubeCfg, err := factory.ToRESTConfig() 58 if err != nil { 59 log.Fatalf("failed to create kubernetes client: %v", err) 60 } 61 cfg.cli, err = client.New(kubeCfg, client.Options{Scheme: scheme}) 62 if err != nil { 63 log.Fatalf("failed to create kubernetes client: %v", err) 64 } 65 return cfg.cli 66 } 67 68 // KubernetesClient returns kubernetes typed client. It's used to work with standard kubernetes types. 69 func (cfg *Configuration) KubernetesClient() kubernetes.Interface { 70 configFlags := genericclioptions.NewConfigFlags(true) 71 factory := cmdutil.NewFactory(configFlags) 72 kubeCfg, err := factory.ToRESTConfig() 73 if err != nil { 74 log.Fatalf("failed to create kubernetes client: %v", err) 75 } 76 clientset, err := kubernetes.NewForConfig(kubeCfg) 77 if err != nil { 78 log.Fatalf("failed to create kubernetes client: %v", err) 79 } 80 return clientset 81 } 82 83 // Client returns initialized templates.Client to perform CRUD operations on templates. 84 func (cfg *Configuration) Storage() templates.Client { 85 if cfg.storage != nil { 86 return cfg.storage 87 } 88 cfg.storage = templates.NewStorage(cfg.Client(), controllers.KetchNamespace) 89 return cfg.storage 90 } 91 92 // DynamicClient returns kubernetes dynamic client. It's used to work with CRDs for which we don't have go types like ClusterIssuer. 93 func (cfg *Configuration) DynamicClient() dynamic.Interface { 94 flags := genericclioptions.NewConfigFlags(true) 95 factory := cmdutil.NewFactory(flags) 96 conf, err := factory.ToRESTConfig() 97 if err != nil { 98 log.Fatalf("failed to create kubernetes client: %v", err) 99 } 100 i, err := dynamic.NewForConfig(conf) 101 if err != nil { 102 log.Fatalf("failed to create kubernetes client: %v", err) 103 } 104 return i 105 } 106 107 // DefaultConfigPath returns the path to the config.toml file 108 func DefaultConfigPath() (string, error) { 109 home, err := ketchHome() 110 if err != nil { 111 return "", err 112 } 113 return filepath.Join(home, "config.toml"), nil 114 } 115 116 func ketchHome() (string, error) { 117 ketchHome := os.Getenv("KETCH_HOME") 118 if ketchHome == "" { 119 home, err := os.UserHomeDir() 120 if err != nil { 121 return "", err 122 } 123 ketchHome = filepath.Join(home, ".ketch") 124 } 125 return ketchHome, nil 126 } 127 128 // Read returns a Configuration containing the unmarshalled config.toml file contents 129 func Read(path string) KetchConfig { 130 var ketchConfig KetchConfig 131 132 _, err := toml.DecodeFile(path, &ketchConfig) 133 if err != nil && !os.IsNotExist(err) { 134 return KetchConfig{} 135 } 136 return ketchConfig 137 } 138 139 //Write writes the provided KetchConfig to the given path. In the event the path is not found it will be created 140 func Write(ketchConfig KetchConfig, path string) error { 141 if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil { 142 return err 143 } 144 w, err := os.Create(path) 145 if err != nil { 146 return err 147 } 148 defer w.Close() 149 150 return toml.NewEncoder(w).Encode(ketchConfig) 151 }