From fa1dcd0a8bbe02d7eb82d3afac2b83ba547f51c7 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Fri, 3 Oct 2014 17:48:05 -0700 Subject: [PATCH] kubelet: add basic test for runonce --- pkg/kubelet/runonce.go | 11 +++- pkg/kubelet/runonce_test.go | 115 ++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 pkg/kubelet/runonce_test.go diff --git a/pkg/kubelet/runonce.go b/pkg/kubelet/runonce.go index f1f48d25b3..524972eee8 100644 --- a/pkg/kubelet/runonce.go +++ b/pkg/kubelet/runonce.go @@ -27,7 +27,7 @@ import ( const ( RunOnceManifestDelay = 1 * time.Second - RunOnceMaxRetries = 1 + RunOnceMaxRetries = 10 RunOnceRetryDelay = 1 * time.Second RunOnceRetryDelayBackoff = 2 ) @@ -93,7 +93,9 @@ func (kl *Kubelet) runPod(pod Pod) (api.PodInfo, error) { } delay := RunOnceRetryDelay - for i := 0; i < RunOnceMaxRetries; i++ { + retry := 0 + for { + glog.Infof("syncing pod") err := kl.syncPod(&pod, dockerContainers) if err != nil { return nil, fmt.Errorf("error syncing pod: %v", err) @@ -105,11 +107,14 @@ func (kl *Kubelet) runPod(pod Pod) (api.PodInfo, error) { if podInfo(info).isRunning() { return info, nil } + if retry >= RunOnceMaxRetries { + return nil, fmt.Errorf("timeout error: pod %q containers not running after %d retries", pod.Name, RunOnceMaxRetries) + } glog.Infof("pod %q containers not running, waiting for %v", pod.Name, delay) <-time.After(delay) + retry++ delay *= RunOnceRetryDelayBackoff } - return nil, fmt.Errorf("timeout error: pod %q containers not running after %d retries", pod.Name, RunOnceMaxRetries) } // Alias PodInfo for internal usage. diff --git a/pkg/kubelet/runonce_test.go b/pkg/kubelet/runonce_test.go new file mode 100644 index 0000000000..4949a99594 --- /dev/null +++ b/pkg/kubelet/runonce_test.go @@ -0,0 +1,115 @@ +/* +Copyright 2014 Google Inc. 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 kubelet + +import ( + "fmt" + "strconv" + "testing" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools" + docker "github.com/fsouza/go-dockerclient" +) + +type listContainersResult struct { + label string + containers []docker.APIContainers + err error +} + +type inspectContainersResult struct { + label string + container docker.Container + err error +} + +type testDocker struct { + listContainersResults []listContainersResult + inspectContainersResults []inspectContainersResult + dockertools.FakeDockerClient + t *testing.T +} + +func (d *testDocker) ListContainers(options docker.ListContainersOptions) ([]docker.APIContainers, error) { + if len(d.listContainersResults) > 0 { + result := d.listContainersResults[0] + d.listContainersResults = d.listContainersResults[1:] + d.t.Logf("ListContainers: %q, returning: (%v, %v)", result.label, result.containers, result.err) + return result.containers, result.err + } + return nil, fmt.Errorf("ListContainers error: no more test results") +} + +func (d *testDocker) InspectContainer(id string) (*docker.Container, error) { + if len(d.inspectContainersResults) > 0 { + result := d.inspectContainersResults[0] + d.inspectContainersResults = d.inspectContainersResults[1:] + d.t.Logf("InspectContainers: %q, returning: (%v, %v)", result.label, result.container, result.err) + return &result.container, result.err + } + return nil, fmt.Errorf("InspectContainer error: no more test results") +} + +func TestRunOnce(t *testing.T) { + kb := &Kubelet{} + container := api.Container{Name: "bar"} + kb.dockerClient = &testDocker{ + listContainersResults: []listContainersResult{ + {label: "pre syncPod", containers: []docker.APIContainers{}}, + {label: "syncPod #1", containers: []docker.APIContainers{}}, + {label: "syncPod #2", containers: []docker.APIContainers{}}, + {label: "post syncPod", containers: []docker.APIContainers{ + { + Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo.test"}, + ID: "1234", + }, + { + Names: []string{"/k8s_net_foo.test_"}, + ID: "9876", + }, + }}, + }, + inspectContainersResults: []inspectContainersResult{ + {label: "syncPod", container: docker.Container{State: docker.State{Running: true}}}, + {label: "syncPod", container: docker.Container{State: docker.State{Running: true}}}, + }, + t: t, + } + kb.dockerPuller = &dockertools.FakeDockerPuller{} + results, err := kb.runOnce([]Pod{ + { + Name: "foo", + Namespace: "test", + Manifest: api.ContainerManifest{ + ID: "foo", + Containers: []api.Container{ + {Name: "bar"}, + }, + }, + }, + }) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if results[0].Err != nil { + t.Errorf("unexpected run pod error: %v", results[0].Err) + } + if results[0].Pod.Name != "foo" { + t.Errorf("unexpected pod: %q", results[0].Pod.Name) + } +}