diff --git a/pkg/client/cache/listers.go b/pkg/client/cache/listers.go index f989116fad8..4e1dd78272c 100644 --- a/pkg/client/cache/listers.go +++ b/pkg/client/cache/listers.go @@ -42,11 +42,11 @@ type StoreToPodLister struct { // TODO Get rid of the selector because that is confusing because the user might not realize that there has already been // some selection at the caching stage. Also, consistency will facilitate code generation. However, the pkg/client // is inconsistent too. -func (s *StoreToPodLister) List(selector labels.Selector) (pods []api.Pod, err error) { +func (s *StoreToPodLister) List(selector labels.Selector) (pods []*api.Pod, err error) { for _, m := range s.Store.List() { pod := m.(*api.Pod) if selector.Matches(labels.Set(pod.Labels)) { - pods = append(pods, *pod) + pods = append(pods, pod) } } return pods, nil @@ -106,7 +106,7 @@ func (s *StoreToServiceLister) List() (services api.ServiceList, err error) { // TODO: Move this back to scheduler as a helper function that takes a Store, // rather than a method of StoreToServiceLister. -func (s *StoreToServiceLister) GetPodServices(pod api.Pod) (services []api.Service, err error) { +func (s *StoreToServiceLister) GetPodServices(pod *api.Pod) (services []api.Service, err error) { var selector labels.Selector var service api.Service diff --git a/pkg/kubelet/config/apiserver.go b/pkg/kubelet/config/apiserver.go index b859944fc0a..e55364877ef 100644 --- a/pkg/kubelet/config/apiserver.go +++ b/pkg/kubelet/config/apiserver.go @@ -34,9 +34,9 @@ func NewSourceApiserver(c *client.Client, hostname string, updates chan<- interf // newSourceApiserverFromLW holds creates a config source that watches and pulls from the apiserver. func newSourceApiserverFromLW(lw cache.ListerWatcher, updates chan<- interface{}) { send := func(objs []interface{}) { - var pods []api.Pod + var pods []*api.Pod for _, o := range objs { - pods = append(pods, *o.(*api.Pod)) + pods = append(pods, o.(*api.Pod)) } updates <- kubelet.PodUpdate{pods, kubelet.SET, kubelet.ApiserverSource} } diff --git a/pkg/kubelet/config/apiserver_test.go b/pkg/kubelet/config/apiserver_test.go index 7b5367578fb..afb9fbb90f5 100644 --- a/pkg/kubelet/config/apiserver_test.go +++ b/pkg/kubelet/config/apiserver_test.go @@ -42,20 +42,20 @@ func (lw fakePodLW) Watch(resourceVersion string) (watch.Interface, error) { var _ cache.ListerWatcher = fakePodLW{} func TestNewSourceApiserver_UpdatesAndMultiplePods(t *testing.T) { - pod1v1 := api.Pod{ + pod1v1 := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "p"}, Spec: api.PodSpec{Containers: []api.Container{{Image: "image/one"}}}} - pod1v2 := api.Pod{ + pod1v2 := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "p"}, Spec: api.PodSpec{Containers: []api.Container{{Image: "image/two"}}}} - pod2 := api.Pod{ + pod2 := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "q"}, Spec: api.PodSpec{Containers: []api.Container{{Image: "image/blah"}}}} // Setup fake api client. fakeWatch := watch.NewFake() lw := fakePodLW{ - listResp: &api.PodList{Items: []api.Pod{pod1v1}}, + listResp: &api.PodList{Items: []api.Pod{*pod1v1}}, watchResp: fakeWatch, } @@ -74,7 +74,7 @@ func TestNewSourceApiserver_UpdatesAndMultiplePods(t *testing.T) { } // Add another pod - fakeWatch.Add(&pod2) + fakeWatch.Add(pod2) got, ok = <-ch if !ok { t.Errorf("Unable to read from channel when expected") @@ -89,7 +89,7 @@ func TestNewSourceApiserver_UpdatesAndMultiplePods(t *testing.T) { } // Modify pod1 - fakeWatch.Modify(&pod1v2) + fakeWatch.Modify(pod1v2) got, ok = <-ch if !ok { t.Errorf("Unable to read from channel when expected") @@ -103,7 +103,7 @@ func TestNewSourceApiserver_UpdatesAndMultiplePods(t *testing.T) { } // Delete pod1 - fakeWatch.Delete(&pod1v2) + fakeWatch.Delete(pod1v2) got, ok = <-ch if !ok { t.Errorf("Unable to read from channel when expected") @@ -115,7 +115,7 @@ func TestNewSourceApiserver_UpdatesAndMultiplePods(t *testing.T) { } // Delete pod2 - fakeWatch.Delete(&pod2) + fakeWatch.Delete(pod2) got, ok = <-ch if !ok { t.Errorf("Unable to read from channel when expected") diff --git a/pkg/kubelet/config/common.go b/pkg/kubelet/config/common.go index 72ec9c7e503..f74084e3fe8 100644 --- a/pkg/kubelet/config/common.go +++ b/pkg/kubelet/config/common.go @@ -85,7 +85,7 @@ func applyDefaults(pod *api.Pod, source string, isFile bool, hostname string) er type defaultFunc func(pod *api.Pod) error -func tryDecodeSinglePod(data []byte, defaultFn defaultFunc) (parsed bool, pod api.Pod, err error) { +func tryDecodeSinglePod(data []byte, defaultFn defaultFunc) (parsed bool, pod *api.Pod, err error) { obj, err := api.Scheme.Decode(data) if err != nil { return false, pod, err @@ -104,7 +104,7 @@ func tryDecodeSinglePod(data []byte, defaultFn defaultFunc) (parsed bool, pod ap err = fmt.Errorf("invalid pod: %v", errs) return true, pod, err } - return true, *newPod, nil + return true, newPod, nil } func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods api.PodList, err error) { @@ -132,7 +132,7 @@ func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods api return true, *newPods, err } -func tryDecodeSingleManifest(data []byte, defaultFn defaultFunc) (parsed bool, manifest v1beta1.ContainerManifest, pod api.Pod, err error) { +func tryDecodeSingleManifest(data []byte, defaultFn defaultFunc) (parsed bool, manifest v1beta1.ContainerManifest, pod *api.Pod, err error) { // TODO: should be api.Scheme.Decode // This is awful. DecodeInto() expects to find an APIObject, which // Manifest is not. We keep reading manifest for now for compat, but @@ -144,6 +144,7 @@ func tryDecodeSingleManifest(data []byte, defaultFn defaultFunc) (parsed bool, m // avoids writing a v1beta1.ContainerManifest -> api.Pod // conversion which would be identical to the api.ContainerManifest -> // api.Pod conversion. + pod = new(api.Pod) if err = yaml.Unmarshal(data, &manifest); err != nil { return false, manifest, pod, err } @@ -155,10 +156,10 @@ func tryDecodeSingleManifest(data []byte, defaultFn defaultFunc) (parsed bool, m err = fmt.Errorf("invalid manifest: %v", errs) return false, manifest, pod, err } - if err = api.Scheme.Convert(&newManifest, &pod); err != nil { + if err = api.Scheme.Convert(&newManifest, pod); err != nil { return true, manifest, pod, err } - if err := defaultFn(&pod); err != nil { + if err := defaultFn(pod); err != nil { return true, manifest, pod, err } // Success. diff --git a/pkg/kubelet/config/config.go b/pkg/kubelet/config/config.go index bc4c1685693..5fb063f1f37 100644 --- a/pkg/kubelet/config/config.go +++ b/pkg/kubelet/config/config.go @@ -168,12 +168,12 @@ func (s *podStorage) Merge(source string, change interface{}) error { s.updates <- *updates } if len(deletes.Pods) > 0 || len(adds.Pods) > 0 { - s.updates <- kubelet.PodUpdate{s.MergedState().([]api.Pod), kubelet.SET, source} + s.updates <- kubelet.PodUpdate{s.MergedState().([]*api.Pod), kubelet.SET, source} } case PodConfigNotificationSnapshot: if len(updates.Pods) > 0 || len(deletes.Pods) > 0 || len(adds.Pods) > 0 { - s.updates <- kubelet.PodUpdate{s.MergedState().([]api.Pod), kubelet.SET, source} + s.updates <- kubelet.PodUpdate{s.MergedState().([]*api.Pod), kubelet.SET, source} } default: @@ -212,7 +212,7 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de if !reflect.DeepEqual(existing.Spec, ref.Spec) { // this is an update existing.Spec = ref.Spec - updates.Pods = append(updates.Pods, *existing) + updates.Pods = append(updates.Pods, existing) continue } // this is a no-op @@ -224,17 +224,17 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de } ref.Annotations[kubelet.ConfigSourceAnnotationKey] = source pods[name] = ref - adds.Pods = append(adds.Pods, *ref) + adds.Pods = append(adds.Pods, ref) } case kubelet.REMOVE: glog.V(4).Infof("Removing a pod %v", update) for _, value := range update.Pods { - name := kubecontainer.GetPodFullName(&value) + name := kubecontainer.GetPodFullName(value) if existing, found := pods[name]; found { // this is a delete delete(pods, name) - deletes.Pods = append(deletes.Pods, *existing) + deletes.Pods = append(deletes.Pods, existing) continue } // this is a no-op @@ -255,7 +255,7 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de if !reflect.DeepEqual(existing.Spec, ref.Spec) { // this is an update existing.Spec = ref.Spec - updates.Pods = append(updates.Pods, *existing) + updates.Pods = append(updates.Pods, existing) continue } // this is a no-op @@ -266,13 +266,13 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de } ref.Annotations[kubelet.ConfigSourceAnnotationKey] = source pods[name] = ref - adds.Pods = append(adds.Pods, *ref) + adds.Pods = append(adds.Pods, ref) } for name, existing := range oldPods { if _, found := pods[name]; !found { // this is a delete - deletes.Pods = append(deletes.Pods, *existing) + deletes.Pods = append(deletes.Pods, existing) } } @@ -297,10 +297,9 @@ func (s *podStorage) seenSources(sources ...string) bool { return s.sourcesSeen.HasAll(sources...) } -func filterInvalidPods(pods []api.Pod, source string, recorder record.EventRecorder) (filtered []*api.Pod) { +func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventRecorder) (filtered []*api.Pod) { names := util.StringSet{} - for i := range pods { - pod := &pods[i] + for i, pod := range pods { var errlist []error if errs := validation.ValidatePod(pod); len(errs) != 0 { errlist = append(errlist, errs...) @@ -330,21 +329,21 @@ func filterInvalidPods(pods []api.Pod, source string, recorder record.EventRecor func (s *podStorage) Sync() { s.updateLock.Lock() defer s.updateLock.Unlock() - s.updates <- kubelet.PodUpdate{s.MergedState().([]api.Pod), kubelet.SET, kubelet.AllSource} + s.updates <- kubelet.PodUpdate{s.MergedState().([]*api.Pod), kubelet.SET, kubelet.AllSource} } // Object implements config.Accessor func (s *podStorage) MergedState() interface{} { s.podLock.RLock() defer s.podLock.RUnlock() - pods := make([]api.Pod, 0) + pods := make([]*api.Pod, 0) for _, sourcePods := range s.pods { for _, podRef := range sourcePods { pod, err := api.Scheme.Copy(podRef) if err != nil { glog.Errorf("unable to copy pod: %v", err) } - pods = append(pods, *pod.(*api.Pod)) + pods = append(pods, pod.(*api.Pod)) } } return pods diff --git a/pkg/kubelet/config/config_test.go b/pkg/kubelet/config/config_test.go index c9288b5d715..6f53db865c5 100644 --- a/pkg/kubelet/config/config_test.go +++ b/pkg/kubelet/config/config_test.go @@ -39,7 +39,7 @@ func expectEmptyChannel(t *testing.T, ch <-chan interface{}) { } } -type sortedPods []api.Pod +type sortedPods []*api.Pod func (s sortedPods) Len() int { return len(s) @@ -51,8 +51,8 @@ func (s sortedPods) Less(i, j int) bool { return s[i].Namespace < s[j].Namespace } -func CreateValidPod(name, namespace, source string) api.Pod { - return api.Pod{ +func CreateValidPod(name, namespace, source string) *api.Pod { + return &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: types.UID(name), // for the purpose of testing, this is unique enough Name: name, @@ -67,12 +67,8 @@ func CreateValidPod(name, namespace, source string) api.Pod { } } -func CreatePodUpdate(op kubelet.PodOperation, source string, pods ...api.Pod) kubelet.PodUpdate { - newPods := make([]api.Pod, len(pods)) - for i := range pods { - newPods[i] = pods[i] - } - return kubelet.PodUpdate{newPods, op, source} +func CreatePodUpdate(op kubelet.PodOperation, source string, pods ...*api.Pod) kubelet.PodUpdate { + return kubelet.PodUpdate{Pods: pods, Op: op, Source: source} } func createPodConfigTester(mode PodConfigNotificationMode) (chan<- interface{}, <-chan kubelet.PodUpdate, *PodConfig) { @@ -162,7 +158,7 @@ func TestInvalidPodFiltered(t *testing.T) { expectPodUpdate(t, ch, CreatePodUpdate(kubelet.ADD, NoneSource, CreateValidPod("foo", "new", "test"))) // add an invalid update - podUpdate = CreatePodUpdate(kubelet.UPDATE, NoneSource, api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) + podUpdate = CreatePodUpdate(kubelet.UPDATE, NoneSource, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) channel <- podUpdate expectNoPodUpdate(t, ch) } @@ -179,10 +175,10 @@ func TestNewPodAddedSnapshotAndUpdates(t *testing.T) { expectPodUpdate(t, ch, CreatePodUpdate(kubelet.SET, kubelet.AllSource, CreateValidPod("foo", "new", "test"))) // container updates are separated as UPDATE - pod := podUpdate.Pods[0] + pod := *podUpdate.Pods[0] pod.Spec.Containers = []api.Container{{Name: "bar", Image: "test", ImagePullPolicy: api.PullIfNotPresent}} - channel <- CreatePodUpdate(kubelet.ADD, NoneSource, pod) - expectPodUpdate(t, ch, CreatePodUpdate(kubelet.UPDATE, NoneSource, pod)) + channel <- CreatePodUpdate(kubelet.ADD, NoneSource, &pod) + expectPodUpdate(t, ch, CreatePodUpdate(kubelet.UPDATE, NoneSource, &pod)) } func TestNewPodAddedSnapshot(t *testing.T) { @@ -197,10 +193,10 @@ func TestNewPodAddedSnapshot(t *testing.T) { expectPodUpdate(t, ch, CreatePodUpdate(kubelet.SET, kubelet.AllSource, CreateValidPod("foo", "new", "test"))) // container updates are separated as UPDATE - pod := podUpdate.Pods[0] + pod := *podUpdate.Pods[0] pod.Spec.Containers = []api.Container{{Name: "bar", Image: "test", ImagePullPolicy: api.PullIfNotPresent}} - channel <- CreatePodUpdate(kubelet.ADD, NoneSource, pod) - expectPodUpdate(t, ch, CreatePodUpdate(kubelet.SET, TestSource, pod)) + channel <- CreatePodUpdate(kubelet.ADD, NoneSource, &pod) + expectPodUpdate(t, ch, CreatePodUpdate(kubelet.SET, TestSource, &pod)) } func TestNewPodAddedUpdatedRemoved(t *testing.T) { @@ -221,7 +217,7 @@ func TestNewPodAddedUpdatedRemoved(t *testing.T) { channel <- podUpdate expectPodUpdate(t, ch, CreatePodUpdate(kubelet.UPDATE, NoneSource, pod)) - podUpdate = CreatePodUpdate(kubelet.REMOVE, NoneSource, api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "new"}}) + podUpdate = CreatePodUpdate(kubelet.REMOVE, NoneSource, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "new"}}) channel <- podUpdate expectPodUpdate(t, ch, CreatePodUpdate(kubelet.REMOVE, NoneSource, pod)) } diff --git a/pkg/kubelet/config/file.go b/pkg/kubelet/config/file.go index bb75fa53a42..cfa48470561 100644 --- a/pkg/kubelet/config/file.go +++ b/pkg/kubelet/config/file.go @@ -66,7 +66,7 @@ func (s *sourceFile) extractFromPath() error { return err } // Emit an update with an empty PodList to allow FileSource to be marked as seen - s.updates <- kubelet.PodUpdate{[]api.Pod{}, kubelet.SET, kubelet.FileSource} + s.updates <- kubelet.PodUpdate{[]*api.Pod{}, kubelet.SET, kubelet.FileSource} return fmt.Errorf("path does not exist, ignoring") } @@ -83,7 +83,7 @@ func (s *sourceFile) extractFromPath() error { if err != nil { return err } - s.updates <- kubelet.PodUpdate{[]api.Pod{pod}, kubelet.SET, kubelet.FileSource} + s.updates <- kubelet.PodUpdate{[]*api.Pod{pod}, kubelet.SET, kubelet.FileSource} default: return fmt.Errorf("path is not a directory or file") @@ -95,13 +95,13 @@ func (s *sourceFile) extractFromPath() error { // Get as many pod configs as we can from a directory. Return an error iff something // prevented us from reading anything at all. Do not return an error if only some files // were problematic. -func (s *sourceFile) extractFromDir(name string) ([]api.Pod, error) { +func (s *sourceFile) extractFromDir(name string) ([]*api.Pod, error) { dirents, err := filepath.Glob(filepath.Join(name, "[^.]*")) if err != nil { return nil, fmt.Errorf("glob failed: %v", err) } - pods := make([]api.Pod, 0) + pods := make([]*api.Pod, 0) if len(dirents) == 0 { return pods, nil } @@ -131,7 +131,7 @@ func (s *sourceFile) extractFromDir(name string) ([]api.Pod, error) { return pods, nil } -func (s *sourceFile) extractFromFile(filename string) (pod api.Pod, err error) { +func (s *sourceFile) extractFromFile(filename string) (pod *api.Pod, err error) { glog.V(3).Infof("Reading config file %q", filename) file, err := os.Open(filename) if err != nil { diff --git a/pkg/kubelet/config/file_test.go b/pkg/kubelet/config/file_test.go index 9ffa5608f3e..9871e47fb34 100644 --- a/pkg/kubelet/config/file_test.go +++ b/pkg/kubelet/config/file_test.go @@ -83,7 +83,7 @@ func TestReadFromFile(t *testing.T) { "id": "test", "containers": [{ "name": "image", "image": "test/image", "imagePullPolicy": "PullAlways"}] }`, - expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.Pod{ + expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "test-" + hostname, UID: "12345", @@ -109,7 +109,7 @@ func TestReadFromFile(t *testing.T) { "uuid": "12345", "containers": [{ "name": "image", "image": "test/image", "imagePullPolicy": "PullAlways"}] }`, - expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.Pod{ + expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "12345-" + hostname, UID: "12345", @@ -136,7 +136,7 @@ func TestReadFromFile(t *testing.T) { "id": "test", "containers": [{ "name": "image", "image": "test/image", "imagePullPolicy": "PullAlways"}] }`, - expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.Pod{ + expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "test-" + hostname, UID: "12345", @@ -169,7 +169,7 @@ func TestReadFromFile(t *testing.T) { } } }`, - expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.Pod{ + expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "test-" + hostname, UID: "12345", @@ -200,7 +200,7 @@ func TestReadFromFile(t *testing.T) { } } }`, - expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.Pod{ + expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "12345-" + hostname, UID: "12345", @@ -232,7 +232,7 @@ func TestReadFromFile(t *testing.T) { "containers": [{ "name": "image", "image": "test/image" }] } }`, - expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.Pod{ + expected: CreatePodUpdate(kubelet.SET, kubelet.FileSource, &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "test-" + hostname, UID: "12345", @@ -264,7 +264,7 @@ func TestReadFromFile(t *testing.T) { case got := <-ch: update := got.(kubelet.PodUpdate) for _, pod := range update.Pods { - if errs := validation.ValidatePod(&pod); len(errs) > 0 { + if errs := validation.ValidatePod(pod); len(errs) > 0 { t.Errorf("%s: Invalid pod %#v, %#v", testCase.desc, pod, errs) } } @@ -335,7 +335,7 @@ func TestExtractFromEmptyDir(t *testing.T) { } } -func ExampleManifestAndPod(id string) (v1beta1.ContainerManifest, api.Pod) { +func ExampleManifestAndPod(id string) (v1beta1.ContainerManifest, *api.Pod) { hostname := "an-example-host" manifest := v1beta1.ContainerManifest{ @@ -358,7 +358,7 @@ func ExampleManifestAndPod(id string) (v1beta1.ContainerManifest, api.Pod) { }, }, } - expectedPod := api.Pod{ + expectedPod := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: id + "-" + hostname, UID: types.UID(id), @@ -391,7 +391,7 @@ func TestExtractFromDir(t *testing.T) { manifest2, expectedPod2 := ExampleManifestAndPod("2") manifests := []v1beta1.ContainerManifest{manifest, manifest2} - pods := []api.Pod{expectedPod, expectedPod2} + pods := []*api.Pod{expectedPod, expectedPod2} files := make([]*os.File, len(manifests)) dirName, err := ioutil.TempDir("", "foo") @@ -433,9 +433,9 @@ func TestExtractFromDir(t *testing.T) { if !api.Semantic.DeepDerivative(expected, update) { t.Fatalf("Expected %#v, Got %#v", expected, update) } - for i := range update.Pods { - if errs := validation.ValidatePod(&update.Pods[i]); len(errs) != 0 { - t.Errorf("Expected no validation errors on %#v, Got %q", update.Pods[i], errs) + for _, pod := range update.Pods { + if errs := validation.ValidatePod(pod); len(errs) != 0 { + t.Errorf("Expected no validation errors on %#v, Got %q", pod, errs) } } } diff --git a/pkg/kubelet/config/http.go b/pkg/kubelet/config/http.go index 5ae1082efc3..e16efcfccce 100644 --- a/pkg/kubelet/config/http.go +++ b/pkg/kubelet/config/http.go @@ -74,7 +74,7 @@ func (s *sourceURL) extractFromURL() error { } if len(data) == 0 { // Emit an update with an empty PodList to allow HTTPSource to be marked as seen - s.updates <- kubelet.PodUpdate{[]api.Pod{}, kubelet.SET, kubelet.HTTPSource} + s.updates <- kubelet.PodUpdate{[]*api.Pod{}, kubelet.SET, kubelet.HTTPSource} return fmt.Errorf("zero-length data received from %v", s.url) } // Short circuit if the manifest has not changed since the last time it was read. @@ -91,12 +91,12 @@ func (s *sourceURL) extractFromURL() error { return singleErr } // It parsed! - s.updates <- kubelet.PodUpdate{[]api.Pod{pod}, kubelet.SET, kubelet.HTTPSource} + s.updates <- kubelet.PodUpdate{[]*api.Pod{pod}, kubelet.SET, kubelet.HTTPSource} return nil } // That didn't work, so try an array of manifests. - parsed, manifests, pods, multiErr := tryDecodeManifestList(data, s.applyDefaults) + parsed, manifests, podList, multiErr := tryDecodeManifestList(data, s.applyDefaults) if parsed { if multiErr != nil { // It parsed but could not be used. @@ -110,7 +110,11 @@ func (s *sourceURL) extractFromURL() error { return singleErr } // It parsed! - s.updates <- kubelet.PodUpdate{pods.Items, kubelet.SET, kubelet.HTTPSource} + pods := make([]*api.Pod, 0) + for i := range podList.Items { + pods = append(pods, &podList.Items[i]) + } + s.updates <- kubelet.PodUpdate{pods, kubelet.SET, kubelet.HTTPSource} return nil } @@ -124,18 +128,22 @@ func (s *sourceURL) extractFromURL() error { // It parsed but could not be used. return singlePodErr } - s.updates <- kubelet.PodUpdate{[]api.Pod{pod}, kubelet.SET, kubelet.HTTPSource} + s.updates <- kubelet.PodUpdate{[]*api.Pod{pod}, kubelet.SET, kubelet.HTTPSource} return nil } // That didn't work, so try a list of pods. - parsed, pods, multiPodErr := tryDecodePodList(data, s.applyDefaults) + parsed, podList, multiPodErr := tryDecodePodList(data, s.applyDefaults) if parsed { if multiPodErr != nil { // It parsed but could not be used. return multiPodErr } - s.updates <- kubelet.PodUpdate{pods.Items, kubelet.SET, kubelet.HTTPSource} + pods := make([]*api.Pod, 0) + for i := range podList.Items { + pods = append(pods, &podList.Items[i]) + } + s.updates <- kubelet.PodUpdate{pods, kubelet.SET, kubelet.HTTPSource} return nil } diff --git a/pkg/kubelet/config/http_test.go b/pkg/kubelet/config/http_test.go index 0032f14625e..0db1c826c7b 100644 --- a/pkg/kubelet/config/http_test.go +++ b/pkg/kubelet/config/http_test.go @@ -130,7 +130,7 @@ func TestExtractManifestFromHTTP(t *testing.T) { Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1beta1.PullAlways}}}, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo" + "-" + hostname, @@ -155,7 +155,7 @@ func TestExtractManifestFromHTTP(t *testing.T) { Containers: []v1beta1.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}}, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "111" + "-" + hostname, @@ -180,7 +180,7 @@ func TestExtractManifestFromHTTP(t *testing.T) { Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1beta1.PullAlways}}}, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo" + "-" + hostname, @@ -209,7 +209,7 @@ func TestExtractManifestFromHTTP(t *testing.T) { }, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo" + "-" + hostname, @@ -227,7 +227,7 @@ func TestExtractManifestFromHTTP(t *testing.T) { ImagePullPolicy: "Always"}}, }, }, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "222", Name: "bar" + "-" + hostname, @@ -283,9 +283,9 @@ func TestExtractManifestFromHTTP(t *testing.T) { if !api.Semantic.DeepEqual(testCase.expected, update) { t.Errorf("%s: Expected: %#v, Got: %#v", testCase.desc, testCase.expected, update) } - for i := range update.Pods { - if errs := validation.ValidatePod(&update.Pods[i]); len(errs) != 0 { - t.Errorf("%s: Expected no validation errors on %#v, Got %v", testCase.desc, update.Pods[i], errors.NewAggregate(errs)) + for _, pod := range update.Pods { + if errs := validation.ValidatePod(pod); len(errs) != 0 { + t.Errorf("%s: Expected no validation errors on %#v, Got %v", testCase.desc, pod, errors.NewAggregate(errs)) } } } @@ -317,7 +317,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { }, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo" + "-" + hostname, @@ -355,7 +355,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { }, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo" + "-" + hostname, @@ -406,7 +406,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { }, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo" + "-" + hostname, @@ -424,7 +424,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { ImagePullPolicy: "Always"}}, }, }, - api.Pod{ + &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "222", Name: "bar" + "-" + hostname, @@ -472,9 +472,9 @@ func TestExtractPodsFromHTTP(t *testing.T) { if !api.Semantic.DeepEqual(testCase.expected, update) { t.Errorf("%s: Expected: %#v, Got: %#v", testCase.desc, testCase.expected, update) } - for i := range update.Pods { - if errs := validation.ValidatePod(&update.Pods[i]); len(errs) != 0 { - t.Errorf("%s: Expected no validation errors on %#v, Got %v", testCase.desc, update.Pods[i], errors.NewAggregate(errs)) + for _, pod := range update.Pods { + if errs := validation.ValidatePod(pod); len(errs) != 0 { + t.Errorf("%s: Expected no validation errors on %#v, Got %v", testCase.desc, pod, errors.NewAggregate(errs)) } } } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index b5629b3ceff..86848acdd1c 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -91,7 +91,7 @@ type SyncHandler interface { // Syncs current state to match the specified pods. SyncPodType specified what // type of sync is occuring per pod. StartTime specifies the time at which // syncing began (for use in monitoring). - SyncPods(pods []api.Pod, podSyncTypes map[types.UID]metrics.SyncPodType, mirrorPods map[string]api.Pod, + SyncPods(pods []*api.Pod, podSyncTypes map[types.UID]metrics.SyncPodType, mirrorPods map[string]api.Pod, startTime time.Time) error } @@ -1319,7 +1319,7 @@ func (kl *Kubelet) syncPod(pod *api.Pod, mirrorPod *api.Pod, runningPod kubecont // Stores all volumes defined by the set of pods into a map. // Keys for each entry are in the format (POD_ID)/(VOLUME_NAME) -func getDesiredVolumes(pods []api.Pod) map[string]api.Volume { +func getDesiredVolumes(pods []*api.Pod) map[string]api.Volume { desiredVolumes := make(map[string]api.Volume) for _, pod := range pods { for _, volume := range pod.Spec.Volumes { @@ -1330,10 +1330,10 @@ func getDesiredVolumes(pods []api.Pod) map[string]api.Volume { return desiredVolumes } -func (kl *Kubelet) cleanupOrphanedPods(pods []api.Pod) error { +func (kl *Kubelet) cleanupOrphanedPods(pods []*api.Pod) error { desired := util.NewStringSet() - for i := range pods { - desired.Insert(string(pods[i].UID)) + for _, pod := range pods { + desired.Insert(string(pod.UID)) } found, err := kl.listPodsFromDisk() if err != nil { @@ -1353,7 +1353,7 @@ func (kl *Kubelet) cleanupOrphanedPods(pods []api.Pod) error { // Compares the map of current volumes to the map of desired volumes. // If an active volume does not have a respective desired volume, clean it up. -func (kl *Kubelet) cleanupOrphanedVolumes(pods []api.Pod, running []*docker.Container) error { +func (kl *Kubelet) cleanupOrphanedVolumes(pods []*api.Pod, running []*docker.Container) error { desiredVolumes := getDesiredVolumes(pods) currentVolumes := kl.getPodVolumesFromDisk() runningSet := util.StringSet{} @@ -1388,7 +1388,7 @@ func (kl *Kubelet) cleanupOrphanedVolumes(pods []api.Pod, running []*docker.Cont } // SyncPods synchronizes the configured list of pods (desired state) with the host current state. -func (kl *Kubelet) SyncPods(allPods []api.Pod, podSyncTypes map[types.UID]metrics.SyncPodType, +func (kl *Kubelet) SyncPods(allPods []*api.Pod, podSyncTypes map[types.UID]metrics.SyncPodType, mirrorPods map[string]api.Pod, start time.Time) error { defer func() { metrics.SyncPodsLatency.Observe(metrics.SinceInMicroseconds(start)) @@ -1397,15 +1397,15 @@ func (kl *Kubelet) SyncPods(allPods []api.Pod, podSyncTypes map[types.UID]metric // Remove obsolete entries in podStatus where the pod is no longer considered bound to this node. podFullNames := make(map[string]bool) for _, pod := range allPods { - podFullNames[kubecontainer.GetPodFullName(&pod)] = true + podFullNames[kubecontainer.GetPodFullName(pod)] = true } kl.statusManager.RemoveOrphanedStatuses(podFullNames) // Filter out the rejected pod. They don't have running containers. kl.handleNotFittingPods(allPods) - var pods []api.Pod + var pods []*api.Pod for _, pod := range allPods { - status, ok := kl.statusManager.GetPodStatus(kubecontainer.GetPodFullName(&pod)) + status, ok := kl.statusManager.GetPodStatus(kubecontainer.GetPodFullName(pod)) if ok && status.Phase == api.PodFailed { continue } @@ -1423,8 +1423,7 @@ func (kl *Kubelet) SyncPods(allPods []api.Pod, podSyncTypes map[types.UID]metric } // Check for any containers that need starting - for ix := range pods { - pod := &pods[ix] + for _, pod := range pods { podFullName := kubecontainer.GetPodFullName(pod) uid := pod.UID desiredPods[uid] = empty{} @@ -1504,7 +1503,7 @@ func (kl *Kubelet) SyncPods(allPods []api.Pod, podSyncTypes map[types.UID]metric return err } -type podsByCreationTime []api.Pod +type podsByCreationTime []*api.Pod func (s podsByCreationTime) Len() int { return len(s) @@ -1519,31 +1518,30 @@ func (s podsByCreationTime) Less(i, j int) bool { } // checkHostPortConflicts detects pods with conflicted host ports. -func checkHostPortConflicts(pods []api.Pod) (fitting []api.Pod, notFitting []api.Pod) { +func checkHostPortConflicts(pods []*api.Pod) (fitting []*api.Pod, notFitting []*api.Pod) { ports := map[int]bool{} extract := func(p *api.ContainerPort) int { return p.HostPort } // Respect the pod creation order when resolving conflicts. sort.Sort(podsByCreationTime(pods)) - for i := range pods { - pod := &pods[i] + for _, pod := range pods { if errs := validation.AccumulateUniquePorts(pod.Spec.Containers, ports, extract); len(errs) != 0 { glog.Errorf("Pod %q: HostPort is already allocated, ignoring: %v", kubecontainer.GetPodFullName(pod), errs) - notFitting = append(notFitting, *pod) + notFitting = append(notFitting, pod) continue } - fitting = append(fitting, *pod) + fitting = append(fitting, pod) } return } // checkCapacityExceeded detects pods that exceeds node's resources. -func (kl *Kubelet) checkCapacityExceeded(pods []api.Pod) (fitting []api.Pod, notFitting []api.Pod) { +func (kl *Kubelet) checkCapacityExceeded(pods []*api.Pod) (fitting []*api.Pod, notFitting []*api.Pod) { info, err := kl.GetCachedMachineInfo() if err != nil { glog.Errorf("error getting machine info: %v", err) - return pods, []api.Pod{} + return pods, nil } // Respect the pod creation order when resolving conflicts. @@ -1554,14 +1552,14 @@ func (kl *Kubelet) checkCapacityExceeded(pods []api.Pod) (fitting []api.Pod, not } // checkNodeSelectorMatching detects pods that do not match node's labels. -func (kl *Kubelet) checkNodeSelectorMatching(pods []api.Pod) (fitting []api.Pod, notFitting []api.Pod) { +func (kl *Kubelet) checkNodeSelectorMatching(pods []*api.Pod) (fitting []*api.Pod, notFitting []*api.Pod) { node, err := kl.GetNode() if err != nil { glog.Errorf("error getting node: %v", err) - return pods, []api.Pod{} + return pods, nil } for _, pod := range pods { - if !scheduler.PodMatchesNodeLabels(&pod, node) { + if !scheduler.PodMatchesNodeLabels(pod, node) { notFitting = append(notFitting, pod) continue } @@ -1572,25 +1570,25 @@ func (kl *Kubelet) checkNodeSelectorMatching(pods []api.Pod) (fitting []api.Pod, // handleNotfittingPods handles pods that do not fit on the node. // Currently conflicts on Port.HostPort values, matching node's labels and exceeding node's capacity are handled. -func (kl *Kubelet) handleNotFittingPods(pods []api.Pod) { +func (kl *Kubelet) handleNotFittingPods(pods []*api.Pod) { fitting, notFitting := checkHostPortConflicts(pods) for _, pod := range notFitting { - kl.recorder.Eventf(&pod, "hostPortConflict", "Cannot start the pod due to host port conflict.") - kl.statusManager.SetPodStatus(&pod, api.PodStatus{ + kl.recorder.Eventf(pod, "hostPortConflict", "Cannot start the pod due to host port conflict.") + kl.statusManager.SetPodStatus(pod, api.PodStatus{ Phase: api.PodFailed, Message: "Pod cannot be started due to host port conflict"}) } fitting, notFitting = kl.checkNodeSelectorMatching(fitting) for _, pod := range notFitting { - kl.recorder.Eventf(&pod, "nodeSelectorMismatching", "Cannot start the pod due to node selector mismatch.") - kl.statusManager.SetPodStatus(&pod, api.PodStatus{ + kl.recorder.Eventf(pod, "nodeSelectorMismatching", "Cannot start the pod due to node selector mismatch.") + kl.statusManager.SetPodStatus(pod, api.PodStatus{ Phase: api.PodFailed, Message: "Pod cannot be started due to node selector mismatch"}) } fitting, notFitting = kl.checkCapacityExceeded(fitting) for _, pod := range notFitting { - kl.recorder.Eventf(&pod, "capacityExceeded", "Cannot start the pod due to exceeded capacity.") - kl.statusManager.SetPodStatus(&pod, api.PodStatus{ + kl.recorder.Eventf(pod, "capacityExceeded", "Cannot start the pod due to exceeded capacity.") + kl.statusManager.SetPodStatus(pod, api.PodStatus{ Phase: api.PodFailed, Message: "Pod cannot be started due to exceeded capacity"}) } @@ -1716,7 +1714,7 @@ func (kl *Kubelet) GetHostIP() (net.IP, error) { // GetPods returns all pods bound to the kubelet and their spec, and the mirror // pods. -func (kl *Kubelet) GetPods() []api.Pod { +func (kl *Kubelet) GetPods() []*api.Pod { return kl.podManager.GetPods() } diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 7a56906a333..494b59d49e3 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -459,7 +459,7 @@ func TestSyncPodsDoesNothing(t *testing.T) { waitGroup := testKubelet.waitGroup container := api.Container{Name: "bar"} - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -482,7 +482,7 @@ func TestSyncPodsDoesNothing(t *testing.T) { }, { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo_new_12345678_0"}, ID: "9876", }, } @@ -527,7 +527,7 @@ func TestSyncPodsWithTerminationLog(t *testing.T) { TerminationMessagePath: "/dev/somepath", } fakeDocker.ContainerList = []docker.APIContainers{} - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -586,7 +586,7 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) { waitGroup := testKubelet.waitGroup kubelet.containerManager.PodInfraContainerImage = "custom_image_name" fakeDocker.ContainerList = []docker.APIContainers{} - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -649,7 +649,7 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) { puller.HasImages = []string{} kubelet.containerManager.PodInfraContainerImage = "custom_image_name" fakeDocker.ContainerList = []docker.APIContainers{} - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -702,7 +702,7 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) { kubelet := testKubelet.kubelet fakeDocker := testKubelet.fakeDocker waitGroup := testKubelet.waitGroup - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -719,7 +719,7 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo_new_12345678_0"}, ID: "9876", }, } @@ -765,7 +765,7 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) { waitGroup := testKubelet.waitGroup fakeHttp := fakeHTTP{} kubelet.httpClient = &fakeHttp - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -793,7 +793,7 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo_new_12345678_0"}, ID: "9876", }, } @@ -841,7 +841,7 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) { fakeDocker := testKubelet.fakeDocker waitGroup := testKubelet.waitGroup - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -880,7 +880,7 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) { }, { // format is // k8s___ - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo2_new_87654321_0"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo2_new_87654321_0"}, ID: "8765", }, } @@ -966,7 +966,7 @@ func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) { ID: "9876", }, } - if err := kubelet.SyncPods([]api.Pod{}, emptyPodUIDs, map[string]api.Pod{}, time.Now()); err != nil { + if err := kubelet.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]api.Pod{}, time.Now()); err != nil { t.Errorf("unexpected error: %v", err) } // Validate nothing happened. @@ -974,7 +974,7 @@ func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) { fakeDocker.ClearCalls() ready = true - if err := kubelet.SyncPods([]api.Pod{}, emptyPodUIDs, map[string]api.Pod{}, time.Now()); err != nil { + if err := kubelet.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]api.Pod{}, time.Now()); err != nil { t.Errorf("unexpected error: %v", err) } verifyCalls(t, fakeDocker, []string{"list", "stop", "stop", "inspect_container", "inspect_container"}) @@ -1013,7 +1013,7 @@ func TestSyncPodsDeletes(t *testing.T) { ID: "4567", }, } - err := kubelet.SyncPods([]api.Pod{}, emptyPodUIDs, map[string]api.Pod{}, time.Now()) + err := kubelet.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]api.Pod{}, time.Now()) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1040,7 +1040,7 @@ func TestSyncPodsDeletesDuplicate(t *testing.T) { fakeDocker := testKubelet.fakeDocker waitGroup := testKubelet.waitGroup - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -1063,7 +1063,7 @@ func TestSyncPodsDeletesDuplicate(t *testing.T) { }, { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_bar_new_12345678_2222"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_bar_new_12345678_2222"}, ID: "9876", }, { @@ -1121,7 +1121,7 @@ func TestSyncPodsBadHash(t *testing.T) { fakeDocker := testKubelet.fakeDocker waitGroup := testKubelet.waitGroup - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -1144,7 +1144,7 @@ func TestSyncPodsBadHash(t *testing.T) { }, { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_42"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo_new_12345678_42"}, ID: "9876", }, } @@ -1192,7 +1192,7 @@ func TestSyncPodsUnhealthy(t *testing.T) { fakeDocker := testKubelet.fakeDocker waitGroup := testKubelet.waitGroup - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -1219,7 +1219,7 @@ func TestSyncPodsUnhealthy(t *testing.T) { }, { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_42"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo_new_12345678_42"}, ID: "9876", }, } @@ -1808,7 +1808,7 @@ func TestSyncPodEventHandlerFails(t *testing.T) { err: fmt.Errorf("test error"), } - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -1836,7 +1836,7 @@ func TestSyncPodEventHandlerFails(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_42"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo_new_12345678_42"}, ID: "9876", }, } @@ -1892,7 +1892,7 @@ func TestSyncPodsWithPullPolicy(t *testing.T) { kubelet.containerManager.PodInfraContainerImage = "custom_image_name" fakeDocker.ContainerList = []docker.APIContainers{} - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -3005,7 +3005,7 @@ func TestPortForward(t *testing.T) { // Tests that identify the host port conflicts are detected correctly. func TestGetHostPortConflicts(t *testing.T) { - pods := []api.Pod{ + pods := []*api.Pod{ {Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.ContainerPort{{HostPort: 80}}}}}}, {Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.ContainerPort{{HostPort: 81}}}}}}, {Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.ContainerPort{{HostPort: 82}}}}}}, @@ -3018,11 +3018,11 @@ func TestGetHostPortConflicts(t *testing.T) { } // The new pod should cause conflict and be reported. - expected := api.Pod{ + expected := &api.Pod{ Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.ContainerPort{{HostPort: 81}}}}}, } pods = append(pods, expected) - if _, actual := checkHostPortConflicts(pods); !reflect.DeepEqual(actual, []api.Pod{expected}) { + if _, actual := checkHostPortConflicts(pods); !reflect.DeepEqual(actual, []*api.Pod{expected}) { t.Errorf("expected %#v, Got %#v", expected, actual) } } @@ -3034,7 +3034,7 @@ func TestHandlePortConflicts(t *testing.T) { testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) spec := api.PodSpec{Containers: []api.Container{{Ports: []api.ContainerPort{{HostPort: 80}}}}} - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "123456789", @@ -3056,7 +3056,7 @@ func TestHandlePortConflicts(t *testing.T) { pods[1].CreationTimestamp = util.NewTime(time.Now()) pods[0].CreationTimestamp = util.NewTime(time.Now().Add(1 * time.Second)) // The newer pod should be rejected. - conflictedPodName := kubecontainer.GetPodFullName(&pods[0]) + conflictedPodName := kubecontainer.GetPodFullName(pods[0]) kl.handleNotFittingPods(pods) // Check pod status stored in the status map. @@ -3087,7 +3087,7 @@ func TestHandleNodeSelector(t *testing.T) { {ObjectMeta: api.ObjectMeta{Name: "testnode", Labels: map[string]string{"key": "B"}}}, }} testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "123456789", @@ -3106,7 +3106,7 @@ func TestHandleNodeSelector(t *testing.T) { }, } // The first pod should be rejected. - notfittingPodName := kubecontainer.GetPodFullName(&pods[0]) + notfittingPodName := kubecontainer.GetPodFullName(pods[0]) kl.handleNotFittingPods(pods) // Check pod status stored in the status map. @@ -3140,7 +3140,7 @@ func TestHandleMemExceeded(t *testing.T) { "memory": resource.MustParse("90"), }, }}}} - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "123456789", @@ -3162,7 +3162,7 @@ func TestHandleMemExceeded(t *testing.T) { pods[1].CreationTimestamp = util.NewTime(time.Now()) pods[0].CreationTimestamp = util.NewTime(time.Now().Add(1 * time.Second)) // The newer pod should be rejected. - notfittingPodName := kubecontainer.GetPodFullName(&pods[0]) + notfittingPodName := kubecontainer.GetPodFullName(pods[0]) kl.handleNotFittingPods(pods) // Check pod status stored in the status map. @@ -3191,7 +3191,7 @@ func TestPurgingObsoleteStatusMapEntries(t *testing.T) { testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) kl := testKubelet.kubelet - pods := []api.Pod{ + pods := []*api.Pod{ {ObjectMeta: api.ObjectMeta{Name: "pod1"}, Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.ContainerPort{{HostPort: 80}}}}}}, {ObjectMeta: api.ObjectMeta{Name: "pod2"}, Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.ContainerPort{{HostPort: 80}}}}}}, } @@ -3201,7 +3201,7 @@ func TestPurgingObsoleteStatusMapEntries(t *testing.T) { t.Fatalf("expected to have status cached for %q: %v", "pod2", err) } // Sync with empty pods so that the entry in status map will be removed. - kl.SyncPods([]api.Pod{}, emptyPodUIDs, map[string]api.Pod{}, time.Now()) + kl.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]api.Pod{}, time.Now()) if _, err := kl.GetPodStatus(kubecontainer.BuildPodFullName("pod2", "")); err == nil { t.Fatalf("expected to not have status cached for %q: %v", "pod2", err) } @@ -3483,7 +3483,7 @@ func TestCreateMirrorPod(t *testing.T) { testKubelet := newTestKubelet(t) kl := testKubelet.kubelet manager := testKubelet.fakeMirrorClient - pod := api.Pod{ + pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "12345678", Name: "bar", @@ -3493,13 +3493,13 @@ func TestCreateMirrorPod(t *testing.T) { }, }, } - pods := []api.Pod{pod} + pods := []*api.Pod{pod} kl.podManager.SetPods(pods) - err := kl.syncPod(&pod, nil, container.Pod{}) + err := kl.syncPod(pod, nil, container.Pod{}) if err != nil { t.Errorf("unexpected error: %v", err) } - podFullName := kubecontainer.GetPodFullName(&pod) + podFullName := kubecontainer.GetPodFullName(pod) if !manager.HasPod(podFullName) { t.Errorf("expected mirror pod %q to be created", podFullName) } @@ -3513,7 +3513,7 @@ func TestDeleteOutdatedMirrorPod(t *testing.T) { testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) kl := testKubelet.kubelet manager := testKubelet.fakeMirrorClient - pod := api.Pod{ + pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "12345678", Name: "foo", @@ -3529,7 +3529,7 @@ func TestDeleteOutdatedMirrorPod(t *testing.T) { }, } // Mirror pod has an outdated spec. - mirrorPod := api.Pod{ + mirrorPod := &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "11111111", Name: "foo", @@ -3546,13 +3546,13 @@ func TestDeleteOutdatedMirrorPod(t *testing.T) { }, } - pods := []api.Pod{pod, mirrorPod} + pods := []*api.Pod{pod, mirrorPod} kl.podManager.SetPods(pods) - err := kl.syncPod(&pod, &mirrorPod, container.Pod{}) + err := kl.syncPod(pod, mirrorPod, container.Pod{}) if err != nil { t.Errorf("unexpected error: %v", err) } - name := kubecontainer.GetPodFullName(&pod) + name := kubecontainer.GetPodFullName(pod) creates, deletes := manager.GetCounts(name) if creates != 0 || deletes != 1 { t.Errorf("expected 0 creation and 1 deletion of %q, got %d, %d", name, creates, deletes) @@ -3564,7 +3564,7 @@ func TestDeleteOrphanedMirrorPods(t *testing.T) { testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) kl := testKubelet.kubelet manager := testKubelet.fakeMirrorClient - orphanPods := []api.Pod{ + orphanPods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -3600,7 +3600,7 @@ func TestDeleteOrphanedMirrorPods(t *testing.T) { t.Errorf("expected zero mirror pods, got %v", manager.GetPods()) } for _, pod := range orphanPods { - name := kubecontainer.GetPodFullName(&pod) + name := kubecontainer.GetPodFullName(pod) creates, deletes := manager.GetCounts(name) if creates != 0 || deletes != 1 { t.Errorf("expected 0 creation and one deletion of %q, got %d, %d", name, creates, deletes) @@ -3611,7 +3611,7 @@ func TestDeleteOrphanedMirrorPods(t *testing.T) { func TestGetContainerInfoForMirrorPods(t *testing.T) { // pods contain one static and one mirror pod with the same name but // different UIDs. - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "1234", @@ -3685,7 +3685,7 @@ func TestDoNotCacheStatusForStaticPods(t *testing.T) { kubelet := testKubelet.kubelet waitGroup := testKubelet.waitGroup - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -3709,7 +3709,7 @@ func TestDoNotCacheStatusForStaticPods(t *testing.T) { t.Errorf("unexpected error: %v", err) } waitGroup.Wait() - podFullName := kubecontainer.GetPodFullName(&pods[0]) + podFullName := kubecontainer.GetPodFullName(pods[0]) status, ok := kubelet.statusManager.GetPodStatus(podFullName) if ok { t.Errorf("unexpected status %#v found for static pod %q", status, podFullName) @@ -3739,7 +3739,7 @@ func TestHostNetworkAllowed(t *testing.T) { HostNetwork: true, }, } - kubelet.podManager.SetPods([]api.Pod{*pod}) + kubelet.podManager.SetPods([]*api.Pod{pod}) err := kubelet.syncPod(pod, nil, container.Pod{}) if err != nil { t.Errorf("expected pod infra creation to succeed: %v", err) @@ -3786,7 +3786,7 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) { {Name: "succeeded"}, {Name: "failed"}, } - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -3802,7 +3802,7 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) { runningAPIContainers := []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo_new_12345678_0"}, ID: "9876", }, } @@ -4019,7 +4019,7 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { fakeDocker.ExitedContainerList = exitedAPIContainers fakeDocker.ContainerMap = containerMap fakeDocker.ClearCalls() - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -4035,7 +4035,7 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { fakeDocker.ContainerList = []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_foo_new_12345678_0"}, ID: "9876", }, } @@ -4048,7 +4048,7 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { waitGroup.Wait() // Check if we can retrieve the pod status from GetPodStatus(). - podName := kubecontainer.GetPodFullName(&pods[0]) + podName := kubecontainer.GetPodFullName(pods[0]) status, err := kubelet.GetPodStatus(podName) if err != nil { t.Fatalf("unable to retrieve pod status for pod %q: %#v.", podName, err) @@ -4084,7 +4084,7 @@ func TestGetPodCreationFailureReason(t *testing.T) { "create": fmt.Errorf("%s", failureReason), } fakeDocker.ContainerList = []docker.APIContainers{} - pod := api.Pod{ + pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "12345678", Name: "bar", @@ -4096,13 +4096,13 @@ func TestGetPodCreationFailureReason(t *testing.T) { }, }, } - pods := []api.Pod{pod} + pods := []*api.Pod{pod} kubelet.podManager.SetPods(pods) - _, err := kubelet.runContainer(&pod, &pod.Spec.Containers[0], make(map[string]volume.Volume), "", "") + _, err := kubelet.runContainer(pod, &pod.Spec.Containers[0], make(map[string]volume.Volume), "", "") if err == nil { t.Errorf("expected error, found nil") } - status, err := kubelet.GetPodStatus(kubecontainer.GetPodFullName(&pod)) + status, err := kubelet.GetPodStatus(kubecontainer.GetPodFullName(pod)) if err != nil { t.Errorf("unexpected error %v", err) } diff --git a/pkg/kubelet/pod_manager.go b/pkg/kubelet/pod_manager.go index 11658998150..7bdd2909117 100644 --- a/pkg/kubelet/pod_manager.go +++ b/pkg/kubelet/pod_manager.go @@ -43,11 +43,11 @@ import ( // also be removed. type podManager interface { - GetPods() []api.Pod + GetPods() []*api.Pod GetPodByFullName(podFullName string) (*api.Pod, bool) GetPodByName(namespace, name string) (*api.Pod, bool) - GetPodsAndMirrorMap() ([]api.Pod, map[string]api.Pod) - SetPods(pods []api.Pod) + GetPodsAndMirrorMap() ([]*api.Pod, map[string]api.Pod) + SetPods(pods []*api.Pod) UpdatePods(u PodUpdate, podSyncTypes map[types.UID]metrics.SyncPodType) DeleteOrphanedMirrorPods() TranslatePodUID(uid types.UID) types.UID @@ -78,7 +78,7 @@ type basicPodManager struct { func newBasicPodManager(apiserverClient client.Interface) *basicPodManager { pm := &basicPodManager{} pm.mirrorClient = newBasicMirrorClient(apiserverClient) - pm.SetPods([]api.Pod{}) + pm.SetPods(nil) return pm } @@ -127,27 +127,26 @@ func (self *basicPodManager) UpdatePods(u PodUpdate, podSyncTypes map[types.UID] } // Set the internal pods based on the new pods. -func (self *basicPodManager) SetPods(newPods []api.Pod) { +func (self *basicPodManager) SetPods(newPods []*api.Pod) { self.lock.Lock() defer self.lock.Unlock() self.setPods(newPods) } -func (self *basicPodManager) setPods(newPods []api.Pod) { +func (self *basicPodManager) setPods(newPods []*api.Pod) { podByUID := make(map[types.UID]*api.Pod) mirrorPodByUID := make(map[types.UID]*api.Pod) podByFullName := make(map[string]*api.Pod) mirrorPodByFullName := make(map[string]*api.Pod) - for i := range newPods { - pod := newPods[i] - podFullName := kubecontainer.GetPodFullName(&pod) - if isMirrorPod(&pod) { - mirrorPodByUID[pod.UID] = &pod - mirrorPodByFullName[podFullName] = &pod + for _, pod := range newPods { + podFullName := kubecontainer.GetPodFullName(pod) + if isMirrorPod(pod) { + mirrorPodByUID[pod.UID] = pod + mirrorPodByFullName[podFullName] = pod } else { - podByUID[pod.UID] = &pod - podByFullName[podFullName] = &pod + podByUID[pod.UID] = pod + podByFullName[podFullName] = pod } } @@ -157,21 +156,19 @@ func (self *basicPodManager) setPods(newPods []api.Pod) { self.mirrorPodByFullName = mirrorPodByFullName } -func applyUpdates(changed []api.Pod, current []api.Pod) []api.Pod { - updated := []api.Pod{} +func applyUpdates(changed []*api.Pod, current []*api.Pod) []*api.Pod { + updated := []*api.Pod{} m := map[types.UID]*api.Pod{} - for i := range changed { - pod := &changed[i] + for _, pod := range changed { m[pod.UID] = pod } - for i := range current { - pod := ¤t[i] + for _, pod := range current { if m[pod.UID] != nil { - updated = append(updated, *m[pod.UID]) + updated = append(updated, m[pod.UID]) glog.V(4).Infof("pod with UID: %q has a new spec %+v", pod.UID, *m[pod.UID]) } else { - updated = append(updated, *pod) + updated = append(updated, pod) glog.V(4).Infof("pod with UID: %q stay with the same spec %+v", pod.UID, *pod) } } @@ -180,20 +177,20 @@ func applyUpdates(changed []api.Pod, current []api.Pod) []api.Pod { } // GetPods returns the regular pods bound to the kubelet and their spec. -func (self *basicPodManager) GetPods() []api.Pod { +func (self *basicPodManager) GetPods() []*api.Pod { self.lock.RLock() defer self.lock.RUnlock() return podsMapToPods(self.podByUID) } // Returns all pods (including mirror pods). -func (self *basicPodManager) getAllPods() []api.Pod { +func (self *basicPodManager) getAllPods() []*api.Pod { return append(podsMapToPods(self.podByUID), podsMapToPods(self.mirrorPodByUID)...) } // GetPodsAndMirrorMap returns the a copy of the regular pods and the mirror // pods indexed by full name. -func (self *basicPodManager) GetPodsAndMirrorMap() ([]api.Pod, map[string]api.Pod) { +func (self *basicPodManager) GetPodsAndMirrorMap() ([]*api.Pod, map[string]api.Pod) { self.lock.RLock() defer self.lock.RUnlock() mirrorPods := make(map[string]api.Pod) @@ -270,10 +267,10 @@ func (self *basicPodManager) IsMirrorPodOf(mirrorPod, pod *api.Pod) bool { return api.Semantic.DeepEqual(&pod.Spec, &mirrorPod.Spec) } -func podsMapToPods(UIDMap map[types.UID]*api.Pod) []api.Pod { - pods := make([]api.Pod, 0, len(UIDMap)) +func podsMapToPods(UIDMap map[types.UID]*api.Pod) []*api.Pod { + pods := make([]*api.Pod, 0, len(UIDMap)) for _, pod := range UIDMap { - pods = append(pods, *pod) + pods = append(pods, pod) } return pods } diff --git a/pkg/kubelet/pod_manager_test.go b/pkg/kubelet/pod_manager_test.go index 1e4c88b64b6..90fbdee50be 100644 --- a/pkg/kubelet/pod_manager_test.go +++ b/pkg/kubelet/pod_manager_test.go @@ -34,7 +34,7 @@ func newFakePodManager() (*basicPodManager, *fakeMirrorClient) { // Tests that pods/maps are properly set after the pod update, and the basic // methods work correctly. func TestGetSetPods(t *testing.T) { - mirrorPod := api.Pod{ + mirrorPod := &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "987654321", Name: "bar", @@ -45,7 +45,7 @@ func TestGetSetPods(t *testing.T) { }, }, } - staticPod := api.Pod{ + staticPod := &api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "123456789", Name: "bar", @@ -54,7 +54,7 @@ func TestGetSetPods(t *testing.T) { }, } - expectedPods := []api.Pod{ + expectedPods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "999999999", @@ -98,11 +98,11 @@ func TestGetSetPods(t *testing.T) { // Test the basic Get methods. actualPod, ok := podManager.GetPodByFullName("bar_default") - if !ok || !reflect.DeepEqual(actualPod, &staticPod) { + if !ok || !reflect.DeepEqual(actualPod, staticPod) { t.Errorf("unable to get pod by full name; expected: %#v, got: %#v", staticPod, actualPod) } actualPod, ok = podManager.GetPodByName("default", "bar") - if !ok || !reflect.DeepEqual(actualPod, &staticPod) { + if !ok || !reflect.DeepEqual(actualPod, staticPod) { t.Errorf("unable to get pod by name; expected: %#v, got: %#v", staticPod, actualPod) } diff --git a/pkg/kubelet/runonce.go b/pkg/kubelet/runonce.go index 67f53de042e..f040c5faa62 100644 --- a/pkg/kubelet/runonce.go +++ b/pkg/kubelet/runonce.go @@ -51,16 +51,15 @@ func (kl *Kubelet) RunOnce(updates <-chan PodUpdate) ([]RunPodResult, error) { } // runOnce runs a given set of pods and returns their status. -func (kl *Kubelet) runOnce(pods []api.Pod, retryDelay time.Duration) (results []RunPodResult, err error) { +func (kl *Kubelet) runOnce(pods []*api.Pod, retryDelay time.Duration) (results []RunPodResult, err error) { kl.handleNotFittingPods(pods) ch := make(chan RunPodResult) - for i := range pods { - pod := pods[i] // Make a copy - go func() { + for _, pod := range pods { + go func(pod *api.Pod) { err := kl.runPod(pod, retryDelay) - ch <- RunPodResult{&pod, err} - }() + ch <- RunPodResult{pod, err} + }(pod) } glog.Infof("waiting for %d pods", len(pods)) @@ -84,7 +83,7 @@ func (kl *Kubelet) runOnce(pods []api.Pod, retryDelay time.Duration) (results [] } // runPod runs a single pod and wait until all containers are running. -func (kl *Kubelet) runPod(pod api.Pod, retryDelay time.Duration) error { +func (kl *Kubelet) runPod(pod *api.Pod, retryDelay time.Duration) error { delay := retryDelay retry := 0 for { @@ -104,7 +103,7 @@ func (kl *Kubelet) runPod(pod api.Pod, retryDelay time.Duration) error { glog.Infof("pod %q containers not running: syncing", pod.Name) // We don't create mirror pods in this mode; pass a dummy boolean value // to sycnPod. - if err = kl.syncPod(&pod, nil, p); err != nil { + if err = kl.syncPod(pod, nil, p); err != nil { return fmt.Errorf("error syncing pod: %v", err) } if retry >= RunOnceMaxRetries { @@ -119,7 +118,7 @@ func (kl *Kubelet) runPod(pod api.Pod, retryDelay time.Duration) error { } // isPodRunning returns true if all containers of a manifest are running. -func (kl *Kubelet) isPodRunning(pod api.Pod, runningPod container.Pod) (bool, error) { +func (kl *Kubelet) isPodRunning(pod *api.Pod, runningPod container.Pod) (bool, error) { for _, container := range pod.Spec.Containers { c := runningPod.FindContainerByName(container.Name) if c == nil { diff --git a/pkg/kubelet/runonce_test.go b/pkg/kubelet/runonce_test.go index 75ddab52b69..264ff3b3365 100644 --- a/pkg/kubelet/runonce_test.go +++ b/pkg/kubelet/runonce_test.go @@ -148,7 +148,7 @@ func TestRunOnce(t *testing.T) { kb.containerManager = dockertools.NewDockerManager(kb.dockerClient, kb.recorder, dockertools.PodInfraContainerImage, 0, 0) kb.containerManager.Puller = &dockertools.FakeDockerPuller{} - pods := []api.Pod{ + pods := []*api.Pod{ { ObjectMeta: api.ObjectMeta{ UID: "12345678", diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index c051e9f414f..78e80e45f55 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -102,7 +102,7 @@ type HostInterface interface { GetRootInfo(req *cadvisorApi.ContainerInfoRequest) (*cadvisorApi.ContainerInfo, error) GetDockerVersion() ([]uint, error) GetCachedMachineInfo() (*cadvisorApi.MachineInfo, error) - GetPods() []api.Pod + GetPods() []*api.Pod GetPodByName(namespace, name string) (*api.Pod, bool) GetPodStatus(name string) (api.PodStatus, error) RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error) @@ -279,8 +279,9 @@ func (s *Server) handleContainerLogs(w http.ResponseWriter, req *http.Request) { // handlePods returns a list of pod bound to the Kubelet and their spec func (s *Server) handlePods(w http.ResponseWriter, req *http.Request) { pods := s.host.GetPods() - podList := &api.PodList{ - Items: pods, + podList := new(api.PodList) + for _, pod := range pods { + podList.Items = append(podList.Items, *pod) } data, err := latest.Codec.Encode(podList) if err != nil { diff --git a/pkg/kubelet/server_test.go b/pkg/kubelet/server_test.go index 935cd6df408..32aa644eaae 100644 --- a/pkg/kubelet/server_test.go +++ b/pkg/kubelet/server_test.go @@ -44,7 +44,7 @@ type fakeKubelet struct { containerInfoFunc func(podFullName string, uid types.UID, containerName string, req *cadvisorApi.ContainerInfoRequest) (*cadvisorApi.ContainerInfo, error) rootInfoFunc func(query *cadvisorApi.ContainerInfoRequest) (*cadvisorApi.ContainerInfo, error) machineInfoFunc func() (*cadvisorApi.MachineInfo, error) - podsFunc func() []api.Pod + podsFunc func() []*api.Pod logFunc func(w http.ResponseWriter, req *http.Request) runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) dockerVersionFunc func() ([]uint, error) @@ -79,7 +79,7 @@ func (fk *fakeKubelet) GetCachedMachineInfo() (*cadvisorApi.MachineInfo, error) return fk.machineInfoFunc() } -func (fk *fakeKubelet) GetPods() []api.Pod { +func (fk *fakeKubelet) GetPods() []*api.Pod { return fk.podsFunc() } diff --git a/pkg/kubelet/types.go b/pkg/kubelet/types.go index 5d3aa9cc25f..cb0fdba2b69 100644 --- a/pkg/kubelet/types.go +++ b/pkg/kubelet/types.go @@ -64,7 +64,7 @@ const ( // functionally similar, this helps our unit tests properly check that the correct PodUpdates // are generated. type PodUpdate struct { - Pods []api.Pod + Pods []*api.Pod Op PodOperation Source string } diff --git a/pkg/scheduler/generic_scheduler.go b/pkg/scheduler/generic_scheduler.go index 7a2542daa0a..3d55baa5e83 100644 --- a/pkg/scheduler/generic_scheduler.go +++ b/pkg/scheduler/generic_scheduler.go @@ -30,7 +30,7 @@ import ( type FailedPredicateMap map[string]util.StringSet type FitError struct { - Pod api.Pod + Pod *api.Pod FailedPredicates FailedPredicateMap } @@ -51,7 +51,7 @@ type genericScheduler struct { randomLock sync.Mutex } -func (g *genericScheduler) Schedule(pod api.Pod, minionLister MinionLister) (string, error) { +func (g *genericScheduler) Schedule(pod *api.Pod, minionLister MinionLister) (string, error) { minions, err := minionLister.List() if err != nil { return "", err @@ -97,7 +97,7 @@ func (g *genericScheduler) selectHost(priorityList HostPriorityList) (string, er // Filters the minions to find the ones that fit based on the given predicate functions // Each minion is passed through the predicate functions to determine if it is a fit -func findNodesThatFit(pod api.Pod, podLister PodLister, predicates map[string]FitPredicate, nodes api.NodeList) (api.NodeList, FailedPredicateMap, error) { +func findNodesThatFit(pod *api.Pod, podLister PodLister, predicates map[string]FitPredicate, nodes api.NodeList) (api.NodeList, FailedPredicateMap, error) { filtered := []api.Node{} machineToPods, err := MapPodsToMachines(podLister) failedPredicateMap := FailedPredicateMap{} @@ -133,7 +133,7 @@ func findNodesThatFit(pod api.Pod, podLister PodLister, predicates map[string]Fi // Each priority function can also have its own weight // The minion scores returned by the priority function are multiplied by the weights to get weighted scores // All scores are finally combined (added) to get the total weighted scores of all minions -func prioritizeNodes(pod api.Pod, podLister PodLister, priorityConfigs []PriorityConfig, minionLister MinionLister) (HostPriorityList, error) { +func prioritizeNodes(pod *api.Pod, podLister PodLister, priorityConfigs []PriorityConfig, minionLister MinionLister) (HostPriorityList, error) { result := HostPriorityList{} // If no priority configs are provided, then the EqualPriority function is applied @@ -177,7 +177,7 @@ func getBestHosts(list HostPriorityList) []string { } // EqualPriority is a prioritizer function that gives an equal weight of one to all nodes -func EqualPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { +func EqualPriority(_ *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { nodes, err := minionLister.List() if err != nil { fmt.Errorf("failed to list nodes: %v", err) diff --git a/pkg/scheduler/generic_scheduler_test.go b/pkg/scheduler/generic_scheduler_test.go index b9cfd2f41c6..8b507bccb83 100644 --- a/pkg/scheduler/generic_scheduler_test.go +++ b/pkg/scheduler/generic_scheduler_test.go @@ -27,19 +27,19 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) -func falsePredicate(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func falsePredicate(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { return false, nil } -func truePredicate(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func truePredicate(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { return true, nil } -func matchesPredicate(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func matchesPredicate(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { return pod.Name == node, nil } -func numericPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { +func numericPriority(pod *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { nodes, err := minionLister.List() result := []HostPriority{} @@ -60,7 +60,7 @@ func numericPriority(pod api.Pod, podLister PodLister, minionLister MinionLister return result, nil } -func reverseNumericPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { +func reverseNumericPriority(pod *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { var maxScore float64 minScore := math.MaxFloat64 reverseResult := []HostPriority{} @@ -165,7 +165,7 @@ func TestGenericScheduler(t *testing.T) { predicates map[string]FitPredicate prioritizers []PriorityConfig nodes []string - pod api.Pod + pod *api.Pod expectedHost string expectsErr bool }{ @@ -189,7 +189,7 @@ func TestGenericScheduler(t *testing.T) { predicates: map[string]FitPredicate{"matches": matchesPredicate}, prioritizers: []PriorityConfig{{Function: EqualPriority, Weight: 1}}, nodes: []string{"machine1", "machine2"}, - pod: api.Pod{ObjectMeta: api.ObjectMeta{Name: "machine2"}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "machine2"}}, expectedHost: "machine2", name: "test 3", }, @@ -204,7 +204,7 @@ func TestGenericScheduler(t *testing.T) { predicates: map[string]FitPredicate{"matches": matchesPredicate}, prioritizers: []PriorityConfig{{Function: numericPriority, Weight: 1}}, nodes: []string{"3", "2", "1"}, - pod: api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, expectedHost: "2", name: "test 5", }, @@ -212,7 +212,7 @@ func TestGenericScheduler(t *testing.T) { predicates: map[string]FitPredicate{"true": truePredicate}, prioritizers: []PriorityConfig{{Function: numericPriority, Weight: 1}, {Function: reverseNumericPriority, Weight: 2}}, nodes: []string{"3", "2", "1"}, - pod: api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, expectedHost: "1", name: "test 6", }, @@ -227,7 +227,7 @@ func TestGenericScheduler(t *testing.T) { for _, test := range tests { random := rand.New(rand.NewSource(0)) - scheduler := NewGenericScheduler(test.predicates, test.prioritizers, FakePodLister([]api.Pod{}), random) + scheduler := NewGenericScheduler(test.predicates, test.prioritizers, FakePodLister([]*api.Pod{}), random) machine, err := scheduler.Schedule(test.pod, FakeMinionLister(makeNodeList(test.nodes))) if test.expectsErr { if err == nil { @@ -247,7 +247,7 @@ func TestGenericScheduler(t *testing.T) { func TestFindFitAllError(t *testing.T) { nodes := []string{"3", "2", "1"} predicates := map[string]FitPredicate{"true": truePredicate, "false": falsePredicate} - _, predicateMap, err := findNodesThatFit(api.Pod{}, FakePodLister([]api.Pod{}), predicates, makeNodeList(nodes)) + _, predicateMap, err := findNodesThatFit(&api.Pod{}, FakePodLister([]*api.Pod{}), predicates, makeNodeList(nodes)) if err != nil { t.Errorf("unexpected error: %v", err) @@ -271,8 +271,8 @@ func TestFindFitAllError(t *testing.T) { func TestFindFitSomeError(t *testing.T) { nodes := []string{"3", "2", "1"} predicates := map[string]FitPredicate{"true": truePredicate, "match": matchesPredicate} - pod := api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}} - _, predicateMap, err := findNodesThatFit(pod, FakePodLister([]api.Pod{}), predicates, makeNodeList(nodes)) + pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}} + _, predicateMap, err := findNodesThatFit(pod, FakePodLister([]*api.Pod{}), predicates, makeNodeList(nodes)) if err != nil { t.Errorf("unexpected error: %v", err) diff --git a/pkg/scheduler/listers.go b/pkg/scheduler/listers.go index 10d887c9417..73e5b58c37e 100644 --- a/pkg/scheduler/listers.go +++ b/pkg/scheduler/listers.go @@ -39,14 +39,14 @@ func (f FakeMinionLister) List() (api.NodeList, error) { // PodLister interface represents anything that can list pods for a scheduler. type PodLister interface { // TODO: make this exactly the same as client's Pods(ns).List() method, by returning a api.PodList - List(labels.Selector) ([]api.Pod, error) + List(labels.Selector) ([]*api.Pod, error) } // FakePodLister implements PodLister on an []api.Pods for test purposes. -type FakePodLister []api.Pod +type FakePodLister []*api.Pod // List returns []api.Pod matching a query. -func (f FakePodLister) List(s labels.Selector) (selected []api.Pod, err error) { +func (f FakePodLister) List(s labels.Selector) (selected []*api.Pod, err error) { for _, pod := range f { if s.Matches(labels.Set(pod.Labels)) { selected = append(selected, pod) @@ -60,7 +60,7 @@ type ServiceLister interface { // Lists all the services List() (api.ServiceList, error) // Gets the services for the given pod - GetPodServices(api.Pod) ([]api.Service, error) + GetPodServices(*api.Pod) ([]api.Service, error) } // FakeServiceLister implements ServiceLister on []api.Service for test purposes. @@ -72,7 +72,7 @@ func (f FakeServiceLister) List() (api.ServiceList, error) { } // GetPodServices gets the services that have the selector that match the labels on the given pod -func (f FakeServiceLister) GetPodServices(pod api.Pod) (services []api.Service, err error) { +func (f FakeServiceLister) GetPodServices(pod *api.Pod) (services []api.Service, err error) { var selector labels.Selector for _, service := range f { diff --git a/pkg/scheduler/predicates.go b/pkg/scheduler/predicates.go index b8a8e043b3a..c20f3c6969b 100644 --- a/pkg/scheduler/predicates.go +++ b/pkg/scheduler/predicates.go @@ -80,11 +80,11 @@ func isVolumeConflict(volume api.Volume, pod *api.Pod) bool { // are exclusive so if there is already a volume mounted on that node, another pod can't schedule // there. This is GCE specific for now. // TODO: migrate this into some per-volume specific code? -func NoDiskConflict(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func NoDiskConflict(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { manifest := &(pod.Spec) for ix := range manifest.Volumes { for podIx := range existingPods { - if isVolumeConflict(manifest.Volumes[ix], &existingPods[podIx]) { + if isVolumeConflict(manifest.Volumes[ix], existingPods[podIx]) { return false, nil } } @@ -111,31 +111,31 @@ func getResourceRequest(pod *api.Pod) resourceRequest { return result } -func CheckPodsExceedingCapacity(pods []api.Pod, capacity api.ResourceList) (fitting []api.Pod, notFitting []api.Pod) { +func CheckPodsExceedingCapacity(pods []*api.Pod, capacity api.ResourceList) (fitting []*api.Pod, notFitting []*api.Pod) { totalMilliCPU := capacity.Cpu().MilliValue() totalMemory := capacity.Memory().Value() milliCPURequested := int64(0) memoryRequested := int64(0) - for ix := range pods { - podRequest := getResourceRequest(&pods[ix]) + for _, pod := range pods { + podRequest := getResourceRequest(pod) fitsCPU := totalMilliCPU == 0 || (totalMilliCPU-milliCPURequested) >= podRequest.milliCPU fitsMemory := totalMemory == 0 || (totalMemory-memoryRequested) >= podRequest.memory if !fitsCPU || !fitsMemory { // the pod doesn't fit - notFitting = append(notFitting, pods[ix]) + notFitting = append(notFitting, pod) continue } // the pod fits milliCPURequested += podRequest.milliCPU memoryRequested += podRequest.memory - fitting = append(fitting, pods[ix]) + fitting = append(fitting, pod) } return } // PodFitsResources calculates fit based on requested, rather than used resources -func (r *ResourceFit) PodFitsResources(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { - podRequest := getResourceRequest(&pod) +func (r *ResourceFit) PodFitsResources(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { + podRequest := getResourceRequest(pod) if podRequest.milliCPU == 0 && podRequest.memory == 0 { // no resources requested always fits. return true, nil @@ -144,7 +144,7 @@ func (r *ResourceFit) PodFitsResources(pod api.Pod, existingPods []api.Pod, node if err != nil { return false, err } - pods := []api.Pod{} + pods := []*api.Pod{} copy(pods, existingPods) pods = append(existingPods, pod) _, exceeding := CheckPodsExceedingCapacity(pods, info.Status.Capacity) @@ -180,15 +180,15 @@ type NodeSelector struct { info NodeInfo } -func (n *NodeSelector) PodSelectorMatches(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func (n *NodeSelector) PodSelectorMatches(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { minion, err := n.info.GetNodeInfo(node) if err != nil { return false, err } - return PodMatchesNodeLabels(&pod, minion), nil + return PodMatchesNodeLabels(pod, minion), nil } -func PodFitsHost(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func PodFitsHost(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { if len(pod.Spec.Host) == 0 { return true, nil } @@ -222,7 +222,7 @@ func NewNodeLabelPredicate(info NodeInfo, labels []string, presence bool) FitPre // Alternately, eliminating minions that have a certain label, regardless of value, is also useful // A minion may have a label with "retiring" as key and the date as the value // and it may be desirable to avoid scheduling new pods on this minion -func (n *NodeLabelChecker) CheckNodeLabelPresence(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func (n *NodeLabelChecker) CheckNodeLabelPresence(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { var exists bool minion, err := n.info.GetNodeInfo(node) if err != nil { @@ -264,7 +264,7 @@ func NewServiceAffinityPredicate(podLister PodLister, serviceLister ServiceListe // - L is listed in the ServiceAffinity object that is passed into the function // - the pod does not have any NodeSelector for L // - some other pod from the same service is already scheduled onto a minion that has value V for label L -func (s *ServiceAffinity) CheckServiceAffinity(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func (s *ServiceAffinity) CheckServiceAffinity(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { var affinitySelector labels.Selector // check if the pod being scheduled has the affinity labels specified in its NodeSelector @@ -292,7 +292,7 @@ func (s *ServiceAffinity) CheckServiceAffinity(pod api.Pod, existingPods []api.P return false, err } // consider only the pods that belong to the same namespace - nsServicePods := []api.Pod{} + nsServicePods := []*api.Pod{} for _, nsPod := range servicePods { if nsPod.Namespace == pod.Namespace { nsServicePods = append(nsServicePods, nsPod) @@ -333,7 +333,7 @@ func (s *ServiceAffinity) CheckServiceAffinity(pod api.Pod, existingPods []api.P return affinitySelector.Matches(labels.Set(minion.Labels)), nil } -func PodFitsPorts(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func PodFitsPorts(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { existingPorts := getUsedPorts(existingPods...) wantPorts := getUsedPorts(pod) for wport := range wantPorts { @@ -347,7 +347,7 @@ func PodFitsPorts(pod api.Pod, existingPods []api.Pod, node string) (bool, error return true, nil } -func getUsedPorts(pods ...api.Pod) map[int]bool { +func getUsedPorts(pods ...*api.Pod) map[int]bool { ports := make(map[int]bool) for _, pod := range pods { for _, container := range pod.Spec.Containers { @@ -361,12 +361,12 @@ func getUsedPorts(pods ...api.Pod) map[int]bool { // MapPodsToMachines obtains a list of pods and pivots that list into a map where the keys are host names // and the values are the list of pods running on that host. -func MapPodsToMachines(lister PodLister) (map[string][]api.Pod, error) { - machineToPods := map[string][]api.Pod{} +func MapPodsToMachines(lister PodLister) (map[string][]*api.Pod, error) { + machineToPods := map[string][]*api.Pod{} // TODO: perform more targeted query... pods, err := lister.List(labels.Everything()) if err != nil { - return map[string][]api.Pod{}, err + return map[string][]*api.Pod{}, err } for _, scheduledPod := range pods { host := scheduledPod.Spec.Host diff --git a/pkg/scheduler/predicates_test.go b/pkg/scheduler/predicates_test.go index e8833c28c5d..56a135b7dd3 100644 --- a/pkg/scheduler/predicates_test.go +++ b/pkg/scheduler/predicates_test.go @@ -52,7 +52,7 @@ func makeResources(milliCPU int64, memory int64) api.NodeResources { } } -func newResourcePod(usage ...resourceRequest) api.Pod { +func newResourcePod(usage ...resourceRequest) *api.Pod { containers := []api.Container{} for _, req := range usage { containers = append(containers, api.Container{ @@ -64,7 +64,7 @@ func newResourcePod(usage ...resourceRequest) api.Pod { }, }) } - return api.Pod{ + return &api.Pod{ Spec: api.PodSpec{ Containers: containers, }, @@ -73,14 +73,14 @@ func newResourcePod(usage ...resourceRequest) api.Pod { func TestPodFitsResources(t *testing.T) { tests := []struct { - pod api.Pod - existingPods []api.Pod + pod *api.Pod + existingPods []*api.Pod fits bool test string }{ { - pod: api.Pod{}, - existingPods: []api.Pod{ + pod: &api.Pod{}, + existingPods: []*api.Pod{ newResourcePod(resourceRequest{milliCPU: 10, memory: 20}), }, fits: true, @@ -88,7 +88,7 @@ func TestPodFitsResources(t *testing.T) { }, { pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 1}), - existingPods: []api.Pod{ + existingPods: []*api.Pod{ newResourcePod(resourceRequest{milliCPU: 10, memory: 20}), }, fits: false, @@ -96,7 +96,7 @@ func TestPodFitsResources(t *testing.T) { }, { pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 1}), - existingPods: []api.Pod{ + existingPods: []*api.Pod{ newResourcePod(resourceRequest{milliCPU: 5, memory: 5}), }, fits: true, @@ -104,7 +104,7 @@ func TestPodFitsResources(t *testing.T) { }, { pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 2}), - existingPods: []api.Pod{ + existingPods: []*api.Pod{ newResourcePod(resourceRequest{milliCPU: 5, memory: 19}), }, fits: false, @@ -112,7 +112,7 @@ func TestPodFitsResources(t *testing.T) { }, { pod: newResourcePod(resourceRequest{milliCPU: 5, memory: 1}), - existingPods: []api.Pod{ + existingPods: []*api.Pod{ newResourcePod(resourceRequest{milliCPU: 5, memory: 19}), }, fits: true, @@ -135,19 +135,19 @@ func TestPodFitsResources(t *testing.T) { func TestPodFitsHost(t *testing.T) { tests := []struct { - pod api.Pod + pod *api.Pod node string fits bool test string }{ { - pod: api.Pod{}, + pod: &api.Pod{}, node: "foo", fits: true, test: "no host specified", }, { - pod: api.Pod{ + pod: &api.Pod{ Spec: api.PodSpec{ Host: "foo", }, @@ -157,7 +157,7 @@ func TestPodFitsHost(t *testing.T) { test: "host matches", }, { - pod: api.Pod{ + pod: &api.Pod{ Spec: api.PodSpec{ Host: "bar", }, @@ -169,7 +169,7 @@ func TestPodFitsHost(t *testing.T) { } for _, test := range tests { - result, err := PodFitsHost(test.pod, []api.Pod{}, test.node) + result, err := PodFitsHost(test.pod, []*api.Pod{}, test.node) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -181,20 +181,20 @@ func TestPodFitsHost(t *testing.T) { func TestPodFitsPorts(t *testing.T) { tests := []struct { - pod api.Pod - existingPods []api.Pod + pod *api.Pod + existingPods []*api.Pod fits bool test string }{ { - pod: api.Pod{}, - existingPods: []api.Pod{}, + pod: &api.Pod{}, + existingPods: []*api.Pod{}, fits: true, test: "nothing running", }, { pod: newPod("m1", 8080), - existingPods: []api.Pod{ + existingPods: []*api.Pod{ newPod("m1", 9090), }, fits: true, @@ -202,7 +202,7 @@ func TestPodFitsPorts(t *testing.T) { }, { pod: newPod("m1", 8080), - existingPods: []api.Pod{ + existingPods: []*api.Pod{ newPod("m1", 8080), }, fits: false, @@ -210,7 +210,7 @@ func TestPodFitsPorts(t *testing.T) { }, { pod: newPod("m1", 8000, 8080), - existingPods: []api.Pod{ + existingPods: []*api.Pod{ newPod("m1", 8080), }, fits: false, @@ -218,7 +218,7 @@ func TestPodFitsPorts(t *testing.T) { }, { pod: newPod("m1", 8000, 8080), - existingPods: []api.Pod{ + existingPods: []*api.Pod{ newPod("m1", 8001, 8080), }, fits: false, @@ -238,25 +238,25 @@ func TestPodFitsPorts(t *testing.T) { func TestGetUsedPorts(t *testing.T) { tests := []struct { - pods []api.Pod + pods []*api.Pod ports map[int]bool }{ { - []api.Pod{ + []*api.Pod{ newPod("m1", 9090), }, map[int]bool{9090: true}, }, { - []api.Pod{ + []*api.Pod{ newPod("m1", 9090), newPod("m1", 9091), }, map[int]bool{9090: true, 9091: true}, }, { - []api.Pod{ + []*api.Pod{ newPod("m1", 9090), newPod("m2", 9091), }, @@ -296,15 +296,15 @@ func TestDiskConflicts(t *testing.T) { }, } tests := []struct { - pod api.Pod - existingPods []api.Pod + pod *api.Pod + existingPods []*api.Pod isOk bool test string }{ - {api.Pod{}, []api.Pod{}, true, "nothing"}, - {api.Pod{}, []api.Pod{{Spec: volState}}, true, "one state"}, - {api.Pod{Spec: volState}, []api.Pod{{Spec: volState}}, false, "same state"}, - {api.Pod{Spec: volState2}, []api.Pod{{Spec: volState}}, true, "different state"}, + {&api.Pod{}, []*api.Pod{}, true, "nothing"}, + {&api.Pod{}, []*api.Pod{{Spec: volState}}, true, "one state"}, + {&api.Pod{Spec: volState}, []*api.Pod{{Spec: volState}}, false, "same state"}, + {&api.Pod{Spec: volState2}, []*api.Pod{{Spec: volState}}, true, "different state"}, } for _, test := range tests { @@ -345,15 +345,15 @@ func TestAWSDiskConflicts(t *testing.T) { }, } tests := []struct { - pod api.Pod - existingPods []api.Pod + pod *api.Pod + existingPods []*api.Pod isOk bool test string }{ - {api.Pod{}, []api.Pod{}, true, "nothing"}, - {api.Pod{}, []api.Pod{{Spec: volState}}, true, "one state"}, - {api.Pod{Spec: volState}, []api.Pod{{Spec: volState}}, false, "same state"}, - {api.Pod{Spec: volState2}, []api.Pod{{Spec: volState}}, true, "different state"}, + {&api.Pod{}, []*api.Pod{}, true, "nothing"}, + {&api.Pod{}, []*api.Pod{{Spec: volState}}, true, "one state"}, + {&api.Pod{Spec: volState}, []*api.Pod{{Spec: volState}}, false, "same state"}, + {&api.Pod{Spec: volState2}, []*api.Pod{{Spec: volState}}, true, "different state"}, } for _, test := range tests { @@ -372,18 +372,18 @@ func TestAWSDiskConflicts(t *testing.T) { func TestPodFitsSelector(t *testing.T) { tests := []struct { - pod api.Pod + pod *api.Pod labels map[string]string fits bool test string }{ { - pod: api.Pod{}, + pod: &api.Pod{}, fits: true, test: "no selector", }, { - pod: api.Pod{ + pod: &api.Pod{ Spec: api.PodSpec{ NodeSelector: map[string]string{ "foo": "bar", @@ -394,7 +394,7 @@ func TestPodFitsSelector(t *testing.T) { test: "missing labels", }, { - pod: api.Pod{ + pod: &api.Pod{ Spec: api.PodSpec{ NodeSelector: map[string]string{ "foo": "bar", @@ -408,7 +408,7 @@ func TestPodFitsSelector(t *testing.T) { test: "same labels", }, { - pod: api.Pod{ + pod: &api.Pod{ Spec: api.PodSpec{ NodeSelector: map[string]string{ "foo": "bar", @@ -423,7 +423,7 @@ func TestPodFitsSelector(t *testing.T) { test: "node labels are superset", }, { - pod: api.Pod{ + pod: &api.Pod{ Spec: api.PodSpec{ NodeSelector: map[string]string{ "foo": "bar", @@ -442,7 +442,7 @@ func TestPodFitsSelector(t *testing.T) { node := api.Node{ObjectMeta: api.ObjectMeta{Labels: test.labels}} fit := NodeSelector{FakeNodeInfo(node)} - fits, err := fit.PodSelectorMatches(test.pod, []api.Pod{}, "machine") + fits, err := fit.PodSelectorMatches(test.pod, []*api.Pod{}, "machine") if err != nil { t.Errorf("unexpected error: %v", err) } @@ -455,8 +455,8 @@ func TestPodFitsSelector(t *testing.T) { func TestNodeLabelPresence(t *testing.T) { label := map[string]string{"foo": "bar", "bar": "foo"} tests := []struct { - pod api.Pod - existingPods []api.Pod + pod *api.Pod + existingPods []*api.Pod labels []string presence bool fits bool @@ -536,8 +536,8 @@ func TestServiceAffinity(t *testing.T) { node4 := api.Node{ObjectMeta: api.ObjectMeta{Name: "machine4", Labels: labels4}} node5 := api.Node{ObjectMeta: api.ObjectMeta{Name: "machine5", Labels: labels4}} tests := []struct { - pod api.Pod - pods []api.Pod + pod *api.Pod + pods []*api.Pod services []api.Service node string labels []string @@ -545,28 +545,29 @@ func TestServiceAffinity(t *testing.T) { test string }{ { + pod: new(api.Pod), node: "machine1", fits: true, labels: []string{"region"}, test: "nothing scheduled", }, { - pod: api.Pod{Spec: api.PodSpec{NodeSelector: map[string]string{"region": "r1"}}}, + pod: &api.Pod{Spec: api.PodSpec{NodeSelector: map[string]string{"region": "r1"}}}, node: "machine1", fits: true, labels: []string{"region"}, test: "pod with region label match", }, { - pod: api.Pod{Spec: api.PodSpec{NodeSelector: map[string]string{"region": "r2"}}}, + pod: &api.Pod{Spec: api.PodSpec{NodeSelector: map[string]string{"region": "r2"}}}, node: "machine1", fits: false, labels: []string{"region"}, test: "pod with region label mismatch", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, - pods: []api.Pod{{Spec: api.PodSpec{Host: "machine1"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, + pods: []*api.Pod{{Spec: api.PodSpec{Host: "machine1"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, node: "machine1", services: []api.Service{{Spec: api.ServiceSpec{Selector: selector}}}, fits: true, @@ -574,8 +575,8 @@ func TestServiceAffinity(t *testing.T) { test: "service pod on same minion", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, - pods: []api.Pod{{Spec: api.PodSpec{Host: "machine2"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, + pods: []*api.Pod{{Spec: api.PodSpec{Host: "machine2"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, node: "machine1", services: []api.Service{{Spec: api.ServiceSpec{Selector: selector}}}, fits: true, @@ -583,8 +584,8 @@ func TestServiceAffinity(t *testing.T) { test: "service pod on different minion, region match", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, - pods: []api.Pod{{Spec: api.PodSpec{Host: "machine3"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, + pods: []*api.Pod{{Spec: api.PodSpec{Host: "machine3"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, node: "machine1", services: []api.Service{{Spec: api.ServiceSpec{Selector: selector}}}, fits: false, @@ -592,8 +593,8 @@ func TestServiceAffinity(t *testing.T) { test: "service pod on different minion, region mismatch", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}, - pods: []api.Pod{{Spec: api.PodSpec{Host: "machine3"}, ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}, + pods: []*api.Pod{{Spec: api.PodSpec{Host: "machine3"}, ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}}, node: "machine1", services: []api.Service{{Spec: api.ServiceSpec{Selector: selector}, ObjectMeta: api.ObjectMeta{Namespace: "ns2"}}}, fits: true, @@ -601,8 +602,8 @@ func TestServiceAffinity(t *testing.T) { test: "service in different namespace, region mismatch", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}, - pods: []api.Pod{{Spec: api.PodSpec{Host: "machine3"}, ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns2"}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}, + pods: []*api.Pod{{Spec: api.PodSpec{Host: "machine3"}, ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns2"}}}, node: "machine1", services: []api.Service{{Spec: api.ServiceSpec{Selector: selector}, ObjectMeta: api.ObjectMeta{Namespace: "ns1"}}}, fits: true, @@ -610,8 +611,8 @@ func TestServiceAffinity(t *testing.T) { test: "pod in different namespace, region mismatch", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}, - pods: []api.Pod{{Spec: api.PodSpec{Host: "machine3"}, ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}, + pods: []*api.Pod{{Spec: api.PodSpec{Host: "machine3"}, ObjectMeta: api.ObjectMeta{Labels: selector, Namespace: "ns1"}}}, node: "machine1", services: []api.Service{{Spec: api.ServiceSpec{Selector: selector}, ObjectMeta: api.ObjectMeta{Namespace: "ns1"}}}, fits: false, @@ -619,8 +620,8 @@ func TestServiceAffinity(t *testing.T) { test: "service and pod in same namespace, region mismatch", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, - pods: []api.Pod{{Spec: api.PodSpec{Host: "machine2"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, + pods: []*api.Pod{{Spec: api.PodSpec{Host: "machine2"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, node: "machine1", services: []api.Service{{Spec: api.ServiceSpec{Selector: selector}}}, fits: false, @@ -628,8 +629,8 @@ func TestServiceAffinity(t *testing.T) { test: "service pod on different minion, multiple labels, not all match", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, - pods: []api.Pod{{Spec: api.PodSpec{Host: "machine5"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: selector}}, + pods: []*api.Pod{{Spec: api.PodSpec{Host: "machine5"}, ObjectMeta: api.ObjectMeta{Labels: selector}}}, node: "machine4", services: []api.Service{{Spec: api.ServiceSpec{Selector: selector}}}, fits: true, @@ -641,7 +642,7 @@ func TestServiceAffinity(t *testing.T) { for _, test := range tests { nodes := []api.Node{node1, node2, node3, node4, node5} serviceAffinity := ServiceAffinity{FakePodLister(test.pods), FakeServiceLister(test.services), FakeNodeListInfo(nodes), test.labels} - fits, err := serviceAffinity.CheckServiceAffinity(test.pod, []api.Pod{}, test.node) + fits, err := serviceAffinity.CheckServiceAffinity(test.pod, []*api.Pod{}, test.node) if err != nil { t.Errorf("unexpected error: %v", err) } diff --git a/pkg/scheduler/priorities.go b/pkg/scheduler/priorities.go index 2d5d3dac3ac..16c2214aa64 100644 --- a/pkg/scheduler/priorities.go +++ b/pkg/scheduler/priorities.go @@ -39,7 +39,7 @@ func calculateScore(requested, capacity int64, node string) int { // Calculate the occupancy on a node. 'node' has information about the resources on the node. // 'pods' is a list of pods currently scheduled on the node. -func calculateOccupancy(pod api.Pod, node api.Node, pods []api.Pod) HostPriority { +func calculateOccupancy(pod *api.Pod, node api.Node, pods []*api.Pod) HostPriority { totalMilliCPU := int64(0) totalMemory := int64(0) for _, existingPod := range pods { @@ -78,7 +78,7 @@ func calculateOccupancy(pod api.Pod, node api.Node, pods []api.Pod) HostPriority // It calculates the percentage of memory and CPU requested by pods scheduled on the node, and prioritizes // based on the minimum of the average of the fraction of requested to capacity. // Details: (Sum(requested cpu) / Capacity + Sum(requested memory) / Capacity) * 50 -func LeastRequestedPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { +func LeastRequestedPriority(pod *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { nodes, err := minionLister.List() if err != nil { return HostPriorityList{}, err @@ -108,7 +108,7 @@ func NewNodeLabelPriority(label string, presence bool) PriorityFunction { // CalculateNodeLabelPriority checks whether a particular label exists on a minion or not, regardless of its value. // If presence is true, prioritizes minions that have the specified label, regardless of value. // If presence is false, prioritizes minions that do not have the specified label. -func (n *NodeLabelPrioritizer) CalculateNodeLabelPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { +func (n *NodeLabelPrioritizer) CalculateNodeLabelPriority(pod *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { var score int minions, err := minionLister.List() if err != nil { @@ -141,7 +141,7 @@ func (n *NodeLabelPrioritizer) CalculateNodeLabelPriority(pod api.Pod, podLister // close the two metrics are to each other. // Detail: score = 10 - abs(cpuFraction-memoryFraction)*10. The algorithm is partly inspired by: // "Wei Huang et al. An Energy Efficient Virtual Machine Placement Algorithm with Balanced Resource Utilization" -func BalancedResourceAllocation(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { +func BalancedResourceAllocation(pod *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { nodes, err := minionLister.List() if err != nil { return HostPriorityList{}, err @@ -155,7 +155,7 @@ func BalancedResourceAllocation(pod api.Pod, podLister PodLister, minionLister M return list, nil } -func calculateBalancedResourceAllocation(pod api.Pod, node api.Node, pods []api.Pod) HostPriority { +func calculateBalancedResourceAllocation(pod *api.Pod, node api.Node, pods []*api.Pod) HostPriority { totalMilliCPU := int64(0) totalMemory := int64(0) score := int(0) diff --git a/pkg/scheduler/priorities_test.go b/pkg/scheduler/priorities_test.go index 88c5aa31f41..5cddfc05730 100644 --- a/pkg/scheduler/priorities_test.go +++ b/pkg/scheduler/priorities_test.go @@ -98,8 +98,8 @@ func TestLeastRequested(t *testing.T) { }, } tests := []struct { - pod api.Pod - pods []api.Pod + pod *api.Pod + pods []*api.Pod nodes []api.Node expectedList HostPriorityList test string @@ -116,7 +116,7 @@ func TestLeastRequested(t *testing.T) { Memory Score: ((10000 - 0) *10) / 10000 = 10 Minion2 Score: (10 + 10) / 2 = 10 */ - pod: api.Pod{Spec: noResources}, + pod: &api.Pod{Spec: noResources}, nodes: []api.Node{makeMinion("machine1", 4000, 10000), makeMinion("machine2", 4000, 10000)}, expectedList: []HostPriority{{"machine1", 10}, {"machine2", 10}}, test: "nothing scheduled, nothing requested", @@ -133,7 +133,7 @@ func TestLeastRequested(t *testing.T) { Memory Score: ((10000 - 5000) *10) / 10000 = 5 Minion2 Score: (5 + 5) / 2 = 5 */ - pod: api.Pod{Spec: cpuAndMemory}, + pod: &api.Pod{Spec: cpuAndMemory}, nodes: []api.Node{makeMinion("machine1", 4000, 10000), makeMinion("machine2", 6000, 10000)}, expectedList: []HostPriority{{"machine1", 3}, {"machine2", 5}}, test: "nothing scheduled, resources requested, differently sized machines", @@ -150,11 +150,11 @@ func TestLeastRequested(t *testing.T) { Memory Score: ((10000 - 0) *10) / 10000 = 10 Minion2 Score: (10 + 10) / 2 = 10 */ - pod: api.Pod{Spec: noResources}, + pod: &api.Pod{Spec: noResources}, nodes: []api.Node{makeMinion("machine1", 4000, 10000), makeMinion("machine2", 4000, 10000)}, expectedList: []HostPriority{{"machine1", 10}, {"machine2", 10}}, test: "no resources requested, pods scheduled", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: machine1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: machine1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: machine2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -173,11 +173,11 @@ func TestLeastRequested(t *testing.T) { Memory Score: ((20000 - 5000) *10) / 20000 = 7.5 Minion2 Score: (4 + 7.5) / 2 = 5 */ - pod: api.Pod{Spec: noResources}, + pod: &api.Pod{Spec: noResources}, nodes: []api.Node{makeMinion("machine1", 10000, 20000), makeMinion("machine2", 10000, 20000)}, expectedList: []HostPriority{{"machine1", 7}, {"machine2", 5}}, test: "no resources requested, pods scheduled with resources", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: cpuOnly, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: cpuOnly2, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -196,11 +196,11 @@ func TestLeastRequested(t *testing.T) { Memory Score: ((20000 - 10000) *10) / 20000 = 5 Minion2 Score: (4 + 5) / 2 = 4 */ - pod: api.Pod{Spec: cpuAndMemory}, + pod: &api.Pod{Spec: cpuAndMemory}, nodes: []api.Node{makeMinion("machine1", 10000, 20000), makeMinion("machine2", 10000, 20000)}, expectedList: []HostPriority{{"machine1", 5}, {"machine2", 4}}, test: "resources requested, pods scheduled with resources", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, @@ -217,11 +217,11 @@ func TestLeastRequested(t *testing.T) { Memory Score: ((50000 - 10000) *10) / 50000 = 8 Minion2 Score: (4 + 8) / 2 = 6 */ - pod: api.Pod{Spec: cpuAndMemory}, + pod: &api.Pod{Spec: cpuAndMemory}, nodes: []api.Node{makeMinion("machine1", 10000, 20000), makeMinion("machine2", 10000, 50000)}, expectedList: []HostPriority{{"machine1", 5}, {"machine2", 6}}, test: "resources requested, pods scheduled with resources, differently sized machines", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, @@ -238,21 +238,21 @@ func TestLeastRequested(t *testing.T) { Memory Score: ((10000 - 5000) *10) / 10000 = 5 Minion2 Score: (0 + 5) / 2 = 2 */ - pod: api.Pod{Spec: cpuOnly}, + pod: &api.Pod{Spec: cpuOnly}, nodes: []api.Node{makeMinion("machine1", 4000, 10000), makeMinion("machine2", 4000, 10000)}, expectedList: []HostPriority{{"machine1", 5}, {"machine2", 2}}, test: "requested resources exceed minion capacity", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, }, { - pod: api.Pod{Spec: noResources}, + pod: &api.Pod{Spec: noResources}, nodes: []api.Node{makeMinion("machine1", 0, 0), makeMinion("machine2", 0, 0)}, expectedList: []HostPriority{{"machine1", 0}, {"machine2", 0}}, test: "zero minion resources, pods scheduled with resources", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, @@ -275,8 +275,6 @@ func TestNewNodeLabelPriority(t *testing.T) { label2 := map[string]string{"bar": "foo"} label3 := map[string]string{"bar": "baz"} tests := []struct { - pod api.Pod - pods []api.Pod nodes []api.Node label string presence bool @@ -356,7 +354,7 @@ func TestNewNodeLabelPriority(t *testing.T) { label: test.label, presence: test.presence, } - list, err := prioritizer.CalculateNodeLabelPriority(test.pod, FakePodLister(test.pods), FakeMinionLister(api.NodeList{Items: test.nodes})) + list, err := prioritizer.CalculateNodeLabelPriority(nil, nil, FakeMinionLister(api.NodeList{Items: test.nodes})) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -430,8 +428,8 @@ func TestBalancedResourceAllocation(t *testing.T) { }, } tests := []struct { - pod api.Pod - pods []api.Pod + pod *api.Pod + pods []*api.Pod nodes []api.Node expectedList HostPriorityList test string @@ -448,7 +446,7 @@ func TestBalancedResourceAllocation(t *testing.T) { Memory Fraction: 0 / 10000 = 0% Minion2 Score: 10 - (0-0)*10 = 10 */ - pod: api.Pod{Spec: noResources}, + pod: &api.Pod{Spec: noResources}, nodes: []api.Node{makeMinion("machine1", 4000, 10000), makeMinion("machine2", 4000, 10000)}, expectedList: []HostPriority{{"machine1", 10}, {"machine2", 10}}, test: "nothing scheduled, nothing requested", @@ -465,7 +463,7 @@ func TestBalancedResourceAllocation(t *testing.T) { Memory Fraction: 5000/10000 = 50% Minion2 Score: 10 - (0.5-0.5)*10 = 10 */ - pod: api.Pod{Spec: cpuAndMemory}, + pod: &api.Pod{Spec: cpuAndMemory}, nodes: []api.Node{makeMinion("machine1", 4000, 10000), makeMinion("machine2", 6000, 10000)}, expectedList: []HostPriority{{"machine1", 7}, {"machine2", 10}}, test: "nothing scheduled, resources requested, differently sized machines", @@ -482,11 +480,11 @@ func TestBalancedResourceAllocation(t *testing.T) { Memory Fraction: 0 / 10000 = 0% Minion2 Score: 10 - (0-0)*10 = 10 */ - pod: api.Pod{Spec: noResources}, + pod: &api.Pod{Spec: noResources}, nodes: []api.Node{makeMinion("machine1", 4000, 10000), makeMinion("machine2", 4000, 10000)}, expectedList: []HostPriority{{"machine1", 10}, {"machine2", 10}}, test: "no resources requested, pods scheduled", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: machine1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: machine1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: machine2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -505,11 +503,11 @@ func TestBalancedResourceAllocation(t *testing.T) { Memory Fraction: 5000 / 20000 = 25% Minion2 Score: 10 - (0.6-0.25)*10 = 6 */ - pod: api.Pod{Spec: noResources}, + pod: &api.Pod{Spec: noResources}, nodes: []api.Node{makeMinion("machine1", 10000, 20000), makeMinion("machine2", 10000, 20000)}, expectedList: []HostPriority{{"machine1", 4}, {"machine2", 6}}, test: "no resources requested, pods scheduled with resources", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: cpuOnly, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: cpuOnly2, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -528,11 +526,11 @@ func TestBalancedResourceAllocation(t *testing.T) { Memory Fraction: 10000 / 20000 = 50% Minion2 Score: 10 - (0.6-0.5)*10 = 9 */ - pod: api.Pod{Spec: cpuAndMemory}, + pod: &api.Pod{Spec: cpuAndMemory}, nodes: []api.Node{makeMinion("machine1", 10000, 20000), makeMinion("machine2", 10000, 20000)}, expectedList: []HostPriority{{"machine1", 6}, {"machine2", 9}}, test: "resources requested, pods scheduled with resources", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, @@ -549,11 +547,11 @@ func TestBalancedResourceAllocation(t *testing.T) { Memory Fraction: 10000 / 50000 = 20% Minion2 Score: 10 - (0.6-0.2)*10 = 6 */ - pod: api.Pod{Spec: cpuAndMemory}, + pod: &api.Pod{Spec: cpuAndMemory}, nodes: []api.Node{makeMinion("machine1", 10000, 20000), makeMinion("machine2", 10000, 50000)}, expectedList: []HostPriority{{"machine1", 6}, {"machine2", 6}}, test: "resources requested, pods scheduled with resources, differently sized machines", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, @@ -570,21 +568,21 @@ func TestBalancedResourceAllocation(t *testing.T) { Memory Fraction 5000 / 10000 = 50% Minion2 Score: 0 */ - pod: api.Pod{Spec: cpuOnly}, + pod: &api.Pod{Spec: cpuOnly}, nodes: []api.Node{makeMinion("machine1", 4000, 10000), makeMinion("machine2", 4000, 10000)}, expectedList: []HostPriority{{"machine1", 0}, {"machine2", 0}}, test: "requested resources exceed minion capacity", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, }, { - pod: api.Pod{Spec: noResources}, + pod: &api.Pod{Spec: noResources}, nodes: []api.Node{makeMinion("machine1", 0, 0), makeMinion("machine2", 0, 0)}, expectedList: []HostPriority{{"machine1", 0}, {"machine2", 0}}, test: "zero minion resources, pods scheduled with resources", - pods: []api.Pod{ + pods: []*api.Pod{ {Spec: cpuOnly}, {Spec: cpuAndMemory}, }, diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index 34e645fbe81..8aea816d788 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -23,5 +23,5 @@ import ( // Scheduler is an interface implemented by things that know how to schedule pods // onto machines. type Scheduler interface { - Schedule(api.Pod, MinionLister) (selectedMachine string, err error) + Schedule(*api.Pod, MinionLister) (selectedMachine string, err error) } diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index c4285664487..72d37a8ce68 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -31,7 +31,7 @@ type schedulerTester struct { } // Call if you know exactly where pod should get scheduled. -func (st *schedulerTester) expectSchedule(pod api.Pod, expected string) { +func (st *schedulerTester) expectSchedule(pod *api.Pod, expected string) { actual, err := st.scheduler.Schedule(pod, st.minionLister) if err != nil { st.t.Errorf("Unexpected error %v\nTried to scheduler: %#v", err, pod) @@ -43,7 +43,7 @@ func (st *schedulerTester) expectSchedule(pod api.Pod, expected string) { } // Call if you can't predict where pod will be scheduled. -func (st *schedulerTester) expectSuccess(pod api.Pod) { +func (st *schedulerTester) expectSuccess(pod *api.Pod) { _, err := st.scheduler.Schedule(pod, st.minionLister) if err != nil { st.t.Errorf("Unexpected error %v\nTried to scheduler: %#v", err, pod) @@ -52,19 +52,19 @@ func (st *schedulerTester) expectSuccess(pod api.Pod) { } // Call if pod should *not* schedule. -func (st *schedulerTester) expectFailure(pod api.Pod) { +func (st *schedulerTester) expectFailure(pod *api.Pod) { _, err := st.scheduler.Schedule(pod, st.minionLister) if err == nil { st.t.Error("Unexpected non-error") } } -func newPod(host string, hostPorts ...int) api.Pod { +func newPod(host string, hostPorts ...int) *api.Pod { networkPorts := []api.ContainerPort{} for _, port := range hostPorts { networkPorts = append(networkPorts, api.ContainerPort{HostPort: port}) } - return api.Pod{ + return &api.Pod{ Spec: api.PodSpec{ Host: host, Containers: []api.Container{ diff --git a/pkg/scheduler/spreading.go b/pkg/scheduler/spreading.go index 43322703504..711cb7387df 100644 --- a/pkg/scheduler/spreading.go +++ b/pkg/scheduler/spreading.go @@ -34,9 +34,9 @@ func NewServiceSpreadPriority(serviceLister ServiceLister) PriorityFunction { // CalculateSpreadPriority spreads pods by minimizing the number of pods belonging to the same service // on the same machine. -func (s *ServiceSpread) CalculateSpreadPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { +func (s *ServiceSpread) CalculateSpreadPriority(pod *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { var maxCount int - var nsServicePods []api.Pod + var nsServicePods []*api.Pod services, err := s.serviceLister.GetPodServices(pod) if err == nil { @@ -101,8 +101,8 @@ func NewServiceAntiAffinityPriority(serviceLister ServiceLister, label string) P // CalculateAntiAffinityPriority spreads pods by minimizing the number of pods belonging to the same service // on machines with the same value for a particular label. // The label to be considered is provided to the struct (ServiceAntiAffinity). -func (s *ServiceAntiAffinity) CalculateAntiAffinityPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { - var nsServicePods []api.Pod +func (s *ServiceAntiAffinity) CalculateAntiAffinityPriority(pod *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) { + var nsServicePods []*api.Pod services, err := s.serviceLister.GetPodServices(pod) if err == nil { diff --git a/pkg/scheduler/spreading_test.go b/pkg/scheduler/spreading_test.go index 00bb7c5b5b6..921fed0248c 100644 --- a/pkg/scheduler/spreading_test.go +++ b/pkg/scheduler/spreading_test.go @@ -40,36 +40,37 @@ func TestServiceSpreadPriority(t *testing.T) { Host: "machine2", } tests := []struct { - pod api.Pod - pods []api.Pod + pod *api.Pod + pods []*api.Pod nodes []string services []api.Service expectedList HostPriorityList test string }{ { + pod: new(api.Pod), nodes: []string{"machine1", "machine2"}, expectedList: []HostPriority{{"machine1", 10}, {"machine2", 10}}, test: "nothing scheduled", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{{Spec: zone1Spec}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{{Spec: zone1Spec}}, nodes: []string{"machine1", "machine2"}, expectedList: []HostPriority{{"machine1", 10}, {"machine2", 10}}, test: "no services", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{{Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{{Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}}, nodes: []string{"machine1", "machine2"}, services: []api.Service{{Spec: api.ServiceSpec{Selector: map[string]string{"key": "value"}}}}, expectedList: []HostPriority{{"machine1", 10}, {"machine2", 10}}, test: "different services", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, }, @@ -79,8 +80,8 @@ func TestServiceSpreadPriority(t *testing.T) { test: "two pods, one service pod", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: api.NamespaceDefault}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, @@ -93,8 +94,8 @@ func TestServiceSpreadPriority(t *testing.T) { test: "five pods, one service pod in no namespace", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: api.NamespaceDefault}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: api.NamespaceDefault}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: api.NamespaceDefault}}, @@ -106,8 +107,8 @@ func TestServiceSpreadPriority(t *testing.T) { test: "four pods, one service pod in default namespace", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: api.NamespaceDefault}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: "ns2"}}, @@ -120,8 +121,8 @@ func TestServiceSpreadPriority(t *testing.T) { test: "five pods, one service pod in specific namespace", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -132,8 +133,8 @@ func TestServiceSpreadPriority(t *testing.T) { test: "three pods, two service pods on different machines", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -145,8 +146,8 @@ func TestServiceSpreadPriority(t *testing.T) { test: "four pods, three service pods", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -203,14 +204,15 @@ func TestZoneSpreadPriority(t *testing.T) { "machine21": zone2, "machine22": zone2, } tests := []struct { - pod api.Pod - pods []api.Pod + pod *api.Pod + pods []*api.Pod nodes map[string]map[string]string services []api.Service expectedList HostPriorityList test string }{ { + pod: new(api.Pod), nodes: labeledNodes, expectedList: []HostPriority{{"machine11", 10}, {"machine12", 10}, {"machine21", 10}, {"machine22", 10}, @@ -218,8 +220,8 @@ func TestZoneSpreadPriority(t *testing.T) { test: "nothing scheduled", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{{Spec: zone1Spec}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{{Spec: zone1Spec}}, nodes: labeledNodes, expectedList: []HostPriority{{"machine11", 10}, {"machine12", 10}, {"machine21", 10}, {"machine22", 10}, @@ -227,8 +229,8 @@ func TestZoneSpreadPriority(t *testing.T) { test: "no services", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{{Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}}, + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{{Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}}, nodes: labeledNodes, services: []api.Service{{Spec: api.ServiceSpec{Selector: map[string]string{"key": "value"}}}}, expectedList: []HostPriority{{"machine11", 10}, {"machine12", 10}, @@ -237,8 +239,8 @@ func TestZoneSpreadPriority(t *testing.T) { test: "different services", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone0Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -251,8 +253,8 @@ func TestZoneSpreadPriority(t *testing.T) { test: "three pods, one service pod", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -265,8 +267,8 @@ func TestZoneSpreadPriority(t *testing.T) { test: "three pods, two service pods on different machines", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: api.NamespaceDefault}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: api.NamespaceDefault}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1, Namespace: api.NamespaceDefault}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -280,8 +282,8 @@ func TestZoneSpreadPriority(t *testing.T) { test: "three service label match pods in different namespaces", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -295,8 +297,8 @@ func TestZoneSpreadPriority(t *testing.T) { test: "four pods, three service pods", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels2}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, @@ -309,8 +311,8 @@ func TestZoneSpreadPriority(t *testing.T) { test: "service with partial pod label matches", }, { - pod: api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, - pods: []api.Pod{ + pod: &api.Pod{ObjectMeta: api.ObjectMeta{Labels: labels1}}, + pods: []*api.Pod{ {Spec: zone0Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone1Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, {Spec: zone2Spec, ObjectMeta: api.ObjectMeta{Labels: labels1}}, diff --git a/pkg/scheduler/types.go b/pkg/scheduler/types.go index 471529b491d..c2481a73346 100644 --- a/pkg/scheduler/types.go +++ b/pkg/scheduler/types.go @@ -21,7 +21,7 @@ import ( ) // FitPredicate is a function that indicates if a pod fits into an existing node. -type FitPredicate func(pod api.Pod, existingPods []api.Pod, node string) (bool, error) +type FitPredicate func(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) // HostPriority represents the priority of scheduling to a particular host, lower priority is better. type HostPriority struct { @@ -46,7 +46,7 @@ func (h HostPriorityList) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -type PriorityFunction func(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) +type PriorityFunction func(pod *api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) type PriorityConfig struct { Function PriorityFunction diff --git a/plugin/pkg/scheduler/factory/factory_test.go b/plugin/pkg/scheduler/factory/factory_test.go index 9c08b489aeb..a39bea0b1c6 100644 --- a/plugin/pkg/scheduler/factory/factory_test.go +++ b/plugin/pkg/scheduler/factory/factory_test.go @@ -115,19 +115,19 @@ func TestCreateFromEmptyConfig(t *testing.T) { factory.CreateFromConfig(policy) } -func PredicateOne(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func PredicateOne(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { return true, nil } -func PredicateTwo(pod api.Pod, existingPods []api.Pod, node string) (bool, error) { +func PredicateTwo(pod *api.Pod, existingPods []*api.Pod, node string) (bool, error) { return true, nil } -func PriorityOne(pod api.Pod, podLister algorithm.PodLister, minionLister algorithm.MinionLister) (algorithm.HostPriorityList, error) { +func PriorityOne(pod *api.Pod, podLister algorithm.PodLister, minionLister algorithm.MinionLister) (algorithm.HostPriorityList, error) { return []algorithm.HostPriority{}, nil } -func PriorityTwo(pod api.Pod, podLister algorithm.PodLister, minionLister algorithm.MinionLister) (algorithm.HostPriorityList, error) { +func PriorityTwo(pod *api.Pod, podLister algorithm.PodLister, minionLister algorithm.MinionLister) (algorithm.HostPriorityList, error) { return []algorithm.HostPriority{}, nil } diff --git a/plugin/pkg/scheduler/modeler.go b/plugin/pkg/scheduler/modeler.go index a80187477ea..fef0998d496 100644 --- a/plugin/pkg/scheduler/modeler.go +++ b/plugin/pkg/scheduler/modeler.go @@ -123,7 +123,7 @@ func (s *SimpleModeler) ForgetPodByKey(key string) { } // Extract names for readable logging. -func podNames(pods []api.Pod) []string { +func podNames(pods []*api.Pod) []string { out := make([]string, len(pods)) for i := range pods { out[i] = fmt.Sprintf("'%v/%v (%v)'", pods[i].Namespace, pods[i].Name, pods[i].UID) @@ -131,7 +131,7 @@ func podNames(pods []api.Pod) []string { return out } -func (s *SimpleModeler) listPods(selector labels.Selector) (pods []api.Pod, err error) { +func (s *SimpleModeler) listPods(selector labels.Selector) (pods []*api.Pod, err error) { assumed, err := s.assumedPods.List(selector) if err != nil { return nil, err @@ -140,20 +140,20 @@ func (s *SimpleModeler) listPods(selector labels.Selector) (pods []api.Pod, err // Goal here is to stop making assumptions about a pod once it shows // up in one of these other lists. for _, pod := range assumed { - qExist, err := s.queuedPods.Exists(&pod) + qExist, err := s.queuedPods.Exists(pod) if err != nil { return nil, err } if qExist { - s.assumedPods.Store.Delete(&pod) + s.assumedPods.Store.Delete(pod) continue } - sExist, err := s.scheduledPods.Exists(&pod) + sExist, err := s.scheduledPods.Exists(pod) if err != nil { return nil, err } if sExist { - s.assumedPods.Store.Delete(&pod) + s.assumedPods.Store.Delete(pod) continue } } @@ -190,6 +190,6 @@ type simpleModelerPods struct { } // List returns pods known and assumed to exist. -func (s simpleModelerPods) List(selector labels.Selector) (pods []api.Pod, err error) { +func (s simpleModelerPods) List(selector labels.Selector) (pods []*api.Pod, err error) { return s.simpleModeler.listPods(selector) } diff --git a/plugin/pkg/scheduler/modeler_test.go b/plugin/pkg/scheduler/modeler_test.go index 45fd3914b89..d4bb3526058 100644 --- a/plugin/pkg/scheduler/modeler_test.go +++ b/plugin/pkg/scheduler/modeler_test.go @@ -30,15 +30,15 @@ type nn struct { type names []nn -func (ids names) list() []api.Pod { - out := make([]api.Pod, len(ids)) - for i, id := range ids { - out[i] = api.Pod{ +func (ids names) list() []*api.Pod { + out := make([]*api.Pod, 0, len(ids)) + for _, id := range ids { + out = append(out, &api.Pod{ ObjectMeta: api.ObjectMeta{ Namespace: id.namespace, Name: id.name, }, - } + }) } return out } @@ -54,9 +54,9 @@ func (ids names) has(pod *api.Pod) bool { func TestModeler(t *testing.T) { table := []struct { - queuedPods []api.Pod - scheduledPods []api.Pod - assumedPods []api.Pod + queuedPods []*api.Pod + scheduledPods []*api.Pod + assumedPods []*api.Pod expectPods names }{ { @@ -79,16 +79,16 @@ func TestModeler(t *testing.T) { for _, item := range table { q := &cache.StoreToPodLister{cache.NewStore(cache.MetaNamespaceKeyFunc)} - for i := range item.queuedPods { - q.Store.Add(&item.queuedPods[i]) + for _, pod := range item.queuedPods { + q.Store.Add(pod) } s := &cache.StoreToPodLister{cache.NewStore(cache.MetaNamespaceKeyFunc)} - for i := range item.scheduledPods { - s.Store.Add(&item.scheduledPods[i]) + for _, pod := range item.scheduledPods { + s.Store.Add(pod) } m := NewSimpleModeler(q, s) - for i := range item.assumedPods { - m.AssumePod(&item.assumedPods[i]) + for _, pod := range item.assumedPods { + m.AssumePod(pod) } list, err := m.PodLister().List(labels.Everything()) @@ -98,14 +98,14 @@ func TestModeler(t *testing.T) { found := 0 for _, pod := range list { - if item.expectPods.has(&pod) { + if item.expectPods.has(pod) { found++ } else { t.Errorf("found unexpected pod %#v", pod) } } if e, a := item.expectPods, found; len(e) != a { - t.Errorf("Expected pods:\n%+v\nFound pods:\n%v\n", e, list) + t.Errorf("Expected pods:\n%+v\nFound pods:\n%s\n", podNames(e.list()), podNames(list)) } } } diff --git a/plugin/pkg/scheduler/scheduler.go b/plugin/pkg/scheduler/scheduler.go index 1ff417b97c5..49987c17492 100644 --- a/plugin/pkg/scheduler/scheduler.go +++ b/plugin/pkg/scheduler/scheduler.go @@ -112,7 +112,7 @@ func (s *Scheduler) scheduleOne() { defer func() { metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start)) }() - dest, err := s.config.Algorithm.Schedule(*pod, s.config.MinionLister) + dest, err := s.config.Algorithm.Schedule(pod, s.config.MinionLister) metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start)) if err != nil { glog.V(1).Infof("Failed to schedule: %v", pod) diff --git a/plugin/pkg/scheduler/scheduler_test.go b/plugin/pkg/scheduler/scheduler_test.go index 41b8c0cf040..3766e4ade8e 100644 --- a/plugin/pkg/scheduler/scheduler_test.go +++ b/plugin/pkg/scheduler/scheduler_test.go @@ -59,7 +59,7 @@ type mockScheduler struct { err error } -func (es mockScheduler) Schedule(pod api.Pod, ml scheduler.MinionLister) (string, error) { +func (es mockScheduler) Schedule(pod *api.Pod, ml scheduler.MinionLister) (string, error) { return es.machine, es.err }