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

Add support for arbitrary [Secure]JsonData #803

Merged
merged 4 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ docker-buildx: test
# Download controller-gen locally if necessary
CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
controller-gen:
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.4.1)
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.6.2)

# Download kustomize locally if necessary
KUSTOMIZE = $(shell pwd)/bin/kustomize
Expand Down
13 changes: 13 additions & 0 deletions api/integreatly/v1alpha1/grafanadatasource_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1alpha1

import (
"encoding/json"
"fmt"
"strings"

Expand Down Expand Up @@ -83,6 +84,18 @@ type GrafanaDataSourceFields struct {
SecureJsonData GrafanaDataSourceSecureJsonData `json:"secureJsonData,omitempty"`
Version int `json:"version,omitempty"`
Editable bool `json:"editable,omitempty"`
// +kubebuilder:validation:Schemaless
// +kubebuilder:pruning:PreserveUnknownFields
// +kubebuilder:validation:Type=object
// +optional
// CustomJsonData will be used in place of jsonData, if present, and supports arbitrary JSON, not just those of official datasources
CustomJsonData json.RawMessage `json:"customJsonData,omitempty"`
// +kubebuilder:validation:Schemaless
// +kubebuilder:pruning:PreserveUnknownFields
// +kubebuilder:validation:Type=object
// +optional
// SecureCustomJsonData will be used in place of secureJsonData, if present, and supports arbitrary JSON, not just those of official datasources
CustomSecureJsonData json.RawMessage `json:"customSecureJsonData,omitempty"`
}

// GrafanaDataSourceJsonData contains the most common json options
Expand Down
11 changes: 11 additions & 0 deletions api/integreatly/v1alpha1/zz_generated.deepcopy.go

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

2 changes: 1 addition & 1 deletion config/crd/bases/integreatly.org_grafanadashboards.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
controller-gen.kubebuilder.io/version: v0.6.2
creationTimestamp: null
name: grafanadashboards.integreatly.org
spec:
Expand Down
14 changes: 13 additions & 1 deletion config/crd/bases/integreatly.org_grafanadatasources.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
controller-gen.kubebuilder.io/version: v0.6.2
creationTimestamp: null
name: grafanadatasources.integreatly.org
spec:
Expand Down Expand Up @@ -47,6 +47,18 @@ spec:
type: string
basicAuthUser:
type: string
customJsonData:
description: CustomJsonData will be used in place of jsonData,
if present, and supports arbitrary JSON, not just those of
official datasources
type: object
x-kubernetes-preserve-unknown-fields: true
customSecureJsonData:
description: SecureCustomJsonData will be used in place of secureJsonData,
if present, and supports arbitrary JSON, not just those of
official datasources
type: object
x-kubernetes-preserve-unknown-fields: true
database:
type: string
editable:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
controller-gen.kubebuilder.io/version: v0.6.2
creationTimestamp: null
name: grafananotificationchannels.integreatly.org
spec:
Expand Down
2 changes: 1 addition & 1 deletion config/crd/bases/integreatly.org_grafanas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
controller-gen.kubebuilder.io/version: v0.6.2
creationTimestamp: null
name: grafanas.integreatly.org
spec:
Expand Down
35 changes: 35 additions & 0 deletions controllers/grafanadatasource/datasource_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ func (i *DatasourcePipelineImpl) ProcessDatasource(known *v1.ConfigMap) error {
return nil
}

func applyCustomJsonData(datasource v1alpha1.GrafanaDataSourceFields, unmarshaledDatasource map[string]interface{}) (needsRemarshaling bool) {
if datasource.CustomJsonData != nil {
needsRemarshaling = true
unmarshaledDatasource["jsonData"] = unmarshaledDatasource["customJsonData"]
delete(unmarshaledDatasource, "customJsonData")
}
if datasource.CustomSecureJsonData != nil {
needsRemarshaling = true
unmarshaledDatasource["secureJsonData"] = unmarshaledDatasource["customSecureJsonData"]
delete(unmarshaledDatasource, "customSecureJsonData")
}
return
}

func (i *DatasourcePipelineImpl) parse() error {
datasources := struct {
ApiVersion int `json:"apiVersion"`
Expand All @@ -47,6 +61,27 @@ func (i *DatasourcePipelineImpl) parse() error {
if err != nil {
return err
}
unmarshaledDatasources := make(map[string]interface{})
if err = yaml.Unmarshal(bytes, &unmarshaledDatasources); err != nil {
return err
}
unmarshaledDatasourceList, ok := unmarshaledDatasources["datasources"].([]interface{})
needsRemarshaling := false
if ok {
for ix, datasource := range i.datasource.Spec.Datasources {
unmarshaledDatasource, ok := unmarshaledDatasourceList[ix].(map[string]interface{})
if !ok {
continue
}
needsRemarshaling = needsRemarshaling || applyCustomJsonData(datasource, unmarshaledDatasource)
}
}
if needsRemarshaling {
bytes, err = yaml.Marshal(unmarshaledDatasources)
if err != nil {
return err
}
}
i.contents = string(bytes)
return nil
}
Expand Down
52 changes: 52 additions & 0 deletions deploy/examples/GrafanaWithPlugin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# For use with deploy/examples/datasources/Custom.yaml
apiVersion: integreatly.org/v1alpha1
kind: Grafana
metadata:
name: example-grafana-with-plugin
spec:
client:
preferService: true
# Plugin requires 8+
baseImage: docker.io/grafana/grafana:8.4.3
deployment:
envFrom:
- configMapRef:
name: grafana-plugins
ingress:
enabled: True
pathType: Prefix
path: "/"
config:
log:
mode: "console"
level: "error"
log.frontend:
enabled: true
auth:
disable_login_form: False
disable_signout_menu: True
auth.anonymous:
enabled: True
service:
name: "grafana-service"
labels:
app: "grafana"
type: "grafana-service"
dashboardLabelSelector:
- matchExpressions:
- { key: app, operator: In, values: [grafana] }
resources:
# Optionally specify container resources
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
---
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-plugins
data:
GF_INSTALL_PLUGINS: grafadruid-druid-datasource
23 changes: 23 additions & 0 deletions deploy/examples/datasources/Custom.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# For use with deploy/examples/GrafanaWithPlugin.yaml
# Requires https://grafana.com/grafana/plugins/grafadruid-druid-datasource
apiVersion: integreatly.org/v1alpha1
kind: GrafanaDataSource
metadata:
name: example-grafanadatasource
spec:
name: middleware.yaml
datasources:
- name: Druid
type: grafadruid-druid-datasource
access: proxy
url: http://druid:8888
isDefault: false
version: 1
editable: true
customJsonData:
'connection.retryableRetryMax': 10
'connection.retryableRetryWaitMax': 5000
'connection.retryableRetryWaitMin': 750
'connection.url': 'http://druid:8888'
# for secureJsonData
# customSecureJsonData: {}
20 changes: 16 additions & 4 deletions deploy/manifests/latest/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
controller-gen.kubebuilder.io/version: v0.6.2
name: grafanadashboards.integreatly.org
spec:
group: integreatly.org
Expand Down Expand Up @@ -166,7 +166,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
controller-gen.kubebuilder.io/version: v0.6.2
name: grafanadatasources.integreatly.org
spec:
group: integreatly.org
Expand Down Expand Up @@ -209,6 +209,18 @@ spec:
type: string
basicAuthUser:
type: string
customJsonData:
description: CustomJsonData will be used in place of jsonData,
if present, and supports arbitrary JSON, not just those of
official datasources
type: object
x-kubernetes-preserve-unknown-fields: true
customSecureJsonData:
description: SecureCustomJsonData will be used in place of secureJsonData,
if present, and supports arbitrary JSON, not just those of
official datasources
type: object
x-kubernetes-preserve-unknown-fields: true
database:
type: string
editable:
Expand Down Expand Up @@ -579,7 +591,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
controller-gen.kubebuilder.io/version: v0.6.2
creationTimestamp: null
name: grafananotificationchannels.integreatly.org
spec:
Expand Down Expand Up @@ -658,7 +670,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
controller-gen.kubebuilder.io/version: v0.6.2
name: grafanas.integreatly.org
spec:
group: integreatly.org
Expand Down
14 changes: 14 additions & 0 deletions documentation/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,20 @@ GrafanaDataSourceSpec defines the desired state of GrafanaDataSource
<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>customJsonData</b></td>
<td>object</td>
<td>
CustomJsonData will be used in place of jsonData, if present, and supports arbitrary JSON, not just those of official datasources<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>customSecureJsonData</b></td>
<td>object</td>
<td>
SecureCustomJsonData will be used in place of secureJsonData, if present, and supports arbitrary JSON, not just those of official datasources<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>database</b></td>
<td>string</td>
Expand Down
2 changes: 2 additions & 0 deletions documentation/datasources.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ A data source accepts all properties
listed [here](https://grafana.com/docs/administration/provisioning/#example-datasource-config-file), but does not
support `apiVersion` and `deleteDatasources`.

For custom datasources provided by plugins, use the `customJsonData` and `customSecureJsonData` fields instead of `jsonData` and `secureJsonData`.

To see how to install datasource plugins, see [Plugins](./plugins.md).