From 8d5a7cc6648c3b6129da6206ceda8bad83d7c81c Mon Sep 17 00:00:00 2001 From: Simon Bein Date: Wed, 7 Jan 2026 11:38:23 +0100 Subject: [PATCH] enhance error message on no current context --- cmd/api-syncagent/main.go | 6 ++-- internal/kubeconfig/check.go | 36 +++++++++++++++++++ internal/kubeconfig/check_test.go | 60 +++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 internal/kubeconfig/check.go create mode 100644 internal/kubeconfig/check_test.go diff --git a/cmd/api-syncagent/main.go b/cmd/api-syncagent/main.go index 708449a..fa6372a 100644 --- a/cmd/api-syncagent/main.go +++ b/cmd/api-syncagent/main.go @@ -22,7 +22,6 @@ import ( "fmt" golog "log" "slices" - "strings" "github.com/go-logr/zapr" "github.com/spf13/pflag" @@ -32,6 +31,7 @@ import ( "github.com/kcp-dev/api-syncagent/internal/controller/apiexport" "github.com/kcp-dev/api-syncagent/internal/controller/apiresourceschema" "github.com/kcp-dev/api-syncagent/internal/controller/syncmanager" + "github.com/kcp-dev/api-syncagent/internal/kubeconfig" syncagentlog "github.com/kcp-dev/api-syncagent/internal/log" "github.com/kcp-dev/api-syncagent/internal/version" syncagentv1alpha1 "github.com/kcp-dev/api-syncagent/sdk/apis/syncagent/v1alpha1" @@ -108,8 +108,8 @@ func run(ctx context.Context, log *zap.SugaredLogger, opts *Options) error { } // sanity check - if !strings.Contains(kcpRestConfig.Host, "/clusters/") { - return fmt.Errorf("kcp kubeconfig does not point to a specific workspace") + if err := kubeconfig.Validate(kcpRestConfig); err != nil { + return fmt.Errorf("failed to check kcp kubeconfig: %w", err) } // We check if the APIExport/APIExportEndpointSlice exists and extract information we need to set up our kcpCluster. diff --git a/internal/kubeconfig/check.go b/internal/kubeconfig/check.go new file mode 100644 index 0000000..21e9050 --- /dev/null +++ b/internal/kubeconfig/check.go @@ -0,0 +1,36 @@ +/* +Copyright 2025 The KCP Authors. + +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 ( + "errors" + "strings" + + "k8s.io/client-go/rest" +) + +func Validate(c *rest.Config) error { + if c == nil { + return errors.New("no kubeconfig was found. Have you set current-context?") + } + + if !strings.Contains(c.Host, "/clusters/") { + return errors.New("kcp kubeconfig does not point to a specific workspace") + } + + return nil +} diff --git a/internal/kubeconfig/check_test.go b/internal/kubeconfig/check_test.go new file mode 100644 index 0000000..3d078aa --- /dev/null +++ b/internal/kubeconfig/check_test.go @@ -0,0 +1,60 @@ +/* +Copyright 2025 The KCP Authors. + +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 ( + "testing" + + "k8s.io/client-go/rest" +) + +func TestValidate(t *testing.T) { + tests := []struct { + name string + kubeconfig *rest.Config + expErr bool + }{ + { + name: "nil kubeconfig", + kubeconfig: nil, + expErr: true, + }, + { + name: "kubeconfig without workspace", + kubeconfig: &rest.Config{ + Host: "https://example.com", + }, + expErr: true, + }, + { + name: "valid kcp kubeconfig", + kubeconfig: &rest.Config{ + Host: "https://example.com/clusters/foo", + }, + expErr: false, + }, + } + + for _, testcase := range tests { + t.Run(testcase.name, func(t *testing.T) { + err := Validate(testcase.kubeconfig) + if (err != nil) != testcase.expErr { + t.Errorf("Expected error %v, got %v", testcase.expErr, err) + } + }) + } +}