Skip to content

Commit ae7395e

Browse files
authored
Add minikube option to quickstart plugin (#44)
* adding minikube option to quickstart plugin * removing clutter, making version check < instead of == * cleanup * more cleanup * 3 CPUs for minikube * typo * timing install, finished message * password prompting on mac * adding message for setting minikube driver
1 parent f346b0c commit ae7395e

File tree

7 files changed

+270
-5
lines changed

7 files changed

+270
-5
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ After the plugin is installed, you can use `kn quickstart` to run its related su
2121
## Usage
2222

2323
```
24-
Get up and running with a local Knative environment running on KinD.
24+
Get up and running with a local Knative environment
2525
2626
Usage:
2727
kn-quickstart [command]
@@ -30,6 +30,7 @@ Available Commands:
3030
completion generate the autocompletion script for the specified shell
3131
help Help about any command
3232
kind Quickstart with Kind
33+
minikube Quickstart with Minikube
3334
version Prints the plugin version
3435
3536
Flags:
@@ -46,6 +47,14 @@ Set up a local Knative cluster using [KinD](https://kind.sigs.k8s.io/):
4647
kn quickstart kind
4748
```
4849

50+
### Quickstart with Minikube
51+
52+
Set up a local Knative cluster using [Minikube](https://minikube.sigs.k8s.io/):
53+
54+
```bash
55+
kn quickstart minikube
56+
```
57+
4958
## Building from Source
5059

5160
You must [set up your development environment](https://github.com/knative/client/blob/master/docs/DEVELOPMENT.md#prerequisites) before you build `kn-plugin-quickstart`.
@@ -57,3 +66,4 @@ git clone [email protected]:knative-sandbox/kn-plugin-quickstart.git
5766
cd kn-plugin-quickstart
5867
./hack/build.sh
5968
```
69+

internal/command/kind.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"knative.dev/kn-plugin-quickstart/pkg/kind"
2222
)
2323

24-
// NewKindCommand implements 'kn kind' command
24+
// NewKindCommand implements 'kn quickstart kind' command
2525
func NewKindCommand() *cobra.Command {
2626
return &cobra.Command{
2727
Use: "kind",

internal/command/minikube.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright © 2021 The Knative Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package command
16+
17+
import (
18+
"fmt"
19+
20+
"knative.dev/kn-plugin-quickstart/pkg/minikube"
21+
22+
"github.com/spf13/cobra"
23+
)
24+
25+
// NewMinikubeCommand implements 'kn quickstart minikube' command
26+
func NewMinikubeCommand() *cobra.Command {
27+
return &cobra.Command{
28+
Use: "minikube",
29+
Short: "Quickstart with Minikube",
30+
RunE: func(cmd *cobra.Command, args []string) error {
31+
fmt.Println("Running Knative Quickstart using Minikube")
32+
return minikube.SetUp()
33+
},
34+
}
35+
}

internal/root/root.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@ import (
1919
"knative.dev/kn-plugin-quickstart/internal/command"
2020
)
2121

22-
// NewSourceKafkaCommand represents the plugin's entrypoint
22+
// NewRootCommand represents the plugin's entrypoint
2323
func NewRootCommand() *cobra.Command {
2424

2525
var rootCmd = &cobra.Command{
2626
Use: "kn-quickstart",
2727
Short: "Get started quickly with Knative",
28-
Long: `Get up and running with a local Knative environment running on KinD.`,
28+
Long: `Get up and running with a local Knative environment`,
2929
}
3030

3131
rootCmd.AddCommand(command.NewKindCommand())
32+
rootCmd.AddCommand(command.NewMinikubeCommand())
3233
rootCmd.AddCommand(command.NewVersionCommand())
3334

3435
return rootCmd

pkg/install/install.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ func Kourier() error {
4646
}
4747
fmt.Println(" Ingress patched...")
4848

49+
fmt.Println(" Finished installing Kourier Networking layer")
50+
51+
return nil
52+
}
53+
54+
// KourierKind runs the kind-specific setup for Kourier
55+
func KourierKind() error {
56+
fmt.Println("🕸 Configuring Kourier for Kind...")
57+
4958
config := `apiVersion: v1
5059
kind: Service
5160
metadata:
@@ -76,9 +85,30 @@ spec:
7685
return fmt.Errorf("domain dns: %w", err)
7786
}
7887
fmt.Println(" Domain DNS set up...")
88+
fmt.Println(" Finished configuring Kourier")
7989

80-
fmt.Println(" Finished installing Kourier Networking layer")
90+
return nil
91+
}
8192

93+
// KourierMinikube runs the minikube-specific setup for Kourier
94+
func KourierMinikube() error {
95+
fmt.Println("🕸 Configuring Kourier for Minikube...")
96+
97+
if err := retryingApply("https://github.com/knative/serving/releases/download/v" + servingVersion + "/serving-default-domain.yaml"); err != nil {
98+
return fmt.Errorf("default domain: %w", err)
99+
}
100+
if err := waitForPodsReady("knative-serving"); err != nil {
101+
return fmt.Errorf("core: %w", err)
102+
}
103+
104+
fmt.Println(" Domain DNS set up...")
105+
106+
tunnel := exec.Command("minikube", "tunnel", "--profile", "minikube-knative")
107+
if err := tunnel.Start(); err != nil {
108+
return fmt.Errorf("tunnel: %w", err)
109+
}
110+
fmt.Println(" Minikube tunnel...")
111+
fmt.Println(" Finished configuring Kourier")
82112
return nil
83113
}
84114

pkg/kind/kind.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ func SetUp() error {
4141
if err := install.Kourier(); err != nil {
4242
return fmt.Errorf("install kourier: %w", err)
4343
}
44+
if err := install.KourierKind(); err != nil {
45+
return fmt.Errorf("configure kourier: %w", err)
46+
}
4447
if err := install.Eventing(); err != nil {
4548
return fmt.Errorf("install eventing: %w", err)
4649
}

pkg/minikube/minikube.go

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// Copyright © 2021 The Knative Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package minikube
16+
17+
import (
18+
"fmt"
19+
"os"
20+
"os/exec"
21+
"regexp"
22+
"runtime"
23+
"strconv"
24+
"strings"
25+
"time"
26+
27+
"knative.dev/kn-plugin-quickstart/pkg/install"
28+
)
29+
30+
var clusterName = "minikube-knative"
31+
var minikubeVersion = 1.23
32+
33+
// SetUp creates a local Minikube cluster and installs all the relevant Knative components
34+
func SetUp() error {
35+
start := time.Now()
36+
37+
if runtime.GOOS == "darwin" {
38+
fmt.Println("NOTE: Using Minikube on Mac may require entering your password to enable networking.")
39+
}
40+
41+
if err := createMinikubeCluster(); err != nil {
42+
return fmt.Errorf("creating cluster: %w", err)
43+
}
44+
if err := install.Serving(); err != nil {
45+
return fmt.Errorf("install serving: %w", err)
46+
}
47+
if err := install.Kourier(); err != nil {
48+
return fmt.Errorf("install kourier: %w", err)
49+
}
50+
if err := install.KourierMinikube(); err != nil {
51+
return fmt.Errorf("configure kourier: %w", err)
52+
}
53+
if err := install.Eventing(); err != nil {
54+
return fmt.Errorf("install eventing: %w", err)
55+
}
56+
finish := time.Since(start).Round(time.Second)
57+
fmt.Printf("🚀 Knative install took: %s \n", finish)
58+
fmt.Println("🎉 Now have some fun with Serverless and Event Driven Apps!")
59+
return nil
60+
}
61+
62+
func createMinikubeCluster() error {
63+
if err := checkMinikubeVersion(); err != nil {
64+
return fmt.Errorf("minikube version: %w", err)
65+
}
66+
if err := checkForExistingCluster(); err != nil {
67+
return fmt.Errorf("existing cluster: %w", err)
68+
}
69+
return nil
70+
}
71+
72+
// checkMinikubeVersion validates that the user has the correct version of Minikube installed.
73+
// If not, it prompts the user to download a newer version before continuing.
74+
func checkMinikubeVersion() error {
75+
versionCheck := exec.Command("minikube", "version", "--short")
76+
out, err := versionCheck.CombinedOutput()
77+
if err != nil {
78+
return fmt.Errorf("minikube version: %w", err)
79+
}
80+
fmt.Printf("Minikube version is: %s\n", string(out))
81+
82+
userMinikubeVersion, err := parseMinikubeVersion(string(out))
83+
if err != nil {
84+
return fmt.Errorf("parsing minikube version: %w", err)
85+
}
86+
if userMinikubeVersion < minikubeVersion {
87+
var resp string
88+
fmt.Printf("WARNING: We require at least Minikube v%.2f, while you are using v%.2f\n", minikubeVersion, userMinikubeVersion)
89+
fmt.Println("You can download a newer version from https://github.com/kubernetes/minikube/releases/")
90+
fmt.Print("Continue anyway? (not recommended) [y/N]: ")
91+
fmt.Scanf("%s", &resp)
92+
if strings.ToLower(resp) != "y" {
93+
fmt.Println("Installation stopped. Please upgrade minikube and run again")
94+
os.Exit(0)
95+
}
96+
}
97+
98+
return nil
99+
}
100+
101+
// checkForExistingCluster checks if the user already has a Minikube cluster. If so, it provides
102+
// the option of deleting the existing cluster and recreating it. If not, it proceeds to
103+
// creating a new cluster
104+
func checkForExistingCluster() error {
105+
106+
getClusters := exec.Command("minikube", "profile", "list")
107+
out, err := getClusters.CombinedOutput()
108+
if err != nil {
109+
// there are no existing minikube profiles, the listing profiles command will error
110+
// if there were no profiles, we simply want to create a new one and not stop the install
111+
// so if the error is the "MK_USAGE_NO_PROFILE" error, we ignore it and continue onwards
112+
if !strings.Contains(string(out), "MK_USAGE_NO_PROFILE") {
113+
return fmt.Errorf("check cluster: %w", err)
114+
}
115+
}
116+
// TODO Add tests for regex
117+
r := regexp.MustCompile(clusterName)
118+
matches := r.Match(out)
119+
if matches {
120+
var resp string
121+
fmt.Print("Knative Cluster " + clusterName + " already installed.\nDelete and recreate [y/N]: ")
122+
fmt.Scanf("%s", &resp)
123+
if strings.ToLower(resp) != "y" {
124+
fmt.Println("Installation skipped")
125+
return nil
126+
}
127+
fmt.Println("deleting cluster...")
128+
deleteCluster := exec.Command("minikube", "delete", "--profile", clusterName)
129+
if err := deleteCluster.Run(); err != nil {
130+
return fmt.Errorf("delete cluster: %w", err)
131+
}
132+
if err := createNewCluster(); err != nil {
133+
return fmt.Errorf("new cluster: %w", err)
134+
}
135+
}
136+
137+
if err := createNewCluster(); err != nil {
138+
return fmt.Errorf("new cluster: %w", err)
139+
}
140+
141+
return nil
142+
}
143+
144+
// createNewCluster creates a new Minikube cluster
145+
func createNewCluster() error {
146+
147+
fmt.Println("☸ Creating Minikube cluster...")
148+
fmt.Println("\n By default, using the standard minikube driver for your system")
149+
fmt.Println("If you wish to use a different driver, please configure minikube using")
150+
fmt.Println(" minikube config set --driver <your-driver>")
151+
152+
// create cluster and wait until ready
153+
createCluster := exec.Command("minikube", "start", "--cpus", "3", "--profile", clusterName, "--wait", "all")
154+
if err := runCommand(createCluster); err != nil {
155+
return fmt.Errorf("minikube create: %w", err)
156+
}
157+
158+
// minikube tunnel
159+
tunnel := exec.Command("minikube", "tunnel", "--profile", "minikube-knative")
160+
if err := tunnel.Start(); err != nil {
161+
return fmt.Errorf("tunnel: %w", err)
162+
}
163+
fmt.Println(" Minikube tunnel...")
164+
165+
fmt.Println(" Cluster ready")
166+
return nil
167+
}
168+
169+
func runCommand(c *exec.Cmd) error {
170+
if out, err := c.CombinedOutput(); err != nil {
171+
fmt.Println(string(out))
172+
return err
173+
}
174+
return nil
175+
}
176+
177+
func parseMinikubeVersion(v string) (float64, error) {
178+
strippedVersion := strings.TrimLeft(strings.TrimRight(v, "\n"), "v")
179+
dotVersion := strings.Split(strippedVersion, ".")
180+
floatVersion, err := strconv.ParseFloat(dotVersion[0]+"."+dotVersion[1], 64)
181+
if err != nil {
182+
return 0, err
183+
}
184+
185+
return floatVersion, nil
186+
}

0 commit comments

Comments
 (0)