Skip to content

Commit 91b8da1

Browse files
authored
feat(ContactPoint): Allow setting editable at creation (#2250)
* feat(ContactPoint): Allow setting editable on create * chore(ContactPoint): Generate docs and CRD
1 parent 6ddbce0 commit 91b8da1

File tree

7 files changed

+86
-3
lines changed

7 files changed

+86
-3
lines changed

api/v1beta1/grafanacontactpoint_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
// GrafanaContactPointSpec defines the desired state of GrafanaContactPoint
2828
// +kubebuilder:validation:XValidation:rule="((!has(oldSelf.name) && !has(self.name)) || (has(oldSelf.name) && has(self.name)))", message="spec.name is immutable"
29+
// +kubebuilder:validation:XValidation:rule="((!has(oldSelf.editable) && !has(self.editable)) || (has(oldSelf.editable) && has(self.editable)))", message="spec.editable is immutable"
2930
type GrafanaContactPointSpec struct {
3031
GrafanaCommonSpec `json:",inline"`
3132

@@ -41,6 +42,11 @@ type GrafanaContactPointSpec struct {
4142
// +kubebuilder:validation:MaxItems=99
4243
Receivers []ContactPointReceiver `json:"receivers,omitempty"`
4344

45+
// Whether to enable or disable editing of the contact point in Grafana UI
46+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="spec.editable is immutable"
47+
// +optional
48+
Editable bool `json:"editable,omitempty"`
49+
4450
// Deprecated: define the receiver under .spec.receivers[]
4551
// Manually specify the UID the Contact Point is created with. Can be any string consisting of alphanumeric characters, - and _ with a maximum length of 40
4652
// +optional

api/v1beta1/grafanacontactpoint_types_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,36 @@ var _ = Describe("ContactPoint type", func() {
7878
})
7979
})
8080

81+
Context("Ensure ContactPoint spec.editable is immutable", func() {
82+
t := GinkgoT()
83+
84+
It("Should block enabling editable", func() {
85+
contactpoint := newContactPoint("updating-editable")
86+
contactpoint.Spec.Type = "webhook" // nolint:goconst
87+
contactpoint.Spec.Editable = false
88+
89+
err := k8sClient.Create(t.Context(), contactpoint)
90+
require.NoError(t, err)
91+
92+
contactpoint.Spec.Editable = true
93+
err = k8sClient.Update(t.Context(), contactpoint)
94+
require.Error(t, err)
95+
})
96+
97+
It("Should block disabling editable", func() {
98+
contactpoint := newContactPoint("removing-editable")
99+
contactpoint.Spec.Type = "webhook"
100+
contactpoint.Spec.Editable = true
101+
102+
err := k8sClient.Create(t.Context(), contactpoint)
103+
require.NoError(t, err)
104+
105+
contactpoint.Spec.Editable = false
106+
err = k8sClient.Update(t.Context(), contactpoint)
107+
require.Error(t, err)
108+
})
109+
})
110+
81111
Context("Ensure ContactPoint receivers is correctly handled", func() {
82112
settings := apiextensionsv1.JSON{Raw: []byte("{}")}
83113

config/crd/bases/grafana.integreatly.org_grafanacontactpoints.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ spec:
6060
Deprecated: define the receiver under .spec.receivers[]
6161
Will be removed in a later version
6262
type: boolean
63+
editable:
64+
description: Whether to enable or disable editing of the contact point
65+
in Grafana UI
66+
type: boolean
67+
x-kubernetes-validations:
68+
- message: spec.editable is immutable
69+
rule: self == oldSelf
6370
instanceSelector:
6471
description: Selects Grafana instances for import
6572
properties:
@@ -315,6 +322,9 @@ spec:
315322
- message: spec.name is immutable
316323
rule: ((!has(oldSelf.name) && !has(self.name)) || (has(oldSelf.name)
317324
&& has(self.name)))
325+
- message: spec.editable is immutable
326+
rule: ((!has(oldSelf.editable) && !has(self.editable)) || (has(oldSelf.editable)
327+
&& has(self.editable)))
318328
- message: disabling spec.allowCrossNamespaceImport requires a recreate
319329
to ensure desired state
320330
rule: '!oldSelf.allowCrossNamespaceImport || (oldSelf.allowCrossNamespaceImport

controllers/contactpoint_controller.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,17 @@ func (r *GrafanaContactPointReconciler) reconcileWithInstance(ctx context.Contex
198198
}
199199

200200
if existingIdx == -1 {
201-
cp.UID = recUID
202201
log.Info("create missing contact point receiver", "uid", recUID)
203202

204-
_, err := cl.Provisioning.PostContactpoints(provisioning.NewPostContactpointsParams().WithBody(cp)) //nolint:errcheck
203+
cp.UID = recUID
204+
params := provisioning.NewPostContactpointsParams().WithBody(cp)
205+
206+
if cr.Spec.Editable {
207+
editable := "true"
208+
params = params.WithXDisableProvenance(&editable)
209+
}
210+
211+
_, err := cl.Provisioning.PostContactpoints(params) //nolint:errcheck
205212
if err != nil {
206213
return fmt.Errorf("creating contact point receiver: %w", err)
207214
}
@@ -214,6 +221,7 @@ func (r *GrafanaContactPointReconciler) reconcileWithInstance(ctx context.Contex
214221
!reflect.DeepEqual(cp.Settings, remote.Settings) {
215222
log.Info("update existing contact point receiver", "uid", recUID)
216223

224+
// TODO Implement provenance when Grafana API allows changing it
217225
_, err := cl.Provisioning.PutContactpoint(provisioning.NewPutContactpointParams().WithUID(recUID).WithBody(cp)) //nolint:errcheck
218226
if err != nil {
219227
return fmt.Errorf("updating contact point receiver: %w", err)

deploy/helm/grafana-operator/files/crds/grafana.integreatly.org_grafanacontactpoints.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ spec:
6060
Deprecated: define the receiver under .spec.receivers[]
6161
Will be removed in a later version
6262
type: boolean
63+
editable:
64+
description: Whether to enable or disable editing of the contact point
65+
in Grafana UI
66+
type: boolean
67+
x-kubernetes-validations:
68+
- message: spec.editable is immutable
69+
rule: self == oldSelf
6370
instanceSelector:
6471
description: Selects Grafana instances for import
6572
properties:
@@ -315,6 +322,9 @@ spec:
315322
- message: spec.name is immutable
316323
rule: ((!has(oldSelf.name) && !has(self.name)) || (has(oldSelf.name)
317324
&& has(self.name)))
325+
- message: spec.editable is immutable
326+
rule: ((!has(oldSelf.editable) && !has(self.editable)) || (has(oldSelf.editable)
327+
&& has(self.editable)))
318328
- message: disabling spec.allowCrossNamespaceImport requires a recreate
319329
to ensure desired state
320330
rule: '!oldSelf.allowCrossNamespaceImport || (oldSelf.allowCrossNamespaceImport

deploy/kustomize/base/crds.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,13 @@ spec:
433433
Deprecated: define the receiver under .spec.receivers[]
434434
Will be removed in a later version
435435
type: boolean
436+
editable:
437+
description: Whether to enable or disable editing of the contact point
438+
in Grafana UI
439+
type: boolean
440+
x-kubernetes-validations:
441+
- message: spec.editable is immutable
442+
rule: self == oldSelf
436443
instanceSelector:
437444
description: Selects Grafana instances for import
438445
properties:
@@ -688,6 +695,9 @@ spec:
688695
- message: spec.name is immutable
689696
rule: ((!has(oldSelf.name) && !has(self.name)) || (has(oldSelf.name)
690697
&& has(self.name)))
698+
- message: spec.editable is immutable
699+
rule: ((!has(oldSelf.editable) && !has(self.editable)) || (has(oldSelf.editable)
700+
&& has(self.editable)))
691701
- message: disabling spec.allowCrossNamespaceImport requires a recreate
692702
to ensure desired state
693703
rule: '!oldSelf.allowCrossNamespaceImport || (oldSelf.allowCrossNamespaceImport

docs/docs/api.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ GrafanaContactPoint is the Schema for the grafanacontactpoints API
752752
<td>
753753
GrafanaContactPointSpec defines the desired state of GrafanaContactPoint<br/>
754754
<br/>
755-
<i>Validations</i>:<li>((!has(oldSelf.name) && !has(self.name)) || (has(oldSelf.name) && has(self.name))): spec.name is immutable</li><li>!oldSelf.allowCrossNamespaceImport || (oldSelf.allowCrossNamespaceImport && self.allowCrossNamespaceImport): disabling spec.allowCrossNamespaceImport requires a recreate to ensure desired state</li>
755+
<i>Validations</i>:<li>((!has(oldSelf.name) && !has(self.name)) || (has(oldSelf.name) && has(self.name))): spec.name is immutable</li><li>((!has(oldSelf.editable) && !has(self.editable)) || (has(oldSelf.editable) && has(self.editable))): spec.editable is immutable</li><li>!oldSelf.allowCrossNamespaceImport || (oldSelf.allowCrossNamespaceImport && self.allowCrossNamespaceImport): disabling spec.allowCrossNamespaceImport requires a recreate to ensure desired state</li>
756756
</td>
757757
<td>true</td>
758758
</tr><tr>
@@ -808,6 +808,15 @@ GrafanaContactPointSpec defines the desired state of GrafanaContactPoint
808808
Will be removed in a later version<br/>
809809
</td>
810810
<td>false</td>
811+
</tr><tr>
812+
<td><b>editable</b></td>
813+
<td>boolean</td>
814+
<td>
815+
Whether to enable or disable editing of the contact point in Grafana UI<br/>
816+
<br/>
817+
<i>Validations</i>:<li>self == oldSelf: spec.editable is immutable</li>
818+
</td>
819+
<td>false</td>
811820
</tr><tr>
812821
<td><b>name</b></td>
813822
<td>string</td>

0 commit comments

Comments
 (0)