diff --git a/lib/backend/k8s/k8s.go b/lib/backend/k8s/k8s.go index 5c9a1bc4a..09458bb77 100644 --- a/lib/backend/k8s/k8s.go +++ b/lib/backend/k8s/k8s.go @@ -114,8 +114,13 @@ func (c *KubeClient) Update(d *model.KVPair) (*model.KVPair, error) { // Set an existing entry in the datastore. This ignores whether an entry already // exists. func (c *KubeClient) Apply(d *model.KVPair) (*model.KVPair, error) { - log.Infof("Ignoring 'Apply' for %s", d.Key) - return d, nil + switch d.Key.(type) { + case model.WorkloadEndpointKey: + return c.applyWorkloadEndpoint(d) + default: + log.Infof("Ignoring 'Apply' for %s", d.Key) + return d, nil + } } // Delete an entry in the datastore. This is a no-op when using the k8s backend. @@ -214,6 +219,27 @@ func (c *KubeClient) getProfile(k model.ProfileKey) (*model.KVPair, error) { return c.converter.namespaceToProfile(namespace) } +// applyWorkloadEndpoint patches the existing Pod to include an IP address, if +// one has been set on the workload endpoint. +func (c *KubeClient) applyWorkloadEndpoint(k *model.KVPair) (*model.KVPair, error) { + ips := k.Value.(*model.WorkloadEndpoint).IPv4Nets + if len(ips) > 0 { + ns, name := c.converter.parseWorkloadID(k.Key.(model.WorkloadEndpointKey).WorkloadID) + pod, err := c.clientSet.Pods(ns).Get(name) + if err != nil { + return nil, err + } + pod.Status.PodIP = ips[0].IP.String() + pod, err = c.clientSet.Pods(ns).Update(pod) + if err != nil { + return nil, err + } + log.Debugf("Successfully applied pod: %+v", pod) + return c.converter.podToWorkloadEndpoint(pod) + } + return k, nil +} + // listWorkloadEndpoints lists WorkloadEndpoints from the k8s API based on existing Pods. func (c *KubeClient) listWorkloadEndpoints(l model.WorkloadEndpointListOptions) ([]*model.KVPair, error) { // If a workload is provided, we can do an exact lookup of this diff --git a/lib/backend/k8s/k8s_fv_test.go b/lib/backend/k8s/k8s_fv_test.go index 39049db86..b93edc673 100644 --- a/lib/backend/k8s/k8s_fv_test.go +++ b/lib/backend/k8s/k8s_fv_test.go @@ -283,7 +283,9 @@ var _ = Describe("Test Syncer API for Kubernetes backend", func() { Expect(len(weps)).To(Equal(1)) // Perform a Get and ensure no error in the Calico API. - _, err = c.Get(model.WorkloadEndpointKey{WorkloadID: fmt.Sprintf("default.%s", pod.ObjectMeta.Name)}) + wep, err := c.Get(model.WorkloadEndpointKey{WorkloadID: fmt.Sprintf("default.%s", pod.ObjectMeta.Name)}) + Expect(err).NotTo(HaveOccurred()) + _, err = c.Apply(wep) Expect(err).NotTo(HaveOccurred()) })