diff --git a/DRIVERS.md b/DRIVERS.md index 170031d2580c..a6404c244ced 100644 --- a/DRIVERS.md +++ b/DRIVERS.md @@ -14,9 +14,23 @@ the host PATH: #### KVM driver -Download the `docker-machine-driver-kvm` binary from -https://github.com/dhiltgen/docker-machine-kvm/releases and put it somewhere in -your PATH. Minikube is currently tested against `docker-machine-driver-kvm` 0.7.0. +Minikube is currently tested against `docker-machine-driver-kvm` 0.7.0. + +From https://github.com/dhiltgen/docker-machine-kvm#quick-start-instructions: + +``` +$ sudo curl -L https://github.com/dhiltgen/docker-machine-kvm/releases/download/v0.7.0/docker-machine-driver-kvm -o /usr/local/bin/docker-machine-driver-kvm +$ sudo chmod +x /usr/local/bin/docker-machine-driver-kvm + +# Install libvirt and qemu-kvm on your system, e.g. +$ sudo apt install libvirt-bin qemu-kvm + +# Add yourself to the libvirtd group (may vary by linux distro) so you don't need to sudo +$ sudo usermod -a -G libvirtd $(whoami) + +# Update your current session for the group change to take effect +$ newgrp libvirtd +``` #### xhyve driver diff --git a/Makefile b/Makefile index 6f3288f9271b..9a982856a51c 100644 --- a/Makefile +++ b/Makefile @@ -77,20 +77,25 @@ $(GOPATH)/bin/gh-release: go get github.com/progrium/gh-release .PHONY: gendocs -gendocs: $(shell find cmd) out/openshift +gendocs: $(shell find cmd) pkg/minikube/cluster/assets.go $(MKGOPATH) cd $(GOPATH)/src/$(REPOPATH) && go run -ldflags="-X github.com/jimmidyson/minishift/pkg/version.version=$(shell cat VERSION)" gen_help_text.go .PHONY: release -release: clean deploy/iso/minishift.iso test $(GOPATH)/bin/gh-release - GOOS=linux GOARCH=amd64 make out/minishift-linux-amd64 - GOOS=darwin GOARCH=amd64 make out/minishift-darwin-amd64 +release: clean deploy/iso/minishift.iso test $(GOPATH)/bin/gh-release cross mkdir -p release - cp out/minishift-linux-amd64 out/minishift-darwin-amd64 release + cp out/minishift-*-amd64* release cp deploy/iso/minishift.iso release/boot2docker.iso gh-release checksums sha1 gh-release create jimmidyson/minishift $(VERSION) +.PHONY: cross +cross: out/openshift + GOOS=linux GOARCH=amd64 make out/minishift-linux-amd64 + GOOS=darwin GOARCH=amd64 make out/minishift-darwin-amd64 + GOOS=windows GOARCH=amd64 make out/minishift-windows-amd64 + mv out/minishift-windows-amd64 out/minishift-windows-amd64.exe + .PHONY: clean clean: rm -rf $(GOPATH) diff --git a/README.md b/README.md index 8342dfe54473..9b83a8929b21 100644 --- a/README.md +++ b/README.md @@ -48,26 +48,32 @@ Starting local OpenShift cluster... Running pre-create checks... Creating machine... Starting local OpenShift cluster... -OpenShift is available at https://192.168.99.100:443. +OpenShift is available at https://192.168.99.100:8443. + +$ oc run hello-minishift --image=gcr.io/google_containers/echoserver:1.4 --port=8080 --expose --service-overrides='{"apiVersion": "v1", "spec": {"type": "NodePort"}}' +service "hello-minishift" created +deploymentconfig "hello-minishift" created -$ oc run hello-minishift --image=gcr.io/google_containers/echoserver:1.4 --hostport=8000 --port=8080 -deployment "hello-minishift" created # We have now launched an echoserver pod but we have to wait until the pod is up before curling/accessing it +# via the exposed service. # To check whether the pod is up and running we can use the following: $ oc get pod NAME READY STATUS RESTARTS AGE hello-minishift-3383150820-vctvh 1/1 ContainerCreating 0 3s + # We can see that the pod is still being created from the ContainerCreating status $ oc get pod NAME READY STATUS RESTARTS AGE hello-minishift-3383150820-vctvh 1/1 Running 0 13s + # We can see that the pod is now Running and we will now be able to curl it: -$ curl http://$(minishift ip):8000 +$ curl $(minishift service hello-minikube --url) CLIENT VALUES: client_address=192.168.99.1 command=GET real path=/ ... + $ minishift stop Stopping local OpenShift cluster... Stopping "minishiftVM"... diff --git a/cmd/minikube/cmd/flags.go b/cmd/minikube/cmd/flags.go new file mode 100644 index 000000000000..aea86d5e3e40 --- /dev/null +++ b/cmd/minikube/cmd/flags.go @@ -0,0 +1,40 @@ +/* +Copyright (C) 2016 Red Hat, Inc. + +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 "github.com/docker/go-units" + +// unitValue represents an int64 flag specified with units as a string. +type unitValue int64 + +func newUnitValue(v int64) *unitValue { + return (*unitValue)(&v) +} + +func (u *unitValue) Set(s string) error { + v, err := units.FromHumanSize(s) + *u = unitValue(v) + return err +} + +func (u *unitValue) Type() string { + return "unit" +} + +func (u *unitValue) String() string { + return units.HumanSize(float64(*u)) +} diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index bc8e30e72bf8..f0cc110be18d 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -19,8 +19,10 @@ package cmd import ( "fmt" "os" + "strconv" "strings" + "github.com/docker/go-units" "github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine/host" "github.com/golang/glog" @@ -36,6 +38,7 @@ var ( minikubeISO string memory int cpus int + disk = newUnitValue(20 * units.GB) vmDriver string ) @@ -57,9 +60,12 @@ func runStart(cmd *cobra.Command, args []string) { MinikubeISO: minikubeISO, Memory: memory, CPUs: cpus, + DiskSize: int(*disk / units.MB), VMDriver: vmDriver, } + fmt.Println(config.DiskSize) + var host *host.Host start := func() (err error) { host, err = cluster.StartHost(api, config) @@ -91,7 +97,7 @@ func runStart(cmd *cobra.Command, args []string) { glog.Errorln("Error connecting to cluster: ", err) } kubeHost = strings.Replace(kubeHost, "tcp://", "https://", -1) - kubeHost = strings.Replace(kubeHost, ":2376", ":443", -1) + kubeHost = strings.Replace(kubeHost, ":2376", ":"+strconv.Itoa(constants.APIServerPort), -1) fmt.Printf("OpenShift is available at %s.\n", kubeHost) // setup kubeconfig @@ -99,30 +105,25 @@ func runStart(cmd *cobra.Command, args []string) { certAuth := constants.MakeMiniPath("apiserver.crt") clientCert := constants.MakeMiniPath("apiserver.crt") clientKey := constants.MakeMiniPath("apiserver.key") - if active, err := setupKubeconfig(name, kubeHost, certAuth, clientCert, clientKey); err != nil { + if err := setupKubeconfig(name, kubeHost, certAuth, clientCert, clientKey); err != nil { glog.Errorln("Error setting up kubeconfig: ", err) os.Exit(1) - } else if !active { - fmt.Println("Run these commands to use the cluster: ") - fmt.Printf("oc config use-context %s\n", name) - fmt.Println("oc login --username=admin --password=admin --insecure-skip-tls-verify") - } else { - fmt.Println("oc is now configured to use the cluster.") - fmt.Println("Run this command to login: ") - fmt.Println("oc login --username=admin --password=admin --insecure-skip-tls-verify") } + fmt.Println("oc is now configured to use the cluster.") + fmt.Println("Run this command to use the cluster: ") + fmt.Println("oc login --username=admin --password=admin --insecure-skip-tls-verify") } // setupKubeconfig reads config from disk, adds the minikube settings, and writes it back. // activeContext is true when minikube is the CurrentContext // If no CurrentContext is set, the given name will be used. -func setupKubeconfig(name, server, certAuth, cliCert, cliKey string) (activeContext bool, err error) { +func setupKubeconfig(name, server, certAuth, cliCert, cliKey string) error { configFile := constants.KubeconfigPath // read existing config or create new if does not exist config, err := kubeconfig.ReadConfigOrNew(configFile) if err != nil { - return false, err + return err } clusterName := name @@ -145,18 +146,14 @@ func setupKubeconfig(name, server, certAuth, cliCert, cliKey string) (activeCont context.AuthInfo = userName config.Contexts[contextName] = context - // set current context to minikube if unset - if len(config.CurrentContext) == 0 { - config.CurrentContext = contextName - } + // Always set current context to minikube. + config.CurrentContext = contextName // write back to disk if err := kubeconfig.WriteConfig(config, configFile); err != nil { - return false, err + return err } - - // activeContext if current matches name - return name == config.CurrentContext, nil + return nil } func init() { @@ -164,5 +161,7 @@ func init() { startCmd.Flags().StringVarP(&vmDriver, "vm-driver", "", constants.DefaultVMDriver, fmt.Sprintf("VM driver is one of: %v", constants.SupportedVMDrivers)) startCmd.Flags().IntVarP(&memory, "memory", "", constants.DefaultMemory, "Amount of RAM allocated to the minishift VM") startCmd.Flags().IntVarP(&cpus, "cpus", "", constants.DefaultCPUS, "Number of CPUs allocated to the minishift VM") + diskFlag := startCmd.Flags().VarPF(disk, "disk-size", "", "Disk size allocated to the minishift VM (format: [], where unit = b, k, m or g)") + diskFlag.DefValue = constants.DefaultDiskSize RootCmd.AddCommand(startCmd) } diff --git a/docs/minishift_start.md b/docs/minishift_start.md index 131fa97aad40..cd6eeff8f5bc 100644 --- a/docs/minishift_start.md +++ b/docs/minishift_start.md @@ -16,6 +16,7 @@ minishift start ``` --cpus=1: Number of CPUs allocated to the minishift VM + --disk-size=20g: Disk size allocated to the minishift VM (format: [], where unit = b, k, m or g) --iso-url="https://github.com/jimmidyson/minishift/releases/download/v0.1.1/boot2docker.iso": Location of the minishift iso --memory=1024: Amount of RAM allocated to the minishift VM --vm-driver="kvm": VM driver is one of: [virtualbox kvm] diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 1b6e95dd97fe..1d94a3adf747 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -161,6 +161,7 @@ type MachineConfig struct { MinikubeISO string Memory int CPUs int + DiskSize int VMDriver string } @@ -259,6 +260,7 @@ func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) { d.Boot2DockerURL = config.MinikubeISO d.Memory = config.Memory d.CPU = config.CPUs + d.DiskSize = int(config.DiskSize) driver = d case "vmwarefusion": driver = createVMwareFusionHost(config) @@ -420,7 +422,14 @@ func getServicePortFromServiceGetter(services serviceGetter, service string) (in if err != nil { return 0, fmt.Errorf("Error getting %s service: %s", service, err) } - return int(svc.Spec.Ports[0].NodePort), nil + nodePort := 0 + if len(svc.Spec.Ports) > 0 { + nodePort = int(svc.Spec.Ports[0].NodePort) + } + if nodePort == 0 { + return 0, fmt.Errorf("Service %s does not have a node port. To have one assigned automatically, the service type must be NodePort or LoadBalancer, but this service is of type %s.", service, svc.Spec.Type) + } + return nodePort, nil } func getKubernetesServicesWithNamespace(namespace string) (serviceGetter, error) { diff --git a/pkg/minikube/cluster/cluster_darwin.go b/pkg/minikube/cluster/cluster_darwin.go index d7565923de62..c98e2245ad13 100644 --- a/pkg/minikube/cluster/cluster_darwin.go +++ b/pkg/minikube/cluster/cluster_darwin.go @@ -61,6 +61,6 @@ func createXhyveHost(config MachineConfig) *xhyveDriver { CPU: config.CPUs, Boot2DockerURL: config.MinikubeISO, BootCmd: "loglevel=3 user=docker console=ttyS0 console=tty0 noembed nomodeset norestore waitusb=10 base host=boot2docker", - DiskSize: 20000, + DiskSize: int64(config.DiskSize), } } diff --git a/pkg/minikube/cluster/cluster_linux.go b/pkg/minikube/cluster/cluster_linux.go index 3c6e9f45b7f6..2055a53bd7ee 100644 --- a/pkg/minikube/cluster/cluster_linux.go +++ b/pkg/minikube/cluster/cluster_linux.go @@ -50,7 +50,7 @@ func createKVMHost(config MachineConfig) *kvmDriver { Network: "default", PrivateNetwork: "docker-machines", Boot2DockerURL: config.MinikubeISO, - DiskSize: 20000, + DiskSize: config.DiskSize, DiskPath: filepath.Join(constants.Minipath, "machines", constants.MachineName, fmt.Sprintf("%s.img", constants.MachineName)), ISO: filepath.Join(constants.Minipath, "machines", constants.MachineName, "boot2docker.iso"), CacheMode: "default", diff --git a/pkg/minikube/cluster/cluster_test.go b/pkg/minikube/cluster/cluster_test.go index 0b0405f15cd6..d1b551767f48 100644 --- a/pkg/minikube/cluster/cluster_test.go +++ b/pkg/minikube/cluster/cluster_test.go @@ -464,6 +464,17 @@ func TestGetDashboardURL(t *testing.T) { } +func TestGetServiceURLWithoutNodePort(t *testing.T) { + mockServiceGetter := NewMockServiceGetter() + mockDashboardService := api.Service{} + mockServiceGetter.services["mock-service"] = mockDashboardService + + _, err := getServicePortFromServiceGetter(mockServiceGetter, "mock-service") + if err == nil { + t.Fatalf("Expected error getting service with no node port") + } +} + func TestUpdate(t *testing.T) { s, _ := tests.NewSSHServer() port, err := s.Start() diff --git a/pkg/minikube/cluster/commands.go b/pkg/minikube/cluster/commands.go index 296abb91f265..b069ee2fa89e 100644 --- a/pkg/minikube/cluster/commands.go +++ b/pkg/minikube/cluster/commands.go @@ -28,8 +28,8 @@ var stopCommand = "sudo killall openshift | true" var startCommandFmtStr = ` # Run with nohup so it stays up. Redirect logs to useful places. cd /var/lib/minishift; -PATH=/usr/local/sbin:$PATH nohup sudo /usr/local/bin/openshift start --listen=https://0.0.0.0:443 > %s 2> %s < /dev/null & -until $(curl --output /dev/null --silent --fail -k https://localhost/healthz/ready); do +sudo sh -c 'PATH=/usr/local/sbin:$PATH nohup sudo /usr/local/bin/openshift start --listen=https://0.0.0.0:%d> %s 2> %s < /dev/null &' +until $(curl --output /dev/null --silent --fail -k https://localhost:%d/healthz/ready); do printf '.' sleep 1 done; @@ -39,5 +39,5 @@ sudo /usr/local/bin/openshift admin policy add-cluster-role-to-user cluster-admi var logsCommand = fmt.Sprintf("tail -n +1 %s %s", constants.RemoteOpenShiftErrPath, constants.RemoteOpenShiftOutPath) func GetStartCommand() string { - return fmt.Sprintf(startCommandFmtStr, constants.RemoteOpenShiftErrPath, constants.RemoteOpenShiftOutPath) + return fmt.Sprintf(startCommandFmtStr, constants.APIServerPort, constants.RemoteOpenShiftErrPath, constants.RemoteOpenShiftOutPath, constants.APIServerPort) } diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index d6fc1b5b319a..c6a56b7e9dbf 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -27,6 +27,9 @@ import ( // MachineName is the name to use for the VM. const MachineName = "minishiftVM" +// APIServerPort is the port that the API server should listen on. +const APIServerPort = 8443 + // Fix for windows var Minipath = filepath.Join(homedir.HomeDir(), ".minishift") @@ -49,15 +52,16 @@ var LogFlags = [...]string{ } const ( - DefaultMemory = 1024 - DefaultCPUS = 1 + DefaultMemory = 1024 + DefaultCPUS = 1 + DefaultDiskSize = "20g" ) var DefaultIsoUrl = "https://github.com/jimmidyson/minishift/releases/download/v" + version.GetVersion() + "/boot2docker.iso" const ( - RemoteOpenShiftErrPath = "/var/log/openshift.err" - RemoteOpenShiftOutPath = "/var/log/openshift.out" + RemoteOpenShiftErrPath = "/var/lib/minishift/openshift.err" + RemoteOpenShiftOutPath = "/var/lib/minishift/openshift.out" ) var ConfigFilePath = MakeMiniPath("config") diff --git a/pkg/minikube/kubeconfig/config_test.go b/pkg/minikube/kubeconfig/config_test.go index efdc9ced7937..7570292e2224 100644 --- a/pkg/minikube/kubeconfig/config_test.go +++ b/pkg/minikube/kubeconfig/config_test.go @@ -20,8 +20,10 @@ import ( "io/ioutil" "os" "path/filepath" + "strconv" "testing" + "github.com/jimmidyson/minishift/pkg/minikube/constants" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" ) @@ -101,7 +103,7 @@ func minikubeConfig(config *api.Config) { // cluster clusterName := "minikube" cluster := api.NewCluster() - cluster.Server = "https://192.168.99.100:443" + cluster.Server = "https://192.168.99.100:" + strconv.Itoa(constants.APIServerPort) cluster.CertificateAuthority = "/home/tux/.minikube/apiserver.crt" config.Clusters[clusterName] = cluster diff --git a/pkg/minikube/notify/notify.go b/pkg/minikube/notify/notify.go index d0a99c8f138a..fd9cd4c1e073 100644 --- a/pkg/minikube/notify/notify.go +++ b/pkg/minikube/notify/notify.go @@ -111,7 +111,7 @@ func getLatestVersionFromGitHub(githubOwner, githubRepo string) (semver.Version, return semver.Version{}, err } defer resp.Body.Close() - latestVersionString := release.Name + latestVersionString := release.TagName if latestVersionString != nil { return semver.Make(strings.TrimPrefix(*latestVersionString, "v")) diff --git a/pkg/minikube/notify/notify_test.go b/pkg/minikube/notify/notify_test.go index 07c934ad0d80..6e6530bf197d 100644 --- a/pkg/minikube/notify/notify_test.go +++ b/pkg/minikube/notify/notify_test.go @@ -69,12 +69,8 @@ func TestShouldCheckURL(t *testing.T) { } -type release struct { - Name string `json:name` -} - type URLHandlerCorrect struct { - release release + release github.RepositoryRelease } func (h *URLHandlerCorrect) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -90,8 +86,9 @@ func (h *URLHandlerCorrect) ServeHTTP(w http.ResponseWriter, r *http.Request) { func TestGetLatestVersionFromURLCorrect(t *testing.T) { // test that the version is correctly parsed if returned if valid JSON is returned the url endpoint latestVersionFromURL := "0.0.0-dev" + v := version.VersionPrefix + latestVersionFromURL handler := &URLHandlerCorrect{ - release: release{Name: version.VersionPrefix + latestVersionFromURL}, + release: github.RepositoryRelease{TagName: &v}, } server := httptest.NewServer(handler) @@ -166,8 +163,9 @@ func TestMaybePrintUpdateText(t *testing.T) { // test that no update text is printed if the latest version is lower/equal to the current version latestVersionFromURL := "0.0.0-dev" + v := version.VersionPrefix + latestVersionFromURL handler := &URLHandlerCorrect{ - release: release{Name: version.VersionPrefix + latestVersionFromURL}, + release: github.RepositoryRelease{TagName: &v}, } server := httptest.NewServer(handler) @@ -184,8 +182,9 @@ func TestMaybePrintUpdateText(t *testing.T) { // test that update text is printed if the latest version is greater than the current version latestVersionFromURL = "100.0.0-dev" + v = version.VersionPrefix + latestVersionFromURL handler = &URLHandlerCorrect{ - release: release{Name: version.VersionPrefix + latestVersionFromURL}, + release: github.RepositoryRelease{TagName: &v}, } server = httptest.NewServer(handler) diff --git a/test/integration/addons_test.go b/test/integration/addons_test.go index 007a853aa089..805e501a6151 100644 --- a/test/integration/addons_test.go +++ b/test/integration/addons_test.go @@ -20,6 +20,7 @@ package integration import ( "fmt" + "strings" "testing" "time" @@ -30,7 +31,7 @@ import ( ) var ( - addonManagerCmd = []string{"get", "pod", "kube-addon-manager-minikubevm", "--namespace=kube-system"} + addonManagerCmd = []string{"get", "pods", "--namespace=kube-system"} dashboardRcCmd = []string{"get", "rc", "kubernetes-dashboard", "--namespace=kube-system"} dashboardSvcCmd = []string{"get", "svc", "kubernetes-dashboard", "--namespace=kube-system"} ) @@ -45,15 +46,22 @@ func TestAddons(t *testing.T) { kubectlRunner := util.NewKubectlRunner(t) checkAddon := func() error { - p := api.Pod{} - if err := kubectlRunner.RunCommandParseOutput(addonManagerCmd, &p); err != nil { + pods := api.PodList{} + if err := kubectlRunner.RunCommandParseOutput(addonManagerCmd, &pods); err != nil { return err } - if p.Status.Phase != "Running" { - return fmt.Errorf("Pod is not Running. Status: %s", p.Status.Phase) + for _, p := range pods.Items { + if strings.HasPrefix(p.ObjectMeta.Name, "kube-addon-manager-") { + if p.Status.Phase == "Running" { + return nil + } else { + return fmt.Errorf("Pod is not Running. Status: %s", p.Status.Phase) + } + } } - return nil + + return fmt.Errorf("Addon manager not found. Found pods: %s", pods) } if err := commonutil.RetryAfter(20, checkAddon, 5*time.Second); err != nil { diff --git a/test/integration/testdata/busybox.yaml b/test/integration/testdata/busybox.yaml index e98561fee9be..6f5029924577 100644 --- a/test/integration/testdata/busybox.yaml +++ b/test/integration/testdata/busybox.yaml @@ -4,7 +4,7 @@ metadata: name: busybox spec: containers: - - image: busybox + - image: gcr.io/google-containers/busybox command: - sleep - "3600"