2016-12-05 22:49:52 +00:00
// +build integration
/ *
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 integration
import (
2019-09-11 16:59:38 +00:00
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"os/exec"
2020-03-04 22:48:40 +00:00
"path"
2019-09-11 16:59:38 +00:00
"path/filepath"
2019-10-11 14:43:00 +00:00
"regexp"
2019-11-06 22:14:56 +00:00
"runtime"
2019-09-11 16:59:38 +00:00
"strings"
2016-12-05 22:49:52 +00:00
"testing"
2019-09-11 16:59:38 +00:00
"time"
2019-11-07 01:20:52 +00:00
"github.com/google/go-cmp/cmp"
2020-12-09 19:06:17 +00:00
"k8s.io/minikube/pkg/drivers/kic/oci"
2020-04-07 04:03:12 +00:00
"k8s.io/minikube/pkg/minikube/config"
2019-11-07 01:20:52 +00:00
"k8s.io/minikube/pkg/minikube/localpath"
2020-08-31 18:21:23 +00:00
"k8s.io/minikube/pkg/minikube/reason"
2020-04-07 04:26:45 +00:00
"k8s.io/minikube/pkg/util/retry"
2019-11-07 01:20:52 +00:00
2019-09-11 16:59:38 +00:00
"github.com/elazarl/goproxy"
"github.com/hashicorp/go-retryablehttp"
2019-11-07 01:20:52 +00:00
"github.com/otiai10/copy"
2019-09-11 16:59:38 +00:00
"github.com/phayes/freeport"
"github.com/pkg/errors"
"golang.org/x/build/kubernetes/api"
2016-12-05 22:49:52 +00:00
)
2019-09-11 16:59:38 +00:00
// validateFunc are for subtests that share a single setup
type validateFunc func ( context . Context , * testing . T , string )
2020-04-07 20:14:30 +00:00
// used in validateStartWithProxy and validateSoftStart
var apiPortTest = 8441
2019-09-11 16:59:38 +00:00
// TestFunctional are functionality tests which can safely share a profile in parallel
2017-05-30 20:23:24 +00:00
func TestFunctional ( t * testing . T ) {
2019-09-11 16:59:38 +00:00
profile := UniqueProfileName ( "functional" )
2020-02-21 00:19:59 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , Minutes ( 40 ) )
2020-02-12 22:26:38 +00:00
defer func ( ) {
2020-03-04 22:48:40 +00:00
if ! * cleanup {
return
}
2020-02-12 22:26:38 +00:00
p := localSyncTestPath ( )
if err := os . Remove ( p ) ; err != nil {
2020-03-26 04:43:32 +00:00
t . Logf ( "unable to remove %q: %v" , p , err )
2020-02-12 22:26:38 +00:00
}
2020-04-08 22:04:12 +00:00
2020-05-08 20:12:30 +00:00
Cleanup ( t , profile , cancel )
2020-02-12 22:26:38 +00:00
} ( )
2019-09-11 16:59:38 +00:00
// Serial tests
t . Run ( "serial" , func ( t * testing . T ) {
tests := [ ] struct {
name string
validator validateFunc
} {
2020-02-12 17:54:17 +00:00
{ "CopySyncFile" , setupFileSync } , // Set file for the file sync test case
{ "StartWithProxy" , validateStartWithProxy } , // Set everything else up for success
2020-04-07 04:06:27 +00:00
{ "SoftStart" , validateSoftStart } , // do a soft start. ensure config didnt change.
2020-02-12 17:54:17 +00:00
{ "KubeContext" , validateKubeContext } , // Racy: must come immediately after "minikube start"
{ "KubectlGetPods" , validateKubectlGetPods } , // Make sure apiserver is up
{ "CacheCmd" , validateCacheCmd } , // Caches images needed for subsequent tests because of proxy
{ "MinikubeKubectlCmd" , validateMinikubeKubectl } , // Make sure `minikube kubectl` works
2020-08-17 11:26:26 +00:00
{ "MinikubeKubectlCmdDirectly" , validateMinikubeKubectlDirectCall } ,
2020-11-28 20:40:09 +00:00
{ "ExtraConfig" , validateExtraConfig } , // Ensure extra cmdline config change is saved
2019-09-11 16:59:38 +00:00
}
for _ , tc := range tests {
tc := tc
2020-08-22 17:18:15 +00:00
if ctx . Err ( ) == context . DeadlineExceeded {
t . Fatalf ( "Unable to run more tests (deadline exceeded)" )
}
2019-09-11 16:59:38 +00:00
t . Run ( tc . name , func ( t * testing . T ) {
2020-04-07 04:26:45 +00:00
tc . validator ( ctx , t , profile )
2019-09-11 16:59:38 +00:00
} )
2019-07-30 04:52:05 +00:00
}
2019-09-11 16:59:38 +00:00
} )
2019-07-30 04:52:05 +00:00
2019-09-11 16:59:38 +00:00
// Parallelized tests
t . Run ( "parallel" , func ( t * testing . T ) {
tests := [ ] struct {
name string
validator validateFunc
} {
{ "ComponentHealth" , validateComponentHealth } ,
{ "ConfigCmd" , validateConfigCmd } ,
{ "DashboardCmd" , validateDashboardCmd } ,
2020-01-09 19:10:23 +00:00
{ "DryRun" , validateDryRun } ,
2019-10-13 15:24:40 +00:00
{ "StatusCmd" , validateStatusCmd } ,
2019-09-11 16:59:38 +00:00
{ "LogsCmd" , validateLogsCmd } ,
{ "MountCmd" , validateMountCmd } ,
{ "ProfileCmd" , validateProfileCmd } ,
2019-10-30 17:44:54 +00:00
{ "ServiceCmd" , validateServiceCmd } ,
2019-10-11 14:43:00 +00:00
{ "AddonsCmd" , validateAddonsCmd } ,
2019-09-11 16:59:38 +00:00
{ "PersistentVolumeClaim" , validatePersistentVolumeClaim } ,
{ "TunnelCmd" , validateTunnelCmd } ,
{ "SSHCmd" , validateSSHCmd } ,
2019-10-29 05:31:57 +00:00
{ "MySQL" , validateMySQL } ,
2019-11-07 01:20:52 +00:00
{ "FileSync" , validateFileSync } ,
2020-03-04 22:48:40 +00:00
{ "CertSync" , validateCertSync } ,
2019-12-16 15:58:45 +00:00
{ "UpdateContextCmd" , validateUpdateContextCmd } ,
2020-02-13 09:17:11 +00:00
{ "DockerEnv" , validateDockerEnv } ,
2020-02-20 21:57:09 +00:00
{ "NodeLabels" , validateNodeLabels } ,
2019-09-11 16:59:38 +00:00
}
for _ , tc := range tests {
tc := tc
2020-08-22 17:18:15 +00:00
if ctx . Err ( ) == context . DeadlineExceeded {
t . Fatalf ( "Unable to run more tests (deadline exceeded)" )
}
2019-09-11 16:59:38 +00:00
t . Run ( tc . name , func ( t * testing . T ) {
MaybeParallel ( t )
tc . validator ( ctx , t , profile )
} )
}
2019-07-30 04:52:05 +00:00
} )
2019-09-11 16:59:38 +00:00
}
2020-02-20 21:57:09 +00:00
// validateNodeLabels checks if minikube cluster is created with correct kubernetes's node label
func validateNodeLabels ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-02-22 00:01:47 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "get" , "nodes" , "--output=go-template" , "--template='{{range $k, $v := (index .items 0).metadata.labels}}{{$k}} {{end}}'" ) )
2020-02-20 21:57:09 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to 'kubectl get nodes' with args %q: %v" , rr . Command ( ) , err )
2020-02-20 21:57:09 +00:00
}
expectedLabels := [ ] string { "minikube.k8s.io/commit" , "minikube.k8s.io/version" , "minikube.k8s.io/updated_at" , "minikube.k8s.io/name" }
for _ , el := range expectedLabels {
2020-02-22 00:01:47 +00:00
if ! strings . Contains ( rr . Output ( ) , el ) {
2020-04-02 04:34:37 +00:00
t . Errorf ( "expected to have label %q in node labels but got : %s" , el , rr . Output ( ) )
2020-02-20 21:57:09 +00:00
}
}
}
2020-02-13 09:17:11 +00:00
// check functionality of minikube after evaling docker-env
func validateDockerEnv ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-05-24 22:20:58 +00:00
mctx , cancel := context . WithTimeout ( ctx , Seconds ( 30 ) )
2020-02-13 09:17:11 +00:00
defer cancel ( )
2020-05-24 21:55:38 +00:00
var rr * RunResult
var err error
2020-05-27 20:45:27 +00:00
if runtime . GOOS == "windows" {
2020-05-27 22:40:43 +00:00
c := exec . CommandContext ( mctx , "powershell.exe" , "-NoProfile" , "-NonInteractive" , Target ( ) + " -p " + profile + " docker-env | Invoke-Expression ;" + Target ( ) + " status -p " + profile )
rr , err = Run ( t , c )
2020-05-24 21:55:38 +00:00
} else {
c := exec . CommandContext ( mctx , "/bin/bash" , "-c" , "eval $(" + Target ( ) + " -p " + profile + " docker-env) && " + Target ( ) + " status -p " + profile )
// we should be able to get minikube status with a bash which evaled docker-env
rr , err = Run ( t , c )
}
2020-05-27 20:45:27 +00:00
if mctx . Err ( ) == context . DeadlineExceeded {
t . Errorf ( "failed to run the command by deadline. exceeded timeout. %s" , rr . Command ( ) )
2020-05-24 22:20:58 +00:00
}
2020-02-13 09:17:11 +00:00
if err != nil {
2020-05-24 21:55:38 +00:00
t . Fatalf ( "failed to do status after eval-ing docker-env. error: %v" , err )
2020-02-13 09:17:11 +00:00
}
if ! strings . Contains ( rr . Output ( ) , "Running" ) {
2020-04-02 04:40:09 +00:00
t . Fatalf ( "expected status output to include 'Running' after eval docker-env but got: *%s*" , rr . Output ( ) )
2020-02-13 09:17:11 +00:00
}
2020-05-24 22:20:58 +00:00
mctx , cancel = context . WithTimeout ( ctx , Seconds ( 30 ) )
2020-02-13 09:17:11 +00:00
defer cancel ( )
// do a eval $(minikube -p profile docker-env) and check if we are point to docker inside minikube
2020-05-24 21:55:38 +00:00
if runtime . GOOS == "windows" { // testing docker-env eval in powershell
2020-05-27 22:40:43 +00:00
c := exec . CommandContext ( mctx , "powershell.exe" , "-NoProfile" , "-NonInteractive" , Target ( ) , "-p " + profile + " docker-env | Invoke-Expression ; docker images" )
rr , err = Run ( t , c )
2020-05-24 11:46:35 +00:00
} else {
2020-05-24 21:55:38 +00:00
c := exec . CommandContext ( mctx , "/bin/bash" , "-c" , "eval $(" + Target ( ) + " -p " + profile + " docker-env) && docker images" )
2020-05-24 11:46:35 +00:00
rr , err = Run ( t , c )
}
2020-05-27 20:45:27 +00:00
if mctx . Err ( ) == context . DeadlineExceeded {
2020-05-27 04:53:07 +00:00
t . Errorf ( "failed to run the command in 30 seconds. exceeded 30s timeout. %s" , rr . Command ( ) )
2020-05-24 22:20:58 +00:00
}
2020-02-13 09:17:11 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Fatalf ( "failed to run minikube docker-env. args %q : %v " , rr . Command ( ) , err )
2020-02-13 09:17:11 +00:00
}
expectedImgInside := "gcr.io/k8s-minikube/storage-provisioner"
if ! strings . Contains ( rr . Output ( ) , expectedImgInside ) {
2020-04-02 04:40:09 +00:00
t . Fatalf ( "expected 'docker images' to have %q inside minikube. but the output is: *%s*" , expectedImgInside , rr . Output ( ) )
2020-02-13 09:17:11 +00:00
}
}
2020-04-07 04:26:45 +00:00
func validateStartWithProxy ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-09-11 16:59:38 +00:00
srv , err := startHTTPProxy ( t )
if err != nil {
2020-03-26 04:43:32 +00:00
t . Fatalf ( "failed to set up the test proxy: %s" , err )
2019-09-11 16:59:38 +00:00
}
2019-11-06 23:17:09 +00:00
// Use more memory so that we may reliably fit MySQL and nginx
2020-04-07 04:03:12 +00:00
// changing api server so later in soft start we verify it didn't change
2020-08-10 18:53:46 +00:00
startArgs := append ( [ ] string { "start" , "-p" , profile , "--memory=4000" , fmt . Sprintf ( "--apiserver-port=%d" , apiPortTest ) , "--wait=true" } , StartArgs ( ) ... )
2019-09-11 20:08:44 +00:00
c := exec . CommandContext ( ctx , Target ( ) , startArgs ... )
2019-09-11 16:59:38 +00:00
env := os . Environ ( )
env = append ( env , fmt . Sprintf ( "HTTP_PROXY=%s" , srv . Addr ) )
env = append ( env , "NO_PROXY=" )
c . Env = env
rr , err := Run ( t , c )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed minikube start. args %q: %v" , rr . Command ( ) , err )
2019-09-11 16:59:38 +00:00
}
want := "Found network options:"
if ! strings . Contains ( rr . Stdout . String ( ) , want ) {
t . Errorf ( "start stdout=%s, want: *%s*" , rr . Stdout . String ( ) , want )
}
want = "You appear to be using a proxy"
if ! strings . Contains ( rr . Stderr . String ( ) , want ) {
t . Errorf ( "start stderr=%s, want: *%s*" , rr . Stderr . String ( ) , want )
}
}
2020-04-07 04:03:12 +00:00
// validateSoftStart validates that after minikube already started, a "minikube start" should not change the configs.
2020-04-07 04:26:45 +00:00
func validateSoftStart ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-04-07 04:06:27 +00:00
start := time . Now ( )
2020-04-07 04:08:09 +00:00
// the test before this had been start with --apiserver-port=8441
2020-04-07 04:26:45 +00:00
beforeCfg , err := config . LoadProfile ( profile )
if err != nil {
2020-05-28 21:42:00 +00:00
t . Fatalf ( "error reading cluster config before soft start: %v" , err )
2020-04-07 04:26:45 +00:00
}
2020-04-07 20:14:30 +00:00
if beforeCfg . Config . KubernetesConfig . NodePort != apiPortTest {
t . Errorf ( "expected cluster config node port before soft start to be %d but got %d" , apiPortTest , beforeCfg . Config . KubernetesConfig . NodePort )
2020-04-07 04:03:12 +00:00
}
2020-08-10 21:48:44 +00:00
softStartArgs := [ ] string { "start" , "-p" , profile , "--alsologtostderr" , "-v=8" }
2020-04-07 04:03:12 +00:00
c := exec . CommandContext ( ctx , Target ( ) , softStartArgs ... )
2020-04-07 04:26:45 +00:00
rr , err := Run ( t , c )
2020-04-07 04:03:12 +00:00
if err != nil {
t . Errorf ( "failed to soft start minikube. args %q: %v" , rr . Command ( ) , err )
}
2020-04-07 04:06:27 +00:00
t . Logf ( "soft start took %s for %q cluster." , time . Since ( start ) , profile )
2020-04-07 04:03:12 +00:00
2020-04-07 04:26:45 +00:00
afterCfg , err := config . LoadProfile ( profile )
if err != nil {
t . Errorf ( "error reading cluster config after soft start: %v" , err )
}
2020-04-07 20:14:30 +00:00
if afterCfg . Config . KubernetesConfig . NodePort != apiPortTest {
t . Errorf ( "expected node port in the config not change after soft start. exepceted node port to be %d but got %d." , apiPortTest , afterCfg . Config . KubernetesConfig . NodePort )
2020-04-07 04:03:12 +00:00
}
2020-04-07 04:06:27 +00:00
2020-04-07 04:03:12 +00:00
}
2019-09-11 16:59:38 +00:00
// validateKubeContext asserts that kubectl is properly configured (race-condition prone!)
func validateKubeContext ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-09-11 16:59:38 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , "kubectl" , "config" , "current-context" ) )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to get current-context. args %q : %v" , rr . Command ( ) , err )
2019-09-11 16:59:38 +00:00
}
if ! strings . Contains ( rr . Stdout . String ( ) , profile ) {
2020-03-26 04:43:32 +00:00
t . Errorf ( "expected current-context = %q, but got *%q*" , profile , rr . Stdout . String ( ) )
2019-09-11 16:59:38 +00:00
}
}
2019-10-28 23:50:01 +00:00
// validateKubectlGetPods asserts that `kubectl get pod -A` returns non-zero content
func validateKubectlGetPods ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-11-13 05:38:31 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "get" , "po" , "-A" ) )
2019-10-28 23:50:01 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to get kubectl pods: args %q : %v" , rr . Command ( ) , err )
2019-10-28 23:50:01 +00:00
}
2019-11-13 05:38:31 +00:00
if rr . Stderr . String ( ) != "" {
2020-03-26 04:43:32 +00:00
t . Errorf ( "expected stderr to be empty but got *%q*: args %q" , rr . Stderr , rr . Command ( ) )
2019-11-13 05:38:31 +00:00
}
2019-11-12 22:19:52 +00:00
if ! strings . Contains ( rr . Stdout . String ( ) , "kube-system" ) {
2020-03-26 04:43:32 +00:00
t . Errorf ( "expected stdout to include *kube-system* but got *%q*. args: %q" , rr . Stdout , rr . Command ( ) )
2019-10-28 23:50:01 +00:00
}
}
2020-02-12 17:54:17 +00:00
// validateMinikubeKubectl validates that the `minikube kubectl` command returns content
func validateMinikubeKubectl ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-03-25 21:57:27 +00:00
// Must set the profile so that it knows what version of Kubernetes to use
kubectlArgs := [ ] string { "-p" , profile , "kubectl" , "--" , "--context" , profile , "get" , "pods" }
2020-02-13 21:34:05 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , kubectlArgs ... ) )
2020-02-12 17:54:17 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Fatalf ( "failed to get pods. args %q: %v" , rr . Command ( ) , err )
2020-02-12 17:54:17 +00:00
}
}
2020-08-17 02:52:21 +00:00
// validateMinikubeKubectlDirectCall validates that calling minikube's kubectl
func validateMinikubeKubectlDirectCall ( ctx context . Context , t * testing . T , profile string ) {
defer PostMortemLogs ( t , profile )
dir := filepath . Dir ( Target ( ) )
dstfn := filepath . Join ( dir , "kubectl" )
err := os . Link ( Target ( ) , dstfn )
if err != nil {
t . Fatal ( err )
}
defer os . Remove ( dstfn ) // clean up
2020-10-28 19:16:02 +00:00
kubectlArgs := [ ] string { "--context" , profile , "get" , "pods" }
2020-08-17 02:52:21 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , dstfn , kubectlArgs ... ) )
if err != nil {
2020-10-27 17:00:41 +00:00
t . Fatalf ( "failed to run kubectl directly. args %q: %v" , rr . Command ( ) , err )
2020-08-17 02:52:21 +00:00
}
}
2020-11-28 20:40:09 +00:00
func validateExtraConfig ( ctx context . Context , t * testing . T , profile string ) {
defer PostMortemLogs ( t , profile )
start := time . Now ( )
// The tests before this already created a profile, starting minikube with different --extra-config cmdline option.
startArgs := [ ] string { "start" , "-p" , profile , "--extra-config=apiserver.enable-admission-plugins=NamespaceAutoProvision" }
c := exec . CommandContext ( ctx , Target ( ) , startArgs ... )
rr , err := Run ( t , c )
if err != nil {
t . Errorf ( "failed to restart minikube. args %q: %v" , rr . Command ( ) , err )
}
t . Logf ( "restart took %s for %q cluster." , time . Since ( start ) , profile )
afterCfg , err := config . LoadProfile ( profile )
if err != nil {
t . Errorf ( "error reading cluster config after soft start: %v" , err )
}
expectedExtraOptions := "apiserver.enable-admission-plugins=NamespaceAutoProvision"
if ! strings . Contains ( afterCfg . Config . KubernetesConfig . ExtraOptions . String ( ) , expectedExtraOptions ) {
t . Errorf ( "expected ExtraOptions to contain %s but got %s" , expectedExtraOptions , afterCfg . Config . KubernetesConfig . ExtraOptions . String ( ) )
}
}
2021-01-13 21:58:55 +00:00
func imageID ( image string ) string {
ids := map [ string ] map [ string ] string {
"pause" : {
"amd64" : "0184c1613d929" ,
"arm64" : "3d18732f8686c" ,
} ,
}
if imgIds , ok := ids [ image ] ; ok {
if id , ok := imgIds [ runtime . GOARCH ] ; ok {
return id
}
panic ( fmt . Sprintf ( "unexpected architecture for image %q: %v" , image , runtime . GOARCH ) )
}
panic ( "unexpected image name: " + image )
}
2019-09-11 16:59:38 +00:00
// validateComponentHealth asserts that all Kubernetes components are healthy
func validateComponentHealth ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-08-21 23:07:39 +00:00
// The ComponentStatus API is deprecated in v1.19, so do the next closest thing.
found := map [ string ] bool {
"etcd" : false ,
"kube-apiserver" : false ,
"kube-controller-manager" : false ,
"kube-scheduler" : false ,
}
rr , err := Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "get" , "po" , "-l" , "tier=control-plane" , "-n" , "kube-system" , "-o=json" ) )
2019-09-11 16:59:38 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Fatalf ( "failed to get components. args %q: %v" , rr . Command ( ) , err )
2019-09-11 16:59:38 +00:00
}
2020-08-21 23:07:39 +00:00
cs := api . PodList { }
2019-09-11 16:59:38 +00:00
d := json . NewDecoder ( bytes . NewReader ( rr . Stdout . Bytes ( ) ) )
if err := d . Decode ( & cs ) ; err != nil {
2020-03-26 05:21:19 +00:00
t . Fatalf ( "failed to decode kubectl json output: args %q : %v" , rr . Command ( ) , err )
2019-09-11 16:59:38 +00:00
}
for _ , i := range cs . Items {
2020-08-21 23:07:39 +00:00
for _ , l := range i . Labels {
t . Logf ( "%s phase: %s" , l , i . Status . Phase )
_ , ok := found [ l ]
if ok {
found [ l ] = true
if i . Status . Phase != "Running" {
t . Errorf ( "%s is not Running: %+v" , l , i . Status )
}
2019-09-11 16:59:38 +00:00
}
}
2020-08-21 23:07:39 +00:00
}
for k , v := range found {
if ! v {
t . Errorf ( "expected component %q was not found" , k )
2019-09-11 16:59:38 +00:00
}
}
}
2019-10-13 15:24:40 +00:00
func validateStatusCmd ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-10-21 18:00:01 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "status" ) )
2019-10-13 15:24:40 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to run minikube status. args %q : %v" , rr . Command ( ) , err )
2019-10-13 15:24:40 +00:00
}
// Custom format
2019-10-21 18:00:01 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "status" , "-f" , "host:{{.Host}},kublet:{{.Kubelet}},apiserver:{{.APIServer}},kubeconfig:{{.Kubeconfig}}" ) )
2019-10-13 15:24:40 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to run minikube status with custom format: args %q: %v" , rr . Command ( ) , err )
2019-10-13 15:24:40 +00:00
}
2020-03-26 04:43:32 +00:00
re := ` host:([A-z]+),kublet:([A-z]+),apiserver:([A-z]+),kubeconfig:([A-z]+) `
match , _ := regexp . MatchString ( re , rr . Stdout . String ( ) )
2019-10-13 15:24:40 +00:00
if ! match {
2020-04-02 04:40:09 +00:00
t . Errorf ( "failed to match regex %q for minikube status with custom format. args %q. output: %s" , re , rr . Command ( ) , rr . Output ( ) )
2019-10-13 15:24:40 +00:00
}
// Json output
2019-10-21 18:00:01 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "status" , "-o" , "json" ) )
2019-10-13 15:24:40 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to run minikube status with json output. args %q : %v" , rr . Command ( ) , err )
2019-10-13 15:24:40 +00:00
}
var jsonObject map [ string ] interface { }
err = json . Unmarshal ( rr . Stdout . Bytes ( ) , & jsonObject )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to decode json from minikube status. args %q. %v" , rr . Command ( ) , err )
2019-10-13 15:24:40 +00:00
}
if _ , ok := jsonObject [ "Host" ] ; ! ok {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%q failed: %v. Missing key %s in json object" , rr . Command ( ) , err , "Host" )
2019-10-13 15:24:40 +00:00
}
if _ , ok := jsonObject [ "Kubelet" ] ; ! ok {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%q failed: %v. Missing key %s in json object" , rr . Command ( ) , err , "Kubelet" )
2019-10-13 15:24:40 +00:00
}
if _ , ok := jsonObject [ "APIServer" ] ; ! ok {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%q failed: %v. Missing key %s in json object" , rr . Command ( ) , err , "APIServer" )
2019-10-13 15:24:40 +00:00
}
if _ , ok := jsonObject [ "Kubeconfig" ] ; ! ok {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%q failed: %v. Missing key %s in json object" , rr . Command ( ) , err , "Kubeconfig" )
2019-10-13 15:24:40 +00:00
}
}
2019-09-11 16:59:38 +00:00
// validateDashboardCmd asserts that the dashboard command works
func validateDashboardCmd ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-09-11 16:59:38 +00:00
args := [ ] string { "dashboard" , "--url" , "-p" , profile , "--alsologtostderr" , "-v=1" }
ss , err := Start ( t , exec . CommandContext ( ctx , Target ( ) , args ... ) )
if err != nil {
2020-03-26 04:43:32 +00:00
t . Errorf ( "failed to run minikube dashboard. args %q : %v" , args , err )
2019-09-11 16:59:38 +00:00
}
defer func ( ) {
ss . Stop ( t )
} ( )
start := time . Now ( )
2020-02-21 00:19:59 +00:00
s , err := ReadLineWithTimeout ( ss . Stdout , Seconds ( 300 ) )
2019-09-11 16:59:38 +00:00
if err != nil {
2019-11-06 22:14:56 +00:00
if runtime . GOOS == "windows" {
t . Skipf ( "failed to read url within %s: %v\noutput: %q\n" , time . Since ( start ) , err , s )
}
t . Fatalf ( "failed to read url within %s: %v\noutput: %q\n" , time . Since ( start ) , err , s )
2019-09-11 16:59:38 +00:00
}
u , err := url . Parse ( strings . TrimSpace ( s ) )
if err != nil {
t . Fatalf ( "failed to parse %q: %v" , s , err )
}
resp , err := retryablehttp . Get ( u . String ( ) )
if err != nil {
2020-04-02 17:51:15 +00:00
t . Fatalf ( "failed to http get %q: %v\nresponse: %+v" , u . String ( ) , err , resp )
2019-09-11 16:59:38 +00:00
}
2020-04-02 17:51:15 +00:00
2019-09-11 16:59:38 +00:00
if resp . StatusCode != http . StatusOK {
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
2020-03-26 04:43:32 +00:00
t . Errorf ( "failed to read http response body from dashboard %q: %v" , u . String ( ) , err )
2019-09-11 16:59:38 +00:00
}
t . Errorf ( "%s returned status code %d, expected %d.\nbody:\n%s" , u , resp . StatusCode , http . StatusOK , body )
}
}
2019-07-30 04:52:05 +00:00
2020-01-09 19:10:23 +00:00
// validateDryRun asserts that the dry-run mode quickly exits with the right code
func validateDryRun ( ctx context . Context , t * testing . T , profile string ) {
2020-01-22 20:14:05 +00:00
// dry-run mode should always be able to finish quickly (<5s)
2020-02-21 00:19:59 +00:00
mctx , cancel := context . WithTimeout ( ctx , Seconds ( 5 ) )
2020-01-09 19:10:23 +00:00
defer cancel ( )
// Too little memory!
2020-12-01 00:06:06 +00:00
var startArgs [ ] string
orgStartArgs := StartArgs ( )
for i := 0 ; i < len ( orgStartArgs ) ; i ++ {
arg := orgStartArgs [ i ]
if strings . HasPrefix ( arg , "--memory=" ) {
continue
}
if arg == "--memory" {
i ++ // skip next
continue
}
startArgs = append ( startArgs , arg )
}
startArgs = append ( [ ] string { "start" , "-p" , profile , "--dry-run" , "--memory" , "250MB" , "--alsologtostderr" } , startArgs ... )
2020-01-09 19:10:23 +00:00
c := exec . CommandContext ( mctx , Target ( ) , startArgs ... )
rr , err := Run ( t , c )
2020-08-31 18:21:23 +00:00
wantCode := reason . ExInsufficientMemory
2020-01-09 19:10:23 +00:00
if rr . ExitCode != wantCode {
t . Errorf ( "dry-run(250MB) exit code = %d, wanted = %d: %v" , rr . ExitCode , wantCode , err )
}
2020-02-21 00:19:59 +00:00
dctx , cancel := context . WithTimeout ( ctx , Seconds ( 5 ) )
2020-01-09 19:10:23 +00:00
defer cancel ( )
2020-01-22 20:14:05 +00:00
startArgs = append ( [ ] string { "start" , "-p" , profile , "--dry-run" , "--alsologtostderr" , "-v=1" } , StartArgs ( ) ... )
2020-01-09 19:10:23 +00:00
c = exec . CommandContext ( dctx , Target ( ) , startArgs ... )
rr , err = Run ( t , c )
if rr . ExitCode != 0 || err != nil {
t . Errorf ( "dry-run exit code = %d, wanted = %d: %v" , rr . ExitCode , 0 , err )
}
}
2019-11-27 00:08:07 +00:00
// validateCacheCmd tests functionality of cache command (cache add, delete, list)
2019-09-11 16:59:38 +00:00
func validateCacheCmd ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-09-11 16:59:38 +00:00
if NoneDriver ( ) {
t . Skipf ( "skipping: cache unsupported by none" )
}
2020-09-02 14:25:43 +00:00
2019-11-27 00:19:29 +00:00
t . Run ( "cache" , func ( t * testing . T ) {
2020-09-10 19:58:14 +00:00
t . Run ( "add_remote" , func ( t * testing . T ) {
2020-09-17 20:57:06 +00:00
for _ , img := range [ ] string { "k8s.gcr.io/pause:3.1" , "k8s.gcr.io/pause:3.3" , "k8s.gcr.io/pause:latest" } {
2020-03-26 04:43:32 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "cache" , "add" , img ) )
2019-11-27 00:19:29 +00:00
if err != nil {
2020-09-10 19:58:14 +00:00
t . Errorf ( "failed to 'cache add' remote image %q. args %q err %v" , img , rr . Command ( ) , err )
2019-11-27 00:19:29 +00:00
}
}
} )
2020-09-02 14:25:43 +00:00
t . Run ( "add_local" , func ( t * testing . T ) {
2020-10-08 21:24:02 +00:00
if GithubActionRunner ( ) && runtime . GOOS == "darwin" {
t . Skipf ( "skipping this test because Docker can not run in macos on github action free version. https://github.community/t/is-it-possible-to-install-and-configure-docker-on-macos-runner/16981" )
2020-12-09 19:06:17 +00:00
}
2020-10-08 21:24:02 +00:00
2020-12-09 19:06:17 +00:00
_ , err := exec . LookPath ( oci . Docker )
if err != nil {
t . Skipf ( "docker is not installed, skipping local image test" )
2020-10-08 21:24:02 +00:00
}
2020-09-02 14:25:43 +00:00
dname , err := ioutil . TempDir ( "" , profile )
if err != nil {
t . Fatalf ( "Cannot create temp dir: %v" , err )
}
message := [ ] byte ( "FROM scratch\nADD Dockerfile /x" )
err = ioutil . WriteFile ( filepath . Join ( dname , "Dockerfile" ) , message , 0644 )
if err != nil {
2020-09-10 19:58:14 +00:00
t . Fatalf ( "unable to write Dockerfile: %v" , err )
2020-09-02 14:25:43 +00:00
}
img := "minikube-local-cache-test:" + profile
2020-09-02 15:21:35 +00:00
_ , err = Run ( t , exec . CommandContext ( ctx , "docker" , "build" , "-t" , img , dname ) )
2020-09-02 14:25:43 +00:00
if err != nil {
2020-12-09 19:06:17 +00:00
t . Skipf ( "failed to build docker image, skipping local test: %v" , err )
2020-09-02 14:25:43 +00:00
}
2020-09-02 15:21:35 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "cache" , "add" , img ) )
2020-09-02 14:25:43 +00:00
if err != nil {
2020-09-10 19:58:14 +00:00
t . Errorf ( "failed to 'cache add' local image %q. args %q err %v" , img , rr . Command ( ) , err )
2020-09-02 14:25:43 +00:00
}
} )
2020-09-10 19:58:14 +00:00
t . Run ( "delete_k8s.gcr.io/pause:3.3" , func ( t * testing . T ) {
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "cache" , "delete" , "k8s.gcr.io/pause:3.3" ) )
2019-11-27 00:19:29 +00:00
if err != nil {
2020-09-10 19:58:14 +00:00
t . Errorf ( "failed to delete image k8s.gcr.io/pause:3.3 from cache. args %q: %v" , rr . Command ( ) , err )
2019-11-27 00:19:29 +00:00
}
} )
2019-11-27 00:08:07 +00:00
2019-11-27 00:19:29 +00:00
t . Run ( "list" , func ( t * testing . T ) {
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "cache" , "list" ) )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to do cache list. args %q: %v" , rr . Command ( ) , err )
2019-11-27 00:19:29 +00:00
}
if ! strings . Contains ( rr . Output ( ) , "k8s.gcr.io/pause" ) {
2020-09-10 19:58:14 +00:00
t . Errorf ( "expected 'cache list' output to include 'k8s.gcr.io/pause' but got: ***%s***" , rr . Output ( ) )
2019-11-27 00:19:29 +00:00
}
2020-09-10 19:58:14 +00:00
if strings . Contains ( rr . Output ( ) , "k8s.gcr.io/pause:3.3" ) {
t . Errorf ( "expected 'cache list' output not to include k8s.gcr.io/pause:3.3 but got: ***%s***" , rr . Output ( ) )
2019-11-27 00:19:29 +00:00
}
} )
2019-11-27 00:08:07 +00:00
2020-02-13 02:11:44 +00:00
t . Run ( "verify_cache_inside_node" , func ( t * testing . T ) {
2019-12-10 20:15:20 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "ssh" , "sudo" , "crictl" , "images" ) )
2019-11-27 00:19:29 +00:00
if err != nil {
2019-12-11 05:01:12 +00:00
t . Errorf ( "failed to get images by %q ssh %v" , rr . Command ( ) , err )
2019-11-27 00:19:29 +00:00
}
2021-01-13 21:58:55 +00:00
pauseID := imageID ( "pause" )
2020-12-01 00:06:06 +00:00
if ! strings . Contains ( rr . Output ( ) , pauseID ) {
2021-01-13 21:58:55 +00:00
t . Errorf ( "expected sha for pause:3.3 %q to be in the output but got *%s*" , pauseID , rr . Output ( ) )
2019-11-27 00:19:29 +00:00
}
} )
2019-12-11 05:01:12 +00:00
2020-02-13 02:11:44 +00:00
t . Run ( "cache_reload" , func ( t * testing . T ) { // deleting image inside minikube node manually and expecting reload to bring it back
2020-09-10 19:58:14 +00:00
img := "k8s.gcr.io/pause:latest"
2019-12-11 05:01:12 +00:00
// deleting image inside minikube node manually
2020-05-27 19:25:10 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "ssh" , "sudo" , "docker" , "rmi" , img ) )
2020-05-26 02:58:28 +00:00
2019-12-11 05:01:12 +00:00
if err != nil {
2020-09-16 22:01:15 +00:00
t . Errorf ( "failed to manually delete image %q : %v" , rr . Command ( ) , err )
2019-12-11 05:01:12 +00:00
}
// make sure the image is deleted.
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "ssh" , "sudo" , "crictl" , "inspecti" , img ) )
if err == nil {
2020-09-10 19:58:14 +00:00
t . Errorf ( "expected an error but got no error. image should not exist. ! cmd: %q" , rr . Command ( ) )
2019-12-11 05:01:12 +00:00
}
2019-12-11 05:06:17 +00:00
// minikube cache reload.
2019-12-11 05:01:12 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "cache" , "reload" ) )
if err != nil {
2020-03-26 02:58:38 +00:00
t . Errorf ( "expected %q to run successfully but got error: %v" , rr . Command ( ) , err )
2019-12-11 05:01:12 +00:00
}
2019-12-11 05:06:17 +00:00
// make sure 'cache reload' brought back the manually deleted image.
2019-12-11 05:01:12 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "ssh" , "sudo" , "crictl" , "inspecti" , img ) )
if err != nil {
2020-03-26 02:58:38 +00:00
t . Errorf ( "expected %q to run successfully but got error: %v" , rr . Command ( ) , err )
2019-12-11 05:01:12 +00:00
}
} )
2020-06-22 20:29:41 +00:00
// delete will clean up the cached images since they are global and all other tests will load it for no reason
t . Run ( "delete" , func ( t * testing . T ) {
2020-09-17 21:12:48 +00:00
for _ , img := range [ ] string { "k8s.gcr.io/pause:3.1" , "k8s.gcr.io/pause:latest" } {
2020-06-22 20:29:41 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "cache" , "delete" , img ) )
if err != nil {
t . Errorf ( "failed to delete %s from cache. args %q: %v" , img , rr . Command ( ) , err )
}
}
} )
2019-11-27 00:19:29 +00:00
} )
2019-09-11 16:59:38 +00:00
}
// validateConfigCmd asserts basic "config" command functionality
func validateConfigCmd ( ctx context . Context , t * testing . T , profile string ) {
tests := [ ] struct {
args [ ] string
wantOut string
wantErr string
} {
{ [ ] string { "unset" , "cpus" } , "" , "" } ,
{ [ ] string { "get" , "cpus" } , "" , "Error: specified key could not be found in config" } ,
2020-04-02 19:27:19 +00:00
{ [ ] string { "set" , "cpus" , "2" } , "" , "! These changes will take effect upon a minikube delete and then a minikube start" } ,
2019-09-11 16:59:38 +00:00
{ [ ] string { "get" , "cpus" } , "2" , "" } ,
{ [ ] string { "unset" , "cpus" } , "" , "" } ,
{ [ ] string { "get" , "cpus" } , "" , "Error: specified key could not be found in config" } ,
}
for _ , tc := range tests {
args := append ( [ ] string { "-p" , profile , "config" } , tc . args ... )
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , args ... ) )
if err != nil && tc . wantErr == "" {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to config minikube. args %q : %v" , rr . Command ( ) , err )
2019-09-11 16:59:38 +00:00
}
got := strings . TrimSpace ( rr . Stdout . String ( ) )
if got != tc . wantOut {
2020-03-26 04:43:32 +00:00
t . Errorf ( "expected config output for %q to be -%q- but got *%q*" , rr . Command ( ) , tc . wantOut , got )
2019-09-11 16:59:38 +00:00
}
got = strings . TrimSpace ( rr . Stderr . String ( ) )
if got != tc . wantErr {
2020-03-26 04:43:32 +00:00
t . Errorf ( "expected config error for %q to be -%q- but got *%q*" , rr . Command ( ) , tc . wantErr , got )
2019-09-11 16:59:38 +00:00
}
}
}
// validateLogsCmd asserts basic "logs" command functionality
func validateLogsCmd ( ctx context . Context , t * testing . T , profile string ) {
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "logs" ) )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%s failed: %v" , rr . Command ( ) , err )
2019-09-11 16:59:38 +00:00
}
for _ , word := range [ ] string { "Docker" , "apiserver" , "Linux" , "kubelet" } {
if ! strings . Contains ( rr . Stdout . String ( ) , word ) {
2020-04-02 04:40:09 +00:00
t . Errorf ( "excpeted minikube logs to include word: -%q- but got \n***%s***\n" , word , rr . Output ( ) )
2019-09-11 16:59:38 +00:00
}
}
}
2019-10-11 17:16:26 +00:00
// validateProfileCmd asserts "profile" command functionality
2019-09-11 16:59:38 +00:00
func validateProfileCmd ( ctx context . Context , t * testing . T , profile string ) {
2020-02-20 06:30:47 +00:00
t . Run ( "profile_not_create" , func ( t * testing . T ) {
// Profile command should not create a nonexistent profile
nonexistentProfile := "lis"
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "profile" , nonexistentProfile ) )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%s failed: %v" , rr . Command ( ) , err )
2020-02-20 06:30:47 +00:00
}
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "profile" , "list" , "--output" , "json" ) )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%s failed: %v" , rr . Command ( ) , err )
2020-02-20 06:30:47 +00:00
}
var profileJSON map [ string ] [ ] map [ string ] interface { }
err = json . Unmarshal ( rr . Stdout . Bytes ( ) , & profileJSON )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%s failed: %v" , rr . Command ( ) , err )
2020-02-20 06:30:47 +00:00
}
for profileK := range profileJSON {
for _ , p := range profileJSON [ profileK ] {
var name = p [ "Name" ]
if name == nonexistentProfile {
t . Errorf ( "minikube profile %s should not exist" , nonexistentProfile )
}
2020-02-20 03:56:32 +00:00
}
2020-02-18 12:10:27 +00:00
}
2020-02-20 06:30:47 +00:00
} )
2020-02-18 12:10:27 +00:00
2020-02-20 06:30:47 +00:00
t . Run ( "profile_list" , func ( t * testing . T ) {
// List profiles
2020-02-20 06:41:23 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "profile" , "list" ) )
2020-02-20 06:30:47 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to list profiles: args %q : %v" , rr . Command ( ) , err )
2020-02-20 06:30:47 +00:00
}
2019-10-11 17:16:26 +00:00
2020-02-20 06:30:47 +00:00
// Table output
listLines := strings . Split ( strings . TrimSpace ( rr . Stdout . String ( ) ) , "\n" )
profileExists := false
for i := 3 ; i < ( len ( listLines ) - 1 ) ; i ++ {
profileLine := listLines [ i ]
if strings . Contains ( profileLine , profile ) {
profileExists = true
break
}
}
if ! profileExists {
2020-03-26 05:21:19 +00:00
t . Errorf ( "expected 'profile list' output to include %q but got *%q*. args: %q" , profile , rr . Stdout . String ( ) , rr . Command ( ) )
2019-10-11 17:16:26 +00:00
}
2020-02-20 06:30:47 +00:00
} )
t . Run ( "profile_json_output" , func ( t * testing . T ) {
// Json output
2020-02-20 06:41:23 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "profile" , "list" , "--output" , "json" ) )
2020-02-20 06:30:47 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to list profiles with json format. args %q: %v" , rr . Command ( ) , err )
2019-10-11 17:16:26 +00:00
}
2020-02-20 06:30:47 +00:00
var jsonObject map [ string ] [ ] map [ string ] interface { }
err = json . Unmarshal ( rr . Stdout . Bytes ( ) , & jsonObject )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to decode json from profile list: args %q: %v" , rr . Command ( ) , err )
2020-02-20 06:30:47 +00:00
}
validProfiles := jsonObject [ "valid" ]
2020-02-20 06:41:23 +00:00
profileExists := false
2020-02-20 06:30:47 +00:00
for _ , profileObject := range validProfiles {
if profileObject [ "Name" ] == profile {
profileExists = true
break
}
}
if ! profileExists {
2020-03-26 05:21:19 +00:00
t . Errorf ( "expected the json of 'profile list' to include %q but got *%q*. args: %q" , profile , rr . Stdout . String ( ) , rr . Command ( ) )
2020-02-20 06:30:47 +00:00
}
} )
2019-09-11 16:59:38 +00:00
}
// validateServiceCmd asserts basic "service" command functionality
2019-10-30 17:44:54 +00:00
func validateServiceCmd ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-05-07 23:44:42 +00:00
defer func ( ) {
if t . Failed ( ) {
t . Logf ( "service test failed - dumping debug information" )
2020-11-19 19:53:04 +00:00
t . Logf ( "-----------------------service failure post-mortem--------------------------------" )
ctx , cancel := context . WithTimeout ( context . Background ( ) , Minutes ( 2 ) )
defer cancel ( )
2020-05-07 23:44:42 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "describe" , "po" , "hello-node" ) )
if err != nil {
t . Logf ( "%q failed: %v" , rr . Command ( ) , err )
}
t . Logf ( "hello-node pod describe:\n%s" , rr . Stdout )
rr , err = Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "logs" , "-l" , "app=hello-node" ) )
if err != nil {
t . Logf ( "%q failed: %v" , rr . Command ( ) , err )
}
t . Logf ( "hello-node logs:\n%s" , rr . Stdout )
rr , err = Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "describe" , "svc" , "hello-node" ) )
if err != nil {
t . Logf ( "%q failed: %v" , rr . Command ( ) , err )
}
t . Logf ( "hello-node svc describe:\n%s" , rr . Stdout )
}
} ( )
2020-12-01 00:06:06 +00:00
var echoServerArg string
if Arm64Platform ( ) {
echoServerArg = "k8s.gcr.io/echoserver-arm:1.8"
} else {
echoServerArg = "k8s.gcr.io/echoserver:1.10"
}
rr , err := Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "create" , "deployment" , "hello-node" , "--image=" + echoServerArg ) )
2019-10-30 17:44:54 +00:00
if err != nil {
2020-11-20 22:46:22 +00:00
t . Fatalf ( "failed to create hello-node deployment with this command %q: %v." , rr . Command ( ) , err )
2019-10-30 17:44:54 +00:00
}
2019-10-30 20:57:08 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "expose" , "deployment" , "hello-node" , "--type=NodePort" , "--port=8080" ) )
2019-10-30 17:44:54 +00:00
if err != nil {
2020-11-20 22:46:22 +00:00
t . Fatalf ( "failed to expose hello-node deployment: %q : %v" , rr . Command ( ) , err )
2019-10-30 17:44:54 +00:00
}
2020-02-21 00:40:18 +00:00
if _ , err := PodWait ( ctx , t , profile , "default" , "app=hello-node" , Minutes ( 10 ) ) ; err != nil {
2020-03-26 04:43:32 +00:00
t . Fatalf ( "failed waiting for hello-node pod: %v" , err )
2019-10-30 20:57:08 +00:00
}
2019-10-30 17:44:54 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "service" , "list" ) )
2019-09-11 16:59:38 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to do service list. args %q : %v" , rr . Command ( ) , err )
2019-09-11 16:59:38 +00:00
}
2019-10-30 20:57:08 +00:00
if ! strings . Contains ( rr . Stdout . String ( ) , "hello-node" ) {
2020-03-26 04:43:32 +00:00
t . Errorf ( "expected 'service list' to contain *hello-node* but got -%q-" , rr . Stdout . String ( ) )
2019-10-30 17:44:54 +00:00
}
2020-04-02 17:51:15 +00:00
if NeedsPortForward ( ) {
t . Skipf ( "test is broken for port-forwarded drivers: https://github.com/kubernetes/minikube/issues/7383" )
}
2020-05-09 00:19:32 +00:00
// Test --https --url mode
2019-10-30 20:57:08 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "service" , "--namespace=default" , "--https" , "--url" , "hello-node" ) )
2019-10-30 17:44:54 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Fatalf ( "failed to get service url. args %q : %v" , rr . Command ( ) , err )
2019-10-30 20:57:08 +00:00
}
if rr . Stderr . String ( ) != "" {
2020-04-18 21:37:58 +00:00
t . Errorf ( "expected stderr to be empty but got *%q* . args %q" , rr . Stderr , rr . Command ( ) )
2019-10-30 17:44:54 +00:00
}
2020-05-08 20:12:30 +00:00
2020-05-09 00:19:32 +00:00
endpoint := strings . TrimSpace ( rr . Stdout . String ( ) )
2020-05-08 20:12:30 +00:00
t . Logf ( "found endpoint: %s" , endpoint )
2020-05-09 00:19:32 +00:00
2019-10-30 17:44:54 +00:00
u , err := url . Parse ( endpoint )
if err != nil {
2020-03-26 04:43:32 +00:00
t . Fatalf ( "failed to parse service url endpoint %q: %v" , endpoint , err )
2019-10-30 17:44:54 +00:00
}
if u . Scheme != "https" {
2020-05-08 20:12:30 +00:00
t . Errorf ( "expected scheme for %s to be 'https' but got %q" , endpoint , u . Scheme )
2019-10-30 17:44:54 +00:00
}
// Test --format=IP
2019-10-30 20:57:08 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "service" , "hello-node" , "--url" , "--format={{.IP}}" ) )
2019-10-30 17:44:54 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to get service url with custom format. args %q: %v" , rr . Command ( ) , err )
2019-10-30 17:44:54 +00:00
}
2019-10-30 20:57:08 +00:00
if strings . TrimSpace ( rr . Stdout . String ( ) ) != u . Hostname ( ) {
2020-03-26 05:21:19 +00:00
t . Errorf ( "expected 'service --format={{.IP}}' output to be -%q- but got *%q* . args %q." , u . Hostname ( ) , rr . Stdout . String ( ) , rr . Command ( ) )
2019-10-30 17:44:54 +00:00
}
2020-05-08 20:12:30 +00:00
// Test a regular URL
2019-10-30 20:57:08 +00:00
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "service" , "hello-node" , "--url" ) )
2019-10-30 17:44:54 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to get service url. args: %q: %v" , rr . Command ( ) , err )
2019-10-30 17:44:54 +00:00
}
2019-10-30 20:57:08 +00:00
endpoint = strings . TrimSpace ( rr . Stdout . String ( ) )
2020-05-07 23:44:42 +00:00
t . Logf ( "found endpoint for hello-node: %s" , endpoint )
2019-10-30 20:57:08 +00:00
u , err = url . Parse ( endpoint )
if err != nil {
t . Fatalf ( "failed to parse %q: %v" , endpoint , err )
}
2020-05-07 23:44:42 +00:00
2019-10-30 20:57:08 +00:00
if u . Scheme != "http" {
2020-03-26 05:15:24 +00:00
t . Fatalf ( "expected scheme to be -%q- got scheme: *%q*" , "http" , u . Scheme )
2019-10-30 20:57:08 +00:00
}
2020-05-07 23:44:42 +00:00
t . Logf ( "Attempting to fetch %s ..." , endpoint )
fetch := func ( ) error {
resp , err := http . Get ( endpoint )
if err != nil {
t . Logf ( "error fetching %s: %v" , endpoint , err )
return err
}
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Logf ( "error reading body from %s: %v" , endpoint , err )
return err
}
if resp . StatusCode != http . StatusOK {
t . Logf ( "%s: unexpected status code %d - body:\n%s" , endpoint , resp . StatusCode , body )
} else {
t . Logf ( "%s: success! body:\n%s" , endpoint , body )
}
return nil
2019-10-30 17:44:54 +00:00
}
2020-05-07 23:44:42 +00:00
if err = retry . Expo ( fetch , 1 * time . Second , Seconds ( 30 ) ) ; err != nil {
t . Errorf ( "failed to fetch %s: %v" , endpoint , err )
2019-09-11 16:59:38 +00:00
}
}
2019-10-11 14:43:00 +00:00
// validateAddonsCmd asserts basic "addon" command functionality
func validateAddonsCmd ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-01-11 00:39:17 +00:00
// Table output
2019-10-11 14:43:00 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "addons" , "list" ) )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to do addon list: args %q : %v" , rr . Command ( ) , err )
2019-10-11 14:43:00 +00:00
}
2020-01-11 00:39:17 +00:00
for _ , a := range [ ] string { "dashboard" , "ingress" , "ingress-dns" } {
if ! strings . Contains ( rr . Output ( ) , a ) {
2020-04-02 04:40:09 +00:00
t . Errorf ( "expected 'addon list' output to include -%q- but got *%s*" , a , rr . Output ( ) )
2019-10-11 14:43:00 +00:00
}
}
2019-10-11 18:34:50 +00:00
// Json output
rr , err = Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "addons" , "list" , "-o" , "json" ) )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to do addon list with json output. args %q: %v" , rr . Command ( ) , err )
2019-10-11 18:34:50 +00:00
}
var jsonObject map [ string ] interface { }
err = json . Unmarshal ( rr . Stdout . Bytes ( ) , & jsonObject )
if err != nil {
2020-03-26 04:43:32 +00:00
t . Errorf ( "failed to decode addon list json output : %v" , err )
2019-10-11 18:34:50 +00:00
}
2019-10-11 14:43:00 +00:00
}
2019-09-11 16:59:38 +00:00
// validateSSHCmd asserts basic "ssh" command functionality
func validateSSHCmd ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-09-11 16:59:38 +00:00
if NoneDriver ( ) {
t . Skipf ( "skipping: ssh unsupported by none" )
}
2020-05-27 20:56:16 +00:00
mctx , cancel := context . WithTimeout ( ctx , Minutes ( 1 ) )
defer cancel ( )
2020-05-27 06:52:55 +00:00
2020-05-27 22:54:07 +00:00
want := "hello"
2020-05-27 06:52:55 +00:00
2020-05-27 20:56:16 +00:00
rr , err := Run ( t , exec . CommandContext ( mctx , Target ( ) , "-p" , profile , "ssh" , "echo hello" ) )
if mctx . Err ( ) == context . DeadlineExceeded {
2020-05-27 04:53:07 +00:00
t . Errorf ( "failed to run command by deadline. exceeded timeout : %s" , rr . Command ( ) )
}
if err != nil {
t . Errorf ( "failed to run an ssh command. args %q : %v" , rr . Command ( ) , err )
}
2020-05-27 23:55:55 +00:00
// trailing whitespace differs between native and external SSH clients, so let's trim it and call it a day
2020-05-27 23:56:54 +00:00
if strings . TrimSpace ( rr . Stdout . String ( ) ) != want {
2020-05-27 04:53:07 +00:00
t . Errorf ( "expected minikube ssh command output to be -%q- but got *%q*. args %q" , want , rr . Stdout . String ( ) , rr . Command ( ) )
}
2020-05-27 20:45:27 +00:00
// testing hostname as well because testing something like "minikube ssh echo" could be confusing
// because it is not clear if echo was run inside minikube on the powershell
2020-05-27 20:56:16 +00:00
// so better to test something inside minikube, that is meaningful per profile
2020-05-27 20:45:27 +00:00
// in this case /etc/hostname is same as the profile name
2020-05-27 23:55:55 +00:00
want = profile
2020-05-27 20:56:16 +00:00
rr , err = Run ( t , exec . CommandContext ( mctx , Target ( ) , "-p" , profile , "ssh" , "cat /etc/hostname" ) )
2020-05-27 20:45:27 +00:00
if mctx . Err ( ) == context . DeadlineExceeded {
2020-05-27 04:53:07 +00:00
t . Errorf ( "failed to run command by deadline. exceeded timeout : %s" , rr . Command ( ) )
2020-05-25 22:55:54 +00:00
}
2019-09-11 16:59:38 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to run an ssh command. args %q : %v" , rr . Command ( ) , err )
2019-09-11 16:59:38 +00:00
}
2020-05-27 23:54:03 +00:00
// trailing whitespace differs between native and external SSH clients, so let's trim it and call it a day
2020-05-27 22:54:07 +00:00
if strings . TrimSpace ( rr . Stdout . String ( ) ) != want {
2020-03-26 05:21:19 +00:00
t . Errorf ( "expected minikube ssh command output to be -%q- but got *%q*. args %q" , want , rr . Stdout . String ( ) , rr . Command ( ) )
2019-09-11 16:59:38 +00:00
}
}
2019-10-29 05:31:57 +00:00
// validateMySQL validates a minimalist MySQL deployment
func validateMySQL ( ctx context . Context , t * testing . T , profile string ) {
2020-12-01 00:06:06 +00:00
if Arm64Platform ( ) {
t . Skip ( "arm64 is not supported by mysql. skip the test" )
return
}
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-10-29 05:31:57 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "replace" , "--force" , "-f" , filepath . Join ( * testdataDir , "mysql.yaml" ) ) )
if err != nil {
2020-03-26 05:21:19 +00:00
t . Fatalf ( "failed to kubectl replace mysql: args %q failed: %v" , rr . Command ( ) , err )
2019-10-29 05:31:57 +00:00
}
2020-02-21 00:40:18 +00:00
names , err := PodWait ( ctx , t , profile , "default" , "app=mysql" , Minutes ( 10 ) )
2019-11-06 23:17:09 +00:00
if err != nil {
2020-03-26 04:43:32 +00:00
t . Fatalf ( "failed waiting for mysql pod: %v" , err )
2019-11-06 23:17:09 +00:00
}
2019-10-29 20:13:33 +00:00
// Retry, as mysqld first comes up without users configured. Scan for names in case of a reschedule.
mysql := func ( ) error {
rr , err = Run ( t , exec . CommandContext ( ctx , "kubectl" , "--context" , profile , "exec" , names [ 0 ] , "--" , "mysql" , "-ppassword" , "-e" , "show databases;" ) )
return err
2019-10-29 05:31:57 +00:00
}
2020-04-03 07:08:32 +00:00
if err = retry . Expo ( mysql , 1 * time . Second , Minutes ( 5 ) ) ; err != nil {
2020-03-26 04:43:32 +00:00
t . Errorf ( "failed to exec 'mysql -ppassword -e show databases;': %v" , err )
2019-10-29 05:31:57 +00:00
}
}
2020-02-12 22:26:38 +00:00
// vmSyncTestPath is where the test file will be synced into the VM
func vmSyncTestPath ( ) string {
return fmt . Sprintf ( "/etc/test/nested/copy/%d/hosts" , os . Getpid ( ) )
}
// localSyncTestPath is where the test file will be synced into the VM
func localSyncTestPath ( ) string {
return filepath . Join ( localpath . MiniPath ( ) , "/files" , vmSyncTestPath ( ) )
}
2020-03-04 22:48:40 +00:00
// testCert is name of the test certificate installed
func testCert ( ) string {
return fmt . Sprintf ( "%d.pem" , os . Getpid ( ) )
}
// localTestCertPath is where the test file will be synced into the VM
func localTestCertPath ( ) string {
return filepath . Join ( localpath . MiniPath ( ) , "/certs" , testCert ( ) )
}
2020-04-08 22:04:12 +00:00
// localEmptyCertPath is where the test file will be synced into the VM
func localEmptyCertPath ( ) string {
return filepath . Join ( localpath . MiniPath ( ) , "/certs" , fmt . Sprintf ( "%d_empty.pem" , os . Getpid ( ) ) )
}
2019-11-07 01:20:52 +00:00
// Copy extra file into minikube home folder for file sync test
func setupFileSync ( ctx context . Context , t * testing . T , profile string ) {
2020-02-12 22:26:38 +00:00
p := localSyncTestPath ( )
t . Logf ( "local sync path: %s" , p )
2020-08-04 18:57:10 +00:00
syncFile := filepath . Join ( * testdataDir , "sync.test" )
err := copy . Copy ( syncFile , p )
2019-11-07 01:20:52 +00:00
if err != nil {
2020-08-04 18:57:10 +00:00
t . Fatalf ( "failed to copy testdata/sync.test: %v" , err )
2019-11-07 01:20:52 +00:00
}
2020-03-04 22:48:40 +00:00
2020-08-04 18:57:10 +00:00
testPem := filepath . Join ( * testdataDir , "minikube_test.pem" )
2020-04-08 22:04:12 +00:00
2020-04-10 15:32:41 +00:00
// Write to a temp file for an atomic write
tmpPem := localTestCertPath ( ) + ".pem"
if err := copy . Copy ( testPem , tmpPem ) ; err != nil {
2020-04-08 22:04:12 +00:00
t . Fatalf ( "failed to copy %s: %v" , testPem , err )
}
2020-04-10 15:32:41 +00:00
if err := os . Rename ( tmpPem , localTestCertPath ( ) ) ; err != nil {
t . Fatalf ( "failed to rename %s: %v" , tmpPem , err )
}
2020-04-08 22:04:12 +00:00
want , err := os . Stat ( testPem )
if err != nil {
t . Fatalf ( "stat failed: %v" , err )
}
got , err := os . Stat ( localTestCertPath ( ) )
if err != nil {
t . Fatalf ( "stat failed: %v" , err )
}
if want . Size ( ) != got . Size ( ) {
t . Errorf ( "%s size=%d, want %d" , localTestCertPath ( ) , got . Size ( ) , want . Size ( ) )
}
// Create an empty file just to mess with people
if _ , err := os . Create ( localEmptyCertPath ( ) ) ; err != nil {
t . Fatalf ( "create failed: %v" , err )
2020-03-04 22:48:40 +00:00
}
2019-11-07 01:20:52 +00:00
}
// validateFileSync to check existence of the test file
func validateFileSync ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2019-11-07 01:20:52 +00:00
if NoneDriver ( ) {
t . Skipf ( "skipping: ssh unsupported by none" )
}
2020-02-12 22:26:38 +00:00
vp := vmSyncTestPath ( )
t . Logf ( "Checking for existence of %s within VM" , vp )
2020-04-02 17:37:23 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "ssh" , fmt . Sprintf ( "sudo cat %s" , vp ) ) )
2019-11-07 01:20:52 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "%s failed: %v" , rr . Command ( ) , err )
2019-11-07 01:20:52 +00:00
}
2020-02-12 22:26:38 +00:00
got := rr . Stdout . String ( )
t . Logf ( "file sync test content: %s" , got )
2019-11-07 01:20:52 +00:00
2020-08-04 18:57:10 +00:00
syncFile := filepath . Join ( * testdataDir , "sync.test" )
expected , err := ioutil . ReadFile ( syncFile )
2019-11-07 01:20:52 +00:00
if err != nil {
2020-08-04 18:57:10 +00:00
t . Errorf ( "failed to read test file 'testdata/sync.test' : %v" , err )
2019-11-07 01:20:52 +00:00
}
2020-02-12 22:26:38 +00:00
if diff := cmp . Diff ( string ( expected ) , got ) ; diff != "" {
2019-11-07 01:20:52 +00:00
t . Errorf ( "/etc/sync.test content mismatch (-want +got):\n%s" , diff )
}
}
2020-03-04 22:48:40 +00:00
// validateCertSync to check existence of the test certificate
func validateCertSync ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-03-04 22:48:40 +00:00
if NoneDriver ( ) {
t . Skipf ( "skipping: ssh unsupported by none" )
}
2020-08-04 18:57:10 +00:00
testPem := filepath . Join ( * testdataDir , "minikube_test.pem" )
want , err := ioutil . ReadFile ( testPem )
2020-03-04 22:48:40 +00:00
if err != nil {
t . Errorf ( "test file not found: %v" , err )
}
// Check both the installed & reference certs (they should be symlinked)
paths := [ ] string {
path . Join ( "/etc/ssl/certs" , testCert ( ) ) ,
path . Join ( "/usr/share/ca-certificates" , testCert ( ) ) ,
// hashed path generated by: 'openssl x509 -hash -noout -in testCert()'
"/etc/ssl/certs/51391683.0" ,
}
for _ , vp := range paths {
t . Logf ( "Checking for existence of %s within VM" , vp )
2020-04-02 17:37:23 +00:00
rr , err := Run ( t , exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "ssh" , fmt . Sprintf ( "sudo cat %s" , vp ) ) )
2020-03-04 22:48:40 +00:00
if err != nil {
2020-03-26 05:21:19 +00:00
t . Errorf ( "failed to check existence of %q inside minikube. args %q: %v" , vp , rr . Command ( ) , err )
2020-03-04 22:48:40 +00:00
}
// Strip carriage returned by ssh
got := strings . Replace ( rr . Stdout . String ( ) , "\r" , "" , - 1 )
if diff := cmp . Diff ( string ( want ) , got ) ; diff != "" {
2020-03-26 04:43:32 +00:00
t . Errorf ( "failed verify pem file. minikube_test.pem -> %s mismatch (-want +got):\n%s" , vp , diff )
2020-03-04 22:48:40 +00:00
}
}
}
2019-12-16 15:58:45 +00:00
// validateUpdateContextCmd asserts basic "update-context" command functionality
func validateUpdateContextCmd ( ctx context . Context , t * testing . T , profile string ) {
2020-05-08 20:12:30 +00:00
defer PostMortemLogs ( t , profile )
2020-08-16 05:03:41 +00:00
tests := [ ] struct {
name string
kubeconfig [ ] byte
want [ ] byte
} {
{
name : "no changes" ,
kubeconfig : nil ,
want : [ ] byte ( "No changes" ) ,
} ,
{
name : "no minikube cluster" ,
kubeconfig : [ ] byte ( `
apiVersion : v1
clusters :
- cluster :
certificate - authority : / home / la - croix / apiserver . crt
server : 192.168 .1 .1 : 8080
name : la - croix
contexts :
- context :
cluster : la - croix
user : la - croix
name : la - croix
current - context : la - croix
kind : Config
preferences : { }
users :
- name : la - croix
user :
client - certificate : / home / la - croix / apiserver . crt
client - key : / home / la - croix / apiserver . key
` ) ,
want : [ ] byte ( "context has been updated" ) ,
} ,
{
name : "no clusters" ,
kubeconfig : [ ] byte ( `
apiVersion : v1
clusters :
contexts :
kind : Config
preferences : { }
users :
` ) ,
want : [ ] byte ( "context has been updated" ) ,
} ,
2019-12-16 15:58:45 +00:00
}
2020-08-16 05:03:41 +00:00
for _ , tc := range tests {
tc := tc
2020-08-22 17:18:15 +00:00
if ctx . Err ( ) == context . DeadlineExceeded {
t . Fatalf ( "Unable to run more tests (deadline exceeded)" )
}
2020-08-16 05:03:41 +00:00
t . Run ( tc . name , func ( t * testing . T ) {
t . Parallel ( )
c := exec . CommandContext ( ctx , Target ( ) , "-p" , profile , "update-context" , "--alsologtostderr" , "-v=2" )
if tc . kubeconfig != nil {
tf , err := ioutil . TempFile ( "" , "kubeconfig" )
if err != nil {
t . Fatal ( err )
}
if err := ioutil . WriteFile ( tf . Name ( ) , tc . kubeconfig , 0644 ) ; err != nil {
t . Fatal ( err )
}
t . Cleanup ( func ( ) {
os . Remove ( tf . Name ( ) )
} )
c . Env = append ( os . Environ ( ) , fmt . Sprintf ( "KUBECONFIG=%s" , tf . Name ( ) ) )
}
rr , err := Run ( t , c )
if err != nil {
t . Errorf ( "failed to run minikube update-context: args %q: %v" , rr . Command ( ) , err )
}
if ! bytes . Contains ( rr . Stdout . Bytes ( ) , tc . want ) {
t . Errorf ( "update-context: got=%q, want=*%q*" , rr . Stdout . Bytes ( ) , tc . want )
}
} )
2019-12-16 15:58:45 +00:00
}
}
2019-09-11 16:59:38 +00:00
// startHTTPProxy runs a local http proxy and sets the env vars for it.
func startHTTPProxy ( t * testing . T ) ( * http . Server , error ) {
port , err := freeport . GetFreePort ( )
if err != nil {
return nil , errors . Wrap ( err , "Failed to get an open port" )
}
addr := fmt . Sprintf ( "localhost:%d" , port )
proxy := goproxy . NewProxyHttpServer ( )
srv := & http . Server { Addr : addr , Handler : proxy }
go func ( s * http . Server , t * testing . T ) {
if err := s . ListenAndServe ( ) ; err != http . ErrServerClosed {
t . Errorf ( "Failed to start http server for proxy mock" )
}
} ( srv , t )
return srv , nil
2016-12-05 22:49:52 +00:00
}