Example #1
0
// 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
}
Example #2
0
// 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[kubeletTypes.ConfigFirstSeenAnnotationKey] = existing.Annotations[kubeletTypes.ConfigFirstSeenAnnotationKey]

	existing.Spec = ref.Spec
	existing.Labels = ref.Labels
	existing.DeletionTimestamp = ref.DeletionTimestamp
	existing.DeletionGracePeriodSeconds = ref.DeletionGracePeriodSeconds
	updateAnnotations(existing, ref)
	return true
}
func TestConsistencyPodUpdateRemovePrev(t *testing.T) {
	env := new(TestFramework)
	env.SetUp("192.0.2.0/24")
	client := env.client
	config := env.config

	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "x-1",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":                  "client",
				config.NetworkTag:       "client",
				config.NetworkAccessTag: "red",
			},
		},
	}

	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "x-2",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":                  "client",
				config.NetworkTag:       "client",
				config.NetworkAccessTag: "red",
			},
		},
	}

	pod3 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "redPod",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "red",
				config.NetworkTag: "redPrivate",
			},
		},
	}

	pod4 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "bluePod",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "blue",
				config.NetworkTag: "bluePrivate",
			},
		},
	}

	redService := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "red",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "red",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "red",
			},
			ClusterIP: "10.254.42.42",
		},
	}

	blueService := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "blue",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "blue",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "blue",
			},
			ClusterIP: "10.254.42.43",
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	env.Start()

	env.AddPod(pod1)
	env.AddService(redService, "red")
	env.AddPod(pod2)
	env.AddPod(pod3)
	env.AddPod(pod4)
	env.AddService(blueService, "blue")
	env.SyncBarrier()

	serviceConnections := getNetworkServiceConnections(t, client, config, "testns", "client")
	assert.EqualValues(t, []string{"default", "red"}, serviceConnections)
	assert.True(t, env.checker.Check())
	policyName := makeServicePolicyName(config, "testns", "red")
	_, err := types.NetworkPolicyByName(client, strings.Join(policyName, ":"))
	assert.NoError(t, err)

	clonePodAndUpdateAccessTag := func(pod *api.Pod, color string) *api.Pod {
		newPod := new(api.Pod)
		*newPod = *pod
		newPod.Labels = make(map[string]string, 0)
		for k, v := range pod.Labels {
			newPod.Labels[k] = v
		}
		newPod.Labels[config.NetworkAccessTag] = color
		return newPod
	}

	// Update connections on pod1
	nPod1 := clonePodAndUpdateAccessTag(pod1, "blue")
	env.UpdatePod(pod1, nPod1)
	env.SyncBarrier()

	serviceConnections = getNetworkServiceConnections(t, client, config, "testns", "client")
	assert.EqualValues(t, []string{"default", "red", "blue"}, serviceConnections)
	assert.True(t, env.checker.Check(), "red and blue present")

	// Update connections on pod2
	// This will leave a stale connection to network red.
	nPod2 := clonePodAndUpdateAccessTag(pod2, "blue")
	env.UpdatePod(pod2, nPod2)
	env.SyncBarrier()

	serviceConnections = getNetworkServiceConnections(t, client, config, "testns", "client")
	assert.EqualValues(t, []string{"default", "red", "blue"}, serviceConnections)

	assert.False(t, env.checker.Check())

	env.DeleteService(redService, "red")
	env.SyncBarrier()

	// The second pass will delete the connection to network red.
	assert.False(t, env.checker.Check())
	serviceConnections = getNetworkServiceConnections(t, client, config, "testns", "client")
	assert.EqualValues(t, []string{"default", "blue"}, serviceConnections)

	assert.True(t, env.checker.Check())

	env.Shutdown()

	_, err = types.NetworkPolicyByName(client, strings.Join(policyName, ":"))
	assert.Error(t, err)
}