diff --git a/go.mod b/go.mod index f3c6fc74dcd..177932f493d 100644 --- a/go.mod +++ b/go.mod @@ -181,7 +181,7 @@ require ( github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/emirpasic/gods v1.12.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/evanphx/json-patch/v5 v5.6.0 github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect github.com/fasthttp-contrib/sessions v0.0.0-20160905201309-74f6ac73d5d5 // indirect github.com/fatih/color v1.13.0 // indirect diff --git a/pkg/injector/pod_patch.go b/pkg/injector/pod_patch.go index cd0d3f636b6..eefd1c1dc7e 100644 --- a/pkg/injector/pod_patch.go +++ b/pkg/injector/pod_patch.go @@ -129,11 +129,13 @@ func (i *injector) getPodPatchOperations(ar *v1.AdmissionReview, }) } - patchOps = append(patchOps, sidecar.PatchOperation{ - Op: "add", - Path: sidecar.PatchPathContainers + "/-", - Value: sidecarContainer, - }) + patchOps = append(patchOps, + sidecar.PatchOperation{ + Op: "add", + Path: sidecar.PatchPathContainers + "/-", + Value: sidecarContainer, + }, + sidecar.AddDaprSideCarInjectedLabel(pod.Labels)) patchOps = append(patchOps, sidecar.AddDaprEnvVarsToContainers(appContainers)...) patchOps = append(patchOps, diff --git a/pkg/injector/sidecar/consts.go b/pkg/injector/sidecar/consts.go index 8823069551a..24d261a95c7 100644 --- a/pkg/injector/sidecar/consts.go +++ b/pkg/injector/sidecar/consts.go @@ -26,12 +26,14 @@ const ( SidecarMetricsPortName = "dapr-metrics" SidecarDebugPortName = "dapr-debug" SidecarHealthzPath = "healthz" + SidecarInjectedLabel = "dapr.io/sidecar-injected" APIVersionV1 = "v1.0" UnixDomainSocketVolume = "dapr-unix-domain-socket" // Name of the Unix domain socket volume. UserContainerDaprHTTPPortName = "DAPR_HTTP_PORT" // Name of the variable exposed to the app containing the Dapr HTTP port. UserContainerDaprGRPCPortName = "DAPR_GRPC_PORT" // Name of the variable exposed to the app containing the Dapr gRPC port. PatchPathContainers = "/spec/containers" PatchPathVolumes = "/spec/volumes" + PatchPathLabels = "/metadata/labels" TokenVolumeKubernetesMountPath = "/var/run/secrets/dapr.io/sentrytoken" /* #nosec */ // Mount path for the Kubernetes service account volume with the sentry token. TokenVolumeName = "dapr-identity-token" /* #nosec */ // Name of the volume with the service account token for daprd. ) diff --git a/pkg/injector/sidecar/pod_patch.go b/pkg/injector/sidecar/pod_patch.go index fa92d472d05..afca20d4729 100644 --- a/pkg/injector/sidecar/pod_patch.go +++ b/pkg/injector/sidecar/pod_patch.go @@ -58,6 +58,24 @@ func AddDaprEnvVarsToContainers(containers map[int]corev1.Container) []PatchOper return envPatchOps } +// AddDaprSideCarInjectedLabel adds Dapr label to patch pod so list of patched pods can be retrieved more efficiently +func AddDaprSideCarInjectedLabel(labels map[string]string) PatchOperation { + if len(labels) == 0 { // empty labels + return PatchOperation{ + Op: "add", + Path: PatchPathLabels, + Value: map[string]string{ + SidecarInjectedLabel: "true", + }, + } + } + return PatchOperation{ + Op: "add", + Path: PatchPathLabels + "/dapr.io~1sidecar-injected", + Value: "true", + } +} + // GetEnvPatchOperations adds new environment variables only if they do not exist. // It does not override existing values for those variables if they have been defined already. func GetEnvPatchOperations(envs []corev1.EnvVar, addEnv []corev1.EnvVar, containerIdx int) []PatchOperation { diff --git a/pkg/injector/sidecar/pod_patch_test.go b/pkg/injector/sidecar/pod_patch_test.go index 15d1e744bfb..a798d9b21dc 100644 --- a/pkg/injector/sidecar/pod_patch_test.go +++ b/pkg/injector/sidecar/pod_patch_test.go @@ -14,11 +14,14 @@ limitations under the License. package sidecar import ( + "encoding/json" "strconv" "testing" + jsonpatch "github.com/evanphx/json-patch/v5" "github.com/stretchr/testify/assert" coreV1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/dapr/dapr/pkg/injector/annotations" ) @@ -141,6 +144,67 @@ func TestAddDaprEnvVarsToContainers(t *testing.T) { } } +func TestAddDaprInjectedLabel(t *testing.T) { + testCases := []struct { + testName string + mockPod coreV1.Pod + expLabels map[string]string + }{ + { + testName: "empty labels", + mockPod: coreV1.Pod{ + ObjectMeta: metav1.ObjectMeta{}, + }, + expLabels: map[string]string{SidecarInjectedLabel: "true"}, + }, + { + testName: "with some previous labels", + mockPod: coreV1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"app": "my-app"}, + }, + }, + expLabels: map[string]string{SidecarInjectedLabel: "true", "app": "my-app"}, + }, + { + testName: "with dapr injected label already present", + mockPod: coreV1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{SidecarInjectedLabel: "true", "app": "my-app"}, + }, + }, + expLabels: map[string]string{SidecarInjectedLabel: "true", "app": "my-app"}, + }, + } + + for _, tc := range testCases { + tc := tc // closure copy + t.Run(tc.testName, func(t *testing.T) { + newPodJSON := patchObject(t, tc.mockPod, []PatchOperation{AddDaprSideCarInjectedLabel(tc.mockPod.Labels)}) + newPod := coreV1.Pod{} + assert.NoError(t, json.Unmarshal(newPodJSON, &newPod)) + assert.Equal(t, tc.expLabels, newPod.Labels) + }) + } +} + +// patchObject executes a jsonpatch action against the object passed +func patchObject(t *testing.T, origObj interface{}, patchOperations []PatchOperation) []byte { + marshal := func(o interface{}) []byte { + objBytes, err := json.Marshal(o) + assert.NoError(t, err) + return objBytes + } + + podJSON := marshal(origObj) + patchJSON := marshal(patchOperations) + decodedPatch, err := jsonpatch.DecodePatch(patchJSON) + assert.NoError(t, err) + newJSON, err := decodedPatch.Apply(podJSON) + assert.NoError(t, err) + return newJSON +} + func TestAddSocketVolumeToContainers(t *testing.T) { testCases := []struct { testName string