Added unit tests which cover localkube caching scenarios. Refactored
code to use localkube_caching.go and localkubeCacher.pull/438/head
parent
405453758e
commit
976eeeb12e
|
@ -19,7 +19,6 @@ package cluster
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -39,7 +38,6 @@ import (
|
|||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/crypto/ssh"
|
||||
kubeApi "k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
|
@ -211,101 +209,14 @@ var assets = []fileToCopy{
|
|||
},
|
||||
}
|
||||
|
||||
func (k *KubernetesConfig) getLocalkubeCacheFilepath() string {
|
||||
return filepath.Join(constants.Minipath, "cache", "localkube",
|
||||
filepath.Base("localkube-"+util.GetMD5Hash(k.KubernetesVersion)))
|
||||
}
|
||||
|
||||
func (k *KubernetesConfig) isLocalkubeCached() bool {
|
||||
if _, err := os.Stat(k.getLocalkubeCacheFilepath()); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (k *KubernetesConfig) cacheLocalkube(response *http.Response) error {
|
||||
// store localkube inside the .minikube dir
|
||||
out, err := os.Create(k.getLocalkubeCacheFilepath())
|
||||
if err != nil {
|
||||
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
defer response.Body.Close()
|
||||
if _, err = io.Copy(out, response.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *KubernetesConfig) downloadAndCacheLocalkube() error {
|
||||
resp := &http.Response{}
|
||||
err := errors.New("")
|
||||
downloader := func() (err error) {
|
||||
url, err := util.GetLocalkubeDownloadURL(k.KubernetesVersion,
|
||||
constants.LocalkubeLinuxFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err = http.Get(url)
|
||||
return err
|
||||
}
|
||||
|
||||
if err = util.Retry(5, downloader); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.cacheLocalkube(resp); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateLocalkubeFromURL(config KubernetesConfig, client *ssh.Client) error {
|
||||
if !config.isLocalkubeCached() {
|
||||
if err := config.downloadAndCacheLocalkube(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := config.transferCachedLocalkubeToVM(client); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *KubernetesConfig) transferCachedLocalkubeToVM(client *ssh.Client) error {
|
||||
contents, err := ioutil.ReadFile(k.getLocalkubeCacheFilepath())
|
||||
if err != nil {
|
||||
glog.Infof("Error loading asset out/localkube: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err = sshutil.Transfer(bytes.NewReader(contents), len(contents), "/usr/local/bin",
|
||||
"localkube", "0777", client); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateLocalkubeFromAsset(client *ssh.Client) error {
|
||||
contents, err := Asset("out/localkube")
|
||||
if err != nil {
|
||||
glog.Infof("Error loading asset out/localkube: %s", err)
|
||||
return err
|
||||
}
|
||||
if err := sshutil.Transfer(bytes.NewReader(contents), len(contents), "/usr/local/bin",
|
||||
"localkube", "0777", client); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateCluster(h sshAble, d drivers.Driver, config KubernetesConfig) error {
|
||||
client, err := sshutil.NewSSHClient(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if localkubeURLWasSpecified(config) {
|
||||
if err = updateLocalkubeFromURL(config, client); err != nil {
|
||||
lCacher := localkubeCacher{config}
|
||||
if err = updateLocalkubeFromURL(lCacher, client); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
@ -394,7 +305,6 @@ func createVirtualboxHost(config MachineConfig) drivers.Driver {
|
|||
|
||||
func (m *MachineConfig) CacheMinikubeISOFromURL() error {
|
||||
// store the miniube-iso inside the .minikube dir
|
||||
// TODO(aprindle) put this in a retry loop?
|
||||
response, err := http.Get(m.MinikubeISO)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -568,3 +568,48 @@ func TestUpdateKubernetesVersion(t *testing.T) {
|
|||
t.Fatalf("File not copied. Expected transfers to contain: %s. It was: %s", contents, transferred)
|
||||
}
|
||||
}
|
||||
|
||||
type nopCloser struct {
|
||||
io.Reader
|
||||
}
|
||||
|
||||
func (nopCloser) Close() error { return nil }
|
||||
|
||||
func TestIsLocalkubeCached(t *testing.T) {
|
||||
tempDir := tests.MakeTempDir()
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
inputArr := [...]string{
|
||||
"v1.3.3",
|
||||
"1.3.0",
|
||||
"http://test-url.localkube.com/localkube-binary",
|
||||
"file:///test/dir/to/localkube-binary",
|
||||
}
|
||||
|
||||
readCloser := nopCloser{}
|
||||
|
||||
localkubeCacher := localkubeCacher{
|
||||
k8sConf: KubernetesConfig{},
|
||||
}
|
||||
|
||||
inner := func(input string) {
|
||||
localkubeCacher.k8sConf = KubernetesConfig{
|
||||
KubernetesVersion: input,
|
||||
}
|
||||
if localkubeCacher.isLocalkubeCached() {
|
||||
t.Errorf("IsLocalKubeCached returned true even though %s was not cached",
|
||||
localkubeCacher.getLocalkubeCacheFilepath())
|
||||
}
|
||||
|
||||
readCloser = nopCloser{bytes.NewBufferString("test-localkube-binary-data")}
|
||||
localkubeCacher.cacheLocalkube(readCloser)
|
||||
if !localkubeCacher.isLocalkubeCached() {
|
||||
t.Errorf("IsLocalKubeCached returned false even though %s was cached",
|
||||
localkubeCacher.getLocalkubeCacheFilepath())
|
||||
}
|
||||
|
||||
}
|
||||
for _, input := range inputArr {
|
||||
inner(input)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
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 cluster
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/sshutil"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
// localkubeCacher is a struct with methods designed for caching localkube
|
||||
type localkubeCacher struct {
|
||||
k8sConf KubernetesConfig
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) getLocalkubeCacheFilepath() string {
|
||||
return filepath.Join(constants.Minipath, "cache", "localkube",
|
||||
filepath.Base(url.QueryEscape("localkube-"+l.k8sConf.KubernetesVersion)))
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) isLocalkubeCached() bool {
|
||||
if _, err := os.Stat(l.getLocalkubeCacheFilepath()); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) cacheLocalkube(body io.ReadCloser) error {
|
||||
// store localkube inside the .minikube dir
|
||||
out, err := os.Create(l.getLocalkubeCacheFilepath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
defer body.Close()
|
||||
if _, err = io.Copy(out, body); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) downloadAndCacheLocalkube() error {
|
||||
resp := &http.Response{}
|
||||
err := errors.New("")
|
||||
downloader := func() (err error) {
|
||||
url, err := util.GetLocalkubeDownloadURL(l.k8sConf.KubernetesVersion,
|
||||
constants.LocalkubeLinuxFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err = http.Get(url)
|
||||
return err
|
||||
}
|
||||
|
||||
if err = util.Retry(5, downloader); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = l.cacheLocalkube(resp.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateLocalkubeFromURL(lCacher localkubeCacher, client *ssh.Client) error {
|
||||
if !lCacher.isLocalkubeCached() {
|
||||
if err := lCacher.downloadAndCacheLocalkube(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := lCacher.transferCachedLocalkubeToVM(client); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) transferCachedLocalkubeToVM(client *ssh.Client) error {
|
||||
contents, err := ioutil.ReadFile(l.getLocalkubeCacheFilepath())
|
||||
if err != nil {
|
||||
glog.Infof("Error loading asset out/localkube: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err = sshutil.Transfer(bytes.NewReader(contents), len(contents), "/usr/local/bin",
|
||||
"localkube", "0777", client); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateLocalkubeFromAsset(client *ssh.Client) error {
|
||||
contents, err := Asset("out/localkube")
|
||||
if err != nil {
|
||||
glog.Infof("Error loading asset out/localkube: %s", err)
|
||||
return err
|
||||
}
|
||||
if err := sshutil.Transfer(bytes.NewReader(contents), len(contents), "/usr/local/bin",
|
||||
"localkube", "0777", client); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||
package util
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
|
@ -107,7 +105,6 @@ func GetLocalkubeDownloadURL(versionOrURL string, filename string) (string, erro
|
|||
return fmt.Sprintf("%s%s/%s", constants.LocalkubeDownloadURLPrefix, versionOrURL, filename), nil
|
||||
}
|
||||
|
||||
<<<<<<< 38d0f083510df2b7b91dc59fdbc8517b8d02fbd1
|
||||
type MultiError struct {
|
||||
Errors []error
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue