Repository: m3db/m3db-operator
Pull request #210 (2020-04-14 03:04:25)

Added initial support for PodMetaData, handling Annotations only
The general Annotations in the ClusterSpec get applied to both the Services and the Pods.  There are cases where the user wants annotation exclusively for the Pod, such as when marking a Pod to be scraped by Prometheus.  This PR puts in an ObjectMeta at the PodMetadata metav1.ClusterSpec level to facilitate specifying Pod-only Metadata.  I've only implemented Annotations.  I've added a test case for the Pod-only annotations.


codecov[bot]: # [Codecov](https://codecov.io/gh/m3db/m3db-operator/pull/210?src=pr&el=h1) Report
> Merging [#210](https://codecov.io/gh/m3db/m3db-operator/pull/210?src=pr&el=desc) into [master](https://codecov.io/gh/m3db/m3db-operator/commit/895fc3f9bb8396137df4423f10d3199fff9ee759&el=desc) will **increase** coverage by `0.07%`.
> The diff coverage is `100.00%`.


[![Impacted file tree graph](https://codecov.io/gh/m3db/m3db-operator/pull/210/graphs/tree.svg?width=650&height=150&src=pr&token=jtHDyWhsto)](https://codecov.io/gh/m3db/m3db-operator/pull/210?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #210      +/-   ##
==========================================
+ Coverage   75.23%   75.30%   +0.07%     
==========================================
  Files          30       30              
  Lines        2104     2110       +6     
==========================================
+ Hits         1583     1589       +6     
  Misses        393      393              
  Partials      128      128              
```


------

[Continue to review full report at Codecov](https://codecov.io/gh/m3db/m3db-operator/pull/210?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/m3db/m3db-operator/pull/210?src=pr&el=footer). Last update [895fc3f...ac05ef2](https://codecov.io/gh/m3db/m3db-operator/pull/210?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/docs/api.md b/docs/api.md
index 0825196..6478fb2 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -65,6 +65,7 @@ ClusterSpec defines the desired state for a M3 cluster to be converge to.
 | externalCoordinatorSelector | Specify a \"controlling\" coordinator for the cluster It is expected that there is a separate standalone coordinator cluster It is externally managed - not managed by this operator It is expected to have a service endpoint Setup this db cluster, but do not assume a co-located coordinator Instead provide a selector here so we can point to a separate coordinator service Specify here the labels required for the selector | map[string]string | false |
 | initContainers | Custom setup for db nodes can be done via initContainers Provide the complete spec for the initContainer here If any storage volumes are needed in the initContainer see InitVolumes below | []corev1.Container | false |
 | initVolumes | If the InitContainers require any storage volumes Provide the complete specification for the required Volumes here | []corev1.Volume | false |
+| podMetadata | PodMetadata is for any Metadata that is unique to the pods, and does not belong on any other objects, such as Prometheus scrape tags | [metav1.ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/#objectmeta-v1-meta) | false |
 
 [Back to TOC](#table-of-contents)
 
diff --git a/pkg/apis/m3dboperator/v1alpha1/cluster.go b/pkg/apis/m3dboperator/v1alpha1/cluster.go
index 66b044f..ea16bc0 100644
--- a/pkg/apis/m3dboperator/v1alpha1/cluster.go
+++ b/pkg/apis/m3dboperator/v1alpha1/cluster.go
@@ -295,6 +295,10 @@ type ClusterSpec struct {
 	// If the InitContainers require any storage volumes
 	// Provide the complete specification for the required Volumes here
 	InitVolumes []corev1.Volume `json:"initVolumes,omitempty"`
+
+	// PodMetadata is for any Metadata that is unique to the pods, and does
+	// not belong on any other objects, such as Prometheus scrape tags
+	PodMetadata metav1.ObjectMeta `json:"podMetadata,omitempty"`
 }
 
 // NodeAffinityTerm represents a node label and a set of label values, any of
diff --git a/pkg/k8sops/annotations/annotations.go b/pkg/k8sops/annotations/annotations.go
index dc8964d..b6dc6f4 100644
--- a/pkg/k8sops/annotations/annotations.go
+++ b/pkg/k8sops/annotations/annotations.go
@@ -51,3 +51,17 @@ func BaseAnnotations(cluster *myspec.M3DBCluster) map[string]string {
 
 	return base
 }
+
+// PodAnnotations is for specifying annotations that are only to be
+// applied to the pods such as prometheus scrape tags
+func PodAnnotations(cluster *myspec.M3DBCluster) map[string]string {
+	base := BaseAnnotations(cluster)
+	for k := range cluster.Spec.PodMetadata.Annotations {
+		// accept any user-specified annotations if its safe to do so
+		if _, found := base[k]; !found {
+			base[k] = cluster.Spec.PodMetadata.Annotations[k]
+		}
+	}
+
+	return base
+}
diff --git a/pkg/k8sops/m3db/statefulset.go b/pkg/k8sops/m3db/statefulset.go
index 68a1f99..63c6725 100644
--- a/pkg/k8sops/m3db/statefulset.go
+++ b/pkg/k8sops/m3db/statefulset.go
@@ -63,7 +63,7 @@ func NewBaseStatefulSet(ssName, isolationGroup string, cluster *myspec.M3DBClust
 		objLabels[k] = v
 	}
 
-	objAnnotations := annotations.BaseAnnotations(cluster)
+	objAnnotations := annotations.PodAnnotations(cluster)
 
 	// TODO(schallert): we're currently using the health of the coordinator for
 	// liveness probes until https://github.com/m3db/m3/issues/996 is fixed. Move


Test patch:
diff --git a/pkg/k8sops/annotations/annotations_test.go b/pkg/k8sops/annotations/annotations_test.go
index a479fb3..ffa8923 100644
--- a/pkg/k8sops/annotations/annotations_test.go
+++ b/pkg/k8sops/annotations/annotations_test.go
@@ -51,3 +51,34 @@ func TestGenerateBaseAnnotations(t *testing.T) {
 
 	assert.Equal(t, expAnnotations, annotations)
 }
+
+func TestGeneratePodAnnotations(t *testing.T) {
+	cluster := &myspec.M3DBCluster{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "cluster-foo",
+		},
+		Spec: myspec.ClusterSpec{
+			PodMetadata: metav1.ObjectMeta{
+				Annotations: map[string]string{
+					"pod-annotation": "some-annotation",
+				},
+			},
+		},
+	}
+
+	annotations := PodAnnotations(cluster)
+	expAnnotations := map[string]string{
+		"operator.m3db.io/app":     "m3db",
+		"operator.m3db.io/cluster": "cluster-foo",
+		"pod-annotation":           "some-annotation",
+	}
+
+	assert.Equal(t, expAnnotations, annotations)
+
+	cluster.Spec.Annotations = map[string]string{"foo": "bar"}
+	annotations = PodAnnotations(cluster)
+	expAnnotations["foo"] = "bar"
+	expAnnotations["pod-annotation"] = "some-annotation"
+
+	assert.Equal(t, expAnnotations, annotations)
+}