Merge pull request #277 from aaron-prindle/get-kubernetes-version

Added get_kubernetes_versions command and tests
pull/296/head
dlorenc 2016-07-07 13:38:47 -07:00 committed by GitHub
commit 9fa002d573
9 changed files with 297 additions and 11 deletions

View File

@ -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)
}

View File

@ -0,0 +1,5 @@
[
{
"version": "v1.3.0"
}
]

View File

@ -0,0 +1,15 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items": {
"type": "object",
"properties": {
"version": {
"type": "string"
}
},
"required": [
"version"
]
}
}

View File

@ -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)
}
}

View File

@ -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 service](minikube_service.md) - Gets the kubernetes URL for the specified service in your local cluster

View File

@ -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.

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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")
}
}