Skip to content

Commit

Permalink
chore: pass linter
Browse files Browse the repository at this point in the history
  • Loading branch information
chenlujjj committed Dec 17, 2024
1 parent 418969f commit 57ba3aa
Show file tree
Hide file tree
Showing 12 changed files with 230 additions and 113 deletions.
46 changes: 32 additions & 14 deletions api/v1beta1/grafananotificationtemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,34 @@ package v1beta1

import (
"fmt"
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// GrafanaNotificationTemplateSpec defines the desired state of GrafanaNotificationTemplate
// +kubebuilder:validation:XValidation:rule="((!has(oldSelf.editable) && !has(self.editable)) || (has(oldSelf.editable) && has(self.editable)))", message="spec.editable is immutable"
type GrafanaNotificationTemplateSpec struct {
// +optional
// +kubebuilder:validation:Type=string
// +kubebuilder:validation:Format=duration
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$"
// +kubebuilder:default="10m"
ResyncPeriod metav1.Duration `json:"resyncPeriod,omitempty"`

// selects Grafanas for import
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
InstanceSelector *metav1.LabelSelector `json:"instanceSelector"`
GrafanaCommonSpec `json:",inline"`

// Template name
Name string `json:"name"`

// Template content
Template string `json:"template,omitempty"`

// Whether to enable or disable editing of the notification template in Grafana UI
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="spec.editable is immutable"
// +optional
Editable *bool `json:"editable,omitempty"`

// +optional
AllowCrossNamespaceImport *bool `json:"allowCrossNamespaceImport,omitempty"`
}

// GrafanaNotificationTemplateStatus defines the observed state of GrafanaNotificationTemplate
type GrafanaNotificationTemplateStatus struct {
// The notification template instanceSelector can't find matching grafana instances
NoMatchingInstances bool `json:"NoMatchingInstances,omitempty"`
// Last time the folder was resynced
LastResync metav1.Time `json:"lastResync,omitempty"`
Conditions []metav1.Condition `json:"conditions"`
}

Expand All @@ -66,6 +62,28 @@ type GrafanaNotificationTemplate struct {
Status GrafanaNotificationTemplateStatus `json:"status,omitempty"`
}

var _ CommonResource = (*GrafanaNotificationTemplate)(nil)

func (in *GrafanaNotificationTemplate) ResyncPeriodHasElapsed() bool {
deadline := in.Status.LastResync.Add(in.Spec.ResyncPeriod.Duration)
return time.Now().After(deadline)
}

func (in *GrafanaNotificationTemplate) MatchLabels() *metav1.LabelSelector {
return in.Spec.InstanceSelector
}

func (in *GrafanaNotificationTemplate) MatchNamespace() string {
return in.ObjectMeta.Namespace
}

func (in *GrafanaNotificationTemplate) AllowCrossNamespace() bool {
if in.Spec.AllowCrossNamespaceImport != nil {
return *in.Spec.AllowCrossNamespaceImport
}
return false
}

func (np *GrafanaNotificationTemplate) NamespacedResource() string {
return fmt.Sprintf("%v/%v/%v", np.ObjectMeta.Namespace, np.ObjectMeta.Name, np.ObjectMeta.UID)
}
Expand Down
72 changes: 72 additions & 0 deletions api/v1beta1/grafananotificationtemplate_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package v1beta1

import (
"context"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func newNotificationTemplate(name string, editable *bool) *GrafanaNotificationTemplate {
return &GrafanaNotificationTemplate{
TypeMeta: v1.TypeMeta{
APIVersion: APIVersion,
Kind: "GrafanaNotificationTemplate",
},
ObjectMeta: v1.ObjectMeta{
Name: name,
Namespace: "default",
},
Spec: GrafanaNotificationTemplateSpec{
Editable: editable,
GrafanaCommonSpec: GrafanaCommonSpec{
InstanceSelector: &v1.LabelSelector{
MatchLabels: map[string]string{
"test": "notificationtemplate",
},
},
},
Name: name,
Template: "mock template",
},
}
}

var _ = Describe("NotificationTemplate type", func() {
Context("Ensure NotificationTemplate spec.editable is immutable", func() {
ctx := context.Background()
refTrue := true
refFalse := false

It("Should block adding editable field when missing", func() {
notificationtemplate := newNotificationTemplate("missing-editable", nil)
By("Create new NotificationTemplate without editable")
Expect(k8sClient.Create(ctx, notificationtemplate)).To(Succeed())

By("Adding a editable")
notificationtemplate.Spec.Editable = &refTrue
Expect(k8sClient.Update(ctx, notificationtemplate)).To(HaveOccurred())
})

It("Should block removing editable field when set", func() {
notificationtemplate := newNotificationTemplate("existing-editable", &refTrue)
By("Creating NotificationTemplate with existing editable")
Expect(k8sClient.Create(ctx, notificationtemplate)).To(Succeed())

By("And setting editable to ''")
notificationtemplate.Spec.Editable = nil
Expect(k8sClient.Update(ctx, notificationtemplate)).To(HaveOccurred())
})

It("Should block changing value of editable", func() {
notificationtemplate := newNotificationTemplate("removing-editable", &refTrue)
By("Create new NotificationTemplate with existing editable")
Expect(k8sClient.Create(ctx, notificationtemplate)).To(Succeed())

By("Changing the existing editable")
notificationtemplate.Spec.Editable = &refFalse
Expect(k8sClient.Update(ctx, notificationtemplate)).To(HaveOccurred())
})
})
})
13 changes: 2 additions & 11 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,18 @@ spec:
of GrafanaNotificationTemplate
properties:
allowCrossNamespaceImport:
description: Allow the Operator to match this resource with Grafanas
outside the current namespace
type: boolean
editable:
description: Whether to enable or disable editing of the notification
template in Grafana UI
type: boolean
x-kubernetes-validations:
- message: Value is immutable
- message: spec.editable is immutable
rule: self == oldSelf
instanceSelector:
description: selects Grafanas for import
description: Selects Grafana instances for import
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
Expand Down Expand Up @@ -99,25 +101,37 @@ spec:
type: object
x-kubernetes-map-type: atomic
x-kubernetes-validations:
- message: Value is immutable
- message: spec.instanceSelector is immutable
rule: self == oldSelf
name:
description: Template name
type: string
resyncPeriod:
default: 10m
default: 10m0s
description: How often the resource is synced, defaults to 10m0s if
not set
format: duration
pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$
type: string
template:
description: Template content
type: string
required:
- instanceSelector
- name
type: object
x-kubernetes-validations:
- message: spec.editable is immutable
rule: ((!has(oldSelf.editable) && !has(self.editable)) || (has(oldSelf.editable)
&& has(self.editable)))
status:
description: GrafanaNotificationTemplateStatus defines the observed state
of GrafanaNotificationTemplate
properties:
NoMatchingInstances:
description: The notification template instanceSelector can't find
matching grafana instances
type: boolean
conditions:
items:
description: Condition contains details for one aspect of the current
Expand Down Expand Up @@ -174,6 +188,10 @@ spec:
- type
type: object
type: array
lastResync:
description: Last time the folder was resynced
format: date-time
type: string
required:
- conditions
type: object
Expand Down
Empty file.
15 changes: 10 additions & 5 deletions controllers/controller_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ import (
const grafanaFinalizer = "operator.grafana.com/finalizer"

const (
// condition types
conditionNoMatchingInstance = "NoMatchingInstance"
conditionNoMatchingFolder = "NoMatchingFolder"
conditionInvalidSpec = "InvalidSpec"

// condition reasons
conditionApplySuccessful = "ApplySuccessful"
conditionApplyFailed = "ApplyFailed"
)

//+kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -256,7 +261,7 @@ func setNoMatchingInstancesCondition(conditions *[]metav1.Condition, generation
func setNoMatchingInstance(conditions *[]metav1.Condition, generation int64, reason, message string) {
meta.SetStatusCondition(conditions, metav1.Condition{
Type: conditionNoMatchingInstance,
Status: "True",
Status: metav1.ConditionTrue,
ObservedGeneration: generation,
LastTransitionTime: metav1.Time{
Time: time.Now(),
Expand All @@ -273,7 +278,7 @@ func removeNoMatchingInstance(conditions *[]metav1.Condition) {
func setNoMatchingFolder(conditions *[]metav1.Condition, generation int64, reason, message string) {
meta.SetStatusCondition(conditions, metav1.Condition{
Type: conditionNoMatchingFolder,
Status: "True",
Status: metav1.ConditionTrue,
ObservedGeneration: generation,
LastTransitionTime: metav1.Time{
Time: time.Now(),
Expand All @@ -290,7 +295,7 @@ func removeNoMatchingFolder(conditions *[]metav1.Condition) {
func setInvalidSpec(conditions *[]metav1.Condition, generation int64, reason, message string) {
meta.SetStatusCondition(conditions, metav1.Condition{
Type: conditionInvalidSpec,
Status: "True",
Status: metav1.ConditionTrue,
ObservedGeneration: generation,
LastTransitionTime: metav1.Time{
Time: time.Now(),
Expand Down Expand Up @@ -323,11 +328,11 @@ func buildSynchronizedCondition(resource string, syncType string, generation int
}

if len(applyErrors) == 0 {
condition.Status = "True"
condition.Status = metav1.ConditionTrue
condition.Reason = "ApplySuccessful"
condition.Message = fmt.Sprintf("%s was successfully applied to %d instances", resource, total)
} else {
condition.Status = "False"
condition.Status = metav1.ConditionFalse
condition.Reason = "ApplyFailed"

var sb strings.Builder
Expand Down
2 changes: 1 addition & 1 deletion controllers/grafanaalertrulegroup_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func (r *GrafanaAlertRuleGroupReconciler) reconcileWithInstance(ctx context.Cont
return fmt.Errorf("building grafana client: %w", err)
}

trueRef := "true"
trueRef := "true" //nolint:goconst
editable := true
if group.Spec.Editable != nil && !*group.Spec.Editable {
editable = false
Expand Down
8 changes: 4 additions & 4 deletions controllers/grafanacontactpoint_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,12 @@ func (r *GrafanaContactPointReconciler) Reconcile(ctx context.Context, req ctrl.
}

if len(applyErrors) == 0 {
condition.Status = "True"
condition.Reason = "ApplySuccessful"
condition.Status = metav1.ConditionTrue
condition.Reason = conditionApplySuccessful
condition.Message = fmt.Sprintf("Contact point was successfully applied to %d instances", len(instances))
} else {
condition.Status = "False"
condition.Reason = "ApplyFailed"
condition.Status = metav1.ConditionFalse
condition.Reason = conditionApplyFailed

var sb strings.Builder
for i, err := range applyErrors {
Expand Down
Loading

0 comments on commit 57ba3aa

Please sign in to comment.