Skip to content

Commit 45a06ca

Browse files
committed
wip
1 parent 2533d2c commit 45a06ca

32 files changed

+3064
-10
lines changed

api/v1beta1/grafana_types.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,16 @@ type GrafanaPreferences struct {
131131

132132
// GrafanaStatus defines the observed state of Grafana
133133
type GrafanaStatus struct {
134-
Stage OperatorStageName `json:"stage,omitempty"`
135-
StageStatus OperatorStageStatus `json:"stageStatus,omitempty"`
136-
LastMessage string `json:"lastMessage,omitempty"`
137-
AdminUrl string `json:"adminUrl,omitempty"`
138-
Dashboards NamespacedResourceList `json:"dashboards,omitempty"`
139-
Datasources NamespacedResourceList `json:"datasources,omitempty"`
140-
Folders NamespacedResourceList `json:"folders,omitempty"`
141-
LibraryPanels NamespacedResourceList `json:"libraryPanels,omitempty"`
142-
Version string `json:"version,omitempty"`
134+
Stage OperatorStageName `json:"stage,omitempty"`
135+
StageStatus OperatorStageStatus `json:"stageStatus,omitempty"`
136+
LastMessage string `json:"lastMessage,omitempty"`
137+
AdminUrl string `json:"adminUrl,omitempty"`
138+
Dashboards NamespacedResourceList `json:"dashboards,omitempty"`
139+
Datasources NamespacedResourceList `json:"datasources,omitempty"`
140+
ServiceAccounts NamespacedResourceList `json:"serviceaccounts,omitempty"`
141+
Folders NamespacedResourceList `json:"folders,omitempty"`
142+
LibraryPanels NamespacedResourceList `json:"libraryPanels,omitempty"`
143+
Version string `json:"version,omitempty"`
143144
}
144145

145146
// +kubebuilder:object:root=true
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
Copyright 2025.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
// GrafanaServiceAccountToken describes a token to create.
24+
type GrafanaServiceAccountToken struct {
25+
// Name is the name of the Kubernetes Secret (and token identifier in Grafana). The secret will contain the token value.
26+
// +kubebuilder:validation:Required
27+
Name string `json:"name"`
28+
29+
// Expires is the optional expiration time for the token. After this time, the operator may rotate the token.
30+
// +kubebuilder:validation:Optional
31+
Expires *metav1.Time `json:"expires,omitempty"`
32+
}
33+
34+
// GrafanaServiceAccountTokenStatus describes a token created in Grafana.
35+
type GrafanaServiceAccountTokenStatus struct {
36+
// Name of the token (same as Secret name).
37+
Name string `json:"name"`
38+
39+
// TokenID is the Grafana-assigned ID of the token.
40+
TokenID int64 `json:"tokenId"`
41+
42+
// SecretName is the name of the Kubernetes Secret that stores the actual token value.
43+
// This may seem redundant if the Secret name usually matches the token's Name,
44+
// but it's stored explicitly in Status for clarity and future flexibility.
45+
SecretName string `json:"secretName"`
46+
}
47+
48+
// GrafanaServiceAccountPermission defines a permission grant for a user or team.
49+
type GrafanaServiceAccountPermission struct {
50+
// User login or email to grant permissions to (optional).
51+
// +kubebuilder:validation:Optional
52+
User string `json:"user,omitempty"`
53+
54+
// Team name to grant permissions to (optional).
55+
// +kubebuilder:validation:Optional
56+
Team string `json:"team,omitempty"`
57+
58+
// Permission level: Viewer, Editor, or Admin.
59+
// +kubebuilder:validation:Required
60+
// +kubebuilder:validation:Enum=Viewer;Editor;Admin
61+
Permission string `json:"permission"`
62+
}
63+
64+
// GrafanaServiceAccountSpec defines the desired state of a GrafanaServiceAccount.
65+
type GrafanaServiceAccountSpec struct {
66+
GrafanaCommonSpec `json:",inline"`
67+
68+
// Name is the desired name of the service account in Grafana.
69+
// +kubebuilder:validation:Required
70+
Name string `json:"name"`
71+
72+
// Role is the Grafana role for the service account (Viewer, Editor, Admin).
73+
// +kubebuilder:validation:Required
74+
// +kubebuilder:validation:Enum=Viewer;Editor;Admin
75+
Role string `json:"role"`
76+
77+
// IsDisabled indicates if the service account should be disabled in Grafana.
78+
// +kubebuilder:validation:Optional
79+
IsDisabled bool `json:"isDisabled,omitempty"`
80+
81+
// Tokens defines API tokens to create for this service account. Each token will be stored in a Kubernetes Secret with the given name.
82+
// +kubebuilder:validation:Optional
83+
Tokens []GrafanaServiceAccountToken `json:"tokens,omitempty"`
84+
85+
// Permissions specifies additional Grafana permission grants for existing users or teams on this service account.
86+
// +kubebuilder:validation:Optional
87+
Permissions []GrafanaServiceAccountPermission `json:"permissions,omitempty"`
88+
89+
// GenerateTokenSecret, if true, will create one default API token in a Secret if no Tokens are specified.
90+
// If false, no token is created unless explicitly listed in Tokens.
91+
// +kubebuilder:default=true
92+
GenerateTokenSecret bool `json:"generateTokenSecret,omitempty"`
93+
}
94+
95+
// GrafanaServiceAccountInstanceStatus holds status for one Grafana instance.
96+
type GrafanaServiceAccountInstanceStatus struct {
97+
// GrafanaNamespace and GrafanaName specify which Grafana resource this status record belongs to.
98+
GrafanaNamespace string `json:"grafanaNamespace"`
99+
GrafanaName string `json:"grafanaName"`
100+
101+
// ServiceAccountID is the numeric ID of the service account in this Grafana.
102+
ServiceAccountID int64 `json:"serviceAccountID"`
103+
104+
// Tokens is the status of tokens for this service account in Grafana.
105+
Tokens []GrafanaServiceAccountTokenStatus `json:"tokens,omitempty"`
106+
}
107+
108+
// GrafanaServiceAccountStatus defines the observed state of a GrafanaServiceAccount.
109+
type GrafanaServiceAccountStatus struct {
110+
GrafanaCommonStatus `json:",inline"`
111+
112+
// Instances lists Grafana instances where this service account is applied.
113+
// +optional
114+
Instances []GrafanaServiceAccountInstanceStatus `json:"instances,omitempty"`
115+
}
116+
117+
//+kubebuilder:object:root=true
118+
//+kubebuilder:subresource:status
119+
120+
// GrafanaServiceAccount is the Schema for the grafanaserviceaccounts API.
121+
// +kubebuilder:printcolumn:name="Last resync",type="date",format="date-time",JSONPath=".status.lastResync",description=""
122+
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
123+
// +kubebuilder:resource:categories={grafana-operator}
124+
type GrafanaServiceAccount struct {
125+
metav1.TypeMeta `json:",inline"`
126+
metav1.ObjectMeta `json:"metadata,omitempty"`
127+
128+
Spec GrafanaServiceAccountSpec `json:"spec,omitempty"`
129+
Status GrafanaServiceAccountStatus `json:"status,omitempty"`
130+
}
131+
132+
//+kubebuilder:object:root=true
133+
134+
// GrafanaServiceAccountList contains a list of GrafanaServiceAccount objects.
135+
type GrafanaServiceAccountList struct {
136+
metav1.TypeMeta `json:",inline"`
137+
metav1.ListMeta `json:"metadata,omitempty"`
138+
Items []GrafanaServiceAccount `json:"items"`
139+
}
140+
141+
// Find searches for a GrafanaServiceAccount by namespace/name in the list.
142+
func (in *GrafanaServiceAccountList) Find(namespace, name string) *GrafanaServiceAccount {
143+
for _, serviceAccount := range in.Items {
144+
if serviceAccount.Namespace == namespace && serviceAccount.Name == name {
145+
return &serviceAccount
146+
}
147+
}
148+
return nil
149+
}
150+
151+
// MatchLabels returns the LabelSelector (from GrafanaCommonSpec) to find matching Grafana instances.
152+
func (in *GrafanaServiceAccount) MatchLabels() *metav1.LabelSelector {
153+
return in.Spec.InstanceSelector
154+
}
155+
156+
// MatchNamespace returns the namespace where this service account is defined.
157+
func (in *GrafanaServiceAccount) MatchNamespace() string {
158+
return in.ObjectMeta.Namespace
159+
}
160+
161+
// AllowCrossNamespace indicates whether cross-namespace import is allowed for this resource.
162+
func (in *GrafanaServiceAccount) AllowCrossNamespace() bool {
163+
return in.Spec.AllowCrossNamespaceImport
164+
}
165+
166+
func init() {
167+
SchemeBuilder.Register(&GrafanaServiceAccount{}, &GrafanaServiceAccountList{})
168+
}

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 184 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)