kubeconfig pkg for loading/parsing

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
Ahmet Alp Balkan 2020-04-12 12:59:20 -07:00
parent 21d0a6aeeb
commit 94664bcaf9
No known key found for this signature in database
GPG Key ID: 441833503E604E2C
4 changed files with 85 additions and 4 deletions

View File

@ -6,8 +6,34 @@ import (
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
"github.com/ahmetb/kubectx/cmd/kubectx/kubeconfig"
)
type defaultKubeconfigLoader struct{}
type kubeconfigFile struct { *os.File }
func (kf *kubeconfigFile) Reset() error {
if err := kf.Truncate(0);err!= nil {
return errors.Wrap(err, "failed to truncate file")
}
_, err := kf.Seek(0,0)
return errors.Wrap(err, "failed to seek in file")
}
func (defaultKubeconfigLoader) Load() (kubeconfig.ReadWriteResetCloser, error) {
cfgPath, err := kubeconfigPath()
if err != nil {
return nil, errors.Wrap(err, "cannot determine kubeconfig path")
}
f, err := os.OpenFile(cfgPath, os.O_RDWR, 0)
if err != nil {
return nil, errors.Wrap(err, "failed to open file")
}
return &kubeconfigFile{f}, nil
}
func kubeconfigPath() (string, error) {
// KUBECONFIG env var
if v := os.Getenv("KUBECONFIG"); v != "" {
@ -40,11 +66,10 @@ func homeDir() string {
return home
}
// TODO parseKubeconfig doesn't seem necessary when there's a raw version that returns what's needed
func parseKubeconfig(path string) (kubeconfig, error) {
func parseKubeconfig(path string) (kubeconfigContents, error) {
// TODO refactor to accept io.Reader instead of file
var v kubeconfig
var v kubeconfigContents
f, err := os.Open(path)
if err != nil {

View File

@ -0,0 +1,55 @@
package kubeconfig
import (
"io"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
)
type ReadWriteResetCloser interface{
io.ReadWriteCloser
// Reset truncates the file and seeks to the beginning of the file.
Reset() error
}
type Loader interface {
Load() (ReadWriteResetCloser, error)
}
type Kubeconfig struct {
loader Loader
f ReadWriteResetCloser
rootNode *yaml.Node
}
func (k *Kubeconfig) WithLoader(l Loader) {
k.loader = l
}
func (k *Kubeconfig) ParseRaw() (*yaml.Node, error) {
f, err := k.loader.Load()
if err != nil {
return nil, errors.Wrap(err, "failed to load kubeconfig")
}
k.f = f
var v yaml.Node
if err := yaml.NewDecoder(f).Decode(&v); err != nil {
return nil, errors.Wrap(err, "failed to decode kubeconfig")
}
k.rootNode = v.Content[0]
return k. rootNode, nil
}
func (k *Kubeconfig) Save() error {
if err := k.f.Reset(); err != nil {
return errors.Wrap(err, "failed to reset file")
}
enc := yaml.NewEncoder(k.f)
enc.SetIndent(2)
return enc.Encode(k.rootNode)
}

View File

@ -9,6 +9,7 @@ import (
)
func parseKubeconfigRaw(r io.Reader) (*yaml.Node, error) {
// TODO DELETE
var v yaml.Node
if err := yaml.NewDecoder(r).Decode(&v); err != nil {
return nil, err

View File

@ -13,7 +13,7 @@ type context struct {
Name string `yaml:"name"`
}
type kubeconfig struct {
type kubeconfigContents struct {
APIVersion string `yaml:"apiVersion"`
CurrentContext string `yaml:"current-context"`
Contexts []context `yaml:"contexts"`