func TestStoreBasicExport(t *testing.T) { podA := api.Pod{ ObjectMeta: api.ObjectMeta{ Namespace: "test", Name: "foo", Labels: map[string]string{}, }, Spec: api.PodSpec{NodeName: "machine"}, Status: api.PodStatus{HostIP: "1.2.3.4"}, } server, registry := NewTestGenericStoreRegistry(t) defer server.Terminate(t) testContext := api.WithNamespace(api.NewContext(), "test") registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true if !updateAndVerify(t, testContext, registry, &podA) { t.Errorf("Unexpected error updating podA") } obj, err := registry.Export(testContext, podA.Name, unversioned.ExportOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } exportedPod := obj.(*api.Pod) if exportedPod.Labels["prepare_create"] != "true" { t.Errorf("expected: prepare_create->true, found: %s", exportedPod.Labels["prepare_create"]) } delete(exportedPod.Labels, "prepare_create") exportObjectMeta(&podA.ObjectMeta, false) podA.Spec = exportedPod.Spec if !reflect.DeepEqual(&podA, exportedPod) { t.Errorf("expected:\n%v\nsaw:\n%v\n", &podA, exportedPod) } }
// checkAndUpdatePod updates existing, and: // * if ref makes a meaningful change, returns needUpdate=true // * if ref makes no meaningful change, but changes the pod status, returns needReconcile=true // * else return both false // Now, needUpdate and needReconcile should never be both true func checkAndUpdatePod(existing, ref *api.Pod) (needUpdate, needReconcile bool) { // TODO: it would be better to update the whole object and only preserve certain things // like the source annotation or the UID (to ensure safety) if !podsDifferSemantically(existing, ref) { // this is not an update // Only check reconcile when it is not an update, because if the pod is going to // be updated, an extra reconcile is unnecessary if !reflect.DeepEqual(existing.Status, ref.Status) { // Pod with changed pod status needs reconcile, because kubelet should // be the source of truth of pod status. existing.Status = ref.Status needReconcile = true } return } // this is an update // Overwrite the first-seen time with the existing one. This is our own // internal annotation, there is no need to update. ref.Annotations[kubetypes.ConfigFirstSeenAnnotationKey] = existing.Annotations[kubetypes.ConfigFirstSeenAnnotationKey] existing.Spec = ref.Spec existing.Labels = ref.Labels existing.DeletionTimestamp = ref.DeletionTimestamp existing.DeletionGracePeriodSeconds = ref.DeletionGracePeriodSeconds existing.Status = ref.Status updateAnnotations(existing, ref) needUpdate = true return }
// checkAndUpdatePod updates existing if ref makes a meaningful change and returns true, or // returns false if there was no update. func checkAndUpdatePod(existing, ref *api.Pod) bool { // TODO: it would be better to update the whole object and only preserve certain things // like the source annotation or the UID (to ensure safety) if reflect.DeepEqual(existing.Spec, ref.Spec) && reflect.DeepEqual(existing.DeletionTimestamp, ref.DeletionTimestamp) && reflect.DeepEqual(existing.DeletionGracePeriodSeconds, ref.DeletionGracePeriodSeconds) { return false } // this is an update existing.Spec = ref.Spec existing.DeletionTimestamp = ref.DeletionTimestamp existing.DeletionGracePeriodSeconds = ref.DeletionGracePeriodSeconds return true }
// checkAndUpdatePod updates existing if ref makes a meaningful change and returns true, or // returns false if there was no update. func checkAndUpdatePod(existing, ref *api.Pod) bool { // TODO: it would be better to update the whole object and only preserve certain things // like the source annotation or the UID (to ensure safety) if !podsDifferSemantically(existing, ref) { return false } // this is an update // Overwrite the first-seen time with the existing one. This is our own // internal annotation, there is no need to update. ref.Annotations[kubelet.ConfigFirstSeenAnnotationKey] = existing.Annotations[kubelet.ConfigFirstSeenAnnotationKey] existing.Spec = ref.Spec existing.DeletionTimestamp = ref.DeletionTimestamp existing.DeletionGracePeriodSeconds = ref.DeletionGracePeriodSeconds updateAnnotations(existing, ref) return true }
func TestStoreCustomExport(t *testing.T) { podA := api.Pod{ ObjectMeta: api.ObjectMeta{ Namespace: "test", Name: "foo", Labels: map[string]string{}, }, Spec: api.PodSpec{NodeName: "machine"}, } destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() registry.ExportStrategy = testPodExport{} testContext := api.WithNamespace(api.NewContext(), "test") registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true if !updateAndVerify(t, testContext, registry, &podA) { t.Errorf("Unexpected error updating podA") } obj, err := registry.Export(testContext, podA.Name, metav1.ExportOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } exportedPod := obj.(*api.Pod) if exportedPod.Labels["exported"] != "true" { t.Errorf("expected: exported->true, found: %s", exportedPod.Labels["exported"]) } if exportedPod.Labels["exact"] != "false" { t.Errorf("expected: exact->false, found: %s", exportedPod.Labels["exact"]) } if exportedPod.Labels["prepare_create"] != "true" { t.Errorf("expected: prepare_create->true, found: %s", exportedPod.Labels["prepare_create"]) } delete(exportedPod.Labels, "exported") delete(exportedPod.Labels, "exact") delete(exportedPod.Labels, "prepare_create") exportObjectMeta(&podA.ObjectMeta, false) podA.Spec = exportedPod.Spec if !reflect.DeepEqual(&podA, exportedPod) { t.Errorf("expected:\n%v\nsaw:\n%v\n", &podA, exportedPod) } }