Merge branch 'master' of github.com:kubernetes/minikube into master
commit
bd721de0cf
|
@ -151,14 +151,14 @@ var mountCmd = &cobra.Command{
|
|||
bindIP = "127.0.0.1"
|
||||
}
|
||||
out.T(out.Mounting, "Mounting host path {{.sourcePath}} into VM as {{.destinationPath}} ...", out.V{"sourcePath": hostPath, "destinationPath": vmPath})
|
||||
out.T(out.Option, "Mount type: {{.name}}", out.V{"type": cfg.Type})
|
||||
out.T(out.Option, "User ID: {{.userID}}", out.V{"userID": cfg.UID})
|
||||
out.T(out.Option, "Group ID: {{.groupID}}", out.V{"groupID": cfg.GID})
|
||||
out.T(out.Option, "Version: {{.version}}", out.V{"version": cfg.Version})
|
||||
out.T(out.Option, "Message Size: {{.size}}", out.V{"size": cfg.MSize})
|
||||
out.T(out.Option, "Permissions: {{.octalMode}} ({{.writtenMode}})", out.V{"octalMode": fmt.Sprintf("%o", cfg.Mode), "writtenMode": cfg.Mode})
|
||||
out.T(out.Option, "Options: {{.options}}", out.V{"options": cfg.Options})
|
||||
out.T(out.Option, "Bind Address: {{.Address}}", out.V{"Address": net.JoinHostPort(bindIP, fmt.Sprint(port))})
|
||||
out.Infof("Mount type: {{.name}}", out.V{"type": cfg.Type})
|
||||
out.Infof("User ID: {{.userID}}", out.V{"userID": cfg.UID})
|
||||
out.Infof("Group ID: {{.groupID}}", out.V{"groupID": cfg.GID})
|
||||
out.Infof("Version: {{.version}}", out.V{"version": cfg.Version})
|
||||
out.Infof("Message Size: {{.size}}", out.V{"size": cfg.MSize})
|
||||
out.Infof("Permissions: {{.octalMode}} ({{.writtenMode}})", out.V{"octalMode": fmt.Sprintf("%o", cfg.Mode), "writtenMode": cfg.Mode})
|
||||
out.Infof("Options: {{.options}}", out.V{"options": cfg.Options})
|
||||
out.Infof("Bind Address: {{.Address}}", out.V{"Address": net.JoinHostPort(bindIP, fmt.Sprint(port))})
|
||||
|
||||
var wg sync.WaitGroup
|
||||
if cfg.Type == nineP {
|
||||
|
|
|
@ -57,6 +57,8 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/node"
|
||||
"k8s.io/minikube/pkg/minikube/notify"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/out/register"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/registry"
|
||||
"k8s.io/minikube/pkg/minikube/translate"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
|
@ -122,6 +124,7 @@ func platform() string {
|
|||
|
||||
// runStart handles the executes the flow of "minikube start"
|
||||
func runStart(cmd *cobra.Command, args []string) {
|
||||
out.SetJSON(viper.GetString(startOutput) == "json")
|
||||
displayVersion(version.GetVersion())
|
||||
|
||||
// No need to do the update check if no one is going to see it
|
||||
|
@ -348,6 +351,7 @@ func displayVersion(version string) {
|
|||
prefix = fmt.Sprintf("[%s] ", ClusterFlagValue())
|
||||
}
|
||||
|
||||
register.Reg.SetStep(register.InitialSetup)
|
||||
out.T(out.Happy, "{{.prefix}}minikube {{.version}} on {{.platform}}", out.V{"prefix": prefix, "version": version, "platform": platform()})
|
||||
}
|
||||
|
||||
|
@ -358,12 +362,13 @@ func displayEnviron(env []string) {
|
|||
k := bits[0]
|
||||
v := bits[1]
|
||||
if strings.HasPrefix(k, "MINIKUBE_") || k == constants.KubeconfigEnvVar {
|
||||
out.T(out.Option, "{{.key}}={{.value}}", out.V{"key": k, "value": v})
|
||||
out.Infof("{{.key}}={{.value}}", out.V{"key": k, "value": v})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func showKubectlInfo(kcs *kubeconfig.Settings, k8sVersion string, machineName string) error {
|
||||
register.Reg.SetStep(register.Done)
|
||||
if kcs.KeepContext {
|
||||
out.T(out.Kubectl, "To connect to this cluster, use: kubectl --context={{.name}}", out.V{"name": kcs.ClusterName})
|
||||
} else {
|
||||
|
@ -476,7 +481,7 @@ func kubectlVersion(path string) (string, error) {
|
|||
func selectDriver(existing *config.ClusterConfig) (registry.DriverState, []registry.DriverState, bool) {
|
||||
// Technically unrelated, but important to perform before detection
|
||||
driver.SetLibvirtURI(viper.GetString(kvmQemuURI))
|
||||
|
||||
register.Reg.SetStep(register.SelectingDriver)
|
||||
// By default, the driver is whatever we used last time
|
||||
if existing != nil {
|
||||
old := hostDriver(existing)
|
||||
|
@ -520,7 +525,7 @@ func selectDriver(existing *config.ClusterConfig) (registry.DriverState, []regis
|
|||
if pick.Name == "" {
|
||||
out.T(out.ThumbsDown, "Unable to pick a default driver. Here is what was considered, in preference order:")
|
||||
for _, r := range rejects {
|
||||
out.T(out.Option, "{{ .name }}: {{ .rejection }}", out.V{"name": r.Name, "rejection": r.Rejection})
|
||||
out.Infof("{{ .name }}: {{ .rejection }}", out.V{"name": r.Name, "rejection": r.Rejection})
|
||||
}
|
||||
out.T(out.Workaround, "Try specifying a --driver, or see https://minikube.sigs.k8s.io/docs/start/")
|
||||
os.Exit(exit.Unavailable)
|
||||
|
@ -921,6 +926,10 @@ func validateFlags(cmd *cobra.Command, drvName string) {
|
|||
}
|
||||
}
|
||||
|
||||
if s := viper.GetString(startOutput); s != "text" && s != "json" {
|
||||
exit.UsageT("Sorry, please set the --output flag to one of the following valid options: [text,json]")
|
||||
}
|
||||
|
||||
validateRegistryMirror()
|
||||
}
|
||||
|
||||
|
@ -980,6 +989,10 @@ func autoSetDriverOptions(cmd *cobra.Command, drvName string) (err error) {
|
|||
hints := driver.FlagDefaults(drvName)
|
||||
if len(hints.ExtraOptions) > 0 {
|
||||
for _, eo := range hints.ExtraOptions {
|
||||
if config.ExtraOptions.Exists(eo) {
|
||||
glog.Infof("skipping extra-config %q.", eo)
|
||||
continue
|
||||
}
|
||||
glog.Infof("auto setting extra-config to %q.", eo)
|
||||
err = config.ExtraOptions.Set(eo)
|
||||
if err != nil {
|
||||
|
|
|
@ -104,6 +104,7 @@ const (
|
|||
deleteOnFailure = "delete-on-failure"
|
||||
forceSystemd = "force-systemd"
|
||||
kicBaseImage = "base-image"
|
||||
startOutput = "output"
|
||||
)
|
||||
|
||||
// initMinikubeFlags includes commandline flags for minikube.
|
||||
|
@ -144,6 +145,7 @@ func initMinikubeFlags() {
|
|||
startCmd.Flags().Bool(preload, true, "If set, download tarball of preloaded images if available to improve start time. Defaults to true.")
|
||||
startCmd.Flags().Bool(deleteOnFailure, false, "If set, delete the current cluster if start fails and try again. Defaults to false.")
|
||||
startCmd.Flags().Bool(forceSystemd, false, "If set, force the container runtime to use sytemd as cgroup manager. Currently available for docker and crio. Defaults to false.")
|
||||
startCmd.Flags().String(startOutput, "text", "Format to print stdout in. Options include: [text,json]")
|
||||
}
|
||||
|
||||
// initKubernetesFlags inits the commandline flags for Kubernetes related options
|
||||
|
|
2
go.mod
2
go.mod
|
@ -11,6 +11,7 @@ require (
|
|||
github.com/c4milo/gotoolkit v0.0.0-20170318115440-bcc06269efa9 // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/cheggaaa/pb/v3 v3.0.1
|
||||
github.com/cloudevents/sdk-go/v2 v2.1.0
|
||||
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
|
||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 // indirect
|
||||
github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57 // indirect
|
||||
|
@ -28,6 +29,7 @@ require (
|
|||
github.com/google/go-containerregistry v0.0.0-20200601195303-96cf69f03a3c
|
||||
github.com/google/go-github v17.0.0+incompatible
|
||||
github.com/google/slowjam v0.0.0-20200530021616-df27e642fe7b
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/googleapis/gnostic v0.3.0 // indirect
|
||||
github.com/hashicorp/go-getter v1.4.0
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6
|
||||
|
|
9
go.sum
9
go.sum
|
@ -212,6 +212,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
|
|||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudevents/sdk-go/v2 v2.1.0 h1:bmgrU8k+K2ppZ+G/q5xEQx/Xk9HRtJmkrEO3qtDO2k0=
|
||||
github.com/cloudevents/sdk-go/v2 v2.1.0/go.mod h1:3CTrpB4+u7Iaj6fd7E2Xvm5IxMdRoaAhqaRVnOr2rCU=
|
||||
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:Yg2hDs4b13Evkpj42FU2idX2cVXVFqQSheXYKM86Qsk=
|
||||
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:MgJyK38wkzZbiZSKeIeFankxxSA8gayko/nr5x5bgBA=
|
||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
|
||||
|
@ -719,6 +721,8 @@ github.com/libvirt/libvirt-go v3.4.0+incompatible h1:Cpyalgj1x8JIeTlL6SDYZBo7j8n
|
|||
github.com/libvirt/libvirt-go v3.4.0+incompatible/go.mod h1:34zsnB4iGeOv7Byj6qotuW8Ya4v4Tr43ttjz/F0wjLE=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
||||
github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac h1:+2b6iGRJe3hvV/yVXrd41yVEjxuFHxasJqDhkIjS4gk=
|
||||
github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac/go.mod h1:Frd2bnT3w5FB5q49ENTfVlztJES+1k/7lyWX2+9gq/M=
|
||||
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
|
||||
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
|
@ -855,6 +859,7 @@ github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
|||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||
|
@ -1093,6 +1098,7 @@ github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
|||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
|
||||
github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
|
||||
github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
|
||||
|
@ -1136,8 +1142,11 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI=
|
||||
|
|
|
@ -40,6 +40,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/out/register"
|
||||
"k8s.io/minikube/pkg/minikube/storageclass"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
)
|
||||
|
@ -382,6 +383,7 @@ func Start(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]boo
|
|||
var awg sync.WaitGroup
|
||||
|
||||
defer func() { // making it show after verifications( not perfect till #7613 is closed)
|
||||
register.Reg.SetStep(register.EnablingAddons)
|
||||
out.T(out.AddonEnable, "Enabled addons: {{.addons}}", out.V{"addons": strings.Join(toEnableList, ", ")})
|
||||
}()
|
||||
for _, a := range toEnableList {
|
||||
|
|
|
@ -20,7 +20,6 @@ package hyperkit
|
|||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
|
|
|
@ -16,7 +16,17 @@ limitations under the License.
|
|||
|
||||
package kubeadm
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// max minutes wait for kubeadm init. usually finishes in less than 1 minute.
|
||||
// giving it a generous timeout for possible super slow machines.
|
||||
const initTimeoutMinutes = 10
|
||||
|
||||
// max seconds to wait for running kubectl apply manifests to the cluster to exit
|
||||
const applyTimeoutSeconds = 10
|
||||
|
||||
// FailFastError type is an error that could not be solved by trying again
|
||||
type FailFastError struct {
|
||||
|
@ -30,3 +40,6 @@ func (f *FailFastError) Error() string {
|
|||
// ErrNoExecLinux is thrown on linux when the kubeadm binaries are mounted in a noexec volume on Linux as seen in https://github.com/kubernetes/minikube/issues/8327#issuecomment-651288459
|
||||
// this error could be seen on docker/podman or none driver.
|
||||
var ErrNoExecLinux = &FailFastError{errors.New("mounted kubeadm binary is not executable")}
|
||||
|
||||
// ErrInitTimedout is thrown if kubeadm init takes longer than max time allowed
|
||||
var ErrInitTimedout = fmt.Errorf("kubeadm init timed out in %d minutes", initTimeoutMinutes)
|
||||
|
|
|
@ -55,6 +55,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/driver"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/out/register"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
|
@ -224,9 +225,15 @@ func (k *Bootstrapper) init(cfg config.ClusterConfig) error {
|
|||
}
|
||||
|
||||
conf := bsutil.KubeadmYamlPath
|
||||
c := exec.Command("/bin/bash", "-c", fmt.Sprintf("%s init --config %s %s --ignore-preflight-errors=%s",
|
||||
ctx, cancel := context.WithTimeout(context.Background(), initTimeoutMinutes*time.Minute)
|
||||
defer cancel()
|
||||
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 {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return ErrInitTimedout
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "'kubeadm': Permission denied") {
|
||||
return ErrNoExecLinux
|
||||
}
|
||||
|
@ -394,6 +401,7 @@ func (k *Bootstrapper) WaitForNode(cfg config.ClusterConfig, n config.Node, time
|
|||
return nil
|
||||
}
|
||||
|
||||
register.Reg.SetStep(register.VerifyingKubernetes)
|
||||
out.T(out.HealthCheck, "Verifying Kubernetes components...")
|
||||
|
||||
// TODO: #7706: for better performance we could use k.client inside minikube to avoid asking for external IP:PORT
|
||||
|
@ -830,8 +838,7 @@ func (k *Bootstrapper) applyNodeLabels(cfg config.ClusterConfig) error {
|
|||
commitLbl := "minikube.k8s.io/commit=" + version.GetGitCommitID()
|
||||
nameLbl := "minikube.k8s.io/name=" + cfg.Name
|
||||
|
||||
// Allow no more than 5 seconds for applying labels
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), applyTimeoutSeconds*time.Second)
|
||||
defer cancel()
|
||||
// example:
|
||||
// sudo /var/lib/minikube/binaries/<version>/kubectl label nodes minikube.k8s.io/version=<version> minikube.k8s.io/commit=aa91f39ffbcf27dcbb93c4ff3f457c54e585cf4a-dirty minikube.k8s.io/name=p1 minikube.k8s.io/updated_at=2020_02_20T12_05_35_0700 --all --overwrite --kubeconfig=/var/lib/minikube/kubeconfig
|
||||
|
@ -840,6 +847,9 @@ func (k *Bootstrapper) applyNodeLabels(cfg config.ClusterConfig) error {
|
|||
fmt.Sprintf("--kubeconfig=%s", path.Join(vmpath.GuestPersistentDir, "kubeconfig")))
|
||||
|
||||
if _, err := k.c.RunCmd(cmd); err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return errors.Wrapf(err, "timeout apply labels")
|
||||
}
|
||||
return errors.Wrapf(err, "applying node labels")
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -17,6 +17,9 @@ limitations under the License.
|
|||
package cni
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
)
|
||||
|
||||
|
@ -637,6 +640,12 @@ func (c Flannel) String() string {
|
|||
|
||||
// Apply enables the CNI
|
||||
func (c Flannel) Apply(r Runner) error {
|
||||
// Mostly applicable to the 'none' driver
|
||||
_, err := r.RunCmd(exec.Command("stat", "/opt/cni/bin/portmap"))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "required 'portmap' CNI plug-in not found")
|
||||
}
|
||||
|
||||
return applyManifest(c.cc, r, manifestAsset([]byte(flannelTmpl)))
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package cni
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"text/template"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
@ -168,6 +169,12 @@ func (c KindNet) manifest() (assets.CopyableFile, error) {
|
|||
|
||||
// Apply enables the CNI
|
||||
func (c KindNet) Apply(r Runner) error {
|
||||
// This is mostly applicable to the 'none' driver
|
||||
_, err := r.RunCmd(exec.Command("stat", "/opt/cni/bin/portmap"))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "required 'portmap' CNI plug-in not found")
|
||||
}
|
||||
|
||||
m, err := c.manifest()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "manifest")
|
||||
|
|
|
@ -19,6 +19,8 @@ package config
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// ExtraOption is an extra option
|
||||
|
@ -38,6 +40,29 @@ type ExtraOptionSlice []ExtraOption
|
|||
// ComponentExtraOptionMap maps components to their extra opts, which is a map of keys to values
|
||||
type ComponentExtraOptionMap map[string]map[string]string
|
||||
|
||||
// Exists returns true if component.key (parsed from value) is already in ExtraOptionSlice
|
||||
func (es *ExtraOptionSlice) Exists(value string) bool {
|
||||
// The component is the value before the first dot.
|
||||
componentSplit := strings.SplitN(value, ".", 2)
|
||||
if len(componentSplit) != 2 {
|
||||
glog.Errorf("invalid value: must contain at least one period: %q", value)
|
||||
return false
|
||||
}
|
||||
|
||||
keySplit := strings.SplitN(componentSplit[1], "=", 2)
|
||||
if len(keySplit) != 2 {
|
||||
glog.Errorf("invalid value: must contain one equal sign: %q", value)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, opt := range *es {
|
||||
if opt.Component == componentSplit[0] && opt.Key == keySplit[0] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Set parses the string value into a slice
|
||||
func (es *ExtraOptionSlice) Set(value string) error {
|
||||
// The component is the value before the first dot.
|
||||
|
|
|
@ -79,6 +79,29 @@ func TestValidFlags(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestExists(t *testing.T) {
|
||||
extraOptions := ExtraOptionSlice{
|
||||
ExtraOption{Component: "c1", Key: "bar", Value: "c1-bar"},
|
||||
ExtraOption{Component: "c1", Key: "baz", Value: "c1-baz"},
|
||||
ExtraOption{Component: "c2", Key: "bar", Value: "c2-bar"},
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
searchString string
|
||||
expRes bool
|
||||
}{
|
||||
{"c1.bar=bar", true},
|
||||
{"c1.foo=foo", false},
|
||||
{"c2.bar=bar", true},
|
||||
{"c2.baz=baz", false},
|
||||
{"c3.baz=baz", false},
|
||||
} {
|
||||
if res := extraOptions.Exists(tc.searchString); res != tc.expRes {
|
||||
t.Errorf("Unexpected value. Expected %t, got %t", tc.expRes, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
extraOptions := ExtraOptionSlice{
|
||||
ExtraOption{Component: "c1", Key: "bar", Value: "c1-bar"},
|
||||
|
|
|
@ -39,6 +39,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/driver"
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/out/register"
|
||||
"k8s.io/minikube/pkg/minikube/proxy"
|
||||
"k8s.io/minikube/pkg/minikube/registry"
|
||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||
|
@ -257,9 +258,11 @@ func showHostInfo(cfg config.ClusterConfig) {
|
|||
return
|
||||
}
|
||||
if driver.IsKIC(cfg.Driver) { // TODO:medyagh add free disk space on docker machine
|
||||
register.Reg.SetStep(register.CreatingContainer)
|
||||
out.T(out.StartingVM, "Creating {{.driver_name}} {{.machine_type}} (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB) ...", out.V{"driver_name": cfg.Driver, "number_of_cpus": cfg.CPUs, "memory_size": cfg.Memory, "machine_type": machineType})
|
||||
return
|
||||
}
|
||||
register.Reg.SetStep(register.CreatingVM)
|
||||
out.T(out.StartingVM, "Creating {{.driver_name}} {{.machine_type}} (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB, Disk={{.disk_size}}MB) ...", out.V{"driver_name": cfg.Driver, "number_of_cpus": cfg.CPUs, "memory_size": cfg.Memory, "disk_size": cfg.DiskSize, "machine_type": machineType})
|
||||
}
|
||||
|
||||
|
|
|
@ -32,17 +32,19 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/out/register"
|
||||
"k8s.io/minikube/pkg/util/lock"
|
||||
)
|
||||
|
||||
func showVersionInfo(k8sVersion string, cr cruntime.Manager) {
|
||||
version, _ := cr.Version()
|
||||
register.Reg.SetStep(register.PreparingKubernetes)
|
||||
out.T(cr.Style(), "Preparing Kubernetes {{.k8sVersion}} on {{.runtime}} {{.runtimeVersion}} ...", out.V{"k8sVersion": k8sVersion, "runtime": cr.Name(), "runtimeVersion": version})
|
||||
for _, v := range config.DockerOpt {
|
||||
out.T(out.Option, "opt {{.docker_option}}", out.V{"docker_option": v})
|
||||
out.Infof("opt {{.docker_option}}", out.V{"docker_option": v})
|
||||
}
|
||||
for _, v := range config.DockerEnv {
|
||||
out.T(out.Option, "env {{.docker_env}}", out.V{"docker_env": v})
|
||||
out.Infof("env {{.docker_env}}", out.V{"docker_env": v})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/mustload"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/out/register"
|
||||
"k8s.io/minikube/pkg/minikube/proxy"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
|
@ -205,7 +206,7 @@ func Start(starter Starter, apiServer bool) (*kubeconfig.Settings, error) {
|
|||
|
||||
// Provision provisions the machine/container for the node
|
||||
func Provision(cc *config.ClusterConfig, n *config.Node, apiServer bool, delOnFail bool) (command.Runner, bool, libmachine.API, *host.Host, error) {
|
||||
|
||||
register.Reg.SetStep(register.StartingNode)
|
||||
name := driver.MachineName(*cc, *n)
|
||||
if apiServer {
|
||||
out.T(out.ThumbsUp, "Starting control plane node {{.name}} in cluster {{.cluster}}", out.V{"name": name, "cluster": cc.Name})
|
||||
|
@ -288,7 +289,7 @@ func setupKubeAdm(mAPI libmachine.API, cfg config.ClusterConfig, n config.Node,
|
|||
exit.WithError("Failed to get bootstrapper", err)
|
||||
}
|
||||
for _, eo := range config.ExtraOptions {
|
||||
out.T(out.Option, "{{.extra_option_component_name}}.{{.key}}={{.value}}", out.V{"extra_option_component_name": eo.Component, "key": eo.Key, "value": eo.Value})
|
||||
out.Infof("{{.extra_option_component_name}}.{{.key}}={{.value}}", out.V{"extra_option_component_name": eo.Component, "key": eo.Key, "value": eo.Value})
|
||||
}
|
||||
// Loads cached images, generates config files, download binaries
|
||||
// update cluster and set up certs
|
||||
|
@ -423,7 +424,7 @@ func validateNetwork(h *host.Host, r command.Runner, imageRepository string) (st
|
|||
out.T(out.Internet, "Found network options:")
|
||||
optSeen = true
|
||||
}
|
||||
out.T(out.Option, "{{.key}}={{.value}}", out.V{"key": k, "value": v})
|
||||
out.Infof("{{.key}}={{.value}}", out.V{"key": k, "value": v})
|
||||
ipExcluded := proxy.IsIPExcluded(ip) // Skip warning if minikube ip is already in NO_PROXY
|
||||
k = strings.ToUpper(k) // for http_proxy & https_proxy
|
||||
if (k == "HTTP_PROXY" || k == "HTTPS_PROXY") && !ipExcluded && !warnedOnce {
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
"k8s.io/minikube/pkg/minikube/out/register"
|
||||
"k8s.io/minikube/pkg/minikube/translate"
|
||||
)
|
||||
|
||||
|
@ -50,6 +51,8 @@ var (
|
|||
useColor = false
|
||||
// OverrideEnv is the environment variable used to override color/emoji usage
|
||||
OverrideEnv = "MINIKUBE_IN_STYLE"
|
||||
// JSON is whether or not we should output stdout in JSON format. Set using SetJSON()
|
||||
JSON = false
|
||||
)
|
||||
|
||||
// MaxLogEntries controls the number of log entries to show for each source
|
||||
|
@ -66,7 +69,25 @@ type V map[string]interface{}
|
|||
|
||||
// T writes a stylized and templated message to stdout
|
||||
func T(style StyleEnum, format string, a ...V) {
|
||||
if style == Option {
|
||||
Infof(format, a...)
|
||||
return
|
||||
}
|
||||
outStyled := ApplyTemplateFormatting(style, useColor, format, a...)
|
||||
if JSON {
|
||||
register.PrintStep(outStyled)
|
||||
return
|
||||
}
|
||||
String(outStyled)
|
||||
}
|
||||
|
||||
// Infof is used for informational logs (options, env variables, etc)
|
||||
func Infof(format string, a ...V) {
|
||||
outStyled := ApplyTemplateFormatting(Option, useColor, format, a...)
|
||||
if JSON {
|
||||
register.PrintInfo(outStyled)
|
||||
return
|
||||
}
|
||||
String(outStyled)
|
||||
}
|
||||
|
||||
|
@ -87,6 +108,10 @@ func String(format string, a ...interface{}) {
|
|||
|
||||
// Ln writes a basic formatted string with a newline to stdout
|
||||
func Ln(format string, a ...interface{}) {
|
||||
if JSON {
|
||||
glog.Warningf("please use out.T to log steps in JSON")
|
||||
return
|
||||
}
|
||||
String(format+"\n", a...)
|
||||
}
|
||||
|
||||
|
@ -140,6 +165,12 @@ func SetOutFile(w fdWriter) {
|
|||
useColor = wantsColor(w.Fd())
|
||||
}
|
||||
|
||||
// SetJSON configures printing to STDOUT in JSON
|
||||
func SetJSON(j bool) {
|
||||
glog.Infof("Setting JSON to %v", j)
|
||||
JSON = j
|
||||
}
|
||||
|
||||
// SetErrFile configures which writer error output goes to.
|
||||
func SetErrFile(w fdWriter) {
|
||||
glog.Infof("Setting ErrFile to fd %d...", w.Fd())
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2020 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 register
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
"github.com/golang/glog"
|
||||
guuid "github.com/google/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
specVersion = "1.0"
|
||||
)
|
||||
|
||||
var (
|
||||
outputFile io.Writer = os.Stdout
|
||||
getUUID = randomID
|
||||
)
|
||||
|
||||
func printAsCloudEvent(log Log, data map[string]string) {
|
||||
event := cloudevents.NewEvent()
|
||||
event.SetSource("https://minikube.sigs.k8s.io/")
|
||||
event.SetType(log.Type())
|
||||
event.SetSpecVersion(specVersion)
|
||||
if err := event.SetData(cloudevents.ApplicationJSON, data); err != nil {
|
||||
glog.Warningf("error setting data: %v", err)
|
||||
}
|
||||
event.SetID(getUUID())
|
||||
json, err := event.MarshalJSON()
|
||||
if err != nil {
|
||||
glog.Warningf("error marashalling event: %v", err)
|
||||
}
|
||||
fmt.Fprintln(outputFile, string(json))
|
||||
}
|
||||
|
||||
func randomID() string {
|
||||
return guuid.New().String()
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2020 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 register
|
||||
|
||||
// PrintStep prints a Step type in JSON format
|
||||
func PrintStep(message string) {
|
||||
s := NewStep(message)
|
||||
printAsCloudEvent(s, s.data)
|
||||
}
|
||||
|
||||
// PrintInfo prints an Info type in JSON format
|
||||
func PrintInfo(message string) {
|
||||
s := NewInfo(message)
|
||||
printAsCloudEvent(s, s.data)
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright 2020 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 register
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPrintStep(t *testing.T) {
|
||||
expected := `{"data":{"currentstep":"0","message":"message","name":"Initial Minikube Setup","totalsteps":"%v"},"datacontenttype":"application/json","id":"random-id","source":"https://minikube.sigs.k8s.io/","specversion":"1.0","type":"io.k8s.sigs.minikube.step"}`
|
||||
expected = fmt.Sprintf(expected, Reg.totalSteps())
|
||||
expected += "\n"
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
outputFile = buf
|
||||
defer func() { outputFile = os.Stdout }()
|
||||
|
||||
getUUID = func() string {
|
||||
return "random-id"
|
||||
}
|
||||
|
||||
PrintStep("message")
|
||||
actual := buf.String()
|
||||
|
||||
if actual != expected {
|
||||
t.Fatalf("expected didn't match actual:\nExpected:\n%v\n\nActual:\n%v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintInfo(t *testing.T) {
|
||||
expected := `{"data":{"message":"info"},"datacontenttype":"application/json","id":"random-id","source":"https://minikube.sigs.k8s.io/","specversion":"1.0","type":"io.k8s.sigs.minikube.info"}`
|
||||
expected += "\n"
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
outputFile = buf
|
||||
defer func() { outputFile = os.Stdout }()
|
||||
|
||||
getUUID = func() string {
|
||||
return "random-id"
|
||||
}
|
||||
|
||||
PrintInfo("info")
|
||||
actual := buf.String()
|
||||
|
||||
if actual != expected {
|
||||
t.Fatalf("expected didn't match actual:\nExpected:\n%v\n\nActual:\n%v", expected, actual)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
Copyright 2020 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 register
|
||||
|
||||
// Log represents the different types of logs that can be output as JSON
|
||||
// This includes: Step, Download, DownloadProgress, Warning, Info, Error
|
||||
type Log interface {
|
||||
Type() string
|
||||
}
|
||||
|
||||
// Step represents a normal step in minikube execution
|
||||
type Step struct {
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func (s *Step) Type() string {
|
||||
return "io.k8s.sigs.minikube.step"
|
||||
}
|
||||
|
||||
func NewStep(message string) *Step {
|
||||
return &Step{data: map[string]string{
|
||||
"totalsteps": Reg.totalSteps(),
|
||||
"currentstep": Reg.currentStep(),
|
||||
"message": message,
|
||||
"name": string(Reg.current),
|
||||
}}
|
||||
}
|
||||
|
||||
// TODO (priyawadhwa@): implement all types below this comment
|
||||
// Download will be used to notify the user that a download has begun
|
||||
type Download struct {
|
||||
}
|
||||
|
||||
func (s *Download) Type() string {
|
||||
return "io.k8s.sigs.minikube.download"
|
||||
}
|
||||
|
||||
// DownloadProgress will be used to notify the user around the progress of a download
|
||||
type DownloadProgress struct {
|
||||
}
|
||||
|
||||
func (s *DownloadProgress) Type() string {
|
||||
return "io.k8s.sigs.minikube.download.progress"
|
||||
}
|
||||
|
||||
// Warning will be used to notify the user of warnings
|
||||
type Warning struct {
|
||||
}
|
||||
|
||||
func (s *Warning) Type() string {
|
||||
return "io.k8s.sigs.minikube.warning"
|
||||
}
|
||||
|
||||
// Info will be used to notify users of any extra info (env variables, options)
|
||||
type Info struct {
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func (s *Info) Type() string {
|
||||
return "io.k8s.sigs.minikube.info"
|
||||
}
|
||||
|
||||
// NewInfo returns a new Info type
|
||||
func NewInfo(message string) *Info {
|
||||
return &Info{
|
||||
map[string]string{
|
||||
"message": message,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Error will be used to notify the user of errors
|
||||
type Error struct {
|
||||
}
|
||||
|
||||
func (s *Error) Type() string {
|
||||
return "io.k8s.sigs.minikube.error"
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
Copyright 2020 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 register contains all the logic to print out `minikube start` in JSON
|
||||
package register
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
InitialSetup RegStep = "Initial Minikube Setup"
|
||||
SelectingDriver RegStep = "Selecting Driver"
|
||||
DownloadingArtifacts RegStep = "Downloading Artifacts"
|
||||
StartingNode RegStep = "Starting Node"
|
||||
CreatingContainer RegStep = "Creating Container"
|
||||
CreatingVM RegStep = "Creating VM"
|
||||
PreparingKubernetes RegStep = "Preparing Kubernetes"
|
||||
VerifyingKubernetes RegStep = "Verifying Kubernetes"
|
||||
EnablingAddons RegStep = "Enabling Addons"
|
||||
Done RegStep = "Done"
|
||||
)
|
||||
|
||||
// RegStep is a type representing a distinct step of `minikube start`
|
||||
type RegStep string
|
||||
|
||||
// Register holds all of the steps we could see in `minikube start`
|
||||
// and keeps track of the current step
|
||||
type Register struct {
|
||||
steps []RegStep
|
||||
current RegStep
|
||||
}
|
||||
|
||||
// Reg keeps track of all possible steps and the current step we are on
|
||||
var Reg Register
|
||||
|
||||
func init() {
|
||||
Reg = Register{
|
||||
steps: []RegStep{
|
||||
InitialSetup,
|
||||
SelectingDriver,
|
||||
DownloadingArtifacts,
|
||||
StartingNode,
|
||||
CreatingContainer,
|
||||
CreatingVM,
|
||||
PreparingKubernetes,
|
||||
VerifyingKubernetes,
|
||||
EnablingAddons,
|
||||
Done,
|
||||
},
|
||||
current: InitialSetup,
|
||||
}
|
||||
}
|
||||
|
||||
// totalSteps returns the total number of steps in the register
|
||||
func (r *Register) totalSteps() string {
|
||||
return fmt.Sprintf("%d", len(r.steps)-1)
|
||||
}
|
||||
|
||||
// currentStep returns the current step we are on
|
||||
func (r *Register) currentStep() string {
|
||||
for i, s := range r.steps {
|
||||
if r.current == s {
|
||||
return fmt.Sprintf("%d", i)
|
||||
}
|
||||
}
|
||||
// all steps should be registered so this shouldn't happen
|
||||
// can't call exit.WithError as it creates an import dependency loop
|
||||
panic(fmt.Sprintf("%v is not a registered step", r.current))
|
||||
}
|
||||
|
||||
// SetStep sets the current step
|
||||
func (r *Register) SetStep(s RegStep) {
|
||||
r.current = s
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Copyright 2020 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 register
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetCurrentStep(t *testing.T) {
|
||||
secondStep := Reg.steps[1]
|
||||
Reg.SetStep(secondStep)
|
||||
|
||||
expected := `{"data":{"currentstep":"1","message":"message","name":"%s","totalsteps":"%v"},"datacontenttype":"application/json","id":"random-id","source":"https://minikube.sigs.k8s.io/","specversion":"1.0","type":"io.k8s.sigs.minikube.step"}`
|
||||
expected = fmt.Sprintf(expected, secondStep, Reg.totalSteps())
|
||||
expected += "\n"
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
outputFile = buf
|
||||
defer func() { outputFile = os.Stdout }()
|
||||
|
||||
getUUID = func() string {
|
||||
return "random-id"
|
||||
}
|
||||
|
||||
PrintStep("message")
|
||||
actual := buf.String()
|
||||
|
||||
if actual != expected {
|
||||
t.Fatalf("expected didn't match actual:\nExpected:\n%v\n\nActual:\n%v", expected, actual)
|
||||
}
|
||||
}
|
|
@ -155,7 +155,7 @@ func applyStyle(style StyleEnum, useColor bool, format string) string {
|
|||
}
|
||||
|
||||
// Similar to CSS styles, if no style matches, output an unformatted string.
|
||||
if !ok {
|
||||
if !ok || JSON {
|
||||
return format
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ minikube start [flags]
|
|||
--nfs-shares-root string Where to root the NFS Shares, defaults to /nfsshares (hyperkit driver only) (default "/nfsshares")
|
||||
--no-vtx-check Disable checking for the availability of hardware virtualization before the vm is started (virtualbox driver only)
|
||||
-n, --nodes int The number of nodes to spin up. Defaults to 1. (default 1)
|
||||
--output string Format to print stdout in. Options include: [text,json] (default "text")
|
||||
--preload If set, download tarball of preloaded images if available to improve start time. Defaults to true. (default true)
|
||||
--registry-mirror strings Registry mirrors to pass to the Docker daemon
|
||||
--service-cluster-ip-range string The CIDR to be used for service cluster IPs. (default "10.96.0.0/12")
|
||||
|
|
|
@ -49,7 +49,7 @@ multinode-demo-m02 Ready <none> 33s v1.18.2
|
|||
|
||||
- You can also check the status of your nodes:
|
||||
```
|
||||
$ minikube status
|
||||
$ minikube status -p multinode-demo
|
||||
multinode-demo
|
||||
type: Control Plane
|
||||
host: Running
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Copyright 2020 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 integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
func TestJSONOutput(t *testing.T) {
|
||||
if NoneDriver() || DockerDriver() {
|
||||
t.Skipf("skipping: test drivers once all JSON output is enabled")
|
||||
}
|
||||
profile := UniqueProfileName("json-output")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), Minutes(40))
|
||||
defer Cleanup(t, profile, cancel)
|
||||
|
||||
startArgs := []string{"start", "-p", profile, "--memory=2200", "--output=json", "--wait=true"}
|
||||
startArgs = append(startArgs, StartArgs()...)
|
||||
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), startArgs...))
|
||||
if err != nil {
|
||||
t.Errorf("failed to clean up: args %q: %v", rr.Command(), err)
|
||||
}
|
||||
|
||||
type validateJSONOutputFunc func(context.Context, *testing.T, *RunResult)
|
||||
t.Run("serial", func(t *testing.T) {
|
||||
serialTests := []struct {
|
||||
name string
|
||||
validator validateJSONOutputFunc
|
||||
}{
|
||||
{"CloudEvents", validateCloudEvents},
|
||||
}
|
||||
for _, stc := range serialTests {
|
||||
t.Run(stc.name, func(t *testing.T) {
|
||||
stc.validator(ctx, t, rr)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// make sure all output can be marshaled as a cloud event
|
||||
func validateCloudEvents(ctx context.Context, t *testing.T, rr *RunResult) {
|
||||
stdout := strings.Split(rr.Stdout.String(), "\n")
|
||||
for _, s := range stdout {
|
||||
if s == "" {
|
||||
continue
|
||||
}
|
||||
event := cloudevents.NewEvent()
|
||||
if err := json.Unmarshal([]byte(s), &event); err != nil {
|
||||
t.Fatalf("unable to unmarshal output: %v\n%s", err, s)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -90,7 +90,16 @@ func TestNetworkPlugins(t *testing.T) {
|
|||
}
|
||||
if !t.Failed() {
|
||||
t.Run("KubeletFlags", func(t *testing.T) {
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "pgrep -a kubelet"))
|
||||
var rr *RunResult
|
||||
var err error
|
||||
|
||||
// none does not support 'minikube ssh'
|
||||
if NoneDriver() {
|
||||
rr, err = Run(t, exec.CommandContext(ctx, "pgrep", "-a", "kubelet"))
|
||||
} else {
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "pgrep -a kubelet"))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ssh failed: %v", err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue