diff --git a/cmd/minikube/cmd/tunnel.go b/cmd/minikube/cmd/tunnel.go index 8fdcae40a6e1..7639bdfacb19 100644 --- a/cmd/minikube/cmd/tunnel.go +++ b/cmd/minikube/cmd/tunnel.go @@ -20,16 +20,23 @@ import ( "context" "os" "os/signal" + "path/filepath" + "runtime" + "strconv" "time" "github.com/golang/glog" "github.com/spf13/cobra" "github.com/spf13/viper" + + "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" + "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/tunnel" + "k8s.io/minikube/pkg/minikube/tunnel/kic" ) var cleanup bool @@ -69,6 +76,23 @@ var tunnelCmd = &cobra.Command{ exit.WithError("error creating clientset", err) } + cfg, err := config.Load(viper.GetString(config.MachineProfile)) + if err != nil { + exit.WithError("Error getting config", err) + } + + if runtime.GOOS == "darwin" && cfg.VMDriver == "docker" { + // do not ignore error + port, _ := oci.HostPortBinding("docker", "minikube", 22) + sshPort := strconv.Itoa(port) + sshKey := filepath.Join(localpath.MiniPath(), "machines", cfg.Name, "id_rsa") + + kicTunnel := kic.NewTunnel(sshPort, sshKey, clientset.CoreV1()) + kicTunnel.Start() + + return + } + ctrlC := make(chan os.Signal, 1) signal.Notify(ctrlC, os.Interrupt) ctx, cancel := context.WithCancel(context.Background()) @@ -77,10 +101,6 @@ var tunnelCmd = &cobra.Command{ cancel() }() - cfg, err := config.Load(viper.GetString(config.MachineProfile)) - if err != nil { - exit.WithError("Error getting config", err) - } done, err := manager.StartTunnel(ctx, cfg.Name, api, config.DefaultLoader, clientset.CoreV1()) if err != nil { exit.WithError("error starting tunnel", err) diff --git a/pkg/minikube/tunnel/kic/tunnel.go b/pkg/minikube/tunnel/kic/tunnel.go new file mode 100644 index 000000000000..d538e4fd8a3c --- /dev/null +++ b/pkg/minikube/tunnel/kic/tunnel.go @@ -0,0 +1,71 @@ +package kic + +import ( + "fmt" + "os/exec" + "time" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + typed_core "k8s.io/client-go/kubernetes/typed/core/v1" +) + +// Tunnel ... +type Tunnel struct { + sshPort string + sshKey string + v1Core typed_core.CoreV1Interface +} + +// NewTunnel ... +func NewTunnel(sshPort, sshKey string, v1Core typed_core.CoreV1Interface) *Tunnel { + return &Tunnel{ + sshPort: sshPort, + sshKey: sshKey, + v1Core: v1Core, + } +} + +// Start ... +func (t *Tunnel) Start() error { + for { + services, err := t.v1Core.Services("").List(metav1.ListOptions{}) + if err != nil { + // do I return error, or log and continue? + return err + } + + for _, s := range services.Items { + if s.Spec.Type == v1.ServiceTypeLoadBalancer { + t.createTunnel(s.Name, s.Spec.ClusterIP, s.Spec.Ports) + } + } + + // which time to use? + time.Sleep(10 * time.Second) + } +} + +func (t *Tunnel) createTunnel(name, clusterIP string, ports []v1.ServicePort) { + sshArgs := []string{ + "-N", + "docker@127.0.0.1", + "-p", t.sshPort, + "-i", t.sshKey, + } + + for _, port := range ports { + arg := fmt.Sprintf( + "-L %d:%s:%d", + port.Port, + clusterIP, + port.Port, + ) + + sshArgs = append(sshArgs, arg) + } + + cmd := exec.Command("ssh", sshArgs...) + err := cmd.Run() + fmt.Println(err) +}