diff --git a/CHANGELOG.md b/CHANGELOG.md index 89d01b57b1..df70336d01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,13 +82,16 @@ Thank you to our contributors for this release! ## Version 1.15.1 - 2020-11-16 -Feature: +Features: + * Add Support for driver name alias [#9672](https://github.com/kubernetes/minikube/pull/9672) -Bug fix: +Bug fixes: + * less verbose language selector [#9715](https://github.com/kubernetes/minikube/pull/9715) Thank you to our contributors for this release! + - Ben Leggett - Medya Ghazizadeh - Priya Wadhwa @@ -96,7 +99,6 @@ Thank you to our contributors for this release! - Sharif Elgamal - Vasilyev, Viacheslav - ## Version 1.15.0 - 2020-11-13 Features: @@ -127,7 +129,7 @@ Minor Improvements: * Improving log message when profile not found [#9613](https://github.com/kubernetes/minikube/pull/9613) * Upgrade buildroot and kernel minor version [#9523](https://github.com/kubernetes/minikube/pull/9523) -Thank you to our contributors for this release! +Thank you to our contributors for this release! - Anders F Björklund - Evgeny Shmarnev @@ -146,7 +148,6 @@ Thank you to our contributors for this release! - vinu2003 - zouyu - ## Version 1.14.2 - 2020-10-27 Bug Fixes: @@ -182,7 +183,7 @@ Minor Improvements: * bump helm-tiller addon to v2.16.12 [#9444](https://github.com/kubernetes/minikube/pull/9444) * bump version for ingress dns addon [#9435](https://github.com/kubernetes/minikube/pull/9435) -Thank you to our contributors for this release! +Thank you to our contributors for this release! - Anders F Björklund - Dale Hamel @@ -204,12 +205,12 @@ Thank you to our contributors for this release! ## Version 1.14.0 - 2020-10-08 -## Features +Features: * Delete context when stopped [#9414](https://github.com/kubernetes/minikube/pull/9414) * New flag "--ports" to expose ports for docker & podman drivers [#9404](https://github.com/kubernetes/minikube/pull/9404) -## Bug Fixes and minor improvements +Bug fixes and minor improvements: * Ingress addon: fix the controller name [#9413](https://github.com/kubernetes/minikube/pull/9413) * docker/podman drivers: no panic when updating mount-string with no configuration [#9412](https://github.com/kubernetes/minikube/pull/9412) @@ -230,23 +231,23 @@ Thank you to our contributors for this release. ## Version 1.14.0-beta.0 - 2020-10-06 -## Features +Features: * add dedicated network for docker driver [#9294](https://github.com/kubernetes/minikube/pull/9294) * Make sure gcp-auth addon can be enabled on startup [#9318](https://github.com/kubernetes/minikube/pull/9318) -## Bug Fixes +Bug fixes: * Fix minikube status bug when cluster is paused [#9383](https://github.com/kubernetes/minikube/pull/9383) * don't allow profile name to be less than 2 characters [#9367](https://github.com/kubernetes/minikube/pull/9367) * fix: "profile list" shows paused clusters as "Running" [#8978](https://github.com/kubernetes/minikube/pull/8978) * Fix error in unittest, as pointed out by warning [#9345](https://github.com/kubernetes/minikube/pull/9345) -## Updates +Improvements: * update kicbase image to ubuntu-based [#9353](https://github.com/kubernetes/minikube/pull/9353) -Thank you to our contributors for this release! +Thank you to our contributors for this release! - Anders F Björklund - Bob Killen @@ -267,9 +268,8 @@ Thank you to our contributors for this release! - programistka - zhanwang - - ## Version 1.13.1 - 2020-09-18 + * Update Default Kubernetes Version to v1.19.2 [#9265](https://github.com/kubernetes/minikube/pull/9265) * fix mounting for docker driver in windows [#9263](https://github.com/kubernetes/minikube/pull/9263) * CSI Hostpath Driver & VolumeSnapshots addons [#8461](https://github.com/kubernetes/minikube/pull/8461) @@ -282,7 +282,8 @@ Thank you to our contributors for this release! * Add Docker Desktop instructions if memory is greater than minimum but less than recommended [#9181](https://github.com/kubernetes/minikube/pull/9181) * Update minimum memory constants to use MiB instead of MB [#9180](https://github.com/kubernetes/minikube/pull/9180) -Thank you to our contributors for this release! +Thank you to our contributors for this release! + - Anders F Björklund - Dean Coakley - Julien Breux @@ -294,10 +295,9 @@ Thank you to our contributors for this release! - Zadjad Rezai - jjanik - ## Version 1.13.0 - 2020-09-03 -## Features +Features: * Update default Kubernetes version to v1.19.0 🎉 [#9050](https://github.com/kubernetes/minikube/pull/9050) * start: Support for mounting host volumes on start with docker driver [#8159](https://github.com/kubernetes/minikube/pull/8159) @@ -305,7 +305,7 @@ Thank you to our contributors for this release! * stop: add --keep-context-active flag [#9044](https://github.com/kubernetes/minikube/pull/9044) * kubectl: Invoke kubectl if minikube binary is named 'kubectl' [#8872](https://github.com/kubernetes/minikube/pull/8872) -## Bug fixes +Bug fixes: * docker: Choose the appropriate bridge interface when multiple exist [#9062](https://github.com/kubernetes/minikube/pull/9062) * cache: Fix "cache add" for local images by cherry-picking go-containerregistry fix [#9160](https://github.com/kubernetes/minikube/pull/9160) @@ -322,7 +322,7 @@ Thank you to our contributors for this release! * addon-manager: Add namespace to persistent volume path [#9128](https://github.com/kubernetes/minikube/pull/9128) * ssh: respect native-ssh flag [#8907](https://github.com/kubernetes/minikube/pull/8907) -## Other improvements +Improvements: * kic: Disable swap in Docker & podman containers [#9149](https://github.com/kubernetes/minikube/pull/9149) * kic: prioritize /etc/hosts over dns [#9029](https://github.com/kubernetes/minikube/pull/9029) @@ -336,7 +336,7 @@ Thank you to our contributors for this release! * perf: set proxy-refresh-interval=70000 for etcd to improve CPU overhead [#8850](https://github.com/kubernetes/minikube/pull/8850) * json: buffer download progress every second [#9099](https://github.com/kubernetes/minikube/pull/9099) * localization: Fix typos in pl translation [#9168](https://github.com/kubernetes/minikube/pull/9168) -* dashboard: Update dashboard to v2.0.3 [#9129](https://github.com/kubernetes/minikube/pull/9129) +* dashboard: Update dashboard to v2.0.3 [#9129](https://github.com/kubernetes/minikube/pull/9129) Thank you to our many wonderful contributors for this release! @@ -384,7 +384,7 @@ Improvements: * Update Japanese translation [#8967](https://github.com/kubernetes/minikube/pull/8967) * Fix for a few typos in polish translations [#8950](https://github.com/kubernetes/minikube/pull/8950) -Thank you to our contributors for this release! +Thank you to our contributors for this release! - Anders F Björklund - Andrej Guran @@ -408,6 +408,7 @@ Thank you to our contributors for this release! ## Version 1.12.2 - 2020-08-03 Features: + * New Addon: Automated GCP Credentials [#8682](https://github.com/kubernetes/minikube/pull/8682) * status: Add experimental cluster JSON status with state transition support [#8868](https://github.com/kubernetes/minikube/pull/8868) * Add support for Error type to JSON output [#8796](https://github.com/kubernetes/minikube/pull/8796) @@ -417,6 +418,7 @@ Features: * Add SCH_PRIO, SCH_SFQ and CLS_BASIC kernel module to add filter on traffic control [#8670](https://github.com/kubernetes/minikube/pull/8670) Bug Fixes: + * docker/podman: warn if allocated memory is below limit [#8718](https://github.com/kubernetes/minikube/pull/8718) * Enabling metrics addon when someone enables dashboard [#8842](https://github.com/kubernetes/minikube/pull/8842) * make base-image respect --image-repository [#8880](https://github.com/kubernetes/minikube/pull/8880) @@ -426,6 +428,7 @@ Bug Fixes: * Make restarts in Docker/Podman drivers more reliable [#8864](https://github.com/kubernetes/minikube/pull/8864) Version changes: + * update crio to 1.18.3 and kicbase to ubuntu 20.04 [#8895](https://github.com/kubernetes/minikube/pull/8895) * Podman downgrade to 1.9.3 for the build command [#8774](https://github.com/kubernetes/minikube/pull/8774) * Upgrade kicbase to v0.0.11 [#8899](https://github.com/kubernetes/minikube/pull/8899) @@ -434,6 +437,7 @@ Version changes: * Upgrade storage provisioner image [#8909](https://github.com/kubernetes/minikube/pull/8909) Thank you to our contributors for this release! + - Ajitesh13 - Alonyb - Anders F Björklund @@ -458,21 +462,24 @@ Thank you to our contributors for this release! ## Version 1.12.1 - 2020-07-17 Features: + * Add support for Calico CNI (--cni=calico) [#8571](https://github.com/kubernetes/minikube/pull/8571) * Add support for Cilium CNI (--cni=cilium) [#8573](https://github.com/kubernetes/minikube/pull/8573) - Bug Fixes: + * Fix bugs which prevented upgrades from v1.0+ to v1.12 [#8741](https://github.com/kubernetes/minikube/pull/8741) * Add KicBaseImage to existing config if missing (fixes v1.9.x upgrade) [#8738](https://github.com/kubernetes/minikube/pull/8738) * multinode: fix control plane not ready on restart [#8698](https://github.com/kubernetes/minikube/pull/8698) * none CNI: error if portmap plug-in is required but unavailable [#8684](https://github.com/kubernetes/minikube/pull/8684) -Version Upgrades: +Improvements: + * ingress addon: bump to latest version [#8705](https://github.com/kubernetes/minikube/pull/8705) * Upgrade go version to 1.14.4 [#8660](https://github.com/kubernetes/minikube/pull/8660) -Huge thank you for this release towards our contributors: +Huge thank you for this release towards our contributors: + - Anders F Björklund - Harsh Modi - James Lucktaylor @@ -487,8 +494,6 @@ Huge thank you for this release towards our contributors: - Thomas Strömberg - jinhong.kim - - ## Version 1.12.0 - 2020-07-09 Features: @@ -669,7 +674,7 @@ Bug fixes: * hyperv: fix virtual switch bug [#8103](https://github.com/kubernetes/minikube/pull/8103) * Bump Default Kubernetes version v1.18.2 and update newest [8099](https://github.com/kubernetes/minikube/pull/8099) -Huge thank you for this release towards our contributors: +Huge thank you for this release towards our contributors: - cprogrammer1994 - Medya Ghazizadeh @@ -683,7 +688,6 @@ Features: * Add new env variable `MINIKUBE_FORCE_SYSTEMD` to configure force-systemd [#8010](https://github.com/kubernetes/minikube/pull/8010) * docker/podman: add alternative repository for base image in github packages [#7943](https://github.com/kubernetes/minikube/pull/7943) - Improvements: * tunnel: change to clean up by default [#7946](https://github.com/kubernetes/minikube/pull/7946) @@ -723,7 +727,6 @@ Huge thank you for this release towards our contributors: - Thomas Strömberg - anencore94 - ## Version 1.10.0-beta.2 - 2020-04-29 Improvements: @@ -767,15 +770,16 @@ Huge thank you for this release towards our contributors: ## Version 1.10.0-beta.1 - 2020-04-22 Improvements: + * Skip preload download if --image-repository is set [#7707](https://github.com/kubernetes/minikube/pull/7707) +Bug fixes: -Bug Fixes: * ISO: persistently mount /var/lib/containerd [#7843](https://github.com/kubernetes/minikube/pull/7843) * docker/podman: fix delete -p not cleaning up & add integration test [#7819](https://github.com/kubernetes/minikube/pull/7819) +Huge thank you for this release towards our contributors: -Huge thank you for this release towards our contributors: - Anders F Björklund - Kenta Iso - Medya Ghazizadeh @@ -785,10 +789,10 @@ Huge thank you for this release towards our contributors: - Thomas Stromberg - Tobias Klauser - ## Version 1.10.0-beta.0 - 2020-04-20 Improvements: + * faster containerd start by preloading images [#7793](https://github.com/kubernetes/minikube/pull/7793) * Add fish completion support [#7777](https://github.com/kubernetes/minikube/pull/7777) * Behavior change: start with no arguments uses existing cluster config [#7449](https://github.com/kubernetes/minikube/pull/7449) @@ -805,6 +809,7 @@ Improvements: * Upgrade falco-probe module to version 0.21.0 [#7436](https://github.com/kubernetes/minikube/pull/7436) Bug Fixes: + * Fix multinode cluster creation for VM drivers [#7700](https://github.com/kubernetes/minikube/pull/7700) * tunnel: Fix resolver file permissions, add DNS forwarding test [#7753](https://github.com/kubernetes/minikube/pull/7753) * unconfine apparmor for kic [#7658](https://github.com/kubernetes/minikube/pull/7658) @@ -812,7 +817,6 @@ Bug Fixes: * Respect driver.FlagDefaults even if --extra-config is set [#7509](https://github.com/kubernetes/minikube/pull/7509) * remove docker/podman overlay network for docker-runtime [#7425](https://github.com/kubernetes/minikube/pull/7425) - Huge thank you for this release towards our contributors: - Alonyb @@ -852,7 +856,6 @@ And big thank you to those who participated in our docs fixit week: - jlaswell - remraz - ## Version 1.9.2 - 2020-04-04 Minor improvements: @@ -926,7 +929,6 @@ New features & improvements * Add sch_tbf and extend filter ipset kernel module for bandwidth shaping [#7255](https://github.com/kubernetes/minikube/pull/7255) * Parse --disk-size and --memory sizes with binary suffixes [#7206](https://github.com/kubernetes/minikube/pull/7206) - Bug Fixes * Re-initalize failed Kubernetes clusters [#7234](https://github.com/kubernetes/minikube/pull/7234) @@ -934,7 +936,7 @@ Bug Fixes * Enable HW_RANDOM_VIRTIO to fix sshd startup delays [#7208](https://github.com/kubernetes/minikube/pull/7208) * hyperv Delete: call StopHost before removing VM [#7160](https://github.com/kubernetes/minikube/pull/7160) -Huge thank you for this release towards our contributors: +Huge thank you for this release towards our contributors: - Anders F Björklund - Medya Ghazizadeh @@ -947,7 +949,6 @@ Huge thank you for this release towards our contributors: - Zhongcheng Lao - vikkyomkar - ## Version 1.9.0-beta.2 - 2020-03-21 New features & improvements @@ -1037,7 +1038,8 @@ Captivating bug fixes: * Check if lz4 is available before trying to use it [#6941](https://github.com/kubernetes/minikube/pull/6941) * Allow backwards compatibility with 1.6 and earlier configs [#6969](https://github.com/kubernetes/minikube/pull/6969) -Huge thank you for this release towards our contributors: +Huge thank you for this release towards our contributors: + - Anders F Björklund - Ian Molee - Kenta Iso @@ -1053,7 +1055,8 @@ Minor bug fix: * Block on preload download before extracting, fall back to caching images if it fails [#6928](https://github.com/kubernetes/minikube/pull/6928) * Cleanup remaining PointToHostDockerDaemon calls [#6925](https://github.com/kubernetes/minikube/pull/6925) -Huge thank you for this release towards our contributors: +Huge thank you for this release towards our contributors: + - Priya Wadhwa - Thomas Stromberg - Medya Ghazizadeh @@ -1237,7 +1240,7 @@ Thank you to those brave souls who made the final push toward this release: * Prevent registry-creds configure from failing when a secret does not exist. [#6380](https://github.com/kubernetes/minikube/pull/6380) * improve checking modprob netfilter [#6427](https://github.com/kubernetes/minikube/pull/6427) -Huge thank you for this release towards our contributors: +Huge thank you for this release towards our contributors: - Anders Björklund - Bjørn Harald Fotland @@ -1293,6 +1296,7 @@ Thanks you to the following contributors: * Add istio addon for minikube [#6154](https://github.com/kubernetes/minikube/pull/6154) Huge thank you for this release towards our contributors: + - Anders Björklund - andylibrian - Dao Cong Tien @@ -1321,6 +1325,7 @@ Huge thank you for this release towards our contributors: * Change error text to encourage better issue reports [#6121](https://github.com/kubernetes/minikube/pull/6121) Huge thank you for this release towards our contributors: + - Anukul Sangwan - Aresforchina - Curtis Carter @@ -1332,7 +1337,6 @@ Huge thank you for this release towards our contributors: - priyawadhwa - tstromberg - ## Version 1.6.1 - 2019-12-11 A special bugfix release to fix a Windows regression: @@ -1385,7 +1389,8 @@ Thanks goes out to the merry band of Kubernetes contributors that made this rele * Upgrade buildroot minor version to 2019.02.7 [#5967](https://github.com/kubernetes/minikube/pull/5967) * dashboard: Update to latest images (2.0.0-beta6) [#5934](https://github.com/kubernetes/minikube/pull/5934) -Huge thank you for this release towards our contributors: +Huge thank you for this release towards our contributors: + - Adam Crowder - Anders F Björklund - David Newman @@ -1413,7 +1418,8 @@ Huge thank you for this release towards our contributors: * none driver: Warn about --cpus, --memory, and --container-runtime settings [#5845](https://github.com/kubernetes/minikube/pull/5845) * Refactor config.Config to prepare for multinode [#5889](https://github.com/kubernetes/minikube/pull/5889) -Huge thank you for this release towards our contributors: +Huge thank you for this release towards our contributors: + - Anders Björklund - Aresforchina - Igor Zibarev @@ -1518,6 +1524,7 @@ Thank you to our contributors! * Change systemd unit files perm to 644 [#5492](https://github.com/kubernetes/minikube/pull/5492) Huge thank you for this release towards our contributors: + - Anders F Björklund - bhanu011 - chentanjun @@ -1542,7 +1549,6 @@ Huge thank you for this release towards our contributors: - Zhongcheng Lao - Zoltán Reegn - ## Version 1.4.0 - 2019-09-17 Notable user-facing changes: @@ -1629,7 +1635,6 @@ Thank you to our recent contributors: * Update gvisor runsc version [#4494](https://github.com/kubernetes/minikube/pull/4494) * Upgrade nginx to security patch v0.25.1 [#5197](https://github.com/kubernetes/minikube/pull/5197) - Thank you to our contributors: - AllenZMC diff --git a/README.md b/README.md index 09422ad96b..1ca755b306 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,8 @@ See minikube in action [here](https://minikube.sigs.k8s.io/docs/handbook/control minikube is a Kubernetes [#sig-cluster-lifecycle](https://github.com/kubernetes/community/tree/master/sig-cluster-lifecycle) project. * [**#minikube on Kubernetes Slack**](https://kubernetes.slack.com) - Live chat with minikube developers! -* [minikube-users mailing list](https://groups.google.com/forum/#!forum/minikube-users) -* [minikube-dev mailing list](https://groups.google.com/forum/#!forum/minikube-dev) +* [minikube-users mailing list](https://groups.google.com/g/minikube-users) +* [minikube-dev mailing list](https://groups.google.com/g/minikube-dev) * [Contributing](https://minikube.sigs.k8s.io/docs/contrib/) * [Development Roadmap](https://minikube.sigs.k8s.io/docs/contrib/roadmap/) diff --git a/cmd/minikube/cmd/ip.go b/cmd/minikube/cmd/ip.go index 6a2ca32055..3a34fad294 100644 --- a/cmd/minikube/cmd/ip.go +++ b/cmd/minikube/cmd/ip.go @@ -18,17 +18,29 @@ package cmd import ( "github.com/spf13/cobra" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/mustload" + "k8s.io/minikube/pkg/minikube/node" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/reason" ) // ipCmd represents the ip command var ipCmd = &cobra.Command{ Use: "ip", - Short: "Retrieves the IP address of the running cluster", - Long: `Retrieves the IP address of the running cluster, and writes it to STDOUT.`, + Short: "Retrieves the IP address of the specified node", + Long: `Retrieves the IP address of the specified node, and writes it to STDOUT.`, Run: func(cmd *cobra.Command, args []string) { co := mustload.Running(ClusterFlagValue()) - out.Ln(co.CP.IP.String()) + n, _, err := node.Retrieve(*co.Config, nodeName) + if err != nil { + exit.Error(reason.GuestNodeRetrieve, "retrieving node", err) + } + + out.Ln(n.IP) }, } + +func init() { + ipCmd.Flags().StringVarP(&nodeName, "node", "n", "", "The node to get IP. Defaults to the primary control plane.") +} diff --git a/cmd/minikube/cmd/root.go b/cmd/minikube/cmd/root.go index 2259f03889..1ef8e2fadf 100644 --- a/cmd/minikube/cmd/root.go +++ b/cmd/minikube/cmd/root.go @@ -221,6 +221,7 @@ func init() { Message: translate.T("Troubleshooting Commands:"), Commands: []*cobra.Command{ sshKeyCmd, + sshHostCmd, ipCmd, logsCmd, updateCheckCmd, diff --git a/cmd/minikube/cmd/ssh-host.go b/cmd/minikube/cmd/ssh-host.go new file mode 100644 index 0000000000..1755c30ea7 --- /dev/null +++ b/cmd/minikube/cmd/ssh-host.go @@ -0,0 +1,116 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 cmd + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + "k8s.io/client-go/util/homedir" + + "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/driver" + "k8s.io/minikube/pkg/minikube/exit" + "k8s.io/minikube/pkg/minikube/machine" + "k8s.io/minikube/pkg/minikube/mustload" + "k8s.io/minikube/pkg/minikube/node" + "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/sshutil" +) + +var ( + appendKnown bool +) + +// sshHostCmd represents the sshHostCmd command +var sshHostCmd = &cobra.Command{ + Use: "ssh-host", + Short: "Retrieve the ssh host key of the specified node", + Long: "Retrieve the ssh host key of the specified node.", + Run: func(cmd *cobra.Command, args []string) { + cname := ClusterFlagValue() + co := mustload.Running(cname) + if co.CP.Host.DriverName == driver.None { + exit.Message(reason.Usage, "'none' driver does not support 'minikube ssh-host' command") + } + + var err error + var n *config.Node + if nodeName == "" { + n = co.CP.Node + } else { + n, _, err = node.Retrieve(*co.Config, nodeName) + if err != nil { + exit.Message(reason.GuestNodeRetrieve, "Node {{.nodeName}} does not exist.", out.V{"nodeName": nodeName}) + } + } + + scanArgs := []string{"-t", "rsa"} + + keys, err := machine.RunSSHHostCommand(co.API, *co.Config, *n, "ssh-keyscan", scanArgs) + if err != nil { + // This is typically due to a non-zero exit code, so no need for flourish. + out.ErrLn("ssh-keyscan: %v", err) + // It'd be nice if we could pass up the correct error code here :( + os.Exit(1) + } + + if appendKnown { + addr, port, err := machine.GetSSHHostAddrPort(co.API, *co.Config, *n) + if err != nil { + out.ErrLn("GetSSHHostAddrPort: %v", err) + os.Exit(1) + } + + host := addr + if port != 22 { + host = fmt.Sprintf("[%s]:%d", addr, port) + } + knownHosts := filepath.Join(homedir.HomeDir(), ".ssh", "known_hosts") + + fmt.Fprintf(os.Stderr, "Host added: %s (%s)\n", knownHosts, host) + if sshutil.KnownHost(host, knownHosts) { + return + } + + f, err := os.OpenFile(knownHosts, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + out.ErrLn("OpenFile: %v", err) + os.Exit(1) + } + defer f.Close() + + _, err = f.WriteString(keys) + if err != nil { + out.ErrLn("WriteString: %v", err) + os.Exit(1) + } + + return + } + + fmt.Printf("%s", keys) + }, +} + +func init() { + sshHostCmd.Flags().StringVarP(&nodeName, "node", "n", "", "The node to ssh into. Defaults to the primary control plane.") + sshHostCmd.Flags().BoolVar(&appendKnown, "append-known", false, "Add host key to SSH known_hosts file") +} diff --git a/cmd/minikube/cmd/ssh-key.go b/cmd/minikube/cmd/ssh-key.go index b7a0ddf0de..99db155c5e 100644 --- a/cmd/minikube/cmd/ssh-key.go +++ b/cmd/minikube/cmd/ssh-key.go @@ -20,18 +20,31 @@ import ( "path/filepath" "github.com/spf13/cobra" + "k8s.io/minikube/pkg/minikube/driver" + "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/mustload" + "k8s.io/minikube/pkg/minikube/node" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/reason" ) // sshKeyCmd represents the sshKey command var sshKeyCmd = &cobra.Command{ Use: "ssh-key", - Short: "Retrieve the ssh identity key path of the specified cluster", - Long: "Retrieve the ssh identity key path of the specified cluster.", + Short: "Retrieve the ssh identity key path of the specified node", + Long: "Retrieve the ssh identity key path of the specified node, and writes it to STDOUT.", Run: func(cmd *cobra.Command, args []string) { _, cc := mustload.Partial(ClusterFlagValue()) - out.Ln(filepath.Join(localpath.MiniPath(), "machines", cc.Name, "id_rsa")) + n, _, err := node.Retrieve(*cc, nodeName) + if err != nil { + exit.Error(reason.GuestNodeRetrieve, "retrieving node", err) + } + + out.Ln(filepath.Join(localpath.MiniPath(), "machines", driver.MachineName(*cc, *n), "id_rsa")) }, } + +func init() { + sshKeyCmd.Flags().StringVarP(&nodeName, "node", "n", "", "The node to get ssh-key path. Defaults to the primary control plane.") +} diff --git a/deploy/addons/dashboard/dashboard-dp.yaml.tmpl b/deploy/addons/dashboard/dashboard-dp.yaml.tmpl index 8fc1875235..2a3fb09f72 100644 --- a/deploy/addons/dashboard/dashboard-dp.yaml.tmpl +++ b/deploy/addons/dashboard/dashboard-dp.yaml.tmpl @@ -91,7 +91,7 @@ spec: containers: - name: kubernetes-dashboard # WARNING: This must match pkg/minikube/bootstrapper/images/images.go - image: {{default "kubernetesui" .ImageRepository}}/dashboard:v2.0.3 + image: {{default "kubernetesui" .ImageRepository}}/dashboard:v2.1.0 ports: - containerPort: 9090 protocol: TCP diff --git a/deploy/iso/minikube-iso/package/buildkit-bin/buildkit-bin.hash b/deploy/iso/minikube-iso/package/buildkit-bin/buildkit-bin.hash index e658bb8341..afdb28733b 100644 --- a/deploy/iso/minikube-iso/package/buildkit-bin/buildkit-bin.hash +++ b/deploy/iso/minikube-iso/package/buildkit-bin/buildkit-bin.hash @@ -1,2 +1,3 @@ sha256 33bcaa49b31bc3a277ac75d32fce3f5442d39f53a1799b8624e985279b579f74 buildkit-v0.7.2.linux-amd64.tar.gz sha256 28005748fae926edf8c93b7cb1df53ec49df65dec67105b94e7fb9c513fa78a4 buildkit-v0.8.0.linux-amd64.tar.gz +sha256 e0438a701d4192f80b2211b0a333984ee4f097c547904e40fc941daad57fe153 buildkit-v0.8.1.linux-amd64.tar.gz diff --git a/deploy/iso/minikube-iso/package/buildkit-bin/buildkit-bin.mk b/deploy/iso/minikube-iso/package/buildkit-bin/buildkit-bin.mk index 639c0bf281..624b17bf08 100644 --- a/deploy/iso/minikube-iso/package/buildkit-bin/buildkit-bin.mk +++ b/deploy/iso/minikube-iso/package/buildkit-bin/buildkit-bin.mk @@ -4,8 +4,8 @@ # ################################################################################ -BUILDKIT_BIN_VERSION = v0.8.0 -BUILDKIT_BIN_COMMIT = 73fe4736135645a342abc7b587bba0994cccf0f9 +BUILDKIT_BIN_VERSION = v0.8.1 +BUILDKIT_BIN_COMMIT = 8142d66b5ebde79846b869fba30d9d30633e74aa BUILDKIT_BIN_SITE = https://github.com/moby/buildkit/releases/download/$(BUILDKIT_BIN_VERSION) BUILDKIT_BIN_SOURCE = buildkit-$(BUILDKIT_BIN_VERSION).linux-amd64.tar.gz diff --git a/deploy/iso/minikube-iso/package/docker-bin/docker-bin.hash b/deploy/iso/minikube-iso/package/docker-bin/docker-bin.hash index 1338dbaee5..4364f390f6 100644 --- a/deploy/iso/minikube-iso/package/docker-bin/docker-bin.hash +++ b/deploy/iso/minikube-iso/package/docker-bin/docker-bin.hash @@ -24,3 +24,4 @@ sha256 88de1b87b8a2582fe827154899475a72fb707c5793cfb39d2a24813ba1f31197 docker- sha256 ddb13aff1fcdcceb710bf71a210169b9c1abfd7420eeaf42cf7975f8fae2fcc8 docker-19.03.13.tgz sha256 9f1ec28e357a8f18e9561129239caf9c0807d74756e21cc63637c7fdeaafe847 docker-19.03.14.tgz sha256 02936a3585f12f13b21b95e02ae722d74eaf1870b536997e914659ee307b2ac4 docker-20.10.0.tgz +sha256 8790f3b94ee07ca69a9fdbd1310cbffc729af0a07e5bf9f34a79df1e13d2e50e docker-20.10.1.tgz diff --git a/deploy/iso/minikube-iso/package/docker-bin/docker-bin.mk b/deploy/iso/minikube-iso/package/docker-bin/docker-bin.mk index 5ba5103cca..7b2eb7b77f 100644 --- a/deploy/iso/minikube-iso/package/docker-bin/docker-bin.mk +++ b/deploy/iso/minikube-iso/package/docker-bin/docker-bin.mk @@ -4,7 +4,7 @@ # ################################################################################ -DOCKER_BIN_VERSION = 20.10.0 +DOCKER_BIN_VERSION = 20.10.1 DOCKER_BIN_SITE = https://download.docker.com/linux/static/stable/x86_64 DOCKER_BIN_SOURCE = docker-$(DOCKER_BIN_VERSION).tgz diff --git a/deploy/kicbase/Dockerfile b/deploy/kicbase/Dockerfile index 45cd7e2e92..98a7e01018 100644 --- a/deploy/kicbase/Dockerfile +++ b/deploy/kicbase/Dockerfile @@ -21,7 +21,7 @@ # for a kubernetes node image, it doesn't contain much we don't need FROM ubuntu:focal-20201106 -ARG BUILDKIT_VERSION="v0.8.0" +ARG BUILDKIT_VERSION="v0.8.1" # copy in static files (configs, scripts) COPY 10-network-security.conf /etc/sysctl.d/10-network-security.conf diff --git a/pkg/minikube/bootstrapper/images/images.go b/pkg/minikube/bootstrapper/images/images.go index d2cc7bd376..0a9d4db0d2 100644 --- a/pkg/minikube/bootstrapper/images/images.go +++ b/pkg/minikube/bootstrapper/images/images.go @@ -148,7 +148,7 @@ func dashboardFrontend(repo string) string { repo = "docker.io/kubernetesui" } // See 'kubernetes-dashboard' in deploy/addons/dashboard/dashboard-dp.yaml - return path.Join(repo, "dashboard:v2.0.3") + return path.Join(repo, "dashboard:v2.1.0") } // dashboardMetrics returns the image used for the dashboard metrics scraper diff --git a/pkg/minikube/bootstrapper/images/images_test.go b/pkg/minikube/bootstrapper/images/images_test.go index 5831e450c6..3d77360340 100644 --- a/pkg/minikube/bootstrapper/images/images_test.go +++ b/pkg/minikube/bootstrapper/images/images_test.go @@ -25,7 +25,7 @@ import ( func TestAuxiliary(t *testing.T) { want := []string{ "gcr.io/k8s-minikube/storage-provisioner:v4", - "docker.io/kubernetesui/dashboard:v2.0.3", + "docker.io/kubernetesui/dashboard:v2.1.0", "docker.io/kubernetesui/metrics-scraper:v1.0.4", } got := auxiliary("") @@ -37,7 +37,7 @@ func TestAuxiliary(t *testing.T) { func TestAuxiliaryMirror(t *testing.T) { want := []string{ "test.mirror/storage-provisioner:v4", - "test.mirror/dashboard:v2.0.3", + "test.mirror/dashboard:v2.1.0", "test.mirror/metrics-scraper:v1.0.4", } got := auxiliary("test.mirror") diff --git a/pkg/minikube/bootstrapper/images/kubeadm_test.go b/pkg/minikube/bootstrapper/images/kubeadm_test.go index 81d37bf8ed..dd3b9f5cda 100644 --- a/pkg/minikube/bootstrapper/images/kubeadm_test.go +++ b/pkg/minikube/bootstrapper/images/kubeadm_test.go @@ -38,7 +38,7 @@ func TestKubeadmImages(t *testing.T) { "k8s.gcr.io/etcd:3.4.3-0", "k8s.gcr.io/pause:3.1", "gcr.io/k8s-minikube/storage-provisioner:v4", - "docker.io/kubernetesui/dashboard:v2.0.3", + "docker.io/kubernetesui/dashboard:v2.1.0", "docker.io/kubernetesui/metrics-scraper:v1.0.4", }}, {"v1.16.1", "mirror.k8s.io", []string{ @@ -50,7 +50,7 @@ func TestKubeadmImages(t *testing.T) { "mirror.k8s.io/etcd:3.3.15-0", "mirror.k8s.io/pause:3.1", "mirror.k8s.io/storage-provisioner:v4", - "mirror.k8s.io/dashboard:v2.0.3", + "mirror.k8s.io/dashboard:v2.1.0", "mirror.k8s.io/metrics-scraper:v1.0.4", }}, {"v1.15.0", "", []string{ @@ -62,7 +62,7 @@ func TestKubeadmImages(t *testing.T) { "k8s.gcr.io/etcd:3.3.10", "k8s.gcr.io/pause:3.1", "gcr.io/k8s-minikube/storage-provisioner:v4", - "docker.io/kubernetesui/dashboard:v2.0.3", + "docker.io/kubernetesui/dashboard:v2.1.0", "docker.io/kubernetesui/metrics-scraper:v1.0.4", }}, {"v1.14.0", "", []string{ @@ -74,7 +74,7 @@ func TestKubeadmImages(t *testing.T) { "k8s.gcr.io/etcd:3.3.10", "k8s.gcr.io/pause:3.1", "gcr.io/k8s-minikube/storage-provisioner:v4", - "docker.io/kubernetesui/dashboard:v2.0.3", + "docker.io/kubernetesui/dashboard:v2.1.0", "docker.io/kubernetesui/metrics-scraper:v1.0.4", }}, {"v1.13.0", "", []string{ @@ -86,7 +86,7 @@ func TestKubeadmImages(t *testing.T) { "k8s.gcr.io/etcd:3.2.24", "k8s.gcr.io/pause:3.1", "gcr.io/k8s-minikube/storage-provisioner:v4", - "docker.io/kubernetesui/dashboard:v2.0.3", + "docker.io/kubernetesui/dashboard:v2.1.0", "docker.io/kubernetesui/metrics-scraper:v1.0.4", }}, {"v1.12.0", "", []string{ @@ -98,7 +98,7 @@ func TestKubeadmImages(t *testing.T) { "k8s.gcr.io/etcd:3.2.24", "k8s.gcr.io/pause:3.1", "gcr.io/k8s-minikube/storage-provisioner:v4", - "docker.io/kubernetesui/dashboard:v2.0.3", + "docker.io/kubernetesui/dashboard:v2.1.0", "docker.io/kubernetesui/metrics-scraper:v1.0.4", }}, } diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go index a85c044024..3a7f0f1f41 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go @@ -17,8 +17,10 @@ limitations under the License. package kubeadm import ( + "bufio" "context" "fmt" + "io" "net" "os/exec" "path" @@ -226,9 +228,17 @@ func (k *Bootstrapper) init(cfg config.ClusterConfig) error { conf := bsutil.KubeadmYamlPath ctx, cancel := context.WithTimeout(context.Background(), initTimeoutMinutes*time.Minute) defer cancel() + kr, kw := io.Pipe() c := exec.CommandContext(ctx, "/bin/bash", "-c", fmt.Sprintf("%s init --config %s %s --ignore-preflight-errors=%s", bsutil.InvokeKubeadm(cfg.KubernetesConfig.KubernetesVersion), conf, extraFlags, strings.Join(ignore, ","))) - if _, err := k.c.RunCmd(c); err != nil { + c.Stdout = kw + c.Stderr = kw + sc, err := k.c.StartCmd(c) + if err != nil { + return errors.Wrap(err, "start") + } + go outputKubeadmInitSteps(kr) + if _, err := k.c.WaitCmd(sc); err != nil { if ctx.Err() == context.DeadlineExceeded { return ErrInitTimedout } @@ -236,9 +246,8 @@ func (k *Bootstrapper) init(cfg config.ClusterConfig) error { if strings.Contains(err.Error(), "'kubeadm': Permission denied") { return ErrNoExecLinux } - return errors.Wrap(err, "run") + return errors.Wrap(err, "wait") } - if err := k.applyCNI(cfg); err != nil { return errors.Wrap(err, "apply cni") } @@ -272,6 +281,37 @@ func (k *Bootstrapper) init(cfg config.ClusterConfig) error { return nil } +// outputKubeadmInitSteps streams the pipe and outputs the current step +func outputKubeadmInitSteps(logs io.Reader) { + type step struct { + logTag string + registerStep register.RegStep + stepMessage string + } + + steps := []step{ + {logTag: "certs", registerStep: register.PreparingKubernetesCerts, stepMessage: "Generating certificates and keys ..."}, + {logTag: "control-plane", registerStep: register.PreparingKubernetesControlPlane, stepMessage: "Booting up control plane ..."}, + {logTag: "bootstrap-token", registerStep: register.PreparingKubernetesBootstrapToken, stepMessage: "Configuring RBAC rules ..."}, + } + nextStepIndex := 0 + + scanner := bufio.NewScanner(logs) + for scanner.Scan() { + if nextStepIndex >= len(steps) { + scanner.Text() + continue + } + nextStep := steps[nextStepIndex] + if !strings.Contains(scanner.Text(), fmt.Sprintf("[%s]", nextStep.logTag)) { + continue + } + register.Reg.SetStep(nextStep.registerStep) + out.Step(style.SubStep, nextStep.stepMessage) + nextStepIndex++ + } +} + // applyCNI applies CNI to a cluster. Needs to be done every time a VM is powered up. func (k *Bootstrapper) applyCNI(cfg config.ClusterConfig) error { cnm, err := cni.New(cfg) diff --git a/pkg/minikube/command/command_runner.go b/pkg/minikube/command/command_runner.go index 7de15d0d5f..88c66c2680 100644 --- a/pkg/minikube/command/command_runner.go +++ b/pkg/minikube/command/command_runner.go @@ -51,12 +51,26 @@ type RunResult struct { Args []string // the args that was passed to Runner } +// StartedCmd holds the contents of a started command +type StartedCmd struct { + cmd *exec.Cmd + rr *RunResult +} + // Runner represents an interface to run commands. type Runner interface { // RunCmd runs a cmd of exec.Cmd type. allowing user to set cmd.Stdin, cmd.Stdout,... // not all implementors are guaranteed to handle all the properties of cmd. RunCmd(cmd *exec.Cmd) (*RunResult, error) + // StartCmd starts a cmd of exec.Cmd type. + // This func in non-blocking, use WaitCmd to block until complete. + // Not all implementors are guaranteed to handle all the properties of cmd. + StartCmd(cmd *exec.Cmd) (*StartedCmd, error) + + // WaitCmd will prevent further execution until the started command has completed. + WaitCmd(startedCmd *StartedCmd) (*RunResult, error) + // Copy is a convenience method that runs a command to copy a file Copy(assets.CopyableFile) error diff --git a/pkg/minikube/command/exec_runner.go b/pkg/minikube/command/exec_runner.go index 862f183ede..066eb64f9f 100644 --- a/pkg/minikube/command/exec_runner.go +++ b/pkg/minikube/command/exec_runner.go @@ -91,6 +91,53 @@ func (e *execRunner) RunCmd(cmd *exec.Cmd) (*RunResult, error) { return rr, fmt.Errorf("%s: %v\nstdout:\n%s\nstderr:\n%s", rr.Command(), err, rr.Stdout.String(), rr.Stderr.String()) } +// StartCmd implements the Command Runner interface to start a exec.Cmd object +func (*execRunner) StartCmd(cmd *exec.Cmd) (*StartedCmd, error) { + rr := &RunResult{Args: cmd.Args} + sc := &StartedCmd{cmd: cmd, rr: rr} + klog.Infof("Start: %v", rr.Command()) + + var outb, errb io.Writer + if cmd.Stdout == nil { + var so bytes.Buffer + outb = io.MultiWriter(&so, &rr.Stdout) + } else { + outb = io.MultiWriter(cmd.Stdout, &rr.Stdout) + } + + if cmd.Stderr == nil { + var se bytes.Buffer + errb = io.MultiWriter(&se, &rr.Stderr) + } else { + errb = io.MultiWriter(cmd.Stderr, &rr.Stderr) + } + + cmd.Stdout = outb + cmd.Stderr = errb + + if err := cmd.Start(); err != nil { + return sc, errors.Wrap(err, "start") + } + + return sc, nil +} + +// WaitCmd implements the Command Runner interface to wait until a started exec.Cmd object finishes +func (*execRunner) WaitCmd(sc *StartedCmd) (*RunResult, error) { + rr := sc.rr + + err := sc.cmd.Wait() + if exitError, ok := err.(*exec.ExitError); ok { + rr.ExitCode = exitError.ExitCode() + } + + if err == nil { + return rr, nil + } + + return rr, fmt.Errorf("%s: %v\nstdout:\n%s\nstderr:\n%s", rr.Command(), err, rr.Stdout.String(), rr.Stderr.String()) +} + // Copy copies a file and its permissions func (e *execRunner) Copy(f assets.CopyableFile) error { dst := path.Join(f.GetTargetDir(), f.GetTargetName()) diff --git a/pkg/minikube/command/fake_runner.go b/pkg/minikube/command/fake_runner.go index e1b8f86150..b663ff7a38 100644 --- a/pkg/minikube/command/fake_runner.go +++ b/pkg/minikube/command/fake_runner.go @@ -90,6 +90,47 @@ func (f *FakeCommandRunner) RunCmd(cmd *exec.Cmd) (*RunResult, error) { return rr, nil } +// StartCmd implements the Command Runner interface to start a exec.Cmd object +func (f *FakeCommandRunner) StartCmd(cmd *exec.Cmd) (*StartedCmd, error) { + rr := &RunResult{Args: cmd.Args} + sc := &StartedCmd{cmd: cmd, rr: rr} + klog.Infof("(FakeCommandRunner) Start: %v", rr.Command()) + + key := rr.Command() + out, ok := f.cmdMap.Load(key) + if !ok { + cmds := f.commands() + if len(cmds) == 0 { + return sc, fmt.Errorf("asked to execute %s, but FakeCommandRunner has no commands stored", rr.Command()) + } + + var txt strings.Builder + for _, c := range f.commands() { + txt.WriteString(fmt.Sprintf(" `%s`\n", c)) + } + return sc, fmt.Errorf("unregistered command:\n `%s`\nexpected one of:\n%s", key, txt.String()) + } + + var buf bytes.Buffer + outStr := "" + if out != nil { + outStr = out.(string) + } + _, err := buf.WriteString(outStr) + if err != nil { + return sc, errors.Wrap(err, "Writing outStr to FakeCommandRunner's buffer") + } + rr.Stdout = buf + rr.Stderr = buf + + return sc, nil +} + +// WaitCmd implements the Command Runner interface to wait until a started exec.Cmd object finishes +func (f *FakeCommandRunner) WaitCmd(sc *StartedCmd) (*RunResult, error) { + return sc.rr, nil +} + // Copy adds the filename, file contents key value pair to the stored map. func (f *FakeCommandRunner) Copy(file assets.CopyableFile) error { var b bytes.Buffer diff --git a/pkg/minikube/command/fake_runner_test.go b/pkg/minikube/command/fake_runner_test.go new file mode 100644 index 0000000000..1d6d544709 --- /dev/null +++ b/pkg/minikube/command/fake_runner_test.go @@ -0,0 +1,118 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +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 command + +import ( + "os/exec" + "testing" + + "k8s.io/minikube/pkg/minikube/assets" +) + +func TestFakeRunnerFile(t *testing.T) { + fakeCommandRunner := NewFakeCommandRunner() + cmdArg := "test" + cmdToOutput := make(map[string]string) + cmdToOutput[cmdArg] = "123" + fakeCommandRunner.SetCommandToOutput(cmdToOutput) + + t.Run("SetGetFileContents", func(t *testing.T) { + fileToContentsMap := make(map[string]string) + fileName := "fileName" + expectedFileContents := "fileContents" + fileToContentsMap[fileName] = expectedFileContents + + fakeCommandRunner.SetFileToContents(fileToContentsMap) + + retrievedFileContents, err := fakeCommandRunner.GetFileToContents(fileName) + if err != nil { + t.Fatal(err) + } + + if expectedFileContents != retrievedFileContents { + t.Errorf("expected %q, retrieved %q", expectedFileContents, retrievedFileContents) + } + }) + + t.Run("CopyRemoveFile", func(t *testing.T) { + expectedFileContents := "test contents" + fileName := "memory" + file := assets.NewMemoryAssetTarget([]byte(expectedFileContents), "", "") + + if err := fakeCommandRunner.Copy(file); err != nil { + t.Fatal(err) + } + + retrievedFileContents, err := fakeCommandRunner.GetFileToContents(fileName) + if err != nil { + t.Fatal(err) + } + + if expectedFileContents != retrievedFileContents { + t.Errorf("expected %q, retrieved %q", expectedFileContents, retrievedFileContents) + } + + if err := fakeCommandRunner.Remove(file); err != nil { + t.Fatal(err) + } + + if _, err := fakeCommandRunner.GetFileToContents(fileName); err == nil { + t.Errorf("file was not removed") + } + }) + + t.Run("RunCmd", func(t *testing.T) { + expectedOutput := "123" + command := &exec.Cmd{Args: []string{cmdArg}} + + rr, err := fakeCommandRunner.RunCmd(command) + if err != nil { + t.Fatal(err) + } + + retrievedOutput := rr.Stdout.String() + if expectedOutput != retrievedOutput { + t.Errorf("expected %q, retrieved %q", expectedOutput, retrievedOutput) + } + }) + + t.Run("StartWaitCmd", func(t *testing.T) { + expectedOutput := "123" + command := &exec.Cmd{Args: []string{cmdArg}} + + sc, err := fakeCommandRunner.StartCmd(command) + if err != nil { + t.Fatal(err) + } + + retrievedOutput := sc.rr.Stdout.String() + if expectedOutput != retrievedOutput { + t.Errorf("expected %q, retrieved %q", expectedOutput, retrievedOutput) + } + + rr, err := fakeCommandRunner.WaitCmd(sc) + if err != nil { + t.Fatal(err) + } + + retrievedOutput = rr.Stdout.String() + if expectedOutput != retrievedOutput { + t.Errorf("expected %q, retrieved %q", expectedOutput, retrievedOutput) + } + + }) +} diff --git a/pkg/minikube/command/kic_runner.go b/pkg/minikube/command/kic_runner.go index 5cc78687bc..ae14308a22 100644 --- a/pkg/minikube/command/kic_runner.go +++ b/pkg/minikube/command/kic_runner.go @@ -131,6 +131,14 @@ func (k *kicRunner) RunCmd(cmd *exec.Cmd) (*RunResult, error) { } +func (k *kicRunner) StartCmd(cmd *exec.Cmd) (*StartedCmd, error) { + return nil, fmt.Errorf("kicRunner does not support StartCmd - you could be the first to add it") +} + +func (k *kicRunner) WaitCmd(sc *StartedCmd) (*RunResult, error) { + return nil, fmt.Errorf("kicRunner does not support WaitCmd - you could be the first to add it") +} + // Copy copies a file and its permissions func (k *kicRunner) Copy(f assets.CopyableFile) error { dst := path.Join(path.Join(f.GetTargetDir(), f.GetTargetName())) diff --git a/pkg/minikube/command/ssh_runner.go b/pkg/minikube/command/ssh_runner.go index 8dc2c15c8e..e2e6bc389e 100644 --- a/pkg/minikube/command/ssh_runner.go +++ b/pkg/minikube/command/ssh_runner.go @@ -46,6 +46,7 @@ var ( type SSHRunner struct { d drivers.Driver c *ssh.Client + s *ssh.Session } // NewSSHRunner returns a new SSHRunner that will run commands @@ -194,6 +195,100 @@ func (s *SSHRunner) RunCmd(cmd *exec.Cmd) (*RunResult, error) { return rr, fmt.Errorf("%s: %v\nstdout:\n%s\nstderr:\n%s", rr.Command(), err, rr.Stdout.String(), rr.Stderr.String()) } +// teeSSHStart starts a non-blocking SSH command, streaming stdout, stderr to logs +func teeSSHStart(s *ssh.Session, cmd string, outB io.Writer, errB io.Writer) error { + outPipe, err := s.StdoutPipe() + if err != nil { + return errors.Wrap(err, "stdout") + } + + errPipe, err := s.StderrPipe() + if err != nil { + return errors.Wrap(err, "stderr") + } + + go func() { + if err := teePrefix(ErrPrefix, errPipe, errB, klog.V(8).Infof); err != nil { + klog.Errorf("tee stderr: %v", err) + } + }() + go func() { + if err := teePrefix(OutPrefix, outPipe, outB, klog.V(8).Infof); err != nil { + klog.Errorf("tee stdout: %v", err) + } + }() + + return s.Start(cmd) +} + +// StartCmd implements the Command Runner interface to start a exec.Cmd object +func (s *SSHRunner) StartCmd(cmd *exec.Cmd) (*StartedCmd, error) { + if cmd.Stdin != nil { + return nil, fmt.Errorf("SSHRunner does not support stdin - you could be the first to add it") + } + + if s.s != nil { + return nil, fmt.Errorf("another SSH command has been started and is currently running") + } + + rr := &RunResult{Args: cmd.Args} + sc := &StartedCmd{cmd: cmd, rr: rr} + klog.Infof("Start: %v", rr.Command()) + + var outb, errb io.Writer + + if cmd.Stdout == nil { + var so bytes.Buffer + outb = io.MultiWriter(&so, &rr.Stdout) + } else { + outb = io.MultiWriter(cmd.Stdout, &rr.Stdout) + } + + if cmd.Stderr == nil { + var se bytes.Buffer + errb = io.MultiWriter(&se, &rr.Stderr) + } else { + errb = io.MultiWriter(cmd.Stderr, &rr.Stderr) + } + + sess, err := s.session() + if err != nil { + return sc, errors.Wrap(err, "NewSession") + } + + s.s = sess + + err = teeSSHStart(s.s, shellquote.Join(cmd.Args...), outb, errb) + + return sc, err +} + +// WaitCmd implements the Command Runner interface to wait until a started exec.Cmd object finishes +func (s *SSHRunner) WaitCmd(sc *StartedCmd) (*RunResult, error) { + if s.s == nil { + return nil, fmt.Errorf("there is no SSH command started") + } + + rr := sc.rr + + err := s.s.Wait() + if exitError, ok := err.(*exec.ExitError); ok { + rr.ExitCode = exitError.ExitCode() + } + + if err := s.s.Close(); err != io.EOF { + klog.Errorf("session close: %v", err) + } + + s.s = nil + + if err == nil { + return rr, nil + } + + return rr, fmt.Errorf("%s: %v\nstdout:\n%s\nstderr:\n%s", rr.Command(), err, rr.Stdout.String(), rr.Stderr.String()) +} + // Copy copies a file to the remote over SSH. func (s *SSHRunner) Copy(f assets.CopyableFile) error { dst := path.Join(path.Join(f.GetTargetDir(), f.GetTargetName())) diff --git a/pkg/minikube/cruntime/containerd_test.go b/pkg/minikube/cruntime/containerd_test.go index bd7227fc77..f354182221 100644 --- a/pkg/minikube/cruntime/containerd_test.go +++ b/pkg/minikube/cruntime/containerd_test.go @@ -25,7 +25,7 @@ func TestAddRepoTagToImageName(t *testing.T) { imgName string want string }{ - {"kubernetesui/dashboard:v2.0.3", "docker.io/kubernetesui/dashboard:v2.0.3"}, + {"kubernetesui/dashboard:v2.1.0", "docker.io/kubernetesui/dashboard:v2.1.0"}, {"kubernetesui/metrics-scraper:v1.0.4", "docker.io/kubernetesui/metrics-scraper:v1.0.4"}, {"gcr.io/k8s-minikube/storage-provisioner:v4", "gcr.io/k8s-minikube/storage-provisioner:v4"}, } diff --git a/pkg/minikube/cruntime/cruntime.go b/pkg/minikube/cruntime/cruntime.go index b6c67c8a13..5d0b4b6c5f 100644 --- a/pkg/minikube/cruntime/cruntime.go +++ b/pkg/minikube/cruntime/cruntime.go @@ -53,7 +53,15 @@ func ValidRuntimes() []string { // CommandRunner is the subset of command.Runner this package consumes type CommandRunner interface { + // RunCmd is a blocking method that runs a command + // Use this if you don't need to stream stdout and stderr in real-time RunCmd(cmd *exec.Cmd) (*command.RunResult, error) + // StartCmd is a non-blocking method that starts a command + // Use WaitCmd to block until the command is complete + // Use this if you need to stream stdout and/or stderr in real-time + StartCmd(cmd *exec.Cmd) (*command.StartedCmd, error) + // WaitCmd blocks until the started command completes + WaitCmd(sc *command.StartedCmd) (*command.RunResult, error) // Copy is a convenience method that runs a command to copy a file Copy(assets.CopyableFile) error // Remove is a convenience method that runs a command to remove a file diff --git a/pkg/minikube/cruntime/cruntime_test.go b/pkg/minikube/cruntime/cruntime_test.go index 3bd39bac78..11acd37c13 100644 --- a/pkg/minikube/cruntime/cruntime_test.go +++ b/pkg/minikube/cruntime/cruntime_test.go @@ -217,6 +217,14 @@ func (f *FakeRunner) RunCmd(cmd *exec.Cmd) (*command.RunResult, error) { } } +func (f *FakeRunner) StartCmd(cmd *exec.Cmd) (*command.StartedCmd, error) { + return &command.StartedCmd{}, nil +} + +func (f *FakeRunner) WaitCmd(sc *command.StartedCmd) (*command.RunResult, error) { + return &command.RunResult{}, nil +} + func (f *FakeRunner) Copy(assets.CopyableFile) error { return nil } diff --git a/pkg/minikube/machine/ssh.go b/pkg/minikube/machine/ssh.go index c547ed09d7..7d8404e8c6 100644 --- a/pkg/minikube/machine/ssh.go +++ b/pkg/minikube/machine/ssh.go @@ -17,7 +17,11 @@ limitations under the License. package machine import ( + "fmt" + "os/exec" + "github.com/docker/machine/libmachine" + "github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/ssh" "github.com/docker/machine/libmachine/state" "github.com/pkg/errors" @@ -25,21 +29,30 @@ import ( "k8s.io/minikube/pkg/minikube/driver" ) -// CreateSSHShell creates a new SSH shell / client -func CreateSSHShell(api libmachine.API, cc config.ClusterConfig, n config.Node, args []string, native bool) error { +func getHost(api libmachine.API, cc config.ClusterConfig, n config.Node) (*host.Host, error) { machineName := driver.MachineName(cc, n) host, err := LoadHost(api, machineName) if err != nil { - return errors.Wrap(err, "host exists and load") + return nil, errors.Wrap(err, "host exists and load") } currentState, err := host.Driver.GetState() if err != nil { - return errors.Wrap(err, "state") + return nil, errors.Wrap(err, "state") } if currentState != state.Running { - return errors.Errorf("%q is not running", machineName) + return nil, errors.Errorf("%q is not running", machineName) + } + + return host, nil +} + +// CreateSSHShell creates a new SSH shell / client +func CreateSSHShell(api libmachine.API, cc config.ClusterConfig, n config.Node, args []string, native bool) error { + host, err := getHost(api, cc, n) + if err != nil { + return err } if native { @@ -55,3 +68,43 @@ func CreateSSHShell(api libmachine.API, cc config.ClusterConfig, n config.Node, } return client.Shell(args...) } + +func GetSSHHostAddrPort(api libmachine.API, cc config.ClusterConfig, n config.Node) (string, int, error) { + host, err := getHost(api, cc, n) + if err != nil { + return "", 0, err + } + + addr, err := host.Driver.GetSSHHostname() + if err != nil { + return "", 0, err + } + port, err := host.Driver.GetSSHPort() + if err != nil { + return "", 0, err + } + + return addr, port, nil +} + +// RunSSHHostCommand runs a command to the SSH host +func RunSSHHostCommand(api libmachine.API, cc config.ClusterConfig, n config.Node, command string, args []string) (string, error) { + addr, port, err := GetSSHHostAddrPort(api, cc, n) + if err != nil { + return "", err + } + + cmdPath, err := exec.LookPath(command) + if err != nil { + return "", err + } + + args = append(args, "-p") + args = append(args, fmt.Sprintf("%d", port)) + + args = append(args, addr) + + cmd := exec.Command(cmdPath, args...) + output, err := cmd.Output() + return string(output), err +} diff --git a/pkg/minikube/out/register/register.go b/pkg/minikube/out/register/register.go index 985d81463d..ebb6c13a4c 100644 --- a/pkg/minikube/out/register/register.go +++ b/pkg/minikube/out/register/register.go @@ -26,20 +26,23 @@ import ( // If you add a new step here, please also add it to register.Reg registry inside the init() function const ( - InitialSetup RegStep = "Initial Minikube Setup" - SelectingDriver RegStep = "Selecting Driver" - DownloadingArtifacts RegStep = "Downloading Artifacts" - StartingNode RegStep = "Starting Node" - PullingBaseImage RegStep = "Pulling Base Image" - RunningLocalhost RegStep = "Running on Localhost" - LocalOSRelease RegStep = "Local OS Release" - CreatingContainer RegStep = "Creating Container" - CreatingVM RegStep = "Creating VM" - ConfiguringLHEnv RegStep = "Configuring Localhost Environment" - PreparingKubernetes RegStep = "Preparing Kubernetes" - VerifyingKubernetes RegStep = "Verifying Kubernetes" - EnablingAddons RegStep = "Enabling Addons" - Done RegStep = "Done" + InitialSetup RegStep = "Initial Minikube Setup" + SelectingDriver RegStep = "Selecting Driver" + DownloadingArtifacts RegStep = "Downloading Artifacts" + StartingNode RegStep = "Starting Node" + PullingBaseImage RegStep = "Pulling Base Image" + RunningLocalhost RegStep = "Running on Localhost" + LocalOSRelease RegStep = "Local OS Release" + CreatingContainer RegStep = "Creating Container" + CreatingVM RegStep = "Creating VM" + ConfiguringLHEnv RegStep = "Configuring Localhost Environment" + PreparingKubernetes RegStep = "Preparing Kubernetes" + PreparingKubernetesCerts RegStep = "Generating certificates" + PreparingKubernetesControlPlane RegStep = "Booting control plane" + PreparingKubernetesBootstrapToken RegStep = "Configuring RBAC rules" + VerifyingKubernetes RegStep = "Verifying Kubernetes" + EnablingAddons RegStep = "Enabling Addons" + Done RegStep = "Done" Stopping RegStep = "Stopping" PowerOff RegStep = "PowerOff" @@ -77,6 +80,9 @@ func init() { CreatingContainer, CreatingVM, PreparingKubernetes, + PreparingKubernetesCerts, + PreparingKubernetesControlPlane, + PreparingKubernetesBootstrapToken, ConfiguringLHEnv, VerifyingKubernetes, EnablingAddons, diff --git a/pkg/minikube/sshutil/sshutil.go b/pkg/minikube/sshutil/sshutil.go index ab3633fb48..94164f1046 100644 --- a/pkg/minikube/sshutil/sshutil.go +++ b/pkg/minikube/sshutil/sshutil.go @@ -17,7 +17,9 @@ limitations under the License. package sshutil import ( + "bufio" "net" + "os" "strconv" "time" @@ -25,6 +27,7 @@ import ( machinessh "github.com/docker/machine/libmachine/ssh" "github.com/pkg/errors" "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/knownhosts" "k8s.io/klog/v2" "k8s.io/minikube/pkg/util/retry" @@ -89,3 +92,28 @@ func newSSHHost(d drivers.Driver) (*sshHost, error) { Username: d.GetSSHUsername(), }, nil } + +func KnownHost(host string, knownHosts string) bool { + fd, err := os.Open(knownHosts) + if err != nil { + return false + } + defer fd.Close() + + hashhost := knownhosts.HashHostname(host) + scanner := bufio.NewScanner(fd) + for scanner.Scan() { + _, hosts, _, _, _, err := ssh.ParseKnownHosts(scanner.Bytes()) + if err != nil { + continue + } + + for _, h := range hosts { + if h == host || h == hashhost { + return true + } + } + } + + return false +} diff --git a/pkg/minikube/style/style.go b/pkg/minikube/style/style.go index 4bd9eaaf32..8f9c653e77 100644 --- a/pkg/minikube/style/style.go +++ b/pkg/minikube/style/style.go @@ -127,6 +127,7 @@ var Config = map[Enum]Options{ Shutdown: {Prefix: "🛑 "}, StartingNone: {Prefix: "🤹 "}, StartingVM: {Prefix: "🔥 "}, + SubStep: {Prefix: " ▪ ", LowPrefix: LowIndent, OmitNewline: true, Spinner: true}, // Indented bullet Tip: {Prefix: "💡 "}, Unmount: {Prefix: "🔥 "}, VerifyingNoLine: {Prefix: "🤔 ", OmitNewline: true}, diff --git a/pkg/minikube/style/style_enum.go b/pkg/minikube/style/style_enum.go index 6489e1ab3b..63a6c49e9f 100644 --- a/pkg/minikube/style/style_enum.go +++ b/pkg/minikube/style/style_enum.go @@ -84,6 +84,7 @@ const ( StartingVM Stopped Stopping + SubStep Success ThumbsDown ThumbsUp diff --git a/site/content/en/docs/commands/ip.md b/site/content/en/docs/commands/ip.md index 044e4435d7..a460649225 100644 --- a/site/content/en/docs/commands/ip.md +++ b/site/content/en/docs/commands/ip.md @@ -1,22 +1,28 @@ --- title: "ip" description: > - Retrieves the IP address of the running cluster + Retrieves the IP address of the specified node --- ## minikube ip -Retrieves the IP address of the running cluster +Retrieves the IP address of the specified node ### Synopsis -Retrieves the IP address of the running cluster, and writes it to STDOUT. +Retrieves the IP address of the specified node, and writes it to STDOUT. ```shell minikube ip [flags] ``` +### Options + +``` + -n, --node string The node to get IP. Defaults to the primary control plane. +``` + ### Options inherited from parent commands ``` diff --git a/site/content/en/docs/commands/ssh-host.md b/site/content/en/docs/commands/ssh-host.md new file mode 100644 index 0000000000..38ad0b8750 --- /dev/null +++ b/site/content/en/docs/commands/ssh-host.md @@ -0,0 +1,47 @@ +--- +title: "ssh-host" +description: > + Retrieve the ssh host key of the specified node +--- + + +## minikube ssh-host + +Retrieve the ssh host key of the specified node + +### Synopsis + +Retrieve the ssh host key of the specified node. + +```shell +minikube ssh-host [flags] +``` + +### Options + +``` + --append-known Add host key to SSH known_hosts file + -n, --node string The node to ssh into. Defaults to the primary control plane. +``` + +### Options inherited from parent commands + +``` + --add_dir_header If true, adds the file directory to the header of the log messages + --alsologtostderr log to standard error as well as files + -b, --bootstrapper string The name of the cluster bootstrapper that will set up the Kubernetes cluster. (default "kubeadm") + -h, --help + --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) + --log_dir string If non-empty, write log files in this directory + --log_file string If non-empty, use this log file + --log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) + --logtostderr log to standard error instead of files + --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level + -p, --profile string The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently. (default "minikube") + --skip_headers If true, avoid header prefixes in the log messages + --skip_log_headers If true, avoid headers when opening log files + --stderrthreshold severity logs at or above this threshold go to stderr (default 2) + -v, --v Level number for the log level verbosity + --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging +``` + diff --git a/site/content/en/docs/commands/ssh-key.md b/site/content/en/docs/commands/ssh-key.md index 5abba114ad..76687f7377 100644 --- a/site/content/en/docs/commands/ssh-key.md +++ b/site/content/en/docs/commands/ssh-key.md @@ -1,22 +1,28 @@ --- title: "ssh-key" description: > - Retrieve the ssh identity key path of the specified cluster + Retrieve the ssh identity key path of the specified node --- ## minikube ssh-key -Retrieve the ssh identity key path of the specified cluster +Retrieve the ssh identity key path of the specified node ### Synopsis -Retrieve the ssh identity key path of the specified cluster. +Retrieve the ssh identity key path of the specified node, and writes it to STDOUT. ```shell minikube ssh-key [flags] ``` +### Options + +``` + -n, --node string The node to get ssh-key path. Defaults to the primary control plane. +``` + ### Options inherited from parent commands ``` diff --git a/test/integration/error_spam_test.go b/test/integration/error_spam_test.go index 48f8ba1b79..1baf483cdd 100644 --- a/test/integration/error_spam_test.go +++ b/test/integration/error_spam_test.go @@ -91,4 +91,17 @@ func TestErrorSpam(t *testing.T) { t.Logf("minikube stdout:\n%s", stdout) t.Logf("minikube stderr:\n%s", stderr) } + + t.Run("KubeadmSteps", func(t *testing.T) { + steps := []string{ + "Generating certificates and keys ...", + "Booting up control plane ...", + "Configuring RBAC rules ...", + } + for _, step := range steps { + if !strings.Contains(stdout, step) { + t.Errorf("missing kubeadm init sub-step %q", step) + } + } + }) } diff --git a/test/integration/start_stop_delete_test.go b/test/integration/start_stop_delete_test.go index 01534f8220..30250b61d3 100644 --- a/test/integration/start_stop_delete_test.go +++ b/test/integration/start_stop_delete_test.go @@ -370,10 +370,10 @@ func testPause(ctx context.Context, t *testing.T, profile string) { // Remove container-specific prefixes for naming consistency // for example in `docker` runtime we get this: // $ docker@minikube:~$ sudo crictl images -o json | grep dash -// "kubernetesui/dashboard:v2.0.3" +// "kubernetesui/dashboard:v2.1.0" // but for 'containerd' we get full name // $ docker@minikube:~$ sudo crictl images -o json | grep dash -// "docker.io/kubernetesui/dashboard:v2.0.3" +// "docker.io/kubernetesui/dashboard:v2.1.0" func trimImageName(name string) string { name = strings.TrimPrefix(name, "docker.io/") name = strings.TrimPrefix(name, "localhost/")