diff --git a/docs/docs/folder.md b/docs/docs/folder.md index a9df2100a..3e46bc6a6 100644 --- a/docs/docs/folder.md +++ b/docs/docs/folder.md @@ -1,6 +1,6 @@ --- title: Folders -weight: 14 +weight: 15 --- Dashboard folders is a good way to manage your dashboards. diff --git a/docs/docs/library-panels.md b/docs/docs/library-panels.md new file mode 100644 index 000000000..1696e3224 --- /dev/null +++ b/docs/docs/library-panels.md @@ -0,0 +1,242 @@ +--- +title: Library panels +weight: 14 +--- + +[Library +panels](https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/manage-library-panels/) +are a reusable panel that you can use in any dashboard. When you make a change +to a library panel, that change propagates to all instances of where the panel +is used. Library panels streamline reuse of panels across multiple dashboards. + +To find all possible configuration options, look at our [API +documentation](../api/#grafanalibrarypanelspec). + +## Library panel management + +Library panels are managed in almost exactly the same way as [dashboards](../dashboards), and as such, +most of the features of dashboard management in the operator can be used for library panels: + +* Variety of content sources (JSON, gzip, URL, jsonnet) +* Automatic plugin provisioning +* Content caching +* Stable `uid` derived from the CR, if not defined explicitly on the content model +* Environment variable interpolation +* Mapping datasource references + +Here is an example library panel that shows a graph of container restarts, using data +fetched from Google Cloud Monitoring: + +```yaml +apiVersion: grafana.integreatly.org/v1beta1 +kind: GrafanaLibraryPanel +metadata: + name: gke-container-restarts-over-time +spec: + instanceSelector: + matchLabels: + dashboards: "grafana" + datasources: + - inputName: "DS_GCP" + datasourceName: "gcp" + json: > + { + "__inputs": [ + { + "name": "DS_GCP", + "label": "gcp", + "description": "", + "type": "datasource", + "pluginId": "stackdriver", + "pluginName": "Google Cloud Monitoring" + } + ], + "name": "GKE Container Restarts (Over Time)", + "uid": "gke-container-restarts-over-time", + "kind": 1, + "datasource": { + "type": "stackdriver", + "uid": "${DS_GCP}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "aliasBy": "", + "datasource": { + "type": "stackdriver", + "uid": "gcp" + }, + "hide": false, + "queryType": "timeSeriesQuery", + "refId": "CPU Usage Time", + "timeSeriesQuery": { + "graphPeriod": "", + "projectName": "$cloud_account_id", + "query": "fetch k8s_container\n| metric 'kubernetes.io/container/restart_count'\n| filter resource.cluster_name == '${k8s_cluster_name}' && resource.namespace_name == '${k8s_namespace_name}'\n && metadata.system.top_level_controller_name == '${k8s_workload_name}'\n && resource.container_name == '${k8s_container_name}'\n| delta\n| group_by [resource.pod_name],\n [value: sum(value.restart_count)]" + } + } + ], + "title": "Container Restarts", + "type": "timeseries" + } +``` + +### Referencing library panels in dashboards + +Once a library panel is provisioned in the Grafana instance, it can either be used to create ad-hoc dashboards +not backed by code, or you can reference it by uid in dashboard definitions. All that is needed is a panel +with a `libraryPanel` field that refers to the panel by uid, e.g.: + +```yaml +apiVersion: grafana.integreatly.org/v1beta1 +kind: GrafanaDashboard +metadata: + name: jason-test-gcp-librarypanel +spec: + folder: gcp + instanceSelector: + matchLabels: + env: stg + region: us-central1 + json: > + { + "id": null, + "title": "Simple Dashboard", + "tags": [], + "style": "dark", + "timezone": "browser", + "editable": true, + "hideControls": false, + "graphTooltip": 1, + "panels": [ + { + "libraryPanel": { + "uid": "gke-container-restarts-over-time" + } + } + ], + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "time_options": [], + "refresh_intervals": [] + }, + "templating": { + "list": [] + }, + "annotations": { + "list": [] + }, + "refresh": "5s", + "schemaVersion": 17, + "version": 0, + "links": [] + } +``` + +You can adjust positioning/size on the other panel fields just as you would for a normal panel. + +**NOTE**: library panels likely depend on dashboard variables to be defined, and they do _not_ +automatically configure any. Any dashboards that utilize a library panel must define any required +variable names. + +## Exporting library panels from Grafana + +If you have library panels already configured in your environment and would like to bring them +in as GrafanaLibraryPanel resources, the simplest way is to query Grafana's Library Elements API: + +```shell +curl "$GRAFANA_HOST/api/library-elements" +``` + +This will list all library panels; if you know a panel's UID you can target it explicitly: + +```shell +curl "$GRAFANA_HOST/api/library-elements/$PANEL_UID" +``` + +However, the form of the library element contains many additional metadata fields that are irrelevant +to the Grafana operator. If you have `jq` installed, you can run this script to "fix up" the library +panel representation so it can be imported as JSON: + +```json +jq '.model | del(.libraryPanel) | .datasource.type as $pluginId | .datasource.uid = "${" + (.__inputs | map(select(.pluginId == $pluginId))[0].name) + "}"' +``` + +This script does the following: + +* only looks at the library panel content model located in the `.model` field +* attempts to rewrite datasource references so they refer to `__inputs`, which are used for late-binding + the uid of the datasource installed and present on the target Grafana instance +* removes the `.libraryPanel` self-reference + +Hopefully, in the future, it will be simpler to export library panels from Grafana for sharing. diff --git a/hugo/README.md b/hugo/README.md index 5ede6c25c..24d3b0fb7 100644 --- a/hugo/README.md +++ b/hugo/README.md @@ -2,8 +2,14 @@ ## Installing and running Hugo -When installing hugo install the `extended` edition, you can easily find it on there github page. -We are currently using [0.111.2](https://github.com/gohugoio/hugo/releases/tag/v0.111.2) but it probably works with other versions as well. +When installing hugo install the `extended` edition at version `v0.134.0`. You +can find it on the [Hugo release +page](https://github.com/gohugoio/hugo/releases/tag/v0.134.0) or build it with a +working Go toolchain: + +```shell +CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@v0.134.0 +``` To develop locally you need to also follow the docsy [pre-req](https://github.com/google/docsy#prerequisites). But in most cases it should work to just run