Skip to content

Folders: Migrate getFolder API to app platform #107617

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

Open
wants to merge 40 commits into
base: main
Choose a base branch
from

Conversation

aocenas
Copy link
Member

@aocenas aocenas commented Jul 4, 2025

Changes the getFolder and it's useGetFolderQueryHook to use APP latform APIs.

This is done by creating a useGetFolderQueryFacade that based on the foldersAppPlatformAPI either uses the legacy client or the recreates the same FolderDTO from multiple app platform API calls.

This should make this change mostly transparent to the front end so no changes to the rendering is needed.

aocenas and others added 22 commits June 18, 2025 16:16
# Conflicts:
#	packages/grafana-data/src/types/featureToggles.gen.ts
#	pkg/services/featuremgmt/registry.go
#	pkg/services/featuremgmt/toggles_gen.csv
#	pkg/services/featuremgmt/toggles_gen.go
…o aocenas/folders/migrate-api

# Conflicts:
#	packages/grafana-data/src/types/featureToggles.gen.ts
#	pkg/services/featuremgmt/registry.go
#	pkg/services/featuremgmt/toggles_gen.csv
#	pkg/services/featuremgmt/toggles_gen.go
# Conflicts:
#	packages/grafana-data/src/types/featureToggles.gen.ts
#	pkg/services/featuremgmt/registry.go
#	pkg/services/featuremgmt/toggles_gen.csv
#	pkg/services/featuremgmt/toggles_gen.go
#	pkg/services/featuremgmt/toggles_gen.json
# Conflicts:
#	public/app/api/clients/folder/v1beta1/index.ts
#	public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts
aocenas added 2 commits July 9, 2025 19:05
# Conflicts:
#	public/app/features/alerting/unified/hooks/useFolder.ts
@aocenas aocenas requested a review from a team as a code owner July 18, 2025 10:58
@aocenas aocenas requested review from joshhunt, ashharrison90, gillesdemey, konrad147, soniaAguilarPeiron and konsalex and removed request for a team July 18, 2025 10:58
@github-actions github-actions bot added this to the 12.1.x milestone Jul 18, 2025
@ArturWierzbicki ArturWierzbicki requested a review from ryantxu July 18, 2025 11:54
Comment on lines 161 to 163
const results = needsUserData
? [result, resultParents, resultAccess]
: [result, resultParents, resultAccess, resultUserDisplay];
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the wrong way round? 🤔
It's reading as "if needs user data, don't check the resultUserDisplay query". I would have expected it to be the other way round here

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch, need to add some tests for this hook to at least check the merging behavior

@aocenas aocenas added the no-changelog Skip including change in changelog/release notes label Jul 18, 2025
@tomratcliffe
Copy link
Contributor

Not sure if this one is out of scope for the current implementation, but I think its a bug in the new hook? Or an issue with permissions on the new API.

Minimal reproduction, using enterprise...:

  • Get a test user that has granular read permissions on just 2 folders (and no basic role, so they can't see any other folders)
  • Go to the Move Folder modal and try to move one folder to a new one
    • There will be no results shown in the dropdown list (just the Dashboards item in the nested picker)
    • There will be a 403 response from /apis/folder.grafana.app/v1beta1/namespaces/default/folders/general/children

Copy link
Contributor

@IevaVasiljeva IevaVasiljeva left a comment

Choose a reason for hiding this comment

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

LGTM access control wise. I feel like we could eventually simplify the returned info a bit (eg, we don't really need both CanEdit, CanSave etc and the access control metadata). But this should work for now 🤞

metadata: {
name: 'general',
namespace: 'org-0',
uid: 'DvhY6m059FraHn96xsOKsb8GRtHy2ftVDUPkqZTzP4kX',
Copy link
Contributor

Choose a reason for hiding this comment

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

question: where is this UID coming from? On the backend, we use general for general folder UID.

Copy link
Member Author

Choose a reason for hiding this comment

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

I copied what I get if the dualWriterMode == 1 so the backend uses the legacy path. As far as I know this uid is not grafana uid but k8s uid and so will be different from general.

This one though is generated here

f.UID = gapiutil.CalculateClusterWideUID(f)
and the function depends on group/kind/name/namespace so I assume this should be stable for these virtual folders?

At the same time it's not actually used right now anyway and does not get into the final FolderDTO right now the exact value does not matter.

Copy link
Contributor

Choose a reason for hiding this comment

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

Gotcha, thanks for the explanation. I still find it hard to tell where the old Grafana style UIDs should be used, and where it's the new k8s UIDs. I agree that it sounds like it'd be a fixed value. And that it's fine to keep it as it is if it's currently not used.

import {
AnnoKeyCreatedBy,
AnnoKeyFolder,
// AnnoKeyFolderUrl,
Copy link
Contributor

Choose a reason for hiding this comment

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

(nit: commented code)

const resultAccess = useGetFolderAccessQuery(params);

// Load users info if needed.
const userKeys = getUserKeys(resultFolder);
Copy link
Contributor

Choose a reason for hiding this comment

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

Overall, might it be better to make the user information dependent on a parameter passed to the hook? Then the consumer can decide whether its needed to be fetched, rather than always doing it.

I would imagine that not every consumer of the hook requires the user information for its display, perhaps?

Something for the future, as I get that here we're just trying to move over to the new API

Copy link
Member Author

Choose a reason for hiding this comment

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

The reason this is done is that the k8s object has user references (like created by) in different format, like user:1 while in the old folderDTO the references are actual logins of the users so user:1 => admin. To resolve that here we need to use the userDisplay API call, but in case the references in the k8s object is empty we don't need to do that. So it's not really something user would decide.

In the future we will just have to change the front end to understand the new data types and deal with it case by case because yeah most time it probably isn't needed.

metadata: {
name: 'sharedwithme',
namespace: 'org-0',
uid: 'DlDSzXw31VwXu6LHMw0JMoFvfVtYzyf3NEPzsOXHtxQX',
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be config.sharedWithMeFolderUID? Not sure how its best to handle all of these virtual folders 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

No, see #107617 (comment) this UID is totally separate thing from the UID we have in grafana. UID we use in grafana == metadata.name in the k8s objects.

Comment on lines +35 to +36
title: 'Shared with me',
description: 'Dashboards and folders shared with me',
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: If these are actually being displayed, then we'll need to turn these into get methods (getSharedWithMeFolder) and add translations

Comment on lines +51 to +53
const result = await (config.featureToggles.foldersAppPlatformAPI
? deleteFolderAppPlatform({ name: folder.uid })
: deleteFolderLegacy(folder));
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be worth moving the feature toggle check/logic into the hook as we've done for the get case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/alerting Grafana Alerting area/backend area/frontend no-changelog Skip including change in changelog/release notes
Projects
Status: In review
Development

Successfully merging this pull request may close these issues.

5 participants