@@ -5,8 +5,10 @@ import (
55 "encoding/json"
66 "fmt"
77 "os"
8+ "slices"
89
910 infrastructure "github.com/ninech/apis/infrastructure/v1alpha1"
11+ "github.com/ninech/nctl/internal/cli"
1012 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1113 "k8s.io/apimachinery/pkg/runtime"
1214 "k8s.io/client-go/tools/clientcmd"
@@ -97,7 +99,7 @@ func readExtension(kubeconfigContent []byte, contextName string) (*Extension, er
9799 }
98100 context , exists := kubeconfig .Contexts [contextName ]
99101 if ! exists {
100- return nil , fmt . Errorf ( "could not find context %q in kubeconfig" , contextName )
102+ return nil , contextNotFoundError ( contextName , kubeconfig . Contexts )
101103 }
102104 extension , exists := context .Extensions [NctlExtensionContext ]
103105 if ! exists {
@@ -127,7 +129,7 @@ func SetContextOrganization(kubeconfigPath string, contextName string, organizat
127129 }
128130 context , exists := kubeconfig .Contexts [contextName ]
129131 if ! exists {
130- return fmt . Errorf ( "could not find context %q in kubeconfig" , contextName )
132+ return contextNotFoundError ( contextName , kubeconfig . Contexts )
131133 }
132134 extension , exists := context .Extensions [NctlExtensionContext ]
133135 if ! exists {
@@ -164,7 +166,7 @@ func SetContextProject(kubeconfigPath string, contextName string, project string
164166 }
165167 context , exists := kubeconfig .Contexts [contextName ]
166168 if ! exists {
167- return fmt . Errorf ( "could not find context %q in kubeconfig" , contextName )
169+ return contextNotFoundError ( contextName , kubeconfig . Contexts )
168170 }
169171 context .Namespace = project
170172 return clientcmd .WriteToFile (* kubeconfig , kubeconfigPath )
@@ -178,7 +180,7 @@ func RemoveClusterFromKubeConfig(kubeconfigPath, clusterContext string) error {
178180 }
179181
180182 if _ , ok := kubeconfig .Clusters [clusterContext ]; ! ok {
181- return fmt . Errorf ( "could not find cluster %q in kubeconfig" , clusterContext )
183+ return clusterNotFoundError ( clusterContext , kubeconfig . Clusters )
182184 }
183185
184186 delete (kubeconfig .Clusters , clusterContext )
@@ -194,3 +196,36 @@ func RemoveClusterFromKubeConfig(kubeconfigPath, clusterContext string) error {
194196func ContextName (cluster * infrastructure.KubernetesCluster ) string {
195197 return fmt .Sprintf ("%s/%s" , cluster .Name , cluster .Namespace )
196198}
199+
200+ // contextNotFoundError returns an error with available contexts listed.
201+ func contextNotFoundError [T any ](contextName string , contexts map [string ]T ) error {
202+ available := make ([]string , 0 , len (contexts ))
203+ for name := range contexts {
204+ available = append (available , name )
205+ }
206+ slices .Sort (available )
207+
208+ return cli .ErrorWithContext (fmt .Errorf ("could not find context %q in kubeconfig" , contextName )).
209+ WithExitCode (cli .ExitUsageError ).
210+ WithAvailable (available ... ).
211+ WithSuggestions (
212+ "List available contexts: kubectl config get-contexts" ,
213+ "Login to the API: nctl auth login" ,
214+ )
215+ }
216+
217+ // clusterNotFoundError returns an error with available clusters listed.
218+ func clusterNotFoundError [T any ](clusterName string , clusters map [string ]T ) error {
219+ available := make ([]string , 0 , len (clusters ))
220+ for name := range clusters {
221+ available = append (available , name )
222+ }
223+ slices .Sort (available )
224+
225+ return cli .ErrorWithContext (fmt .Errorf ("could not find cluster %q in kubeconfig" , clusterName )).
226+ WithExitCode (cli .ExitUsageError ).
227+ WithAvailable (available ... ).
228+ WithSuggestions (
229+ "List available clusters: kubectl config get-clusters" ,
230+ )
231+ }
0 commit comments