Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Dedicated structs for Shared/Common options #1754

Closed
wants to merge 10 commits into from
Closed
7 changes: 7 additions & 0 deletions api/common_interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package api

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

type CommonResource interface {
MatchConditions() (*metav1.LabelSelector, string, *bool)
}
35 changes: 34 additions & 1 deletion api/v1beta1/common.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package v1beta1

import v1 "k8s.io/api/core/v1"
import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// WARN Run `make` on all file changes

type ValueFrom struct {
TargetPath string `json:"targetPath"`
Expand All @@ -16,3 +21,31 @@ type ValueFromSource struct {
// +optional
SecretKeyRef *v1.SecretKeySelector `json:"secretKeyRef,omitempty"`
}

type GrafanaCommonSpec struct {
// How often the resource is synced, defaults to 10m0s if not set
// +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="10m0s"
ResyncPeriod metav1.Duration `json:"resyncPeriod,omitempty"`

// Selects Grafana instances for import
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="spec.instanceSelector is immutable"
InstanceSelector *metav1.LabelSelector `json:"instanceSelector"`

// Allow the Operator to match this resource with Grafanas outside the current namespace
// +optional
AllowCrossNamespaceImport *bool `json:"allowCrossNamespaceImport,omitempty"`
}

// The most recent observed state of a Grafana resource
type GrafanaCommonStatus struct {
// Detect resource changes
Hash string `json:"hash,omitempty"`
// Last time the resource was synchronized
LastResync metav1.Time `json:"lastResync,omitempty"`
// Results when synchonizing resource with Grafana instances
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
29 changes: 8 additions & 21 deletions api/v1beta1/grafanaalertrulegroup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,12 @@ import (
// GrafanaAlertRuleGroupSpec defines the desired state of GrafanaAlertRuleGroup
// +kubebuilder:validation:XValidation:rule="(has(self.folderUID) && !(has(self.folderRef))) || (has(self.folderRef) && !(has(self.folderUID)))", message="Only one of FolderUID or FolderRef can be set"
type GrafanaAlertRuleGroupSpec struct {
GrafanaCommonSpec `json:",inline"`

// +optional
// Name of the alert rule group. If not specified, the resource name will be used.
Name string `json:"name,omitempty"`

// +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"`

// UID of the folder containing this rule group
// Overrides the FolderSelector
FolderUID string `json:"folderUID,omitempty"`
Expand All @@ -56,9 +47,6 @@ type GrafanaAlertRuleGroupSpec struct {
// +kubebuilder:validation:Required
Interval metav1.Duration `json:"interval"`

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

// Whether to enable or disable editing of the alert rule group in Grafana UI
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
// +optional
Expand Down Expand Up @@ -128,11 +116,6 @@ type AlertQuery struct {
RelativeTimeRange *models.RelativeTimeRange `json:"relativeTimeRange,omitempty"`
}

// GrafanaAlertRuleGroupStatus defines the observed state of GrafanaAlertRuleGroup
type GrafanaAlertRuleGroupStatus struct {
Conditions []metav1.Condition `json:"conditions"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

Expand All @@ -142,8 +125,8 @@ type GrafanaAlertRuleGroup struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec GrafanaAlertRuleGroupSpec `json:"spec,omitempty"`
Status GrafanaAlertRuleGroupStatus `json:"status,omitempty"`
Spec GrafanaAlertRuleGroupSpec `json:"spec,omitempty"`
Status GrafanaCommonStatus `json:"status,omitempty"`
}

// GroupName returns the name of alert rule group.
Expand Down Expand Up @@ -194,3 +177,7 @@ type GrafanaAlertRuleGroupList struct {
func init() {
SchemeBuilder.Register(&GrafanaAlertRuleGroup{}, &GrafanaAlertRuleGroupList{})
}

func (in *GrafanaAlertRuleGroup) MatchConditions() (*metav1.LabelSelector, string, *bool) {
return in.Spec.InstanceSelector, in.ObjectMeta.Namespace, in.Spec.AllowCrossNamespaceImport
}
38 changes: 15 additions & 23 deletions api/v1beta1/grafanacontactpoint_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package v1beta1

import (
"time"

apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand All @@ -27,22 +29,13 @@ import (
// GrafanaContactPointSpec defines the desired state of GrafanaContactPoint
// +kubebuilder:validation:XValidation:rule="((!has(oldSelf.uid) && !has(self.uid)) || (has(oldSelf.uid) && has(self.uid)))", message="spec.uid is immutable"
type GrafanaContactPointSpec struct {
GrafanaCommonSpec `json:",inline"`

// Manually specify the UID the Contact Point is created with
// +optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="spec.uid is immutable"
CustomUID string `json:"uid,omitempty"`

// +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"`

// +optional
DisableResolveMessage bool `json:"disableResolveMessage,omitempty"`

Expand All @@ -56,16 +49,6 @@ type GrafanaContactPointSpec struct {

// +kubebuilder:validation:Enum=alertmanager;prometheus-alertmanager;dingding;discord;email;googlechat;kafka;line;opsgenie;pagerduty;pushover;sensugo;sensu;slack;teams;telegram;threema;victorops;webhook;wecom;hipchat;oncall
Type string `json:"type,omitempty"`

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

// GrafanaContactPointStatus defines the observed state of GrafanaContactPoint
type GrafanaContactPointStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
Conditions []metav1.Condition `json:"conditions"`
}

//+kubebuilder:object:root=true
Expand All @@ -77,8 +60,8 @@ type GrafanaContactPoint struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec GrafanaContactPointSpec `json:"spec,omitempty"`
Status GrafanaContactPointStatus `json:"status,omitempty"`
Spec GrafanaContactPointSpec `json:"spec,omitempty"`
Status GrafanaCommonStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true
Expand All @@ -101,3 +84,12 @@ func (in *GrafanaContactPoint) CustomUIDOrUID() string {
func init() {
SchemeBuilder.Register(&GrafanaContactPoint{}, &GrafanaContactPointList{})
}

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

func (in *GrafanaContactPoint) MatchConditions() (*metav1.LabelSelector, string, *bool) {
return in.Spec.InstanceSelector, in.ObjectMeta.Namespace, in.Spec.AllowCrossNamespaceImport
}
58 changes: 12 additions & 46 deletions api/v1beta1/grafanadashboard_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ type GrafanaDashboardUrlAuthorization struct {
// +kubebuilder:validation:XValidation:rule="(has(self.folder) && !(has(self.folderRef) || has(self.folderUID))) || !(has(self.folder))", message="folder field cannot be set when folderUID or folderRef is already declared"
// +kubebuilder:validation:XValidation:rule="((!has(oldSelf.uid) && !has(self.uid)) || (has(oldSelf.uid) && has(self.uid)))", message="spec.uid is immutable"
type GrafanaDashboardSpec struct {
GrafanaCommonSpec `json:",inline"`

// Manually specify the uid for the dashboard, overwrites uids already present in the json model
// +optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="spec.uid is immutable"
Expand Down Expand Up @@ -98,10 +100,6 @@ type GrafanaDashboardSpec struct {
// +optional
ConfigMapRef *v1.ConfigMapKeySelector `json:"configMapRef,omitempty"`

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

// folder assignment for dashboard
// +optional
FolderTitle string `json:"folder,omitempty"`
Expand All @@ -122,22 +120,10 @@ type GrafanaDashboardSpec struct {
// +optional
ContentCacheDuration metav1.Duration `json:"contentCacheDuration,omitempty"`

// how often the dashboard is refreshed, defaults to 5m if not set
// +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="5m"
ResyncPeriod string `json:"resyncPeriod,omitempty"`

// maps required data sources to existing ones
// +optional
Datasources []GrafanaDashboardDatasource `json:"datasources,omitempty"`

// allow to import this resources from an operator in a different namespace
// +optional
AllowCrossNamespaceImport *bool `json:"allowCrossNamespaceImport,omitempty"`

// environments variables as a map
// +optional
Envs []GrafanaDashboardEnv `json:"envs,omitempty"`
Expand Down Expand Up @@ -178,19 +164,17 @@ type GrafanaComDashboardReference struct {
Revision *int `json:"revision,omitempty"`
}

// TODO(V1) Remove
// GrafanaDashboardStatus defines the observed state of GrafanaDashboard
type GrafanaDashboardStatus struct {
GrafanaCommonStatus `json:",inline"`

ContentCache []byte `json:"contentCache,omitempty"`
ContentTimestamp metav1.Time `json:"contentTimestamp,omitempty"`
ContentUrl string `json:"contentUrl,omitempty"`
Hash string `json:"hash,omitempty"`
// The dashboard instanceSelector can't find matching grafana instances
NoMatchingInstances bool `json:"NoMatchingInstances,omitempty"`
// Last time the dashboard was resynced
LastResync metav1.Time `json:"lastResync,omitempty"`
UID string `json:"uid,omitempty"`

Conditions []metav1.Condition `json:"conditions,omitempty"`
NoMatchingInstances bool `json:"NoMatchingInstances,omitempty"`
UID string `json:"uid,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down Expand Up @@ -261,25 +245,10 @@ func (in *GrafanaDashboard) Unchanged(hash string) bool {
}

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

func (in *GrafanaDashboard) GetResyncPeriod() time.Duration {
if in.Spec.ResyncPeriod == "" {
in.Spec.ResyncPeriod = DefaultResyncPeriod
return in.GetResyncPeriod()
}

duration, err := time.ParseDuration(in.Spec.ResyncPeriod)
if err != nil {
in.Spec.ResyncPeriod = DefaultResyncPeriod
return in.GetResyncPeriod()
}

return duration
}

func (in *GrafanaDashboard) GetSourceTypes() []DashboardSourceType {
var sourceTypes []DashboardSourceType

Expand Down Expand Up @@ -337,13 +306,6 @@ func (in *GrafanaDashboardStatus) getContentCache(url string, cacheDuration time
return cache
}

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

func (in *GrafanaDashboard) IsUpdatedUID(uid string) bool {
// Dashboard has just been created, status is not yet updated
if in.Status.UID == "" {
Expand Down Expand Up @@ -392,3 +354,7 @@ func (in *GrafanaDashboardList) Find(namespace string, name string) *GrafanaDash
func init() {
SchemeBuilder.Register(&GrafanaDashboard{}, &GrafanaDashboardList{})
}

func (in *GrafanaDashboard) MatchConditions() (*metav1.LabelSelector, string, *bool) {
return in.Spec.InstanceSelector, in.ObjectMeta.Namespace, in.Spec.AllowCrossNamespaceImport
}
8 changes: 5 additions & 3 deletions api/v1beta1/grafanadashboard_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,11 @@ func getDashboardCR(t *testing.T, crUID string, statusUID string, specUID string
UID: types.UID(crUID),
},
Spec: GrafanaDashboardSpec{
InstanceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"dashboard": "grafana",
GrafanaCommonSpec: GrafanaCommonSpec{
InstanceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"dashboard": "grafana",
},
},
},
CustomUID: specUID,
Expand Down
Loading
Loading