Skip to content

Commit b342348

Browse files
authored
Check-context-name (#313)
* added checks to kubeconfig access * better print of kube context * protect against non-existing kube contexts
1 parent 3969f36 commit b342348

File tree

8 files changed

+86
-57
lines changed

8 files changed

+86
-57
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Changelog:
22

3-
* Fixed cluster-add script
3+
* Protect against invalid kube context

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION=v0.0.289
1+
VERSION=v0.0.290
22

33
OUT_DIR=dist
44
YEAR?=$(shell date +"%Y")

cmd/commands/common.go

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import (
3636

3737
"github.com/manifoldco/promptui"
3838
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
39-
"k8s.io/client-go/tools/clientcmd"
4039

4140
"github.com/spf13/cobra"
4241
"github.com/spf13/pflag"
@@ -163,7 +162,7 @@ func getRepoFromUserInput(cmd *cobra.Command) error {
163162
func ensureRuntimeName(ctx context.Context, args []string) (string, error) {
164163
var (
165164
runtimeName string
166-
err error
165+
err error
167166
)
168167

169168
if len(args) > 0 {
@@ -379,6 +378,10 @@ func ensureKubeContextName(flag *pflag.Flag) (string, error) {
379378
func getKubeContextName(flag *pflag.Flag) (string, error) {
380379
contextName := flag.Value.String()
381380
if contextName != "" {
381+
if !util.CheckExistingContext(contextName) {
382+
return "", fmt.Errorf("kubeconfig file missing context \"%s\"", contextName)
383+
}
384+
382385
return contextName, nil
383386
}
384387

@@ -393,36 +396,24 @@ func getKubeContextName(flag *pflag.Flag) (string, error) {
393396
return contextName, flag.Value.Set(contextName)
394397
}
395398

396-
func getKubeContextNameFromUserSelect() (string, error) {
397-
configAccess := clientcmd.NewDefaultPathOptions()
398-
conf, err := configAccess.GetStartingConfig()
399-
if err != nil {
400-
return "", err
401-
}
402-
403-
contextsList := conf.Contexts
404-
currentContext := conf.CurrentContext
405-
contextsNamesToShowUser := []string{currentContext + " (current)"}
406-
contextsIndex := []string{currentContext}
407-
408-
for key := range contextsList {
409-
if key == currentContext {
410-
continue
411-
}
412-
413-
contextsIndex = append(contextsIndex, key)
414-
contextsNamesToShowUser = append(contextsNamesToShowUser, key)
415-
}
399+
type SelectItem struct {
400+
Value string
401+
Label string
402+
}
416403

404+
func getKubeContextNameFromUserSelect() (string, error) {
405+
contexts := util.KubeContexts()
417406
templates := &promptui.SelectTemplates{
418-
Selected: "{{ . | yellow }} ",
407+
Active: "▸ {{ .Name }} {{if .Current }}(current){{end}}",
408+
Inactive: " {{ .Name }} {{if .Current }}(current){{end}}",
409+
Selected: "{{ .Name | yellow }}",
419410
}
420411

421412
labelStr := fmt.Sprintf("%vSelect kube context%v", CYAN, COLOR_RESET)
422413

423414
prompt := promptui.Select{
424415
Label: labelStr,
425-
Items: contextsNamesToShowUser,
416+
Items: contexts,
426417
Templates: templates,
427418
}
428419

@@ -431,7 +422,7 @@ func getKubeContextNameFromUserSelect() (string, error) {
431422
return "", err
432423
}
433424

434-
return contextsIndex[index], nil
425+
return contexts[index].Name, nil
435426
}
436427

437428
func validateIngressHost(ingressHost string) error {

cmd/commands/runtime.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ func runtimeInstallPreparations(opts *RuntimeInstallOptions) (*runtime.Runtime,
738738
return nil, "", fmt.Errorf("failed to download runtime definition: %w", err)
739739
}
740740

741-
server, err := util.CurrentServer()
741+
server, err := util.KubeCurrentServer()
742742
handleCliStep(reporter.InstallStepGetServerAddress, "Getting current server address", err, false, true)
743743
if err != nil {
744744
return nil, "", fmt.Errorf("failed to get current server address: %w", err)

docs/releases/release_notes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ cf version
2323

2424
```bash
2525
# download and extract the binary
26-
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.0.289/cf-linux-amd64.tar.gz | tar zx
26+
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.0.290/cf-linux-amd64.tar.gz | tar zx
2727

2828
# move the binary to your $PATH
2929
mv ./cf-linux-amd64 /usr/local/bin/cf
@@ -36,7 +36,7 @@ cf version
3636

3737
```bash
3838
# download and extract the binary
39-
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.0.289/cf-darwin-amd64.tar.gz | tar zx
39+
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.0.290/cf-darwin-amd64.tar.gz | tar zx
4040

4141
# move the binary to your $PATH
4242
mv ./cf-darwin-amd64 /usr/local/bin/cf

manifests/add-cluster/helm/values.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@ serviceAccountName: argocd-manager
55
# example https://some.domain.name
66
ingressUrl: <ingressUrl>
77

8-
# csdpToken is used to authenticate against the app-proxy
9-
#
8+
# csdpToken is the user's Personal Access Token
109
csdpToken: <csdpToken>
1110

1211
# contextName is the name of the kube context (in the local kubeconfig file) that connects to the target cluster
1312
contextName: <contextName>
1413

15-
# server is the
14+
# server is the k8s cluster API endpoint url
1615
# can be obtained by
1716
# CONTEXT_NAME=<TARGET_CONTEXT_NAME>
1817
# CLUSTER_NAME=$(kubectl config view --raw --flatten -o jsonpath='{.contexts[?(@.name == "'"${CONTEXT_NAME}"'")].context.cluster}')

manifests/runtime.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ metadata:
55
namespace: "{{ namespace }}"
66
spec:
77
defVersion: 1.0.1
8-
version: 0.0.289
8+
version: 0.0.290
99
bootstrapSpecifier: github.com/codefresh-io/cli-v2/manifests/argo-cd
1010
components:
1111
- name: events

pkg/util/util.go

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"os"
2121
"os/signal"
2222
"regexp"
23+
"sort"
2324
"strings"
2425
"sync"
2526
"time"
@@ -30,6 +31,7 @@ import (
3031
"github.com/codefresh-io/cli-v2/pkg/store"
3132

3233
"k8s.io/client-go/tools/clientcmd"
34+
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
3335
)
3436

3537
const (
@@ -161,34 +163,63 @@ func EscapeAppsetFieldName(field string) string {
161163
return appsetFieldRegexp.ReplaceAllString(field, "_")
162164
}
163165

164-
func CurrentContext() (string, error) {
166+
func kubeConfig() *clientcmdapi.Config {
165167
configAccess := clientcmd.NewDefaultPathOptions()
166168
conf, err := configAccess.GetStartingConfig()
167-
if err != nil {
168-
return "", err
169-
}
169+
Die(err, "failed reading kubeconfig file")
170+
return conf
171+
}
170172

171-
return conf.CurrentContext, nil
173+
type kubeContext struct {
174+
Name string
175+
Current bool
172176
}
173177

174-
func CurrentServer() (string, error) {
175-
configAccess := clientcmd.NewDefaultPathOptions()
176-
conf, err := configAccess.GetStartingConfig()
177-
if err != nil {
178-
return "", err
178+
func KubeContexts() []kubeContext {
179+
conf := kubeConfig()
180+
contexts := make([]kubeContext, len(conf.Contexts))
181+
i := 0
182+
for key := range conf.Contexts {
183+
contexts[i] = kubeContext{
184+
Name: key,
185+
Current: key == conf.CurrentContext,
186+
}
187+
i += 1
179188
}
180189

181-
currentContext := conf.Contexts[conf.CurrentContext]
182-
return conf.Clusters[currentContext.Cluster].Server, nil
190+
sort.SliceStable(contexts, func(i, j int) bool {
191+
c1 := contexts[i]
192+
if c1.Current {
193+
return true
194+
}
195+
196+
c2 := contexts[j]
197+
if c2.Current {
198+
return true
199+
}
200+
201+
return c1.Name < c2.Name
202+
})
203+
204+
return contexts
183205
}
184206

185-
func KubeContextNameByServer(server string) (string, error) {
186-
configAccess := clientcmd.NewDefaultPathOptions()
187-
conf, err := configAccess.GetStartingConfig()
188-
if err != nil {
189-
return "", err
207+
func CheckExistingContext(contextName string) bool {
208+
for _, context := range KubeContexts() {
209+
if context.Name == contextName {
210+
return true
211+
}
190212
}
191213

214+
return false
215+
}
216+
217+
func KubeCurrentServer() (string, error) {
218+
return KubeServerByContextName("")
219+
}
220+
221+
func KubeContextNameByServer(server string) (string, error) {
222+
conf := kubeConfig()
192223
for contextName, context := range conf.Contexts {
193224
if cluster, ok := conf.Clusters[context.Cluster]; ok {
194225
if cluster.Server == server {
@@ -201,14 +232,22 @@ func KubeContextNameByServer(server string) (string, error) {
201232
}
202233

203234
func KubeServerByContextName(contextName string) (string, error) {
204-
configAccess := clientcmd.NewDefaultPathOptions()
205-
conf, err := configAccess.GetStartingConfig()
206-
if err != nil {
207-
return "", err
235+
conf := kubeConfig()
236+
if contextName == "" {
237+
contextName = conf.CurrentContext
238+
}
239+
240+
context := conf.Contexts[contextName]
241+
if context == nil {
242+
return "", fmt.Errorf("kubeconfig file missing context \"%s\"", contextName)
243+
}
244+
245+
cluster := conf.Clusters[context.Cluster]
246+
if cluster == nil {
247+
return "", fmt.Errorf("kubeconfig file missing cluster \"%s\"", context.Cluster)
208248
}
209249

210-
currentContext := conf.Contexts[contextName]
211-
return conf.Clusters[currentContext.Cluster].Server, nil
250+
return cluster.Server, nil
212251
}
213252

214253
func DecorateErrorWithDocsLink(err error, link ...string) error {

0 commit comments

Comments
 (0)