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

Implement spec.uid for GrafanaDashboard #1694

Merged
merged 4 commits into from
Oct 25, 2024

Conversation

Baarsgaard
Copy link
Contributor

@Baarsgaard Baarsgaard commented Sep 27, 2024

Followed the same pattern as #1686 for the CustomUID.
As discussed in the weekly sync, spec.uid or metadata.uid will always overwrite dashboardModel.uid.

Thanks to the existing Status.UID update detection, existing dashboards are automatically migrated to using metadata.uid by the operator.

Local procedure for testing

Chainsaw tests

make e2e-local-gh-actions TESTS=immutable_uids

Manual

make start-kind
make deploy
kind export kubeconfig --name kind-grafana

# Test resources
kubectl apply -f https://raw.githubusercontent.com/grafana-operator/grafana-operator/master/examples/basic/resources.yaml
kubectl apply -f ../test-dashboard.yaml

# Check status:
# dashboards
#   - default/dashboard-uid/dashUID
kubectl get grafanas -A -o yaml

# Build and apply image to cluster
make ko-build-kind
IMG=ko.local/grafana/grafana-operator make deploy
kubectl patch deploy -n grafana-operator-system grafana-operator-controller-manager-v5  --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/imagePullPolicy", "value":"IfNotPresent"}]'

# Check status:
# dashboards
#   - default/dashboard-uid/dashUID -> specUID
kubectl get grafanas -A -o yaml

../test-dashboard.yaml

apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
  name: dashboard-uid
spec:
  instanceSelector:
    matchLabels:
      dashboards: "grafana"
  uid: specUID
  resyncPeriod: 10s
  json: >
    {
      "id": null,
      "uid": "dashUID",
      "title": "Simple Dashboard",
      "tags": [],
      "style": "dark",
      "timezone": "browser",
      "editable": true,
      "hideControls": false,
      "graphTooltip": 1,
      "panels": [],
      "time": {
        "from": "now-6h",
        "to": "now"
      },
      "timepicker": {
        "time_options": [],
        "refresh_intervals": []
      },
      "templating": {
        "list": []
      },
      "annotations": {
        "list": []
      },
      "refresh": "5s",
      "schemaVersion": 17,
      "version": 0,
      "links": []
    }
  • Chainsaw tests for immutability of spec.uid
  • Chainsaw tests for expected status on Grafana instance
  • Update dashboard UID documentation

@kcolford
Copy link

kcolford commented Oct 1, 2024

is it possible for this to only override the uid if a uid is not already configured? some collections of dashboards already have a uid in them and then link to each other through that but other dashboards have no uid at all and it would helpful to make sure that the uid can be deterministic if the dashboard's uid isn't present 🤔

@Baarsgaard
Copy link
Contributor Author

Baarsgaard commented Oct 1, 2024

Just to sum up the behaviours:

  1. Master branch: spec.json?.uid > metadata.uid
    Allows modifying dashboard UID with fallback to metadata.uid.

  2. This PR: spec.uid > metadata.uid
    Resulting UID is immutable, spec.json?.uid is entirely ignored

  3. Your suggestion spec.uid > spec.json?.uid > metadata.uid (I think?)
    spec.json?.uid is mutable only when spec.uid is not defined?

All of which has their drawbacks, notably:

  1. UID collisions require downloading remotely sourced dashboards getting rid of the benefit of updates.
  2. Linking between Dashboards need to have their UIDs hardcoded in the spec.uid to not break the links.
    Requires a delete and create of the resource to change the set UID
  3. Same problem as 1 except the workaround is specifying the spec.uid with no other drawbacks to my knowledge, unless the links change?

Personally I don't see much difference between 2 and 3 except they introduce annoyances in two different use cases.
Additionally, there's a slightly higher maintenance burden of 3 due to extra tests and checks necessary.

Yes, it's possible, but I don't know if its the right direction to go in.

@kcolford
Copy link

kcolford commented Oct 7, 2024

@Baarsgaard the scenario I’m thinking of is how to maintain multiple k8s clusters all with Grafana operator running on them, pointing to what should ostensibly be the “same” Grafana. Having something deterministic is better than using the metadata uid. Although maybe that’s not the best use of this feature and I should instead open a different PR that directly addresses that.

@Baarsgaard
Copy link
Contributor Author

Baarsgaard commented Oct 7, 2024

@kcolford The opposite of my use case where I have 1 Grafana operator with multiple Grafana instances in tens of other clusters!
Would your case be covered by specifying the spec.uid on every GrafanaDashboard manifest as that will overwrite the cr.uid

@kcolford
Copy link

@Baarsgaard I think that could work, but it could get messy with determining whether a dashboard already specifies a uid or not. Definitely still possible though, I was just hoping to avoid some extra work.

Copy link
Member

@theSuess theSuess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! From a technical standpoint, this looks great. However, in its current implementation, this would break compatibility with existing setups that rely on the UID being taken from the dashboard spec.

To avoid this, we should only override the UID when the field is actually set.
Once that's implemented, I'm more than happy to merge this!

@Baarsgaard
Copy link
Contributor Author

Baarsgaard commented Oct 17, 2024

@theSuess Sure, but in this case, should the spec.uid field still be immutable?
Or should it be left mutable and thereby different from the other CRs?
additionally, will this be the intended behaviour for the eventual v1 version of the CR?

@theSuess
Copy link
Member

It should be left immutable, since editing the UID still shouldn't be allowed.
If possible, it would also be great to forbid setting the field after creation, but I'm not sure if that's possible

@Baarsgaard
Copy link
Contributor Author

It is possible, part of the Chainsaw tests validate that behaviour right now!
Alright, I will see to fixing it such that dashboard provided uids are sourced before the metadata.uid
This should align with your usecase as well @kcolford

@Baarsgaard Baarsgaard force-pushed the dashboard_uid_refactor branch 2 times, most recently from edbfd2f to 6b702a2 Compare October 22, 2024 17:46
@Baarsgaard
Copy link
Contributor Author

Baarsgaard commented Oct 22, 2024

Alright @theSuess I think that's it?
Please do a review from scratch as I ended up reverting a lot of the uid handling in the dashboards controller due to the previous implementation being more aligned with the cr.CustomUIDOrUID function.

@theSuess
Copy link
Member

Code looks good at first glance - will try it out tomorrow & hopefully also merge it/release a new version :)

@Baarsgaard Baarsgaard force-pushed the dashboard_uid_refactor branch 2 times, most recently from 558dfb2 to 0873848 Compare October 24, 2024 16:32
@theSuess
Copy link
Member

I've cleaned up the commit history a bit and queued the PR for merge - thanks again!

@theSuess theSuess added this pull request to the merge queue Oct 25, 2024
Merged via the queue into grafana:master with commit 7a81b34 Oct 25, 2024
14 checks passed
@Baarsgaard Baarsgaard deleted the dashboard_uid_refactor branch October 25, 2024 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants