Skip to content

Commit 881b3c0

Browse files
committed
wip
1 parent b7134d5 commit 881b3c0

File tree

10 files changed

+1094
-20
lines changed

10 files changed

+1094
-20
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ vendor
2626
*~
2727

2828
.vscode/
29+
.mirrord/
2930
.DS_Store
3031

3132
# Audit lab

api/v1beta1/grafana_types.go

Lines changed: 108 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@ type OperatorStageName string
2626
type OperatorStageStatus string
2727

2828
const (
29-
OperatorStageGrafanaConfig OperatorStageName = "config"
30-
OperatorStageAdminUser OperatorStageName = "admin user"
31-
OperatorStagePvc OperatorStageName = "pvc"
32-
OperatorStageServiceAccount OperatorStageName = "service account"
33-
OperatorStageService OperatorStageName = "service"
34-
OperatorStageIngress OperatorStageName = "ingress"
35-
OperatorStagePlugins OperatorStageName = "plugins"
36-
OperatorStageDeployment OperatorStageName = "deployment"
37-
OperatorStageComplete OperatorStageName = "complete"
29+
OperatorStageGrafanaConfig OperatorStageName = "config"
30+
OperatorStageAdminUser OperatorStageName = "admin user"
31+
OperatorStagePvc OperatorStageName = "pvc"
32+
OperatorStageServiceAccount OperatorStageName = "service account"
33+
OperatorStageService OperatorStageName = "service"
34+
OperatorStageIngress OperatorStageName = "ingress"
35+
OperatorStagePlugins OperatorStageName = "plugins"
36+
OperatorStageDeployment OperatorStageName = "deployment"
37+
OperatorStageGrafanaServiceAccounts OperatorStageName = "grafana service-accounts"
38+
OperatorStageComplete OperatorStageName = "complete"
3839
)
3940

4041
const (
@@ -52,6 +53,64 @@ type OperatorReconcileVars struct {
5253
Plugins string
5354
}
5455

56+
// GrafanaServiceAccountTokenSpec describes a token to create.
57+
type GrafanaServiceAccountTokenSpec struct {
58+
// Name is the name of the Kubernetes Secret (and token identifier in Grafana). The secret will contain the token value.
59+
// +kubebuilder:validation:Required
60+
Name string `json:"name"`
61+
62+
// Expires is the optional expiration time for the token. After this time, the operator may rotate the token.
63+
// +kubebuilder:validation:Optional
64+
Expires *metav1.Time `json:"expires,omitempty"`
65+
}
66+
67+
// GrafanaServiceAccountPermissionSpec defines a permission grant for a user or team.
68+
// +kubebuilder:validation:XValidation:rule="(has(self.user) && self.user != '') || (has(self.team) && self.team != '')",message="one of user or team must be set"
69+
// +kubebuilder:validation:XValidation:rule="!((has(self.user) && self.user != '') && (has(self.team) && self.team != ''))",message="user and team cannot both be set"
70+
type GrafanaServiceAccountPermissionSpec struct {
71+
// User login or email to grant permissions to (optional).
72+
// +kubebuilder:validation:Optional
73+
User string `json:"user,omitempty"`
74+
75+
// Team name to grant permissions to (optional).
76+
// +kubebuilder:validation:Optional
77+
Team string `json:"team,omitempty"`
78+
79+
// Permission level: Edit or Admin.
80+
// +kubebuilder:validation:Required
81+
// +kubebuilder:validation:Enum=Edit;Admin
82+
Permission string `json:"permission"`
83+
}
84+
85+
// GrafanaServiceAccountSpec defines the desired state of a GrafanaServiceAccount.
86+
type GrafanaServiceAccountSpec struct {
87+
// Name is the desired name of the service account in Grafana.
88+
// +kubebuilder:validation:Required
89+
Name string `json:"name"`
90+
91+
// Role is the Grafana role for the service account (Viewer, Editor, Admin).
92+
// +kubebuilder:validation:Required
93+
// +kubebuilder:validation:Enum=Viewer;Editor;Admin
94+
Role string `json:"role"`
95+
96+
// IsDisabled indicates if the service account should be disabled in Grafana.
97+
// +kubebuilder:validation:Optional
98+
IsDisabled bool `json:"isDisabled,omitempty"`
99+
100+
// Tokens defines API tokens to create for this service account. Each token will be stored in a Kubernetes Secret with the given name.
101+
// +kubebuilder:validation:Optional
102+
Tokens []GrafanaServiceAccountTokenSpec `json:"tokens,omitempty"`
103+
104+
// Permissions specifies additional Grafana permission grants for existing users or teams on this service account.
105+
// +kubebuilder:validation:Optional
106+
Permissions []GrafanaServiceAccountPermissionSpec `json:"permissions,omitempty"`
107+
108+
// GenerateTokenSecret, if true, will create one default API token in a Secret if no Tokens are specified.
109+
// If false, no token is created unless explicitly listed in Tokens.
110+
// +kubebuilder:default=true
111+
GenerateTokenSecret bool `json:"generateTokenSecret,omitempty"`
112+
}
113+
55114
// GrafanaSpec defines the desired state of Grafana
56115
type GrafanaSpec struct {
57116
// +kubebuilder:pruning:PreserveUnknownFields
@@ -80,6 +139,8 @@ type GrafanaSpec struct {
80139
Preferences *GrafanaPreferences `json:"preferences,omitempty"`
81140
// DisableDefaultAdminSecret prevents operator from creating default admin-credentials secret
82141
DisableDefaultAdminSecret bool `json:"disableDefaultAdminSecret,omitempty"`
142+
// Grafana Service Accounts
143+
GrafanaServiceAccounts []GrafanaServiceAccountSpec `json:"grafanaServiceAccounts,omitempty"`
83144
}
84145

85146
type External struct {
@@ -131,18 +192,45 @@ type GrafanaPreferences struct {
131192
HomeDashboardUID string `json:"homeDashboardUid,omitempty"`
132193
}
133194

195+
// GrafanaServiceAccountTokenStatus describes a token created in Grafana.
196+
type GrafanaServiceAccountTokenStatus struct {
197+
// Name is the name of the Kubernetes Secret. The secret will contain the token value.
198+
Name string `json:"name"`
199+
200+
// ID is the Grafana-assigned ID of the token.
201+
ID int64 `json:"tokenId"`
202+
203+
// SecretName is the name of the Kubernetes Secret that stores the actual token value.
204+
// This may seem redundant if the Secret name usually matches the token's Name,
205+
// but it's stored explicitly in Status for clarity and future flexibility.
206+
SecretName string `json:"secretName"`
207+
}
208+
209+
// GrafanaServiceAccountStatus holds status for one Grafana instance.
210+
type GrafanaServiceAccountStatus struct {
211+
// Name is the name of the service account in Grafana.
212+
Name string `json:"name"`
213+
214+
// ID is the numeric ID of the service account in this Grafana.
215+
ID int64 `json:"serviceAccountID"`
216+
217+
// Tokens is the status of tokens for this service account in Grafana.
218+
Tokens []GrafanaServiceAccountTokenStatus `json:"tokens,omitempty"`
219+
}
220+
134221
// GrafanaStatus defines the observed state of Grafana
135222
type GrafanaStatus struct {
136-
Stage OperatorStageName `json:"stage,omitempty"`
137-
StageStatus OperatorStageStatus `json:"stageStatus,omitempty"`
138-
LastMessage string `json:"lastMessage,omitempty"`
139-
AdminURL string `json:"adminUrl,omitempty"`
140-
ContactPoints NamespacedResourceList `json:"contactPoints,omitempty"`
141-
Dashboards NamespacedResourceList `json:"dashboards,omitempty"`
142-
Datasources NamespacedResourceList `json:"datasources,omitempty"`
143-
Folders NamespacedResourceList `json:"folders,omitempty"`
144-
LibraryPanels NamespacedResourceList `json:"libraryPanels,omitempty"`
145-
Version string `json:"version,omitempty"`
223+
Stage OperatorStageName `json:"stage,omitempty"`
224+
StageStatus OperatorStageStatus `json:"stageStatus,omitempty"`
225+
LastMessage string `json:"lastMessage,omitempty"`
226+
AdminURL string `json:"adminUrl,omitempty"`
227+
ContactPoints NamespacedResourceList `json:"contactPoints,omitempty"`
228+
Dashboards NamespacedResourceList `json:"dashboards,omitempty"`
229+
Datasources NamespacedResourceList `json:"datasources,omitempty"`
230+
Folders NamespacedResourceList `json:"folders,omitempty"`
231+
LibraryPanels NamespacedResourceList `json:"libraryPanels,omitempty"`
232+
GrafanaServiceAccounts []GrafanaServiceAccountStatus `json:"serviceAccounts,omitempty"`
233+
Version string `json:"version,omitempty"`
146234
}
147235

148236
// +kubebuilder:object:root=true
@@ -153,6 +241,7 @@ type GrafanaStatus struct {
153241
// +kubebuilder:printcolumn:name="Stage",type="string",JSONPath=".status.stage",description=""
154242
// +kubebuilder:printcolumn:name="Stage status",type="string",JSONPath=".status.stageStatus",description=""
155243
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
244+
// +kubebuilder:printcolumn:name="ServiceAccounts",type=string,JSONPath=`.status.serviceAccounts[*].name`
156245
// +kubebuilder:resource:categories={grafana-operator}
157246
type Grafana struct {
158247
metav1.TypeMeta `json:",inline"`

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 110 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)