-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
settings.go
169 lines (139 loc) · 4.81 KB
/
settings.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
Copyright 2019 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubeconfig
import (
"os"
"path/filepath"
"sync/atomic"
"github.com/juju/mutex/v2"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/clientcmd/api"
"k8s.io/klog/v2"
"k8s.io/minikube/pkg/util/lock"
)
// Settings is the minikubes settings for kubeconfig
type Settings struct {
// The name of the cluster for this context
ClusterName string
// The name of the namespace for this context
Namespace string
// ClusterServerAddress is the address of the Kubernetes cluster
ClusterServerAddress string
// ClientCertificate is the path to a client cert file for TLS.
ClientCertificate string
// CertificateAuthority is the path to a cert file for the certificate authority.
CertificateAuthority string
// ClientKey is the path to a client key file for TLS.
ClientKey string
// Should the current context be kept when setting up this one
KeepContext bool
// Should the certificate files be embedded instead of referenced by path
EmbedCerts bool
// Extension meta data for the cluster
ExtensionCluster *Extension
// Extension meta data for the cluster
ExtensionContext *Extension
// kubeConfigFile is the path where the kube config is stored
// Only access this with atomic ops
kubeConfigFile atomic.Value
}
// SetPath sets the setting for kubeconfig filepath
func (k *Settings) SetPath(kubeConfigFile string) {
k.kubeConfigFile.Store(kubeConfigFile)
}
// filePath gets the kubeconfig file
func (k *Settings) filePath() string {
return k.kubeConfigFile.Load().(string)
}
// PopulateFromSettings populates an api.Config object with values from *Settings
func PopulateFromSettings(cfg *Settings, apiCfg *api.Config) error {
var err error
clusterName := cfg.ClusterName
cluster := api.NewCluster()
cluster.Server = cfg.ClusterServerAddress
if cfg.EmbedCerts {
cluster.CertificateAuthorityData, err = os.ReadFile(cfg.CertificateAuthority)
if err != nil {
return errors.Wrapf(err, "reading CertificateAuthority %s", cfg.CertificateAuthority)
}
} else {
cluster.CertificateAuthority = cfg.CertificateAuthority
}
if cfg.ExtensionCluster != nil {
cluster.Extensions = map[string]runtime.Object{"cluster_info": cfg.ExtensionCluster.DeepCopy()}
}
apiCfg.Clusters[clusterName] = cluster
// user
userName := cfg.ClusterName
user := api.NewAuthInfo()
if cfg.EmbedCerts {
user.ClientCertificateData, err = os.ReadFile(cfg.ClientCertificate)
if err != nil {
return errors.Wrapf(err, "reading ClientCertificate %s", cfg.ClientCertificate)
}
user.ClientKeyData, err = os.ReadFile(cfg.ClientKey)
if err != nil {
return errors.Wrapf(err, "reading ClientKey %s", cfg.ClientKey)
}
} else {
user.ClientCertificate = cfg.ClientCertificate
user.ClientKey = cfg.ClientKey
}
apiCfg.AuthInfos[userName] = user
// context
contextName := cfg.ClusterName
context := api.NewContext()
context.Cluster = cfg.ClusterName
context.Namespace = cfg.Namespace
context.AuthInfo = userName
if cfg.ExtensionContext != nil {
context.Extensions = map[string]runtime.Object{"context_info": cfg.ExtensionContext.DeepCopy()}
}
apiCfg.Contexts[contextName] = context
// Only set current context to minikube if the user has not used the keepContext flag
if !cfg.KeepContext {
apiCfg.CurrentContext = cfg.ClusterName
}
return nil
}
// Update reads config from disk, adds the minikube settings, and writes it back.
// activeContext is true when minikube is the CurrentContext
// If no CurrentContext is set, the given name will be used.
func Update(kcs *Settings) error {
spec := lock.PathMutexSpec(filepath.Join(kcs.filePath(), "settings.Update"))
klog.Infof("acquiring lock: %+v", spec)
releaser, err := mutex.Acquire(spec)
if err != nil {
return errors.Wrapf(err, "unable to acquire lock for %+v", spec)
}
defer releaser.Release()
// read existing config or create new if does not exist
klog.Infoln("Updating kubeconfig: ", kcs.filePath())
kcfg, err := readOrNew(kcs.filePath())
if err != nil {
return err
}
ext := NewExtension()
kcs.ExtensionCluster = ext
kcs.ExtensionContext = ext
err = PopulateFromSettings(kcs, kcfg)
if err != nil {
return err
}
// write back to disk
if err := writeToFile(kcfg, kcs.filePath()); err != nil {
return errors.Wrap(err, "writing kubeconfig")
}
return nil
}