From 216077d8b8200658bb369266e0da8ec3e271c4bc Mon Sep 17 00:00:00 2001 From: aprindle Date: Wed, 6 Jul 2016 10:33:52 -0700 Subject: [PATCH 1/2] Added get-k8s-versions command and tests. --- cmd/minikube/cmd/get_kubernetes_versions.go | 38 ++++++ .../kubernetes_versions.go | 72 +++++++++++ .../kubernetes_versions_test.go | 121 ++++++++++++++++++ pkg/minikube/notify/notify_test.go | 10 +- 4 files changed, 236 insertions(+), 5 deletions(-) create mode 100644 cmd/minikube/cmd/get_kubernetes_versions.go create mode 100644 pkg/minikube/kubernetes_versions/kubernetes_versions.go create mode 100644 pkg/minikube/kubernetes_versions/kubernetes_versions_test.go diff --git a/cmd/minikube/cmd/get_kubernetes_versions.go b/cmd/minikube/cmd/get_kubernetes_versions.go new file mode 100644 index 0000000000..48c3cb84ef --- /dev/null +++ b/cmd/minikube/cmd/get_kubernetes_versions.go @@ -0,0 +1,38 @@ +/* +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 ( + "os" + + "github.com/spf13/cobra" + "k8s.io/minikube/pkg/minikube/kubernetes_versions" +) + +// getK8sVersionsCmd represents the ip command +var getK8sVersionsCmd = &cobra.Command{ + Use: "get-k8s-versions", + Short: "Gets the list of available kubernetes versions available for minikube.", + Long: `Gets the list of available kubernetes versions available for minikube.`, + Run: func(cmd *cobra.Command, args []string) { + kubernetes_versions.PrintKubernetesVersionsFromGCS(os.Stdout) + }, +} + +func init() { + RootCmd.AddCommand(getK8sVersionsCmd) +} diff --git a/pkg/minikube/kubernetes_versions/kubernetes_versions.go b/pkg/minikube/kubernetes_versions/kubernetes_versions.go new file mode 100644 index 0000000000..c8b2a30f67 --- /dev/null +++ b/pkg/minikube/kubernetes_versions/kubernetes_versions.go @@ -0,0 +1,72 @@ +/* +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 kubernetes_versions + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/golang/glog" +) + +const kubernetesVersionGCSURL = "https://storage.googleapis.com/minikube/k8s_releases.json" + +func PrintKubernetesVersionsFromGCS(output io.Writer) { + PrintKubernetesVersions(output, kubernetesVersionGCSURL) +} + +func PrintKubernetesVersions(output io.Writer, url string) { + k8sVersions, err := getK8sVersionsFromURL(url) + if err != nil { + glog.Errorln(err) + return + } + fmt.Fprint(output, "The following Kubernetes versions are available: \n") + + for _, k8sVersion := range k8sVersions { + fmt.Fprintf(output, "\t- %s\n", k8sVersion.Version) + } +} + +type k8sRelease struct { + Version string +} + +type k8sReleases []k8sRelease + +func getJson(url string, target *k8sReleases) error { + r, err := http.Get(url) + if err != nil { + return err + } + defer r.Body.Close() + + return json.NewDecoder(r.Body).Decode(target) +} + +func getK8sVersionsFromURL(url string) (k8sReleases, error) { + var k8sVersions k8sReleases + if err := getJson(url, &k8sVersions); err != nil { + return k8sReleases{}, err + } + if len(k8sVersions) == 0 { + return k8sReleases{}, fmt.Errorf("There were no json k8s Releases at the url specified: %s", url) + } + return k8sVersions, nil +} diff --git a/pkg/minikube/kubernetes_versions/kubernetes_versions_test.go b/pkg/minikube/kubernetes_versions/kubernetes_versions_test.go new file mode 100644 index 0000000000..8eb82c652e --- /dev/null +++ b/pkg/minikube/kubernetes_versions/kubernetes_versions_test.go @@ -0,0 +1,121 @@ +/* +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 kubernetes_versions + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "testing" +) + +type URLHandlerCorrect struct { + K8sReleases k8sReleases +} + +func (h *URLHandlerCorrect) ServeHTTP(w http.ResponseWriter, r *http.Request) { + b, err := json.Marshal(h.K8sReleases) + if err != nil { + fmt.Println(err) + return + } + w.Header().Set("Content-Type", "application/javascript") + fmt.Fprintf(w, string(b)) +} + +func TestGetK8sVersionsFromURLCorrect(t *testing.T) { + // test that the version is correctly parsed if returned if valid JSON is returned the url endpoint + version0 := "0.0.0" + version1 := "1.0.0" + handler := &URLHandlerCorrect{ + K8sReleases: []k8sRelease{{Version: version0}, {Version: version1}}, + } + server := httptest.NewServer(handler) + + k8sVersions, err := getK8sVersionsFromURL(server.URL) + if err != nil { + t.Fatalf(err.Error()) + } + if len(k8sVersions) != 2 { // TODO(aprindle) change to len(handler....) + //Check values here as well? Write eq method? + t.Fatalf("Expected two kubernetes versions from URL to be %s, it was instead %s", 2, len(k8sVersions)) + } +} + +type URLHandlerNone struct{} + +func (h *URLHandlerNone) ServeHTTP(w http.ResponseWriter, r *http.Request) { +} + +func TestGetK8sVersionsFromURLNone(t *testing.T) { + // test that an error is returned if nothing is returned at the url endpoint + handler := &URLHandlerNone{} + server := httptest.NewServer(handler) + + _, err := getK8sVersionsFromURL(server.URL) + if err == nil { + t.Fatalf("No kubernetes versions were returned from URL but no error was thrown") + } +} + +type URLHandlerMalformed struct{} + +func (h *URLHandlerMalformed) ServeHTTP(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/javascript") + fmt.Fprintf(w, "Malformed JSON") +} + +func TestGetK8sVersionsFromURLMalformed(t *testing.T) { + // test that an error is returned if malformed JSON is at the url endpoint + handler := &URLHandlerMalformed{} + server := httptest.NewServer(handler) + + _, err := getK8sVersionsFromURL(server.URL) + if err == nil { + t.Fatalf("Malformed version value was returned from URL but no error was thrown") + } +} + +func TestPrintKubernetesVersions(t *testing.T) { + // test that no kubernetes version text is printed if there are no versions being served + // TODO(aprindle) or should this be an error?!?! + handlerNone := &URLHandlerNone{} + server := httptest.NewServer(handlerNone) + + var outputBuffer bytes.Buffer + PrintKubernetesVersions(&outputBuffer, server.URL) + if len(outputBuffer.String()) != 0 { + t.Fatalf("Expected PrintKubernetesVersions to not output text as there are no versioned served at the current URL but output was [%s]", outputBuffer.String()) + } + + // test that update text is printed if the latest version is greater than the current version + // k8sVersionsFromURL = "100.0.0-dev" + version0 := "0.0.0" + version1 := "1.0.0" + handlerCorrect := &URLHandlerCorrect{ + K8sReleases: []k8sRelease{{Version: version0}, {Version: version1}}, + } + server = httptest.NewServer(handlerCorrect) + + PrintKubernetesVersions(&outputBuffer, server.URL) + if len(outputBuffer.String()) == 0 { + t.Fatalf("Expected PrintKubernetesVersion to output text as %s versions were served from URL but output was [%s]", + 2, outputBuffer.String()) //TODO(aprindle) change the 2 + } +} diff --git a/pkg/minikube/notify/notify_test.go b/pkg/minikube/notify/notify_test.go index cbc6ef01f0..63d27c3cec 100644 --- a/pkg/minikube/notify/notify_test.go +++ b/pkg/minikube/notify/notify_test.go @@ -43,26 +43,26 @@ func TestShouldCheckURL(t *testing.T) { // test that if users disable update notification in config, the URL version does not get checked viper.Set(config.WantUpdateNotification, false) if shouldCheckURLVersion(lastUpdateCheckFilePath) { - t.Fatalf("Error: shouldCheckURLVersion returned true even though config had WantUpdateNotification: false") + t.Fatalf("shouldCheckURLVersion returned true even though config had WantUpdateNotification: false") } // test that if users want update notification, the URL version does get checked viper.Set(config.WantUpdateNotification, true) if shouldCheckURLVersion(lastUpdateCheckFilePath) == false { - t.Fatalf("Error: shouldCheckURLVersion returned false even though there was no last_update_check file") + t.Fatalf("shouldCheckURLVersion returned false even though there was no last_update_check file") } // test that update notifications get triggered if it has been longer than 24 hours viper.Set(config.ReminderWaitPeriodInHours, 24) writeTimeToFile(lastUpdateCheckFilePath, time.Time{}) //time.Time{} returns time -> January 1, year 1, 00:00:00.000000000 UTC. if shouldCheckURLVersion(lastUpdateCheckFilePath) == false { - t.Fatalf("Error: shouldCheckURLVersion returned false even though longer than 24 hours since last update") + t.Fatalf("shouldCheckURLVersion returned false even though longer than 24 hours since last update") } // test that update notifications do not get triggered if it has been less than 24 hours writeTimeToFile(lastUpdateCheckFilePath, time.Now().UTC()) if shouldCheckURLVersion(lastUpdateCheckFilePath) == true { - t.Fatalf("Error: shouldCheckURLVersion returned false even though longer than 24 hours since last update") + t.Fatalf("shouldCheckURLVersion returned false even though longer than 24 hours since last update") } } @@ -129,7 +129,7 @@ func TestGetLatestVersionFromURLMalformed(t *testing.T) { _, err := getLatestVersionFromURL(server.URL) if err == nil { - t.Fatalf("Error: ") + t.Fatalf("Malformed version value was returned from URL but no error was thrown") } } From 3eccdd523f5332a76bbe7f681d710f99742e2f17 Mon Sep 17 00:00:00 2001 From: aprindle Date: Wed, 6 Jul 2016 15:18:10 -0700 Subject: [PATCH 2/2] Added json file and schema for k8s versions. Also updated documentation. --- deploy/minikube/k8s_releases.json | 5 +++++ deploy/minikube/k8s_schema.json | 15 +++++++++++++++ deploy/minikube/schema_check.go | 16 ++++++++++------ docs/minikube.md | 1 + docs/minikube_get-k8s-versions.md | 30 ++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 deploy/minikube/k8s_releases.json create mode 100644 deploy/minikube/k8s_schema.json create mode 100644 docs/minikube_get-k8s-versions.md diff --git a/deploy/minikube/k8s_releases.json b/deploy/minikube/k8s_releases.json new file mode 100644 index 0000000000..bc2993d8bf --- /dev/null +++ b/deploy/minikube/k8s_releases.json @@ -0,0 +1,5 @@ +[ + { + "version": "v1.3.0" + } +] diff --git a/deploy/minikube/k8s_schema.json b/deploy/minikube/k8s_schema.json new file mode 100644 index 0000000000..2e211dbced --- /dev/null +++ b/deploy/minikube/k8s_schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "items": { + "type": "object", + "properties": { + "version": { + "type": "string" + } + }, + "required": [ + "version" + ] + } +} diff --git a/deploy/minikube/schema_check.go b/deploy/minikube/schema_check.go index 64239d7fee..2aadc436c9 100644 --- a/deploy/minikube/schema_check.go +++ b/deploy/minikube/schema_check.go @@ -25,11 +25,17 @@ import ( ) func main() { - schemaPath, _ := filepath.Abs("deploy/minikube/schema.json") + validateSchema("deploy/minikube/schema.json", "deploy/minikube/releases.json") + validateSchema("deploy/minikube/k8s_schema.json", "deploy/minikube/k8s_releases.json") + os.Exit(0) +} + +func validateSchema(schemaPathString string, docPathString string) { + schemaPath, _ := filepath.Abs(schemaPathString) schemaUri := "file://" + schemaPath schemaLoader := gojsonschema.NewReferenceLoader(schemaUri) - docPath, _ := filepath.Abs("deploy/minikube/releases.json") + docPath, _ := filepath.Abs(docPathString) docUri := "file://" + docPath docLoader := gojsonschema.NewReferenceLoader(docUri) @@ -39,14 +45,12 @@ func main() { } if result.Valid() { - fmt.Printf("The document is valid\n") - os.Exit(0) + fmt.Printf("The document %s is valid\n", docPathString) } else { - fmt.Printf("The document is not valid. see errors :\n") + fmt.Printf("The document %s is not valid. see errors :\n", docPathString) for _, desc := range result.Errors() { fmt.Printf("- %s\n", desc) } os.Exit(1) } - } diff --git a/docs/minikube.md b/docs/minikube.md index eb3adb0819..341318fb3a 100644 --- a/docs/minikube.md +++ b/docs/minikube.md @@ -25,6 +25,7 @@ Minikube is a CLI tool that provisions and manages single-node Kubernetes cluste * [minikube dashboard](minikube_dashboard.md) - Opens/displays the kubernetes dashboard URL for your local cluster * [minikube delete](minikube_delete.md) - Deletes a local kubernetes cluster. * [minikube docker-env](minikube_docker-env.md) - sets up docker env variables; similar to '$(docker-machine env)' +* [minikube get-k8s-versions](minikube_get-k8s-versions.md) - Gets the list of available kubernetes versions available for minikube. * [minikube ip](minikube_ip.md) - Retrieve the IP address of the running cluster. * [minikube logs](minikube_logs.md) - Gets the logs of the running localkube instance, used for debugging minikube, not user code. * [minikube ssh](minikube_ssh.md) - Log into or run a command on a machine with SSH; similar to 'docker-machine ssh' diff --git a/docs/minikube_get-k8s-versions.md b/docs/minikube_get-k8s-versions.md new file mode 100644 index 0000000000..66cbc86214 --- /dev/null +++ b/docs/minikube_get-k8s-versions.md @@ -0,0 +1,30 @@ +## minikube get-k8s-versions + +Gets the list of available kubernetes versions available for minikube. + +### Synopsis + + +Gets the list of available kubernetes versions available for minikube. + +``` +minikube get-k8s-versions +``` + +### Options inherited from parent commands + +``` + --alsologtostderr[=false]: log to standard error as well as files + --log-flush-frequency=5s: Maximum number of seconds between log flushes + --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace + --log_dir="": If non-empty, write log files in this directory + --logtostderr[=false]: log to standard error instead of files + --show-libmachine-logs[=false]: Whether or not to show logs from libmachine. + --stderrthreshold=2: logs at or above this threshold go to stderr + --v=0: log level for V logs + --vmodule=: comma-separated list of pattern=N settings for file-filtered logging +``` + +### SEE ALSO +* [minikube](minikube.md) - Minikube is a tool for managing local Kubernetes clusters. +