diff --git a/Makefile b/Makefile index dd32ae71f1..74445a3658 100644 --- a/Makefile +++ b/Makefile @@ -141,3 +141,7 @@ out/minikube-installer.exe: out/minikube-windows-amd64.exe makensis out/windows_tmp/minikube.nsi mv out/windows_tmp/minikube-installer.exe out/minikube-installer.exe rm -rf out/windows_tmp + +.PHONY: check-release +check-release: + go test -v ./deploy/minikube/release_sanity_test.go -tags=release diff --git a/RELEASING.md b/RELEASING.md index c191a8292e..8bbb3a7f0f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -106,3 +106,8 @@ These are downstream packages that are being maintained by others and how to upg #### [How to Generate an Appcast Checkpoint for Homebrew](https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/appcast.md) `curl --compressed --location --user-agent 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36' "https://github.com/kubernetes/minikube/releases.atom" | sed 's|[^<]*||g' | shasum --algorithm 256` + +## Release Verification + +After you've finished the release, run this command from the release commit to verify the release was done correctly: +`make check-release`. \ No newline at end of file diff --git a/deploy/minikube/release_sanity_test.go b/deploy/minikube/release_sanity_test.go index 4145016b81..5858a54e68 100644 --- a/deploy/minikube/release_sanity_test.go +++ b/deploy/minikube/release_sanity_test.go @@ -1,3 +1,5 @@ +// +build release + /* Copyright 2016 The Kubernetes Authors All rights reserved. @@ -14,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package minikube +package main import ( "crypto/sha256" @@ -25,7 +27,9 @@ import ( "testing" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/kubernetes_versions" "k8s.io/minikube/pkg/minikube/notify" + "k8s.io/minikube/pkg/util" ) const ( @@ -70,10 +74,43 @@ func TestReleasesJson(t *testing.T) { actualSha, err := getShaFromURL(getDownloadURL(r.Name, platform)) if err != nil { t.Errorf("Error calcuating SHA for %s-%s. Error: %s", r.Name, platform, err) + continue } if actualSha != sha { t.Errorf("ERROR: SHA does not match for version %s, platform %s. Expected %s, got %s.", r.Name, platform, sha, actualSha) + continue } } } } + +func TestK8sReleases(t *testing.T) { + releases, err := kubernetes_versions.GetK8sVersionsFromURL(constants.KubernetesVersionGCSURL) + if err != nil { + t.Fatalf("Error getting k8s_releases.json: %s", err) + } + + for _, r := range releases { + fmt.Printf("Checking release: %s\n", r.Version) + url, err := util.GetLocalkubeDownloadURL(r.Version, constants.LocalkubeLinuxFilename) + if err != nil { + t.Errorf("Error getting URL for %s. Error: %s", r.Version, err) + continue + } + shaURL := fmt.Sprintf("%s%s", url, constants.ShaSuffix) + expectedSha, err := util.ParseSHAFromURL(shaURL) + if err != nil { + t.Errorf("Error retrieving SHA for %s. Error: %s", r.Version, err) + continue + } + actualSha, err := getShaFromURL(url) + if err != nil { + t.Errorf("Error calculating SHA for %s. Error: %s", r.Version, err) + continue + } + if expectedSha != actualSha { + t.Errorf("ERROR: SHA does not match for version %s. Expected %s, got %s.", r.Version, expectedSha, actualSha) + continue + } + } +} diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 2f19463a47..1565a47154 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -440,24 +440,12 @@ func createVirtualboxHost(config MachineConfig) drivers.Driver { } func isIsoChecksumValid(isoData *[]byte, shaURL string) bool { - r, err := http.Get(shaURL) + expectedSum, err := util.ParseSHAFromURL(shaURL) if err != nil { - glog.Errorf("Error downloading ISO checksum: %s", err) - return false - } else if r.StatusCode != http.StatusOK { - glog.Errorf("Error downloading ISO checksum. Got HTTP Error: %s", r.Status) + glog.Errorf("Error retrieving SHA from URL: %s. Error: %s.", shaURL, err) return false } - defer r.Body.Close() - body, err := ioutil.ReadAll(r.Body) - if err != nil { - glog.Errorf("Error reading ISO checksum: %s", err) - return false - } - - expectedSum := strings.Trim(string(body), "\n") - b := sha256.Sum256(*isoData) actualSum := hex.EncodeToString(b[:]) if string(expectedSum) != actualSum { diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index 24f28855db..87084ec9ac 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -57,7 +57,8 @@ var LogFlags = [...]string{ const ( DefaultIsoUrl = "https://storage.googleapis.com/minikube/minikube-0.7.iso" - DefaultIsoShaUrl = "https://storage.googleapis.com/minikube/minikube-0.7.iso.sha256" + ShaSuffix = ".sha256" + DefaultIsoShaUrl = DefaultIsoUrl + ShaSuffix DefaultMemory = 1024 DefaultCPUS = 1 DefaultDiskSize = "20g" @@ -65,6 +66,7 @@ const ( DefaultStatusFormat = "minikubeVM: {{.MinikubeStatus}}\n" + "localkube: {{.LocalkubeStatus}}\n" GithubMinikubeReleasesURL = "https://storage.googleapis.com/minikube/releases.json" + KubernetesVersionGCSURL = "https://storage.googleapis.com/minikube/k8s_releases.json" ) var DefaultKubernetesVersion = version.Get().GitVersion diff --git a/pkg/minikube/kubernetes_versions/kubernetes_versions.go b/pkg/minikube/kubernetes_versions/kubernetes_versions.go index 3b955e0fcb..8f419e0e0c 100644 --- a/pkg/minikube/kubernetes_versions/kubernetes_versions.go +++ b/pkg/minikube/kubernetes_versions/kubernetes_versions.go @@ -22,18 +22,18 @@ import ( "io" "net/http" + "k8s.io/minikube/pkg/minikube/constants" + "github.com/golang/glog" "github.com/pkg/errors" ) -const kubernetesVersionGCSURL = "https://storage.googleapis.com/minikube/k8s_releases.json" - func PrintKubernetesVersionsFromGCS(output io.Writer) { - PrintKubernetesVersions(output, kubernetesVersionGCSURL) + PrintKubernetesVersions(output, constants.KubernetesVersionGCSURL) } func PrintKubernetesVersions(output io.Writer, url string) { - k8sVersions, err := getK8sVersionsFromURL(url) + k8sVersions, err := GetK8sVersionsFromURL(url) if err != nil { glog.Errorln(err) return @@ -45,13 +45,13 @@ func PrintKubernetesVersions(output io.Writer, url string) { } } -type k8sRelease struct { +type K8sRelease struct { Version string } -type k8sReleases []k8sRelease +type K8sReleases []K8sRelease -func getJson(url string, target *k8sReleases) error { +func getJson(url string, target *K8sReleases) error { r, err := http.Get(url) if err != nil { return errors.Wrapf(err, "Error getting json from url: %s via http", url) @@ -61,13 +61,13 @@ func getJson(url string, target *k8sReleases) error { return json.NewDecoder(r.Body).Decode(target) } -func getK8sVersionsFromURL(url string) (k8sReleases, error) { - var k8sVersions k8sReleases +func GetK8sVersionsFromURL(url string) (K8sReleases, error) { + var k8sVersions K8sReleases if err := getJson(url, &k8sVersions); err != nil { - return k8sReleases{}, errors.Wrapf(err, "Error getting json via http with url: %s", url) + return K8sReleases{}, errors.Wrapf(err, "Error getting json via http with url: %s", url) } if len(k8sVersions) == 0 { - return k8sReleases{}, errors.Errorf("There were no json k8s Releases at the url specified: %s", url) + return K8sReleases{}, errors.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 index 3878321a9b..46e93fa9d8 100644 --- a/pkg/minikube/kubernetes_versions/kubernetes_versions_test.go +++ b/pkg/minikube/kubernetes_versions/kubernetes_versions_test.go @@ -26,7 +26,7 @@ import ( ) type URLHandlerCorrect struct { - K8sReleases k8sReleases + K8sReleases K8sReleases } func (h *URLHandlerCorrect) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -44,11 +44,11 @@ func TestGetK8sVersionsFromURLCorrect(t *testing.T) { version0 := "0.0.0" version1 := "1.0.0" handler := &URLHandlerCorrect{ - K8sReleases: []k8sRelease{{Version: version0}, {Version: version1}}, + K8sReleases: []K8sRelease{{Version: version0}, {Version: version1}}, } server := httptest.NewServer(handler) - k8sVersions, err := getK8sVersionsFromURL(server.URL) + k8sVersions, err := GetK8sVersionsFromURL(server.URL) if err != nil { t.Fatalf(err.Error()) } @@ -68,7 +68,7 @@ func TestGetK8sVersionsFromURLNone(t *testing.T) { handler := &URLHandlerNone{} server := httptest.NewServer(handler) - _, err := getK8sVersionsFromURL(server.URL) + _, err := GetK8sVersionsFromURL(server.URL) if err == nil { t.Fatalf("No kubernetes versions were returned from URL but no error was thrown") } @@ -86,7 +86,7 @@ func TestGetK8sVersionsFromURLMalformed(t *testing.T) { handler := &URLHandlerMalformed{} server := httptest.NewServer(handler) - _, err := getK8sVersionsFromURL(server.URL) + _, err := GetK8sVersionsFromURL(server.URL) if err == nil { t.Fatalf("Malformed version value was returned from URL but no error was thrown") } @@ -109,7 +109,7 @@ func TestPrintKubernetesVersions(t *testing.T) { version0 := "0.0.0" version1 := "1.0.0" handlerCorrect := &URLHandlerCorrect{ - K8sReleases: []k8sRelease{{Version: version0}, {Version: version1}}, + K8sReleases: []K8sRelease{{Version: version0}, {Version: version1}}, } server = httptest.NewServer(handlerCorrect) diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 6ef20bdd72..b19de86c1a 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -21,6 +21,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "net/http" "net/url" "os" @@ -112,6 +113,23 @@ func GetLocalkubeDownloadURL(versionOrURL string, filename string) (string, erro return fmt.Sprintf("%s%s/%s", constants.LocalkubeDownloadURLPrefix, versionOrURL, filename), nil } +func ParseSHAFromURL(url string) (string, error) { + r, err := http.Get(url) + if err != nil { + return "", errors.Wrap(err, "Error downloading checksum.") + } else if r.StatusCode != http.StatusOK { + return "", errors.Errorf("Error downloading checksum. Got HTTP Error: %s", r.Status) + } + + defer r.Body.Close() + body, err := ioutil.ReadAll(r.Body) + if err != nil { + return "", errors.Wrap(err, "Error reading checksum.") + } + + return strings.Trim(string(body), "\n"), nil +} + type MultiError struct { Errors []error }