From 04486049d2a476b49d02afc963e75ab40b406c32 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Tue, 17 Dec 2019 13:21:34 -0800 Subject: [PATCH 1/7] Always transfer images when local reference lookups fail --- pkg/minikube/machine/cache_images.go | 92 ++++++++++++++++------------ 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index dcfc7792a29a..1ac409b45af1 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -17,6 +17,7 @@ limitations under the License. package machine import ( + "fmt" "io/ioutil" "os" "os/exec" @@ -109,34 +110,41 @@ func LoadImages(cc *config.MachineConfig, runner command.Runner, images []string for _, image := range images { image := image g.Go(func() error { - ref, err := name.ParseReference(image, name.WeakValidation) - if err != nil { - return errors.Wrap(err, "image name reference") - } - - img, err := retrieveImage(ref) - if err != nil { - return errors.Wrap(err, "fetching image") - } - cf, err := img.ConfigName() - hash := cf.Hex - if err != nil { - glog.Infof("error retrieving image manifest for %s to check if it already exists: %v", image, err) - } else if cr.ImageExists(image, hash) { - glog.Infof("skipping re-loading image %q because sha %q already exists ", image, hash) + err := needsTransfer(image, cr) + if err == nil { return nil } - if err := transferAndLoadImage(runner, cc.KubernetesConfig, image, cacheDir); err != nil { - glog.Warningf("Failed to load %s: %v", image, err) - return errors.Wrapf(err, "loading image %s", image) - } - return nil + glog.Infof("%q needs transfer: %v", image, err) + return transferAndLoadImage(runner, cc.KubernetesConfig, image, cacheDir) }) } if err := g.Wait(); err != nil { return errors.Wrap(err, "loading cached images") } - glog.Infoln("Successfully loaded all cached images.") + glog.Infoln("Successfully loaded all cached images") + return nil +} + +// needsTransfer returns an error if an image needs to be retransfered +func needsTransfer(image string, cr cruntime.Manager) error { + ref, err := name.ParseReference(image, name.WeakValidation) + if err != nil { + return errors.Wrap(err, "parse ref") + } + + img, err := retrieveImage(ref) + if err != nil { + return errors.Wrap(err, "retrieve") + } + + cf, err := img.ConfigName() + if err != nil { + return errors.Wrap(err, "image hash") + } + + if !cr.ImageExists(image, cf.Hex) { + return fmt.Errorf("%q does not exist at hash %q in container runtime", image, cf.Hex) + } return nil } @@ -277,7 +285,7 @@ func transferAndLoadImage(cr command.Runner, k8s config.KubernetesConfig, imgNam return errors.Wrapf(err, "%s load %s", r.Name(), dst) } - glog.Infof("Successfully loaded image %s from cache", src) + glog.Infof("Transferred and loaded %s from cache", src) return nil } @@ -362,7 +370,7 @@ func CacheImage(image, dst string) error { img, err := retrieveImage(ref) if err != nil { - return errors.Wrap(err, "fetching image") + glog.Warningf("unable to retrieve image: %v", err) } glog.Infoln("OPENING: ", dstPath) @@ -370,27 +378,31 @@ func CacheImage(image, dst string) error { if err != nil { return err } - defer func() { // clean up temp files - err := os.Remove(f.Name()) - if err != nil { - glog.Infof("Failed to clean up the temp file %s : %v", f.Name(), err) + defer func() { + // If we left behind a temp file, remove it. + _, err := os.Stat(f.Name()) + if err == nil { + os.Remove(f.Name()) + if err != nil { + glog.Warningf("Failed to clean up the temp file %s: %v", f.Name(), err) + } } }() tag, err := name.NewTag(image, name.WeakValidation) if err != nil { - return err + return errors.Wrap(err, "newtag") } err = tarball.Write(tag, img, &tarball.WriteOptions{}, f) if err != nil { - return err + return errors.Wrap(err, "write") } err = f.Close() if err != nil { - return err + return errors.Wrap(err, "close") } err = os.Rename(f.Name(), dstPath) if err != nil { - return err + return errors.Wrap(err, "rename") } glog.Infof("%s exists", dst) return nil @@ -400,18 +412,20 @@ func retrieveImage(ref name.Reference) (v1.Image, error) { glog.Infof("retrieving image: %+v", ref) img, err := daemon.Image(ref) if err == nil { - glog.Infof("found %s locally; caching", ref.Name()) - return img, err + glog.Infof("found %s locally: %+v", ref.Name(), img) + return img, nil + } + // reference does not exist in the local daemon + if err != nil { + glog.Infof("daemon lookup for %+v: %v", ref, err) } - glog.Infof("daemon image for %+v: %v", img, err) + img, err = remote.Image(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain)) if err == nil { - return img, err + return img, nil } - glog.Warningf("failed authn download for %+v (trying anon): %+v", ref, err) + + glog.Warningf("authn lookup for %+v (trying anon): %+v", ref, err) img, err = remote.Image(ref) - if err != nil { - glog.Warningf("failed anon download for %+v: %+v", ref, err) - } return img, err } From de4b9b65fbd3e552dd5a6f01ec922cf2941baec9 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Tue, 17 Dec 2019 15:22:13 -0800 Subject: [PATCH 2/7] Add offline integration test --- test/integration/offline_test.go | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 test/integration/offline_test.go diff --git a/test/integration/offline_test.go b/test/integration/offline_test.go new file mode 100644 index 000000000000..60c7a3e01d9f --- /dev/null +++ b/test/integration/offline_test.go @@ -0,0 +1,60 @@ +// +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 ( + "context" + "fmt" + "os" + "os/exec" + "testing" + "time" +) + +func TestOffline(t *testing.T) { + MaybeParallel(t) + + t.Run("group", func(t *testing.T) { + for _, runtime := range []string{"docker", "crio", "containerd"} { + t.Run(runtime, func(t *testing.T) { + MaybeParallel(t) + WaitForStartSlot(t) + + if runtime != "docker" && NoneDriver() { + t.Skipf("skipping %s - incompatible with none driver", t.Name()) + } + + profile := UniqueProfileName(fmt.Sprintf("offline-%s", runtime)) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer CleanupWithLogs(t, profile, cancel) + + startArgs := append([]string{"start", "-p", profile, "--alsologtostderr", "-v=1", "--wait=true", "--container-runtime", runtime}) + c := exec.CommandContext(ctx, Target(), startArgs...) + env := os.Environ() + env = append(env, "HTTP_PROXYS=172.1.1.1") + env = append(env, "DOCKER_HOST=172.1.1.1") + rr, err := Run(t, c) + if err != nil { + // Fatal so that we may collect logs before stop/delete steps + t.Fatalf("%s failed: %v", rr.Args, err) + } + }) + } + }) +} From 896f96dfc4b66b4abd8cd7cafac0df22ab753da5 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Tue, 17 Dec 2019 15:34:47 -0800 Subject: [PATCH 3/7] Pass the env in properly --- test/integration/offline_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/integration/offline_test.go b/test/integration/offline_test.go index 60c7a3e01d9f..9af847b53176 100644 --- a/test/integration/offline_test.go +++ b/test/integration/offline_test.go @@ -44,11 +44,13 @@ func TestOffline(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) defer CleanupWithLogs(t, profile, cancel) - startArgs := append([]string{"start", "-p", profile, "--alsologtostderr", "-v=1", "--wait=true", "--container-runtime", runtime}) + startArgs := []string{"start", "-p", profile, "--alsologtostderr", "-v=1", "--wait=true", "--container-runtime", runtime} + startArgs = append(startArgs, StartArgs()...) c := exec.CommandContext(ctx, Target(), startArgs...) env := os.Environ() env = append(env, "HTTP_PROXYS=172.1.1.1") env = append(env, "DOCKER_HOST=172.1.1.1") + c.Env = env rr, err := Run(t, c) if err != nil { // Fatal so that we may collect logs before stop/delete steps From 6208b6cc27e96dd501e73ba939e8e1236a036cb1 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 18 Dec 2019 09:41:52 -0800 Subject: [PATCH 4/7] Add HTTP_PROXY and comment --- test/integration/offline_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/integration/offline_test.go b/test/integration/offline_test.go index 9af847b53176..1f521e912061 100644 --- a/test/integration/offline_test.go +++ b/test/integration/offline_test.go @@ -48,8 +48,10 @@ func TestOffline(t *testing.T) { startArgs = append(startArgs, StartArgs()...) c := exec.CommandContext(ctx, Target(), startArgs...) env := os.Environ() - env = append(env, "HTTP_PROXYS=172.1.1.1") - env = append(env, "DOCKER_HOST=172.1.1.1") + // RFC1918 address that unlikely to host working a proxy server + env = append(env, "HTTP_PROXY=172.16.1.1:1") + env = append(env, "HTTP_PROXYS=172.16.1.1:1") + env = append(env, "DOCKER_HOST=172.16.1.1:1") c.Env = env rr, err := Run(t, c) if err != nil { From 98508253a526b19904f4ed7eb211f19963f7a30a Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 18 Dec 2019 09:46:36 -0800 Subject: [PATCH 5/7] --download-only should download drivers --- cmd/minikube/cmd/start.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index d1e4fbec98f9..b58a14a98f43 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -304,10 +304,8 @@ func runStart(cmd *cobra.Command, args []string) { validateFlags(cmd, driverName) validateUser(driverName) - // No need to install a driver in download-only mode - if !viper.GetBool(downloadOnly) { - updateDriver(driverName) - } + // Download & update the driver, even in --download-only mode + updateDriver(driverName) k8sVersion, isUpgrade := getKubernetesVersion(existing) config, err := generateCfgFromFlags(cmd, k8sVersion, driverName) From 561046ab51c53247c31d9ec7bc4c73057e103b5e Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 18 Dec 2019 09:47:38 -0800 Subject: [PATCH 6/7] Rename tests to ensure ordering --- test/integration/a_serial_test.go | 145 ------------------------------ test/integration/offline_test.go | 64 ------------- 2 files changed, 209 deletions(-) delete mode 100644 test/integration/a_serial_test.go delete mode 100644 test/integration/offline_test.go diff --git a/test/integration/a_serial_test.go b/test/integration/a_serial_test.go deleted file mode 100644 index 0efa3e7e57b7..000000000000 --- a/test/integration/a_serial_test.go +++ /dev/null @@ -1,145 +0,0 @@ -// +build integration - -/* -Copyright 2019 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 ( - "context" - "encoding/json" - "fmt" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" - "time" - - "k8s.io/minikube/pkg/minikube/bootstrapper/images" - "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/constants" - "k8s.io/minikube/pkg/minikube/localpath" -) - -func TestDownloadOnly(t *testing.T) { - profile := UniqueProfileName("download") - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) - defer Cleanup(t, profile, cancel) - - // Stores the startup run result for later error messages - var rrr *RunResult - var err error - - t.Run("group", func(t *testing.T) { - versions := []string{ - constants.OldestKubernetesVersion, - constants.DefaultKubernetesVersion, - constants.NewestKubernetesVersion, - } - for _, v := range versions { - t.Run(v, func(t *testing.T) { - // Explicitly does not pass StartArgs() to test driver default - // --force to avoid uid check - args := []string{"start", "--download-only", "-p", profile, "--force", "--alsologtostderr", fmt.Sprintf("--kubernetes-version=%s", v)} - - // Preserve the initial run-result for debugging - if rrr == nil { - rrr, err = Run(t, exec.CommandContext(ctx, Target(), args...)) - } else { - _, err = Run(t, exec.CommandContext(ctx, Target(), args...)) - } - - if err != nil { - t.Errorf("%s failed: %v", args, err) - } - - imgs, err := images.Kubeadm("", v) - if err != nil { - t.Errorf("kubeadm images: %v", v) - } - - for _, img := range imgs { - img = strings.Replace(img, ":", "_", 1) // for example kube-scheduler:v1.15.2 --> kube-scheduler_v1.15.2 - fp := filepath.Join(localpath.MiniPath(), "cache", "images", img) - _, err := os.Stat(fp) - if err != nil { - t.Errorf("expected image file exist at %q but got error: %v", fp, err) - } - } - - // checking binaries downloaded (kubelet,kubeadm) - for _, bin := range constants.KubeadmBinaries { - fp := filepath.Join(localpath.MiniPath(), "cache", v, bin) - _, err := os.Stat(fp) - if err != nil { - t.Errorf("expected the file for binary exist at %q but got error %v", fp, err) - } - } - }) - } - - // Check that the profile we've created has the expected driver - t.Run("ExpectedDefaultDriver", func(t *testing.T) { - if ExpectedDefaultDriver() == "" { - t.Skipf("--expected-default-driver is unset, skipping test") - return - } - rr, err := Run(t, exec.CommandContext(ctx, Target(), "profile", "list", "--output", "json")) - if err != nil { - t.Errorf("%s failed: %v", rr.Args, err) - } - var ps map[string][]config.Profile - err = json.Unmarshal(rr.Stdout.Bytes(), &ps) - if err != nil { - t.Errorf("%s failed: %v", rr.Args, err) - } - - got := "" - for _, p := range ps["valid"] { - if p.Name == profile { - got = p.Config[0].VMDriver - } - } - - if got != ExpectedDefaultDriver() { - t.Errorf("got driver %q, expected %q\nstart output: %s", got, ExpectedDefaultDriver(), rrr.Output()) - } - }) - - // This is a weird place to test profile deletion, but this test is serial, and we have a profile to delete! - t.Run("DeleteAll", func(t *testing.T) { - if !CanCleanup() { - t.Skip("skipping, as cleanup is disabled") - } - rr, err := Run(t, exec.CommandContext(ctx, Target(), "delete", "--all")) - if err != nil { - t.Errorf("%s failed: %v", rr.Args, err) - } - }) - // Delete should always succeed, even if previously partially or fully deleted. - t.Run("DeleteAlwaysSucceeds", func(t *testing.T) { - if !CanCleanup() { - t.Skip("skipping, as cleanup is disabled") - } - rr, err := Run(t, exec.CommandContext(ctx, Target(), "delete", "-p", profile)) - if err != nil { - t.Errorf("%s failed: %v", rr.Args, err) - } - }) - }) - -} diff --git a/test/integration/offline_test.go b/test/integration/offline_test.go deleted file mode 100644 index 1f521e912061..000000000000 --- a/test/integration/offline_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// +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 ( - "context" - "fmt" - "os" - "os/exec" - "testing" - "time" -) - -func TestOffline(t *testing.T) { - MaybeParallel(t) - - t.Run("group", func(t *testing.T) { - for _, runtime := range []string{"docker", "crio", "containerd"} { - t.Run(runtime, func(t *testing.T) { - MaybeParallel(t) - WaitForStartSlot(t) - - if runtime != "docker" && NoneDriver() { - t.Skipf("skipping %s - incompatible with none driver", t.Name()) - } - - profile := UniqueProfileName(fmt.Sprintf("offline-%s", runtime)) - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) - defer CleanupWithLogs(t, profile, cancel) - - startArgs := []string{"start", "-p", profile, "--alsologtostderr", "-v=1", "--wait=true", "--container-runtime", runtime} - startArgs = append(startArgs, StartArgs()...) - c := exec.CommandContext(ctx, Target(), startArgs...) - env := os.Environ() - // RFC1918 address that unlikely to host working a proxy server - env = append(env, "HTTP_PROXY=172.16.1.1:1") - env = append(env, "HTTP_PROXYS=172.16.1.1:1") - env = append(env, "DOCKER_HOST=172.16.1.1:1") - c.Env = env - rr, err := Run(t, c) - if err != nil { - // Fatal so that we may collect logs before stop/delete steps - t.Fatalf("%s failed: %v", rr.Args, err) - } - }) - } - }) -} From a0b752ad0079941710f088159c4e181e6570cc30 Mon Sep 17 00:00:00 2001 From: tstromberg Date: Wed, 18 Dec 2019 15:15:48 -0800 Subject: [PATCH 7/7] Enforce that offline test runs right after download test --- test/integration/aaa_download_only_test.go | 145 +++++++++++++++++++++ test/integration/aab_offline_test.go | 62 +++++++++ 2 files changed, 207 insertions(+) create mode 100644 test/integration/aaa_download_only_test.go create mode 100644 test/integration/aab_offline_test.go diff --git a/test/integration/aaa_download_only_test.go b/test/integration/aaa_download_only_test.go new file mode 100644 index 000000000000..0efa3e7e57b7 --- /dev/null +++ b/test/integration/aaa_download_only_test.go @@ -0,0 +1,145 @@ +// +build integration + +/* +Copyright 2019 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 ( + "context" + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + "time" + + "k8s.io/minikube/pkg/minikube/bootstrapper/images" + "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/localpath" +) + +func TestDownloadOnly(t *testing.T) { + profile := UniqueProfileName("download") + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer Cleanup(t, profile, cancel) + + // Stores the startup run result for later error messages + var rrr *RunResult + var err error + + t.Run("group", func(t *testing.T) { + versions := []string{ + constants.OldestKubernetesVersion, + constants.DefaultKubernetesVersion, + constants.NewestKubernetesVersion, + } + for _, v := range versions { + t.Run(v, func(t *testing.T) { + // Explicitly does not pass StartArgs() to test driver default + // --force to avoid uid check + args := []string{"start", "--download-only", "-p", profile, "--force", "--alsologtostderr", fmt.Sprintf("--kubernetes-version=%s", v)} + + // Preserve the initial run-result for debugging + if rrr == nil { + rrr, err = Run(t, exec.CommandContext(ctx, Target(), args...)) + } else { + _, err = Run(t, exec.CommandContext(ctx, Target(), args...)) + } + + if err != nil { + t.Errorf("%s failed: %v", args, err) + } + + imgs, err := images.Kubeadm("", v) + if err != nil { + t.Errorf("kubeadm images: %v", v) + } + + for _, img := range imgs { + img = strings.Replace(img, ":", "_", 1) // for example kube-scheduler:v1.15.2 --> kube-scheduler_v1.15.2 + fp := filepath.Join(localpath.MiniPath(), "cache", "images", img) + _, err := os.Stat(fp) + if err != nil { + t.Errorf("expected image file exist at %q but got error: %v", fp, err) + } + } + + // checking binaries downloaded (kubelet,kubeadm) + for _, bin := range constants.KubeadmBinaries { + fp := filepath.Join(localpath.MiniPath(), "cache", v, bin) + _, err := os.Stat(fp) + if err != nil { + t.Errorf("expected the file for binary exist at %q but got error %v", fp, err) + } + } + }) + } + + // Check that the profile we've created has the expected driver + t.Run("ExpectedDefaultDriver", func(t *testing.T) { + if ExpectedDefaultDriver() == "" { + t.Skipf("--expected-default-driver is unset, skipping test") + return + } + rr, err := Run(t, exec.CommandContext(ctx, Target(), "profile", "list", "--output", "json")) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + var ps map[string][]config.Profile + err = json.Unmarshal(rr.Stdout.Bytes(), &ps) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + + got := "" + for _, p := range ps["valid"] { + if p.Name == profile { + got = p.Config[0].VMDriver + } + } + + if got != ExpectedDefaultDriver() { + t.Errorf("got driver %q, expected %q\nstart output: %s", got, ExpectedDefaultDriver(), rrr.Output()) + } + }) + + // This is a weird place to test profile deletion, but this test is serial, and we have a profile to delete! + t.Run("DeleteAll", func(t *testing.T) { + if !CanCleanup() { + t.Skip("skipping, as cleanup is disabled") + } + rr, err := Run(t, exec.CommandContext(ctx, Target(), "delete", "--all")) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + }) + // Delete should always succeed, even if previously partially or fully deleted. + t.Run("DeleteAlwaysSucceeds", func(t *testing.T) { + if !CanCleanup() { + t.Skip("skipping, as cleanup is disabled") + } + rr, err := Run(t, exec.CommandContext(ctx, Target(), "delete", "-p", profile)) + if err != nil { + t.Errorf("%s failed: %v", rr.Args, err) + } + }) + }) + +} diff --git a/test/integration/aab_offline_test.go b/test/integration/aab_offline_test.go new file mode 100644 index 000000000000..4224ecda8dc1 --- /dev/null +++ b/test/integration/aab_offline_test.go @@ -0,0 +1,62 @@ +// +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 ( + "context" + "fmt" + "os" + "os/exec" + "testing" + "time" +) + +func TestOffline(t *testing.T) { + t.Run("group", func(t *testing.T) { + for _, runtime := range []string{"docker", "crio", "containerd"} { + t.Run(runtime, func(t *testing.T) { + MaybeParallel(t) + WaitForStartSlot(t) + + if runtime != "docker" && NoneDriver() { + t.Skipf("skipping %s - incompatible with none driver", t.Name()) + } + + profile := UniqueProfileName(fmt.Sprintf("offline-%s", runtime)) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer CleanupWithLogs(t, profile, cancel) + + startArgs := []string{"start", "-p", profile, "--alsologtostderr", "-v=1", "--wait=true", "--container-runtime", runtime} + startArgs = append(startArgs, StartArgs()...) + c := exec.CommandContext(ctx, Target(), startArgs...) + env := os.Environ() + // RFC1918 address that unlikely to host working a proxy server + env = append(env, "HTTP_PROXY=172.16.1.1:1") + env = append(env, "HTTP_PROXYS=172.16.1.1:1") + env = append(env, "DOCKER_HOST=172.16.1.1:1") + c.Env = env + rr, err := Run(t, c) + if err != nil { + // Fatal so that we may collect logs before stop/delete steps + t.Fatalf("%s failed: %v", rr.Args, err) + } + }) + } + }) +}