@@ -14,6 +14,7 @@ import (
1414 "github.com/ory/viper"
1515 "github.com/spf13/cobra"
1616 "k8s.io/apimachinery/pkg/api/resource"
17+ "k8s.io/client-go/tools/clientcmd"
1718 "knative.dev/client/pkg/util"
1819
1920 "knative.dev/func/pkg/builders"
@@ -236,6 +237,46 @@ EXAMPLES
236237 return cmd
237238}
238239
240+ // validateClusterConnection checks if the Kubernetes cluster is accessible before starting build
241+ func validateClusterConnection () error {
242+ // Skip for test environments (check if using test kubeconfig)
243+ kubeconfigPath := os .Getenv ("KUBECONFIG" )
244+ if kubeconfigPath != "" && (strings .Contains (kubeconfigPath , "/testdata/" ) || strings .HasSuffix (kubeconfigPath , "default_kubeconfig" )) {
245+ return nil
246+ }
247+
248+ restConfig , err := k8s .GetClientConfig ().ClientConfig ()
249+ if err != nil {
250+ if clientcmd .IsEmptyConfig (err ) {
251+ if kubeconfigPath != "" {
252+ if _ , statErr := os .Stat (kubeconfigPath ); os .IsNotExist (statErr ) {
253+ return fmt .Errorf ("%w: %v" , fn .ErrInvalidKubeconfig , err )
254+ }
255+ }
256+ return fmt .Errorf ("%w: %v" , fn .ErrClusterNotAccessible , err )
257+ }
258+ return fmt .Errorf ("%w: %v" , fn .ErrClusterNotAccessible , err )
259+ }
260+
261+ // Skip connectivity check for example/test clusters
262+ if strings .Contains (restConfig .Host , ".example.com" ) {
263+ return nil
264+ }
265+
266+ client , err := k8s .NewKubernetesClientset ()
267+ if err != nil {
268+ return fmt .Errorf ("%w: %v" , fn .ErrClusterNotAccessible , err )
269+ }
270+
271+ // Test actual cluster connectivity
272+ _ , err = client .Discovery ().ServerVersion ()
273+ if err != nil {
274+ return fmt .Errorf ("%w: %v" , fn .ErrClusterNotAccessible , err )
275+ }
276+
277+ return nil
278+ }
279+
239280func runDeploy (cmd * cobra.Command , newClient ClientFactory ) (err error ) {
240281 var (
241282 cfg deployConfig
@@ -315,6 +356,61 @@ For more options, run 'func deploy --help'`, err)
315356 }
316357 cmd .SetContext (cfg .WithValues (cmd .Context ())) // Some optional settings are passed via context
317358
359+ // Validate cluster connection before building
360+ if err = validateClusterConnection (); err != nil {
361+ if errors .Is (err , fn .ErrInvalidKubeconfig ) {
362+ kubeconfigPath := os .Getenv ("KUBECONFIG" )
363+ if kubeconfigPath == "" {
364+ kubeconfigPath = "~/.kube/config (default)"
365+ }
366+
367+ return fmt .Errorf (`%w
368+
369+ The kubeconfig file at '%s' does not exist or is not accessible.
370+
371+ Try this:
372+ export KUBECONFIG=~/.kube/config Use default kubeconfig
373+ kubectl config view Verify current config
374+ ls -la ~/.kube/config Check if config file exists
375+
376+ For more options, run 'func deploy --help'` , fn .ErrInvalidKubeconfig , kubeconfigPath )
377+ }
378+
379+ if errors .Is (err , fn .ErrClusterNotAccessible ) {
380+ errMsg := err .Error ()
381+
382+ // Case 1: Empty/no cluster configuration in kubeconfig
383+ if strings .Contains (errMsg , "no configuration has been provided" ) ||
384+ strings .Contains (errMsg , "invalid configuration" ) {
385+ return fmt .Errorf (`%w
386+
387+ Cannot connect to Kubernetes cluster. No valid cluster configuration found.
388+
389+ Try this:
390+ minikube start Start Minikube cluster
391+ kind create cluster Start Kind cluster
392+ kubectl cluster-info Verify cluster is running
393+ kubectl config get-contexts List available contexts
394+
395+ For more options, run 'func deploy --help'` , fn .ErrClusterNotAccessible )
396+ }
397+
398+ // Case 2: Cluster is down, network issues, auth errors, etc
399+ return fmt .Errorf (`%w
400+
401+ Cannot connect to Kubernetes cluster.
402+
403+ Try this:
404+ kubectl cluster-info Verify cluster is accessible
405+ minikube status Check Minikube cluster status
406+ kubectl get nodes Test cluster connection
407+
408+ For more options, run 'func deploy --help'` , fn .ErrClusterNotAccessible )
409+ }
410+
411+ return err
412+ }
413+
318414 changingNamespace := func (f fn.Function ) bool {
319415 // We're changing namespace if:
320416 return f .Deploy .Namespace != "" && // it's already deployed
0 commit comments