diff --git a/.betterer.results b/.betterer.results index 01a8e96aa9f..cfb0ebda934 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1687,15 +1687,6 @@ exports[`better eslint`] = { "public/app/features/dashboard-scene/serialization/transformToV1TypesUtils.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], - "public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx:5381": [ - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"], - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"], - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "2"], - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "3"], - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "4"], - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "5"], - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "6"] - ], "public/app/features/dashboard-scene/settings/annotations/AnnotationSettingsEdit.tsx:5381": [ [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"], [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"], @@ -2547,10 +2538,10 @@ exports[`better eslint`] = { "public/app/features/plugins/loader/sharedDependencies.ts:5381": [ [0, 0, 0, "* import is invalid because \'Layout,HorizontalGroup,VerticalGroup\' from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"] ], - "public/app/features/plugins/sandbox/distortion_map.ts:5381": [ + "public/app/features/plugins/sandbox/distortions.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], - "public/app/features/plugins/sandbox/sandbox_plugin_loader.ts:5381": [ + "public/app/features/plugins/sandbox/sandboxPluginLoader.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Do not use any type assertions.", "2"] @@ -3130,9 +3121,6 @@ exports[`better eslint`] = { "public/app/plugins/datasource/cloud-monitoring/types/types.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], - "public/app/plugins/datasource/cloud-monitoring/webpack.config.ts:5381": [ - [0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"] - ], "public/app/plugins/datasource/cloudwatch/components/ConfigEditor/ConfigEditor.tsx:5381": [ [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"], [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"], @@ -3299,9 +3287,6 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], - "public/app/plugins/datasource/grafana-testdata-datasource/webpack.config.ts:5381": [ - [0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"] - ], "public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.tsx:5381": [ [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"], [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"], @@ -3653,9 +3638,6 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "2"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"] ], - "public/app/plugins/datasource/tempo/webpack.config.ts:5381": [ - [0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"] - ], "public/app/plugins/datasource/zipkin/QueryField.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"] @@ -3666,9 +3648,6 @@ exports[`better eslint`] = { "public/app/plugins/datasource/zipkin/utils/transforms.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], - "public/app/plugins/datasource/zipkin/webpack.config.ts:5381": [ - [0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"] - ], "public/app/plugins/panel/annolist/AnnoListPanel.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], @@ -4012,9 +3991,6 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], - "public/app/types/acl.ts:5381": [ - [0, 0, 0, "Do not re-export imported variable (\`OrgRole\`)", "0"] - ], "public/app/types/alerting.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], @@ -4036,29 +4012,6 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "7"], [0, 0, 0, "Unexpected any. Specify a different type.", "8"] ], - "public/app/types/index.ts:5381": [ - [0, 0, 0, "Do not re-export imported variable (\`CoreEvents\`)", "0"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "3"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "4"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "5"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "6"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "7"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "8"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "9"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "10"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "11"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "12"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "13"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "14"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "15"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "16"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "17"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "18"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "19"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "20"] - ], "public/app/types/jquery/jquery.d.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], diff --git a/.github/workflows/i18n-crowdin-download.yml b/.github/workflows/i18n-crowdin-download.yml index 1c1f87efc40..e8e04c22029 100644 --- a/.github/workflows/i18n-crowdin-download.yml +++ b/.github/workflows/i18n-crowdin-download.yml @@ -7,6 +7,7 @@ on: jobs: download-sources-from-crowdin: + if: github.repository == 'grafana/grafana' uses: grafana/grafana-github-actions/.github/workflows/crowdin-download.yml@main with: crowdin_project_id: 5 diff --git a/.github/workflows/i18n-crowdin-upload.yml b/.github/workflows/i18n-crowdin-upload.yml index c3a48f97481..b61a7538bf0 100644 --- a/.github/workflows/i18n-crowdin-upload.yml +++ b/.github/workflows/i18n-crowdin-upload.yml @@ -14,6 +14,7 @@ on: jobs: upload-sources-to-crowdin: + if: github.repository == 'grafana/grafana' uses: grafana/grafana-github-actions/.github/workflows/crowdin-upload.yml@main with: crowdin_project_id: 5 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4527ac3487d..12a43e07e98 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,29 +1,56 @@ -# Contributing to Grafana +# Contribute to Grafana Thank you for your interest in contributing to Grafana! We welcome all people who want to contribute in a healthy and constructive manner within our community. To help us create a safe and positive community experience for all, we require all participants to adhere to the [Code of Conduct](CODE_OF_CONDUCT.md). -This document is a guide to help you through the process of contributing to Grafana. +This document is a guide to help you through the process of making technical contributions to Grafana. -## Become a contributor +Whether you're a new contributer or a seasoned veteran we hope these resources help you connect with the community: -You can contribute to Grafana in several ways. Here are some examples: +Interact and be heard: -- Contribute to the Grafana codebase. -- Report and triage bugs. -- Develop community plugins and dashboards. -- Write technical documentation and blog posts, for users and contributors. -- Organize meetups and user groups in your local area. -- Help others by answering questions about Grafana. +- Forums: Do you have a problem, question, or curiosity? Visit our [forums](https://gra.fan/fromgithubtoforums) for a reservoir of knowledge- submit your own questions and answers! +- Meetups: Craving in-person connections without the long journeys? [Join your local Grafana & Friends meetup group](https://gra.fan/githubtomeetup)! +- Community Slack: Eager for real-time connections with fellow users? Begin a conversation on [Slack](https://gra.fan/githubtoslack). + Learn: +- YouTube: From getting started to exploring newer projects like Pyroscope and Beyla, the [Grafana YouTube channel](https://gra.fan/githubtoyoutube) has what you need to get started! +- Meetups: Join a [group near you](https://gra.fan/githubtomeetup) to learn from local experts and ask questions in real time. + Share your story: +- Meetups and blogs: We’d love to feature your OSS Grafana Labs use case or story at an upcoming Grafana & Friends meetup or on the Grafana blog! Submit your idea [here](https://gra.fan/githubtocca) and we’ll connect with you on next steps if accepted. + +## Make technical contributions + +We welcome your technical contributions! Here are some examples: + +- Contribute to the Grafana codebase- check out these [help-wanted issues](<(https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)>) +- Develop community [plugins](https://grafana.com/developers/plugin-tools) +- Report [bugs](https://github.com/grafana/grafana/issues/new?template=0-bug-report.yaml) +- [Triage issues](https://github.com/grafana/grafana/blob/4414b92e93440cc9ed0f281989ee71dc16216a15/contribute/triage-issues.md) +- Report [security vulnerabilities](https://github.com/grafana/grafana/security/policy) +- Submit a [feature request](https://github.com/grafana/grafana/issues/new?template=1-feature_requests.md) +- Write [technical documentation](https://github.com/grafana/grafana/blob/4414b92e93440cc9ed0f281989ee71dc16216a15/contribute/documentation/README.md) **Please note:** We do not currently accept contributions for translations. Please do not submit pull requests translating grafana.json files - they will be rejected. We do accept contributions to mark up phrases for translation. See [Internationalization](contribute/internationalization.md). -For more ways to contribute, check out the [Open Source Guides](https://opensource.guide/how-to-contribute/). +### Your first contribution + +Unsure where to begin contributing to Grafana? Start by browsing issues labeled `beginner friendly` or `help wanted`. + +- [Beginner-friendly](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) issues are generally straightforward to complete. +- [Help wanted](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues are problems we would like the community to help us with regardless of complexity. + +If you're looking to make a code change, see how to set up your environment for [local development](contribute/developer-guide.md). + +When you're ready to contribute, it's time to [create a pull request](/contribute/create-pull-request.md). + +### Develop a plugin + +Developing a Grafana plugin is a fantastic way to share your unique ideas with the community, extend the platform’s capabilities, and make a real impact on how people visualize and understand their data. Check out our guide to creating [plugins](https://grafana.com/developers/plugin-tools) ### Report bugs Before submitting a new issue, try to make sure someone hasn't already reported the problem. Look through the [existing issues](https://github.com/grafana/grafana/issues) for similar issues. -Report a bug by submitting a [bug report](https://github.com/grafana/grafana/issues/new?labels=type%3A+bug&template=1-bug_report.md). Make sure that you provide as much information as possible on how to reproduce the bug. +Report a bug by submitting a [bug report](https://github.com/grafana/grafana/issues/new?template=0-bug-report.yaml). Make sure that you provide as much information as possible on how to reproduce the bug. Follow the issue template and add additional information that will help us replicate the problem. @@ -38,42 +65,25 @@ For a dashboard related issues: For authentication and alerting Grafana server logs are useful. -#### Security issues - -If you believe you've found a security vulnerability, please read our [security policy](https://github.com/grafana/grafana/security/policy) for more details. - -### Suggest enhancements - -If you have an idea of how to improve Grafana, submit a [feature request](https://github.com/grafana/grafana/issues/new?assignees=&labels=type%2Ffeature-request&projects=&template=1-feature_requests.md). - -We want to make Grafana accessible to even more people. Submit an [accessibility issue](https://github.com/grafana/grafana/issues/new?labels=type%3A+accessibility&template=3-accessibility.md) to help us understand what we can improve. - -### Write documentation - -To edit or write technical content, refer to [Contribute to our documentation](/contribute/documentation/README.md). We welcome your expertise and input as our body of technical content grows. - ### Triage issues If you don't have the knowledge or time to code, consider helping with _issue triage_. The community will thank you for saving them time by spending some of yours. Read more about the ways you can [Triage issues](/contribute/triage-issues.md). -### Answering questions +#### Security issues -If you have a question and you can't find the answer in the [documentation](https://grafana.com/docs/), the next step is to ask it on the [community site](https://community.grafana.com/). +If you believe you've found a security vulnerability, please read our [security policy](https://github.com/grafana/grafana/security/policy) for more details on reporting. -It's important to us to help these users, and we'd love your help. Sign up to our [community site](https://community.grafana.com/), and start helping other Grafana users by answering their questions. +### Suggest enhancements -### Your first contribution +If you have an idea of how to improve Grafana, submit a [feature request](https://github.com/grafana/grafana/issues/new?template=1-feature_requests.md). -Unsure where to begin contributing to Grafana? Start by browsing issues labeled `beginner friendly` or `help wanted`. +We want to make Grafana accessible to even more people. Submit an [accessibility issue](https://github.com/grafana/grafana/issues/new?template=2-accessibility.md) to help us understand what we can improve. -- [Beginner-friendly](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) issues are generally straightforward to complete. -- [Help wanted](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues are problems we would like the community to help us with regardless of complexity. +### Write documentation -If you're looking to make a code change, see how to set up your environment for [local development](contribute/developer-guide.md). - -When you're ready to contribute, it's time to [create a pull request](/contribute/create-pull-request.md). +To edit or write technical content, refer to [Contribute to our documentation](/contribute/documentation/README.md). We welcome your expertise and input as our body of technical content grows. #### Contributor License Agreement (CLA) diff --git a/apps/alerting/notifications/pkg/apis/alerting_manifest.go b/apps/alerting/notifications/pkg/apis/alerting_manifest.go index 4ea6c3da1c7..9b1e424d463 100644 --- a/apps/alerting/notifications/pkg/apis/alerting_manifest.go +++ b/apps/alerting/notifications/pkg/apis/alerting_manifest.go @@ -14,8 +14,6 @@ import ( v0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1" ) -var () - var appManifestData = app.ManifestData{ AppName: "alerting", Group: "notifications.alerting.grafana.app", diff --git a/apps/dashboard/pkg/apis/dashboard_manifest.go b/apps/dashboard/pkg/apis/dashboard_manifest.go index 7a4552f5e0a..568e229d09d 100644 --- a/apps/dashboard/pkg/apis/dashboard_manifest.go +++ b/apps/dashboard/pkg/apis/dashboard_manifest.go @@ -16,8 +16,6 @@ import ( v2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1" ) -var () - var appManifestData = app.ManifestData{ AppName: "dashboard", Group: "dashboard.grafana.app", diff --git a/apps/folder/pkg/apis/folder_manifest.go b/apps/folder/pkg/apis/folder_manifest.go index 8525663fea8..8491ddc6083 100644 --- a/apps/folder/pkg/apis/folder_manifest.go +++ b/apps/folder/pkg/apis/folder_manifest.go @@ -14,8 +14,6 @@ import ( v1beta1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" ) -var () - var appManifestData = app.ManifestData{ AppName: "folder", Group: "folder.grafana.app", diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index c20e71dab3d..4015e51df88 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -82,7 +82,7 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general- | `alertingMigrationUI` | Enables the alerting migration UI, to migrate data source-managed rules to Grafana-managed rules | Yes | | `alertingImportYAMLUI` | Enables a UI feature for importing rules from a Prometheus file to Grafana-managed rules | Yes | | `unifiedNavbars` | Enables unified navbars | | -| `tabularNumbers` | Use fixed-width numbers globally in the UI | Yes | +| `tabularNumbers` | Use fixed-width numbers globally in the UI | | ## Public preview feature toggles diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md index 5091d40fd94..2405baa4ca0 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md @@ -239,10 +239,6 @@ Ensure that you have followed the steps in [Create the Microsoft Entra ID applic ## Configure Azure AD authentication client using the Grafana UI -{{< admonition type="note" >}} -Available in Public Preview in Grafana 10.4 behind the `ssoSettingsApi` feature toggle. -{{< /admonition >}} - As a Grafana Admin, you can configure your Azure AD/Entra ID OAuth client from within Grafana using the Grafana UI. To do this, navigate to the **Administration > Authentication > Azure AD** page and fill in the form. If you have a current configuration in the Grafana configuration file, the form will be pre-populated with those values. Otherwise the form will contain default values. After you have filled in the form, click **Save** to save the configuration. If the save was successful, Grafana will apply the new configurations. @@ -255,10 +251,6 @@ If you run Grafana in high availability mode, configuration changes may not get ## Configure Azure AD authentication client using the Terraform provider -{{< admonition type="note" >}} -Available in Public Preview in Grafana 10.4 behind the `ssoSettingsApi` feature toggle. Supported in the Terraform provider since v2.12.0. -{{< /admonition >}} - ```terraform resource "grafana_sso_settings" "azuread_sso_settings" { provider_name = "azuread" diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md index 3beaeca97ff..d1a613d6b66 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md @@ -49,10 +49,6 @@ If Users use the same email address in Azure AD that they use with other authent ## Configure generic OAuth authentication client using the Grafana UI -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. -{{< /admonition >}} - As a Grafana Admin, you can configure Generic OAuth client from within Grafana using the Generic OAuth UI. To do this, navigate to **Administration > Authentication > Generic OAuth** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values. After you have filled in the form, click **Save** to save the configuration. If the save was successful, Grafana will apply the new configurations. @@ -67,10 +63,6 @@ Refer to [configuration options](#configuration-options) for more information. ## Configure generic OAuth authentication client using the Terraform provider -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0. -{{< /admonition >}} - ```terraform resource "grafana_sso_settings" "generic_sso_settings" { provider_name = "generic_oauth" diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md index 25e83cfd5e6..86edef93132 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md @@ -43,10 +43,6 @@ Ensure you know how to create a GitHub OAuth app. Consult GitHub's documentation ## Configure GitHub authentication client using the Grafana UI -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. -{{< /admonition >}} - As a Grafana Admin, you can configure GitHub OAuth client from within Grafana using the GitHub UI. To do this, navigate to **Administration > Authentication > GitHub** page and fill in the form. If you have a current configuration in the Grafana configuration file, the form will be pre-populated with those values. Otherwise the form will contain default values. After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations. @@ -61,10 +57,6 @@ Refer to [configuration options](#configuration-options) for more information. ## Configure GitHub authentication client using the Terraform provider -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0. -{{< /admonition >}} - ```terraform resource "grafana_sso_settings" "github_sso_settings" { provider_name = "github" diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md index ad42174ae64..8f0aaf0f38f 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md @@ -57,10 +57,6 @@ Refer to [configuration options](#configuration-options) for more information. ## Configure GitLab authentication client using the Terraform provider -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0. -{{< /admonition >}} - ```terraform resource "grafana_sso_settings" "gitlab_sso_settings" { provider_name = "gitlab" diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md index 4561f6c63b3..b162eb52305 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md @@ -45,10 +45,6 @@ First, you need to create a Google OAuth Client: ## Configure Google authentication client using the Grafana UI -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. -{{< /admonition >}} - As a Grafana Admin, you can configure Google OAuth client from within Grafana using the Google UI. To do this, navigate to **Administration > Authentication > Google** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values. After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations. @@ -61,10 +57,6 @@ If you run Grafana in high availability mode, configuration changes may not get ## Configure Google authentication client using the Terraform provider -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0. -{{< /admonition >}} - ```terraform resource "grafana_sso_settings" "google_sso_settings" { provider_name = "google" diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md index 1323a6ed423..93a21c70bc1 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md @@ -101,10 +101,6 @@ If you want to configure the role for all users in the Okta directory, you can a ## Configure Okta authentication client using the Grafana UI -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. -{{< /admonition >}} - As a Grafana Admin, you can configure Okta OAuth2 client from within Grafana using the Okta UI. To do this, navigate to **Administration > Authentication > Okta** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values. After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations. @@ -119,10 +115,6 @@ Refer to [configuration options](#configuration-options) for more information. ## Configure Okta authentication client using the Terraform provider -{{< admonition type="note" >}} -Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0. -{{< /admonition >}} - ```terraform resource "grafana_sso_settings" "okta_sso_settings" { provider_name = "okta" diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/_index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/_index.md index 06a38944b83..4a846a622e2 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/_index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/_index.md @@ -40,7 +40,7 @@ If you are using Okta or Azure AD as Identity Provider, see the following docume - [Configure SAML with Okta](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/saml/configure-saml-with-okta/) {{< admonition type="note" >}} -The API and Terraform support are available in Public Preview in Grafana v11.1 behind the `ssoSettingsSAML` feature toggle. You must also enable the `ssoSettingsApi` flag. +The API and Terraform support are available in Public Preview in Grafana v11.1 behind the `ssoSettingsSAML` feature toggle. {{< /admonition >}} All methods offer the same configuration options. However, if you want to keep all of Grafana authentication settings in one place, use the Grafana configuration file or the Terraform provider. If you are a Grafana Cloud user, you do not have access to Grafana configuration file. Instead, configure SAML through the other methods. diff --git a/e2e/test-plugins/grafana-extensionstest-app/package.json b/e2e/test-plugins/grafana-extensionstest-app/package.json index 5fe3da7246e..d11250bdc4d 100644 --- a/e2e/test-plugins/grafana-extensionstest-app/package.json +++ b/e2e/test-plugins/grafana-extensionstest-app/package.json @@ -3,8 +3,8 @@ "version": "12.1.0-pre", "private": true, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "dev": "webpack -w -c ./webpack.config.ts --env development", + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development", "typecheck": "tsc --noEmit", "lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx ." }, diff --git a/e2e/test-plugins/grafana-extensionstest-app/webpack.config.ts b/e2e/test-plugins/grafana-extensionstest-app/webpack.config.ts index 3303ed94f3c..564555396a5 100644 --- a/e2e/test-plugins/grafana-extensionstest-app/webpack.config.ts +++ b/e2e/test-plugins/grafana-extensionstest-app/webpack.config.ts @@ -1,7 +1,7 @@ import CopyWebpackPlugin from 'copy-webpack-plugin'; -import grafanaConfig from '@grafana/plugin-configs/webpack.config'; +import grafanaConfig, { type Env } from '@grafana/plugin-configs/webpack.config.ts'; import { mergeWithCustomize, unique } from 'webpack-merge'; -import { Configuration } from 'webpack'; +import { type Configuration } from 'webpack'; function skipFiles(f: string): boolean { if (f.includes('/dist/')) { @@ -19,7 +19,7 @@ function skipFiles(f: string): boolean { return true; } -const config = async (env: Record): Promise => { +const config = async (env: Env): Promise => { const baseConfig = await grafanaConfig(env); const customConfig = { plugins: [ diff --git a/e2e/test-plugins/grafana-test-datasource/package.json b/e2e/test-plugins/grafana-test-datasource/package.json index 437d542510a..9f976341268 100644 --- a/e2e/test-plugins/grafana-test-datasource/package.json +++ b/e2e/test-plugins/grafana-test-datasource/package.json @@ -3,8 +3,8 @@ "version": "12.1.0-pre", "private": true, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "dev": "webpack -w -c ./webpack.config.ts --env development", + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development", "typecheck": "tsc --noEmit", "lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx ." }, diff --git a/e2e/test-plugins/grafana-test-datasource/webpack.config.ts b/e2e/test-plugins/grafana-test-datasource/webpack.config.ts index 3303ed94f3c..564555396a5 100644 --- a/e2e/test-plugins/grafana-test-datasource/webpack.config.ts +++ b/e2e/test-plugins/grafana-test-datasource/webpack.config.ts @@ -1,7 +1,7 @@ import CopyWebpackPlugin from 'copy-webpack-plugin'; -import grafanaConfig from '@grafana/plugin-configs/webpack.config'; +import grafanaConfig, { type Env } from '@grafana/plugin-configs/webpack.config.ts'; import { mergeWithCustomize, unique } from 'webpack-merge'; -import { Configuration } from 'webpack'; +import { type Configuration } from 'webpack'; function skipFiles(f: string): boolean { if (f.includes('/dist/')) { @@ -19,7 +19,7 @@ function skipFiles(f: string): boolean { return true; } -const config = async (env: Record): Promise => { +const config = async (env: Env): Promise => { const baseConfig = await grafanaConfig(env); const customConfig = { plugins: [ diff --git a/go.mod b/go.mod index 44aa93b4190..86ece166842 100644 --- a/go.mod +++ b/go.mod @@ -99,14 +99,14 @@ require ( github.com/grafana/grafana-api-golang-client v0.27.0 // @grafana/alerting-backend github.com/grafana/grafana-app-sdk v0.39.2 // @grafana/grafana-app-platform-squad github.com/grafana/grafana-app-sdk/logging v0.39.1 // @grafana/grafana-app-platform-squad - github.com/grafana/grafana-aws-sdk v1.0.2 // @grafana/aws-datasources + github.com/grafana/grafana-aws-sdk v1.0.3 // @grafana/aws-datasources github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6 // @grafana/partner-datasources github.com/grafana/grafana-cloud-migration-snapshot v1.6.0 // @grafana/grafana-operator-experience-squad github.com/grafana/grafana-google-sdk-go v0.4.1 // @grafana/partner-datasources github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 // @grafana/grafana-backend-group github.com/grafana/grafana-plugin-sdk-go v0.278.0 // @grafana/plugins-platform-backend github.com/grafana/loki/v3 v3.2.1 // @grafana/observability-logs - github.com/grafana/nanogit v0.0.0-20250625082556-a4828b879bbb // @grafana-app-platform-squad + github.com/grafana/nanogit v0.0.0-20250709085038-55508a6a9f40 // @grafana-app-platform-squad github.com/grafana/otel-profiling-go v0.5.1 // @grafana/grafana-backend-group github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // @grafana/observability-traces-and-profiling github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae // @grafana/observability-traces-and-profiling diff --git a/go.sum b/go.sum index 88a184a171a..53054254a04 100644 --- a/go.sum +++ b/go.sum @@ -1610,8 +1610,8 @@ github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmF github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY= github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU= github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk= -github.com/grafana/grafana-aws-sdk v1.0.2 h1:98eBuHYFmgvH0xO9kKf4RBsEsgQRp8EOA/9yhDIpkss= -github.com/grafana/grafana-aws-sdk v1.0.2/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE= +github.com/grafana/grafana-aws-sdk v1.0.3 h1:FtGiTrdlPXuQmLqeZdyNjjkNKOOdvQ4sxWw8MtJc6ow= +github.com/grafana/grafana-aws-sdk v1.0.3/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE= github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6 h1:OfCkitCuomzZKW1WYHrG8MxKwtMhALb7jqoj+487eTg= github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6/go.mod h1:V7y2BmsWxS3A9Ohebwn4OiSfJJqi//4JQydQ8fHTduo= github.com/grafana/grafana-cloud-migration-snapshot v1.6.0 h1:S4kHwr//AqhtL9xHBtz1gqVgZQeCRGTxjgsRBAkpjKY= @@ -1654,8 +1654,8 @@ github.com/grafana/loki/pkg/push v0.0.0-20231124142027-e52380921608 h1:ZYk42718k github.com/grafana/loki/pkg/push v0.0.0-20231124142027-e52380921608/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= github.com/grafana/loki/v3 v3.2.1 h1:VB7u+KHfvL5aHAxgoVBvz5wVhsdGuqKC7uuOFOOe7jw= github.com/grafana/loki/v3 v3.2.1/go.mod h1:WvdLl6wOS+yahaeQY+xhD2m2XzkHDfKr5FZaX7D/X2Y= -github.com/grafana/nanogit v0.0.0-20250625082556-a4828b879bbb h1:JR672zBiCkfiKuRRsU76TRC2q12q0VfZl2SP8jBIAJQ= -github.com/grafana/nanogit v0.0.0-20250625082556-a4828b879bbb/go.mod h1:tN93IZUaAmnSWgL0IgnKdLv6DNeIhTJGvl1wvQMrWco= +github.com/grafana/nanogit v0.0.0-20250709085038-55508a6a9f40 h1:wsIgOI4Ou1o/UtxtJlemLufpVBpMdcXVJxedk0wLoCM= +github.com/grafana/nanogit v0.0.0-20250709085038-55508a6a9f40/go.mod h1:ToqLjIdvV3AZQa3K6e5m9hy/nsGaUByc2dWQlctB9iA= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= github.com/grafana/prometheus-alertmanager v0.25.1-0.20250620093340-be61a673dee6 h1:oJnbhG6ZNy10AjsgNeAtAKeGHogIGOMfAsBH6fYYa5M= diff --git a/package.json b/package.json index 515bc414b97..f22f1b7196e 100644 --- a/package.json +++ b/package.json @@ -180,7 +180,7 @@ "cypress": "14.3.2", "cypress-file-upload": "5.0.8", "cypress-recurse": "^1.35.3", - "esbuild": "0.25.0", + "esbuild": "0.25.6", "esbuild-loader": "4.3.0", "esbuild-plugin-browserslist": "^1.0.0", "eslint": "9.19.0", @@ -192,13 +192,13 @@ "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-lodash": "8.0.0", "eslint-plugin-no-barrel-files": "^1.1.1", - "eslint-plugin-react": "7.37.4", + "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "5.1.0", "eslint-plugin-testing-library": "^7.0.0", "eslint-plugin-unicorn": "^56.0.0", "eslint-scope": "^8.1.0", "eslint-webpack-plugin": "4.2.0", - "expose-loader": "5.0.0", + "expose-loader": "5.0.1", "fishery": "^2.2.2", "fork-ts-checker-webpack-plugin": "9.0.2", "glob": "11.0.1", @@ -279,7 +279,7 @@ "@grafana/faro-web-sdk": "^1.13.2", "@grafana/faro-web-tracing": "^1.13.2", "@grafana/flamegraph": "workspace:*", - "@grafana/google-sdk": "0.3.2", + "@grafana/google-sdk": "0.3.4", "@grafana/i18n": "workspace:*", "@grafana/lezer-logql": "0.2.8", "@grafana/llm": "0.22.1", diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index aa2da7aef48..9d43bc9b4fa 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -92,7 +92,7 @@ "@types/react": "18.3.18", "@types/react-dom": "18.3.5", "@types/tinycolor2": "1.4.6", - "esbuild": "0.25.0", + "esbuild": "0.25.6", "react": "18.3.1", "react-dom": "18.3.1", "rimraf": "6.0.1", diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 4a5de4fd928..c1099124dc5 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -999,7 +999,7 @@ export interface FeatureToggles { preferLibraryPanelTitle?: boolean; /** * Use fixed-width numbers globally in the UI - * @default true + * @default false */ tabularNumbers?: boolean; /** diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index aaa4a34e671..265adc2ffdb 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -42,7 +42,7 @@ "@rollup/plugin-node-resolve": "16.0.1", "@types/node": "22.15.0", "@types/semver": "7.7.0", - "esbuild": "0.25.0", + "esbuild": "0.25.6", "rimraf": "6.0.1", "rollup": "^4.22.4", "rollup-plugin-esbuild": "6.2.0", diff --git a/packages/grafana-flamegraph/package.json b/packages/grafana-flamegraph/package.json index 4e744fa3d8a..93e41401ba8 100644 --- a/packages/grafana-flamegraph/package.json +++ b/packages/grafana-flamegraph/package.json @@ -73,7 +73,7 @@ "@types/react-virtualized-auto-sizer": "1.0.4", "@types/tinycolor2": "1.4.6", "babel-jest": "29.7.0", - "esbuild": "0.25.0", + "esbuild": "0.25.6", "jest": "^29.6.4", "jest-canvas-mock": "2.5.2", "rollup": "^4.22.4", diff --git a/packages/grafana-plugin-configs/package.json b/packages/grafana-plugin-configs/package.json index 845ae3a750f..ffd590576f5 100644 --- a/packages/grafana-plugin-configs/package.json +++ b/packages/grafana-plugin-configs/package.json @@ -6,6 +6,7 @@ "dependencies": { "tslib": "2.8.1" }, + "type": "module", "devDependencies": { "@grafana/tsconfig": "^2.0.0", "@swc/core": "1.10.12", diff --git a/packages/grafana-plugin-configs/tsconfig.json b/packages/grafana-plugin-configs/tsconfig.json index 1790c28c284..b7a0dd239e8 100644 --- a/packages/grafana-plugin-configs/tsconfig.json +++ b/packages/grafana-plugin-configs/tsconfig.json @@ -4,19 +4,11 @@ "alwaysStrict": true, "declaration": false, "resolveJsonModule": true, - "moduleResolution": "bundler" - }, - "ts-node": { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "moduleResolution": "Node", - "esModuleInterop": true - }, - "transpileOnly": true + "moduleResolution": "bundler", + "noEmit": true, + "allowImportingTsExtensions": true }, "extends": "@grafana/tsconfig", - "exclude": ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"], "include": ["./types", "."] } diff --git a/packages/grafana-plugin-configs/types/replace-in-webpack-plugin.d.ts b/packages/grafana-plugin-configs/types/replace-in-webpack-plugin.d.ts new file mode 100644 index 00000000000..746b3e0d303 --- /dev/null +++ b/packages/grafana-plugin-configs/types/replace-in-webpack-plugin.d.ts @@ -0,0 +1,23 @@ +declare module 'replace-in-file-webpack-plugin' { + import { Compiler, Plugin } from 'webpack'; + + interface ReplaceRule { + search: string | RegExp; + replace: string | ((match: string) => string); + } + + interface ReplaceOption { + dir?: string; + files?: string[]; + test?: RegExp | RegExp[]; + rules: ReplaceRule[]; + } + + class ReplaceInFilePlugin extends Plugin { + constructor(options?: ReplaceOption[]); + options: ReplaceOption[]; + apply(compiler: Compiler): void; + } + + export = ReplaceInFilePlugin; +} diff --git a/packages/grafana-plugin-configs/utils.ts b/packages/grafana-plugin-configs/utils.ts index 3a74dd90af6..7c517dc2d18 100644 --- a/packages/grafana-plugin-configs/utils.ts +++ b/packages/grafana-plugin-configs/utils.ts @@ -3,12 +3,19 @@ import { glob } from 'glob'; import path from 'path'; import process from 'process'; +// Support for node 22 and 24. Due to the many changes in importing json files +// across recent node versions we load the json files using fs for simplicity. +function loadJson(path: string) { + const rawJson = fs.readFileSync(path, 'utf8'); + return JSON.parse(rawJson); +} + export function getPackageJson() { - return require(path.resolve(process.cwd(), 'package.json')); + return loadJson(path.resolve(process.cwd(), 'package.json')); } export function getPluginJson() { - return require(path.resolve(process.cwd(), 'plugin.json')); + return loadJson(path.resolve(process.cwd(), 'plugin.json')); } export async function getEntries(): Promise> { diff --git a/packages/grafana-plugin-configs/webpack.config.ts b/packages/grafana-plugin-configs/webpack.config.ts index 7714093000a..c1bfc469d7b 100644 --- a/packages/grafana-plugin-configs/webpack.config.ts +++ b/packages/grafana-plugin-configs/webpack.config.ts @@ -2,15 +2,14 @@ import CopyWebpackPlugin from 'copy-webpack-plugin'; import ESLintPlugin from 'eslint-webpack-plugin'; import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import path from 'path'; -// @ts-expect-error - there are no types for this package import ReplaceInFileWebpackPlugin from 'replace-in-file-webpack-plugin'; import TerserPlugin from 'terser-webpack-plugin'; -import { type Configuration, BannerPlugin } from 'webpack'; +import webpack, { type Configuration } from 'webpack'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import VirtualModulesPlugin from 'webpack-virtual-modules'; -import { DIST_DIR } from './constants'; -import { getPackageJson, getPluginJson, getEntries, hasLicense } from './utils'; +import { DIST_DIR } from './constants.ts'; +import { getPackageJson, getPluginJson, getEntries, hasLicense } from './utils.ts'; function skipFiles(f: string): boolean { if (f.includes('/dist/')) { @@ -32,7 +31,7 @@ function skipFiles(f: string): boolean { return true; } -type Env = { +export type Env = { [key: string]: true | string | Env; }; @@ -54,9 +53,13 @@ const config = async (env: Env): Promise => { cache: { type: 'filesystem', buildDependencies: { - config: [__filename], + config: [import.meta.filename], }, - cacheDirectory: path.resolve(__dirname, '../../node_modules/.cache/webpack', path.basename(process.cwd())), + cacheDirectory: path.resolve( + import.meta.dirname, + '../../node_modules/.cache/webpack', + path.basename(process.cwd()) + ), }, context: process.cwd(), @@ -114,7 +117,7 @@ const config = async (env: Env): Promise => { test: /module\.tsx?$/, use: [ { - loader: require.resolve('imports-loader'), + loader: 'imports-loader', options: { imports: `side-effects grafana-public-path`, }, @@ -125,10 +128,10 @@ const config = async (env: Env): Promise => { exclude: /(node_modules)/, test: /\.[tj]sx?$/, use: { - loader: require.resolve('swc-loader'), + loader: 'swc-loader', options: { jsc: { - baseUrl: path.resolve(__dirname), + baseUrl: path.resolve(import.meta.dirname), target: 'es2015', loose: false, parser: { @@ -209,7 +212,7 @@ const config = async (env: Env): Promise => { plugins: [ virtualPublicPath, // Insert create plugin version information into the bundle so Grafana will load from cdn with script tags. - new BannerPlugin({ + new webpack.BannerPlugin({ banner: '/* [create-plugin] version: 5.22.0 */', raw: true, entryOnly: true, @@ -264,7 +267,7 @@ const config = async (env: Env): Promise => { extensions: ['.ts', '.tsx'], lintDirtyModulesOnly: true, // don't lint on start, only lint changed files cacheLocation: path.resolve( - __dirname, + import.meta.dirname, '../../node_modules/.cache/eslint-webpack-plugin', path.basename(process.cwd()), '.eslintcache' diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index 973cd50edaf..d6a5ef7fd3e 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -90,7 +90,7 @@ "@types/node": "22.15.0", "@types/pluralize": "^0.0.33", "@types/prismjs": "1.26.5", - "esbuild": "0.25.0", + "esbuild": "0.25.6", "i18next-parser": "9.3.0", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index 7eab5671779..3d129df19ae 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -78,7 +78,7 @@ "@types/lodash": "4.17.20", "@types/react": "18.3.18", "@types/react-dom": "18.3.5", - "esbuild": "0.25.0", + "esbuild": "0.25.6", "lodash": "4.17.21", "react": "18.3.1", "react-dom": "18.3.1", diff --git a/packages/grafana-schema/package.json b/packages/grafana-schema/package.json index 466b6adcbfc..8dc2e5efe1f 100644 --- a/packages/grafana-schema/package.json +++ b/packages/grafana-schema/package.json @@ -38,7 +38,7 @@ "devDependencies": { "@grafana/tsconfig": "^2.0.0", "@rollup/plugin-node-resolve": "16.0.1", - "esbuild": "0.25.0", + "esbuild": "0.25.6", "glob": "^11.0.0", "rimraf": "6.0.1", "rollup": "^4.22.4", diff --git a/packages/grafana-schema/src/raw/composable/logs/panelcfg/x/LogsPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/logs/panelcfg/x/LogsPanelCfg_types.gen.ts index dbf274e51bc..73b7933cd79 100644 --- a/packages/grafana-schema/src/raw/composable/logs/panelcfg/x/LogsPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/logs/panelcfg/x/LogsPanelCfg_types.gen.ts @@ -15,6 +15,7 @@ export const pluginVersion = "12.1.0-pre"; export interface Options { controlsStorageKey?: string; dedupStrategy: common.LogsDedupStrategy; + detailsMode?: ('inline' | 'sidebar'); displayedFields?: Array; enableInfiniteScrolling?: boolean; enableLogDetails: boolean; diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index e26cf46e5be..854e58ae28a 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -181,8 +181,8 @@ "core-js": "3.40.0", "css-loader": "7.1.2", "csstype": "3.1.3", - "esbuild": "0.25.0", - "expose-loader": "5.0.0", + "esbuild": "0.25.6", + "expose-loader": "5.0.1", "fs-extra": "^11.2.0", "mock-raf": "1.0.1", "msw": "^2.10.2", diff --git a/packages/grafana-ui/src/components/Cascader/styles.ts b/packages/grafana-ui/src/components/Cascader/styles.ts index cef38b62dcc..68055527b24 100644 --- a/packages/grafana-ui/src/components/Cascader/styles.ts +++ b/packages/grafana-ui/src/components/Cascader/styles.ts @@ -2,6 +2,8 @@ import { css, keyframes } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; +import { getIconPath } from '../Icon/utils'; + const slideUpIn = keyframes({ '0%': { opacity: 0, @@ -58,143 +60,146 @@ const slideDownOut = keyframes({ }, }); -export const getCascaderStyles = (theme: GrafanaTheme2) => ({ - dropdown: css({ - '&.rc-cascader-dropdown': { - position: 'absolute', - // Required, otherwise the portal that the popup is shown in will render under other components - zIndex: 9999, +export const getCascaderStyles = (theme: GrafanaTheme2) => { + const iconPath = getIconPath('angle-right'); + return { + dropdown: css({ + '&.rc-cascader-dropdown': { + position: 'absolute', + // Required, otherwise the portal that the popup is shown in will render under other components + zIndex: 9999, - '&-hidden': { - display: 'none', - }, - }, - '.rc-cascader': { - '&-menus': { - overflow: 'hidden', - background: theme.colors.background.elevated, - border: `none`, - borderRadius: theme.shape.radius.default, - boxShadow: theme.shadows.z3, - whiteSpace: 'nowrap', - - '&.slide-up-enter, &.slide-up-appear': { - animationDuration: '0.3s', - animationFillMode: 'both', - transformOrigin: '0 0', - opacity: 0, - animationTimingFunction: 'cubic-bezier(0.08, 0.82, 0.17, 1)', - animationPlayState: 'paused', - }, - - '&.slide-up-enter.slide-up-enter-active.rc-cascader-menus-placement, &.slide-up-appear.slide-up-appear-active.rc-cascader-menus-placement': - { - '&-bottomLeft': { - animationName: slideUpIn, - animationPlayState: 'running', - }, - - '&-topLeft': { - animationName: slideDownIn, - animationPlayState: 'running', - }, - }, - - '&.slide-up-leave': { - animationDuration: '0.3s', - animationFillMode: 'both', - transformOrigin: '0 0', - opacity: 1, - animationTimingFunction: 'cubic-bezier(0.6, 0.04, 0.98, 0.34)', - animationPlayState: 'paused', - - '&.slide-up-leave-active.rc-cascader-menus-placement': { - '&-bottomLeft': { - animationName: slideUpOut, - animationPlayState: 'running', - }, - - '&-topLeft': { - animationName: slideDownOut, - animationPlayState: 'running', - }, - }, + '&-hidden': { + display: 'none', }, }, - - '&-menu': { - display: 'inline-block', - maxWidth: '50vw', - height: '192px', - listStyle: 'none', - margin: 0, - padding: theme.spacing(0.5), - borderRight: `1px solid ${theme.colors.border.weak}`, - overflow: 'auto', - - '&:last-child': { - borderRight: 0, - }, - - '&-item': { - height: theme.spacing(4), - lineHeight: theme.spacing(4), - padding: theme.spacing(0, 4, 0, 2), - borderRadius: theme.shape.radius.default, - cursor: 'pointer', - whiteSpace: 'nowrap', + '.rc-cascader': { + '&-menus': { overflow: 'hidden', - textOverflow: 'ellipsis', - transition: 'all 0.3s ease', - position: 'relative', + background: theme.colors.background.elevated, + border: `none`, + borderRadius: theme.shape.radius.default, + boxShadow: theme.shadows.z3, + whiteSpace: 'nowrap', - '&:hover': { - background: theme.colors.action.hover, + '&.slide-up-enter, &.slide-up-appear': { + animationDuration: '0.3s', + animationFillMode: 'both', + transformOrigin: '0 0', + opacity: 0, + animationTimingFunction: 'cubic-bezier(0.08, 0.82, 0.17, 1)', + animationPlayState: 'paused', }, - '&-disabled': { - cursor: 'not-allowed', - color: theme.colors.text.disabled, + '&.slide-up-enter.slide-up-enter-active.rc-cascader-menus-placement, &.slide-up-appear.slide-up-appear-active.rc-cascader-menus-placement': + { + '&-bottomLeft': { + animationName: slideUpIn, + animationPlayState: 'running', + }, - '&:hover': { - background: 'transparent', + '&-topLeft': { + animationName: slideDownIn, + animationPlayState: 'running', + }, }, - '&:after': { - position: 'absolute', - right: '12px', - content: "'loading'", - color: theme.colors.text.disabled, - fontStyle: 'italic', + '&.slide-up-leave': { + animationDuration: '0.3s', + animationFillMode: 'both', + transformOrigin: '0 0', + opacity: 1, + animationTimingFunction: 'cubic-bezier(0.6, 0.04, 0.98, 0.34)', + animationPlayState: 'paused', + + '&.slide-up-leave-active.rc-cascader-menus-placement': { + '&-bottomLeft': { + animationName: slideUpOut, + animationPlayState: 'running', + }, + + '&-topLeft': { + animationName: slideDownOut, + animationPlayState: 'running', + }, }, }, + }, - '&-active': { - color: theme.colors.text.maxContrast, - background: theme.colors.background.secondary, + '&-menu': { + display: 'inline-block', + maxWidth: '50vw', + height: '192px', + listStyle: 'none', + margin: 0, + padding: theme.spacing(0.5), + borderRight: `1px solid ${theme.colors.border.weak}`, + overflow: 'auto', + + '&:last-child': { + borderRight: 0, + }, + + '&-item': { + height: theme.spacing(4), + lineHeight: theme.spacing(4), + padding: theme.spacing(0, 4, 0, 2), + borderRadius: theme.shape.radius.default, + cursor: 'pointer', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + transition: 'all 0.3s ease', + position: 'relative', '&:hover': { background: theme.colors.action.hover, }, - }, - '&-expand': { - position: 'relative', + '&-disabled': { + cursor: 'not-allowed', + color: theme.colors.text.disabled, - '&:after': { + '&:hover': { + background: 'transparent', + }, + + '&:after': { + position: 'absolute', + right: '12px', + content: "'loading'", + color: theme.colors.text.disabled, + fontStyle: 'italic', + }, + }, + + '&-active': { + color: theme.colors.text.maxContrast, background: theme.colors.background.secondary, - content: "''", - height: theme.spacing(3), - mask: 'url(../img/icons/unicons/angle-right.svg)', - maskType: 'luminance', - position: 'absolute', - right: 0, - top: theme.spacing(0.5), - width: theme.spacing(3), + + '&:hover': { + background: theme.colors.action.hover, + }, + }, + + '&-expand': { + position: 'relative', + + '&:after': { + background: theme.colors.text.primary, + content: "''", + height: theme.spacing(3), + mask: `url(${iconPath})`, + maskType: 'luminance', + position: 'absolute', + right: 0, + top: theme.spacing(0.5), + width: theme.spacing(3), + }, }, }, }, }, - }, - }), -}); + }), + }; +}; diff --git a/packages/grafana-ui/src/components/Icon/Icon.tsx b/packages/grafana-ui/src/components/Icon/Icon.tsx index f961cafcc14..59135b9a89f 100644 --- a/packages/grafana-ui/src/components/Icon/Icon.tsx +++ b/packages/grafana-ui/src/components/Icon/Icon.tsx @@ -8,7 +8,7 @@ import { useStyles2 } from '../../themes/ThemeContext'; import { IconName, IconType, IconSize } from '../../types/icon'; import { spin } from '../../utils/keyframes'; -import { getIconRoot, getIconSubDir, getSvgSize } from './utils'; +import { getIconPath, getSvgSize } from './utils'; export interface IconProps extends Omit, 'onLoad' | 'onError' | 'ref'> { name: IconName; @@ -53,12 +53,10 @@ export const Icon = React.forwardRef( // handle the deprecated 'fa fa-spinner' const iconName: IconName = name === 'fa fa-spinner' ? 'spinner' : name; - const iconRoot = getIconRoot(); const svgSize = getSvgSize(size); const svgHgt = svgSize; const svgWid = name.startsWith('gf-bar-align') ? 16 : name.startsWith('gf-interp') ? 30 : svgSize; - const subDir = getIconSubDir(iconName, type); - const svgPath = `${iconRoot}${subDir}/${iconName}.svg`; + const svgPath = getIconPath(iconName, type); const composedClassName = cx( styles.icon, diff --git a/packages/grafana-ui/src/components/Icon/utils.ts b/packages/grafana-ui/src/components/Icon/utils.ts index 263e68ac0ff..30f350ee667 100644 --- a/packages/grafana-ui/src/components/Icon/utils.ts +++ b/packages/grafana-ui/src/components/Icon/utils.ts @@ -60,3 +60,9 @@ export function getIconRoot(): string { return iconRoot; } + +export function getIconPath(name: IconName, type: IconType = 'default'): string { + const iconRoot = getIconRoot(); + const subDir = getIconSubDir(name, type); + return `${iconRoot}${subDir}/${name}.svg`; +} diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx index 558d1c7978d..ba5cc0749f1 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx @@ -42,7 +42,8 @@ export function TableCellActions(props: TableCellActionsProps) { dataProjection: 'EPSG:4326', }); mode = TableCellInspectorMode.code; - } else if ('cellType' in cellOptions && cellOptions.cellType === TableCellDisplayMode.JSONView) { + } + if (cellOptions.type === TableCellDisplayMode.JSONView) { mode = TableCellInspectorMode.code; } diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.test.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.test.tsx index b27c050445d..2f364bfa732 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.test.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.test.tsx @@ -141,6 +141,14 @@ describe('TableNG Cells renderers', () => { expect(container).toBeInTheDocument(); expect(container.childNodes).toHaveLength(1); }); + + it('should return AutoCell when cellOptions is unmapped', () => { + const field = createField(FieldType.string); + + const { container } = renderCell(field, { type: 'number' } as unknown as TableCellOptions); + expect(container).toBeInTheDocument(); + expect(container.childNodes).toHaveLength(1); + }); }); }); diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx index d4a16b1d982..74c773f28ff 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx @@ -109,7 +109,7 @@ export function getCellRenderer(field: Field, cellOptions: TableCellOptions): Ta if (cellType === TableCellDisplayMode.Auto) { return getAutoRendererResult(field); } - return CELL_RENDERERS[cellType]; + return CELL_RENDERERS[cellType] ?? AUTO_RENDERER; } /** @internal */ diff --git a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx index aa35b99ae9c..129eb256c97 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx @@ -81,13 +81,14 @@ export function TableNG(props: TableNGProps) { onSortByChange, showTypeIcons, structureRev, + transparent, width, } = props; const theme = useTheme2(); const styles = useStyles2(getGridStyles, { enablePagination, - noHeader, + transparent, }); const panelContext = usePanelContext(); @@ -244,21 +245,9 @@ export function TableNG(props: TableNGProps) { }, sortColumns, rowHeight, - headerRowClass: styles.headerRow, - headerRowHeight: headerHeight, bottomSummaryRows: hasFooter ? [{}] : undefined, }) satisfies Partial>, - [ - enableVirtualization, - resizeHandler, - sortColumns, - headerHeight, - styles.headerRow, - rowHeight, - hasFooter, - setSortColumns, - onSortByChange, - ] + [enableVirtualization, resizeHandler, sortColumns, rowHeight, hasFooter, setSortColumns, onSortByChange] ); interface Schema { @@ -437,6 +426,7 @@ export function TableNG(props: TableNGProps) { return result; } + const hasNestedHeaders = firstNestedData.meta?.custom?.noHeader !== true; const renderRow = renderRowFactory(firstNestedData.fields, panelContext, expandedRows, enableSharedCrosshair); const { columns: nestedColumns, cellRootRenderers: nestedCellRootRenderers } = fromFields( firstNestedData.fields, @@ -486,11 +476,20 @@ export function TableNG(props: TableNGProps) { } const expandedRecords = applySort(frameToRecords(nestedData), nestedData.fields, sortColumns); + if (!expandedRecords.length) { + return ( +
+ No data +
+ ); + } return ( {...commonDataGridProps} className={cx(styles.grid, styles.gridNested)} + headerRowClass={cx(styles.headerRow, { [styles.displayNone]: !hasNestedHeaders })} + headerRowHeight={hasNestedHeaders ? defaultHeaderHeight : 0} columns={nestedColumns} rows={expandedRecords} renderers={{ renderRow, renderCell: renderCellRoot }} @@ -509,6 +508,7 @@ export function TableNG(props: TableNGProps) { crossFilterOrder, crossFilterRows, data, + defaultHeaderHeight, defaultRowHeight, enableSharedCrosshair, expandedRows, @@ -552,6 +552,8 @@ export function TableNG(props: TableNGProps) { className={styles.grid} columns={structureRevColumns} rows={paginatedRows} + headerRowClass={cx(styles.headerRow, { [styles.displayNone]: noHeader })} + headerRowHeight={headerHeight} onCellClick={({ column, row }, { clientX, clientY, preventGridDefault }) => { // Note: could be column.field; JS says yes, but TS says no! const field = columns[column.idx].field; @@ -693,17 +695,20 @@ const renderRowFactory = const getGridStyles = ( theme: GrafanaTheme2, - { enablePagination, noHeader }: { enablePagination?: boolean; noHeader?: boolean } + { enablePagination, transparent }: { enablePagination?: boolean; transparent?: boolean } ) => ({ grid: css({ - '--rdg-background-color': theme.colors.background.primary, - '--rdg-header-background-color': theme.colors.background.primary, - '--rdg-border-color': theme.isDark ? '#282b30' : '#ebebec', + '--rdg-background-color': transparent ? theme.colors.background.canvas : theme.colors.background.primary, + '--rdg-header-background-color': transparent ? theme.colors.background.canvas : theme.colors.background.primary, + '--rdg-border-color': theme.colors.border.weak, '--rdg-color': theme.colors.text.primary, // note: this cannot have any transparency since default cells that // overlay/overflow on hover inherit this background and need to occlude cells below - '--rdg-row-hover-background-color': theme.isDark ? '#212428' : '#f4f5f5', + '--rdg-row-background-color': transparent ? theme.colors.background.canvas : theme.colors.background.primary, + '--rdg-row-hover-background-color': transparent + ? theme.colors.background.primary + : theme.colors.background.secondary, // TODO: magic 32px number is unfortunate. it would be better to have the content // flow using flexbox rather than hard-coding this size via a calc @@ -723,15 +728,24 @@ const getGridStyles = ( }), gridNested: css({ height: '100%', - width: `calc(100% - ${COLUMN.EXPANDER_WIDTH - 1}px)`, + width: `calc(100% - ${COLUMN.EXPANDER_WIDTH - TABLE.CELL_PADDING * 2 - 1}px)`, overflow: 'visible', - marginLeft: COLUMN.EXPANDER_WIDTH - 1, + marginLeft: COLUMN.EXPANDER_WIDTH - TABLE.CELL_PADDING - 1, + marginBlock: TABLE.CELL_PADDING, }), cellNested: css({ '&[aria-selected=true]': { outline: 'none', }, }), + noDataNested: css({ + height: TABLE.NESTED_NO_DATA_HEIGHT, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + color: theme.colors.text.secondary, + fontSize: theme.typography.h4.fontSize, + }), cellActions: css({ display: 'none', position: 'absolute', @@ -739,7 +753,7 @@ const getGridStyles = ( margin: 'auto', height: '100%', color: theme.colors.text.primary, - background: theme.isDark ? 'rgba(0, 0, 0, 0.3)' : 'rgba(255, 255, 255, 0.7)', + background: theme.isDark ? 'rgba(0, 0, 0, 0.7)' : 'rgba(255, 255, 255, 0.7)', padding: theme.spacing.x0_5, paddingInlineStart: theme.spacing.x1, }), @@ -752,12 +766,14 @@ const getGridStyles = ( headerRow: css({ paddingBlockStart: 0, fontWeight: 'normal', - ...(noHeader ? { display: 'none' } : {}), '& .rdg-cell': { height: '100%', alignItems: 'flex-end', }, }), + displayNone: css({ + display: 'none', + }), paginationContainer: css({ alignItems: 'center', display: 'flex', @@ -835,6 +851,7 @@ const getCellStyles = ( whiteSpace: 'pre-line', height: 'fit-content', minWidth: 'fit-content', + paddingBlock: (rowHeight - TABLE.LINE_HEIGHT) / 2 - 1, }), }, }), diff --git a/packages/grafana-ui/src/components/Table/TableNG/constants.ts b/packages/grafana-ui/src/components/Table/TableNG/constants.ts index d7d69c160c0..31a537136d2 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/constants.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/constants.ts @@ -14,5 +14,6 @@ export const TABLE = { SCROLL_BAR_WIDTH: 8, SCROLL_BAR_MARGIN: 2, LINE_HEIGHT: 22, + NESTED_NO_DATA_HEIGHT: 60, BORDER_RIGHT: 0.666667, }; diff --git a/packages/grafana-ui/src/components/Table/TableNG/hooks.ts b/packages/grafana-ui/src/components/Table/TableNG/hooks.ts index 33c89162939..4ef2c8f185e 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/hooks.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/hooks.ts @@ -503,9 +503,13 @@ export function useRowHeight({ return 0; } - // Ensure we have a minimum height (defaultHeight) for the nested table even if data is empty const rowCount = row.data?.length ?? 0; - return Math.max(defaultHeight, defaultHeight * rowCount + headerHeight); + if (rowCount === 0) { + return TABLE.NESTED_NO_DATA_HEIGHT + TABLE.CELL_PADDING * 2; + } + + const nestedHeaderHeight = row.data?.meta?.custom?.noHeader ? 0 : defaultHeight; + return Math.max(defaultHeight, defaultHeight * rowCount + nestedHeaderHeight + TABLE.CELL_PADDING * 2); } // regular rows @@ -519,7 +523,6 @@ export function useRowHeight({ fields, hasNestedFrames, hasWrappedCols, - headerHeight, maxWrapCellOptions, colWidths, ]); diff --git a/packages/grafana-ui/src/components/Table/TableNG/types.ts b/packages/grafana-ui/src/components/Table/TableNG/types.ts index 04caa62c85c..65d40d3c4d1 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/types.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/types.ts @@ -131,6 +131,7 @@ export interface BaseTableProps { enablePagination?: boolean; cellHeight?: TableCellHeight; structureRev?: number; + transparent?: boolean; /** @alpha Used by SparklineCell when provided */ timeRange?: TimeRange; enableSharedCrosshair?: boolean; diff --git a/pkg/api/preferences.go b/pkg/api/preferences.go index c9798e9a767..68bb5ba74c8 100644 --- a/pkg/api/preferences.go +++ b/pkg/api/preferences.go @@ -74,7 +74,7 @@ func (hs *HTTPServer) SetHomeDashboard(c *contextmodel.ReqContext) response.Resp func (hs *HTTPServer) GetUserPreferences(c *contextmodel.ReqContext) response.Response { userID, err := identity.UserIdentifier(c.GetID()) if err != nil { - return response.Error(http.StatusInternalServerError, "Failed to update user preferences", err) + return response.Error(http.StatusUnauthorized, "Not a valid identity", err) } return prefapi.GetPreferencesFor(c.Req.Context(), hs.DashboardService, hs.preferenceService, hs.Features, c.GetOrgID(), userID, 0) diff --git a/pkg/apis/secret/go.mod b/pkg/apis/secret/go.mod index ba65bd5f9c9..81f96e3ecd2 100644 --- a/pkg/apis/secret/go.mod +++ b/pkg/apis/secret/go.mod @@ -9,88 +9,36 @@ require ( google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 k8s.io/apimachinery v0.33.2 - k8s.io/apiserver v0.33.2 k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 ) require ( - github.com/beorn7/perks v1.0.1 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cenkalti/backoff/v5 v5.0.2 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/coreos/go-semver v0.3.1 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9 // indirect - github.com/google/go-cmp v0.7.0 // indirect - github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect - github.com/jonboulle/clockwork v0.5.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/onsi/ginkgo/v2 v2.22.2 // indirect - github.com/onsi/gomega v1.36.2 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.64.0 // indirect - github.com/prometheus/procfs v0.16.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/x448/float16 v0.8.4 // indirect - go.etcd.io/bbolt v1.4.0 // indirect - go.etcd.io/etcd/api/v3 v3.5.21 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect - go.etcd.io/etcd/client/v3 v3.5.21 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect go.opentelemetry.io/otel v1.36.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 // indirect - go.opentelemetry.io/otel/metric v1.36.0 // indirect - go.opentelemetry.io/otel/sdk v1.36.0 // indirect - go.opentelemetry.io/otel/trace v1.36.0 // indirect - go.opentelemetry.io/proto/otlp v1.6.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect golang.org/x/net v0.41.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sys v0.33.0 // indirect - golang.org/x/term v0.32.0 // indirect golang.org/x/text v0.26.0 // indirect - golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.34.0 // indirect - google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - k8s.io/api v0.33.2 // indirect - k8s.io/client-go v0.33.2 // indirect - k8s.io/component-base v0.33.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect diff --git a/pkg/apis/secret/go.sum b/pkg/apis/secret/go.sum index e8ea9a27592..3a4d0158519 100644 --- a/pkg/apis/secret/go.sum +++ b/pkg/apis/secret/go.sum @@ -1,41 +1,11 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= -github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= -github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -46,156 +16,58 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= -github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= -github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= -github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= -github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= -github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= -github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= -github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4= -github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= -github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk= -github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= -go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= -go.etcd.io/etcd/api/v3 v3.5.21 h1:A6O2/JDb3tvHhiIz3xf9nJ7REHvtEFJJ3veW3FbCnS8= -go.etcd.io/etcd/api/v3 v3.5.21/go.mod h1:c3aH5wcvXv/9dqIw2Y810LDXJfhSYdHQ0vxmP3CCHVY= -go.etcd.io/etcd/client/pkg/v3 v3.5.21 h1:lPBu71Y7osQmzlflM9OfeIV2JlmpBjqBNlLtcoBqUTc= -go.etcd.io/etcd/client/pkg/v3 v3.5.21/go.mod h1:BgqT/IXPjK9NkeSDjbzwsHySX3yIle2+ndz28nVsjUs= -go.etcd.io/etcd/client/v2 v2.305.21 h1:eLiFfexc2mE+pTLz9WwnoEsX5JTTpLCYVivKkmVXIRA= -go.etcd.io/etcd/client/v2 v2.305.21/go.mod h1:OKkn4hlYNf43hpjEM3Ke3aRdUkhSl8xjKjSf8eCq2J8= -go.etcd.io/etcd/client/v3 v3.5.21 h1:T6b1Ow6fNjOLOtM0xSoKNQt1ASPCLWrF9XMHcH9pEyY= -go.etcd.io/etcd/client/v3 v3.5.21/go.mod h1:mFYy67IOqmbRf/kRUvsHixzo3iG+1OF2W2+jVIQRAnU= -go.etcd.io/etcd/pkg/v3 v3.5.21 h1:jUItxeKyrDuVuWhdh0HtjUANwyuzcb7/FAeUfABmQsk= -go.etcd.io/etcd/pkg/v3 v3.5.21/go.mod h1:wpZx8Egv1g4y+N7JAsqi2zoUiBIUWznLjqJbylDjWgU= -go.etcd.io/etcd/raft/v3 v3.5.21 h1:dOmE0mT55dIUsX77TKBLq+RgyumsQuYeiRQnW/ylugk= -go.etcd.io/etcd/raft/v3 v3.5.21/go.mod h1:fmcuY5R2SNkklU4+fKVBQi2biVp5vafMrWUEj4TJ4Cs= -go.etcd.io/etcd/server/v3 v3.5.21 h1:9w0/k12majtgarGmlMVuhwXRI2ob3/d1Ik3X5TKo0yU= -go.etcd.io/etcd/server/v3 v3.5.21/go.mod h1:G1mOzdwuzKT1VRL7SqRchli/qcFrtLBTAQ4lV20sXXo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= @@ -204,139 +76,58 @@ go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFw go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= -go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= -go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= -golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE= -google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= -gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY= -k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs= k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/apiserver v0.33.2 h1:KGTRbxn2wJagJowo29kKBp4TchpO1DRO3g+dB/KOJN4= -k8s.io/apiserver v0.33.2/go.mod h1:9qday04wEAMLPWWo9AwqCZSiIn3OYSZacDyu/AcoM/M= -k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E= -k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo= -k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0= -k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= diff --git a/pkg/apis/secret/v0alpha1/register.go b/pkg/apis/secret/v0alpha1/register.go index f31ab882212..87e99392e91 100644 --- a/pkg/apis/secret/v0alpha1/register.go +++ b/pkg/apis/secret/v0alpha1/register.go @@ -4,10 +4,8 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apiserver/pkg/registry/generic" "github.com/grafana/grafana/pkg/apimachinery/utils" ) @@ -33,7 +31,6 @@ var SecureValuesResourceInfo = utils.NewResourceInfo( {Name: "Description", Type: "string", Format: "string", Description: "Short description that explains the purpose of this SecureValue"}, {Name: "Keeper", Type: "string", Format: "string", Description: "Storage of the secure value"}, {Name: "Ref", Type: "string", Format: "string", Description: "If present, the reference to a secret"}, - {Name: "Status", Type: "string", Format: "string", Description: "The status of the secure value"}, }, // Decodes the object into a concrete type. Return order in the slice must be the same as in `Definition`. Reader: func(obj any) ([]interface{}, error) { @@ -44,7 +41,6 @@ var SecureValuesResourceInfo = utils.NewResourceInfo( r.Spec.Description, r.Spec.Keeper, r.Spec.Ref, - r.Status.Phase, }, nil } @@ -92,13 +88,6 @@ var ( AddToScheme = localSchemeBuilder.AddToScheme ) -// Adds the status phase to the selectable fields, besides the generic metadata name and namespace. -func SelectableSecureValueFields(obj *SecureValue) fields.Set { - return generic.MergeFieldsSets(generic.ObjectMetaFieldsSet(&obj.ObjectMeta, false), fields.Set{ - "status.phase": string(obj.Status.Phase), - }) -} - // Adds the list of known types to the given scheme. func AddKnownTypes(scheme *runtime.Scheme, version string) error { // TODO: do we need a type for the secure value decrypt? @@ -112,20 +101,5 @@ func AddKnownTypes(scheme *runtime.Scheme, version string) error { // &secretV0.SecureValueActivityList{}, ) - err := scheme.AddFieldLabelConversionFunc( - SecureValuesResourceInfo.GroupVersionKind(), - func(label, value string) (string, string, error) { - fieldSet := SelectableSecureValueFields(&SecureValue{}) - for key := range fieldSet { - if label == key { - return label, value, nil - } - } - return "", "", fmt.Errorf("field label not supported for %s: %s", SecureValuesResourceInfo.GroupVersionKind(), label) - }, - ) - if err != nil { - return err - } return nil } diff --git a/pkg/apis/secret/v0alpha1/secure_value.go b/pkg/apis/secret/v0alpha1/secure_value.go index 26a68263568..7208683cd0a 100644 --- a/pkg/apis/secret/v0alpha1/secure_value.go +++ b/pkg/apis/secret/v0alpha1/secure_value.go @@ -11,41 +11,18 @@ type SecureValue struct { // Standard object's metadata. It can only be one of `metav1.ObjectMeta` or `metav1.ListMeta`. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - metav1.ObjectMeta `json:"metadata,omitempty"` + metav1.ObjectMeta `json:"metadata"` // This is the actual secure value schema. Spec SecureValueSpec `json:"spec"` // Read-only observed status of the `SecureValue`. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - Status SecureValueStatus `json:"status,omitempty"` + Status SecureValueStatus `json:"status"` } -// +enum -type SecureValuePhase string - -const ( - // When the `SecureValue` is created, it will start in `Pending` phase to create the underlying secret asynchronously. - SecureValuePhasePending SecureValuePhase = "Pending" - - // If the creation of the secret is successful, it will move to the `Succeeded` phase. - SecureValuePhaseSucceeded SecureValuePhase = "Succeeded" - - // If the creation of the secret fails, it will move to the `Failed` phase. - // Check the additional `status` fields for more information on what caused the failure. - // This state is unrecoverable. - SecureValuePhaseFailed SecureValuePhase = "Failed" -) - type SecureValueStatus struct { - // High-level summary of where the `SecureValue` is in its lifecycle. - // One of: `Pending`, `Succeeded` or `Failed`. - Phase SecureValuePhase `json:"phase"` - - // A human readable message indicating details about why the `SecureValue` is in this phase. - // Only applicable if the `phase=Failed`. - // +optional - Message string `json:"message,omitempty"` + Version int64 `json:"version"` // +optional ExternalID string `json:"externalId,omitempty"` @@ -94,7 +71,7 @@ type SecureValueList struct { // Standard list's metadata. It can only be one of `metav1.ObjectMeta` or `metav1.ListMeta`. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - metav1.ListMeta `json:"metadata,omitempty"` + metav1.ListMeta `json:"metadata"` // Slice containing all secure values. This will NOT output decrypted values. Items []SecureValue `json:"items"` diff --git a/pkg/apis/secret/v0alpha1/zz_generated.openapi.go b/pkg/apis/secret/v0alpha1/zz_generated.openapi.go index a4c4a7ff7e6..2857e5f4996 100644 --- a/pkg/apis/secret/v0alpha1/zz_generated.openapi.go +++ b/pkg/apis/secret/v0alpha1/zz_generated.openapi.go @@ -598,7 +598,7 @@ func schema_pkg_apis_secret_v0alpha1_SecureValue(ref common.ReferenceCallback) c }, }, }, - Required: []string{"spec"}, + Required: []string{"spec", "status"}, }, }, Dependencies: []string{ @@ -734,20 +734,11 @@ func schema_pkg_apis_secret_v0alpha1_SecureValueStatus(ref common.ReferenceCallb SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "phase": { + "version": { SchemaProps: spec.SchemaProps{ - Description: "High-level summary of where the `SecureValue` is in its lifecycle. One of: `Pending`, `Succeeded` or `Failed`.\n\nPossible enum values:\n - `\"Failed\"` If the creation of the secret fails, it will move to the `Failed` phase. Check the additional `status` fields for more information on what caused the failure. This state is unrecoverable.\n - `\"Pending\"` When the `SecureValue` is created, it will start in `Pending` phase to create the underlying secret asynchronously.\n - `\"Succeeded\"` If the creation of the secret is successful, it will move to the `Succeeded` phase.", - Default: "", - Type: []string{"string"}, - Format: "", - Enum: []interface{}{"Failed", "Pending", "Succeeded"}, - }, - }, - "message": { - SchemaProps: spec.SchemaProps{ - Description: "A human readable message indicating details about why the `SecureValue` is in this phase. Only applicable if the `phase=Failed`.", - Type: []string{"string"}, - Format: "", + Default: 0, + Type: []string{"integer"}, + Format: "int64", }, }, "externalId": { @@ -757,7 +748,7 @@ func schema_pkg_apis_secret_v0alpha1_SecureValueStatus(ref common.ReferenceCallb }, }, }, - Required: []string{"phase"}, + Required: []string{"version"}, }, }, } diff --git a/pkg/apis/secret/v0alpha1/zz_generated.openapi_violation_exceptions.list b/pkg/apis/secret/v0alpha1/zz_generated.openapi_violation_exceptions.list index 679e6938ae0..0487679a6a6 100644 --- a/pkg/apis/secret/v0alpha1/zz_generated.openapi_violation_exceptions.list +++ b/pkg/apis/secret/v0alpha1/zz_generated.openapi_violation_exceptions.list @@ -6,3 +6,4 @@ API rule violation: names_match,github.com/grafana/grafana/pkg/apis/secret/v0alp API rule violation: names_match,github.com/grafana/grafana/pkg/apis/secret/v0alpha1,KeeperSpec,Azure API rule violation: names_match,github.com/grafana/grafana/pkg/apis/secret/v0alpha1,KeeperSpec,HashiCorp API rule violation: names_match,github.com/grafana/grafana/pkg/apis/secret/v0alpha1,SecureValueStatus,ExternalID +API rule violation: streaming_list_type_json_tags,github.com/grafana/grafana/pkg/apis/secret/v0alpha1,SecureValueList,ListMeta diff --git a/pkg/infra/filestorage/file_storage_mock.go b/pkg/infra/filestorage/file_storage_mock.go index daa8eeaaec2..89918dd159d 100644 --- a/pkg/infra/filestorage/file_storage_mock.go +++ b/pkg/infra/filestorage/file_storage_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.6. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package filestorage @@ -17,6 +17,10 @@ type MockFileStorage struct { func (_m *MockFileStorage) CreateFolder(ctx context.Context, path string) error { ret := _m.Called(ctx, path) + if len(ret) == 0 { + panic("no return value specified for CreateFolder") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { r0 = rf(ctx, path) @@ -31,6 +35,10 @@ func (_m *MockFileStorage) CreateFolder(ctx context.Context, path string) error func (_m *MockFileStorage) Delete(ctx context.Context, path string) error { ret := _m.Called(ctx, path) + if len(ret) == 0 { + panic("no return value specified for Delete") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { r0 = rf(ctx, path) @@ -45,6 +53,10 @@ func (_m *MockFileStorage) Delete(ctx context.Context, path string) error { func (_m *MockFileStorage) DeleteFolder(ctx context.Context, path string, options *DeleteFolderOptions) error { ret := _m.Called(ctx, path, options) + if len(ret) == 0 { + panic("no return value specified for DeleteFolder") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string, *DeleteFolderOptions) error); ok { r0 = rf(ctx, path, options) @@ -59,7 +71,16 @@ func (_m *MockFileStorage) DeleteFolder(ctx context.Context, path string, option func (_m *MockFileStorage) Get(ctx context.Context, path string, options *GetFileOptions) (*File, bool, error) { ret := _m.Called(ctx, path, options) + if len(ret) == 0 { + panic("no return value specified for Get") + } + var r0 *File + var r1 bool + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, string, *GetFileOptions) (*File, bool, error)); ok { + return rf(ctx, path, options) + } if rf, ok := ret.Get(0).(func(context.Context, string, *GetFileOptions) *File); ok { r0 = rf(ctx, path, options) } else { @@ -68,14 +89,12 @@ func (_m *MockFileStorage) Get(ctx context.Context, path string, options *GetFil } } - var r1 bool if rf, ok := ret.Get(1).(func(context.Context, string, *GetFileOptions) bool); ok { r1 = rf(ctx, path, options) } else { r1 = ret.Get(1).(bool) } - var r2 error if rf, ok := ret.Get(2).(func(context.Context, string, *GetFileOptions) error); ok { r2 = rf(ctx, path, options) } else { @@ -89,7 +108,15 @@ func (_m *MockFileStorage) Get(ctx context.Context, path string, options *GetFil func (_m *MockFileStorage) List(ctx context.Context, folderPath string, paging *Paging, options *ListOptions) (*ListResponse, error) { ret := _m.Called(ctx, folderPath, paging, options) + if len(ret) == 0 { + panic("no return value specified for List") + } + var r0 *ListResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *Paging, *ListOptions) (*ListResponse, error)); ok { + return rf(ctx, folderPath, paging, options) + } if rf, ok := ret.Get(0).(func(context.Context, string, *Paging, *ListOptions) *ListResponse); ok { r0 = rf(ctx, folderPath, paging, options) } else { @@ -98,7 +125,6 @@ func (_m *MockFileStorage) List(ctx context.Context, folderPath string, paging * } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, *Paging, *ListOptions) error); ok { r1 = rf(ctx, folderPath, paging, options) } else { @@ -112,6 +138,10 @@ func (_m *MockFileStorage) List(ctx context.Context, folderPath string, paging * func (_m *MockFileStorage) Upsert(ctx context.Context, command *UpsertFileCommand) error { ret := _m.Called(ctx, command) + if len(ret) == 0 { + panic("no return value specified for Upsert") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *UpsertFileCommand) error); ok { r0 = rf(ctx, command) @@ -122,10 +152,14 @@ func (_m *MockFileStorage) Upsert(ctx context.Context, command *UpsertFileComman return r0 } -// close provides a mock function with given fields: +// close provides a mock function with no fields func (_m *MockFileStorage) close() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for close") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -135,3 +169,17 @@ func (_m *MockFileStorage) close() error { return r0 } + +// NewMockFileStorage creates a new instance of MockFileStorage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockFileStorage(t interface { + mock.TestingT + Cleanup(func()) +}) *MockFileStorage { + mock := &MockFileStorage{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/login/social/socialimpl/service_test.go b/pkg/login/social/socialimpl/service_test.go index 870c13cf8e3..74760f0a3b5 100644 --- a/pkg/login/social/socialimpl/service_test.go +++ b/pkg/login/social/socialimpl/service_test.go @@ -36,7 +36,7 @@ func TestIntegrationSocialService_ProvideService(t *testing.T) { expectedGenericOAuthSkipOrgRoleSync bool }{ { - name: "should load all social connectors when ssoSettingsApi is enabled", + name: "should load all social connectors", expectedSocialMapLength: 7, expectedGenericOAuthSkipOrgRoleSync: false, }, diff --git a/pkg/login/social/socialtest/social_connector_mock.go b/pkg/login/social/socialtest/social_connector_mock.go index 17ed902bd01..4150fcb5301 100644 --- a/pkg/login/social/socialtest/social_connector_mock.go +++ b/pkg/login/social/socialtest/social_connector_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.27.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package socialtest @@ -31,6 +31,10 @@ func (_m *MockSocialConnector) AuthCodeURL(state string, opts ...oauth2.AuthCode _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for AuthCodeURL") + } + var r0 string if rf, ok := ret.Get(0).(func(string, ...oauth2.AuthCodeOption) string); ok { r0 = rf(state, opts...) @@ -45,6 +49,10 @@ func (_m *MockSocialConnector) AuthCodeURL(state string, opts ...oauth2.AuthCode func (_m *MockSocialConnector) Client(ctx context.Context, t *oauth2.Token) *http.Client { ret := _m.Called(ctx, t) + if len(ret) == 0 { + panic("no return value specified for Client") + } + var r0 *http.Client if rf, ok := ret.Get(0).(func(context.Context, *oauth2.Token) *http.Client); ok { r0 = rf(ctx, t) @@ -68,6 +76,10 @@ func (_m *MockSocialConnector) Exchange(ctx context.Context, code string, authOp _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Exchange") + } + var r0 *oauth2.Token var r1 error if rf, ok := ret.Get(0).(func(context.Context, string, ...oauth2.AuthCodeOption) (*oauth2.Token, error)); ok { @@ -90,10 +102,14 @@ func (_m *MockSocialConnector) Exchange(ctx context.Context, code string, authOp return r0, r1 } -// GetOAuthInfo provides a mock function with given fields: +// GetOAuthInfo provides a mock function with no fields func (_m *MockSocialConnector) GetOAuthInfo() *social.OAuthInfo { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetOAuthInfo") + } + var r0 *social.OAuthInfo if rf, ok := ret.Get(0).(func() *social.OAuthInfo); ok { r0 = rf() @@ -110,6 +126,10 @@ func (_m *MockSocialConnector) GetOAuthInfo() *social.OAuthInfo { func (_m *MockSocialConnector) IsEmailAllowed(email string) bool { ret := _m.Called(email) + if len(ret) == 0 { + panic("no return value specified for IsEmailAllowed") + } + var r0 bool if rf, ok := ret.Get(0).(func(string) bool); ok { r0 = rf(email) @@ -120,10 +140,14 @@ func (_m *MockSocialConnector) IsEmailAllowed(email string) bool { return r0 } -// IsSignupAllowed provides a mock function with given fields: +// IsSignupAllowed provides a mock function with no fields func (_m *MockSocialConnector) IsSignupAllowed() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsSignupAllowed") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -138,6 +162,10 @@ func (_m *MockSocialConnector) IsSignupAllowed() bool { func (_m *MockSocialConnector) SupportBundleContent(_a0 *bytes.Buffer) error { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for SupportBundleContent") + } + var r0 error if rf, ok := ret.Get(0).(func(*bytes.Buffer) error); ok { r0 = rf(_a0) @@ -152,6 +180,10 @@ func (_m *MockSocialConnector) SupportBundleContent(_a0 *bytes.Buffer) error { func (_m *MockSocialConnector) TokenSource(ctx context.Context, t *oauth2.Token) oauth2.TokenSource { ret := _m.Called(ctx, t) + if len(ret) == 0 { + panic("no return value specified for TokenSource") + } + var r0 oauth2.TokenSource if rf, ok := ret.Get(0).(func(context.Context, *oauth2.Token) oauth2.TokenSource); ok { r0 = rf(ctx, t) @@ -168,6 +200,10 @@ func (_m *MockSocialConnector) TokenSource(ctx context.Context, t *oauth2.Token) func (_m *MockSocialConnector) UserInfo(ctx context.Context, client *http.Client, token *oauth2.Token) (*social.BasicUserInfo, error) { ret := _m.Called(ctx, client, token) + if len(ret) == 0 { + panic("no return value specified for UserInfo") + } + var r0 *social.BasicUserInfo var r1 error if rf, ok := ret.Get(0).(func(context.Context, *http.Client, *oauth2.Token) (*social.BasicUserInfo, error)); ok { @@ -190,13 +226,12 @@ func (_m *MockSocialConnector) UserInfo(ctx context.Context, client *http.Client return r0, r1 } -type mockConstructorTestingTNewMockSocialConnector interface { +// NewMockSocialConnector creates a new instance of MockSocialConnector. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockSocialConnector(t interface { mock.TestingT Cleanup(func()) -} - -// NewMockSocialConnector creates a new instance of MockSocialConnector. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMockSocialConnector(t mockConstructorTestingTNewMockSocialConnector) *MockSocialConnector { +}) *MockSocialConnector { mock := &MockSocialConnector{} mock.Mock.Test(t) diff --git a/pkg/plugins/manager/loader/assetpath/assetpath.go b/pkg/plugins/manager/loader/assetpath/assetpath.go index b15f0dd867b..7802040999c 100644 --- a/pkg/plugins/manager/loader/assetpath/assetpath.go +++ b/pkg/plugins/manager/loader/assetpath/assetpath.go @@ -46,10 +46,6 @@ func DefaultService(cfg *config.PluginManagementCfg) *Service { // Base returns the base path for the specified plugin. func (s *Service) Base(n PluginInfo) (string, error) { - if n.class == plugins.ClassCore { - baseDir := getBaseDir(n.fs.Base()) - return path.Join("public/app/plugins", string(n.pluginJSON.Type), baseDir), nil - } if n.class == plugins.ClassCDN { return n.fs.Base(), nil } @@ -64,7 +60,6 @@ func (s *Service) Base(n PluginInfo) (string, error) { if s.cdn.PluginSupported(n.parent.pluginJSON.ID) { return s.cdn.AssetURL(n.parent.pluginJSON.ID, n.parent.pluginJSON.Info.Version, relPath) } - return path.Join("public/plugins", n.parent.pluginJSON.ID, relPath), nil } return path.Join("public/plugins", n.pluginJSON.ID), nil @@ -73,32 +68,12 @@ func (s *Service) Base(n PluginInfo) (string, error) { // Module returns the module.js path for the specified plugin. func (s *Service) Module(n PluginInfo) (string, error) { if n.class == plugins.ClassCore { - if filepath.Base(n.fs.Base()) == "dist" { - // The core plugin has been built externally, use the module from the dist folder - } else { - baseDir := getBaseDir(n.fs.Base()) - return path.Join("core:plugin", baseDir), nil + if filepath.Base(n.fs.Base()) != "dist" { + return path.Join("core:plugin", filepath.Base(n.fs.Base())), nil } } - if n.class == plugins.ClassCDN { - return pluginscdn.JoinPath(n.fs.Base(), "module.js") - } - if s.cdn.PluginSupported(n.pluginJSON.ID) { - return s.cdn.AssetURL(n.pluginJSON.ID, n.pluginJSON.Info.Version, "module.js") - } - if n.parent != nil { - relPath, err := n.parent.fs.Rel(n.fs.Base()) - if err != nil { - return "", err - } - if s.cdn.PluginSupported(n.parent.pluginJSON.ID) { - return s.cdn.AssetURL(n.parent.pluginJSON.ID, n.parent.pluginJSON.Info.Version, path.Join(relPath, "module.js")) - } - return path.Join("public/plugins", n.parent.pluginJSON.ID, relPath, "module.js"), nil - } - - return path.Join("public/plugins", n.pluginJSON.ID, "module.js"), nil + return s.RelativeURL(n, "module.js") } // RelativeURL returns the relative URL for an arbitrary plugin asset. @@ -145,15 +120,6 @@ func (s *Service) DefaultLogoPath(pluginType plugins.Type) string { return path.Join("public/img", fmt.Sprintf("icn-%s.svg", string(pluginType))) } -func getBaseDir(pluginDir string) string { - baseDir := filepath.Base(pluginDir) - // Decoupled core plugins will be suffixed with "dist" if they have been built - if baseDir == "dist" { - return filepath.Base(strings.TrimSuffix(pluginDir, baseDir)) - } - return baseDir -} - func (s *Service) GetTranslations(n PluginInfo) (map[string]string, error) { pathToTranslations, err := s.RelativeURL(n, "locales") if err != nil { diff --git a/pkg/plugins/manager/loader/assetpath/assetpath_test.go b/pkg/plugins/manager/loader/assetpath/assetpath_test.go index e9cf4638298..424060471a5 100644 --- a/pkg/plugins/manager/loader/assetpath/assetpath_test.go +++ b/pkg/plugins/manager/loader/assetpath/assetpath_test.go @@ -78,7 +78,7 @@ func TestService(t *testing.T) { base, err = svc.Base(NewPluginInfo(jsonData["table-old"], plugins.ClassCore, tableOldFS, nil)) require.NoError(t, err) - require.Equal(t, "public/app/plugins/table-old", base) + require.Equal(t, "public/plugins/table-old", base) parentFS := pluginFS(oneCDNURL) parentFS.RelFunc = func(_ string) (string, error) { @@ -243,9 +243,9 @@ func TestService_ChildPlugins(t *testing.T) { return childInfo }, expected: expected{ - module: "public/plugins/parent/child/module.js", - baseURL: "public/plugins/parent/child", - relURL: "public/plugins/parent/child/path/to/file.txt", + module: "public/plugins/child/module.js", + baseURL: "public/plugins/child", + relURL: "public/plugins/child/path/to/file.txt", }, }, { @@ -256,8 +256,8 @@ func TestService_ChildPlugins(t *testing.T) { }, expected: expected{ module: "core:plugin/parent", - baseURL: "public/app/plugins/parent", - relURL: "public/app/plugins/parent/path/to/file.txt", + baseURL: "public/plugins/parent", + relURL: "public/plugins/parent/path/to/file.txt", }, }, { @@ -268,8 +268,8 @@ func TestService_ChildPlugins(t *testing.T) { }, expected: expected{ module: "public/plugins/parent/module.js", - baseURL: "public/app/plugins/parent", - relURL: "public/app/plugins/parent/path/to/file.txt", + baseURL: "public/plugins/parent", + relURL: "public/plugins/parent/path/to/file.txt", }, }, { diff --git a/pkg/plugins/manager/loader/loader_test.go b/pkg/plugins/manager/loader/loader_test.go index c51b200074c..dcd9a536baa 100644 --- a/pkg/plugins/manager/loader/loader_test.go +++ b/pkg/plugins/manager/loader/loader_test.go @@ -85,8 +85,8 @@ func TestLoader_Load(t *testing.T) { Description: "Data source for Amazon AWS monitoring service", Keywords: []string{"aws", "amazon"}, Logos: plugins.Logos{ - Small: "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", - Large: "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", + Small: "public/plugins/cloudwatch/img/amazon-web-services.png", + Large: "public/plugins/cloudwatch/img/amazon-web-services.png", }, Links: []plugins.InfoLink{ {Name: "Raise issue", URL: "https://github.com/grafana/grafana/issues/new"}, @@ -123,7 +123,7 @@ func TestLoader_Load(t *testing.T) { QueryOptions: map[string]bool{"minInterval": true}, }, Module: "core:plugin/cloudwatch", - BaseURL: "public/app/plugins/datasource/cloudwatch", + BaseURL: "public/plugins/cloudwatch", FS: mustNewStaticFSForTests(t, filepath.Join(corePluginDir, "app/plugins/datasource/cloudwatch")), Signature: plugins.SignatureStatusInternal, Class: plugins.ClassCore, diff --git a/pkg/registry/apis/dashboard/legacy/legacy_migrator_mock.go b/pkg/registry/apis/dashboard/legacy/legacy_migrator_mock.go index 18796640c96..bb7231e86f6 100644 --- a/pkg/registry/apis/dashboard/legacy/legacy_migrator_mock.go +++ b/pkg/registry/apis/dashboard/legacy/legacy_migrator_mock.go @@ -1,12 +1,11 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package legacy import ( context "context" - "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - + resourcepb "github.com/grafana/grafana/pkg/storage/unified/resourcepb" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/folders/register.go b/pkg/registry/apis/folders/register.go index d3b21177afc..8407cf348cb 100644 --- a/pkg/registry/apis/folders/register.go +++ b/pkg/registry/apis/folders/register.go @@ -236,7 +236,7 @@ func (b *FolderAPIBuilder) Mutate(ctx context.Context, a admission.Attributes, _ if !ok { return fmt.Errorf("obj is not folders.Folder") } - f.Spec.Title = strings.Trim(f.Spec.Title, "") + f.Spec.Title = strings.Trim(f.Spec.Title, " ") return nil } return nil diff --git a/pkg/registry/apis/folders/register_test.go b/pkg/registry/apis/folders/register_test.go index d693bd53106..f4ab009ec10 100644 --- a/pkg/registry/apis/folders/register_test.go +++ b/pkg/registry/apis/folders/register_test.go @@ -479,7 +479,7 @@ func TestFolderAPIBuilder_Mutate_Create(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := b.Validate(context.Background(), admission.NewAttributesRecord( + admAttr := admission.NewAttributesRecord( tt.input, nil, folders.SchemeGroupVersion.WithKind("folder"), @@ -491,13 +491,18 @@ func TestFolderAPIBuilder_Mutate_Create(t *testing.T) { nil, true, &user.SignedInUser{}, - ), nil) + ) + err := b.Validate(context.Background(), admAttr, nil) if tt.wantErr { require.Error(t, err) return } require.NoError(t, err) + + err = b.Mutate(context.Background(), admAttr, nil) + require.NoError(t, err) + require.Equal(t, tt.input, tt.expected) }) } } @@ -585,7 +590,7 @@ func TestFolderAPIBuilder_Mutate_Update(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := b.Validate(context.Background(), admission.NewAttributesRecord( + admAttr := admission.NewAttributesRecord( tt.input, existingObj, folders.SchemeGroupVersion.WithKind("folder"), @@ -597,13 +602,18 @@ func TestFolderAPIBuilder_Mutate_Update(t *testing.T) { nil, true, &user.SignedInUser{}, - ), nil) + ) + err := b.Validate(context.Background(), admAttr, nil) if tt.wantErr { require.Error(t, err) return } require.NoError(t, err) + + err = b.Mutate(context.Background(), admAttr, nil) + require.NoError(t, err) + require.Equal(t, tt.input, tt.expected) }) } } diff --git a/pkg/registry/apis/provisioning/jobs/export/mock_export_fn.go b/pkg/registry/apis/provisioning/jobs/export/mock_export_fn.go index e861e7da3c3..e200e43279f 100644 --- a/pkg/registry/apis/provisioning/jobs/export/mock_export_fn.go +++ b/pkg/registry/apis/provisioning/jobs/export/mock_export_fn.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package export diff --git a/pkg/registry/apis/provisioning/jobs/export/mock_wrap_with_clone_fn.go b/pkg/registry/apis/provisioning/jobs/export/mock_wrap_with_clone_fn.go index bc690475577..51c1083ffe1 100644 --- a/pkg/registry/apis/provisioning/jobs/export/mock_wrap_with_clone_fn.go +++ b/pkg/registry/apis/provisioning/jobs/export/mock_wrap_with_clone_fn.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package export diff --git a/pkg/registry/apis/provisioning/jobs/history_mock.go b/pkg/registry/apis/provisioning/jobs/history_mock.go index fd762e9f485..dbb61568566 100644 --- a/pkg/registry/apis/provisioning/jobs/history_mock.go +++ b/pkg/registry/apis/provisioning/jobs/history_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package jobs diff --git a/pkg/registry/apis/provisioning/jobs/job_progress_recorder_mock.go b/pkg/registry/apis/provisioning/jobs/job_progress_recorder_mock.go index f7f4c53681f..7ead8a206e7 100644 --- a/pkg/registry/apis/provisioning/jobs/job_progress_recorder_mock.go +++ b/pkg/registry/apis/provisioning/jobs/job_progress_recorder_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package jobs diff --git a/pkg/registry/apis/provisioning/jobs/migrate/mock_bulk_store_client.go b/pkg/registry/apis/provisioning/jobs/migrate/mock_bulk_store_client.go index ff6a0cd0cf7..d6ab3f82fd2 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/mock_bulk_store_client.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/mock_bulk_store_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package migrate @@ -9,7 +9,7 @@ import ( mock "github.com/stretchr/testify/mock" - "github.com/grafana/grafana/pkg/storage/unified/resourcepb" + resourcepb "github.com/grafana/grafana/pkg/storage/unified/resourcepb" ) // MockBulkStoreClient is an autogenerated mock type for the BulkStoreClient type diff --git a/pkg/registry/apis/provisioning/jobs/migrate/mock_legacy_resources_migrator.go b/pkg/registry/apis/provisioning/jobs/migrate/mock_legacy_resources_migrator.go index 4a0d27fafb5..4aef34066fc 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/mock_legacy_resources_migrator.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/mock_legacy_resources_migrator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package migrate diff --git a/pkg/registry/apis/provisioning/jobs/migrate/mock_namespace_cleaner.go b/pkg/registry/apis/provisioning/jobs/migrate/mock_namespace_cleaner.go index 2b168bfa202..1ae1afa8ccf 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/mock_namespace_cleaner.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/mock_namespace_cleaner.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package migrate diff --git a/pkg/registry/apis/provisioning/jobs/progress_fn_mock.go b/pkg/registry/apis/provisioning/jobs/progress_fn_mock.go index fd634d60844..cfe7e46f88b 100644 --- a/pkg/registry/apis/provisioning/jobs/progress_fn_mock.go +++ b/pkg/registry/apis/provisioning/jobs/progress_fn_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package jobs diff --git a/pkg/registry/apis/provisioning/jobs/queue_mock.go b/pkg/registry/apis/provisioning/jobs/queue_mock.go index f20a8be6221..41552749cad 100644 --- a/pkg/registry/apis/provisioning/jobs/queue_mock.go +++ b/pkg/registry/apis/provisioning/jobs/queue_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package jobs diff --git a/pkg/registry/apis/provisioning/jobs/repo_getter_mock.go b/pkg/registry/apis/provisioning/jobs/repo_getter_mock.go index d0152e725bc..b7dc38de650 100644 --- a/pkg/registry/apis/provisioning/jobs/repo_getter_mock.go +++ b/pkg/registry/apis/provisioning/jobs/repo_getter_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package jobs diff --git a/pkg/registry/apis/provisioning/jobs/store_mock.go b/pkg/registry/apis/provisioning/jobs/store_mock.go index 300bf5fb271..8a6bb364f80 100644 --- a/pkg/registry/apis/provisioning/jobs/store_mock.go +++ b/pkg/registry/apis/provisioning/jobs/store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package jobs diff --git a/pkg/registry/apis/provisioning/jobs/sync/compare_fn_mock.go b/pkg/registry/apis/provisioning/jobs/sync/compare_fn_mock.go index 7cb74e9497a..9a27ddb394c 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/compare_fn_mock.go +++ b/pkg/registry/apis/provisioning/jobs/sync/compare_fn_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package sync diff --git a/pkg/registry/apis/provisioning/jobs/sync/full_sync_fn_mock.go b/pkg/registry/apis/provisioning/jobs/sync/full_sync_fn_mock.go index 29e44c5c02c..d2da032c6c0 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/full_sync_fn_mock.go +++ b/pkg/registry/apis/provisioning/jobs/sync/full_sync_fn_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package sync diff --git a/pkg/registry/apis/provisioning/jobs/sync/incremental_sync_fn_mock.go b/pkg/registry/apis/provisioning/jobs/sync/incremental_sync_fn_mock.go index cef2b0deb07..b38f813e68d 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/incremental_sync_fn_mock.go +++ b/pkg/registry/apis/provisioning/jobs/sync/incremental_sync_fn_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package sync diff --git a/pkg/registry/apis/provisioning/jobs/sync/repository_patch_fn_mock.go b/pkg/registry/apis/provisioning/jobs/sync/repository_patch_fn_mock.go index 6998d67f019..fb44f7eda29 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/repository_patch_fn_mock.go +++ b/pkg/registry/apis/provisioning/jobs/sync/repository_patch_fn_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package sync diff --git a/pkg/registry/apis/provisioning/jobs/sync/syncer_mock.go b/pkg/registry/apis/provisioning/jobs/sync/syncer_mock.go index 79ac697436d..3eb3e4de7bb 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/syncer_mock.go +++ b/pkg/registry/apis/provisioning/jobs/sync/syncer_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package sync diff --git a/pkg/registry/apis/provisioning/jobs/worker_mock.go b/pkg/registry/apis/provisioning/jobs/worker_mock.go index b264b258d1c..59e3c0df1b4 100644 --- a/pkg/registry/apis/provisioning/jobs/worker_mock.go +++ b/pkg/registry/apis/provisioning/jobs/worker_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package jobs diff --git a/pkg/registry/apis/provisioning/repository/clonable_repository_mock.go b/pkg/registry/apis/provisioning/repository/clonable_repository_mock.go index 9e1d671fe36..41e08fd0fb9 100644 --- a/pkg/registry/apis/provisioning/repository/clonable_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/clonable_repository_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package repository diff --git a/pkg/registry/apis/provisioning/repository/clone_fn_mock.go b/pkg/registry/apis/provisioning/repository/clone_fn_mock.go index f248ee243a6..65ab4db119e 100644 --- a/pkg/registry/apis/provisioning/repository/clone_fn_mock.go +++ b/pkg/registry/apis/provisioning/repository/clone_fn_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package repository diff --git a/pkg/registry/apis/provisioning/repository/cloned_repository_mock.go b/pkg/registry/apis/provisioning/repository/cloned_repository_mock.go index 7dc46ddeb77..bcb633f9fb7 100644 --- a/pkg/registry/apis/provisioning/repository/cloned_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/cloned_repository_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package repository diff --git a/pkg/registry/apis/provisioning/repository/config_repository_mock.go b/pkg/registry/apis/provisioning/repository/config_repository_mock.go index 40ea3dcd3de..6c3ce61dc06 100644 --- a/pkg/registry/apis/provisioning/repository/config_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/config_repository_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package repository diff --git a/pkg/registry/apis/provisioning/repository/git_repository_mock.go b/pkg/registry/apis/provisioning/repository/git_repository_mock.go index 07ef1c73cba..a6ed5cb5046 100644 --- a/pkg/registry/apis/provisioning/repository/git_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/git_repository_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package repository diff --git a/pkg/registry/apis/provisioning/repository/github/mock_client.go b/pkg/registry/apis/provisioning/repository/github/mock_client.go index 6ea39c8a67f..2eb282b43ae 100644 --- a/pkg/registry/apis/provisioning/repository/github/mock_client.go +++ b/pkg/registry/apis/provisioning/repository/github/mock_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package github diff --git a/pkg/registry/apis/provisioning/repository/github/mock_commit_file.go b/pkg/registry/apis/provisioning/repository/github/mock_commit_file.go index 68d3d2044f0..29e91059f90 100644 --- a/pkg/registry/apis/provisioning/repository/github/mock_commit_file.go +++ b/pkg/registry/apis/provisioning/repository/github/mock_commit_file.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package github diff --git a/pkg/registry/apis/provisioning/repository/github/mock_repository_content.go b/pkg/registry/apis/provisioning/repository/github/mock_repository_content.go index bddbaaf2558..4121dc99359 100644 --- a/pkg/registry/apis/provisioning/repository/github/mock_repository_content.go +++ b/pkg/registry/apis/provisioning/repository/github/mock_repository_content.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package github diff --git a/pkg/registry/apis/provisioning/repository/github_repository_mock.go b/pkg/registry/apis/provisioning/repository/github_repository_mock.go index 8d4dd2d58ff..0ae6a3f98f5 100644 --- a/pkg/registry/apis/provisioning/repository/github_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/github_repository_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package repository diff --git a/pkg/registry/apis/provisioning/repository/go-git/repository_mock.go b/pkg/registry/apis/provisioning/repository/go-git/repository_mock.go index da1f2a005cf..b00f395beac 100644 --- a/pkg/registry/apis/provisioning/repository/go-git/repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/go-git/repository_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package gogit diff --git a/pkg/registry/apis/provisioning/repository/go-git/worktree_mock.go b/pkg/registry/apis/provisioning/repository/go-git/worktree_mock.go index 0a85a14e12b..e59506eb1ac 100644 --- a/pkg/registry/apis/provisioning/repository/go-git/worktree_mock.go +++ b/pkg/registry/apis/provisioning/repository/go-git/worktree_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package gogit diff --git a/pkg/registry/apis/provisioning/repository/nanogit/git.go b/pkg/registry/apis/provisioning/repository/nanogit/git.go index ce1773e787a..c533d1fb85a 100644 --- a/pkg/registry/apis/provisioning/repository/nanogit/git.go +++ b/pkg/registry/apis/provisioning/repository/nanogit/git.go @@ -595,7 +595,7 @@ func (r *gitRepository) resolveRefToHash(ctx context.Context, ref string) (hash. // Try to parse ref as a hash first refHash, err := hash.FromHex(ref) - if err == nil && refHash != nil { + if err == nil && refHash != hash.Zero { // Valid hash, return it return refHash, nil } @@ -604,9 +604,9 @@ func (r *gitRepository) resolveRefToHash(ctx context.Context, ref string) (hash. branchRef, err := r.client.GetRef(ctx, ref) if err != nil { if errors.Is(err, nanogit.ErrObjectNotFound) { - return nil, fmt.Errorf("ref not found: %s: %w", ref, repository.ErrRefNotFound) + return hash.Zero, fmt.Errorf("ref not found: %s: %w", ref, repository.ErrRefNotFound) } - return nil, fmt.Errorf("get ref %s: %w", ref, err) + return hash.Zero, fmt.Errorf("get ref %s: %w", ref, err) } return branchRef.Hash, nil diff --git a/pkg/registry/apis/provisioning/repository/nanogit/git_test.go b/pkg/registry/apis/provisioning/repository/nanogit/git_test.go index 20df321fc74..d9413c429f0 100644 --- a/pkg/registry/apis/provisioning/repository/nanogit/git_test.go +++ b/pkg/registry/apis/provisioning/repository/nanogit/git_test.go @@ -695,7 +695,7 @@ func TestGitRepository_Read(t *testing.T) { Hash: hash.Hash{}, }, nil) mockClient.GetCommitReturns(&nanogit.Commit{ - Tree: hash.Hash([]byte("tree-hash")), + Tree: hash.MustFromHex("abcdef1234567890abcdef1234567890abcdef12"), }, nil) mockClient.GetTreeByPathReturns(&nanogit.Tree{ Hash: hash.Hash{}, @@ -1191,7 +1191,7 @@ func TestGitRepository_LatestRef(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, // Non-empty hash + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, // Non-empty hash }, nil) }, gitConfig: RepositoryConfig{ @@ -1412,11 +1412,11 @@ func TestGitRepository_CompareFiles(t *testing.T) { // Return refs for base and ref mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }, nil) // Return comparison results @@ -1449,11 +1449,11 @@ func TestGitRepository_CompareFiles(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.CompareCommitsReturns([]nanogit.CommitFile{}, nil) @@ -1547,7 +1547,7 @@ func TestGitRepository_ensureBranchExists(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) }, gitConfig: RepositoryConfig{ @@ -1565,7 +1565,7 @@ func TestGitRepository_ensureBranchExists(t *testing.T) { // Second call - get source branch mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) // CreateRef succeeds mockClient.CreateRefReturns(nil) @@ -1862,7 +1862,7 @@ func TestGitRepository_resolveRefToHash(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) }, gitConfig: RepositoryConfig{ @@ -1887,7 +1887,7 @@ func TestGitRepository_resolveRefToHash(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }, nil) }, gitConfig: RepositoryConfig{ @@ -1939,7 +1939,7 @@ func TestGitRepository_resolveRefToHash(t *testing.T) { if tt.wantError { require.Error(t, err) - require.Nil(t, refHash) + require.Equal(t, hash.Zero, refHash) } else { require.NoError(t, err) require.NotNil(t, refHash) @@ -2212,7 +2212,7 @@ func TestGitRepository_EdgeCases(t *testing.T) { mockClient := &mocks.FakeClient{} mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockWriter := &mocks.FakeStagedWriter{} @@ -2251,7 +2251,7 @@ func TestGitRepository_EdgeCases(t *testing.T) { mockClient := &mocks.FakeClient{} mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetCommitReturns(&nanogit.Commit{Tree: hash.Hash{}}, nil) mockClient.GetBlobByPathReturns(&nanogit.Blob{}, errors.New("some read error")) @@ -2401,7 +2401,7 @@ func TestGitRepository_ResolveRefToHash_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/invalid-hex", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) }, ref: "invalid-hex-zzz", @@ -2412,7 +2412,7 @@ func TestGitRepository_ResolveRefToHash_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }, nil) }, ref: "refs/heads/feature", @@ -2423,7 +2423,7 @@ func TestGitRepository_ResolveRefToHash_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/tags/v1.0.0", - Hash: hash.Hash{7, 8, 9}, + Hash: hash.Hash{7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}, }, nil) }, ref: "refs/tags/v1.0.0", @@ -2540,11 +2540,11 @@ func TestGitRepository_CompareFiles_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }, nil) mockClient.CompareCommitsReturns(nil, errors.New("compare error")) }, @@ -2558,11 +2558,11 @@ func TestGitRepository_CompareFiles_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }, nil) mockClient.CompareCommitsReturns([]nanogit.CommitFile{ { @@ -2580,11 +2580,11 @@ func TestGitRepository_CompareFiles_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }, nil) mockClient.CompareCommitsReturns([]nanogit.CommitFile{ { @@ -2606,11 +2606,11 @@ func TestGitRepository_CompareFiles_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }, nil) mockClient.CompareCommitsReturns([]nanogit.CommitFile{ { @@ -2683,7 +2683,7 @@ func TestGitRepository_ReadTree_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetFlatTreeReturns(nil, errors.New("flat tree error")) }, @@ -2694,23 +2694,23 @@ func TestGitRepository_ReadTree_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.GetFlatTreeReturns(&nanogit.FlatTree{ Entries: []nanogit.FlatTreeEntry{ { Path: "other/file.yaml", // Outside configs/ - Hash: hash.Hash{4, 5, 6}, + Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, Type: protocol.ObjectTypeBlob, }, { Path: "configs/included.yaml", // Inside configs/ - Hash: hash.Hash{7, 8, 9}, + Hash: hash.Hash{7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}, Type: protocol.ObjectTypeBlob, }, { Path: "configs/dir", // Directory without trailing slash - Hash: hash.Hash{10, 11, 12}, + Hash: hash.Hash{10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}, Type: protocol.ObjectTypeTree, }, }, @@ -2828,7 +2828,7 @@ func TestGitRepository_ensureBranchExists_ErrorConditions(t *testing.T) { // Second call - get source branch mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) // CreateRef fails mockClient.CreateRefReturns(errors.New("create ref failed")) @@ -2880,10 +2880,10 @@ func TestGitRepository_Read_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121315"), }, nil) mockClient.GetCommitReturns(&nanogit.Commit{ - Tree: hash.Hash([]byte("tree-hash")), + Tree: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetTreeByPathReturns(nil, errors.New("tree error")) }, @@ -2895,7 +2895,7 @@ func TestGitRepository_Read_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetCommitReturns(nil, errors.New("commit error")) }, @@ -2907,10 +2907,10 @@ func TestGitRepository_Read_EdgeCases(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetCommitReturns(&nanogit.Commit{ - Tree: hash.Hash{4, 5, 6}, + Hash: hash.MustFromHex("0102030405060708092a0b0c0d0e0f1011121314"), }, nil) mockClient.GetBlobByPathReturns(nil, errors.New("blob error")) }, @@ -2965,7 +2965,7 @@ func TestGitRepository_Create_ErrorConditions(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.NewStagedWriterReturns(nil, errors.New("staged writer error")) }, @@ -2977,7 +2977,7 @@ func TestGitRepository_Create_ErrorConditions(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockWriter := &mocks.FakeStagedWriter{} mockWriter.CreateBlobReturns(hash.Hash{}, errors.New("create blob error")) @@ -3030,7 +3030,7 @@ func TestGitRepository_Update_ErrorConditions(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, }, nil) mockClient.NewStagedWriterReturns(nil, errors.New("staged writer error")) }, @@ -3042,7 +3042,7 @@ func TestGitRepository_Update_ErrorConditions(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockWriter := &mocks.FakeStagedWriter{} mockWriter.UpdateBlobReturns(hash.Hash{}, errors.New("update blob error")) @@ -3096,7 +3096,7 @@ func TestGitRepository_Delete_ErrorConditions(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.NewStagedWriterReturns(nil, errors.New("staged writer error")) }, @@ -3109,7 +3109,7 @@ func TestGitRepository_Delete_ErrorConditions(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockWriter := &mocks.FakeStagedWriter{} mockWriter.DeleteBlobReturns(hash.Hash{}, errors.New("delete blob error")) @@ -3124,7 +3124,7 @@ func TestGitRepository_Delete_ErrorConditions(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockWriter := &mocks.FakeStagedWriter{} mockWriter.DeleteTreeReturns(hash.Hash{}, errors.New("delete tree error")) @@ -3139,7 +3139,7 @@ func TestGitRepository_Delete_ErrorConditions(t *testing.T) { setupMock: func(mockClient *mocks.FakeClient) { mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockWriter := &mocks.FakeStagedWriter{} mockWriter.DeleteTreeReturns(hash.Hash{}, nanogit.ErrObjectNotFound) @@ -3186,7 +3186,7 @@ func TestGitRepository_CompareFiles_EmptyBase(t *testing.T) { // Only setup for ref resolution mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.CompareCommitsReturns([]nanogit.CommitFile{ { @@ -3218,8 +3218,8 @@ func TestGitRepository_CompareFiles_EmptyBase(t *testing.T) { // Verify CompareCommits was called with empty base hash and feature hash require.Equal(t, 1, mockClient.CompareCommitsCallCount()) _, baseHash, refHash := mockClient.CompareCommitsArgsForCall(0) - require.Nil(t, baseHash) // Empty hash for empty base - require.Equal(t, hash.Hash{4, 5, 6}, refHash) + require.Equal(t, hash.Zero, baseHash) // Empty hash for empty base + require.Equal(t, hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), refHash) } func TestGitRepository_EmptyRefHandling(t *testing.T) { @@ -3237,7 +3237,7 @@ func TestGitRepository_EmptyRefHandling(t *testing.T) { mockClient := &mocks.FakeClient{} mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockWriter := &mocks.FakeStagedWriter{} @@ -3299,7 +3299,7 @@ func TestGitRepository_CompareFiles_ResolveErrors(t *testing.T) { // First call succeeds for base mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) // Second call fails for ref mockClient.GetRefReturnsOnCall(1, nanogit.Ref{}, errors.New("ref error")) @@ -3341,14 +3341,14 @@ func TestGitRepository_Read_EmptyRef(t *testing.T) { mockClient := &mocks.FakeClient{} mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetCommitReturns(&nanogit.Commit{ - Tree: hash.Hash{4, 5, 6}, + Tree: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }, nil) mockClient.GetBlobByPathReturns(&nanogit.Blob{ Content: []byte("file content"), - Hash: hash.Hash{7, 8, 9}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) gitRepo := &gitRepository{ @@ -3376,13 +3376,13 @@ func TestGitRepository_ReadTree_EmptyRef(t *testing.T) { mockClient := &mocks.FakeClient{} mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetFlatTreeReturns(&nanogit.FlatTree{ Entries: []nanogit.FlatTreeEntry{ { Path: "configs/test.yaml", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), Type: protocol.ObjectTypeBlob, }, }, @@ -3504,17 +3504,17 @@ func TestGitRepository_Write_DefaultRef(t *testing.T) { // First call for Read check - file not found mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetCommitReturns(&nanogit.Commit{ - Tree: hash.Hash{4, 5, 6}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetBlobByPathReturns(&nanogit.Blob{}, nanogit.ErrObjectNotFound) // Second call for Create mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockWriter := &mocks.FakeStagedWriter{} mockWriter.CreateBlobReturns(hash.Hash{}, nil) @@ -3545,14 +3545,14 @@ func TestGitRepository_Read_RefInFileInfo(t *testing.T) { mockClient := &mocks.FakeClient{} mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetCommitReturns(&nanogit.Commit{ - Tree: hash.Hash{4, 5, 6}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetBlobByPathReturns(&nanogit.Blob{ Content: []byte("file content"), - Hash: hash.Hash{7, 8, 9}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) gitRepo := &gitRepository{ @@ -3582,10 +3582,10 @@ func TestGitRepository_Read_GetTreeByPath_NotFound(t *testing.T) { mockClient := &mocks.FakeClient{} mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetCommitReturns(&nanogit.Commit{ - Tree: hash.Hash([]byte("tree-hash")), + Tree: hash.Hash{30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49}, }, nil) mockClient.GetTreeByPathReturns(nil, nanogit.ErrObjectNotFound) @@ -3614,7 +3614,7 @@ func TestGitRepository_ReadTree_GetFlatTree_NotFound(t *testing.T) { mockClient := &mocks.FakeClient{} mockClient.GetRefReturns(nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetFlatTreeReturns(nil, nanogit.ErrObjectNotFound) @@ -3655,11 +3655,11 @@ func TestGitRepository_CompareFiles_FilesOutsideConfiguredPath_AllStatuses(t *te mockClient := &mocks.FakeClient{} mockClient.GetRefReturnsOnCall(0, nanogit.Ref{ Name: "refs/heads/main", - Hash: hash.Hash{1, 2, 3}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), }, nil) mockClient.GetRefReturnsOnCall(1, nanogit.Ref{ Name: "refs/heads/feature", - Hash: hash.Hash{4, 5, 6}, + Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121315"), }, nil) mockClient.CompareCommitsReturns([]nanogit.CommitFile{ { diff --git a/pkg/registry/apis/provisioning/repository/reader_mock.go b/pkg/registry/apis/provisioning/repository/reader_mock.go index dd6a73ab567..f657d10914d 100644 --- a/pkg/registry/apis/provisioning/repository/reader_mock.go +++ b/pkg/registry/apis/provisioning/repository/reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package repository diff --git a/pkg/registry/apis/provisioning/repository/versioned_mock.go b/pkg/registry/apis/provisioning/repository/versioned_mock.go index cdd59b288e1..ab88470699e 100644 --- a/pkg/registry/apis/provisioning/repository/versioned_mock.go +++ b/pkg/registry/apis/provisioning/repository/versioned_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package repository diff --git a/pkg/registry/apis/provisioning/resources/client_factory_mock.go b/pkg/registry/apis/provisioning/resources/client_factory_mock.go index b8aa174e04f..d118582d35c 100644 --- a/pkg/registry/apis/provisioning/resources/client_factory_mock.go +++ b/pkg/registry/apis/provisioning/resources/client_factory_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package resources diff --git a/pkg/registry/apis/provisioning/resources/clients_mock.go b/pkg/registry/apis/provisioning/resources/clients_mock.go index d78496c2183..4af4559943a 100644 --- a/pkg/registry/apis/provisioning/resources/clients_mock.go +++ b/pkg/registry/apis/provisioning/resources/clients_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package resources diff --git a/pkg/registry/apis/provisioning/resources/parser_factory_mock.go b/pkg/registry/apis/provisioning/resources/parser_factory_mock.go index 434863be21c..b266809d58e 100644 --- a/pkg/registry/apis/provisioning/resources/parser_factory_mock.go +++ b/pkg/registry/apis/provisioning/resources/parser_factory_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package resources diff --git a/pkg/registry/apis/provisioning/resources/parser_mock.go b/pkg/registry/apis/provisioning/resources/parser_mock.go index c207d0e9095..21e6ab3e78e 100644 --- a/pkg/registry/apis/provisioning/resources/parser_mock.go +++ b/pkg/registry/apis/provisioning/resources/parser_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package resources diff --git a/pkg/registry/apis/provisioning/resources/repository_resources_factory_mock.go b/pkg/registry/apis/provisioning/resources/repository_resources_factory_mock.go index 3e55762e261..9bf9473d180 100644 --- a/pkg/registry/apis/provisioning/resources/repository_resources_factory_mock.go +++ b/pkg/registry/apis/provisioning/resources/repository_resources_factory_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package resources diff --git a/pkg/registry/apis/provisioning/resources/repository_resources_mock.go b/pkg/registry/apis/provisioning/resources/repository_resources_mock.go index 6245188528e..7e11d9b9eda 100644 --- a/pkg/registry/apis/provisioning/resources/repository_resources_mock.go +++ b/pkg/registry/apis/provisioning/resources/repository_resources_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package resources @@ -26,64 +26,6 @@ func (_m *MockRepositoryResources) EXPECT() *MockRepositoryResources_Expecter { return &MockRepositoryResources_Expecter{mock: &_m.Mock} } -// WriteResourceFileFromObject provides a mock function with given fields: ctx, obj, options -func (_m *MockRepositoryResources) WriteResourceFileFromObject(ctx context.Context, obj *unstructured.Unstructured, options WriteOptions) (string, error) { - ret := _m.Called(ctx, obj, options) - - if len(ret) == 0 { - panic("no return value specified for WriteResourceFileFromObject") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *unstructured.Unstructured, WriteOptions) (string, error)); ok { - return rf(ctx, obj, options) - } - if rf, ok := ret.Get(0).(func(context.Context, *unstructured.Unstructured, WriteOptions) string); ok { - r0 = rf(ctx, obj, options) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, *unstructured.Unstructured, WriteOptions) error); ok { - r1 = rf(ctx, obj, options) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockRepositoryResources_WriteResourceFileFromObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteResourceFileFromObject' -type MockRepositoryResources_WriteResourceFileFromObject_Call struct { - *mock.Call -} - -// WriteResourceFileFromObject is a helper method to define mock.On call -// - ctx context.Context -// - obj *unstructured.Unstructured -// - options WriteOptions -func (_e *MockRepositoryResources_Expecter) WriteResourceFileFromObject(ctx interface{}, obj interface{}, options interface{}) *MockRepositoryResources_WriteResourceFileFromObject_Call { - return &MockRepositoryResources_WriteResourceFileFromObject_Call{Call: _e.mock.On("WriteResourceFileFromObject", ctx, obj, options)} -} - -func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) Run(run func(ctx context.Context, obj *unstructured.Unstructured, options WriteOptions)) *MockRepositoryResources_WriteResourceFileFromObject_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*unstructured.Unstructured), args[2].(WriteOptions)) - }) - return _c -} - -func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) Return(_a0 string, _a1 error) *MockRepositoryResources_WriteResourceFileFromObject_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) RunAndReturn(run func(context.Context, *unstructured.Unstructured, WriteOptions) (string, error)) *MockRepositoryResources_WriteResourceFileFromObject_Call { - _c.Call.Return(run) - return _c -} - // EnsureFolderExists provides a mock function with given fields: ctx, folder, parentID func (_m *MockRepositoryResources) EnsureFolderExists(ctx context.Context, folder Folder, parentID string) error { ret := _m.Called(ctx, folder, parentID) @@ -520,6 +462,64 @@ func (_c *MockRepositoryResources_Stats_Call) RunAndReturn(run func(context.Cont return _c } +// WriteResourceFileFromObject provides a mock function with given fields: ctx, obj, options +func (_m *MockRepositoryResources) WriteResourceFileFromObject(ctx context.Context, obj *unstructured.Unstructured, options WriteOptions) (string, error) { + ret := _m.Called(ctx, obj, options) + + if len(ret) == 0 { + panic("no return value specified for WriteResourceFileFromObject") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *unstructured.Unstructured, WriteOptions) (string, error)); ok { + return rf(ctx, obj, options) + } + if rf, ok := ret.Get(0).(func(context.Context, *unstructured.Unstructured, WriteOptions) string); ok { + r0 = rf(ctx, obj, options) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(context.Context, *unstructured.Unstructured, WriteOptions) error); ok { + r1 = rf(ctx, obj, options) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockRepositoryResources_WriteResourceFileFromObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteResourceFileFromObject' +type MockRepositoryResources_WriteResourceFileFromObject_Call struct { + *mock.Call +} + +// WriteResourceFileFromObject is a helper method to define mock.On call +// - ctx context.Context +// - obj *unstructured.Unstructured +// - options WriteOptions +func (_e *MockRepositoryResources_Expecter) WriteResourceFileFromObject(ctx interface{}, obj interface{}, options interface{}) *MockRepositoryResources_WriteResourceFileFromObject_Call { + return &MockRepositoryResources_WriteResourceFileFromObject_Call{Call: _e.mock.On("WriteResourceFileFromObject", ctx, obj, options)} +} + +func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) Run(run func(ctx context.Context, obj *unstructured.Unstructured, options WriteOptions)) *MockRepositoryResources_WriteResourceFileFromObject_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*unstructured.Unstructured), args[2].(WriteOptions)) + }) + return _c +} + +func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) Return(_a0 string, _a1 error) *MockRepositoryResources_WriteResourceFileFromObject_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) RunAndReturn(run func(context.Context, *unstructured.Unstructured, WriteOptions) (string, error)) *MockRepositoryResources_WriteResourceFileFromObject_Call { + _c.Call.Return(run) + return _c +} + // WriteResourceFromFile provides a mock function with given fields: ctx, path, ref func (_m *MockRepositoryResources) WriteResourceFromFile(ctx context.Context, path string, ref string) (string, schema.GroupVersionKind, error) { ret := _m.Called(ctx, path, ref) diff --git a/pkg/registry/apis/provisioning/resources/resource_lister_mock.go b/pkg/registry/apis/provisioning/resources/resource_lister_mock.go index fae2e39b221..29fb1712f51 100644 --- a/pkg/registry/apis/provisioning/resources/resource_lister_mock.go +++ b/pkg/registry/apis/provisioning/resources/resource_lister_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package resources diff --git a/pkg/registry/apis/provisioning/resources/signature/signature_factory_mock.go b/pkg/registry/apis/provisioning/resources/signature/signature_factory_mock.go index 6f67bc8ffda..80647e0129c 100644 --- a/pkg/registry/apis/provisioning/resources/signature/signature_factory_mock.go +++ b/pkg/registry/apis/provisioning/resources/signature/signature_factory_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package signature diff --git a/pkg/registry/apis/provisioning/resources/signature/signer_mock.go b/pkg/registry/apis/provisioning/resources/signature/signer_mock.go index 93532369d5c..46cd71dab55 100644 --- a/pkg/registry/apis/provisioning/resources/signature/signer_mock.go +++ b/pkg/registry/apis/provisioning/resources/signature/signer_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package signature diff --git a/pkg/registry/apis/provisioning/resources/tree_mock.go b/pkg/registry/apis/provisioning/resources/tree_mock.go index 86b4038a42e..d07ec5459a7 100644 --- a/pkg/registry/apis/provisioning/resources/tree_mock.go +++ b/pkg/registry/apis/provisioning/resources/tree_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package resources diff --git a/pkg/registry/apis/provisioning/secrets/secret_mock.go b/pkg/registry/apis/provisioning/secrets/secret_mock.go index d182c819e3c..58505ed8ab7 100644 --- a/pkg/registry/apis/provisioning/secrets/secret_mock.go +++ b/pkg/registry/apis/provisioning/secrets/secret_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package secrets diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/blobstore_client_mock.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/blobstore_client_mock.go index cddf0ada660..c1c09944ea9 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/blobstore_client_mock.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/blobstore_client_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package pullrequest @@ -9,7 +9,7 @@ import ( mock "github.com/stretchr/testify/mock" - "github.com/grafana/grafana/pkg/storage/unified/resourcepb" + resourcepb "github.com/grafana/grafana/pkg/storage/unified/resourcepb" ) // MockBlobStoreClient is an autogenerated mock type for the BlobStoreClient type @@ -69,7 +69,7 @@ type MockBlobStoreClient_PutBlob_Call struct { // PutBlob is a helper method to define mock.On call // - ctx context.Context -// - in *resource.PutBlobRequest +// - in *resourcepb.PutBlobRequest // - opts ...grpc.CallOption func (_e *MockBlobStoreClient_Expecter) PutBlob(ctx interface{}, in interface{}, opts ...interface{}) *MockBlobStoreClient_PutBlob_Call { return &MockBlobStoreClient_PutBlob_Call{Call: _e.mock.On("PutBlob", diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_commenter.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_commenter.go index 785e552f68d..299a34b3fe5 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_commenter.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_commenter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package pullrequest diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_evaluator.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_evaluator.go index 54673cd92d8..9d328127af4 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_evaluator.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_evaluator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package pullrequest diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_pullrequest_repo.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_pullrequest_repo.go index 08a6f3dff61..f8c4b9ba5a9 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_pullrequest_repo.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_pullrequest_repo.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package pullrequest diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/render_mock.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/render_mock.go index f7aa5bb5039..e2a4ed6db94 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/render_mock.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/render_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package pullrequest diff --git a/pkg/registry/apis/secret/contracts/outbox_queue.go b/pkg/registry/apis/secret/contracts/outbox_queue.go deleted file mode 100644 index 767273b1254..00000000000 --- a/pkg/registry/apis/secret/contracts/outbox_queue.go +++ /dev/null @@ -1,64 +0,0 @@ -package contracts - -import ( - "context" -) - -type contextRequestIdKey struct{} - -type OutboxMessageType string - -func GetRequestId(ctx context.Context) string { - v := ctx.Value(contextRequestIdKey{}) - requestId, ok := v.(string) - if !ok { - return "" - } - - return requestId -} - -func ContextWithRequestID(ctx context.Context, requestId string) context.Context { - return context.WithValue(ctx, contextRequestIdKey{}, requestId) -} - -const ( - CreateSecretOutboxMessage OutboxMessageType = "create" - UpdateSecretOutboxMessage OutboxMessageType = "update" - DeleteSecretOutboxMessage OutboxMessageType = "delete" -) - -type AppendOutboxMessage struct { - RequestID string - Type OutboxMessageType - Name string - Namespace string - EncryptedSecret string - KeeperName *string - ExternalID *string -} - -type OutboxMessage struct { - RequestID string - Type OutboxMessageType - MessageID int64 - Name string - Namespace string - EncryptedSecret string - KeeperName *string - ExternalID *string - // How many times this message has been received - ReceiveCount int - Created int64 -} - -type OutboxQueue interface { - // Appends a message to the outbox queue - Append(ctx context.Context, message AppendOutboxMessage) (int64, error) - // Receives at most n messages from the outbox queue - ReceiveN(ctx context.Context, n uint) ([]OutboxMessage, error) - // Deletes a message from the outbox queue - Delete(ctx context.Context, messageID int64) error - // Increments the number of times each message has been received by 1. Must be atomic. - IncrementReceiveCount(ctx context.Context, messageIDs []int64) error -} diff --git a/pkg/registry/apis/secret/contracts/secure_value.go b/pkg/registry/apis/secret/contracts/secure_value.go index ca3f66f991d..94bde58c68e 100644 --- a/pkg/registry/apis/secret/contracts/secure_value.go +++ b/pkg/registry/apis/secret/contracts/secure_value.go @@ -32,10 +32,9 @@ type ReadOpts struct { type SecureValueMetadataStorage interface { Create(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) Read(ctx context.Context, namespace xkube.Namespace, name string, opts ReadOpts) (*secretv0alpha1.SecureValue, error) - Update(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) - Delete(ctx context.Context, namespace xkube.Namespace, name string) error List(ctx context.Context, namespace xkube.Namespace) ([]secretv0alpha1.SecureValue, error) - SetStatus(ctx context.Context, namespace xkube.Namespace, name string, status secretv0alpha1.SecureValueStatus) error - SetExternalID(ctx context.Context, namespace xkube.Namespace, name string, externalID ExternalID) error + SetVersionToActive(ctx context.Context, namespace xkube.Namespace, name string, version int64) error + SetVersionToInactive(ctx context.Context, namespace xkube.Namespace, name string, version int64) error + SetExternalID(ctx context.Context, namespace xkube.Namespace, name string, version int64, externalID ExternalID) error ReadForDecrypt(ctx context.Context, namespace xkube.Namespace, name string) (*DecryptSecureValue, error) } diff --git a/pkg/registry/apis/secret/service/secure_value.go b/pkg/registry/apis/secret/service/secure_value.go index e667ad4c4be..01b382edbf7 100644 --- a/pkg/registry/apis/secret/service/secure_value.go +++ b/pkg/registry/apis/secret/service/secure_value.go @@ -5,10 +5,10 @@ import ( "fmt" claims "github.com/grafana/authlib/types" + "github.com/grafana/grafana-app-sdk/logging" "github.com/grafana/grafana/pkg/apimachinery/utils" secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" - "github.com/grafana/grafana/pkg/registry/apis/secret/tracectx" "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -19,8 +19,8 @@ type SecureValueService struct { accessClient claims.AccessClient database contracts.Database secureValueMetadataStorage contracts.SecureValueMetadataStorage - outboxQueue contracts.OutboxQueue - encryptionManager contracts.EncryptionManager + keeperMetadataStorage contracts.KeeperMetadataStorage + keeperService contracts.KeeperService } func ProvideSecureValueService( @@ -28,16 +28,16 @@ func ProvideSecureValueService( accessClient claims.AccessClient, database contracts.Database, secureValueMetadataStorage contracts.SecureValueMetadataStorage, - outboxQueue contracts.OutboxQueue, - encryptionManager contracts.EncryptionManager, + keeperMetadataStorage contracts.KeeperMetadataStorage, + keeperService contracts.KeeperService, ) *SecureValueService { return &SecureValueService{ tracer: tracer, accessClient: accessClient, database: database, secureValueMetadataStorage: secureValueMetadataStorage, - outboxQueue: outboxQueue, - encryptionManager: encryptionManager, + keeperMetadataStorage: keeperMetadataStorage, + keeperService: keeperService, } } @@ -48,43 +48,91 @@ func (s *SecureValueService) Create(ctx context.Context, sv *secretv0alpha1.Secu attribute.String("actor", actorUID), )) defer span.End() + return s.createNewVersion(ctx, sv, actorUID) +} - sv.Status = secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhasePending, Message: "Creating secure value"} +func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, bool, error) { + ctx, span := s.tracer.Start(ctx, "SecureValueService.Update", trace.WithAttributes( + attribute.String("name", newSecureValue.GetName()), + attribute.String("namespace", newSecureValue.GetNamespace()), + attribute.String("actor", actorUID), + )) + defer span.End() - var out *secretv0alpha1.SecureValue - - encryptedSecret, err := s.encryptionManager.Encrypt(ctx, sv.Namespace, []byte(sv.Spec.Value.DangerouslyExposeAndConsumeValue())) - if err != nil { - return nil, fmt.Errorf("encrypting secure value secret: %w", err) - } - - // Specifically here so that the spans from the worker are not inside the transaction. - requestID := tracectx.HexEncodeTraceFromContext(ctx) - - if err := s.database.Transaction(ctx, func(ctx context.Context) error { - createdSecureValue, err := s.secureValueMetadataStorage.Create(ctx, sv, actorUID) + if newSecureValue.Spec.Value == "" { + decrypted, err := s.secureValueMetadataStorage.ReadForDecrypt(ctx, xkube.Namespace(newSecureValue.Namespace), newSecureValue.Name) if err != nil { - return fmt.Errorf("failed to create securevalue: %w", err) - } - out = createdSecureValue - - if _, err := s.outboxQueue.Append(ctx, contracts.AppendOutboxMessage{ - RequestID: requestID, - Type: contracts.CreateSecretOutboxMessage, - Name: sv.Name, - Namespace: sv.Namespace, - EncryptedSecret: string(encryptedSecret), - KeeperName: sv.Spec.Keeper, - }); err != nil { - return fmt.Errorf("failed to append message to create secure value to outbox queue: %w", err) + return nil, false, fmt.Errorf("reading secure value secret: %+w", err) } - return nil - }); err != nil { - return out, err + // TODO: does this need to be for update? + keeperCfg, err := s.keeperMetadataStorage.GetKeeperConfig(ctx, newSecureValue.Namespace, newSecureValue.Spec.Keeper, contracts.ReadOpts{ForUpdate: true}) + if err != nil { + return nil, false, fmt.Errorf("fetching keeper config: namespace=%+v keeperName=%+v %w", newSecureValue.Namespace, newSecureValue.Spec.Keeper, err) + } + + keeper, err := s.keeperService.KeeperForConfig(keeperCfg) + if err != nil { + return nil, false, fmt.Errorf("getting keeper for config: namespace=%+v keeperName=%+v %w", newSecureValue.Namespace, newSecureValue.Spec.Keeper, err) + } + logging.FromContext(ctx).Debug("retrieved keeper", "namespace", newSecureValue.Namespace, "keeperName", newSecureValue.Spec.Keeper, "type", keeperCfg.Type()) + + secret, err := keeper.Expose(ctx, keeperCfg, newSecureValue.Namespace, contracts.ExternalID(decrypted.ExternalID)) + if err != nil { + return nil, false, fmt.Errorf("reading secret value from keeper: %w", err) + } + + newSecureValue.Spec.Value = secret } - return out, nil + const updateIsSync = true + createdSv, err := s.createNewVersion(ctx, newSecureValue, actorUID) + return createdSv, updateIsSync, err +} + +func (s *SecureValueService) createNewVersion(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) { + createdSv, err := s.secureValueMetadataStorage.Create(ctx, sv, actorUID) + if err != nil { + return nil, fmt.Errorf("creating secure value: %w", err) + } + createdSv.Status = secretv0alpha1.SecureValueStatus{ + Version: createdSv.Status.Version, + } + + // TODO: does this need to be for update? + keeperCfg, err := s.keeperMetadataStorage.GetKeeperConfig(ctx, sv.Namespace, sv.Spec.Keeper, contracts.ReadOpts{ForUpdate: true}) + if err != nil { + return nil, fmt.Errorf("fetching keeper config: namespace=%+v keeperName=%+v %w", sv.Namespace, sv.Spec.Keeper, err) + } + + keeper, err := s.keeperService.KeeperForConfig(keeperCfg) + if err != nil { + return nil, fmt.Errorf("getting keeper for config: namespace=%+v keeperName=%+v %w", sv.Namespace, sv.Spec.Keeper, err) + } + logging.FromContext(ctx).Debug("retrieved keeper", "namespace", sv.Namespace, "keeperName", sv.Spec.Keeper, "type", keeperCfg.Type()) + + // TODO: can we stop using external id? + // TODO: store uses only the namespace and returns and id. It could be a kv instead. + // TODO: check that the encrypted store works with multiple versions + externalID, err := keeper.Store(ctx, keeperCfg, sv.Namespace, sv.Spec.Value.DangerouslyExposeAndConsumeValue()) + if err != nil { + return nil, fmt.Errorf("storing secure value in keeper: %w", err) + } + createdSv.Status.ExternalID = string(externalID) + + if err := s.secureValueMetadataStorage.SetExternalID(ctx, xkube.Namespace(sv.Namespace), sv.Name, createdSv.Status.Version, externalID); err != nil { + return nil, fmt.Errorf("setting secure value external id: %w", err) + } + + if err := s.secureValueMetadataStorage.SetVersionToActive(ctx, xkube.Namespace(sv.Namespace), sv.Name, createdSv.Status.Version); err != nil { + return nil, fmt.Errorf("marking secure value version as active: %w", err) + } + + // In a single query: + // TODO: set external id + // TODO: set to active + + return createdSv, nil } func (s *SecureValueService) Read(ctx context.Context, namespace xkube.Namespace, name string) (*secretv0alpha1.SecureValue, error) { @@ -139,84 +187,6 @@ func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace }, nil } -func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, bool, error) { - ctx, span := s.tracer.Start(ctx, "SecureValueService.Create", trace.WithAttributes( - attribute.String("name", newSecureValue.GetName()), - attribute.String("namespace", newSecureValue.GetNamespace()), - attribute.String("actor", actorUID), - )) - defer span.End() - - // True when the effects of an update can be seen immediately. - // Never true in this case since updating a secure value is async. - const updateIsSync = false - - var ( - out *secretv0alpha1.SecureValue - encryptedSecret string - ) - - if newSecureValue.Spec.Value != "" { - buffer, err := s.encryptionManager.Encrypt(ctx, newSecureValue.Namespace, []byte(newSecureValue.Spec.Value.DangerouslyExposeAndConsumeValue())) - if err != nil { - return nil, false, fmt.Errorf("encrypting secure value secret: %w", err) - } - encryptedSecret = string(buffer) - } - - // Especifically here so that the spans from the worker are not inside the transaction. - requestID := tracectx.HexEncodeTraceFromContext(ctx) - - if err := s.database.Transaction(ctx, func(ctx context.Context) error { - sv, err := s.secureValueMetadataStorage.Read(ctx, xkube.Namespace(newSecureValue.Namespace), newSecureValue.Name, contracts.ReadOpts{ForUpdate: true}) - if err != nil { - return fmt.Errorf("fetching secure value: %+w", err) - } - - if sv.Status.Phase == secretv0alpha1.SecureValuePhasePending { - return contracts.ErrSecureValueOperationInProgress - } - - // Succeed immediately if the value is not going to be updated - if encryptedSecret == "" { - newSecureValue.Status = secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhaseSucceeded} - } else { - newSecureValue.Status = secretv0alpha1.SecureValueStatus{ - Message: "Updating secure value", - Phase: secretv0alpha1.SecureValuePhasePending, - } - } - - // Current implementation replaces everything passed in the spec, so it is not a PATCH. Do we want/need to support that? - updatedSecureValue, err := s.secureValueMetadataStorage.Update(ctx, newSecureValue, actorUID) - if err != nil { - return fmt.Errorf("failed to update secure value: %w", err) - } - out = updatedSecureValue - - // Only the value needs to be updated asynchronously by the outbox worker - if encryptedSecret != "" { - if _, err := s.outboxQueue.Append(ctx, contracts.AppendOutboxMessage{ - RequestID: requestID, - Type: contracts.UpdateSecretOutboxMessage, - Name: newSecureValue.Name, - Namespace: newSecureValue.Namespace, - EncryptedSecret: encryptedSecret, - KeeperName: newSecureValue.Spec.Keeper, - ExternalID: &updatedSecureValue.Status.ExternalID, - }); err != nil { - return fmt.Errorf("failed to append message to update secure value to outbox queue: %w", err) - } - } - - return nil - }); err != nil { - return out, updateIsSync, err - } - - return out, updateIsSync, nil -} - func (s *SecureValueService) Delete(ctx context.Context, namespace xkube.Namespace, name string) (*secretv0alpha1.SecureValue, error) { ctx, span := s.tracer.Start(ctx, "SecureValueService.Delete", trace.WithAttributes( attribute.String("name", name), @@ -224,45 +194,14 @@ func (s *SecureValueService) Delete(ctx context.Context, namespace xkube.Namespa )) defer span.End() - // Set inside of the transaction callback - var out *secretv0alpha1.SecureValue - - // Especifically here so that the spans from the worker are not inside the transaction. - requestID := tracectx.HexEncodeTraceFromContext(ctx) - - if err := s.database.Transaction(ctx, func(ctx context.Context) error { - sv, err := s.secureValueMetadataStorage.Read(ctx, namespace, name, contracts.ReadOpts{ForUpdate: true}) - if err != nil { - return fmt.Errorf("fetching secure value: %+w", err) - } - - if sv.Status.Phase == secretv0alpha1.SecureValuePhasePending { - return contracts.ErrSecureValueOperationInProgress - } - - sv.Status = secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhasePending, Message: "Deleting secure value"} - - if err := s.secureValueMetadataStorage.SetStatus(ctx, namespace, name, sv.Status); err != nil { - return fmt.Errorf("setting secure value status phase: %+w", err) - } - - if _, err := s.outboxQueue.Append(ctx, contracts.AppendOutboxMessage{ - RequestID: requestID, - Type: contracts.DeleteSecretOutboxMessage, - Name: name, - Namespace: namespace.String(), - KeeperName: sv.Spec.Keeper, - ExternalID: &sv.Status.ExternalID, - }); err != nil { - return fmt.Errorf("appending delete secure value message to outbox queue: %+w", err) - } - - out = sv - - return nil - }); err != nil { - return out, err + sv, err := s.secureValueMetadataStorage.Read(ctx, namespace, name, contracts.ReadOpts{ForUpdate: true}) + if err != nil { + return nil, fmt.Errorf("fetching secure value: %+w", err) } - return out, nil + if err := s.secureValueMetadataStorage.SetVersionToInactive(ctx, namespace, name, sv.Status.Version); err != nil { + return nil, fmt.Errorf("setting secure value version to inactive: %+w", err) + } + + return sv, nil } diff --git a/pkg/registry/apis/secret/service/secure_value_test.go b/pkg/registry/apis/secret/service/secure_value_test.go new file mode 100644 index 00000000000..865138d097b --- /dev/null +++ b/pkg/registry/apis/secret/service/secure_value_test.go @@ -0,0 +1,94 @@ +package service_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/apis/secret/v0alpha1" + "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" + "github.com/grafana/grafana/pkg/registry/apis/secret/testutils" + "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" + "github.com/stretchr/testify/require" +) + +func TestCrud(t *testing.T) { + t.Parallel() + + t.Run("creating a secure value creates new versions", func(t *testing.T) { + t.Parallel() + sut := testutils.Setup(t) + + sv1, err := sut.CreateSv(t.Context()) + require.NoError(t, err) + + // Create the same secure value twice + input := sv1.DeepCopy() + input.Spec.Description = "d2" + input.Spec.Value = v0alpha1.NewExposedSecureValue("v2") + + sv2, err := sut.CreateSv(t.Context(), testutils.CreateSvWithSv(input)) + require.NoError(t, err) + require.True(t, sv2.Status.Version > sv1.Status.Version) + + // Read the secure value + sv, err := sut.SecureValueService.Read(t.Context(), xkube.Namespace(sv2.Namespace), sv2.Name) + require.NoError(t, err) + + // It should be the latest version + require.Equal(t, sv2.Namespace, sv.Namespace) + require.Equal(t, sv2.Name, sv.Name) + require.Equal(t, "d2", sv.Spec.Description) + require.Equal(t, sv2.Status.Version, sv.Status.Version) + }) + + t.Run("updating a secure value creates new versions", func(t *testing.T) { + t.Parallel() + + sut := testutils.Setup(t) + + // Create a secure value + sv1, err := sut.CreateSv(t.Context()) + require.NoError(t, err) + + ns := sv1.Namespace + name := sv1.Name + + // Update the secure value + input := sv1.DeepCopy() + input.Spec.Description = "d2" + sv2, err := sut.UpdateSv(t.Context(), input) + require.NoError(t, err) + + // Read the secure value + sv3, err := sut.SecureValueService.Read(t.Context(), xkube.Namespace(ns), name) + require.NoError(t, err) + + // Nothing has changed except for the updated field. + require.Equal(t, ns, sv2.Namespace) + require.Equal(t, name, sv2.Name) + require.True(t, sv2.Status.Version > sv1.Status.Version) + require.Equal(t, "d2", sv2.Spec.Description) + + require.Equal(t, ns, sv3.Namespace) + require.Equal(t, name, sv3.Name) + require.Equal(t, sv2.Status.Version, sv3.Status.Version) + require.Equal(t, "d2", sv3.Spec.Description) + }) + + t.Run("deleting secure values", func(t *testing.T) { + t.Parallel() + + sut := testutils.Setup(t) + + sv1, err := sut.CreateSv(t.Context()) + require.NoError(t, err) + + sv2, err := sut.DeleteSv(t.Context(), sv1.Namespace, sv1.Name) + require.NoError(t, err) + + require.Equal(t, sv1.Namespace, sv2.Namespace) + require.Equal(t, sv1.Name, sv2.Name) + + _, err = sut.SecureValueMetadataStorage.Read(t.Context(), xkube.Namespace(sv1.Namespace), sv1.Name, contracts.ReadOpts{}) + require.ErrorIs(t, err, contracts.ErrSecureValueNotFound) + }) +} diff --git a/pkg/registry/apis/secret/testutils/testutils.go b/pkg/registry/apis/secret/testutils/testutils.go index 40e571aca63..281304320c8 100644 --- a/pkg/registry/apis/secret/testutils/testutils.go +++ b/pkg/registry/apis/secret/testutils/testutils.go @@ -3,7 +3,6 @@ package testutils import ( "context" "testing" - "time" secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1" encryptionstorage "github.com/grafana/grafana/pkg/storage/secret/encryption" @@ -12,11 +11,11 @@ import ( "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" + "github.com/grafana/grafana/pkg/registry/apis/secret/decrypt" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" "github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper/sqlkeeper" "github.com/grafana/grafana/pkg/registry/apis/secret/service" - "github.com/grafana/grafana/pkg/registry/apis/secret/worker" "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/actest" @@ -29,35 +28,28 @@ import ( "github.com/stretchr/testify/require" ) -type setupConfig struct { - workerCfg worker.Config - keeperService contracts.KeeperService +type SetupConfig struct { + KeeperService contracts.KeeperService + AllowList map[string]struct{} } -func defaultSetupCfg() setupConfig { - return setupConfig{ - workerCfg: worker.Config{ - BatchSize: 10, - ReceiveTimeout: 1 * time.Second, - PollingInterval: time.Millisecond, - MaxMessageProcessingAttempts: 5, - }, +func defaultSetupCfg() SetupConfig { + return SetupConfig{} +} + +func WithKeeperService(keeperService contracts.KeeperService) func(*SetupConfig) { + return func(setupCfg *SetupConfig) { + setupCfg.KeeperService = keeperService } } -func WithWorkerConfig(cfg worker.Config) func(*setupConfig) { - return func(setupCfg *setupConfig) { - setupCfg.workerCfg = cfg +func WithMutateCfg(f func(*SetupConfig)) func(*SetupConfig) { + return func(cfg *SetupConfig) { + f(cfg) } } -func WithKeeperService(keeperService contracts.KeeperService) func(*setupConfig) { - return func(setupCfg *setupConfig) { - setupCfg.keeperService = keeperService - } -} - -func Setup(t *testing.T, opts ...func(*setupConfig)) Sut { +func Setup(t *testing.T, opts ...func(*SetupConfig)) Sut { setupCfg := defaultSetupCfg() for _, opt := range opts { opt(&setupCfg) @@ -68,8 +60,6 @@ func Setup(t *testing.T, opts ...func(*setupConfig)) Sut { database := database.ProvideDatabase(testDB, tracer) - outboxQueue := metadata.ProvideOutboxQueue(database, tracer, nil) - features := featuremgmt.WithFeatures(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, featuremgmt.FlagSecretsManagementAppPlatform) keeperMetadataStorage, err := metadata.ProvideKeeperMetadataStorage(database, tracer, features, nil) @@ -111,34 +101,24 @@ func Setup(t *testing.T, opts ...func(*setupConfig)) Sut { var keeperService contracts.KeeperService = newKeeperServiceWrapper(sqlKeeper) - if setupCfg.keeperService != nil { - keeperService = setupCfg.keeperService + if setupCfg.KeeperService != nil { + keeperService = setupCfg.KeeperService } - secureValueService := service.ProvideSecureValueService(tracer, accessClient, database, secureValueMetadataStorage, outboxQueue, encryptionManager) + secureValueService := service.ProvideSecureValueService(tracer, accessClient, database, secureValueMetadataStorage, keeperMetadataStorage, keeperService) - worker, err := worker.NewWorker( - setupCfg.workerCfg, - tracer, - database, - outboxQueue, - secureValueMetadataStorage, - keeperMetadataStorage, - keeperService, - encryptionManager, - features, - nil, // metrics - ) + decryptAuthorizer := decrypt.ProvideDecryptAuthorizer(tracer, setupCfg.AllowList) + + decryptStorage, err := metadata.ProvideDecryptStorage(features, tracer, keeperService, keeperMetadataStorage, secureValueMetadataStorage, decryptAuthorizer, nil) require.NoError(t, err) - return Sut{Worker: worker, SecureValueService: secureValueService, SecureValueMetadataStorage: secureValueMetadataStorage, OutboxQueue: outboxQueue, Database: database} + return Sut{SecureValueService: secureValueService, SecureValueMetadataStorage: secureValueMetadataStorage, Database: database, DecryptStorage: decryptStorage} } type Sut struct { - Worker *worker.Worker SecureValueService *service.SecureValueService SecureValueMetadataStorage contracts.SecureValueMetadataStorage - OutboxQueue contracts.OutboxQueue + DecryptStorage contracts.DecryptStorage Database *database.Database } @@ -163,9 +143,7 @@ func (s *Sut) CreateSv(ctx context.Context, opts ...func(*CreateSvConfig)) (*sec Description: "desc1", Value: secretv0alpha1.NewExposedSecureValue("v1"), }, - Status: secretv0alpha1.SecureValueStatus{ - Phase: secretv0alpha1.SecureValuePhasePending, - }, + Status: secretv0alpha1.SecureValueStatus{}, }, } for _, opt := range opts { diff --git a/pkg/registry/apis/secret/worker/metrics.go b/pkg/registry/apis/secret/worker/metrics.go deleted file mode 100644 index a6f690f7163..00000000000 --- a/pkg/registry/apis/secret/worker/metrics.go +++ /dev/null @@ -1,44 +0,0 @@ -package worker - -import ( - "github.com/prometheus/client_golang/prometheus" -) - -const ( - namespace = "grafana_secrets_manager" - subsystem = "outbox_worker" -) - -// OutboxMetrics is a struct that contains all the metrics for an implementation of the secrets service. -type OutboxMetrics struct { - OutboxMessageProcessingDuration *prometheus.HistogramVec -} - -func newOutboxMetrics() *OutboxMetrics { - return &OutboxMetrics{ - OutboxMessageProcessingDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "message_processing_duration_seconds", - Help: "Duration of outbox message processing", - Buckets: prometheus.DefBuckets, - }, []string{"message_type", "keeper_type"}), - } -} - -// NewOutboxMetrics creates a new SecretsMetrics struct containing registered metrics -func NewOutboxMetrics(reg prometheus.Registerer) *OutboxMetrics { - m := newOutboxMetrics() - - if reg != nil { - reg.MustRegister( - m.OutboxMessageProcessingDuration, - ) - } - - return m -} - -func NewTestMetrics() *OutboxMetrics { - return newOutboxMetrics() -} diff --git a/pkg/registry/apis/secret/worker/worker.go b/pkg/registry/apis/secret/worker/worker.go deleted file mode 100644 index 35474fdae47..00000000000 --- a/pkg/registry/apis/secret/worker/worker.go +++ /dev/null @@ -1,274 +0,0 @@ -package worker - -import ( - "context" - "errors" - "fmt" - "time" - - "github.com/grafana/grafana-app-sdk/logging" - secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1" - "github.com/grafana/grafana/pkg/registry" - "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" - "github.com/grafana/grafana/pkg/registry/apis/secret/tracectx" - "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/prometheus/client_golang/prometheus" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// Consumes and processes messages from the secure value outbox queue -type Worker struct { - config Config - tracer trace.Tracer - database contracts.Database - outboxQueue contracts.OutboxQueue - secureValueMetadataStorage contracts.SecureValueMetadataStorage - keeperMetadataStorage contracts.KeeperMetadataStorage - keeperService contracts.KeeperService - encryptionManager contracts.EncryptionManager - metrics *OutboxMetrics - enabled bool -} - -// DefaultConfig for the secure value outbox worker. -var DefaultConfig = Config{ - BatchSize: 20, - ReceiveTimeout: 5 * time.Second, - PollingInterval: 100 * time.Millisecond, - MaxMessageProcessingAttempts: 10, -} - -// ProvideWorkerConfig used for wire. -func ProvideWorkerConfig() Config { - return DefaultConfig -} - -type Config struct { - // The max number of messages to fetch from the outbox queue in a batch - BatchSize uint - // How long to wait for a request to fetch messages from the outbox queue - ReceiveTimeout time.Duration - // How often to poll the outbox queue for new messages - PollingInterval time.Duration - // How many tries to try to process a message before marking the operation as failed - MaxMessageProcessingAttempts uint -} - -func NewWorker( - config Config, - tracer trace.Tracer, - database contracts.Database, - outboxQueue contracts.OutboxQueue, - secureValueMetadataStorage contracts.SecureValueMetadataStorage, - keeperMetadataStorage contracts.KeeperMetadataStorage, - keeperService contracts.KeeperService, - encryptionManager contracts.EncryptionManager, - features featuremgmt.FeatureToggles, - reg prometheus.Registerer, -) (*Worker, error) { - if config.BatchSize == 0 { - return nil, fmt.Errorf("config.BatchSize is required") - } - if config.ReceiveTimeout == 0 { - return nil, fmt.Errorf("config.ReceiveTimeout is required") - } - if config.PollingInterval == 0 { - return nil, fmt.Errorf("config.PollingInterval is required") - } - if config.MaxMessageProcessingAttempts == 0 { - return nil, fmt.Errorf("config.MaxMessageProcessingAttempts is required") - } - - // Require both features to be enabled for the worker to run. - enabled := features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) && features.IsEnabledGlobally(featuremgmt.FlagSecretsManagementAppPlatform) - - return &Worker{ - config: config, - tracer: tracer, - database: database, - outboxQueue: outboxQueue, - secureValueMetadataStorage: secureValueMetadataStorage, - keeperMetadataStorage: keeperMetadataStorage, - keeperService: keeperService, - encryptionManager: encryptionManager, - metrics: NewOutboxMetrics(reg), - enabled: enabled, - }, nil -} - -// Ensure that Worker implements the BackgroundService interface, so we can start it as a background service. -var _ registry.BackgroundService = (*Worker)(nil) - -// Run is the main method to drive the worker -func (w *Worker) Run(ctx context.Context) error { - if !w.enabled { - return nil - } - - logging.FromContext(ctx).Debug("starting worker control loop") - - t := time.NewTicker(w.config.PollingInterval) - defer t.Stop() - - for { - select { - // If the context was canceled - case <-ctx.Done(): - // return the reason it was canceled - return ctx.Err() - - // Otherwise try to receive messages - case <-t.C: - if ctx.Err() != nil { - return ctx.Err() - } - - if err := w.ReceiveAndProcessMessages(ctx); err != nil { - logging.FromContext(ctx).Error("receiving outbox messages", "err", err.Error()) - } - } - } -} - -// TODO: don't rollback every message when a single error happens -func (w *Worker) ReceiveAndProcessMessages(ctx context.Context) error { - messageIDs := make([]int64, 0) - - txErr := w.database.Transaction(ctx, func(ctx context.Context) error { - timeoutCtx, cancel := context.WithTimeout(ctx, w.config.ReceiveTimeout) - messages, err := w.outboxQueue.ReceiveN(timeoutCtx, w.config.BatchSize) - cancel() - if err != nil { - return err - } - - for _, message := range messages { - messageIDs = append(messageIDs, message.MessageID) - if err := w.processMessage(ctx, message); err != nil { - return fmt.Errorf("processing message: %+v %w", message, err) - } - } - return nil - }) - - // This call is made outside the transaction to make sure the receive count is updated on rollbacks. - incrementErr := w.outboxQueue.IncrementReceiveCount(ctx, messageIDs) - if incrementErr != nil { - incrementErr = fmt.Errorf("incrementing receive count for outbox message: %w", incrementErr) - } - - return errors.Join(txErr, incrementErr) -} - -func (w *Worker) processMessage(ctx context.Context, message contracts.OutboxMessage) error { - start := time.Now() - keeperType := "unknown" - defer func() { - w.metrics.OutboxMessageProcessingDuration.WithLabelValues(string(message.Type), keeperType).Observe(time.Since(start).Seconds()) - }() - logging.FromContext(ctx).Debug("processing message", "type", message.Type, "name", message.Name, "namespace", message.Namespace, "receiveCount", message.ReceiveCount) - - opts := []trace.SpanStartOption{} - // If there's no request ID in the message, start a new root span and log an error. - ctx, err := tracectx.HexDecodeTraceIntoContext(ctx, message.RequestID) - if err != nil { - opts = append(opts, trace.WithNewRoot()) - logging.FromContext(ctx).Error("decoding trace context from message", "err", err.Error(), "message.requestID", message.RequestID) - } - - opts = append(opts, trace.WithAttributes( - attribute.String("message.requestID", message.RequestID), - attribute.Int64("message.id", message.MessageID), - attribute.String("message.type", string(message.Type)), - attribute.String("message.namespace", message.Namespace), - attribute.String("message.secureValue.name", message.Name), - attribute.Int("message.receive.count", message.ReceiveCount), - )) - - ctx, span := w.tracer.Start(ctx, "Worker.ProcessMessage", opts...) - defer span.End() - - if message.ReceiveCount >= int(w.config.MaxMessageProcessingAttempts) { - if err := w.secureValueMetadataStorage.SetStatus(ctx, xkube.Namespace(message.Namespace), message.Name, secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhaseFailed, Message: fmt.Sprintf("Reached max number of attempts to complete operation: %s", message.Type)}); err != nil { - return fmt.Errorf("setting secret metadata status to Succeeded: message=%+v", message) - } - if err := w.outboxQueue.Delete(ctx, message.MessageID); err != nil { - return fmt.Errorf("deleting message from outbox queue: %w", err) - } - return nil - } - - keeperCfg, err := w.keeperMetadataStorage.GetKeeperConfig(ctx, message.Namespace, message.KeeperName, contracts.ReadOpts{ForUpdate: true}) - if err != nil { - return fmt.Errorf("fetching keeper config: namespace=%+v keeperName=%+v %w", message.Namespace, message.KeeperName, err) - } - keeperType = string(keeperCfg.Type()) - - keeper, err := w.keeperService.KeeperForConfig(keeperCfg) - if err != nil { - return fmt.Errorf("getting keeper for config: namespace=%+v keeperName=%+v %w", message.Namespace, message.KeeperName, err) - } - logging.FromContext(ctx).Debug("retrieved keeper", "namespace", message.Namespace, "keeperName", message.KeeperName, "type", keeperCfg.Type()) - - switch message.Type { - case contracts.CreateSecretOutboxMessage: - rawSecret, err := w.encryptionManager.Decrypt(ctx, message.Namespace, []byte(message.EncryptedSecret)) - if err != nil { - return fmt.Errorf("decrypting secure value secret: %w", err) - } - - externalID, err := keeper.Store(ctx, keeperCfg, message.Namespace, string(rawSecret)) - if err != nil { - return fmt.Errorf("storing secret: message=%+v %w", message, err) - } - - if err := w.secureValueMetadataStorage.SetExternalID(ctx, xkube.Namespace(message.Namespace), message.Name, externalID); err != nil { - return fmt.Errorf("setting secret metadata externalID: externalID=%+v message=%+v %w", externalID, message, err) - } - - // Setting the status to Succeeded must be the last action - // since it acts as a fence to clients. - if err := w.secureValueMetadataStorage.SetStatus(ctx, xkube.Namespace(message.Namespace), message.Name, secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhaseSucceeded}); err != nil { - return fmt.Errorf("setting secret metadata status to Succeeded: message=%+v %w", message, err) - } - - case contracts.UpdateSecretOutboxMessage: - rawSecret, err := w.encryptionManager.Decrypt(ctx, message.Namespace, []byte(message.EncryptedSecret)) - if err != nil { - return fmt.Errorf("decrypting secure value secret: %w", err) - } - - if err := keeper.Update(ctx, keeperCfg, message.Namespace, contracts.ExternalID(*message.ExternalID), string(rawSecret)); err != nil { - return fmt.Errorf("calling keeper to update secret: %w", err) - } - - // Setting the status to Succeeded must be the last action - // since it acts as a fence to clients. - if err := w.secureValueMetadataStorage.SetStatus(ctx, xkube.Namespace(message.Namespace), message.Name, secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhaseSucceeded}); err != nil { - return fmt.Errorf("setting secret metadata status to Succeeded: message=%+v", message) - } - - case contracts.DeleteSecretOutboxMessage: - if err := keeper.Delete(ctx, keeperCfg, message.Namespace, contracts.ExternalID(*message.ExternalID)); err != nil { - return fmt.Errorf("calling keeper to delete secret: %w", err) - } - if err := w.secureValueMetadataStorage.Delete(ctx, xkube.Namespace(message.Namespace), message.Name); err != nil { - return fmt.Errorf("deleting secure value metadata: %+w", err) - } - - default: - return fmt.Errorf("unhandled message type: %s", message.Type) - } - - // Delete the message from the queue after completing all operations because - // if the message is deleted first, the response may be lost, - // resulting in an error, but since the message was actually deleted - // the worker would never retry. - if err := w.outboxQueue.Delete(ctx, message.MessageID); err != nil { - return fmt.Errorf("deleting message from outbox queue: %w", err) - } - - return nil -} diff --git a/pkg/registry/apis/secret/worker/worker_test.go b/pkg/registry/apis/secret/worker/worker_test.go deleted file mode 100644 index 0d20a668e52..00000000000 --- a/pkg/registry/apis/secret/worker/worker_test.go +++ /dev/null @@ -1,246 +0,0 @@ -package worker_test - -import ( - "context" - "fmt" - "testing" - "time" - - secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1" - "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" - "github.com/grafana/grafana/pkg/registry/apis/secret/testutils" - "github.com/grafana/grafana/pkg/registry/apis/secret/worker" - "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" - "github.com/stretchr/testify/require" -) - -type fakeKeeperService struct { - keeperForConfigFunc func(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error) -} - -func newFakeKeeperService(keeperForConfigFunc func(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error)) *fakeKeeperService { - return &fakeKeeperService{keeperForConfigFunc: keeperForConfigFunc} -} - -func (s *fakeKeeperService) KeeperForConfig(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error) { - return s.keeperForConfigFunc(cfg) -} - -func TestProcessMessage(t *testing.T) { - t.Parallel() - - t.Run("secure value metadata status is set to Failed when processing a message fails too many times", func(t *testing.T) { - t.Parallel() - - // Given a worker that will attempt to process a message N times - workerCfg := worker.Config{ - BatchSize: 10, - ReceiveTimeout: 1 * time.Second, - PollingInterval: time.Millisecond, - MaxMessageProcessingAttempts: 2, - } - - // And an error that keeps happening - keeperService := newFakeKeeperService(func(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error) { - return nil, fmt.Errorf("oops") - }) - - sut := testutils.Setup(t, testutils.WithWorkerConfig(workerCfg), testutils.WithKeeperService(keeperService)) - ctx := context.Background() - - // Queue a create secure value operation - sv, err := sut.CreateSv(ctx) - require.NoError(t, err) - - for range workerCfg.MaxMessageProcessingAttempts + 1 { - // The secure value status should be Pending while the worker is trying to process the message - sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{}) - require.NoError(t, err) - require.Equal(t, secretv0alpha1.SecureValuePhasePending, sv.Status.Phase) - - // Worker tries to process messages - _ = sut.Worker.ReceiveAndProcessMessages(ctx) - } - - // After the worker fails to process a message too many times, - // the secure value status is changed to Failed - sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{}) - require.NoError(t, err) - require.Equal(t, secretv0alpha1.SecureValuePhaseFailed, sv.Status.Phase) - - messages, err := sut.OutboxQueue.ReceiveN(ctx, 100) - require.NoError(t, err) - require.Empty(t, messages) - }) - - t.Run("create sv: secure value metadata status is set to Succeeded when message is processed successfully", func(t *testing.T) { - t.Parallel() - - sut := testutils.Setup(t) - ctx := context.Background() - - // Queue a create secure value operation - sv, err := sut.CreateSv(ctx) - require.NoError(t, err) - - // Worker receives and processes the message - require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx)) - - // and sets the secure value status to Succeeded - sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{}) - require.NoError(t, err) - require.Equal(t, secretv0alpha1.SecureValuePhaseSucceeded, sv.Status.Phase) - - messages, err := sut.OutboxQueue.ReceiveN(ctx, 100) - require.NoError(t, err) - require.Empty(t, messages) - }) - - t.Run("update sv: secure value metadata status is set to Succeeded when message is processed successfully", func(t *testing.T) { - t.Parallel() - - sut := testutils.Setup(t) - ctx := context.Background() - - // Queue a create secure value operation - sv, err := sut.CreateSv(ctx) - require.NoError(t, err) - - // Worker receives and processes the message - require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx)) - - // and sets the secure value status to Succeeded - sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{}) - require.NoError(t, err) - require.Equal(t, secretv0alpha1.SecureValuePhaseSucceeded, sv.Status.Phase) - - sv.Spec.Description = "desc2" - sv.Spec.Value = secretv0alpha1.NewExposedSecureValue("v2") - - // Queue an update operation - sv, err = sut.UpdateSv(ctx, sv) - require.NoError(t, err) - require.Equal(t, secretv0alpha1.SecureValuePhasePending, sv.Status.Phase) - - // Worker receives and processes the message - require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx)) - updatedSv, err := sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{}) - require.NoError(t, err) - require.Equal(t, secretv0alpha1.SecureValuePhaseSucceeded, updatedSv.Status.Phase) - require.Equal(t, sv.Spec.Description, updatedSv.Spec.Description) - - messages, err := sut.OutboxQueue.ReceiveN(ctx, 100) - require.NoError(t, err) - require.Empty(t, messages) - }) - - t.Run("delete sv: secure value metadata is deleted", func(t *testing.T) { - t.Parallel() - - sut := testutils.Setup(t) - ctx := context.Background() - - // Queue a create secure value operation - sv, err := sut.CreateSv(ctx) - require.NoError(t, err) - - // Worker receives and processes the message - require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx)) - - // and sets the secure value status to Succeeded - sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{}) - require.NoError(t, err) - require.Equal(t, secretv0alpha1.SecureValuePhaseSucceeded, sv.Status.Phase) - - // Queue a delete operation - updatedSv, err := sut.DeleteSv(ctx, sv.Namespace, sv.Name) - require.NoError(t, err) - require.Equal(t, secretv0alpha1.SecureValuePhasePending, updatedSv.Status.Phase) - - // Worker receives and processes the message - require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx)) - - // The secure value has been deleted - _, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{}) - require.ErrorIs(t, err, contracts.ErrSecureValueNotFound) - - messages, err := sut.OutboxQueue.ReceiveN(ctx, 100) - require.NoError(t, err) - require.Empty(t, messages) - }) - - t.Run("when creating a secure value, the secret is encrypted before it is added to the outbox queue", func(t *testing.T) { - t.Parallel() - - sut := testutils.Setup(t) - ctx := context.Background() - - // Queue a create secure value operation - var secret string - _, err := sut.CreateSv(ctx, func(cfg *testutils.CreateSvConfig) { - secret = string(cfg.Sv.Spec.Value) - }) - require.NoError(t, err) - - messages, err := sut.OutboxQueue.ReceiveN(ctx, 100) - require.NoError(t, err) - require.Equal(t, 1, len(messages)) - - encryptedSecret := messages[0].EncryptedSecret - require.NotEmpty(t, secret) - require.NotEmpty(t, encryptedSecret) - require.NotEqual(t, secret, encryptedSecret) - }) - - t.Run("when updating a secure value, the secret is encrypted before it is added to the outbox queue", func(t *testing.T) { - t.Parallel() - - sut := testutils.Setup(t) - ctx := context.Background() - - // Queue a create secure value operation - sv, err := sut.CreateSv(ctx) - require.NoError(t, err) - sv.Spec.Value = secretv0alpha1.NewExposedSecureValue("v2") - - require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx)) - - newValue := "v2" - sv.Spec.Value = secretv0alpha1.NewExposedSecureValue(newValue) - - // Queue an update secure value operation - _, err = sut.UpdateSv(ctx, sv) - require.NoError(t, err) - - messages, err := sut.OutboxQueue.ReceiveN(ctx, 100) - require.NoError(t, err) - require.Equal(t, 1, len(messages)) - - encryptedSecret := messages[0].EncryptedSecret - require.NotEmpty(t, encryptedSecret) - require.NotEqual(t, newValue, encryptedSecret) - }) - - t.Run("when deleting a secure value, no value is added to the outbox message", func(t *testing.T) { - t.Parallel() - - sut := testutils.Setup(t) - ctx := context.Background() - - // Queue a create secure value operation - sv, err := sut.CreateSv(ctx) - require.NoError(t, err) - sv.Spec.Value = secretv0alpha1.NewExposedSecureValue("v2") - - require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx)) - - // Queue a delete secure value operation - _, err = sut.DeleteSv(ctx, sv.Namespace, sv.Name) - require.NoError(t, err) - - messages, err := sut.OutboxQueue.ReceiveN(ctx, 100) - require.NoError(t, err) - require.Equal(t, 1, len(messages)) - require.Empty(t, messages[0].EncryptedSecret) - }) -} diff --git a/pkg/registry/backgroundsvcs/background_services.go b/pkg/registry/backgroundsvcs/background_services.go index d8a9010bfd2..f6ae88f9dd1 100644 --- a/pkg/registry/backgroundsvcs/background_services.go +++ b/pkg/registry/backgroundsvcs/background_services.go @@ -9,7 +9,6 @@ import ( "github.com/grafana/grafana/pkg/infra/usagestats/statscollector" "github.com/grafana/grafana/pkg/registry" apiregistry "github.com/grafana/grafana/pkg/registry/apis" - secretworker "github.com/grafana/grafana/pkg/registry/apis/secret/worker" appregistry "github.com/grafana/grafana/pkg/registry/apps" "github.com/grafana/grafana/pkg/services/accesscontrol/dualwrite" "github.com/grafana/grafana/pkg/services/anonymous/anonimpl" @@ -71,7 +70,6 @@ func ProvideBackgroundServiceRegistry( appRegistry *appregistry.Service, pluginDashboardUpdater *plugindashboardsservice.DashboardUpdater, dashboardServiceImpl *service.DashboardServiceImpl, - secretManagerWorker *secretworker.Worker, // Need to make sure these are initialized, is there a better place to put them? _ dashboardsnapshots.Service, _ serviceaccounts.Service, @@ -119,7 +117,6 @@ func ProvideBackgroundServiceRegistry( appRegistry, pluginDashboardUpdater, dashboardServiceImpl, - secretManagerWorker, ) } diff --git a/pkg/server/module_server.go b/pkg/server/module_server.go index 979e993eb7a..bca9bf21c6b 100644 --- a/pkg/server/module_server.go +++ b/pkg/server/module_server.go @@ -19,6 +19,7 @@ import ( "github.com/grafana/grafana/pkg/api" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/modules" "github.com/grafana/grafana/pkg/services/authz" "github.com/grafana/grafana/pkg/services/featuremgmt" @@ -39,6 +40,7 @@ func NewModule(opts Options, indexMetrics *resource.BleveIndexMetrics, reg prometheus.Registerer, promGatherer prometheus.Gatherer, + tracer tracing.Tracer, // Ensures tracing is initialized license licensing.Licensing, ) (*ModuleServer, error) { s, err := newModuleServer(opts, apiOpts, features, cfg, storageMetrics, indexMetrics, reg, promGatherer, license) diff --git a/pkg/server/search_server_distributor_test.go b/pkg/server/search_server_distributor_test.go index 3062b1efe8d..32dddffcec8 100644 --- a/pkg/server/search_server_distributor_test.go +++ b/pkg/server/search_server_distributor_test.go @@ -15,6 +15,7 @@ import ( claims "github.com/grafana/authlib/types" "github.com/grafana/grafana/pkg/api" "github.com/grafana/grafana/pkg/apimachinery/identity" + "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/modules" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore/sqlutil" @@ -321,7 +322,9 @@ func initModuleServerForTest( opts Options, apiOpts api.ServerOptions, ) testModuleServer { - ms, err := NewModule(opts, apiOpts, featuremgmt.WithFeatures(featuremgmt.FlagUnifiedStorageSearch), cfg, nil, nil, prometheus.NewRegistry(), prometheus.DefaultGatherer, nil) + tracer := tracing.InitializeTracerForTest() + + ms, err := NewModule(opts, apiOpts, featuremgmt.WithFeatures(featuremgmt.FlagUnifiedStorageSearch), cfg, nil, nil, prometheus.NewRegistry(), prometheus.DefaultGatherer, tracer, nil) require.NoError(t, err) conn, err := grpc.NewClient(cfg.GRPCServer.Address, diff --git a/pkg/server/wire.go b/pkg/server/wire.go index efb82d04bc0..2004a813b11 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -46,7 +46,6 @@ import ( gsmEncryption "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" encryptionManager "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" secretsecurevalueservice "github.com/grafana/grafana/pkg/registry/apis/secret/service" - secretworker "github.com/grafana/grafana/pkg/registry/apis/secret/worker" appregistry "github.com/grafana/grafana/pkg/registry/apps" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/acimpl" @@ -431,15 +430,12 @@ var wireBasicSet = wire.NewSet( secretdecrypt.ProvideDecryptAllowList, secretencryption.ProvideDataKeyStorage, secretencryption.ProvideEncryptedValueStorage, - secretmetadata.ProvideOutboxQueue, secretsecurevalueservice.ProvideSecureValueService, secretmigrator.NewWithEngine, secretdatabase.ProvideDatabase, wire.Bind(new(secretcontracts.Database), new(*secretdatabase.Database)), encryptionManager.ProvideEncryptionManager, gsmEncryption.ProvideThirdPartyProviderMap, - secretworker.ProvideWorkerConfig, - secretworker.NewWorker, // Unified storage resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, diff --git a/pkg/server/wire_gen.go b/pkg/server/wire_gen.go index 166c20a19dc..7b6d39165b3 100644 --- a/pkg/server/wire_gen.go +++ b/pkg/server/wire_gen.go @@ -61,11 +61,9 @@ import ( "github.com/grafana/grafana/pkg/registry/apis/secret" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/decrypt" - encryption2 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" + encryption3 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" manager4 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" - "github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper" service11 "github.com/grafana/grafana/pkg/registry/apis/secret/service" - "github.com/grafana/grafana/pkg/registry/apis/secret/worker" "github.com/grafana/grafana/pkg/registry/apis/userstorage" "github.com/grafana/grafana/pkg/registry/apps" advisor2 "github.com/grafana/grafana/pkg/registry/apps/advisor" @@ -114,7 +112,7 @@ import ( "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources/guardian" service7 "github.com/grafana/grafana/pkg/services/datasources/service" - encryption3 "github.com/grafana/grafana/pkg/services/encryption" + "github.com/grafana/grafana/pkg/services/encryption" "github.com/grafana/grafana/pkg/services/encryption/provider" service2 "github.com/grafana/grafana/pkg/services/encryption/service" "github.com/grafana/grafana/pkg/services/extsvcauth" @@ -236,7 +234,7 @@ import ( "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" database5 "github.com/grafana/grafana/pkg/storage/secret/database" - "github.com/grafana/grafana/pkg/storage/secret/encryption" + encryption2 "github.com/grafana/grafana/pkg/storage/secret/encryption" "github.com/grafana/grafana/pkg/storage/secret/metadata" migrator2 "github.com/grafana/grafana/pkg/storage/secret/migrator" "github.com/grafana/grafana/pkg/storage/unified" @@ -705,38 +703,6 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser } importDashboardService := service9.ProvideService(routeRegisterImpl, quotaService, service12, pluginstoreService, libraryPanelService, dashboardService, accessControl, folderimplService, featureToggles) dashboardUpdater := service6.ProvideDashboardUpdater(inProcBus, pluginstoreService, service12, importDashboardService, service11, pluginService, dashboardService) - config := worker.ProvideWorkerConfig() - databaseDatabase := database5.ProvideDatabase(sqlStore, tracer) - outboxQueue := metadata.ProvideOutboxQueue(databaseDatabase, tracer, registerer) - secureValueMetadataStorage, err := metadata.ProvideSecureValueMetadataStorage(databaseDatabase, tracer, featureToggles, registerer) - if err != nil { - return nil, err - } - keeperMetadataStorage, err := metadata.ProvideKeeperMetadataStorage(databaseDatabase, tracer, featureToggles, registerer) - if err != nil { - return nil, err - } - encryptedValueStorage, err := encryption.ProvideEncryptedValueStorage(databaseDatabase, tracer, featureToggles) - if err != nil { - return nil, err - } - dataKeyStorage, err := encryption.ProvideDataKeyStorage(databaseDatabase, tracer, featureToggles, registerer) - if err != nil { - return nil, err - } - providerMap := encryption2.ProvideThirdPartyProviderMap() - encryptionManager, err := manager4.ProvideEncryptionManager(tracer, dataKeyStorage, cfg, usageStats, providerMap) - if err != nil { - return nil, err - } - ossKeeperService, err := secretkeeper.ProvideService(tracer, encryptedValueStorage, encryptionManager, registerer) - if err != nil { - return nil, err - } - workerWorker, err := worker.NewWorker(config, tracer, databaseDatabase, outboxQueue, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService, encryptionManager, featureToggles, registerer) - if err != nil { - return nil, err - } sanitizerProvider := sanitizer.ProvideService(renderingService) healthService, err := grpcserver.ProvideHealthService(cfg, grpcserverProvider) if err != nil { @@ -803,7 +769,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser } ossUserProtectionImpl := authinfoimpl.ProvideOSSUserProtectionService() registration := authnimpl.ProvideRegistration(cfg, authnService, orgService, userAuthTokenService, acimplService, permissionRegistry, apikeyService, userService, authService, ossUserProtectionImpl, loginattemptimplService, quotaService, authinfoimplService, renderingService, featureToggles, oauthtokenService, socialService, remoteCache, ldapImpl, ossImpl, tracingService, tempuserService, notificationService) - backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, workerWorker, serviceImpl, serviceAccountsProxy, sanitizerProvider, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration) + backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, serviceImpl, serviceAccountsProxy, sanitizerProvider, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration) usageStatsProvidersRegistry := usagestatssvcs.ProvideUsageStatsProvidersRegistry(acimplService, userService) server, err := New(opts, cfg, httpServer, acimplService, provisioningServiceImpl, backgroundServiceRegistry, usageStatsProvidersRegistry, statscollectorService, registerer) if err != nil { @@ -1250,38 +1216,6 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { } importDashboardService := service9.ProvideService(routeRegisterImpl, quotaService, service12, pluginstoreService, libraryPanelService, dashboardService, accessControl, folderimplService, featureToggles) dashboardUpdater := service6.ProvideDashboardUpdater(inProcBus, pluginstoreService, service12, importDashboardService, service11, pluginService, dashboardService) - config := worker.ProvideWorkerConfig() - databaseDatabase := database5.ProvideDatabase(sqlStore, tracer) - outboxQueue := metadata.ProvideOutboxQueue(databaseDatabase, tracer, registerer) - secureValueMetadataStorage, err := metadata.ProvideSecureValueMetadataStorage(databaseDatabase, tracer, featureToggles, registerer) - if err != nil { - return nil, err - } - keeperMetadataStorage, err := metadata.ProvideKeeperMetadataStorage(databaseDatabase, tracer, featureToggles, registerer) - if err != nil { - return nil, err - } - encryptedValueStorage, err := encryption.ProvideEncryptedValueStorage(databaseDatabase, tracer, featureToggles) - if err != nil { - return nil, err - } - dataKeyStorage, err := encryption.ProvideDataKeyStorage(databaseDatabase, tracer, featureToggles, registerer) - if err != nil { - return nil, err - } - providerMap := encryption2.ProvideThirdPartyProviderMap() - encryptionManager, err := manager4.ProvideEncryptionManager(tracer, dataKeyStorage, cfg, usageStats, providerMap) - if err != nil { - return nil, err - } - ossKeeperService, err := secretkeeper.ProvideService(tracer, encryptedValueStorage, encryptionManager, registerer) - if err != nil { - return nil, err - } - workerWorker, err := worker.NewWorker(config, tracer, databaseDatabase, outboxQueue, secureValueMetadataStorage, keeperMetadataStorage, ossKeeperService, encryptionManager, featureToggles, registerer) - if err != nil { - return nil, err - } sanitizerProvider := sanitizer.ProvideService(renderingService) healthService, err := grpcserver.ProvideHealthService(cfg, grpcserverProvider) if err != nil { @@ -1348,7 +1282,7 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { } ossUserProtectionImpl := authinfoimpl.ProvideOSSUserProtectionService() registration := authnimpl.ProvideRegistration(cfg, authnService, orgService, userAuthTokenService, acimplService, permissionRegistry, apikeyService, userService, authService, ossUserProtectionImpl, loginattemptimplService, quotaService, authinfoimplService, renderingService, featureToggles, oauthtokentestService, socialService, remoteCache, ldapImpl, ossImpl, tracingService, tempuserService, notificationServiceMock) - backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, workerWorker, serviceImpl, serviceAccountsProxy, sanitizerProvider, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration) + backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, serviceImpl, serviceAccountsProxy, sanitizerProvider, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration) usageStatsProvidersRegistry := usagestatssvcs.ProvideUsageStatsProvidersRegistry(acimplService, userService) server, err := New(opts, cfg, httpServer, acimplService, provisioningServiceImpl, backgroundServiceRegistry, usageStatsProvidersRegistry, statscollectorService, registerer) if err != nil { @@ -1445,9 +1379,17 @@ func InitializeModuleServer(cfg *setting.Cfg, opts Options, apiOpts api.ServerOp storageMetrics := resource.ProvideStorageMetrics(registerer) bleveIndexMetrics := resource.ProvideIndexMetrics(registerer) gatherer := metrics.ProvideGatherer() + tracingConfig, err := tracing.ProvideTracingConfig(cfg) + if err != nil { + return nil, err + } + tracingService, err := tracing.ProvideService(tracingConfig) + if err != nil { + return nil, err + } hooksService := hooks.ProvideService() ossLicensingService := licensing.ProvideService(cfg, hooksService) - moduleServer, err := NewModule(opts, apiOpts, featureToggles, cfg, storageMetrics, bleveIndexMetrics, registerer, gatherer, ossLicensingService) + moduleServer, err := NewModule(opts, apiOpts, featureToggles, cfg, storageMetrics, bleveIndexMetrics, registerer, gatherer, tracingService, ossLicensingService) if err != nil { return nil, err } @@ -1495,7 +1437,7 @@ var withOTelSet = wire.NewSet( otelTracer, grpcserver.ProvideService, interceptors.ProvideAuthenticator, ) -var wireBasicSet = wire.NewSet(annotationsimpl.ProvideService, wire.Bind(new(annotations.Repository), new(*annotationsimpl.RepositoryImpl)), New, api.ProvideHTTPServer, query.ProvideService, wire.Bind(new(query.Service), new(*query.ServiceImpl)), bus.ProvideBus, wire.Bind(new(bus.Bus), new(*bus.InProcBus)), rendering.ProvideService, wire.Bind(new(rendering.Service), new(*rendering.RenderingService)), routing.ProvideRegister, wire.Bind(new(routing.RouteRegister), new(*routing.RouteRegisterImpl)), hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, bundleregistry.ProvideService, wire.Bind(new(supportbundles.Service), new(*bundleregistry.Service)), updatemanager.ProvideGrafanaService, updatemanager.ProvidePluginsService, service.ProvideService, wire.Bind(new(usagestats.Service), new(*service.UsageStats)), validator2.ProvideService, legacy.ProvideLegacyMigrator, pluginsintegration.WireSet, dashboards.ProvideFileStoreManager, wire.Bind(new(dashboards.FileStore), new(*dashboards.FileStoreManager)), cloudwatch.ProvideService, cloudmonitoring.ProvideService, azuremonitor.ProvideService, postgres.ProvideService, mysql.ProvideService, mssql.ProvideService, store.ProvideEntityEventsService, dualwrite.ProvideService, httpclientprovider.New, wire.Bind(new(httpclient.Provider), new(*httpclient2.Provider)), serverlock.ProvideService, annotationsimpl.ProvideCleanupService, wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)), cleanup.ProvideService, shorturlimpl.ProvideService, wire.Bind(new(shorturls.Service), new(*shorturlimpl.ShortURLService)), queryhistory.ProvideService, wire.Bind(new(queryhistory.Service), new(*queryhistory.QueryHistoryService)), correlations.ProvideService, wire.Bind(new(correlations.Service), new(*correlations.CorrelationsService)), quotaimpl.ProvideService, remotecache.ProvideService, wire.Bind(new(remotecache.CacheStorage), new(*remotecache.RemoteCache)), authinfoimpl.ProvideService, wire.Bind(new(login.AuthInfoService), new(*authinfoimpl.Service)), authinfoimpl.ProvideStore, datasourceproxy.ProvideService, sort.ProvideService, search2.ProvideService, searchV2.ProvideService, searchV2.ProvideSearchHTTPService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, pushhttp.ProvideService, contexthandler.ProvideService, service10.ProvideService, wire.Bind(new(service10.LDAP), new(*service10.LDAPImpl)), jwt.ProvideService, wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), store2.ProvideDBStore, image.ProvideDeleteExpiredService, ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), libraryelements.ProvideService, wire.Bind(new(libraryelements.Service), new(*libraryelements.LibraryElementService)), notifications.ProvideService, notifications.ProvideSmtpService, github.ProvideFactory, tracing.ProvideService, tracing.ProvideTracingConfig, wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), withOTelSet, testdatasource.ProvideService, api4.ProvideService, opentsdb.ProvideService, socialimpl.ProvideService, influxdb.ProvideService, wire.Bind(new(social.Service), new(*socialimpl.SocialService)), tempo.ProvideService, loki.ProvideService, graphite.ProvideService, prometheus.ProvideService, elasticsearch.ProvideService, pyroscope.ProvideService, parca.ProvideService, zipkin.ProvideService, jaeger.ProvideService, service7.ProvideCacheService, wire.Bind(new(datasources.CacheService), new(*service7.CacheServiceImpl)), service2.ProvideEncryptionService, wire.Bind(new(encryption3.Internal), new(*service2.Service)), manager.ProvideSecretsService, wire.Bind(new(secrets.Service), new(*manager.SecretsService)), database.ProvideSecretsStore, wire.Bind(new(secrets.Store), new(*database.SecretsStoreImpl)), grafanads.ProvideService, wire.Bind(new(dashboardsnapshots.Store), new(*database4.DashboardSnapshotStore)), database4.ProvideStore, wire.Bind(new(dashboardsnapshots.Service), new(*service8.ServiceImpl)), service8.ProvideService, service7.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*service7.Service)), service7.ProvideLegacyDataSourceLookup, retriever.ProvideService, wire.Bind(new(serviceaccounts.ServiceAccountRetriever), new(*retriever.Service)), ossaccesscontrol.ProvideServiceAccountPermissions, wire.Bind(new(accesscontrol.ServiceAccountPermissionsService), new(*ossaccesscontrol.ServiceAccountPermissionsService)), manager2.ProvideServiceAccountsService, proxy.ProvideServiceAccountsProxy, wire.Bind(new(serviceaccounts.Service), new(*proxy.ServiceAccountsProxy)), expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, featuremgmt.ProvideOpenFeatureService, featuremgmt.ProvideStaticEvaluator, service5.ProvideDashboardServiceImpl, wire.Bind(new(dashboards2.PermissionsRegistrationService), new(*service5.DashboardServiceImpl)), service5.ProvideDashboardService, service5.ProvideDashboardProvisioningService, service5.ProvideDashboardPluginService, database2.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), folderimpl.ProvideDashboardFolderStore, wire.Bind(new(folder.FolderStore), new(*folderimpl.DashboardFolderStoreImpl)), service9.ProvideService, wire.Bind(new(dashboardimport.Service), new(*service9.ImportDashboardService)), service6.ProvideService, wire.Bind(new(plugindashboards.Service), new(*service6.Service)), service6.ProvideDashboardUpdater, sanitizer.ProvideService, kvstore2.ProvideService, avatar.ProvideAvatarCacheServer, statscollector.ProvideService, csrf.ProvideCSRFFilter, wire.Bind(new(csrf.Service), new(*csrf.CSRF)), ossaccesscontrol.ProvideTeamPermissions, wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)), ossaccesscontrol.ProvideFolderPermissions, wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)), ossaccesscontrol.ProvideDashboardPermissions, wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)), ossaccesscontrol.ProvideReceiverPermissionsService, wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)), starimpl.ProvideService, playlistimpl.ProvideService, apikeyimpl.ProvideService, dashverimpl.ProvideService, service3.ProvideService, wire.Bind(new(publicdashboards.Service), new(*service3.PublicDashboardServiceImpl)), database3.ProvideStore, wire.Bind(new(publicdashboards.Store), new(*database3.PublicDashboardStoreImpl)), metric.ProvideService, api2.ProvideApi, api3.ProvideApi, userimpl.ProvideService, orgimpl.ProvideService, orgimpl.ProvideDeletionService, statsimpl.ProvideService, grpccontext.ProvideContextHandler, grpcserver.ProvideHealthService, grpcserver.ProvideReflectionService, resolver.ProvideEntityReferenceResolver, teamimpl.ProvideService, teamapi.ProvideTeamAPI, tempuserimpl.ProvideService, loginattemptimpl.ProvideService, wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)), migrations2.ProvideDataSourceMigrationService, migrations2.ProvideSecretMigrationProvider, wire.Bind(new(migrations2.SecretMigrationProvider), new(*migrations2.SecretMigrationProviderImpl)), resourcepermissions.NewActionSetService, wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)), wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)), permreg.ProvidePermissionRegistry, acimpl.ProvideAccessControl, dualwrite2.ProvideZanzanaReconciler, navtreeimpl.ProvideService, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), tagimpl.ProvideService, wire.Bind(new(tag.Service), new(*tagimpl.Service)), authnimpl.ProvideService, authnimpl.ProvideIdentitySynchronizer, authnimpl.ProvideAuthnService, authnimpl.ProvideAuthnServiceAuthenticateOnly, authnimpl.ProvideRegistration, supportbundlesimpl.ProvideService, extsvcaccounts.ProvideExtSvcAccountsService, wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)), registry2.ProvideExtSvcRegistry, wire.Bind(new(extsvcauth.ExternalServiceRegistry), new(*registry2.Registry)), anonstore.ProvideAnonDBStore, wire.Bind(new(anonstore.AnonStore), new(*anonstore.AnonDBStore)), loggermw.Provide, slogadapter.Provide, signingkeysimpl.ProvideEmbeddedSigningKeysService, wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)), ssosettingsimpl.ProvideService, wire.Bind(new(ssosettings.Service), new(*ssosettingsimpl.Service)), idimpl.ProvideService, wire.Bind(new(auth.IDService), new(*idimpl.Service)), cloudmigrationimpl.ProvideService, userimpl.ProvideVerifier, connectors.ProvideOrgRoleMapper, wire.Bind(new(user.Verifier), new(*userimpl.Verifier)), authz.WireSet, metadata.ProvideSecureValueMetadataStorage, metadata.ProvideKeeperMetadataStorage, metadata.ProvideDecryptStorage, decrypt.ProvideDecryptAuthorizer, decrypt.ProvideDecryptAllowList, encryption.ProvideDataKeyStorage, encryption.ProvideEncryptedValueStorage, metadata.ProvideOutboxQueue, service11.ProvideSecureValueService, migrator2.NewWithEngine, database5.ProvideDatabase, wire.Bind(new(contracts.Database), new(*database5.Database)), manager4.ProvideEncryptionManager, encryption2.ProvideThirdPartyProviderMap, worker.ProvideWorkerConfig, worker.NewWorker, resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, apiserver.WireSet, apiregistry.WireSet, appregistry.WireSet) +var wireBasicSet = wire.NewSet(annotationsimpl.ProvideService, wire.Bind(new(annotations.Repository), new(*annotationsimpl.RepositoryImpl)), New, api.ProvideHTTPServer, query.ProvideService, wire.Bind(new(query.Service), new(*query.ServiceImpl)), bus.ProvideBus, wire.Bind(new(bus.Bus), new(*bus.InProcBus)), rendering.ProvideService, wire.Bind(new(rendering.Service), new(*rendering.RenderingService)), routing.ProvideRegister, wire.Bind(new(routing.RouteRegister), new(*routing.RouteRegisterImpl)), hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, bundleregistry.ProvideService, wire.Bind(new(supportbundles.Service), new(*bundleregistry.Service)), updatemanager.ProvideGrafanaService, updatemanager.ProvidePluginsService, service.ProvideService, wire.Bind(new(usagestats.Service), new(*service.UsageStats)), validator2.ProvideService, legacy.ProvideLegacyMigrator, pluginsintegration.WireSet, dashboards.ProvideFileStoreManager, wire.Bind(new(dashboards.FileStore), new(*dashboards.FileStoreManager)), cloudwatch.ProvideService, cloudmonitoring.ProvideService, azuremonitor.ProvideService, postgres.ProvideService, mysql.ProvideService, mssql.ProvideService, store.ProvideEntityEventsService, dualwrite.ProvideService, httpclientprovider.New, wire.Bind(new(httpclient.Provider), new(*httpclient2.Provider)), serverlock.ProvideService, annotationsimpl.ProvideCleanupService, wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)), cleanup.ProvideService, shorturlimpl.ProvideService, wire.Bind(new(shorturls.Service), new(*shorturlimpl.ShortURLService)), queryhistory.ProvideService, wire.Bind(new(queryhistory.Service), new(*queryhistory.QueryHistoryService)), correlations.ProvideService, wire.Bind(new(correlations.Service), new(*correlations.CorrelationsService)), quotaimpl.ProvideService, remotecache.ProvideService, wire.Bind(new(remotecache.CacheStorage), new(*remotecache.RemoteCache)), authinfoimpl.ProvideService, wire.Bind(new(login.AuthInfoService), new(*authinfoimpl.Service)), authinfoimpl.ProvideStore, datasourceproxy.ProvideService, sort.ProvideService, search2.ProvideService, searchV2.ProvideService, searchV2.ProvideSearchHTTPService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, pushhttp.ProvideService, contexthandler.ProvideService, service10.ProvideService, wire.Bind(new(service10.LDAP), new(*service10.LDAPImpl)), jwt.ProvideService, wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), store2.ProvideDBStore, image.ProvideDeleteExpiredService, ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), libraryelements.ProvideService, wire.Bind(new(libraryelements.Service), new(*libraryelements.LibraryElementService)), notifications.ProvideService, notifications.ProvideSmtpService, github.ProvideFactory, tracing.ProvideService, tracing.ProvideTracingConfig, wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), withOTelSet, testdatasource.ProvideService, api4.ProvideService, opentsdb.ProvideService, socialimpl.ProvideService, influxdb.ProvideService, wire.Bind(new(social.Service), new(*socialimpl.SocialService)), tempo.ProvideService, loki.ProvideService, graphite.ProvideService, prometheus.ProvideService, elasticsearch.ProvideService, pyroscope.ProvideService, parca.ProvideService, zipkin.ProvideService, jaeger.ProvideService, service7.ProvideCacheService, wire.Bind(new(datasources.CacheService), new(*service7.CacheServiceImpl)), service2.ProvideEncryptionService, wire.Bind(new(encryption.Internal), new(*service2.Service)), manager.ProvideSecretsService, wire.Bind(new(secrets.Service), new(*manager.SecretsService)), database.ProvideSecretsStore, wire.Bind(new(secrets.Store), new(*database.SecretsStoreImpl)), grafanads.ProvideService, wire.Bind(new(dashboardsnapshots.Store), new(*database4.DashboardSnapshotStore)), database4.ProvideStore, wire.Bind(new(dashboardsnapshots.Service), new(*service8.ServiceImpl)), service8.ProvideService, service7.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*service7.Service)), service7.ProvideLegacyDataSourceLookup, retriever.ProvideService, wire.Bind(new(serviceaccounts.ServiceAccountRetriever), new(*retriever.Service)), ossaccesscontrol.ProvideServiceAccountPermissions, wire.Bind(new(accesscontrol.ServiceAccountPermissionsService), new(*ossaccesscontrol.ServiceAccountPermissionsService)), manager2.ProvideServiceAccountsService, proxy.ProvideServiceAccountsProxy, wire.Bind(new(serviceaccounts.Service), new(*proxy.ServiceAccountsProxy)), expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, featuremgmt.ProvideOpenFeatureService, featuremgmt.ProvideStaticEvaluator, service5.ProvideDashboardServiceImpl, wire.Bind(new(dashboards2.PermissionsRegistrationService), new(*service5.DashboardServiceImpl)), service5.ProvideDashboardService, service5.ProvideDashboardProvisioningService, service5.ProvideDashboardPluginService, database2.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), folderimpl.ProvideDashboardFolderStore, wire.Bind(new(folder.FolderStore), new(*folderimpl.DashboardFolderStoreImpl)), service9.ProvideService, wire.Bind(new(dashboardimport.Service), new(*service9.ImportDashboardService)), service6.ProvideService, wire.Bind(new(plugindashboards.Service), new(*service6.Service)), service6.ProvideDashboardUpdater, sanitizer.ProvideService, kvstore2.ProvideService, avatar.ProvideAvatarCacheServer, statscollector.ProvideService, csrf.ProvideCSRFFilter, wire.Bind(new(csrf.Service), new(*csrf.CSRF)), ossaccesscontrol.ProvideTeamPermissions, wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)), ossaccesscontrol.ProvideFolderPermissions, wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)), ossaccesscontrol.ProvideDashboardPermissions, wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)), ossaccesscontrol.ProvideReceiverPermissionsService, wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)), starimpl.ProvideService, playlistimpl.ProvideService, apikeyimpl.ProvideService, dashverimpl.ProvideService, service3.ProvideService, wire.Bind(new(publicdashboards.Service), new(*service3.PublicDashboardServiceImpl)), database3.ProvideStore, wire.Bind(new(publicdashboards.Store), new(*database3.PublicDashboardStoreImpl)), metric.ProvideService, api2.ProvideApi, api3.ProvideApi, userimpl.ProvideService, orgimpl.ProvideService, orgimpl.ProvideDeletionService, statsimpl.ProvideService, grpccontext.ProvideContextHandler, grpcserver.ProvideHealthService, grpcserver.ProvideReflectionService, resolver.ProvideEntityReferenceResolver, teamimpl.ProvideService, teamapi.ProvideTeamAPI, tempuserimpl.ProvideService, loginattemptimpl.ProvideService, wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)), migrations2.ProvideDataSourceMigrationService, migrations2.ProvideSecretMigrationProvider, wire.Bind(new(migrations2.SecretMigrationProvider), new(*migrations2.SecretMigrationProviderImpl)), resourcepermissions.NewActionSetService, wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)), wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)), permreg.ProvidePermissionRegistry, acimpl.ProvideAccessControl, dualwrite2.ProvideZanzanaReconciler, navtreeimpl.ProvideService, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), tagimpl.ProvideService, wire.Bind(new(tag.Service), new(*tagimpl.Service)), authnimpl.ProvideService, authnimpl.ProvideIdentitySynchronizer, authnimpl.ProvideAuthnService, authnimpl.ProvideAuthnServiceAuthenticateOnly, authnimpl.ProvideRegistration, supportbundlesimpl.ProvideService, extsvcaccounts.ProvideExtSvcAccountsService, wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)), registry2.ProvideExtSvcRegistry, wire.Bind(new(extsvcauth.ExternalServiceRegistry), new(*registry2.Registry)), anonstore.ProvideAnonDBStore, wire.Bind(new(anonstore.AnonStore), new(*anonstore.AnonDBStore)), loggermw.Provide, slogadapter.Provide, signingkeysimpl.ProvideEmbeddedSigningKeysService, wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)), ssosettingsimpl.ProvideService, wire.Bind(new(ssosettings.Service), new(*ssosettingsimpl.Service)), idimpl.ProvideService, wire.Bind(new(auth.IDService), new(*idimpl.Service)), cloudmigrationimpl.ProvideService, userimpl.ProvideVerifier, connectors.ProvideOrgRoleMapper, wire.Bind(new(user.Verifier), new(*userimpl.Verifier)), authz.WireSet, metadata.ProvideSecureValueMetadataStorage, metadata.ProvideKeeperMetadataStorage, metadata.ProvideDecryptStorage, decrypt.ProvideDecryptAuthorizer, decrypt.ProvideDecryptAllowList, encryption2.ProvideDataKeyStorage, encryption2.ProvideEncryptedValueStorage, service11.ProvideSecureValueService, migrator2.NewWithEngine, database5.ProvideDatabase, wire.Bind(new(contracts.Database), new(*database5.Database)), manager4.ProvideEncryptionManager, encryption3.ProvideThirdPartyProviderMap, resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, apiserver.WireSet, apiregistry.WireSet, appregistry.WireSet) var wireSet = wire.NewSet( wireBasicSet, metrics.WireSet, sqlstore.ProvideService, metrics2.ProvideService, wire.Bind(new(notifications.Service), new(*notifications.NotificationService)), wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationService)), wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationService)), wire.Bind(new(db.DB), new(*sqlstore.SQLStore)), prefimpl.ProvideService, oauthtoken.ProvideService, wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)), wire.Bind(new(cleanup.AlertRuleService), new(*store2.DBstore)), diff --git a/pkg/server/wireexts_oss.go b/pkg/server/wireexts_oss.go index 0f0dd034983..5a1193c8592 100644 --- a/pkg/server/wireexts_oss.go +++ b/pkg/server/wireexts_oss.go @@ -8,6 +8,7 @@ import ( "github.com/google/wire" "github.com/grafana/grafana/pkg/infra/metrics" + "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/manager" "github.com/grafana/grafana/pkg/registry" @@ -165,6 +166,10 @@ var wireExtsBaseCLISet = wire.NewSet( var wireExtsModuleServerSet = wire.NewSet( NewModule, wireExtsBaseCLISet, + // Tracing + tracing.ProvideTracingConfig, + tracing.ProvideService, + wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), // Unified storage resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, diff --git a/pkg/services/accesscontrol/actest/store_mock.go b/pkg/services/accesscontrol/actest/store_mock.go index ea2a48fe560..84e5bef1eb7 100644 --- a/pkg/services/accesscontrol/actest/store_mock.go +++ b/pkg/services/accesscontrol/actest/store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package actest diff --git a/pkg/services/annotations/annotations_repository_mock.go b/pkg/services/annotations/annotations_repository_mock.go index 242834ced2b..f9cab3f896e 100644 --- a/pkg/services/annotations/annotations_repository_mock.go +++ b/pkg/services/annotations/annotations_repository_mock.go @@ -1,10 +1,9 @@ -// Code generated by mockery v2.12.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package annotations import ( context "context" - testing "testing" mock "github.com/stretchr/testify/mock" ) @@ -18,6 +17,10 @@ type FakeAnnotationsRepo struct { func (_m *FakeAnnotationsRepo) Delete(ctx context.Context, params *DeleteParams) error { ret := _m.Called(ctx, params) + if len(ret) == 0 { + panic("no return value specified for Delete") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *DeleteParams) error); ok { r0 = rf(ctx, params) @@ -32,7 +35,15 @@ func (_m *FakeAnnotationsRepo) Delete(ctx context.Context, params *DeleteParams) func (_m *FakeAnnotationsRepo) Find(ctx context.Context, query *ItemQuery) ([]*ItemDTO, error) { ret := _m.Called(ctx, query) + if len(ret) == 0 { + panic("no return value specified for Find") + } + var r0 []*ItemDTO + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *ItemQuery) ([]*ItemDTO, error)); ok { + return rf(ctx, query) + } if rf, ok := ret.Get(0).(func(context.Context, *ItemQuery) []*ItemDTO); ok { r0 = rf(ctx, query) } else { @@ -41,7 +52,6 @@ func (_m *FakeAnnotationsRepo) Find(ctx context.Context, query *ItemQuery) ([]*I } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *ItemQuery) error); ok { r1 = rf(ctx, query) } else { @@ -55,14 +65,21 @@ func (_m *FakeAnnotationsRepo) Find(ctx context.Context, query *ItemQuery) ([]*I func (_m *FakeAnnotationsRepo) FindTags(ctx context.Context, query *TagsQuery) (FindTagsResult, error) { ret := _m.Called(ctx, query) + if len(ret) == 0 { + panic("no return value specified for FindTags") + } + var r0 FindTagsResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *TagsQuery) (FindTagsResult, error)); ok { + return rf(ctx, query) + } if rf, ok := ret.Get(0).(func(context.Context, *TagsQuery) FindTagsResult); ok { r0 = rf(ctx, query) } else { r0 = ret.Get(0).(FindTagsResult) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *TagsQuery) error); ok { r1 = rf(ctx, query) } else { @@ -76,6 +93,10 @@ func (_m *FakeAnnotationsRepo) FindTags(ctx context.Context, query *TagsQuery) ( func (_m *FakeAnnotationsRepo) Save(ctx context.Context, item *Item) error { ret := _m.Called(ctx, item) + if len(ret) == 0 { + panic("no return value specified for Save") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *Item) error); ok { r0 = rf(ctx, item) @@ -90,6 +111,10 @@ func (_m *FakeAnnotationsRepo) Save(ctx context.Context, item *Item) error { func (_m *FakeAnnotationsRepo) SaveMany(ctx context.Context, items []Item) error { ret := _m.Called(ctx, items) + if len(ret) == 0 { + panic("no return value specified for SaveMany") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, []Item) error); ok { r0 = rf(ctx, items) @@ -104,6 +129,10 @@ func (_m *FakeAnnotationsRepo) SaveMany(ctx context.Context, items []Item) error func (_m *FakeAnnotationsRepo) Update(ctx context.Context, item *Item) error { ret := _m.Called(ctx, item) + if len(ret) == 0 { + panic("no return value specified for Update") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *Item) error); ok { r0 = rf(ctx, item) @@ -114,8 +143,12 @@ func (_m *FakeAnnotationsRepo) Update(ctx context.Context, item *Item) error { return r0 } -// NewFakeAnnotationsRepo creates a new instance of FakeAnnotationsRepo. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. -func NewFakeAnnotationsRepo(t testing.TB) *FakeAnnotationsRepo { +// NewFakeAnnotationsRepo creates a new instance of FakeAnnotationsRepo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFakeAnnotationsRepo(t interface { + mock.TestingT + Cleanup(func()) +}) *FakeAnnotationsRepo { mock := &FakeAnnotationsRepo{} mock.Mock.Test(t) diff --git a/pkg/services/auth/authtest/auth_token_service_mock.go b/pkg/services/auth/authtest/auth_token_service_mock.go index 744ef1fe0b0..11ea10a4d7b 100644 --- a/pkg/services/auth/authtest/auth_token_service_mock.go +++ b/pkg/services/auth/authtest/auth_token_service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package authtest diff --git a/pkg/services/auth/authtest/external_session_store_mock.go b/pkg/services/auth/authtest/external_session_store_mock.go index 10894e67444..e4f727e14ec 100644 --- a/pkg/services/auth/authtest/external_session_store_mock.go +++ b/pkg/services/auth/authtest/external_session_store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package authtest diff --git a/pkg/services/auth/idtest/mock.go b/pkg/services/auth/idtest/mock.go index cb9aeadf316..9837c421cd8 100644 --- a/pkg/services/auth/idtest/mock.go +++ b/pkg/services/auth/idtest/mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package idtest diff --git a/pkg/services/cloudmigration/api/dtos.go b/pkg/services/cloudmigration/api/dtos.go index a9fe7ce855b..801480b910b 100644 --- a/pkg/services/cloudmigration/api/dtos.go +++ b/pkg/services/cloudmigration/api/dtos.go @@ -150,17 +150,19 @@ const ( type ItemErrorCode string const ( - ErrDatasourceNameConflict ItemErrorCode = "DATASOURCE_NAME_CONFLICT" - ErrDatasourceInvalidURL ItemErrorCode = "DATASOURCE_INVALID_URL" - ErrDatasourceAlreadyManaged ItemErrorCode = "DATASOURCE_ALREADY_MANAGED" - ErrFolderNameConflict ItemErrorCode = "FOLDER_NAME_CONFLICT" - ErrDashboardAlreadyManaged ItemErrorCode = "DASHBOARD_ALREADY_MANAGED" - ErrLibraryElementNameConflict ItemErrorCode = "LIBRARY_ELEMENT_NAME_CONFLICT" - ErrUnsupportedDataType ItemErrorCode = "UNSUPPORTED_DATA_TYPE" - ErrResourceConflict ItemErrorCode = "RESOURCE_CONFLICT" - ErrUnexpectedStatus ItemErrorCode = "UNEXPECTED_STATUS_CODE" - ErrInternalServiceError ItemErrorCode = "INTERNAL_SERVICE_ERROR" - ErrGeneric ItemErrorCode = "GENERIC_ERROR" + ErrAlertRulesQuotaReached ItemErrorCode = "ALERT_RULES_QUOTA_REACHED" + ErrAlertRulesGroupQuotaReached ItemErrorCode = "ALERT_RULES_GROUP_QUOTA_REACHED" + ErrDatasourceNameConflict ItemErrorCode = "DATASOURCE_NAME_CONFLICT" + ErrDatasourceInvalidURL ItemErrorCode = "DATASOURCE_INVALID_URL" + ErrDatasourceAlreadyManaged ItemErrorCode = "DATASOURCE_ALREADY_MANAGED" + ErrFolderNameConflict ItemErrorCode = "FOLDER_NAME_CONFLICT" + ErrDashboardAlreadyManaged ItemErrorCode = "DASHBOARD_ALREADY_MANAGED" + ErrLibraryElementNameConflict ItemErrorCode = "LIBRARY_ELEMENT_NAME_CONFLICT" + ErrUnsupportedDataType ItemErrorCode = "UNSUPPORTED_DATA_TYPE" + ErrResourceConflict ItemErrorCode = "RESOURCE_CONFLICT" + ErrUnexpectedStatus ItemErrorCode = "UNEXPECTED_STATUS_CODE" + ErrInternalServiceError ItemErrorCode = "INTERNAL_SERVICE_ERROR" + ErrGeneric ItemErrorCode = "GENERIC_ERROR" ) // swagger:parameters getCloudMigrationRun diff --git a/pkg/services/cloudmigration/model.go b/pkg/services/cloudmigration/model.go index 41d27e02f94..a01a33c62d4 100644 --- a/pkg/services/cloudmigration/model.go +++ b/pkg/services/cloudmigration/model.go @@ -110,17 +110,19 @@ const ( type ResourceErrorCode string const ( - ErrDatasourceNameConflict ResourceErrorCode = "DATASOURCE_NAME_CONFLICT" - ErrDatasourceInvalidURL ResourceErrorCode = "DATASOURCE_INVALID_URL" - ErrDatasourceAlreadyManaged ResourceErrorCode = "DATASOURCE_ALREADY_MANAGED" - ErrFolderNameConflict ResourceErrorCode = "FOLDER_NAME_CONFLICT" - ErrDashboardAlreadyManaged ResourceErrorCode = "DASHBOARD_ALREADY_MANAGED" - ErrLibraryElementNameConflict ResourceErrorCode = "LIBRARY_ELEMENT_NAME_CONFLICT" - ErrUnsupportedDataType ResourceErrorCode = "UNSUPPORTED_DATA_TYPE" - ErrResourceConflict ResourceErrorCode = "RESOURCE_CONFLICT" - ErrUnexpectedStatus ResourceErrorCode = "UNEXPECTED_STATUS_CODE" - ErrInternalServiceError ResourceErrorCode = "INTERNAL_SERVICE_ERROR" - ErrGeneric ResourceErrorCode = "GENERIC_ERROR" + ErrAlertRulesQuotaReached ResourceErrorCode = "ALERT_RULES_QUOTA_REACHED" + ErrAlertRulesGroupQuotaReached ResourceErrorCode = "ALERT_RULES_GROUP_QUOTA_REACHED" + ErrDatasourceNameConflict ResourceErrorCode = "DATASOURCE_NAME_CONFLICT" + ErrDatasourceInvalidURL ResourceErrorCode = "DATASOURCE_INVALID_URL" + ErrDatasourceAlreadyManaged ResourceErrorCode = "DATASOURCE_ALREADY_MANAGED" + ErrFolderNameConflict ResourceErrorCode = "FOLDER_NAME_CONFLICT" + ErrDashboardAlreadyManaged ResourceErrorCode = "DASHBOARD_ALREADY_MANAGED" + ErrLibraryElementNameConflict ResourceErrorCode = "LIBRARY_ELEMENT_NAME_CONFLICT" + ErrUnsupportedDataType ResourceErrorCode = "UNSUPPORTED_DATA_TYPE" + ErrResourceConflict ResourceErrorCode = "RESOURCE_CONFLICT" + ErrUnexpectedStatus ResourceErrorCode = "UNEXPECTED_STATUS_CODE" + ErrInternalServiceError ResourceErrorCode = "INTERNAL_SERVICE_ERROR" + ErrGeneric ResourceErrorCode = "GENERIC_ERROR" ) type SnapshotResourceStats struct { diff --git a/pkg/services/dashboards/dashboard_provisioning_mock.go b/pkg/services/dashboards/dashboard_provisioning_mock.go index 4b7863b27e6..016a20528f3 100644 --- a/pkg/services/dashboards/dashboard_provisioning_mock.go +++ b/pkg/services/dashboards/dashboard_provisioning_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package dashboards diff --git a/pkg/services/dashboards/dashboard_service_mock.go b/pkg/services/dashboards/dashboard_service_mock.go index cba4d23820d..d20a9525622 100644 --- a/pkg/services/dashboards/dashboard_service_mock.go +++ b/pkg/services/dashboards/dashboard_service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package dashboards @@ -94,36 +94,6 @@ func (_m *FakeDashboardService) CountDashboardsInOrg(ctx context.Context, orgID return r0, r1 } -// GetDashboardsByLibraryPanelUID provides a mock function with given fields: ctx, libraryPanelUID, orgID -func (_m *FakeDashboardService) GetDashboardsByLibraryPanelUID(ctx context.Context, libraryPanelUID string, orgID int64) ([]*DashboardRef, error) { - ret := _m.Called(ctx, libraryPanelUID, orgID) - - if len(ret) == 0 { - panic("no return value specified for GetDashboardsByLibraryPanelUID") - } - - var r0 []*DashboardRef - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, int64) ([]*DashboardRef, error)); ok { - return rf(ctx, libraryPanelUID, orgID) - } - if rf, ok := ret.Get(0).(func(context.Context, string, int64) []*DashboardRef); ok { - r0 = rf(ctx, libraryPanelUID, orgID) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*DashboardRef) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok { - r1 = rf(ctx, libraryPanelUID, orgID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // CountInFolders provides a mock function with given fields: ctx, orgID, folderUIDs, user func (_m *FakeDashboardService) CountInFolders(ctx context.Context, orgID int64, folderUIDs []string, user identity.Requester) (int64, error) { ret := _m.Called(ctx, orgID, folderUIDs, user) @@ -368,6 +338,36 @@ func (_m *FakeDashboardService) GetDashboards(ctx context.Context, query *GetDas return r0, r1 } +// GetDashboardsByLibraryPanelUID provides a mock function with given fields: ctx, libraryPanelUID, orgID +func (_m *FakeDashboardService) GetDashboardsByLibraryPanelUID(ctx context.Context, libraryPanelUID string, orgID int64) ([]*DashboardRef, error) { + ret := _m.Called(ctx, libraryPanelUID, orgID) + + if len(ret) == 0 { + panic("no return value specified for GetDashboardsByLibraryPanelUID") + } + + var r0 []*DashboardRef + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, int64) ([]*DashboardRef, error)); ok { + return rf(ctx, libraryPanelUID, orgID) + } + if rf, ok := ret.Get(0).(func(context.Context, string, int64) []*DashboardRef); ok { + r0 = rf(ctx, libraryPanelUID, orgID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*DashboardRef) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok { + r1 = rf(ctx, libraryPanelUID, orgID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ImportDashboard provides a mock function with given fields: ctx, dto func (_m *FakeDashboardService) ImportDashboard(ctx context.Context, dto *SaveDashboardDTO) (*Dashboard, error) { ret := _m.Called(ctx, dto) diff --git a/pkg/services/dashboards/store_mock.go b/pkg/services/dashboards/store_mock.go index 1a0b46c82cd..5b208c34b7f 100644 --- a/pkg/services/dashboards/store_mock.go +++ b/pkg/services/dashboards/store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package dashboards @@ -370,6 +370,36 @@ func (_m *FakeDashboardStore) GetDashboards(ctx context.Context, query *GetDashb return r0, r1 } +// GetDashboardsByLibraryPanelUID provides a mock function with given fields: ctx, libraryPanelUID, orgID +func (_m *FakeDashboardStore) GetDashboardsByLibraryPanelUID(ctx context.Context, libraryPanelUID string, orgID int64) ([]*DashboardRef, error) { + ret := _m.Called(ctx, libraryPanelUID, orgID) + + if len(ret) == 0 { + panic("no return value specified for GetDashboardsByLibraryPanelUID") + } + + var r0 []*DashboardRef + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, int64) ([]*DashboardRef, error)); ok { + return rf(ctx, libraryPanelUID, orgID) + } + if rf, ok := ret.Get(0).(func(context.Context, string, int64) []*DashboardRef); ok { + r0 = rf(ctx, libraryPanelUID, orgID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*DashboardRef) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok { + r1 = rf(ctx, libraryPanelUID, orgID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetDashboardsByPluginID provides a mock function with given fields: ctx, query func (_m *FakeDashboardStore) GetDashboardsByPluginID(ctx context.Context, query *GetDashboardsByPluginIDQuery) ([]*Dashboard, error) { ret := _m.Called(ctx, query) @@ -628,36 +658,6 @@ func (_m *FakeDashboardStore) UnprovisionDashboard(ctx context.Context, id int64 return r0 } -// GetDashboardsByLibraryPanelUID provides a mock function with given fields: ctx, libraryPanelUID, orgID -func (_m *FakeDashboardStore) GetDashboardsByLibraryPanelUID(ctx context.Context, libraryPanelUID string, orgID int64) ([]*DashboardRef, error) { - ret := _m.Called(ctx, libraryPanelUID, orgID) - - if len(ret) == 0 { - panic("no return value specified for GetDashboardsByLibraryPanelUID") - } - - var r0 []*DashboardRef - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, int64) ([]*DashboardRef, error)); ok { - return rf(ctx, libraryPanelUID, orgID) - } - if rf, ok := ret.Get(0).(func(context.Context, string, int64) []*DashboardRef); ok { - r0 = rf(ctx, libraryPanelUID, orgID) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*DashboardRef) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok { - r1 = rf(ctx, libraryPanelUID, orgID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // ValidateDashboardBeforeSave provides a mock function with given fields: ctx, dashboard, overwrite func (_m *FakeDashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashboard *Dashboard, overwrite bool) (bool, error) { ret := _m.Called(ctx, dashboard, overwrite) diff --git a/pkg/services/dashboardsnapshots/service_mock.go b/pkg/services/dashboardsnapshots/service_mock.go index 4d3ef270349..a323aa5d7b2 100644 --- a/pkg/services/dashboardsnapshots/service_mock.go +++ b/pkg/services/dashboardsnapshots/service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.34.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package dashboardsnapshots @@ -17,6 +17,10 @@ type MockService struct { func (_m *MockService) CreateDashboardSnapshot(_a0 context.Context, _a1 *CreateDashboardSnapshotCommand) (*DashboardSnapshot, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CreateDashboardSnapshot") + } + var r0 *DashboardSnapshot var r1 error if rf, ok := ret.Get(0).(func(context.Context, *CreateDashboardSnapshotCommand) (*DashboardSnapshot, error)); ok { @@ -43,6 +47,10 @@ func (_m *MockService) CreateDashboardSnapshot(_a0 context.Context, _a1 *CreateD func (_m *MockService) DeleteDashboardSnapshot(_a0 context.Context, _a1 *DeleteDashboardSnapshotCommand) error { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DeleteDashboardSnapshot") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *DeleteDashboardSnapshotCommand) error); ok { r0 = rf(_a0, _a1) @@ -57,6 +65,10 @@ func (_m *MockService) DeleteDashboardSnapshot(_a0 context.Context, _a1 *DeleteD func (_m *MockService) DeleteExpiredSnapshots(_a0 context.Context, _a1 *DeleteExpiredSnapshotsCommand) error { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DeleteExpiredSnapshots") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *DeleteExpiredSnapshotsCommand) error); ok { r0 = rf(_a0, _a1) @@ -71,6 +83,10 @@ func (_m *MockService) DeleteExpiredSnapshots(_a0 context.Context, _a1 *DeleteEx func (_m *MockService) GetDashboardSnapshot(_a0 context.Context, _a1 *GetDashboardSnapshotQuery) (*DashboardSnapshot, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for GetDashboardSnapshot") + } + var r0 *DashboardSnapshot var r1 error if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardSnapshotQuery) (*DashboardSnapshot, error)); ok { @@ -97,6 +113,10 @@ func (_m *MockService) GetDashboardSnapshot(_a0 context.Context, _a1 *GetDashboa func (_m *MockService) SearchDashboardSnapshots(_a0 context.Context, _a1 *GetDashboardSnapshotsQuery) (DashboardSnapshotsList, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for SearchDashboardSnapshots") + } + var r0 DashboardSnapshotsList var r1 error if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardSnapshotsQuery) (DashboardSnapshotsList, error)); ok { @@ -123,6 +143,10 @@ func (_m *MockService) SearchDashboardSnapshots(_a0 context.Context, _a1 *GetDas func (_m *MockService) ValidateDashboardExists(_a0 context.Context, _a1 int64, _a2 string) error { ret := _m.Called(_a0, _a1, _a2) + if len(ret) == 0 { + panic("no return value specified for ValidateDashboardExists") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok { r0 = rf(_a0, _a1, _a2) diff --git a/pkg/services/extsvcauth/tests/extsvcregmock.go b/pkg/services/extsvcauth/tests/extsvcregmock.go index 82b0a278108..7ef96c6c36e 100644 --- a/pkg/services/extsvcauth/tests/extsvcregmock.go +++ b/pkg/services/extsvcauth/tests/extsvcregmock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.35.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package tests @@ -18,6 +18,10 @@ type ExternalServiceRegistryMock struct { func (_m *ExternalServiceRegistryMock) GetExternalServiceNames(ctx context.Context) ([]string, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for GetExternalServiceNames") + } + var r0 []string var r1 error if rf, ok := ret.Get(0).(func(context.Context) ([]string, error)); ok { @@ -44,6 +48,10 @@ func (_m *ExternalServiceRegistryMock) GetExternalServiceNames(ctx context.Conte func (_m *ExternalServiceRegistryMock) HasExternalService(ctx context.Context, name string) (bool, error) { ret := _m.Called(ctx, name) + if len(ret) == 0 { + panic("no return value specified for HasExternalService") + } + var r0 bool var r1 error if rf, ok := ret.Get(0).(func(context.Context, string) (bool, error)); ok { @@ -68,6 +76,10 @@ func (_m *ExternalServiceRegistryMock) HasExternalService(ctx context.Context, n func (_m *ExternalServiceRegistryMock) RemoveExternalService(ctx context.Context, name string) error { ret := _m.Called(ctx, name) + if len(ret) == 0 { + panic("no return value specified for RemoveExternalService") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { r0 = rf(ctx, name) @@ -82,6 +94,10 @@ func (_m *ExternalServiceRegistryMock) RemoveExternalService(ctx context.Context func (_m *ExternalServiceRegistryMock) SaveExternalService(ctx context.Context, cmd *extsvcauth.ExternalServiceRegistration) (*extsvcauth.ExternalService, error) { ret := _m.Called(ctx, cmd) + if len(ret) == 0 { + panic("no return value specified for SaveExternalService") + } + var r0 *extsvcauth.ExternalService var r1 error if rf, ok := ret.Get(0).(func(context.Context, *extsvcauth.ExternalServiceRegistration) (*extsvcauth.ExternalService, error)); ok { diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index cb275abd33a..fe4c102bfc4 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1714,7 +1714,7 @@ var ( Description: "Use fixed-width numbers globally in the UI", Stage: FeatureStageGeneralAvailability, Owner: grafanaFrontendPlatformSquad, - Expression: "true", + Expression: "false", }, { Name: "newInfluxDSConfigPageDesign", diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 004b9c5e01b..1735b3c01b0 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -2943,17 +2943,17 @@ { "metadata": { "name": "tabularNumbers", - "resourceVersion": "1750754828442", + "resourceVersion": "1752078306230", "creationTimestamp": "2025-06-24T11:52:03Z", "annotations": { - "grafana.app/updatedTimestamp": "2025-06-24 08:47:08.442537461 +0000 UTC" + "grafana.app/updatedTimestamp": "2025-07-09 16:25:06.230922635 +0000 UTC" } }, "spec": { "description": "Use fixed-width numbers globally in the UI", "stage": "GA", "codeowner": "@grafana/grafana-frontend-platform", - "expression": "true" + "expression": "false" } }, { diff --git a/pkg/services/folder/foldertest/folder_store_mock.go b/pkg/services/folder/foldertest/folder_store_mock.go index 816dda5a4bc..1a88e59c4e0 100644 --- a/pkg/services/folder/foldertest/folder_store_mock.go +++ b/pkg/services/folder/foldertest/folder_store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.32.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package foldertest @@ -14,10 +14,44 @@ type FakeFolderStore struct { mock.Mock } +// Get provides a mock function with given fields: ctx, q +func (_m *FakeFolderStore) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.Folder, error) { + ret := _m.Called(ctx, q) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 *folder.Folder + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) (*folder.Folder, error)); ok { + return rf(ctx, q) + } + if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) *folder.Folder); ok { + r0 = rf(ctx, q) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*folder.Folder) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, folder.GetFolderQuery) error); ok { + r1 = rf(ctx, q) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetFolderByID provides a mock function with given fields: ctx, orgID, id func (_m *FakeFolderStore) GetFolderByID(ctx context.Context, orgID int64, id int64) (*folder.Folder, error) { ret := _m.Called(ctx, orgID, id) + if len(ret) == 0 { + panic("no return value specified for GetFolderByID") + } + var r0 *folder.Folder var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, int64) (*folder.Folder, error)); ok { @@ -40,36 +74,14 @@ func (_m *FakeFolderStore) GetFolderByID(ctx context.Context, orgID int64, id in return r0, r1 } -// Get provides a mock function with given fields: ctx, query -func (_m *FakeFolderStore) Get(ctx context.Context, query folder.GetFolderQuery) (*folder.Folder, error) { - ret := _m.Called(ctx, query) - - var r0 *folder.Folder - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) (*folder.Folder, error)); ok { - return rf(ctx, query) - } - if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) *folder.Folder); ok { - r0 = rf(ctx, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*folder.Folder) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, folder.GetFolderQuery) error); ok { - r1 = rf(ctx, query) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // GetFolderByUID provides a mock function with given fields: ctx, orgID, uid func (_m *FakeFolderStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*folder.Folder, error) { ret := _m.Called(ctx, orgID, uid) + if len(ret) == 0 { + panic("no return value specified for GetFolderByUID") + } + var r0 *folder.Folder var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*folder.Folder, error)); ok { @@ -96,6 +108,10 @@ func (_m *FakeFolderStore) GetFolderByUID(ctx context.Context, orgID int64, uid func (_m *FakeFolderStore) GetFolders(ctx context.Context, orgID int64, uids []string) (map[string]*folder.Folder, error) { ret := _m.Called(ctx, orgID, uids) + if len(ret) == 0 { + panic("no return value specified for GetFolders") + } + var r0 map[string]*folder.Folder var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, []string) (map[string]*folder.Folder, error)); ok { @@ -118,29 +134,6 @@ func (_m *FakeFolderStore) GetFolders(ctx context.Context, orgID int64, uids []s return r0, r1 } -func (_m *FakeFolderStore) CountInOrg(ctx context.Context, orgID int64) (int64, error) { - ret := _m.Called(ctx, orgID) - - var r0 int64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64) (int64, error)); ok { - return rf(ctx, orgID) - } - if rf, ok := ret.Get(0).(func(context.Context, int64) int64); ok { - r0 = rf(ctx, orgID) - } else { - r0 = ret.Get(0).(int64) - } - - if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { - r1 = rf(ctx, orgID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // NewFakeFolderStore creates a new instance of FakeFolderStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewFakeFolderStore(t interface { diff --git a/pkg/services/frontend/frontend_service.go b/pkg/services/frontend/frontend_service.go index 81b67859ec2..b79876dd4c5 100644 --- a/pkg/services/frontend/frontend_service.go +++ b/pkg/services/frontend/frontend_service.go @@ -8,6 +8,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" + "go.opentelemetry.io/otel" "github.com/grafana/dskit/services" "github.com/grafana/grafana/pkg/infra/log" @@ -15,6 +16,8 @@ import ( "github.com/grafana/grafana/pkg/setting" ) +var tracer = otel.Tracer("github.com/grafana/grafana/pkg/services/frontend") + type frontendService struct { *services.BasicService cfg *setting.Cfg diff --git a/pkg/services/frontend/index.go b/pkg/services/frontend/index.go index f7fdf617b35..ff18e6e5b7d 100644 --- a/pkg/services/frontend/index.go +++ b/pkg/services/frontend/index.go @@ -79,6 +79,9 @@ func NewIndexProvider(cfg *setting.Cfg, license licensing.Licensing) (*IndexProv } func (p *IndexProvider) HandleRequest(writer http.ResponseWriter, request *http.Request) { + _, span := tracer.Start(request.Context(), "frontend.index.HandleRequest") + defer span.End() + if request.Method != "GET" { writer.WriteHeader(http.StatusMethodNotAllowed) return diff --git a/pkg/services/ngalert/eval/eval_mocks/ConditionEvaluator.go b/pkg/services/ngalert/eval/eval_mocks/ConditionEvaluator.go index 4400a37dfae..1a345e7be84 100644 --- a/pkg/services/ngalert/eval/eval_mocks/ConditionEvaluator.go +++ b/pkg/services/ngalert/eval/eval_mocks/ConditionEvaluator.go @@ -1,15 +1,17 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package eval_mocks import ( context "context" - time "time" backend "github.com/grafana/grafana-plugin-sdk-go/backend" - mock "github.com/stretchr/testify/mock" eval "github.com/grafana/grafana/pkg/services/ngalert/eval" + + mock "github.com/stretchr/testify/mock" + + time "time" ) // ConditionEvaluatorMock is an autogenerated mock type for the ConditionEvaluator type @@ -29,7 +31,15 @@ func (_m *ConditionEvaluatorMock) EXPECT() *ConditionEvaluatorMock_Expecter { func (_m *ConditionEvaluatorMock) Evaluate(ctx context.Context, now time.Time) (eval.Results, error) { ret := _m.Called(ctx, now) + if len(ret) == 0 { + panic("no return value specified for Evaluate") + } + var r0 eval.Results + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, time.Time) (eval.Results, error)); ok { + return rf(ctx, now) + } if rf, ok := ret.Get(0).(func(context.Context, time.Time) eval.Results); ok { r0 = rf(ctx, now) } else { @@ -38,7 +48,6 @@ func (_m *ConditionEvaluatorMock) Evaluate(ctx context.Context, now time.Time) ( } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, time.Time) error); ok { r1 = rf(ctx, now) } else { @@ -56,7 +65,7 @@ type ConditionEvaluatorMock_Evaluate_Call struct { // Evaluate is a helper method to define mock.On call // - ctx context.Context // - now time.Time -func (_e *ConditionEvaluatorMock_Expecter) Evaluate(ctx any, now any) *ConditionEvaluatorMock_Evaluate_Call { +func (_e *ConditionEvaluatorMock_Expecter) Evaluate(ctx interface{}, now interface{}) *ConditionEvaluatorMock_Evaluate_Call { return &ConditionEvaluatorMock_Evaluate_Call{Call: _e.mock.On("Evaluate", ctx, now)} } @@ -72,11 +81,24 @@ func (_c *ConditionEvaluatorMock_Evaluate_Call) Return(_a0 eval.Results, _a1 err return _c } +func (_c *ConditionEvaluatorMock_Evaluate_Call) RunAndReturn(run func(context.Context, time.Time) (eval.Results, error)) *ConditionEvaluatorMock_Evaluate_Call { + _c.Call.Return(run) + return _c +} + // EvaluateRaw provides a mock function with given fields: ctx, now func (_m *ConditionEvaluatorMock) EvaluateRaw(ctx context.Context, now time.Time) (*backend.QueryDataResponse, error) { ret := _m.Called(ctx, now) + if len(ret) == 0 { + panic("no return value specified for EvaluateRaw") + } + var r0 *backend.QueryDataResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, time.Time) (*backend.QueryDataResponse, error)); ok { + return rf(ctx, now) + } if rf, ok := ret.Get(0).(func(context.Context, time.Time) *backend.QueryDataResponse); ok { r0 = rf(ctx, now) } else { @@ -85,7 +107,6 @@ func (_m *ConditionEvaluatorMock) EvaluateRaw(ctx context.Context, now time.Time } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, time.Time) error); ok { r1 = rf(ctx, now) } else { @@ -103,7 +124,7 @@ type ConditionEvaluatorMock_EvaluateRaw_Call struct { // EvaluateRaw is a helper method to define mock.On call // - ctx context.Context // - now time.Time -func (_e *ConditionEvaluatorMock_Expecter) EvaluateRaw(ctx any, now any) *ConditionEvaluatorMock_EvaluateRaw_Call { +func (_e *ConditionEvaluatorMock_Expecter) EvaluateRaw(ctx interface{}, now interface{}) *ConditionEvaluatorMock_EvaluateRaw_Call { return &ConditionEvaluatorMock_EvaluateRaw_Call{Call: _e.mock.On("EvaluateRaw", ctx, now)} } @@ -119,13 +140,17 @@ func (_c *ConditionEvaluatorMock_EvaluateRaw_Call) Return(resp *backend.QueryDat return _c } -type mockConstructorTestingTNewConditionEvaluatorMock interface { - mock.TestingT - Cleanup(func()) +func (_c *ConditionEvaluatorMock_EvaluateRaw_Call) RunAndReturn(run func(context.Context, time.Time) (*backend.QueryDataResponse, error)) *ConditionEvaluatorMock_EvaluateRaw_Call { + _c.Call.Return(run) + return _c } // NewConditionEvaluatorMock creates a new instance of ConditionEvaluatorMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewConditionEvaluatorMock(t mockConstructorTestingTNewConditionEvaluatorMock) *ConditionEvaluatorMock { +// The first argument is typically a *testing.T value. +func NewConditionEvaluatorMock(t interface { + mock.TestingT + Cleanup(func()) +}) *ConditionEvaluatorMock { mock := &ConditionEvaluatorMock{} mock.Mock.Test(t) diff --git a/pkg/services/ngalert/notifier/alertmanager_mock/Alertmanager.go b/pkg/services/ngalert/notifier/alertmanager_mock/Alertmanager.go index a3419fdc508..20f4e14d0ab 100644 --- a/pkg/services/ngalert/notifier/alertmanager_mock/Alertmanager.go +++ b/pkg/services/ngalert/notifier/alertmanager_mock/Alertmanager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.44.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package alertmanager_mock @@ -585,7 +585,7 @@ func (_c *AlertmanagerMock_PutAlerts_Call) RunAndReturn(run func(context.Context return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *AlertmanagerMock) Ready() bool { ret := _m.Called() @@ -781,7 +781,7 @@ func (_c *AlertmanagerMock_SilenceState_Call) RunAndReturn(run func(context.Cont return _c } -// StopAndWait provides a mock function with given fields: +// StopAndWait provides a mock function with no fields func (_m *AlertmanagerMock) StopAndWait() { _m.Called() } @@ -809,7 +809,7 @@ func (_c *AlertmanagerMock_StopAndWait_Call) Return() *AlertmanagerMock_StopAndW } func (_c *AlertmanagerMock_StopAndWait_Call) RunAndReturn(run func()) *AlertmanagerMock_StopAndWait_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/pkg/services/ngalert/notifier/legacy_storage/persist_mock.go b/pkg/services/ngalert/notifier/legacy_storage/persist_mock.go index 03b5f825775..03b7b893757 100644 --- a/pkg/services/ngalert/notifier/legacy_storage/persist_mock.go +++ b/pkg/services/ngalert/notifier/legacy_storage/persist_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.44.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package legacy_storage diff --git a/pkg/services/ngalert/provisioning/provisioning_store_mock.go b/pkg/services/ngalert/provisioning/provisioning_store_mock.go index 65df0062a8a..31cc77e26a6 100644 --- a/pkg/services/ngalert/provisioning/provisioning_store_mock.go +++ b/pkg/services/ngalert/provisioning/provisioning_store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.34.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package provisioning @@ -26,6 +26,10 @@ func (_m *MockProvisioningStore) EXPECT() *MockProvisioningStore_Expecter { func (_m *MockProvisioningStore) DeleteProvenance(ctx context.Context, o models.Provisionable, org int64) error { ret := _m.Called(ctx, o, org) + if len(ret) == 0 { + panic("no return value specified for DeleteProvenance") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, models.Provisionable, int64) error); ok { r0 = rf(ctx, o, org) @@ -70,6 +74,10 @@ func (_c *MockProvisioningStore_DeleteProvenance_Call) RunAndReturn(run func(con func (_m *MockProvisioningStore) GetProvenance(ctx context.Context, o models.Provisionable, org int64) (models.Provenance, error) { ret := _m.Called(ctx, o, org) + if len(ret) == 0 { + panic("no return value specified for GetProvenance") + } + var r0 models.Provenance var r1 error if rf, ok := ret.Get(0).(func(context.Context, models.Provisionable, int64) (models.Provenance, error)); ok { @@ -124,6 +132,10 @@ func (_c *MockProvisioningStore_GetProvenance_Call) RunAndReturn(run func(contex func (_m *MockProvisioningStore) GetProvenances(ctx context.Context, org int64, resourceType string) (map[string]models.Provenance, error) { ret := _m.Called(ctx, org, resourceType) + if len(ret) == 0 { + panic("no return value specified for GetProvenances") + } + var r0 map[string]models.Provenance var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, string) (map[string]models.Provenance, error)); ok { @@ -180,6 +192,10 @@ func (_c *MockProvisioningStore_GetProvenances_Call) RunAndReturn(run func(conte func (_m *MockProvisioningStore) SetProvenance(ctx context.Context, o models.Provisionable, org int64, p models.Provenance) error { ret := _m.Called(ctx, o, org, p) + if len(ret) == 0 { + panic("no return value specified for SetProvenance") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, models.Provisionable, int64, models.Provenance) error); ok { r0 = rf(ctx, o, org, p) diff --git a/pkg/services/ngalert/provisioning/quota_checker_mock.go b/pkg/services/ngalert/provisioning/quota_checker_mock.go index 596e6c92d61..0639fccf984 100644 --- a/pkg/services/ngalert/provisioning/quota_checker_mock.go +++ b/pkg/services/ngalert/provisioning/quota_checker_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.34.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package provisioning @@ -26,6 +26,10 @@ func (_m *MockQuotaChecker) EXPECT() *MockQuotaChecker_Expecter { func (_m *MockQuotaChecker) CheckQuotaReached(ctx context.Context, target quota.TargetSrv, scopeParams *quota.ScopeParameters) (bool, error) { ret := _m.Called(ctx, target, scopeParams) + if len(ret) == 0 { + panic("no return value specified for CheckQuotaReached") + } + var r0 bool var r1 error if rf, ok := ret.Get(0).(func(context.Context, quota.TargetSrv, *quota.ScopeParameters) (bool, error)); ok { diff --git a/pkg/services/ngalert/remote/alertmanager.go b/pkg/services/ngalert/remote/alertmanager.go index 56cf9d8ec26..a5850cb4b0c 100644 --- a/pkg/services/ngalert/remote/alertmanager.go +++ b/pkg/services/ngalert/remote/alertmanager.go @@ -293,18 +293,20 @@ func (am *Alertmanager) CompareAndSendConfiguration(ctx context.Context, config if err := am.mergeExtraConfigs(ctx, decryptedCfg); err != nil { return fmt.Errorf("unable to merge extra configurations: %w", err) } - rawDecrypted, err := json.Marshal(decryptedCfg) + payload := PostableUserConfigToGrafanaAlertmanagerConfig(decryptedCfg) + rawPayload, err := json.Marshal(payload) if err != nil { return fmt.Errorf("unable to marshal decrypted configuration: %w", err) } - configHash := md5.Sum(rawDecrypted) + + configHash := md5.Sum(rawPayload) // Send the configuration only if we need to. if !am.shouldSendConfig(ctx, configHash) { return nil } - return am.sendConfiguration(ctx, decryptedCfg, fmt.Sprintf("%x", configHash), config.CreatedAt, am.isDefaultConfiguration(configHash)) + return am.sendConfiguration(ctx, payload, fmt.Sprintf("%x", configHash), config.CreatedAt, am.isDefaultConfiguration(configHash)) } func (am *Alertmanager) isDefaultConfiguration(configHash [16]byte) bool { @@ -370,11 +372,11 @@ func (am *Alertmanager) mergeExtraConfigs(ctx context.Context, config *apimodels return nil } -func (am *Alertmanager) sendConfiguration(ctx context.Context, decrypted *apimodels.PostableUserConfig, hash string, createdAt int64, isDefault bool) error { +func (am *Alertmanager) sendConfiguration(ctx context.Context, cfg *remoteClient.GrafanaAlertmanagerConfig, hash string, createdAt int64, isDefault bool) error { am.metrics.ConfigSyncsTotal.Inc() if err := am.mimirClient.CreateGrafanaAlertmanagerConfig( ctx, - decrypted, + cfg, hash, createdAt, isDefault, @@ -420,14 +422,14 @@ func (am *Alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.P if err := am.mergeExtraConfigs(ctx, decryptedCfg); err != nil { return fmt.Errorf("unable to merge extra configurations: %w", err) } - - rawCfg, err := json.Marshal(decryptedCfg) + payload := PostableUserConfigToGrafanaAlertmanagerConfig(decryptedCfg) + rawCfg, err := json.Marshal(payload) if err != nil { return err } hash := fmt.Sprintf("%x", md5.Sum(rawCfg)) - return am.sendConfiguration(ctx, decryptedCfg, hash, time.Now().Unix(), false) + return am.sendConfiguration(ctx, payload, hash, time.Now().Unix(), false) } // SaveAndApplyDefaultConfig sends the default Grafana Alertmanager configuration to the remote Alertmanager. @@ -446,10 +448,17 @@ func (am *Alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error { return err } + payload := PostableUserConfigToGrafanaAlertmanagerConfig(decryptedCfg) + rawCfg, err := json.Marshal(payload) + if err != nil { + return err + } + hash := fmt.Sprintf("%x", md5.Sum(rawCfg)) + return am.sendConfiguration( ctx, - decryptedCfg, - am.defaultConfigHash, + payload, + hash, time.Now().Unix(), true, ) diff --git a/pkg/services/ngalert/remote/alertmanager_test.go b/pkg/services/ngalert/remote/alertmanager_test.go index 3bbcb03de6b..27ec3f5a83d 100644 --- a/pkg/services/ngalert/remote/alertmanager_test.go +++ b/pkg/services/ngalert/remote/alertmanager_test.go @@ -3,6 +3,7 @@ package remote import ( "context" "crypto/md5" + "embed" "encoding/base64" "encoding/json" "errors" @@ -11,6 +12,7 @@ import ( "net/http" "net/http/httptest" "os" + "path" "slices" "strings" "testing" @@ -47,6 +49,9 @@ import ( "github.com/grafana/grafana/pkg/util" ) +//go:embed test-data/*.* +var testData embed.FS + var ( defaultGrafanaConfig = setting.GetAlertmanagerDefaultConfiguration() errTest = errors.New("test") @@ -357,12 +362,14 @@ func TestCompareAndSendConfiguration(t *testing.T) { testGrafanaConfigWithBadEncryption, err := json.Marshal(inputCfg) require.NoError(t, err) - cfgWithDecryptedSecret, err := notifier.Load([]byte(testGrafanaConfigWithSecret)) + test, err := notifier.Load([]byte(testGrafanaConfigWithSecret)) require.NoError(t, err) + cfgWithDecryptedSecret := PostableUserConfigToGrafanaAlertmanagerConfig(test) - cfgWithAutogenRoutes, err := notifier.Load([]byte(testGrafanaConfigWithSecret)) + testAutogenRoutes, err := notifier.Load([]byte(testGrafanaConfigWithSecret)) require.NoError(t, err) - require.NoError(t, testAutogenFn(nil, nil, 0, &cfgWithAutogenRoutes.AlertmanagerConfig, false)) + require.NoError(t, testAutogenFn(nil, nil, 0, &testAutogenRoutes.AlertmanagerConfig, false)) + cfgWithAutogenRoutes := PostableUserConfigToGrafanaAlertmanagerConfig(testAutogenRoutes) // Calculate hashes for expected configurations cfgWithDecryptedSecretBytes, err := json.Marshal(cfgWithDecryptedSecret) @@ -373,6 +380,20 @@ func TestCompareAndSendConfiguration(t *testing.T) { require.NoError(t, err) cfgWithAutogenRoutesHash := fmt.Sprintf("%x", md5.Sum(cfgWithAutogenRoutesBytes)) + cfgWithExtraUnmergedBytes, err := testData.ReadFile(path.Join("test-data", "config-with-extra.json")) + require.NoError(t, err) + cfgWithExtraUnmerged, err := notifier.Load(cfgWithExtraUnmergedBytes) + require.NoError(t, err) + r, err := cfgWithExtraUnmerged.GetMergedAlertmanagerConfig() + require.NoError(t, err) + cfgWithExtraMerged := &client.GrafanaAlertmanagerConfig{ + TemplateFiles: cfgWithExtraUnmerged.TemplateFiles, + AlertmanagerConfig: r.Config, + } + cfgWithExtraMergedBytes, err := json.Marshal(cfgWithExtraMerged) + require.NoError(t, err) + cfgWithExtraMergedHash := fmt.Sprintf("%x", md5.Sum(cfgWithExtraMergedBytes)) + tests := []struct { name string config string @@ -428,6 +449,15 @@ func TestCompareAndSendConfiguration(t *testing.T) { }, nil, }, + { + name: "no error, with extra configurations", + config: string(cfgWithExtraUnmergedBytes), + autogenFn: NoopAutogenFn, + expCfg: &client.UserGrafanaConfig{ + GrafanaAlertmanagerConfig: cfgWithExtraMerged, + Hash: cfgWithExtraMergedHash, + }, + }, } for _, test := range tests { @@ -677,7 +707,7 @@ func TestCompareAndSendConfigurationWithExtraConfigs(t *testing.T) { // Return an empty config to ensure it gets replaced w.Header().Add("content-type", "application/json") require.NoError(t, json.NewEncoder(w).Encode(client.UserGrafanaConfig{ - GrafanaAlertmanagerConfig: &apimodels.PostableUserConfig{}, + GrafanaAlertmanagerConfig: &client.GrafanaAlertmanagerConfig{}, })) return } diff --git a/pkg/services/ngalert/remote/client/alertmanager_configuration.go b/pkg/services/ngalert/remote/client/alertmanager_configuration.go index 164a3949011..35239700ea7 100644 --- a/pkg/services/ngalert/remote/client/alertmanager_configuration.go +++ b/pkg/services/ngalert/remote/client/alertmanager_configuration.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/grafana/alerting/definition" + apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" ) @@ -15,14 +16,25 @@ const ( grafanaAlertmanagerReceiversPath = "/api/v1/grafana/receivers" ) +type GrafanaAlertmanagerConfig struct { + TemplateFiles map[string]string `yaml:"template_files" json:"template_files"` + AlertmanagerConfig definition.PostableApiAlertingConfig `yaml:"alertmanager_config" json:"alertmanager_config"` +} + +func (u *GrafanaAlertmanagerConfig) MarshalJSON() ([]byte, error) { + // this is special marshaling that makes sure that secrets are not masked + type cfg GrafanaAlertmanagerConfig + return definition.MarshalJSONWithSecrets((*cfg)(u)) +} + type UserGrafanaConfig struct { - GrafanaAlertmanagerConfig *apimodels.PostableUserConfig `json:"configuration"` - Hash string `json:"configuration_hash"` - CreatedAt int64 `json:"created"` - Default bool `json:"default"` - Promoted bool `json:"promoted"` - ExternalURL string `json:"external_url"` - SmtpConfig SmtpConfig `json:"smtp_config"` + GrafanaAlertmanagerConfig *GrafanaAlertmanagerConfig `json:"configuration"` + Hash string `json:"configuration_hash"` + CreatedAt int64 `json:"created"` + Default bool `json:"default"` + Promoted bool `json:"promoted"` + ExternalURL string `json:"external_url"` + SmtpConfig SmtpConfig `json:"smtp_config"` // TODO: Remove once everything can be sent in the 'SmtpConfig' field. SmtpFrom string `json:"smtp_from"` @@ -52,7 +64,7 @@ func (mc *Mimir) GetGrafanaAlertmanagerConfig(ctx context.Context) (*UserGrafana return gc, nil } -func (mc *Mimir) CreateGrafanaAlertmanagerConfig(ctx context.Context, cfg *apimodels.PostableUserConfig, hash string, createdAt int64, isDefault bool) error { +func (mc *Mimir) CreateGrafanaAlertmanagerConfig(ctx context.Context, cfg *GrafanaAlertmanagerConfig, hash string, createdAt int64, isDefault bool) error { payload, err := definition.MarshalJSONWithSecrets(&UserGrafanaConfig{ GrafanaAlertmanagerConfig: cfg, Hash: hash, diff --git a/pkg/services/ngalert/remote/client/mimir.go b/pkg/services/ngalert/remote/client/mimir.go index 931e2f7aa3d..61075dc1df4 100644 --- a/pkg/services/ngalert/remote/client/mimir.go +++ b/pkg/services/ngalert/remote/client/mimir.go @@ -29,7 +29,7 @@ type MimirClient interface { DeleteGrafanaAlertmanagerState(ctx context.Context) error GetGrafanaAlertmanagerConfig(ctx context.Context) (*UserGrafanaConfig, error) - CreateGrafanaAlertmanagerConfig(ctx context.Context, configuration *apimodels.PostableUserConfig, hash string, createdAt int64, isDefault bool) error + CreateGrafanaAlertmanagerConfig(ctx context.Context, configuration *GrafanaAlertmanagerConfig, hash string, createdAt int64, isDefault bool) error DeleteGrafanaAlertmanagerConfig(ctx context.Context) error TestTemplate(ctx context.Context, c alertingNotify.TestTemplatesConfigBodyParams) (*alertingNotify.TestTemplatesResults, error) diff --git a/pkg/services/ngalert/remote/compat.go b/pkg/services/ngalert/remote/compat.go new file mode 100644 index 00000000000..8914bc96728 --- /dev/null +++ b/pkg/services/ngalert/remote/compat.go @@ -0,0 +1,13 @@ +package remote + +import ( + "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" + "github.com/grafana/grafana/pkg/services/ngalert/remote/client" +) + +func PostableUserConfigToGrafanaAlertmanagerConfig(config *definitions.PostableUserConfig) *client.GrafanaAlertmanagerConfig { + return &client.GrafanaAlertmanagerConfig{ + TemplateFiles: config.TemplateFiles, + AlertmanagerConfig: config.AlertmanagerConfig, + } +} diff --git a/pkg/services/ngalert/remote/mock/remoteAlertmanager.go b/pkg/services/ngalert/remote/mock/remoteAlertmanager.go index 09cfb04bc67..33a77c10f1c 100644 --- a/pkg/services/ngalert/remote/mock/remoteAlertmanager.go +++ b/pkg/services/ngalert/remote/mock/remoteAlertmanager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.44.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package alertmanager_mock @@ -125,52 +125,6 @@ func (_c *RemoteAlertmanagerMock_CompareAndSendConfiguration_Call) RunAndReturn( return _c } -// SendState provides a mock function with given fields: _a0 -func (_m *RemoteAlertmanagerMock) SendState(_a0 context.Context) error { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for SendState") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RemoteAlertmanagerMock_SendState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendState' -type RemoteAlertmanagerMock_SendState_Call struct { - *mock.Call -} - -// SendState is a helper method to define mock.On call -// - _a0 context.Context -func (_e *RemoteAlertmanagerMock_Expecter) SendState(_a0 interface{}) *RemoteAlertmanagerMock_SendState_Call { - return &RemoteAlertmanagerMock_SendState_Call{Call: _e.mock.On("SendState", _a0)} -} - -func (_c *RemoteAlertmanagerMock_SendState_Call) Run(run func(_a0 context.Context)) *RemoteAlertmanagerMock_SendState_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RemoteAlertmanagerMock_SendState_Call) Return(_a0 error) *RemoteAlertmanagerMock_SendState_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RemoteAlertmanagerMock_SendState_Call) RunAndReturn(run func(context.Context) error) *RemoteAlertmanagerMock_SendState_Call { - _c.Call.Return(run) - return _c -} - // CreateSilence provides a mock function with given fields: _a0, _a1 func (_m *RemoteAlertmanagerMock) CreateSilence(_a0 context.Context, _a1 *v2models.PostableSilence) (string, error) { ret := _m.Called(_a0, _a1) @@ -678,7 +632,7 @@ func (_c *RemoteAlertmanagerMock_PutAlerts_Call) RunAndReturn(run func(context.C return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *RemoteAlertmanagerMock) Ready() bool { ret := _m.Called() @@ -816,6 +770,52 @@ func (_c *RemoteAlertmanagerMock_SaveAndApplyDefaultConfig_Call) RunAndReturn(ru return _c } +// SendState provides a mock function with given fields: _a0 +func (_m *RemoteAlertmanagerMock) SendState(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for SendState") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// RemoteAlertmanagerMock_SendState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendState' +type RemoteAlertmanagerMock_SendState_Call struct { + *mock.Call +} + +// SendState is a helper method to define mock.On call +// - _a0 context.Context +func (_e *RemoteAlertmanagerMock_Expecter) SendState(_a0 interface{}) *RemoteAlertmanagerMock_SendState_Call { + return &RemoteAlertmanagerMock_SendState_Call{Call: _e.mock.On("SendState", _a0)} +} + +func (_c *RemoteAlertmanagerMock_SendState_Call) Run(run func(_a0 context.Context)) *RemoteAlertmanagerMock_SendState_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *RemoteAlertmanagerMock_SendState_Call) Return(_a0 error) *RemoteAlertmanagerMock_SendState_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *RemoteAlertmanagerMock_SendState_Call) RunAndReturn(run func(context.Context) error) *RemoteAlertmanagerMock_SendState_Call { + _c.Call.Return(run) + return _c +} + // SilenceState provides a mock function with given fields: _a0 func (_m *RemoteAlertmanagerMock) SilenceState(_a0 context.Context) (notify.SilenceState, error) { ret := _m.Called(_a0) @@ -874,7 +874,7 @@ func (_c *RemoteAlertmanagerMock_SilenceState_Call) RunAndReturn(run func(contex return _c } -// StopAndWait provides a mock function with given fields: +// StopAndWait provides a mock function with no fields func (_m *RemoteAlertmanagerMock) StopAndWait() { _m.Called() } @@ -902,7 +902,7 @@ func (_c *RemoteAlertmanagerMock_StopAndWait_Call) Return() *RemoteAlertmanagerM } func (_c *RemoteAlertmanagerMock_StopAndWait_Call) RunAndReturn(run func()) *RemoteAlertmanagerMock_StopAndWait_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/pkg/services/ngalert/remote/test-data/config-with-extra.json b/pkg/services/ngalert/remote/test-data/config-with-extra.json new file mode 100644 index 00000000000..4f15ddfc590 --- /dev/null +++ b/pkg/services/ngalert/remote/test-data/config-with-extra.json @@ -0,0 +1,41 @@ +{ + "template_files": { + "test": "{{ define \"my_templ\" }}TEST{{ end }}" + }, + "alertmanager_config": { + "route": { + "receiver": "grafana-default-email", + "group_by": [ + "grafana_folder", + "alertname" + ] + }, + "receivers": [ + { + "name": "grafana-default-email", + "grafana_managed_receiver_configs": [ + { + "uid": "", + "name": "some other name", + "type": "email", + "disableResolveMessage": false, + "settings": { + "addresses": "" + } + } + ] + } + ] + }, + "extra_config": [ + { + "identifier": "imported", + "merge_matchers": ["imported=\"true\""], + "template_files": + { + "extra_template": "{{ define \"my_message\" }}TEST{{ end }}" + }, + "alertmanager_config": "{\"receivers\":[{\"webhook_configs\":[{\"url\":\"http://localhost\"}],\"name\":\"webhook\"}],\"route\":{\"receiver\":\"webhook\"}}" + } + ] +} \ No newline at end of file diff --git a/pkg/services/ngalert/schedule/alerts_sender_mock.go b/pkg/services/ngalert/schedule/alerts_sender_mock.go index 75a9e2ecc5e..6ba9367193e 100644 --- a/pkg/services/ngalert/schedule/alerts_sender_mock.go +++ b/pkg/services/ngalert/schedule/alerts_sender_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.34.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package schedule @@ -55,7 +55,7 @@ func (_c *AlertsSenderMock_Send_Call) Return() *AlertsSenderMock_Send_Call { } func (_c *AlertsSenderMock_Send_Call) RunAndReturn(run func(context.Context, models.AlertRuleKey, definitions.PostableAlerts)) *AlertsSenderMock_Send_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/pkg/services/ngalert/store/admin_configuration_store_mock.go b/pkg/services/ngalert/store/admin_configuration_store_mock.go index 4dfc88ff5cc..080a185ef5b 100644 --- a/pkg/services/ngalert/store/admin_configuration_store_mock.go +++ b/pkg/services/ngalert/store/admin_configuration_store_mock.go @@ -1,11 +1,10 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package store import ( - mock "github.com/stretchr/testify/mock" - models "github.com/grafana/grafana/pkg/services/ngalert/models" + mock "github.com/stretchr/testify/mock" ) // AdminConfigurationStoreMock is an autogenerated mock type for the AdminConfigurationStore type @@ -25,6 +24,10 @@ func (_m *AdminConfigurationStoreMock) EXPECT() *AdminConfigurationStoreMock_Exp func (_m *AdminConfigurationStoreMock) DeleteAdminConfiguration(orgID int64) error { ret := _m.Called(orgID) + if len(ret) == 0 { + panic("no return value specified for DeleteAdminConfiguration") + } + var r0 error if rf, ok := ret.Get(0).(func(int64) error); ok { r0 = rf(orgID) @@ -42,7 +45,7 @@ type AdminConfigurationStoreMock_DeleteAdminConfiguration_Call struct { // DeleteAdminConfiguration is a helper method to define mock.On call // - orgID int64 -func (_e *AdminConfigurationStoreMock_Expecter) DeleteAdminConfiguration(orgID any) *AdminConfigurationStoreMock_DeleteAdminConfiguration_Call { +func (_e *AdminConfigurationStoreMock_Expecter) DeleteAdminConfiguration(orgID interface{}) *AdminConfigurationStoreMock_DeleteAdminConfiguration_Call { return &AdminConfigurationStoreMock_DeleteAdminConfiguration_Call{Call: _e.mock.On("DeleteAdminConfiguration", orgID)} } @@ -58,11 +61,24 @@ func (_c *AdminConfigurationStoreMock_DeleteAdminConfiguration_Call) Return(_a0 return _c } +func (_c *AdminConfigurationStoreMock_DeleteAdminConfiguration_Call) RunAndReturn(run func(int64) error) *AdminConfigurationStoreMock_DeleteAdminConfiguration_Call { + _c.Call.Return(run) + return _c +} + // GetAdminConfiguration provides a mock function with given fields: orgID func (_m *AdminConfigurationStoreMock) GetAdminConfiguration(orgID int64) (*models.AdminConfiguration, error) { ret := _m.Called(orgID) + if len(ret) == 0 { + panic("no return value specified for GetAdminConfiguration") + } + var r0 *models.AdminConfiguration + var r1 error + if rf, ok := ret.Get(0).(func(int64) (*models.AdminConfiguration, error)); ok { + return rf(orgID) + } if rf, ok := ret.Get(0).(func(int64) *models.AdminConfiguration); ok { r0 = rf(orgID) } else { @@ -71,7 +87,6 @@ func (_m *AdminConfigurationStoreMock) GetAdminConfiguration(orgID int64) (*mode } } - var r1 error if rf, ok := ret.Get(1).(func(int64) error); ok { r1 = rf(orgID) } else { @@ -88,7 +103,7 @@ type AdminConfigurationStoreMock_GetAdminConfiguration_Call struct { // GetAdminConfiguration is a helper method to define mock.On call // - orgID int64 -func (_e *AdminConfigurationStoreMock_Expecter) GetAdminConfiguration(orgID any) *AdminConfigurationStoreMock_GetAdminConfiguration_Call { +func (_e *AdminConfigurationStoreMock_Expecter) GetAdminConfiguration(orgID interface{}) *AdminConfigurationStoreMock_GetAdminConfiguration_Call { return &AdminConfigurationStoreMock_GetAdminConfiguration_Call{Call: _e.mock.On("GetAdminConfiguration", orgID)} } @@ -104,11 +119,24 @@ func (_c *AdminConfigurationStoreMock_GetAdminConfiguration_Call) Return(_a0 *mo return _c } -// GetAdminConfigurations provides a mock function with given fields: +func (_c *AdminConfigurationStoreMock_GetAdminConfiguration_Call) RunAndReturn(run func(int64) (*models.AdminConfiguration, error)) *AdminConfigurationStoreMock_GetAdminConfiguration_Call { + _c.Call.Return(run) + return _c +} + +// GetAdminConfigurations provides a mock function with no fields func (_m *AdminConfigurationStoreMock) GetAdminConfigurations() ([]*models.AdminConfiguration, error) { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetAdminConfigurations") + } + var r0 []*models.AdminConfiguration + var r1 error + if rf, ok := ret.Get(0).(func() ([]*models.AdminConfiguration, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() []*models.AdminConfiguration); ok { r0 = rf() } else { @@ -117,7 +145,6 @@ func (_m *AdminConfigurationStoreMock) GetAdminConfigurations() ([]*models.Admin } } - var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -149,10 +176,19 @@ func (_c *AdminConfigurationStoreMock_GetAdminConfigurations_Call) Return(_a0 [] return _c } +func (_c *AdminConfigurationStoreMock_GetAdminConfigurations_Call) RunAndReturn(run func() ([]*models.AdminConfiguration, error)) *AdminConfigurationStoreMock_GetAdminConfigurations_Call { + _c.Call.Return(run) + return _c +} + // UpdateAdminConfiguration provides a mock function with given fields: _a0 func (_m *AdminConfigurationStoreMock) UpdateAdminConfiguration(_a0 UpdateAdminConfigurationCmd) error { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for UpdateAdminConfiguration") + } + var r0 error if rf, ok := ret.Get(0).(func(UpdateAdminConfigurationCmd) error); ok { r0 = rf(_a0) @@ -170,7 +206,7 @@ type AdminConfigurationStoreMock_UpdateAdminConfiguration_Call struct { // UpdateAdminConfiguration is a helper method to define mock.On call // - _a0 UpdateAdminConfigurationCmd -func (_e *AdminConfigurationStoreMock_Expecter) UpdateAdminConfiguration(_a0 any) *AdminConfigurationStoreMock_UpdateAdminConfiguration_Call { +func (_e *AdminConfigurationStoreMock_Expecter) UpdateAdminConfiguration(_a0 interface{}) *AdminConfigurationStoreMock_UpdateAdminConfiguration_Call { return &AdminConfigurationStoreMock_UpdateAdminConfiguration_Call{Call: _e.mock.On("UpdateAdminConfiguration", _a0)} } @@ -185,3 +221,22 @@ func (_c *AdminConfigurationStoreMock_UpdateAdminConfiguration_Call) Return(_a0 _c.Call.Return(_a0) return _c } + +func (_c *AdminConfigurationStoreMock_UpdateAdminConfiguration_Call) RunAndReturn(run func(UpdateAdminConfigurationCmd) error) *AdminConfigurationStoreMock_UpdateAdminConfiguration_Call { + _c.Call.Return(run) + return _c +} + +// NewAdminConfigurationStoreMock creates a new instance of AdminConfigurationStoreMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAdminConfigurationStoreMock(t interface { + mock.TestingT + Cleanup(func()) +}) *AdminConfigurationStoreMock { + mock := &AdminConfigurationStoreMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/oauthtoken/oauthtokentest/service_mock.go b/pkg/services/oauthtoken/oauthtokentest/service_mock.go index 925432a6190..e1643e0e848 100644 --- a/pkg/services/oauthtoken/oauthtokentest/service_mock.go +++ b/pkg/services/oauthtoken/oauthtokentest/service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package oauthtokentest diff --git a/pkg/services/org/orgtest/mock.go b/pkg/services/org/orgtest/mock.go index 7dc2b16d34d..ea598a2be0c 100644 --- a/pkg/services/org/orgtest/mock.go +++ b/pkg/services/org/orgtest/mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package orgtest @@ -62,24 +62,6 @@ func (_m *MockService) CreateWithMember(_a0 context.Context, _a1 *org.CreateOrgC return r0, r1 } -// Delete provides a mock function with given fields: _a0, _a1 -func (_m *MockService) Delete(_a0 context.Context, _a1 *org.DeleteOrgCommand) error { - ret := _m.Called(_a0, _a1) - - if len(ret) == 0 { - panic("no return value specified for Delete") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *org.DeleteOrgCommand) error); ok { - r0 = rf(_a0, _a1) - } else { - r0 = ret.Error(0) - } - - return r0 -} - // DeleteUserFromAll provides a mock function with given fields: _a0, _a1 func (_m *MockService) DeleteUserFromAll(_a0 context.Context, _a1 int64) error { ret := _m.Called(_a0, _a1) diff --git a/pkg/services/pluginsintegration/loader/loader_test.go b/pkg/services/pluginsintegration/loader/loader_test.go index bca3a42339b..727eb8d2952 100644 --- a/pkg/services/pluginsintegration/loader/loader_test.go +++ b/pkg/services/pluginsintegration/loader/loader_test.go @@ -83,8 +83,8 @@ func TestLoader_Load(t *testing.T) { Description: "Data source for Amazon AWS monitoring service", Keywords: []string{"aws", "amazon"}, Logos: plugins.Logos{ - Small: "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", - Large: "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", + Small: "public/plugins/cloudwatch/img/amazon-web-services.png", + Large: "public/plugins/cloudwatch/img/amazon-web-services.png", }, Links: []plugins.InfoLink{ {Name: "Raise issue", URL: "https://github.com/grafana/grafana/issues/new"}, @@ -121,7 +121,7 @@ func TestLoader_Load(t *testing.T) { QueryOptions: map[string]bool{"minInterval": true}, }, Module: "core:plugin/cloudwatch", - BaseURL: "public/app/plugins/datasource/cloudwatch", + BaseURL: "public/plugins/cloudwatch", FS: mustNewStaticFSForTests(t, filepath.Join(corePluginDir(t), "app/plugins/datasource/cloudwatch")), Signature: plugins.SignatureStatusInternal, Class: plugins.ClassCore, @@ -1325,8 +1325,8 @@ func TestLoader_Load_NestedPlugins(t *testing.T) { ExtensionPoints: []plugins.ExtensionPoint{}, }, }, - Module: "public/plugins/test-datasource/nested/module.js", - BaseURL: "public/plugins/test-datasource/nested", + Module: "public/plugins/test-panel/module.js", + BaseURL: "public/plugins/test-panel", FS: mustNewStaticFSForTests(t, filepath.Join(testDataDir(t), "nested-plugins/parent/nested")), Signature: plugins.SignatureStatusValid, SignatureType: plugins.SignatureTypeGrafana, @@ -1497,8 +1497,8 @@ func TestLoader_Load_NestedPlugins(t *testing.T) { {Name: "License", URL: "https://github.com/grafana/grafana-starter-panel/blob/master/LICENSE"}, }, Logos: plugins.Logos{ - Small: "public/plugins/myorgid-simple-app/child/img/logo.svg", - Large: "public/plugins/myorgid-simple-app/child/img/logo.svg", + Small: "public/plugins/myorgid-simple-panel/img/logo.svg", + Large: "public/plugins/myorgid-simple-panel/img/logo.svg", }, Screenshots: []plugins.Screenshots{}, Description: "Grafana Panel Plugin Template", @@ -1523,8 +1523,8 @@ func TestLoader_Load_NestedPlugins(t *testing.T) { ExtensionPoints: []plugins.ExtensionPoint{}, }, }, - Module: "public/plugins/myorgid-simple-app/child/module.js", - BaseURL: "public/plugins/myorgid-simple-app/child", + Module: "public/plugins/myorgid-simple-panel/module.js", + BaseURL: "public/plugins/myorgid-simple-panel", FS: mustNewStaticFSForTests(t, filepath.Join(testDataDir(t), "app-with-child/dist/child")), IncludedInAppID: parent.ID, Signature: plugins.SignatureStatusValid, diff --git a/pkg/services/publicdashboards/public_dashboard_middleware_mock.go b/pkg/services/publicdashboards/public_dashboard_middleware_mock.go index f47e99dc0e2..79ebc20e6ce 100644 --- a/pkg/services/publicdashboards/public_dashboard_middleware_mock.go +++ b/pkg/services/publicdashboards/public_dashboard_middleware_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package publicdashboards diff --git a/pkg/services/publicdashboards/public_dashboard_service_mock.go b/pkg/services/publicdashboards/public_dashboard_service_mock.go index 8e07012e294..b54ef3ec6db 100644 --- a/pkg/services/publicdashboards/public_dashboard_service_mock.go +++ b/pkg/services/publicdashboards/public_dashboard_service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package publicdashboards diff --git a/pkg/services/publicdashboards/public_dashboard_service_wrapper_mock.go b/pkg/services/publicdashboards/public_dashboard_service_wrapper_mock.go index 646a6a033e2..e4c828a4faf 100644 --- a/pkg/services/publicdashboards/public_dashboard_service_wrapper_mock.go +++ b/pkg/services/publicdashboards/public_dashboard_service_wrapper_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package publicdashboards diff --git a/pkg/services/publicdashboards/public_dashboard_store_mock.go b/pkg/services/publicdashboards/public_dashboard_store_mock.go index f485ed445e6..32902d98df2 100644 --- a/pkg/services/publicdashboards/public_dashboard_store_mock.go +++ b/pkg/services/publicdashboards/public_dashboard_store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package publicdashboards @@ -264,36 +264,6 @@ func (_m *FakePublicDashboardStore) FindByDashboardUid(ctx context.Context, orgI return r0, r1 } -// FindByFolder provides a mock function with given fields: ctx, orgId, folderUid -func (_m *FakePublicDashboardStore) FindByFolder(ctx context.Context, orgId int64, folderUid string) ([]*models.PublicDashboard, error) { - ret := _m.Called(ctx, orgId, folderUid) - - if len(ret) == 0 { - panic("no return value specified for FindByFolder") - } - - var r0 []*models.PublicDashboard - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, string) ([]*models.PublicDashboard, error)); ok { - return rf(ctx, orgId, folderUid) - } - if rf, ok := ret.Get(0).(func(context.Context, int64, string) []*models.PublicDashboard); ok { - r0 = rf(ctx, orgId, folderUid) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*models.PublicDashboard) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok { - r1 = rf(ctx, orgId, folderUid) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // GetMetrics provides a mock function with given fields: ctx func (_m *FakePublicDashboardStore) GetMetrics(ctx context.Context) (*models.Metrics, error) { ret := _m.Called(ctx) diff --git a/pkg/services/query/query_service_mock.go b/pkg/services/query/query_service_mock.go index 5c5b4b69d37..800c822290d 100644 --- a/pkg/services/query/query_service_mock.go +++ b/pkg/services/query/query_service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package query @@ -9,9 +9,9 @@ import ( dtos "github.com/grafana/grafana/pkg/api/dtos" - mock "github.com/stretchr/testify/mock" - identity "github.com/grafana/grafana/pkg/apimachinery/identity" + + mock "github.com/stretchr/testify/mock" ) // FakeQueryService is an autogenerated mock type for the Service type @@ -19,22 +19,29 @@ type FakeQueryService struct { mock.Mock } -// QueryData provides a mock function with given fields: ctx, _a1, skipDSCache, reqDTO -func (_m *FakeQueryService) QueryData(ctx context.Context, _a1 identity.Requester, skipDSCache bool, reqDTO dtos.MetricRequest) (*backend.QueryDataResponse, error) { - ret := _m.Called(ctx, _a1, skipDSCache, reqDTO) +// QueryData provides a mock function with given fields: ctx, user, skipDSCache, reqDTO +func (_m *FakeQueryService) QueryData(ctx context.Context, user identity.Requester, skipDSCache bool, reqDTO dtos.MetricRequest) (*backend.QueryDataResponse, error) { + ret := _m.Called(ctx, user, skipDSCache, reqDTO) + + if len(ret) == 0 { + panic("no return value specified for QueryData") + } var r0 *backend.QueryDataResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, identity.Requester, bool, dtos.MetricRequest) (*backend.QueryDataResponse, error)); ok { + return rf(ctx, user, skipDSCache, reqDTO) + } if rf, ok := ret.Get(0).(func(context.Context, identity.Requester, bool, dtos.MetricRequest) *backend.QueryDataResponse); ok { - r0 = rf(ctx, _a1, skipDSCache, reqDTO) + r0 = rf(ctx, user, skipDSCache, reqDTO) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*backend.QueryDataResponse) } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, identity.Requester, bool, dtos.MetricRequest) error); ok { - r1 = rf(ctx, _a1, skipDSCache, reqDTO) + r1 = rf(ctx, user, skipDSCache, reqDTO) } else { r1 = ret.Error(1) } @@ -46,6 +53,10 @@ func (_m *FakeQueryService) QueryData(ctx context.Context, _a1 identity.Requeste func (_m *FakeQueryService) Run(ctx context.Context) error { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for Run") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { r0 = rf(ctx) @@ -56,13 +67,12 @@ func (_m *FakeQueryService) Run(ctx context.Context) error { return r0 } -type mockConstructorTestingTNewFakeQueryService interface { +// NewFakeQueryService creates a new instance of FakeQueryService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFakeQueryService(t interface { mock.TestingT Cleanup(func()) -} - -// NewFakeQueryService creates a new instance of FakeQueryService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewFakeQueryService(t mockConstructorTestingTNewFakeQueryService) *FakeQueryService { +}) *FakeQueryService { mock := &FakeQueryService{} mock.Mock.Test(t) diff --git a/pkg/services/searchV2/search_service_mock.go b/pkg/services/searchV2/search_service_mock.go index 63f7214c067..920b0621291 100644 --- a/pkg/services/searchV2/search_service_mock.go +++ b/pkg/services/searchV2/search_service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.6. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package searchV2 @@ -6,6 +6,7 @@ import ( context "context" backend "github.com/grafana/grafana-plugin-sdk-go/backend" + mock "github.com/stretchr/testify/mock" user "github.com/grafana/grafana/pkg/services/user" @@ -20,6 +21,10 @@ type MockSearchService struct { func (_m *MockSearchService) DoDashboardQuery(ctx context.Context, _a1 *backend.User, orgId int64, query DashboardQuery) *backend.DataResponse { ret := _m.Called(ctx, _a1, orgId, query) + if len(ret) == 0 { + panic("no return value specified for DoDashboardQuery") + } + var r0 *backend.DataResponse if rf, ok := ret.Get(0).(func(context.Context, *backend.User, int64, DashboardQuery) *backend.DataResponse); ok { r0 = rf(ctx, _a1, orgId, query) @@ -32,10 +37,14 @@ func (_m *MockSearchService) DoDashboardQuery(ctx context.Context, _a1 *backend. return r0 } -// IsDisabled provides a mock function with given fields: +// IsDisabled provides a mock function with no fields func (_m *MockSearchService) IsDisabled() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsDisabled") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -50,6 +59,10 @@ func (_m *MockSearchService) IsDisabled() bool { func (_m *MockSearchService) IsReady(ctx context.Context, orgId int64) IsSearchReadyResponse { ret := _m.Called(ctx, orgId) + if len(ret) == 0 { + panic("no return value specified for IsReady") + } + var r0 IsSearchReadyResponse if rf, ok := ret.Get(0).(func(context.Context, int64) IsSearchReadyResponse); ok { r0 = rf(ctx, orgId) @@ -69,6 +82,10 @@ func (_m *MockSearchService) RegisterDashboardIndexExtender(ext DashboardIndexEx func (_m *MockSearchService) Run(ctx context.Context) error { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for Run") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { r0 = rf(ctx) @@ -79,7 +96,7 @@ func (_m *MockSearchService) Run(ctx context.Context) error { return r0 } -// TriggerReIndex provides a mock function with given fields: +// TriggerReIndex provides a mock function with no fields func (_m *MockSearchService) TriggerReIndex() { _m.Called() } @@ -88,6 +105,10 @@ func (_m *MockSearchService) TriggerReIndex() { func (_m *MockSearchService) doDashboardQuery(ctx context.Context, _a1 *user.SignedInUser, orgId int64, query DashboardQuery) *backend.DataResponse { ret := _m.Called(ctx, _a1, orgId, query) + if len(ret) == 0 { + panic("no return value specified for doDashboardQuery") + } + var r0 *backend.DataResponse if rf, ok := ret.Get(0).(func(context.Context, *user.SignedInUser, int64, DashboardQuery) *backend.DataResponse); ok { r0 = rf(ctx, _a1, orgId, query) @@ -99,3 +120,17 @@ func (_m *MockSearchService) doDashboardQuery(ctx context.Context, _a1 *user.Sig return r0 } + +// NewMockSearchService creates a new instance of MockSearchService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockSearchService(t interface { + mock.TestingT + Cleanup(func()) +}) *MockSearchService { + mock := &MockSearchService{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/secrets/fakes/mock_service.go b/pkg/services/secrets/fakes/mock_service.go index 30ac1628653..a138659559c 100644 --- a/pkg/services/secrets/fakes/mock_service.go +++ b/pkg/services/secrets/fakes/mock_service.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.37.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package fakes @@ -18,6 +18,10 @@ type MockService struct { func (_m *MockService) Decrypt(ctx context.Context, payload []byte) ([]byte, error) { ret := _m.Called(ctx, payload) + if len(ret) == 0 { + panic("no return value specified for Decrypt") + } + var r0 []byte var r1 error if rf, ok := ret.Get(0).(func(context.Context, []byte) ([]byte, error)); ok { @@ -44,6 +48,10 @@ func (_m *MockService) Decrypt(ctx context.Context, payload []byte) ([]byte, err func (_m *MockService) DecryptJsonData(ctx context.Context, sjd map[string][]byte) (map[string]string, error) { ret := _m.Called(ctx, sjd) + if len(ret) == 0 { + panic("no return value specified for DecryptJsonData") + } + var r0 map[string]string var r1 error if rf, ok := ret.Get(0).(func(context.Context, map[string][]byte) (map[string]string, error)); ok { @@ -70,6 +78,10 @@ func (_m *MockService) DecryptJsonData(ctx context.Context, sjd map[string][]byt func (_m *MockService) Encrypt(ctx context.Context, payload []byte, opt secrets.EncryptionOptions) ([]byte, error) { ret := _m.Called(ctx, payload, opt) + if len(ret) == 0 { + panic("no return value specified for Encrypt") + } + var r0 []byte var r1 error if rf, ok := ret.Get(0).(func(context.Context, []byte, secrets.EncryptionOptions) ([]byte, error)); ok { @@ -96,6 +108,10 @@ func (_m *MockService) Encrypt(ctx context.Context, payload []byte, opt secrets. func (_m *MockService) EncryptJsonData(ctx context.Context, kv map[string]string, opt secrets.EncryptionOptions) (map[string][]byte, error) { ret := _m.Called(ctx, kv, opt) + if len(ret) == 0 { + panic("no return value specified for EncryptJsonData") + } + var r0 map[string][]byte var r1 error if rf, ok := ret.Get(0).(func(context.Context, map[string]string, secrets.EncryptionOptions) (map[string][]byte, error)); ok { @@ -122,6 +138,10 @@ func (_m *MockService) EncryptJsonData(ctx context.Context, kv map[string]string func (_m *MockService) GetDecryptedValue(ctx context.Context, sjd map[string][]byte, key string, fallback string) string { ret := _m.Called(ctx, sjd, key, fallback) + if len(ret) == 0 { + panic("no return value specified for GetDecryptedValue") + } + var r0 string if rf, ok := ret.Get(0).(func(context.Context, map[string][]byte, string, string) string); ok { r0 = rf(ctx, sjd, key, fallback) @@ -136,6 +156,10 @@ func (_m *MockService) GetDecryptedValue(ctx context.Context, sjd map[string][]b func (_m *MockService) ReEncryptDataKeys(ctx context.Context) error { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for ReEncryptDataKeys") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { r0 = rf(ctx) @@ -150,6 +174,10 @@ func (_m *MockService) ReEncryptDataKeys(ctx context.Context) error { func (_m *MockService) RotateDataKeys(ctx context.Context) error { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for RotateDataKeys") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { r0 = rf(ctx) diff --git a/pkg/services/serviceaccounts/tests/extsvcaccmock.go b/pkg/services/serviceaccounts/tests/extsvcaccmock.go index a81afeb50a8..3f1fdf31152 100644 --- a/pkg/services/serviceaccounts/tests/extsvcaccmock.go +++ b/pkg/services/serviceaccounts/tests/extsvcaccmock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.35.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package tests @@ -18,6 +18,10 @@ type MockExtSvcAccountsService struct { func (_m *MockExtSvcAccountsService) EnableExtSvcAccount(ctx context.Context, cmd *serviceaccounts.EnableExtSvcAccountCmd) error { ret := _m.Called(ctx, cmd) + if len(ret) == 0 { + panic("no return value specified for EnableExtSvcAccount") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *serviceaccounts.EnableExtSvcAccountCmd) error); ok { r0 = rf(ctx, cmd) @@ -32,6 +36,10 @@ func (_m *MockExtSvcAccountsService) EnableExtSvcAccount(ctx context.Context, cm func (_m *MockExtSvcAccountsService) ManageExtSvcAccount(ctx context.Context, cmd *serviceaccounts.ManageExtSvcAccountCmd) (int64, error) { ret := _m.Called(ctx, cmd) + if len(ret) == 0 { + panic("no return value specified for ManageExtSvcAccount") + } + var r0 int64 var r1 error if rf, ok := ret.Get(0).(func(context.Context, *serviceaccounts.ManageExtSvcAccountCmd) (int64, error)); ok { @@ -56,6 +64,10 @@ func (_m *MockExtSvcAccountsService) ManageExtSvcAccount(ctx context.Context, cm func (_m *MockExtSvcAccountsService) RemoveExtSvcAccount(ctx context.Context, orgID int64, extSvcSlug string) error { ret := _m.Called(ctx, orgID, extSvcSlug) + if len(ret) == 0 { + panic("no return value specified for RemoveExtSvcAccount") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok { r0 = rf(ctx, orgID, extSvcSlug) @@ -70,6 +82,10 @@ func (_m *MockExtSvcAccountsService) RemoveExtSvcAccount(ctx context.Context, or func (_m *MockExtSvcAccountsService) RetrieveExtSvcAccount(ctx context.Context, orgID int64, saID int64) (*serviceaccounts.ExtSvcAccount, error) { ret := _m.Called(ctx, orgID, saID) + if len(ret) == 0 { + panic("no return value specified for RetrieveExtSvcAccount") + } + var r0 *serviceaccounts.ExtSvcAccount var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, int64) (*serviceaccounts.ExtSvcAccount, error)); ok { diff --git a/pkg/services/serviceaccounts/tests/mocks.go b/pkg/services/serviceaccounts/tests/mocks.go index a33fc5ae5b4..28df9752b24 100644 --- a/pkg/services/serviceaccounts/tests/mocks.go +++ b/pkg/services/serviceaccounts/tests/mocks.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.35.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package tests @@ -21,6 +21,10 @@ type MockServiceAccountService struct { func (_m *MockServiceAccountService) AddServiceAccountToken(ctx context.Context, serviceAccountID int64, cmd *serviceaccounts.AddServiceAccountTokenCommand) (*apikey.APIKey, error) { ret := _m.Called(ctx, serviceAccountID, cmd) + if len(ret) == 0 { + panic("no return value specified for AddServiceAccountToken") + } + var r0 *apikey.APIKey var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, *serviceaccounts.AddServiceAccountTokenCommand) (*apikey.APIKey, error)); ok { @@ -47,6 +51,10 @@ func (_m *MockServiceAccountService) AddServiceAccountToken(ctx context.Context, func (_m *MockServiceAccountService) CreateServiceAccount(ctx context.Context, orgID int64, saForm *serviceaccounts.CreateServiceAccountForm) (*serviceaccounts.ServiceAccountDTO, error) { ret := _m.Called(ctx, orgID, saForm) + if len(ret) == 0 { + panic("no return value specified for CreateServiceAccount") + } + var r0 *serviceaccounts.ServiceAccountDTO var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, *serviceaccounts.CreateServiceAccountForm) (*serviceaccounts.ServiceAccountDTO, error)); ok { @@ -73,6 +81,10 @@ func (_m *MockServiceAccountService) CreateServiceAccount(ctx context.Context, o func (_m *MockServiceAccountService) DeleteServiceAccount(ctx context.Context, orgID int64, serviceAccountID int64) error { ret := _m.Called(ctx, orgID, serviceAccountID) + if len(ret) == 0 { + panic("no return value specified for DeleteServiceAccount") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, int64, int64) error); ok { r0 = rf(ctx, orgID, serviceAccountID) @@ -87,6 +99,10 @@ func (_m *MockServiceAccountService) DeleteServiceAccount(ctx context.Context, o func (_m *MockServiceAccountService) DeleteServiceAccountToken(ctx context.Context, orgID int64, serviceAccountID int64, tokenID int64) error { ret := _m.Called(ctx, orgID, serviceAccountID, tokenID) + if len(ret) == 0 { + panic("no return value specified for DeleteServiceAccountToken") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, int64, int64, int64) error); ok { r0 = rf(ctx, orgID, serviceAccountID, tokenID) @@ -101,6 +117,10 @@ func (_m *MockServiceAccountService) DeleteServiceAccountToken(ctx context.Conte func (_m *MockServiceAccountService) EnableServiceAccount(ctx context.Context, orgID int64, serviceAccountID int64, enable bool) error { ret := _m.Called(ctx, orgID, serviceAccountID, enable) + if len(ret) == 0 { + panic("no return value specified for EnableServiceAccount") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, int64, int64, bool) error); ok { r0 = rf(ctx, orgID, serviceAccountID, enable) @@ -115,6 +135,10 @@ func (_m *MockServiceAccountService) EnableServiceAccount(ctx context.Context, o func (_m *MockServiceAccountService) ListTokens(ctx context.Context, query *serviceaccounts.GetSATokensQuery) ([]apikey.APIKey, error) { ret := _m.Called(ctx, query) + if len(ret) == 0 { + panic("no return value specified for ListTokens") + } + var r0 []apikey.APIKey var r1 error if rf, ok := ret.Get(0).(func(context.Context, *serviceaccounts.GetSATokensQuery) ([]apikey.APIKey, error)); ok { @@ -141,6 +165,10 @@ func (_m *MockServiceAccountService) ListTokens(ctx context.Context, query *serv func (_m *MockServiceAccountService) MigrateApiKeysToServiceAccounts(ctx context.Context, orgID int64) (*serviceaccounts.MigrationResult, error) { ret := _m.Called(ctx, orgID) + if len(ret) == 0 { + panic("no return value specified for MigrateApiKeysToServiceAccounts") + } + var r0 *serviceaccounts.MigrationResult var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64) (*serviceaccounts.MigrationResult, error)); ok { @@ -163,10 +191,14 @@ func (_m *MockServiceAccountService) MigrateApiKeysToServiceAccounts(ctx context return r0, r1 } -// RetrieveServiceAccount provides a mock function with given fields: ctx, orgID, serviceAccountID +// RetrieveServiceAccount provides a mock function with given fields: ctx, query func (_m *MockServiceAccountService) RetrieveServiceAccount(ctx context.Context, query *serviceaccounts.GetServiceAccountQuery) (*serviceaccounts.ServiceAccountProfileDTO, error) { ret := _m.Called(ctx, query) + if len(ret) == 0 { + panic("no return value specified for RetrieveServiceAccount") + } + var r0 *serviceaccounts.ServiceAccountProfileDTO var r1 error if rf, ok := ret.Get(0).(func(context.Context, *serviceaccounts.GetServiceAccountQuery) (*serviceaccounts.ServiceAccountProfileDTO, error)); ok { @@ -193,6 +225,10 @@ func (_m *MockServiceAccountService) RetrieveServiceAccount(ctx context.Context, func (_m *MockServiceAccountService) RetrieveServiceAccountIdByName(ctx context.Context, orgID int64, name string) (int64, error) { ret := _m.Called(ctx, orgID, name) + if len(ret) == 0 { + panic("no return value specified for RetrieveServiceAccountIdByName") + } + var r0 int64 var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, string) (int64, error)); ok { @@ -217,6 +253,10 @@ func (_m *MockServiceAccountService) RetrieveServiceAccountIdByName(ctx context. func (_m *MockServiceAccountService) SearchOrgServiceAccounts(ctx context.Context, query *serviceaccounts.SearchOrgServiceAccountsQuery) (*serviceaccounts.SearchOrgServiceAccountsResult, error) { ret := _m.Called(ctx, query) + if len(ret) == 0 { + panic("no return value specified for SearchOrgServiceAccounts") + } + var r0 *serviceaccounts.SearchOrgServiceAccountsResult var r1 error if rf, ok := ret.Get(0).(func(context.Context, *serviceaccounts.SearchOrgServiceAccountsQuery) (*serviceaccounts.SearchOrgServiceAccountsResult, error)); ok { @@ -243,6 +283,10 @@ func (_m *MockServiceAccountService) SearchOrgServiceAccounts(ctx context.Contex func (_m *MockServiceAccountService) UpdateServiceAccount(ctx context.Context, orgID int64, serviceAccountID int64, saForm *serviceaccounts.UpdateServiceAccountForm) (*serviceaccounts.ServiceAccountProfileDTO, error) { ret := _m.Called(ctx, orgID, serviceAccountID, saForm) + if len(ret) == 0 { + panic("no return value specified for UpdateServiceAccount") + } + var r0 *serviceaccounts.ServiceAccountProfileDTO var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *serviceaccounts.UpdateServiceAccountForm) (*serviceaccounts.ServiceAccountProfileDTO, error)); ok { diff --git a/pkg/services/ssosettings/ssosettingstests/reloadable_mock.go b/pkg/services/ssosettings/ssosettingstests/reloadable_mock.go index b02bc013056..069f5d2ea7b 100644 --- a/pkg/services/ssosettings/ssosettingstests/reloadable_mock.go +++ b/pkg/services/ssosettings/ssosettingstests/reloadable_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package ssosettingstests diff --git a/pkg/services/ssosettings/ssosettingstests/service_mock.go b/pkg/services/ssosettings/ssosettingstests/service_mock.go index 45bd2ab9dc9..528e3e5a059 100644 --- a/pkg/services/ssosettings/ssosettingstests/service_mock.go +++ b/pkg/services/ssosettings/ssosettingstests/service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package ssosettingstests diff --git a/pkg/services/ssosettings/ssosettingstests/store_mock.go b/pkg/services/ssosettings/ssosettingstests/store_mock.go index 009660cd3e6..3ac1d6c1096 100644 --- a/pkg/services/ssosettings/ssosettingstests/store_mock.go +++ b/pkg/services/ssosettings/ssosettingstests/store_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package ssosettingstests diff --git a/pkg/services/store/entity_events_mock.go b/pkg/services/store/entity_events_mock.go index 52dc2bdff45..460f81a75c4 100644 --- a/pkg/services/store/entity_events_mock.go +++ b/pkg/services/store/entity_events_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.12.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package store @@ -18,7 +18,15 @@ type MockEntityEventsService struct { func (_m *MockEntityEventsService) GetAllEventsAfter(ctx context.Context, id int64) ([]*EntityEvent, error) { ret := _m.Called(ctx, id) + if len(ret) == 0 { + panic("no return value specified for GetAllEventsAfter") + } + var r0 []*EntityEvent + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64) ([]*EntityEvent, error)); ok { + return rf(ctx, id) + } if rf, ok := ret.Get(0).(func(context.Context, int64) []*EntityEvent); ok { r0 = rf(ctx, id) } else { @@ -27,7 +35,6 @@ func (_m *MockEntityEventsService) GetAllEventsAfter(ctx context.Context, id int } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { r1 = rf(ctx, id) } else { @@ -41,7 +48,15 @@ func (_m *MockEntityEventsService) GetAllEventsAfter(ctx context.Context, id int func (_m *MockEntityEventsService) GetLastEvent(ctx context.Context) (*EntityEvent, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for GetLastEvent") + } + var r0 *EntityEvent + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*EntityEvent, error)); ok { + return rf(ctx) + } if rf, ok := ret.Get(0).(func(context.Context) *EntityEvent); ok { r0 = rf(ctx) } else { @@ -50,7 +65,6 @@ func (_m *MockEntityEventsService) GetLastEvent(ctx context.Context) (*EntityEve } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(ctx) } else { @@ -60,10 +74,14 @@ func (_m *MockEntityEventsService) GetLastEvent(ctx context.Context) (*EntityEve return r0, r1 } -// IsDisabled provides a mock function with given fields: +// IsDisabled provides a mock function with no fields func (_m *MockEntityEventsService) IsDisabled() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsDisabled") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -74,15 +92,14 @@ func (_m *MockEntityEventsService) IsDisabled() bool { return r0 } -// OnEvent provides a mock function with given fields: handler -func (_m *MockEntityEventsService) OnEvent(handler EventHandler) { - _m.Called(handler) -} - // Run provides a mock function with given fields: ctx func (_m *MockEntityEventsService) Run(ctx context.Context) error { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for Run") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { r0 = rf(ctx) @@ -93,24 +110,14 @@ func (_m *MockEntityEventsService) Run(ctx context.Context) error { return r0 } -// SaveEvent provides a mock function with given fields: ctx, cmd -func (_m *MockEntityEventsService) SaveEvent(ctx context.Context, cmd SaveEventCmd) error { - ret := _m.Called(ctx, cmd) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, SaveEventCmd) error); ok { - r0 = rf(ctx, cmd) - } else { - r0 = ret.Error(0) - } - - return r0 -} - // deleteEventsOlderThan provides a mock function with given fields: ctx, duration func (_m *MockEntityEventsService) deleteEventsOlderThan(ctx context.Context, duration time.Duration) error { ret := _m.Called(ctx, duration) + if len(ret) == 0 { + panic("no return value specified for deleteEventsOlderThan") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, time.Duration) error); ok { r0 = rf(ctx, duration) @@ -121,13 +128,12 @@ func (_m *MockEntityEventsService) deleteEventsOlderThan(ctx context.Context, du return r0 } -type NewMockEntityEventsServiceT interface { +// NewMockEntityEventsService creates a new instance of MockEntityEventsService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockEntityEventsService(t interface { mock.TestingT Cleanup(func()) -} - -// NewMockEntityEventsService creates a new instance of MockEntityEventsService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMockEntityEventsService(t NewMockEntityEventsServiceT) *MockEntityEventsService { +}) *MockEntityEventsService { mock := &MockEntityEventsService{} mock.Mock.Test(t) diff --git a/pkg/services/store/system_users_mock.go b/pkg/services/store/system_users_mock.go index 525a807dd69..d733148bb35 100644 --- a/pkg/services/store/system_users_mock.go +++ b/pkg/services/store/system_users_mock.go @@ -1,11 +1,11 @@ -// Code generated by mockery v2.15.0. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package store import ( + filestorage "github.com/grafana/grafana/pkg/infra/filestorage" mock "github.com/stretchr/testify/mock" - filestorage "github.com/grafana/grafana/pkg/infra/filestorage" user "github.com/grafana/grafana/pkg/services/user" ) @@ -18,7 +18,15 @@ type FakeSystemUsers struct { func (_m *FakeSystemUsers) GetFilter(_a0 *user.SignedInUser) (map[string]filestorage.PathFilter, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for GetFilter") + } + var r0 map[string]filestorage.PathFilter + var r1 error + if rf, ok := ret.Get(0).(func(*user.SignedInUser) (map[string]filestorage.PathFilter, error)); ok { + return rf(_a0) + } if rf, ok := ret.Get(0).(func(*user.SignedInUser) map[string]filestorage.PathFilter); ok { r0 = rf(_a0) } else { @@ -27,7 +35,6 @@ func (_m *FakeSystemUsers) GetFilter(_a0 *user.SignedInUser) (map[string]filesto } } - var r1 error if rf, ok := ret.Get(1).(func(*user.SignedInUser) error); ok { r1 = rf(_a0) } else { @@ -41,7 +48,15 @@ func (_m *FakeSystemUsers) GetFilter(_a0 *user.SignedInUser) (map[string]filesto func (_m *FakeSystemUsers) GetUser(userType SystemUserType, orgID int64) (*user.SignedInUser, error) { ret := _m.Called(userType, orgID) + if len(ret) == 0 { + panic("no return value specified for GetUser") + } + var r0 *user.SignedInUser + var r1 error + if rf, ok := ret.Get(0).(func(SystemUserType, int64) (*user.SignedInUser, error)); ok { + return rf(userType, orgID) + } if rf, ok := ret.Get(0).(func(SystemUserType, int64) *user.SignedInUser); ok { r0 = rf(userType, orgID) } else { @@ -50,7 +65,6 @@ func (_m *FakeSystemUsers) GetUser(userType SystemUserType, orgID int64) (*user. } } - var r1 error if rf, ok := ret.Get(1).(func(SystemUserType, int64) error); ok { r1 = rf(userType, orgID) } else { @@ -65,13 +79,12 @@ func (_m *FakeSystemUsers) RegisterUser(userType SystemUserType, filterFn func() _m.Called(userType, filterFn) } -type mockConstructorTestingTNewFakeSystemUsers interface { +// NewFakeSystemUsers creates a new instance of FakeSystemUsers. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFakeSystemUsers(t interface { mock.TestingT Cleanup(func()) -} - -// NewFakeSystemUsers creates a new instance of FakeSystemUsers. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewFakeSystemUsers(t mockConstructorTestingTNewFakeSystemUsers) *FakeSystemUsers { +}) *FakeSystemUsers { mock := &FakeSystemUsers{} mock.Mock.Test(t) diff --git a/pkg/services/user/usertest/mock.go b/pkg/services/user/usertest/mock.go index 943b1520fb1..36da416d1ef 100644 --- a/pkg/services/user/usertest/mock.go +++ b/pkg/services/user/usertest/mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package usertest @@ -230,35 +230,6 @@ func (_m *MockService) GetByUID(_a0 context.Context, _a1 *user.GetUserByUIDQuery return r0, r1 } -func (_m *MockService) ListByIdOrUID(_a0 context.Context, _a1 []string, _a2 []int64) ([]*user.User, error) { - ret := _m.Called(_a0, _a1, _a2) - - if len(ret) == 0 { - panic("no return value specified for ListByIdOrUID") - } - - var r0 []*user.User - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []string, []int64) ([]*user.User, error)); ok { - return rf(_a0, _a1, _a2) - } - if rf, ok := ret.Get(0).(func(context.Context, []string, []int64) []*user.User); ok { - r0 = rf(_a0, _a1, _a2) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*user.User) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, []string, []int64) error); ok { - r1 = rf(_a0, _a1, _a2) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // GetProfile provides a mock function with given fields: _a0, _a1 func (_m *MockService) GetProfile(_a0 context.Context, _a1 *user.GetUserProfileQuery) (*user.UserProfileDTO, error) { ret := _m.Called(_a0, _a1) @@ -339,6 +310,36 @@ func (_m *MockService) GetUsageStats(ctx context.Context) map[string]interface{} return r0 } +// ListByIdOrUID provides a mock function with given fields: _a0, _a1, _a2 +func (_m *MockService) ListByIdOrUID(_a0 context.Context, _a1 []string, _a2 []int64) ([]*user.User, error) { + ret := _m.Called(_a0, _a1, _a2) + + if len(ret) == 0 { + panic("no return value specified for ListByIdOrUID") + } + + var r0 []*user.User + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string, []int64) ([]*user.User, error)); ok { + return rf(_a0, _a1, _a2) + } + if rf, ok := ret.Get(0).(func(context.Context, []string, []int64) []*user.User); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*user.User) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []string, []int64) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Search provides a mock function with given fields: _a0, _a1 func (_m *MockService) Search(_a0 context.Context, _a1 *user.SearchUsersQuery) (*user.SearchUserQueryResult, error) { ret := _m.Called(_a0, _a1) diff --git a/pkg/setting/settingtest/provider_mock.go b/pkg/setting/settingtest/provider_mock.go index 9cccb382d72..bf0bb232d86 100644 --- a/pkg/setting/settingtest/provider_mock.go +++ b/pkg/setting/settingtest/provider_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package settingtest @@ -12,7 +12,7 @@ type MockProvider struct { mock.Mock } -// Current provides a mock function with given fields: +// Current provides a mock function with no fields func (_m *MockProvider) Current() setting.SettingsBag { ret := _m.Called() @@ -32,7 +32,7 @@ func (_m *MockProvider) Current() setting.SettingsBag { return r0 } -// CurrentVerbose provides a mock function with given fields: +// CurrentVerbose provides a mock function with no fields func (_m *MockProvider) CurrentVerbose() setting.VerboseSettingsBag { ret := _m.Called() diff --git a/pkg/storage/legacysql/dualwrite/service_mock.go b/pkg/storage/legacysql/dualwrite/service_mock.go index 264c19d7047..d7524082652 100644 --- a/pkg/storage/legacysql/dualwrite/service_mock.go +++ b/pkg/storage/legacysql/dualwrite/service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.52.4. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package dualwrite diff --git a/pkg/storage/secret/metadata/data/secure_value_create.sql b/pkg/storage/secret/metadata/data/secure_value_create.sql index ae03dd2405e..a120feaa5e5 100644 --- a/pkg/storage/secret/metadata/data/secure_value_create.sql +++ b/pkg/storage/secret/metadata/data/secure_value_create.sql @@ -8,10 +8,8 @@ INSERT INTO {{ .Ident "secret_secure_value" }} ( {{ .Ident "created_by" }}, {{ .Ident "updated" }}, {{ .Ident "updated_by" }}, - {{ .Ident "status_phase" }}, - {{ if .Row.Message.Valid }} - {{ .Ident "status_message" }}, - {{ end }} + {{ .Ident "active" }}, + {{ .Ident "version" }}, {{ .Ident "description" }}, {{ if .Row.Keeper.Valid }} {{ .Ident "keeper" }}, @@ -33,10 +31,8 @@ INSERT INTO {{ .Ident "secret_secure_value" }} ( {{ .Arg .Row.CreatedBy }}, {{ .Arg .Row.Updated }}, {{ .Arg .Row.UpdatedBy }}, - {{ .Arg .Row.Phase }}, - {{ if .Row.Message.Valid }} - {{ .Arg .Row.Message.String }}, - {{ end }} + {{ .Arg .Row.Active }}, + {{ .Arg .Row.Version }}, {{ .Arg .Row.Description }}, {{ if .Row.Keeper.Valid }} {{ .Arg .Row.Keeper.String }}, @@ -48,4 +44,4 @@ INSERT INTO {{ .Ident "secret_secure_value" }} ( {{ .Arg .Row.Ref.String }}, {{ end }} {{ .Arg .Row.ExternalID }} -); +); \ No newline at end of file diff --git a/pkg/storage/secret/metadata/data/secure_value_delete.sql b/pkg/storage/secret/metadata/data/secure_value_delete.sql deleted file mode 100644 index 2714510c291..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_delete.sql +++ /dev/null @@ -1,4 +0,0 @@ -DELETE FROM {{ .Ident "secret_secure_value" }} -WHERE {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND - {{ .Ident "name" }} = {{ .Arg .Name }} -; diff --git a/pkg/storage/secret/metadata/data/secure_value_get_latest_version.sql b/pkg/storage/secret/metadata/data/secure_value_get_latest_version.sql new file mode 100644 index 00000000000..90319d469eb --- /dev/null +++ b/pkg/storage/secret/metadata/data/secure_value_get_latest_version.sql @@ -0,0 +1,10 @@ +SELECT + {{ .Ident "version" }} +FROM + {{ .Ident "secret_secure_value" }} +WHERE + {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND + {{ .Ident "name" }} = {{ .Arg .Name }} +ORDER BY {{ .Ident "version" }} DESC +LIMIT 1 +; \ No newline at end of file diff --git a/pkg/storage/secret/metadata/data/secure_value_list.sql b/pkg/storage/secret/metadata/data/secure_value_list.sql index db19a729ebf..9c0c604b72d 100644 --- a/pkg/storage/secret/metadata/data/secure_value_list.sql +++ b/pkg/storage/secret/metadata/data/secure_value_list.sql @@ -8,15 +8,17 @@ SELECT {{ .Ident "created_by" }}, {{ .Ident "updated" }}, {{ .Ident "updated_by" }}, - {{ .Ident "status_phase" }}, - {{ .Ident "status_message" }}, {{ .Ident "description" }}, {{ .Ident "keeper" }}, {{ .Ident "decrypters" }}, {{ .Ident "ref" }}, - {{ .Ident "external_id" }} + {{ .Ident "external_id" }}, + {{ .Ident "version" }}, + {{ .Ident "active" }} FROM {{ .Ident "secret_secure_value" }} -WHERE {{ .Ident "namespace" }} = {{ .Arg .Namespace }} +WHERE + {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND + {{ .Ident "active" }} = true ORDER BY {{ .Ident "updated" }} DESC -; +; \ No newline at end of file diff --git a/pkg/storage/secret/metadata/data/secure_value_listByName.sql b/pkg/storage/secret/metadata/data/secure_value_listByName.sql index b8158d3c0ff..7a5945e4fde 100644 --- a/pkg/storage/secret/metadata/data/secure_value_listByName.sql +++ b/pkg/storage/secret/metadata/data/secure_value_listByName.sql @@ -5,7 +5,9 @@ SELECT {{ .Ident "keeper" }} FROM {{ .Ident "secret_secure_value" }} -WHERE {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND - {{ .Ident "name" }} IN ({{ .ArgList .UsedSecureValues }}) +WHERE + {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND + {{ .Ident "name" }} IN ({{ .ArgList .UsedSecureValues }}) AND + {{ .Ident "active" }} = true {{ .SelectFor "UPDATE" }} ; diff --git a/pkg/storage/secret/metadata/data/secure_value_outbox_append.sql b/pkg/storage/secret/metadata/data/secure_value_outbox_append.sql deleted file mode 100644 index e541cec3140..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_outbox_append.sql +++ /dev/null @@ -1,33 +0,0 @@ -INSERT INTO {{ .Ident "secret_secure_value_outbox" }} ( - {{ .Ident "request_id" }}, - {{ .Ident "message_type" }}, - {{ .Ident "name" }}, - {{ .Ident "namespace" }}, -{{ if .Row.EncryptedSecret.Valid }} - {{ .Ident "encrypted_secret" }}, -{{ end }} -{{ if .Row.KeeperName.Valid }} - {{ .Ident "keeper_name" }}, -{{ end }} -{{ if .Row.ExternalID.Valid }} - {{ .Ident "external_id" }}, -{{ end }} - {{ .Ident "receive_count" }}, - {{ .Ident "created" }} -) VALUES ( - {{ .Arg .Row.RequestID }}, - {{ .Arg .Row.MessageType }}, - {{ .Arg .Row.Name }}, - {{ .Arg .Row.Namespace }}, -{{ if .Row.EncryptedSecret.Valid }} - {{ .Arg .Row.EncryptedSecret.String }}, -{{ end }} -{{ if .Row.KeeperName.Valid }} - {{ .Arg .Row.KeeperName.String }}, -{{ end }} -{{ if .Row.ExternalID.Valid }} - {{ .Arg .Row.ExternalID.String }}, -{{ end }} - {{ .Arg .Row.ReceiveCount }}, - {{ .Arg .Row.Created }} -); diff --git a/pkg/storage/secret/metadata/data/secure_value_outbox_delete.sql b/pkg/storage/secret/metadata/data/secure_value_outbox_delete.sql deleted file mode 100644 index d23f3808f9c..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_outbox_delete.sql +++ /dev/null @@ -1,5 +0,0 @@ -DELETE FROM - {{ .Ident "secret_secure_value_outbox" }} -WHERE - {{ .Ident "id" }} = {{ .Arg .MessageID }} -; diff --git a/pkg/storage/secret/metadata/data/secure_value_outbox_fetch_message_ids.sql b/pkg/storage/secret/metadata/data/secure_value_outbox_fetch_message_ids.sql deleted file mode 100644 index 2c53c2223fd..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_outbox_fetch_message_ids.sql +++ /dev/null @@ -1,6 +0,0 @@ -SELECT - {{ .Ident "id" }} -FROM {{ .Ident "secret_secure_value_outbox" }} -ORDER BY id ASC -LIMIT {{ .Arg .ReceiveLimit }} -; diff --git a/pkg/storage/secret/metadata/data/secure_value_outbox_query_timestamp.sql b/pkg/storage/secret/metadata/data/secure_value_outbox_query_timestamp.sql deleted file mode 100644 index 8e525ca9009..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_outbox_query_timestamp.sql +++ /dev/null @@ -1,8 +0,0 @@ -SELECT - {{ .Ident "created" }}, - {{ .Ident "message_type" }} -FROM - {{ .Ident "secret_secure_value_outbox" }} -WHERE - {{ .Ident "id" }} = {{ .Arg .MessageID }} -; diff --git a/pkg/storage/secret/metadata/data/secure_value_outbox_receiveN.sql b/pkg/storage/secret/metadata/data/secure_value_outbox_receiveN.sql deleted file mode 100644 index 254cb3d3f3d..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_outbox_receiveN.sql +++ /dev/null @@ -1,19 +0,0 @@ -SELECT - {{ .Ident "request_id" }}, - {{ .Ident "id" }}, - {{ .Ident "message_type" }}, - {{ .Ident "name" }}, - {{ .Ident "namespace" }}, - {{ .Ident "encrypted_secret" }}, - {{ .Ident "keeper_name" }}, - {{ .Ident "external_id" }}, - {{ .Ident "receive_count" }}, - {{ .Ident "created" }} -FROM - {{ .Ident "secret_secure_value_outbox" }} -WHERE - {{ .Ident "id" }} IN ({{ .ArgList .MessageIDs }}) -ORDER BY - {{ .Ident "id" }} ASC -{{ .SelectFor "UPDATE SKIP LOCKED" }} -; diff --git a/pkg/storage/secret/metadata/data/secure_value_outbox_update_receive_count.sql b/pkg/storage/secret/metadata/data/secure_value_outbox_update_receive_count.sql deleted file mode 100644 index 610f29695a8..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_outbox_update_receive_count.sql +++ /dev/null @@ -1,7 +0,0 @@ -UPDATE - {{ .Ident "secret_secure_value_outbox" }} -SET - {{ .Ident "receive_count" }} = {{ .Ident "receive_count" }} + 1 -WHERE - {{ .Ident "id" }} IN ({{ .ArgList .MessageIDs }}) -; diff --git a/pkg/storage/secret/metadata/data/secure_value_read.sql b/pkg/storage/secret/metadata/data/secure_value_read.sql index 3453abb08e4..b90d54b4a5f 100644 --- a/pkg/storage/secret/metadata/data/secure_value_read.sql +++ b/pkg/storage/secret/metadata/data/secure_value_read.sql @@ -8,18 +8,20 @@ SELECT {{ .Ident "created_by" }}, {{ .Ident "updated" }}, {{ .Ident "updated_by" }}, - {{ .Ident "status_phase" }}, - {{ .Ident "status_message" }}, {{ .Ident "description" }}, {{ .Ident "keeper" }}, {{ .Ident "decrypters" }}, {{ .Ident "ref" }}, - {{ .Ident "external_id" }} + {{ .Ident "external_id" }}, + {{ .Ident "active" }}, + {{ .Ident "version" }} FROM {{ .Ident "secret_secure_value" }} -WHERE {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND - {{ .Ident "name" }} = {{ .Arg .Name }} +WHERE + {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND + {{ .Ident "name" }} = {{ .Arg .Name }} AND + {{ .Ident "active" }} = true {{ if .IsForUpdate }} {{ .SelectFor "UPDATE" }} {{ end }} -; +; \ No newline at end of file diff --git a/pkg/storage/secret/metadata/data/secure_value_read_for_decrypt.sql b/pkg/storage/secret/metadata/data/secure_value_read_for_decrypt.sql index 14080fa0507..975c00d9f3b 100644 --- a/pkg/storage/secret/metadata/data/secure_value_read_for_decrypt.sql +++ b/pkg/storage/secret/metadata/data/secure_value_read_for_decrypt.sql @@ -2,9 +2,12 @@ SELECT {{ .Ident "keeper" }}, {{ .Ident "decrypters" }}, {{ .Ident "ref" }}, - {{ .Ident "external_id" }} + {{ .Ident "external_id" }}, + {{ .Ident "active" }} FROM {{ .Ident "secret_secure_value" }} -WHERE {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND - {{ .Ident "name" }} = {{ .Arg .Name }} -; +WHERE + {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND + {{ .Ident "name" }} = {{ .Arg .Name }} AND + {{ .Ident "active" }} = true +; \ No newline at end of file diff --git a/pkg/storage/secret/metadata/data/secure_value_set_version_to_active.sql b/pkg/storage/secret/metadata/data/secure_value_set_version_to_active.sql new file mode 100644 index 00000000000..bf069441ac3 --- /dev/null +++ b/pkg/storage/secret/metadata/data/secure_value_set_version_to_active.sql @@ -0,0 +1,8 @@ +UPDATE + {{ .Ident "secret_secure_value" }} +SET + {{ .Ident "active" }} = ({{ .Ident "version" }} = {{ .Arg .Version}}) +WHERE + {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND + {{ .Ident "name" }} = {{ .Arg .Name }} +; \ No newline at end of file diff --git a/pkg/storage/secret/metadata/data/secure_value_set_version_to_inactive.sql b/pkg/storage/secret/metadata/data/secure_value_set_version_to_inactive.sql new file mode 100644 index 00000000000..608bb813c4f --- /dev/null +++ b/pkg/storage/secret/metadata/data/secure_value_set_version_to_inactive.sql @@ -0,0 +1,9 @@ +UPDATE + {{ .Ident "secret_secure_value" }} +SET + {{ .Ident "active" }} = false +WHERE + {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND + {{ .Ident "name" }} = {{ .Arg .Name }} AND + {{ .Ident "version" }} = {{ .Arg .Version }} +; \ No newline at end of file diff --git a/pkg/storage/secret/metadata/data/secure_value_update.sql b/pkg/storage/secret/metadata/data/secure_value_update.sql deleted file mode 100644 index 90fc4946611..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_update.sql +++ /dev/null @@ -1,30 +0,0 @@ -UPDATE - {{ .Ident "secret_secure_value" }} -SET - {{ .Ident "guid" }} = {{ .Arg .Row.GUID }}, - {{ .Ident "name" }} = {{ .Arg .Row.Name }}, - {{ .Ident "namespace" }} = {{ .Arg .Row.Namespace }}, - {{ .Ident "annotations" }} = {{ .Arg .Row.Annotations }}, - {{ .Ident "labels" }} = {{ .Arg .Row.Labels }}, - {{ .Ident "created" }} = {{ .Arg .Row.Created }}, - {{ .Ident "created_by" }} = {{ .Arg .Row.CreatedBy }}, - {{ .Ident "updated" }} = {{ .Arg .Row.Updated }}, - {{ .Ident "updated_by" }} = {{ .Arg .Row.UpdatedBy }}, - {{ .Ident "status_phase" }} = {{ .Arg .Row.Phase }}, - {{ if .Row.Message.Valid }} - {{ .Ident "status_message" }} = {{ .Arg .Row.Message.String }}, - {{ end }} - {{ .Ident "description" }} = {{ .Arg .Row.Description }}, - {{ if .Row.Keeper.Valid }} - {{ .Ident "keeper" }} = {{ .Arg .Row.Keeper.String }}, - {{ end }} - {{ if .Row.Decrypters.Valid }} - {{ .Ident "decrypters" }} = {{ .Arg .Row.Decrypters.String }}, - {{ end }} - {{ if .Row.Ref.Valid }} - {{ .Ident "ref" }} = {{ .Arg .Row.Ref.String }}, - {{ end }} - {{ .Ident "external_id" }} = {{ .Arg .Row.ExternalID }} -WHERE {{ .Ident "namespace" }} = {{ .Arg .Row.Namespace }} AND - {{ .Ident "name" }} = {{ .Arg .Row.Name }} -; diff --git a/pkg/storage/secret/metadata/data/secure_value_updateExternalId.sql b/pkg/storage/secret/metadata/data/secure_value_updateExternalId.sql index 9b2927802e6..fb891badaf5 100644 --- a/pkg/storage/secret/metadata/data/secure_value_updateExternalId.sql +++ b/pkg/storage/secret/metadata/data/secure_value_updateExternalId.sql @@ -2,6 +2,8 @@ UPDATE {{ .Ident "secret_secure_value" }} SET {{ .Ident "external_id" }} = {{ .Arg .ExternalID }} -WHERE {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND - {{ .Ident "name" }} = {{ .Arg .Name }} -; +WHERE + {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND + {{ .Ident "name" }} = {{ .Arg .Name }} AND + {{ .Ident "version" }} = {{ .Arg .Version }} +; \ No newline at end of file diff --git a/pkg/storage/secret/metadata/data/secure_value_updateStatus.sql b/pkg/storage/secret/metadata/data/secure_value_updateStatus.sql deleted file mode 100644 index dfba1960ce0..00000000000 --- a/pkg/storage/secret/metadata/data/secure_value_updateStatus.sql +++ /dev/null @@ -1,8 +0,0 @@ -UPDATE - {{ .Ident "secret_secure_value" }} -SET - {{ .Ident "status_phase" }} = {{ .Arg .Phase }}, - {{ .Ident "status_message" }} = {{ .Arg .Message }} -WHERE {{ .Ident "namespace" }} = {{ .Arg .Namespace }} AND - {{ .Ident "name" }} = {{ .Arg .Name }} -; diff --git a/pkg/storage/secret/metadata/decrypt_store_test.go b/pkg/storage/secret/metadata/decrypt_store_test.go index 69a178c01cf..5ebbb2f9466 100644 --- a/pkg/storage/secret/metadata/decrypt_store_test.go +++ b/pkg/storage/secret/metadata/decrypt_store_test.go @@ -1,4 +1,4 @@ -package metadata +package metadata_test import ( "context" @@ -7,23 +7,11 @@ import ( "github.com/grafana/authlib/authn" "github.com/grafana/authlib/types" "github.com/stretchr/testify/require" - "go.opentelemetry.io/otel/trace/noop" "github.com/grafana/grafana/pkg/apimachinery/identity" secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1" - "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" - "github.com/grafana/grafana/pkg/registry/apis/secret/decrypt" - "github.com/grafana/grafana/pkg/registry/apis/secret/encryption" - encryptionmanager "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" - "github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper" - "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/sqlstore" - "github.com/grafana/grafana/pkg/setting" - "github.com/grafana/grafana/pkg/storage/secret/database" - encryptionstorage "github.com/grafana/grafana/pkg/storage/secret/encryption" - "github.com/grafana/grafana/pkg/storage/secret/migrator" + "github.com/grafana/grafana/pkg/registry/apis/secret/testutils" ) func TestIntegrationDecrypt(t *testing.T) { @@ -39,9 +27,9 @@ func TestIntegrationDecrypt(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - decryptSvc, _, _, _ := setupDecryptTestService(t, nil) + sut := testutils.Setup(t) - exposed, err := decryptSvc.Decrypt(ctx, "default", "name") + exposed, err := sut.DecryptStorage.Decrypt(ctx, "default", "name") require.Error(t, err) require.Empty(t, exposed) }) @@ -55,9 +43,11 @@ func TestIntegrationDecrypt(t *testing.T) { // Create auth context with proper permissions authCtx := createAuthContext(ctx, "default", []string{"secret.grafana.app/securevalues/group1:decrypt"}, "svc", types.TypeUser) - decryptSvc, _, _, _ := setupDecryptTestService(t, map[string]struct{}{"group1": {}}) + sut := testutils.Setup(t, testutils.WithMutateCfg(func(sc *testutils.SetupConfig) { + sc.AllowList = map[string]struct{}{"group1": {}} + })) - exposed, err := decryptSvc.Decrypt(authCtx, "default", "non-existent-value") + exposed, err := sut.DecryptStorage.Decrypt(authCtx, "default", "non-existent-value") require.ErrorIs(t, err, contracts.ErrDecryptNotFound) require.Empty(t, exposed) }) @@ -78,7 +68,9 @@ func TestIntegrationDecrypt(t *testing.T) { allowList := map[string]struct{}{"allowed-group": {}} // Setup service - decryptSvc, secureValueMetadataStorage, keeperService, keeperMetadataService := setupDecryptTestService(t, allowList) + sut := testutils.Setup(t, testutils.WithMutateCfg(func(sc *testutils.SetupConfig) { + sc.AllowList = allowList + })) // Create a secure value that is not in the allowlist spec := secretv0alpha1.SecureValueSpec{ @@ -90,9 +82,10 @@ func TestIntegrationDecrypt(t *testing.T) { sv.Name = svName sv.Namespace = "default" - newTestSecureValue(authCtx, t, secureValueMetadataStorage, keeperService, keeperMetadataService, sv, "actor-uid") + _, err := sut.CreateSv(authCtx, testutils.CreateSvWithSv(sv)) + require.NoError(t, err) - exposed, err := decryptSvc.Decrypt(authCtx, "default", svName) + exposed, err := sut.DecryptStorage.Decrypt(authCtx, "default", svName) require.ErrorIs(t, err, contracts.ErrDecryptNotAuthorized) require.Empty(t, exposed) }) @@ -112,7 +105,9 @@ func TestIntegrationDecrypt(t *testing.T) { allowList := map[string]struct{}{svcIdentity: {}} // Setup service - decryptSvc, secureValueMetadataStorage, keeperService, keeperMetadataService := setupDecryptTestService(t, allowList) + sut := testutils.Setup(t, testutils.WithMutateCfg(func(sc *testutils.SetupConfig) { + sc.AllowList = allowList + })) // Create a secure value that is in the allowlist spec := secretv0alpha1.SecureValueSpec{ @@ -124,9 +119,10 @@ func TestIntegrationDecrypt(t *testing.T) { sv.Name = "sv-test" sv.Namespace = "default" - newTestSecureValue(authCtx, t, secureValueMetadataStorage, keeperService, keeperMetadataService, sv, "actor-uid") + _, err := sut.CreateSv(authCtx, testutils.CreateSvWithSv(sv)) + require.NoError(t, err) - exposed, err := decryptSvc.Decrypt(authCtx, "default", "sv-test") + exposed, err := sut.DecryptStorage.Decrypt(authCtx, "default", "sv-test") require.NoError(t, err) require.NotEmpty(t, exposed) require.Equal(t, "value", exposed.DangerouslyExposeAndConsumeValue()) @@ -148,7 +144,9 @@ func TestIntegrationDecrypt(t *testing.T) { allowList := map[string]struct{}{svcIdentity: {}} // Setup service - decryptSvc, secureValueMetadataStorage, keeperService, keeperMetadataService := setupDecryptTestService(t, allowList) + sut := testutils.Setup(t, testutils.WithMutateCfg(func(sc *testutils.SetupConfig) { + sc.AllowList = allowList + })) // Create a secure value that is in the allowlist spec := secretv0alpha1.SecureValueSpec{ @@ -160,9 +158,10 @@ func TestIntegrationDecrypt(t *testing.T) { sv.Name = svName sv.Namespace = "default" - newTestSecureValue(authCtx, t, secureValueMetadataStorage, keeperService, keeperMetadataService, sv, "actor-uid") + _, err := sut.CreateSv(authCtx, testutils.CreateSvWithSv(sv)) + require.NoError(t, err) - exposed, err := decryptSvc.Decrypt(authCtx, "default", svName) + exposed, err := sut.DecryptStorage.Decrypt(authCtx, "default", svName) require.ErrorIs(t, err, contracts.ErrDecryptNotAuthorized) require.Empty(t, exposed) }) @@ -179,7 +178,7 @@ func TestIntegrationDecrypt(t *testing.T) { authCtx := createAuthContext(ctx, "default", []string{"secret.grafana.app/securevalues"}, svcIdentity, types.TypeUser) // Setup service - decryptSvc, secureValueMetadataStorage, keeperService, keeperMetadataService := setupDecryptTestService(t, map[string]struct{}{svcIdentity: {}}) + sut := testutils.Setup(t) // Create a secure value spec := secretv0alpha1.SecureValueSpec{ @@ -191,9 +190,10 @@ func TestIntegrationDecrypt(t *testing.T) { sv.Name = "sv-test" sv.Namespace = "default" - newTestSecureValue(authCtx, t, secureValueMetadataStorage, keeperService, keeperMetadataService, sv, "actor-uid") + _, err := sut.CreateSv(authCtx, testutils.CreateSvWithSv(sv)) + require.NoError(t, err) - exposed, err := decryptSvc.Decrypt(authCtx, "default", "sv-test") + exposed, err := sut.DecryptStorage.Decrypt(authCtx, "default", "sv-test") require.ErrorIs(t, err, contracts.ErrDecryptNotAuthorized) require.Empty(t, exposed) }) @@ -211,7 +211,7 @@ func TestIntegrationDecrypt(t *testing.T) { authCtx := createAuthContext(ctx, "default", []string{"secret.grafana.app/securevalues/" + svName + ":read"}, svcIdentity, types.TypeUser) // Setup service - decryptSvc, secureValueMetadataStorage, keeperService, keeperMetadataService := setupDecryptTestService(t, map[string]struct{}{svcIdentity: {}}) + sut := testutils.Setup(t) // Create a secure value spec := secretv0alpha1.SecureValueSpec{ @@ -223,9 +223,10 @@ func TestIntegrationDecrypt(t *testing.T) { sv.Name = svName sv.Namespace = "default" - newTestSecureValue(authCtx, t, secureValueMetadataStorage, keeperService, keeperMetadataService, sv, "actor-uid") + _, err := sut.CreateSv(authCtx, testutils.CreateSvWithSv(sv)) + require.NoError(t, err) - exposed, err := decryptSvc.Decrypt(authCtx, "default", svName) + exposed, err := sut.DecryptStorage.Decrypt(authCtx, "default", svName) require.ErrorIs(t, err, contracts.ErrDecryptNotAuthorized) require.Empty(t, exposed) }) @@ -242,7 +243,7 @@ func TestIntegrationDecrypt(t *testing.T) { authCtx := createAuthContext(ctx, "default", []string{"secret.grafana.app/securevalues/:decrypt"}, svcIdentity, types.TypeUser) // Setup service - decryptSvc, secureValueMetadataStorage, keeperService, keeperMetadataService := setupDecryptTestService(t, map[string]struct{}{svcIdentity: {}}) + sut := testutils.Setup(t) // Create a secure value spec := secretv0alpha1.SecureValueSpec{ @@ -254,9 +255,10 @@ func TestIntegrationDecrypt(t *testing.T) { sv.Name = "sv-test" sv.Namespace = "default" - newTestSecureValue(authCtx, t, secureValueMetadataStorage, keeperService, keeperMetadataService, sv, "actor-uid") + _, err := sut.CreateSv(authCtx, testutils.CreateSvWithSv(sv)) + require.NoError(t, err) - exposed, err := decryptSvc.Decrypt(authCtx, "default", "sv-test") + exposed, err := sut.DecryptStorage.Decrypt(authCtx, "default", "sv-test") require.ErrorIs(t, err, contracts.ErrDecryptNotAuthorized) require.Empty(t, exposed) }) @@ -274,7 +276,7 @@ func TestIntegrationDecrypt(t *testing.T) { authCtx := createAuthContext(ctx, "default", []string{"wrong.group/securevalues/" + svName + ":decrypt"}, svcIdentity, types.TypeUser) // Setup service - decryptSvc, secureValueMetadataStorage, keeperService, keeperMetadataService := setupDecryptTestService(t, map[string]struct{}{svcIdentity: {}}) + sut := testutils.Setup(t) // Create a secure value spec := secretv0alpha1.SecureValueSpec{ @@ -286,9 +288,10 @@ func TestIntegrationDecrypt(t *testing.T) { sv.Name = svName sv.Namespace = "default" - newTestSecureValue(authCtx, t, secureValueMetadataStorage, keeperService, keeperMetadataService, sv, "actor-uid") + _, err := sut.CreateSv(authCtx, testutils.CreateSvWithSv(sv)) + require.NoError(t, err) - exposed, err := decryptSvc.Decrypt(authCtx, "default", svName) + exposed, err := sut.DecryptStorage.Decrypt(authCtx, "default", svName) require.Error(t, err) require.Equal(t, err.Error(), "not authorized") require.Empty(t, exposed) @@ -297,62 +300,6 @@ func TestIntegrationDecrypt(t *testing.T) { // TODO: add more tests for keeper failure scenarios, lets see how the async work will change this though. } -func setupDecryptTestService(t *testing.T, allowList map[string]struct{}) (*decryptStorage, contracts.SecureValueMetadataStorage, *secretkeeper.OSSKeeperService, contracts.KeeperMetadataStorage) { - t.Helper() - - // Initialize infra dependencies - cfg := &setting.Cfg{ - SecretsManagement: setting.SecretsManagerSettings{ - SecretKey: "sdDkslslld", - EncryptionProvider: "secretKey.v1", - }, - } - - features := featuremgmt.WithFeatures( - featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, - featuremgmt.FlagSecretsManagementAppPlatform, - ) - - db := sqlstore.NewTestStore(t, sqlstore.WithMigrator(migrator.New())) - tracer := noop.NewTracerProvider().Tracer("test") - database := database.ProvideDatabase(db, tracer) - - // Initialize encryption manager and storage - dataKeyStore, err := encryptionstorage.ProvideDataKeyStorage(database, tracer, features, nil) - require.NoError(t, err) - - encValueStore, err := encryptionstorage.ProvideEncryptedValueStorage(database, tracer, features) - require.NoError(t, err) - - encryptionManager, err := encryptionmanager.ProvideEncryptionManager( - tracer, - dataKeyStore, - cfg, - &usagestats.UsageStatsMock{}, - encryption.ProviderMap{}, - ) - require.NoError(t, err) - - // Initialize the keeper service - keeperService, err := secretkeeper.ProvideService(tracer, encValueStore, encryptionManager, nil) - require.NoError(t, err) - - keeperMetadataStorage, err := ProvideKeeperMetadataStorage(database, tracer, features, nil) - require.NoError(t, err) - - // Initialize the secure value storage - secureValueMetadataStorage, err := ProvideSecureValueMetadataStorage(database, tracer, features, nil) - require.NoError(t, err) - - decryptAuthorizer := decrypt.ProvideDecryptAuthorizer(tracer, allowList) - - // Initialize the decrypt storage - decryptSvc, err := ProvideDecryptStorage(features, tracer, keeperService, keeperMetadataStorage, secureValueMetadataStorage, decryptAuthorizer, nil) - require.NoError(t, err) - - return decryptSvc.(*decryptStorage), secureValueMetadataStorage, keeperService, keeperMetadataStorage -} - func createAuthContext(ctx context.Context, namespace string, permissions []string, svc string, identityType types.IdentityType) context.Context { requester := &identity.StaticRequester{ Type: identityType, @@ -371,32 +318,3 @@ func createAuthContext(ctx context.Context, namespace string, permissions []stri return types.WithAuthInfo(ctx, requester) } - -// This helper will also delete the secureValue from the db when the test is done. -func newTestSecureValue(ctx context.Context, t *testing.T, db contracts.SecureValueMetadataStorage, keeperService *secretkeeper.OSSKeeperService, keeperMetadataStorage contracts.KeeperMetadataStorage, sv *secretv0alpha1.SecureValue, actorUID string) { - t.Helper() - - _, err := db.Create(ctx, sv, actorUID) - require.NoError(t, err) - - require.NoError(t, err) - - // Since creating secrets is async, store the secret in the keeper synchronously to make testing easier - cfg, err := keeperMetadataStorage.GetKeeperConfig(ctx, sv.Namespace, sv.Spec.Keeper, contracts.ReadOpts{}) - require.NoError(t, err) - - keeper, err := keeperService.KeeperForConfig(cfg) - require.NoError(t, err) - - externalID, err := keeper.Store(ctx, cfg, sv.Namespace, sv.Spec.Value.DangerouslyExposeAndConsumeValue()) - require.NoError(t, err) - - // Set external id for the secure value - err = db.SetExternalID(ctx, xkube.Namespace(sv.Namespace), sv.Name, externalID) - require.NoError(t, err) - - t.Cleanup(func() { - require.NoError(t, keeper.Delete(ctx, cfg, sv.Namespace, externalID)) - require.NoError(t, db.Delete(ctx, xkube.Namespace(sv.Namespace), sv.Name)) - }) -} diff --git a/pkg/storage/secret/metadata/keeper_store_test.go b/pkg/storage/secret/metadata/keeper_store_test.go index 644b3ccf714..c5da14eaf2d 100644 --- a/pkg/storage/secret/metadata/keeper_store_test.go +++ b/pkg/storage/secret/metadata/keeper_store_test.go @@ -1,4 +1,4 @@ -package metadata +package metadata_test import ( "context" @@ -10,6 +10,7 @@ import ( "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/storage/secret/database" + "github.com/grafana/grafana/pkg/storage/secret/metadata" "github.com/grafana/grafana/pkg/storage/secret/migrator" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" @@ -340,7 +341,7 @@ func initStorage(t *testing.T) contracts.KeeperMetadataStorage { features := featuremgmt.WithFeatures(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, featuremgmt.FlagSecretsManagementAppPlatform) // Initialize the keeper storage - keeperMetadataStorage, err := ProvideKeeperMetadataStorage(db, tracer, features, nil) + keeperMetadataStorage, err := metadata.ProvideKeeperMetadataStorage(db, tracer, features, nil) require.NoError(t, err) return keeperMetadataStorage } diff --git a/pkg/storage/secret/metadata/metrics/metrics.go b/pkg/storage/secret/metadata/metrics/metrics.go index bffbaebc604..bedaa03b4f8 100644 --- a/pkg/storage/secret/metadata/metrics/metrics.go +++ b/pkg/storage/secret/metadata/metrics/metrics.go @@ -13,16 +13,6 @@ const ( // StorageMetrics is a struct that contains all the metrics for all operations of secrets storage. type StorageMetrics struct { - OutboxAppendDuration *prometheus.HistogramVec - OutboxReceiveDuration prometheus.Histogram - OutboxAppendCount *prometheus.CounterVec - OutboxReceiveCount prometheus.Counter - OutboxDeleteDuration prometheus.Histogram - OutboxDeleteCount prometheus.Counter - OutboxIncrementReceiveCountDuration prometheus.Histogram - OutboxIncrementReceiveCountCount prometheus.Counter - OutboxTotalMessageLifetimeDuration *prometheus.HistogramVec - KeeperMetadataCreateDuration *prometheus.HistogramVec KeeperMetadataCreateCount *prometheus.CounterVec KeeperMetadataUpdateDuration *prometheus.HistogramVec @@ -55,67 +45,6 @@ type StorageMetrics struct { func newStorageMetrics() *StorageMetrics { return &StorageMetrics{ - // Outbox metrics - OutboxAppendDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_append_duration_seconds", - Help: "Duration of outbox message append operations", - Buckets: prometheus.DefBuckets, - }, []string{"message_type"}), - OutboxAppendCount: prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_append_count", - Help: "Count of outbox message append operations", - }, []string{"message_type"}), - OutboxReceiveDuration: prometheus.NewHistogram(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_receive_duration_seconds", - Help: "Duration of outbox message receive operations", - Buckets: prometheus.DefBuckets, - }), - OutboxReceiveCount: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_receive_count", - Help: "Count of outbox message receive operations", - }), - OutboxDeleteDuration: prometheus.NewHistogram(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_delete_duration_seconds", - Help: "Duration of outbox message delete operations", - Buckets: prometheus.DefBuckets, - }), - OutboxDeleteCount: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_delete_count", - Help: "Count of outbox message delete operations", - }), - OutboxIncrementReceiveCountDuration: prometheus.NewHistogram(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_increment_receive_count_duration_seconds", - Help: "Duration of outbox message increment receive count operations", - Buckets: prometheus.DefBuckets, - }), - OutboxIncrementReceiveCountCount: prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_increment_receive_count_count", - Help: "Count of outbox message increment receive count operations", - }), - OutboxTotalMessageLifetimeDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "outbox_total_message_lifetime_duration_seconds", - Help: "Total duration of outbox message lifetime", - Buckets: prometheus.DefBuckets, - }, []string{"message_type"}), - // Keeper metrics KeeperMetadataCreateDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ Namespace: namespace, @@ -307,15 +236,6 @@ func NewStorageMetrics(reg prometheus.Registerer) *StorageMetrics { if reg != nil { reg.MustRegister( - m.OutboxAppendDuration, - m.OutboxAppendCount, - m.OutboxReceiveDuration, - m.OutboxReceiveCount, - m.OutboxDeleteDuration, - m.OutboxDeleteCount, - m.OutboxIncrementReceiveCountDuration, - m.OutboxIncrementReceiveCountCount, - m.OutboxTotalMessageLifetimeDuration, m.KeeperMetadataCreateDuration, m.KeeperMetadataCreateCount, m.KeeperMetadataUpdateDuration, diff --git a/pkg/storage/secret/metadata/outbox_store.go b/pkg/storage/secret/metadata/outbox_store.go deleted file mode 100644 index efe569384f4..00000000000 --- a/pkg/storage/secret/metadata/outbox_store.go +++ /dev/null @@ -1,397 +0,0 @@ -package metadata - -import ( - "context" - "database/sql" - "fmt" - "time" - - "github.com/grafana/grafana/pkg/storage/secret/metadata/metrics" - unifiedsql "github.com/grafana/grafana/pkg/storage/unified/sql" - "github.com/prometheus/client_golang/prometheus" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/trace" - - "github.com/grafana/grafana/pkg/registry/apis/secret/assert" - "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" - "github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate" -) - -type outboxStore struct { - db contracts.Database - dialect sqltemplate.Dialect - tracer trace.Tracer - metrics *metrics.StorageMetrics -} - -func ProvideOutboxQueue( - db contracts.Database, - tracer trace.Tracer, - reg prometheus.Registerer, -) contracts.OutboxQueue { - return &outboxStore{ - db: db, - dialect: sqltemplate.DialectForDriver(db.DriverName()), - metrics: metrics.NewStorageMetrics(reg), - tracer: tracer, - } -} - -type outboxMessageDB struct { - RequestID string - MessageID int64 - MessageType contracts.OutboxMessageType - Name string - Namespace string - EncryptedSecret sql.NullString - KeeperName sql.NullString - ExternalID sql.NullString - ReceiveCount int - Created int64 -} - -func (s *outboxStore) Append(ctx context.Context, input contracts.AppendOutboxMessage) (messageID int64, err error) { - ctx, span := s.tracer.Start(ctx, "outboxStore.Append", trace.WithAttributes( - attribute.String("name", input.Name), - attribute.String("namespace", input.Namespace), - attribute.String("type", string(input.Type)), - attribute.String("requestID", input.RequestID), - )) - defer span.End() - - defer func() { - if err != nil { - span.SetStatus(codes.Error, "failed to append outbox message") - span.RecordError(err) - } - - if messageID != 0 { - span.SetAttributes(attribute.Int64("messageID", messageID)) - } - }() - - assert.True(input.Type != "", "outboxStore.Append: outbox message type is required") - - start := time.Now() - messageID, err = s.insertMessage(ctx, input) - if err != nil { - return messageID, fmt.Errorf("inserting message into outbox table: %+w", err) - } - - s.metrics.OutboxAppendDuration.WithLabelValues(string(input.Type)).Observe(time.Since(start).Seconds()) - s.metrics.OutboxAppendCount.WithLabelValues(string(input.Type)).Inc() - - return messageID, nil -} - -func (s *outboxStore) insertMessage(ctx context.Context, input contracts.AppendOutboxMessage) (int64, error) { - keeperName := sql.NullString{} - if input.KeeperName != nil { - keeperName = sql.NullString{ - Valid: true, - String: *input.KeeperName, - } - } - - externalID := sql.NullString{} - if input.ExternalID != nil { - externalID = sql.NullString{ - Valid: true, - String: *input.ExternalID, - } - } - - encryptedSecret := sql.NullString{} - if input.Type == contracts.CreateSecretOutboxMessage || input.Type == contracts.UpdateSecretOutboxMessage { - encryptedSecret = sql.NullString{ - Valid: true, - String: input.EncryptedSecret, - } - } - - req := appendSecureValueOutbox{ - SQLTemplate: sqltemplate.New(s.dialect), - Row: &outboxMessageDB{ - RequestID: input.RequestID, - MessageType: input.Type, - Name: input.Name, - Namespace: input.Namespace, - EncryptedSecret: encryptedSecret, - KeeperName: keeperName, - ExternalID: externalID, - ReceiveCount: 0, - Created: time.Now().UTC().UnixMilli(), - }, - } - - query, err := sqltemplate.Execute(sqlSecureValueOutboxAppend, req) - if err != nil { - return 0, fmt.Errorf("execute template %q: %w", sqlSecureValueOutboxAppend.Name(), err) - } - - result, err := s.db.ExecContext(ctx, query, req.GetArgs()...) - if err != nil { - if unifiedsql.IsRowAlreadyExistsError(err) { - return 0, contracts.ErrSecureValueOperationInProgress - } - return 0, fmt.Errorf("inserting message into secure value outbox table: %w", err) - } - - rowsAffected, err := result.RowsAffected() - if err != nil { - return 0, fmt.Errorf("get rows affected: %w", err) - } - - if rowsAffected != 1 { - return 0, fmt.Errorf("expected to affect 1 row, but affected %d", rowsAffected) - } - - id, err := result.LastInsertId() - if err != nil { - return id, fmt.Errorf("fetching last inserted id: %w", err) - } - - return id, nil -} - -func (s *outboxStore) ReceiveN(ctx context.Context, limit uint) ([]contracts.OutboxMessage, error) { - messageIDs, err := s.fetchMessageIdsInQueue(ctx, limit) - if err != nil { - return nil, fmt.Errorf("fetching message ids from queue: %w", err) - } - // If queue is empty - if len(messageIDs) == 0 { - return nil, nil - } - req := receiveNSecureValueOutbox{ - SQLTemplate: sqltemplate.New(s.dialect), - MessageIDs: messageIDs, - } - - start := time.Now() - query, err := sqltemplate.Execute(sqlSecureValueOutboxReceiveN, req) - if err != nil { - return nil, fmt.Errorf("execute template %q: %w", sqlSecureValueOutboxReceiveN.Name(), err) - } - - rows, err := s.db.QueryContext(ctx, query, req.GetArgs()...) - if err != nil { - return nil, fmt.Errorf("fetching rows from secure value outbox table: %w", err) - } - defer func() { _ = rows.Close() }() - - messages := make([]contracts.OutboxMessage, 0) - - for rows.Next() { - var row outboxMessageDB - if err := rows.Scan( - &row.RequestID, - &row.MessageID, - &row.MessageType, - &row.Name, - &row.Namespace, - &row.EncryptedSecret, - &row.KeeperName, - &row.ExternalID, - &row.ReceiveCount, - &row.Created, - ); err != nil { - return nil, fmt.Errorf("scanning row from secure value outbox table: %w", err) - } - - var keeperName *string - if row.KeeperName.Valid { - keeperName = &row.KeeperName.String - } - - var externalID *string - if row.ExternalID.Valid { - externalID = &row.ExternalID.String - } - - msg := contracts.OutboxMessage{ - RequestID: row.RequestID, - Type: row.MessageType, - MessageID: row.MessageID, - Name: row.Name, - Namespace: row.Namespace, - KeeperName: keeperName, - ExternalID: externalID, - ReceiveCount: row.ReceiveCount, - Created: row.Created, - } - - if row.MessageType != contracts.DeleteSecretOutboxMessage && row.EncryptedSecret.Valid { - msg.EncryptedSecret = row.EncryptedSecret.String - } - - messages = append(messages, msg) - } - - if err := rows.Err(); err != nil { - return messages, fmt.Errorf("reading rows: %w", err) - } - - s.metrics.OutboxReceiveDuration.Observe(time.Since(start).Seconds()) - s.metrics.OutboxReceiveCount.Add(float64(len(messages))) - - return messages, nil -} - -func (s *outboxStore) fetchMessageIdsInQueue(ctx context.Context, limit uint) ([]int64, error) { - req := fetchMessageIDsOutbox{ - SQLTemplate: sqltemplate.New(s.dialect), - ReceiveLimit: limit, - } - - query, err := sqltemplate.Execute(sqlSecureValueOutboxFetchMessageIDs, req) - if err != nil { - return nil, fmt.Errorf("execute template %q: %w", sqlSecureValueOutboxFetchMessageIDs.Name(), err) - } - - rows, err := s.db.QueryContext(ctx, query, req.GetArgs()...) - if err != nil { - return nil, fmt.Errorf("fetching rows from secure value outbox table: %w", err) - } - defer func() { _ = rows.Close() }() - - messageIDs := make([]int64, 0, limit) - - for rows.Next() { - var id int64 - if err := rows.Scan(&id); err != nil { - return nil, fmt.Errorf("scanning row; %w", err) - } - messageIDs = append(messageIDs, id) - } - - if err := rows.Err(); err != nil { - return nil, fmt.Errorf("reading rows: %w", err) - } - - return messageIDs, nil -} - -func (s *outboxStore) Delete(ctx context.Context, messageID int64) (err error) { - ctx, span := s.tracer.Start(ctx, "outboxStore.Append", trace.WithAttributes( - attribute.Int64("messageID", messageID), - )) - defer span.End() - - defer func() { - if err != nil { - span.SetStatus(codes.Error, "failed to delete message from outbox") - span.RecordError(err) - } - }() - - assert.True(messageID != 0, "outboxStore.Delete: messageID is required") - - start := time.Now() - if err := s.deleteMessage(ctx, messageID); err != nil { - return fmt.Errorf("deleting message from outbox table %+w", err) - } - - s.metrics.OutboxDeleteDuration.Observe(time.Since(start).Seconds()) - s.metrics.OutboxDeleteCount.Inc() - - return nil -} - -func (s *outboxStore) deleteMessage(ctx context.Context, messageID int64) error { - tsReq := getOutboxMessageTimestamp{ - SQLTemplate: sqltemplate.New(s.dialect), - MessageID: messageID, - } - - // First query the object so we can get the timestamp and calculate the total lifetime - timestampQuery, err := sqltemplate.Execute(sqlSecureValueOutboxQueryTimestamp, tsReq) - if err != nil { - return fmt.Errorf("execute template %q: %w", sqlSecureValueOutboxQueryTimestamp.Name(), err) - } - - rows, err := s.db.QueryContext(ctx, timestampQuery, tsReq.GetArgs()...) - if err != nil { - return fmt.Errorf("querying timestamp from secure value outbox table: %w", err) - } - - if !rows.Next() { - _ = rows.Close() - return fmt.Errorf("no row found for message id=%v", messageID) - } - - var timestamp int64 - var messageType string - if err := rows.Scan(×tamp, &messageType); err != nil { - _ = rows.Close() - return fmt.Errorf("scanning timestamp: %w", err) - } - - // Explicitly close rows and check for errors before proceeding - if err := rows.Close(); err != nil { - return fmt.Errorf("closing rows: %w", err) - } - - if err := rows.Err(); err != nil { - return fmt.Errorf("rows error: %w", err) - } - - totalLifetime := time.Since(time.UnixMilli(timestamp)) - s.metrics.OutboxTotalMessageLifetimeDuration.WithLabelValues(messageType).Observe(totalLifetime.Seconds()) - - // Then delete the object - delReq := deleteSecureValueOutbox{ - SQLTemplate: sqltemplate.New(s.dialect), - MessageID: messageID, - } - - query, err := sqltemplate.Execute(sqlSecureValueOutboxDelete, delReq) - if err != nil { - return fmt.Errorf("execute template %q: %w", sqlSecureValueOutboxDelete.Name(), err) - } - - result, err := s.db.ExecContext(ctx, query, delReq.GetArgs()...) - if err != nil { - return fmt.Errorf("deleting message id=%v from secure value outbox table: %w", messageID, err) - } - - rowsAffected, err := result.RowsAffected() - if err != nil { - return fmt.Errorf("get rows affected: %w", err) - } - - // TODO: Presumably it's a bug if we delete 0 rows? - if rowsAffected > 1 { - return fmt.Errorf("bug: deleted more than one row from the outbox table, should delete only one at a time: deleted=%v", rowsAffected) - } - - return nil -} - -func (s *outboxStore) IncrementReceiveCount(ctx context.Context, messageIDs []int64) error { - if len(messageIDs) == 0 { - return nil - } - - req := incrementReceiveCountOutbox{ - SQLTemplate: sqltemplate.New(s.dialect), - MessageIDs: messageIDs, - } - - start := time.Now() - query, err := sqltemplate.Execute(sqlSecureValueOutboxUpdateReceiveCount, req) - if err != nil { - return fmt.Errorf("execute template %q: %w", sqlSecureValueOutboxUpdateReceiveCount.Name(), err) - } - - _, err = s.db.ExecContext(ctx, query, req.GetArgs()...) - if err != nil { - return fmt.Errorf("updating outbox messages receive count: %w", err) - } - - s.metrics.OutboxIncrementReceiveCountDuration.Observe(time.Since(start).Seconds()) - s.metrics.OutboxIncrementReceiveCountCount.Add(float64(len(messageIDs))) - - return nil -} diff --git a/pkg/storage/secret/metadata/outbox_store_test.go b/pkg/storage/secret/metadata/outbox_store_test.go deleted file mode 100644 index f757e8b6b38..00000000000 --- a/pkg/storage/secret/metadata/outbox_store_test.go +++ /dev/null @@ -1,269 +0,0 @@ -package metadata - -import ( - "context" - "fmt" - "math/rand" - "slices" - "testing" - "time" - - "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" - "github.com/grafana/grafana/pkg/services/sqlstore" - "github.com/grafana/grafana/pkg/storage/secret/database" - "github.com/grafana/grafana/pkg/storage/secret/migrator" - "github.com/stretchr/testify/require" - "go.opentelemetry.io/otel/trace/noop" -) - -type outboxStoreModel struct { - rows []contracts.OutboxMessage -} - -func newOutboxStoreModel() *outboxStoreModel { - return &outboxStoreModel{} -} - -func (model *outboxStoreModel) Append(messageID int64, message contracts.AppendOutboxMessage) { - model.rows = append(model.rows, contracts.OutboxMessage{ - Type: message.Type, - MessageID: messageID, - Name: message.Name, - Namespace: message.Namespace, - EncryptedSecret: message.EncryptedSecret, - KeeperName: message.KeeperName, - ExternalID: message.ExternalID, - }) -} - -func (model *outboxStoreModel) ReceiveN(n uint) []contracts.OutboxMessage { - maxMessages := min(len(model.rows), int(n)) - if maxMessages == 0 { - return nil - } - return model.rows[:maxMessages] -} - -func (model *outboxStoreModel) Delete(messageID int64) { - oldLen := len(model.rows) - model.rows = slices.DeleteFunc(model.rows, func(m contracts.OutboxMessage) bool { - return m.MessageID == messageID - }) - if len(model.rows) != oldLen-1 { - panic("Delete: deleted more than one message") - } -} - -func TestOutboxStoreModel(t *testing.T) { - t.Parallel() - - model := newOutboxStoreModel() - - require.Empty(t, model.ReceiveN(10)) - - appendOutboxMessage := contracts.AppendOutboxMessage{ - Type: contracts.CreateSecretOutboxMessage, - Name: "s-1", - Namespace: "n-1", - EncryptedSecret: "value", - ExternalID: nil, - } - - outboxMessage1 := contracts.OutboxMessage{ - MessageID: 1, - Type: contracts.CreateSecretOutboxMessage, - Name: "s-1", - Namespace: "n-1", - EncryptedSecret: "value", - ExternalID: nil, - } - - outboxMessage2 := contracts.OutboxMessage{ - MessageID: 2, - Type: contracts.CreateSecretOutboxMessage, - Name: "s-1", - Namespace: "n-1", - EncryptedSecret: "value", - ExternalID: nil, - } - - model.Append(1, appendOutboxMessage) - - require.Equal(t, []contracts.OutboxMessage{outboxMessage1}, model.ReceiveN(10)) - - model.Append(2, appendOutboxMessage) - - require.Equal(t, []contracts.OutboxMessage{outboxMessage1, outboxMessage2}, model.ReceiveN(10)) - - model.Delete(outboxMessage1.MessageID) - - require.Equal(t, []contracts.OutboxMessage{outboxMessage2}, model.ReceiveN(5)) - - model.Delete(outboxMessage2.MessageID) - - require.Empty(t, model.ReceiveN(1)) -} - -func TestOutboxStoreSecureValueOperationInProgress(t *testing.T) { - t.Parallel() - - t.Run("Append returns error when the queue already contains an operation for the secure value", func(t *testing.T) { - t.Parallel() - - testDB := sqlstore.NewTestStore(t, sqlstore.WithMigrator(migrator.New())) - tracer := noop.NewTracerProvider().Tracer("test") - - ctx := context.Background() - - outbox := ProvideOutboxQueue(database.ProvideDatabase(testDB, tracer), tracer, nil) - - _, err := outbox.Append(ctx, contracts.AppendOutboxMessage{ - RequestID: "1", - Type: contracts.CreateSecretOutboxMessage, - Name: "name1", - Namespace: "ns1", - EncryptedSecret: "v1", - KeeperName: nil, - ExternalID: nil, - }) - require.NoError(t, err) - - _, err = outbox.Append(ctx, contracts.AppendOutboxMessage{ - RequestID: "1", - Type: contracts.UpdateSecretOutboxMessage, - Name: "name1", - Namespace: "ns1", - EncryptedSecret: "v1", - KeeperName: nil, - ExternalID: nil, - }) - - require.ErrorIs(t, err, contracts.ErrSecureValueOperationInProgress) - }) -} - -func TestOutboxStore(t *testing.T) { - testDB := sqlstore.NewTestStore(t, sqlstore.WithMigrator(migrator.New())) - tracer := noop.NewTracerProvider().Tracer("test") - - ctx := context.Background() - - outbox := ProvideOutboxQueue(database.ProvideDatabase(testDB, tracer), tracer, nil) - - m1 := contracts.AppendOutboxMessage{ - Type: contracts.CreateSecretOutboxMessage, - Name: "s-1", - Namespace: "n-1", - EncryptedSecret: "value", - ExternalID: nil, - } - m2 := contracts.AppendOutboxMessage{ - Type: contracts.CreateSecretOutboxMessage, - Name: "s-1", - Namespace: "n-2", - EncryptedSecret: "value", - ExternalID: nil, - } - - messages, err := outbox.ReceiveN(ctx, 10) - require.NoError(t, err) - require.Empty(t, messages) - - messageID1, err := outbox.Append(ctx, m1) - require.NoError(t, err) - - for range 2 { - messages, err = outbox.ReceiveN(ctx, 10) - require.NoError(t, err) - require.Equal(t, 1, len(messages)) - require.Equal(t, messageID1, messages[0].MessageID) - } - - messageID2, err := outbox.Append(ctx, m2) - require.NoError(t, err) - - messages, err = outbox.ReceiveN(ctx, 3) - require.NoError(t, err) - require.Equal(t, 2, len(messages)) - require.Equal(t, messageID1, messages[0].MessageID) - require.Equal(t, messageID2, messages[1].MessageID) - - require.NoError(t, outbox.Delete(ctx, messageID1)) - messages, err = outbox.ReceiveN(ctx, 10) - require.NoError(t, err) - require.Equal(t, 1, len(messages)) - require.Equal(t, messageID2, messages[0].MessageID) - - require.NoError(t, outbox.Delete(ctx, messageID2)) - - messages, err = outbox.ReceiveN(ctx, 100) - require.NoError(t, err) - require.Empty(t, messages) -} - -func TestOutboxStoreProperty(t *testing.T) { - seed := time.Now().UnixMicro() - rng := rand.New(rand.NewSource(seed)) - - defer func() { - if t.Failed() { - fmt.Printf("TestOutboxStoreProperty: SEED=%+v\n\n", seed) - } - }() - - // The number of iterations was decided arbitrarily based on the time the test takes to run - for range 10 { - testDB := sqlstore.NewTestStore(t, sqlstore.WithMigrator(migrator.New())) - tracer := noop.NewTracerProvider().Tracer("test") - - outbox := ProvideOutboxQueue(database.ProvideDatabase(testDB, tracer), tracer, nil) - - model := newOutboxStoreModel() - - ctx := context.Background() - - for i := range 100 { - n := rng.Intn(3) - switch n { - case 0: - time.Sleep(1 * time.Microsecond) - message := contracts.AppendOutboxMessage{ - Type: contracts.CreateSecretOutboxMessage, - Name: fmt.Sprintf("s-%d", i), - Namespace: fmt.Sprintf("n-%d", i), - EncryptedSecret: "value", - ExternalID: nil, - } - messageID, err := outbox.Append(ctx, message) - require.NoError(t, err) - - model.Append(messageID, message) - - case 1: - n := uint(rng.Intn(10)) - messages, err := outbox.ReceiveN(ctx, n) - require.NoError(t, err) - - modelMessages := model.ReceiveN(n) - - require.Equal(t, len(modelMessages), len(messages)) - for i := range len(modelMessages) { - require.Equal(t, modelMessages[i].MessageID, messages[i].MessageID) - } - - case 2: - if len(model.rows) == 0 { - continue - } - - message := model.rows[rng.Intn(len(model.rows))] - - model.Delete(message.MessageID) - require.NoError(t, outbox.Delete(ctx, message.MessageID)) - - default: - panic(fmt.Sprintf("unhandled action: %+v", n)) - } - } - } -} diff --git a/pkg/storage/secret/metadata/query.go b/pkg/storage/secret/metadata/query.go index 907a4d6cbea..2c85d762b87 100644 --- a/pkg/storage/secret/metadata/query.go +++ b/pkg/storage/secret/metadata/query.go @@ -27,18 +27,12 @@ var ( sqlSecureValueRead = mustTemplate("secure_value_read.sql") sqlSecureValueList = mustTemplate("secure_value_list.sql") sqlSecureValueCreate = mustTemplate("secure_value_create.sql") - sqlSecureValueDelete = mustTemplate("secure_value_delete.sql") - sqlSecureValueUpdate = mustTemplate("secure_value_update.sql") sqlSecureValueUpdateExternalId = mustTemplate("secure_value_updateExternalId.sql") - sqlSecureValueUpdateStatus = mustTemplate("secure_value_updateStatus.sql") sqlSecureValueReadForDecrypt = mustTemplate("secure_value_read_for_decrypt.sql") - sqlSecureValueOutboxAppend = mustTemplate("secure_value_outbox_append.sql") - sqlSecureValueOutboxFetchMessageIDs = mustTemplate("secure_value_outbox_fetch_message_ids.sql") - sqlSecureValueOutboxReceiveN = mustTemplate("secure_value_outbox_receiveN.sql") - sqlSecureValueOutboxDelete = mustTemplate("secure_value_outbox_delete.sql") - sqlSecureValueOutboxUpdateReceiveCount = mustTemplate("secure_value_outbox_update_receive_count.sql") - sqlSecureValueOutboxQueryTimestamp = mustTemplate("secure_value_outbox_query_timestamp.sql") + sqlGetLatestSecureValueVersion = mustTemplate("secure_value_get_latest_version.sql") + sqlSecureValueSetVersionToActive = mustTemplate("secure_value_set_version_to_active.sql") + sqlSecureValueSetVersionToInactive = mustTemplate("secure_value_set_version_to_inactive.sql") ) func mustTemplate(filename string) *template.Template { @@ -150,6 +144,38 @@ func (r readSecureValue) Validate() error { return nil // TODO } +type getLatestSecureValueVersion struct { + sqltemplate.SQLTemplate + Namespace string + Name string +} + +func (r getLatestSecureValueVersion) Validate() error { + return nil +} + +type secureValueSetVersionToActive struct { + sqltemplate.SQLTemplate + Namespace string + Name string + Version int64 +} + +func (r secureValueSetVersionToActive) Validate() error { + return nil +} + +type secureValueSetVersionToInactive struct { + sqltemplate.SQLTemplate + Namespace string + Name string + Version int64 +} + +func (r secureValueSetVersionToInactive) Validate() error { + return nil +} + type listSecureValue struct { sqltemplate.SQLTemplate Namespace string @@ -170,23 +196,12 @@ func (r createSecureValue) Validate() error { return nil // TODO } -// Delete -type deleteSecureValue struct { - sqltemplate.SQLTemplate - Namespace string - Name string -} - -// Validate is only used if we use `dbutil` from `unifiedstorage` -func (r deleteSecureValue) Validate() error { - return nil // TODO -} - // Update externalId type updateExternalIdSecureValue struct { sqltemplate.SQLTemplate Namespace string Name string + Version int64 ExternalID string } @@ -195,33 +210,6 @@ func (r updateExternalIdSecureValue) Validate() error { return nil // TODO } -// Update secure value -type updateSecureValue struct { - sqltemplate.SQLTemplate - Namespace string - Name string - Row *secureValueDB -} - -// Validate is only used if we use `dbutil` from `unifiedstorage` -func (r updateSecureValue) Validate() error { - return nil // TODO -} - -// update status message -type updateStatusSecureValue struct { - sqltemplate.SQLTemplate - Namespace string - Name string - Phase string - Message string -} - -// Validate is only used if we use `dbutil` from `unifiedstorage` -func (r updateStatusSecureValue) Validate() error { - return nil // TODO -} - type readSecureValueForDecrypt struct { sqltemplate.SQLTemplate Namespace string @@ -229,48 +217,3 @@ type readSecureValueForDecrypt struct { } func (r readSecureValueForDecrypt) Validate() error { return nil } - -/*************************************/ -/**-- Secure Value Outbox Queries --**/ -/*************************************/ -type appendSecureValueOutbox struct { - sqltemplate.SQLTemplate - Row *outboxMessageDB -} - -func (appendSecureValueOutbox) Validate() error { return nil } - -type receiveNSecureValueOutbox struct { - sqltemplate.SQLTemplate - MessageIDs []int64 -} - -func (receiveNSecureValueOutbox) Validate() error { return nil } - -type fetchMessageIDsOutbox struct { - sqltemplate.SQLTemplate - ReceiveLimit uint -} - -func (fetchMessageIDsOutbox) Validate() error { return nil } - -type deleteSecureValueOutbox struct { - sqltemplate.SQLTemplate - MessageID int64 -} - -func (deleteSecureValueOutbox) Validate() error { return nil } - -type getOutboxMessageTimestamp struct { - sqltemplate.SQLTemplate - MessageID int64 -} - -func (getOutboxMessageTimestamp) Validate() error { return nil } - -type incrementReceiveCountOutbox struct { - sqltemplate.SQLTemplate - MessageIDs []int64 -} - -func (incrementReceiveCountOutbox) Validate() error { return nil } diff --git a/pkg/storage/secret/metadata/query_test.go b/pkg/storage/secret/metadata/query_test.go index 8a5ff0e6a9a..dce469d6d87 100644 --- a/pkg/storage/secret/metadata/query_test.go +++ b/pkg/storage/secret/metadata/query_test.go @@ -1,7 +1,6 @@ package metadata import ( - "database/sql" "testing" "text/template" @@ -123,6 +122,27 @@ func TestSecureValueQueries(t *testing.T) { mocks.CheckQuerySnapshots(t, mocks.TemplateTestSetup{ RootDir: "testdata", Templates: map[*template.Template][]mocks.TemplateTestCase{ + sqlGetLatestSecureValueVersion: { + { + Name: "get latest secure value version", + Data: &getLatestSecureValueVersion{ + SQLTemplate: mocks.NewTestingSQLTemplate(), + Name: "name", + Namespace: "ns", + }, + }, + }, + sqlSecureValueSetVersionToActive: { + { + Name: "set secure value version to active", + Data: &secureValueSetVersionToActive{ + SQLTemplate: mocks.NewTestingSQLTemplate(), + Name: "name", + Namespace: "ns", + Version: 1, + }, + }, + }, sqlSecureValueRead: { { Name: "read", @@ -166,8 +186,7 @@ func TestSecureValueQueries(t *testing.T) { CreatedBy: "user:ryan", Updated: 5678, UpdatedBy: "user:cameron", - Phase: "creating", - Message: toNullString(nil), + Version: 1, Description: "description", Keeper: toNullString(nil), Decrypters: toNullString(nil), @@ -190,72 +209,7 @@ func TestSecureValueQueries(t *testing.T) { CreatedBy: "user:ryan", Updated: 5678, UpdatedBy: "user:cameron", - Phase: "creating", - Message: toNullString(ptr.To("message_test")), - Description: "description", - Keeper: toNullString(ptr.To("keeper_test")), - Decrypters: toNullString(ptr.To("decrypters_test")), - Ref: toNullString(ptr.To("ref_test")), - ExternalID: "extId", - }, - }, - }, - }, - sqlSecureValueDelete: { - { - Name: "delete", - Data: &deleteSecureValue{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - Name: "name", - Namespace: "ns", - }, - }, - }, - sqlSecureValueUpdate: { - { - Name: "update-null", - Data: &updateSecureValue{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - Name: "name", - Namespace: "ns", - Row: &secureValueDB{ - GUID: "abc", - Name: "name", - Namespace: "ns", - Annotations: `{"x":"XXXX"}`, - Labels: `{"a":"AAA", "b", "BBBB"}`, - Created: 1234, - CreatedBy: "user:ryan", - Updated: 5678, - UpdatedBy: "user:cameron", - Phase: "creating", - Message: toNullString(nil), - Description: "description", - Keeper: toNullString(nil), - Decrypters: toNullString(nil), - Ref: toNullString(nil), - ExternalID: "extId", - }, - }, - }, - { - Name: "update-not-null", - Data: &updateSecureValue{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - Name: "name", - Namespace: "ns", - Row: &secureValueDB{ - GUID: "abc", - Name: "name", - Namespace: "ns", - Annotations: `{"x":"XXXX"}`, - Labels: `{"a":"AAA", "b", "BBBB"}`, - Created: 1234, - CreatedBy: "user:ryan", - Updated: 5678, - UpdatedBy: "user:cameron", - Phase: "creating", - Message: toNullString(ptr.To("message_test")), + Version: 1, Description: "description", Keeper: toNullString(ptr.To("keeper_test")), Decrypters: toNullString(ptr.To("decrypters_test")), @@ -276,18 +230,6 @@ func TestSecureValueQueries(t *testing.T) { }, }, }, - sqlSecureValueUpdateStatus: { - { - Name: "updateStatus", - Data: &updateStatusSecureValue{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - Name: "name", - Namespace: "ns", - Phase: "Succeeded", - Message: "message-1", - }, - }, - }, sqlSecureValueReadForDecrypt: { { Name: "read-for-decrypt", @@ -301,111 +243,3 @@ func TestSecureValueQueries(t *testing.T) { }, }) } - -func TestSecureValueOutboxQueries(t *testing.T) { - mocks.CheckQuerySnapshots(t, mocks.TemplateTestSetup{ - RootDir: "testdata", - Templates: map[*template.Template][]mocks.TemplateTestCase{ - sqlSecureValueOutboxUpdateReceiveCount: { - { - - Name: "update-receive-count", - Data: &incrementReceiveCountOutbox{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - MessageIDs: []int64{1, 2, 3}, - }, - }, - }, - sqlSecureValueOutboxAppend: { - { - Name: "no-encrypted-secret", - Data: &appendSecureValueOutbox{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - Row: &outboxMessageDB{ - MessageID: 1, - MessageType: "some-type", - Name: "name", - Namespace: "namespace", - ExternalID: sql.NullString{Valid: true, String: "external-id"}, - KeeperName: sql.NullString{Valid: true, String: "keeper"}, - Created: 1234, - }, - }, - }, - { - Name: "no-external-id", - Data: &appendSecureValueOutbox{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - Row: &outboxMessageDB{ - MessageID: 1, - MessageType: "some-type", - Name: "name", - Namespace: "namespace", - EncryptedSecret: sql.NullString{Valid: true, String: "encrypted"}, - KeeperName: sql.NullString{Valid: true, String: "keeper"}, - Created: 1234, - }, - }, - }, - { - Name: "no-keeper-name", - Data: &appendSecureValueOutbox{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - Row: &outboxMessageDB{ - MessageID: 1, - MessageType: "some-type", - Name: "name", - Namespace: "namespace", - EncryptedSecret: sql.NullString{Valid: true, String: "encrypted"}, - ExternalID: sql.NullString{Valid: true, String: "external-id"}, - Created: 1234, - }, - }, - }, - { - Name: "all-fields-present", - Data: &appendSecureValueOutbox{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - Row: &outboxMessageDB{ - MessageID: 1, - MessageType: "some-type", - Name: "name", - Namespace: "namespace", - EncryptedSecret: sql.NullString{Valid: true, String: "encrypted"}, - ExternalID: sql.NullString{Valid: true, String: ""}, // can be empty string - KeeperName: sql.NullString{Valid: true, String: "keeper"}, - Created: 1234, - }, - }, - }, - }, - sqlSecureValueOutboxFetchMessageIDs: { - { - Name: "basic", - Data: &fetchMessageIDsOutbox{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - ReceiveLimit: 10, - }, - }, - }, - sqlSecureValueOutboxReceiveN: { - { - Name: "basic", - Data: &receiveNSecureValueOutbox{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - MessageIDs: []int64{1, 2, 3}, - }, - }, - }, - sqlSecureValueOutboxDelete: { - { - Name: "basic", - Data: &deleteSecureValueOutbox{ - SQLTemplate: mocks.NewTestingSQLTemplate(), - MessageID: 1, - }, - }, - }, - }, - }) -} diff --git a/pkg/storage/secret/metadata/secure_value_model.go b/pkg/storage/secret/metadata/secure_value_model.go index d90beaa6782..134128f8a25 100644 --- a/pkg/storage/secret/metadata/secure_value_model.go +++ b/pkg/storage/secret/metadata/secure_value_model.go @@ -29,8 +29,8 @@ type secureValueDB struct { UpdatedBy string // Kubernetes Status - Phase string - Message sql.NullString + Active bool + Version int64 // Spec Description string @@ -74,8 +74,8 @@ func (sv *secureValueDB) toKubernetes() (*secretv0alpha1.SecureValue, error) { Decrypters: decrypters, }, Status: secretv0alpha1.SecureValueStatus{ - Phase: secretv0alpha1.SecureValuePhase(sv.Phase), ExternalID: sv.ExternalID, + Version: sv.Version, }, } @@ -85,10 +85,7 @@ func (sv *secureValueDB) toKubernetes() (*secretv0alpha1.SecureValue, error) { if sv.Ref.Valid { resource.Spec.Ref = &sv.Ref.String } - if sv.Message.Valid { - resource.Status.Message = sv.Message.String - } - resource.Status.Phase = secretv0alpha1.SecureValuePhase(sv.Phase) + resource.Status.ExternalID = sv.ExternalID // Set all meta fields here for consistency. @@ -131,24 +128,6 @@ func toCreateRow(sv *secretv0alpha1.SecureValue, actorUID string) (*secureValueD return row, nil } -// toUpdateRow maps a Kubernetes resource into a DB row for existing resources being updated. -func toUpdateRow(currentRow *secureValueDB, newSecureValue *secretv0alpha1.SecureValue, actorUID, externalID string) (*secureValueDB, error) { - row, err := toRow(newSecureValue, externalID) - if err != nil { - return nil, fmt.Errorf("failed to create: %w", err) - } - - now := time.Now().UTC().Unix() - - row.GUID = currentRow.GUID - row.Created = currentRow.Created - row.CreatedBy = currentRow.CreatedBy - row.Updated = now - row.UpdatedBy = actorUID - - return row, nil -} - // toRow maps a Kubernetes resource into a DB row. func toRow(sv *secretv0alpha1.SecureValue, externalID string) (*secureValueDB, error) { var annotations string @@ -201,11 +180,6 @@ func toRow(sv *secretv0alpha1.SecureValue, externalID string) (*secureValueDB, e return nil, fmt.Errorf("failed to get resource version: %w", err) } - var statusMessage *string - if sv.Status.Message != "" { - statusMessage = &sv.Status.Message - } - return &secureValueDB{ GUID: string(sv.UID), Name: sv.Name, @@ -217,8 +191,7 @@ func toRow(sv *secretv0alpha1.SecureValue, externalID string) (*secureValueDB, e Updated: updatedTimestamp, UpdatedBy: meta.GetUpdatedBy(), - Phase: string(sv.Status.Phase), - Message: toNullString(statusMessage), + Version: sv.Status.Version, Description: sv.Spec.Description, Keeper: toNullString(sv.Spec.Keeper), @@ -233,6 +206,7 @@ type secureValueForDecrypt struct { Keeper sql.NullString Decrypters sql.NullString Ref sql.NullString + Active bool ExternalID string } diff --git a/pkg/storage/secret/metadata/secure_value_store.go b/pkg/storage/secret/metadata/secure_value_store.go index 6f79dfbd353..ecc22df28bd 100644 --- a/pkg/storage/secret/metadata/secure_value_store.go +++ b/pkg/storage/secret/metadata/secure_value_store.go @@ -55,33 +55,18 @@ func (s *secureValueMetadataStorage) Create(ctx context.Context, sv *secretv0alp )) defer span.End() - sv.Status.Phase = secretv0alpha1.SecureValuePhasePending - sv.Status.Message = "Creating secure value" + // Set inside of the transaction callback + var row *secureValueDB - row, err := toCreateRow(sv, actorUID) - if err != nil { - return nil, fmt.Errorf("to create row: %w", err) - } - - req := createSecureValue{ - SQLTemplate: sqltemplate.New(s.dialect), - Row: row, - } - - query, err := sqltemplate.Execute(sqlSecureValueCreate, req) - if err != nil { - return nil, fmt.Errorf("execute template %q: %w", sqlSecureValueCreate.Name(), err) - } - - err = s.db.Transaction(ctx, func(ctx context.Context) error { - if row.Keeper.Valid { + err := s.db.Transaction(ctx, func(ctx context.Context) error { + if sv.Spec.Keeper != nil { // Validate before inserting that the chosen `keeper` exists. // -- This is a copy of KeeperMetadataStore.read, which is not public at the moment, and is not defined in contract.KeeperMetadataStorage req := &readKeeper{ SQLTemplate: sqltemplate.New(s.dialect), - Namespace: row.Namespace, - Name: row.Keeper.String, + Namespace: sv.Namespace, + Name: *sv.Spec.Keeper, IsForUpdate: true, } @@ -101,23 +86,61 @@ func (s *secureValueMetadataStorage) Create(ctx context.Context, sv *secretv0alp } } - res, err := s.db.ExecContext(ctx, query, req.GetArgs()...) + latestVersion, err := s.getLatestVersion(ctx, xkube.Namespace(sv.Namespace), sv.Name) if err != nil { - if sql.IsRowAlreadyExistsError(err) { - return fmt.Errorf("namespace=%+v name=%+v %w", sv.Namespace, sv.Name, contracts.ErrSecureValueAlreadyExists) + return fmt.Errorf("fetching latest secure value version: %w", err) + } + + version := int64(1) + if latestVersion != nil { + version = *latestVersion + 1 + } + + // Some other concurrent request may have created the version we're trying to create, + // if that's the case, we'll retry with a new version up to max attempts. + maxAttempts := 3 + attempts := 0 + for { + sv.Status.Version = version + + row, err = toCreateRow(sv, actorUID) + if err != nil { + return fmt.Errorf("to create row: %w", err) } - return fmt.Errorf("inserting row: %w", err) - } - rowsAffected, err := res.RowsAffected() - if err != nil { - return fmt.Errorf("getting rows affected: %w", err) - } + req := createSecureValue{ + SQLTemplate: sqltemplate.New(s.dialect), + Row: row, + } - if rowsAffected != 1 { - return fmt.Errorf("expected 1 row affected, got %d for %s on %s", rowsAffected, row.Name, row.Namespace) + query, err := sqltemplate.Execute(sqlSecureValueCreate, req) + if err != nil { + return fmt.Errorf("execute template %q: %w", sqlSecureValueCreate.Name(), err) + } + + res, err := s.db.ExecContext(ctx, query, req.GetArgs()...) + if err != nil { + if sql.IsRowAlreadyExistsError(err) { + if attempts < maxAttempts { + attempts += 1 + version += 1 + continue + } + return fmt.Errorf("namespace=%+v name=%+v %w", sv.Namespace, sv.Name, contracts.ErrSecureValueAlreadyExists) + } + return fmt.Errorf("inserting row: %w", err) + } + + rowsAffected, err := res.RowsAffected() + if err != nil { + return fmt.Errorf("getting rows affected: %w", err) + } + + if rowsAffected != 1 { + return fmt.Errorf("expected 1 row affected, got %d for %s on %s", rowsAffected, row.Name, row.Namespace) + } + return nil } - return nil }) if err != nil { return nil, fmt.Errorf("db failure: %w", err) @@ -134,6 +157,138 @@ func (s *secureValueMetadataStorage) Create(ctx context.Context, sv *secretv0alp return createdSecureValue, nil } +func (s *secureValueMetadataStorage) getLatestVersion(ctx context.Context, namespace xkube.Namespace, name string) (*int64, error) { + ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.getLatestVersion", trace.WithAttributes( + attribute.String("name", name), + attribute.String("namespace", namespace.String()), + )) + defer span.End() + + req := getLatestSecureValueVersion{ + SQLTemplate: sqltemplate.New(s.dialect), + Namespace: namespace.String(), + Name: name, + } + + q, err := sqltemplate.Execute(sqlGetLatestSecureValueVersion, req) + if err != nil { + return nil, fmt.Errorf("execute template %q: %w", sqlGetLatestSecureValueVersion.Name(), err) + } + + rows, err := s.db.QueryContext(ctx, q, req.GetArgs()...) + if err != nil { + return nil, fmt.Errorf("fetching latest version for secure value: namespace=%+v name=%+v %w", namespace, name, err) + } + defer func() { _ = rows.Close() }() + + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("error executing query: %w", err) + } + + if !rows.Next() { + return nil, nil + } + + var version int64 + if err := rows.Scan(&version); err != nil { + return nil, fmt.Errorf("scanning version from returned rows: %w", err) + } + + return &version, nil +} + +func (s *secureValueMetadataStorage) ReadForDecrypt(ctx context.Context, namespace xkube.Namespace, name string) (*contracts.DecryptSecureValue, error) { + start := time.Now() + ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.ReadForDecrypt", trace.WithAttributes( + attribute.String("name", name), + attribute.String("namespace", namespace.String()), + )) + defer span.End() + + req := readSecureValueForDecrypt{ + SQLTemplate: sqltemplate.New(s.dialect), + Namespace: namespace.String(), + Name: name, + } + + query, err := sqltemplate.Execute(sqlSecureValueReadForDecrypt, req) + if err != nil { + return nil, fmt.Errorf("execute template %q: %w", sqlSecureValueReadForDecrypt.Name(), err) + } + + res, err := s.db.QueryContext(ctx, query, req.GetArgs()...) + if err != nil { + return nil, fmt.Errorf("reading row: %w", err) + } + defer func() { _ = res.Close() }() + + var row secureValueForDecrypt + if !res.Next() { + return nil, contracts.ErrSecureValueNotFound + } + if err := res.Scan( + &row.Keeper, &row.Decrypters, + &row.Ref, &row.ExternalID, &row.Active); err != nil { + return nil, fmt.Errorf("failed to scan secure value row: %w", err) + } + + if err := res.Err(); err != nil { + return nil, fmt.Errorf("read rows error: %w", err) + } + + if !row.Active { + return nil, fmt.Errorf("bug: read an inactive version: row=%+v", row) + } + + secureValue, err := row.toDecrypt() + if err != nil { + return nil, fmt.Errorf("convert to kubernetes object: %w", err) + } + + s.metrics.SecureValueGetForDecryptDuration.Observe(time.Since(start).Seconds()) + + return secureValue, nil +} + +func (s *secureValueMetadataStorage) readActiveVersion(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (secureValueDB, error) { + req := readSecureValue{ + SQLTemplate: sqltemplate.New(s.dialect), + Namespace: namespace.String(), + Name: name, + IsForUpdate: opts.ForUpdate, + } + + query, err := sqltemplate.Execute(sqlSecureValueRead, req) + if err != nil { + return secureValueDB{}, fmt.Errorf("execute template %q: %w", sqlSecureValueRead.Name(), err) + } + + res, err := s.db.QueryContext(ctx, query, req.GetArgs()...) + if err != nil { + return secureValueDB{}, fmt.Errorf("reading row: %w", err) + } + defer func() { _ = res.Close() }() + + var secureValue secureValueDB + if !res.Next() { + return secureValueDB{}, contracts.ErrSecureValueNotFound + } + + if err := res.Scan( + &secureValue.GUID, &secureValue.Name, &secureValue.Namespace, + &secureValue.Annotations, &secureValue.Labels, + &secureValue.Created, &secureValue.CreatedBy, + &secureValue.Updated, &secureValue.UpdatedBy, + &secureValue.Description, &secureValue.Keeper, &secureValue.Decrypters, &secureValue.Ref, &secureValue.ExternalID, &secureValue.Active, &secureValue.Version); err != nil { + return secureValueDB{}, fmt.Errorf("failed to scan secure value row: %w", err) + } + + if err := res.Err(); err != nil { + return secureValueDB{}, fmt.Errorf("read rows error: %w", err) + } + return secureValue, nil +} + func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (*secretv0alpha1.SecureValue, error) { start := time.Now() ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.Read", trace.WithAttributes( @@ -143,7 +298,7 @@ func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.N )) defer span.End() - secureValue, err := s.read(ctx, namespace, name, opts) + secureValue, err := s.readActiveVersion(ctx, namespace, name, opts) if err != nil { return nil, err } @@ -159,134 +314,6 @@ func (s *secureValueMetadataStorage) Read(ctx context.Context, namespace xkube.N return secureValueKub, nil } -func (s *secureValueMetadataStorage) Update(ctx context.Context, newSecureValue *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) { - start := time.Now() - ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.Update", trace.WithAttributes( - attribute.String("name", newSecureValue.GetName()), - attribute.String("namespace", newSecureValue.GetNamespace()), - attribute.String("actorUID", actorUID), - )) - defer span.End() - - var newRow *secureValueDB - - err := s.db.Transaction(ctx, func(ctx context.Context) error { - read, err := s.read(ctx, xkube.Namespace(newSecureValue.Namespace), newSecureValue.Name, contracts.ReadOpts{ForUpdate: true}) - if err != nil { - return fmt.Errorf("reading secure value: %w", err) - } - - // TODO: Confirm the ExternalID should come from the read model. - var updateErr error - newRow, updateErr = toUpdateRow(&read, newSecureValue, actorUID, read.ExternalID) - if updateErr != nil { - return fmt.Errorf("model to update row: %w", updateErr) - } - - if newRow.Keeper.Valid { - // Validate before updating that the new `keeper` exists. - - // -- This is a copy of KeeperMetadataStore.read, which is not public at the moment, and is not defined in contract.KeeperMetadataStorage - req := &readKeeper{ - SQLTemplate: sqltemplate.New(s.dialect), - Namespace: newRow.Namespace, - Name: newRow.Keeper.String, - IsForUpdate: true, - } - - query, err := sqltemplate.Execute(sqlKeeperRead, req) - if err != nil { - return fmt.Errorf("execute template %q: %w", sqlKeeperRead.Name(), err) - } - - res, err := s.db.QueryContext(ctx, query, req.GetArgs()...) - if err != nil { - return fmt.Errorf("getting row: %w", err) - } - defer func() { _ = res.Close() }() - - if !res.Next() { - return contracts.ErrKeeperNotFound - } - } - - req := &updateSecureValue{ - SQLTemplate: sqltemplate.New(s.dialect), - Namespace: newRow.Namespace, - Name: newRow.Name, - Row: newRow, - } - - query, err := sqltemplate.Execute(sqlSecureValueUpdate, req) - if err != nil { - return fmt.Errorf("execute template %q: %w", sqlSecureValueUpdate.Name(), err) - } - - result, err := s.db.ExecContext(ctx, query, req.GetArgs()...) - if err != nil { - return fmt.Errorf("updating row: %w", err) - } - - rowsAffected, err := result.RowsAffected() - if err != nil { - return fmt.Errorf("getting rows affected: %w", err) - } - - if rowsAffected != 1 { - return fmt.Errorf("expected 1 row affected, got %d for %s on %s", rowsAffected, newRow.Name, newRow.Namespace) - } - - return nil - }) - if err != nil { - return nil, fmt.Errorf("db failure: %w", err) - } - - secureValue, err := newRow.toKubernetes() - if err != nil { - return nil, fmt.Errorf("convert to kubernetes object: %w", err) - } - - s.metrics.SecureValueMetadataUpdateDuration.Observe(time.Since(start).Seconds()) - s.metrics.SecureValueMetadataUpdateCount.Inc() - - return secureValue, nil -} - -func (s *secureValueMetadataStorage) Delete(ctx context.Context, namespace xkube.Namespace, name string) error { - start := time.Now() - ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.Delete", trace.WithAttributes( - attribute.String("name", name), - attribute.String("namespace", namespace.String()), - )) - defer span.End() - - req := deleteSecureValue{ - SQLTemplate: sqltemplate.New(s.dialect), - Namespace: namespace.String(), - Name: name, - } - - query, err := sqltemplate.Execute(sqlSecureValueDelete, req) - if err != nil { - return fmt.Errorf("execute template %q: %w", sqlSecureValueDelete.Name(), err) - } - - res, err := s.db.ExecContext(ctx, query, req.GetArgs()...) - if err != nil { - return fmt.Errorf("deleting secure value row: %w", err) - } - - if rowsAffected, err := res.RowsAffected(); err != nil || rowsAffected != 1 { - return fmt.Errorf("deleting secure value rowsAffected=%d error=%w", rowsAffected, err) - } - - s.metrics.SecureValueMetadataDeleteDuration.Observe(time.Since(start).Seconds()) - s.metrics.SecureValueMetadataDeleteCount.Inc() - - return nil -} - func (s *secureValueMetadataStorage) List(ctx context.Context, namespace xkube.Namespace) (svList []secretv0alpha1.SecureValue, error error) { start := time.Now() ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.List", trace.WithAttributes( @@ -323,15 +350,18 @@ func (s *secureValueMetadataStorage) List(ctx context.Context, namespace xkube.N &row.Labels, &row.Created, &row.CreatedBy, &row.Updated, &row.UpdatedBy, - &row.Phase, &row.Message, &row.Description, &row.Keeper, &row.Decrypters, - &row.Ref, &row.ExternalID, + &row.Ref, &row.ExternalID, &row.Version, &row.Active, ) if err != nil { return nil, fmt.Errorf("error reading secure value row: %w", err) } + if !row.Active { + return nil, fmt.Errorf("bug: read an inactive version: row=%+v", row) + } + secureValue, err := row.toKubernetes() if err != nil { return nil, fmt.Errorf("convert to kubernetes object: %w", err) @@ -349,12 +379,86 @@ func (s *secureValueMetadataStorage) List(ctx context.Context, namespace xkube.N return secureValues, nil } -func (s *secureValueMetadataStorage) SetExternalID(ctx context.Context, namespace xkube.Namespace, name string, externalID contracts.ExternalID) error { +func (s *secureValueMetadataStorage) SetVersionToActive(ctx context.Context, namespace xkube.Namespace, name string, version int64) error { + ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.SetExternalID", trace.WithAttributes( + attribute.String("name", name), + attribute.String("namespace", namespace.String()), + attribute.Int64("version", version), + )) + defer span.End() + + req := secureValueSetVersionToActive{ + SQLTemplate: sqltemplate.New(s.dialect), + Namespace: namespace.String(), + Name: name, + Version: version, + } + + q, err := sqltemplate.Execute(sqlSecureValueSetVersionToActive, req) + if err != nil { + return fmt.Errorf("execute template %q: %w", sqlSecureValueSetVersionToActive.Name(), err) + } + + res, err := s.db.ExecContext(ctx, q, req.GetArgs()...) + if err != nil { + return fmt.Errorf("setting secure value version to active: namespace=%+v name=%+v version=%+v %w", namespace, name, version, err) + } + + // validate modified cound + modifiedCount, err := res.RowsAffected() + if err != nil { + return fmt.Errorf("fetching number of modified rows: %w", err) + } + if modifiedCount == 0 { + return fmt.Errorf("expected to modify at least one row but modified 0: modifiedCount=%d", modifiedCount) + } + + return nil +} + +func (s *secureValueMetadataStorage) SetVersionToInactive(ctx context.Context, namespace xkube.Namespace, name string, version int64) error { + ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.SetExternalID", trace.WithAttributes( + attribute.String("name", name), + attribute.String("namespace", namespace.String()), + attribute.Int64("version", version), + )) + defer span.End() + + req := secureValueSetVersionToInactive{ + SQLTemplate: sqltemplate.New(s.dialect), + Namespace: namespace.String(), + Name: name, + Version: version, + } + + q, err := sqltemplate.Execute(sqlSecureValueSetVersionToInactive, req) + if err != nil { + return fmt.Errorf("execute template %q: %w", sqlSecureValueSetVersionToInactive.Name(), err) + } + + res, err := s.db.ExecContext(ctx, q, req.GetArgs()...) + if err != nil { + return fmt.Errorf("setting secure value version to active: namespace=%+v name=%+v version=%+v %w", namespace, name, version, err) + } + + modifiedCount, err := res.RowsAffected() + if err != nil { + return fmt.Errorf("fetching number of modified rows: %w", err) + } + if modifiedCount > 1 { + return fmt.Errorf("expected to modify at at most one row but modified more: modifiedCount=%d", modifiedCount) + } + + return nil +} + +func (s *secureValueMetadataStorage) SetExternalID(ctx context.Context, namespace xkube.Namespace, name string, version int64, externalID contracts.ExternalID) error { start := time.Now() ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.SetExternalID", trace.WithAttributes( attribute.String("name", name), attribute.String("namespace", namespace.String()), attribute.String("externalID", externalID.String()), + attribute.Int64("version", version), )) defer span.End() @@ -362,6 +466,7 @@ func (s *secureValueMetadataStorage) SetExternalID(ctx context.Context, namespac SQLTemplate: sqltemplate.New(s.dialect), Namespace: namespace.String(), Name: name, + Version: version, ExternalID: externalID.String(), } @@ -387,134 +492,3 @@ func (s *secureValueMetadataStorage) SetExternalID(ctx context.Context, namespac return nil } - -func (s *secureValueMetadataStorage) SetStatus(ctx context.Context, namespace xkube.Namespace, name string, status secretv0alpha1.SecureValueStatus) error { - start := time.Now() - ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.SetStatus", trace.WithAttributes( - attribute.String("name", name), - attribute.String("namespace", namespace.String()), - attribute.String("status.phase", string(status.Phase)), - attribute.String("status.message", status.Message), - attribute.String("status.externalID", status.ExternalID), - )) - defer span.End() - - req := updateStatusSecureValue{ - SQLTemplate: sqltemplate.New(s.dialect), - Namespace: namespace.String(), - Name: name, - Phase: string(status.Phase), - Message: status.Message, - } - - q, err := sqltemplate.Execute(sqlSecureValueUpdateStatus, req) - if err != nil { - return fmt.Errorf("execute template %q: %w", sqlSecureValueUpdateStatus.Name(), err) - } - - res, err := s.db.ExecContext(ctx, q, req.GetArgs()...) - if err != nil { - return fmt.Errorf("setting secure value status to Succeeded id: namespace=%+v name=%+v %w", namespace, name, err) - } - - // validate modified cound - modifiedCount, err := res.RowsAffected() - if err != nil { - return fmt.Errorf("getting updated rows update status secure value: %w", err) - } - if modifiedCount > 1 { - return fmt.Errorf("secureValueMetadataStorage.SetExternalID: modified more than one secret, this is a bug, check the where condition: modifiedCount=%d", modifiedCount) - } - s.metrics.SecureValueSetStatusDuration.Observe(time.Since(start).Seconds()) - - return nil -} - -func (s *secureValueMetadataStorage) ReadForDecrypt(ctx context.Context, namespace xkube.Namespace, name string) (*contracts.DecryptSecureValue, error) { - start := time.Now() - ctx, span := s.tracer.Start(ctx, "SecureValueMetadataStorage.ReadForDecrypt", trace.WithAttributes( - attribute.String("name", name), - attribute.String("namespace", namespace.String()), - )) - defer span.End() - - req := readSecureValueForDecrypt{ - SQLTemplate: sqltemplate.New(s.dialect), - Namespace: namespace.String(), - Name: name, - } - - query, err := sqltemplate.Execute(sqlSecureValueReadForDecrypt, req) - if err != nil { - return nil, fmt.Errorf("execute template %q: %w", sqlSecureValueReadForDecrypt.Name(), err) - } - - res, err := s.db.QueryContext(ctx, query, req.GetArgs()...) - if err != nil { - return nil, fmt.Errorf("reading row: %w", err) - } - defer func() { _ = res.Close() }() - - var row secureValueForDecrypt - if !res.Next() { - return nil, contracts.ErrSecureValueNotFound - } - if err := res.Scan( - &row.Keeper, &row.Decrypters, - &row.Ref, &row.ExternalID); err != nil { - return nil, fmt.Errorf("failed to scan secure value row: %w", err) - } - - if err := res.Err(); err != nil { - return nil, fmt.Errorf("read rows error: %w", err) - } - - secureValue, err := row.toDecrypt() - if err != nil { - return nil, fmt.Errorf("convert to kubernetes object: %w", err) - } - - s.metrics.SecureValueGetForDecryptDuration.Observe(time.Since(start).Seconds()) - - return secureValue, nil -} - -func (s *secureValueMetadataStorage) read(ctx context.Context, namespace xkube.Namespace, name string, opts contracts.ReadOpts) (secureValueDB, error) { - req := readSecureValue{ - SQLTemplate: sqltemplate.New(s.dialect), - Namespace: namespace.String(), - Name: name, - IsForUpdate: opts.ForUpdate, - } - - query, err := sqltemplate.Execute(sqlSecureValueRead, req) - if err != nil { - return secureValueDB{}, fmt.Errorf("execute template %q: %w", sqlSecureValueRead.Name(), err) - } - - res, err := s.db.QueryContext(ctx, query, req.GetArgs()...) - if err != nil { - return secureValueDB{}, fmt.Errorf("reading row: %w", err) - } - defer func() { _ = res.Close() }() - - var secureValue secureValueDB - if !res.Next() { - return secureValueDB{}, contracts.ErrSecureValueNotFound - } - - if err := res.Scan( - &secureValue.GUID, &secureValue.Name, &secureValue.Namespace, - &secureValue.Annotations, &secureValue.Labels, - &secureValue.Created, &secureValue.CreatedBy, - &secureValue.Updated, &secureValue.UpdatedBy, - &secureValue.Phase, &secureValue.Message, - &secureValue.Description, &secureValue.Keeper, &secureValue.Decrypters, &secureValue.Ref, &secureValue.ExternalID); err != nil { - return secureValueDB{}, fmt.Errorf("failed to scan secure value row: %w", err) - } - - if err := res.Err(); err != nil { - return secureValueDB{}, fmt.Errorf("read rows error: %w", err) - } - return secureValue, nil -} diff --git a/pkg/storage/secret/metadata/secure_value_store_test.go b/pkg/storage/secret/metadata/secure_value_store_test.go index b9ec0023430..1de2dbf73f1 100644 --- a/pkg/storage/secret/metadata/secure_value_store_test.go +++ b/pkg/storage/secret/metadata/secure_value_store_test.go @@ -1,4 +1,4 @@ -package metadata +package metadata_test import ( "context" @@ -10,6 +10,7 @@ import ( "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/storage/secret/database" + "github.com/grafana/grafana/pkg/storage/secret/metadata" "github.com/grafana/grafana/pkg/storage/secret/migrator" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" @@ -43,11 +44,11 @@ func Test_SecureValueMetadataStorage_CreateAndRead(t *testing.T) { features := featuremgmt.WithFeatures(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, featuremgmt.FlagSecretsManagementAppPlatform) // Initialize the secure value storage - secureValueStorage, err := ProvideSecureValueMetadataStorage(db, tracer, features, nil) + secureValueStorage, err := metadata.ProvideSecureValueMetadataStorage(db, tracer, features, nil) require.NoError(t, err) // Initialize the keeper storage - keeperStorage, err := ProvideKeeperMetadataStorage(db, tracer, features, nil) + keeperStorage, err := metadata.ProvideKeeperMetadataStorage(db, tracer, features, nil) require.NoError(t, err) t.Run("create and read a secure value", func(t *testing.T) { @@ -73,7 +74,8 @@ func Test_SecureValueMetadataStorage_CreateAndRead(t *testing.T) { require.Equal(t, "default", createdSecureValue.Namespace) require.Equal(t, "test description", createdSecureValue.Spec.Description) require.Equal(t, keeperName, *createdSecureValue.Spec.Keeper) - require.Equal(t, secretv0alpha1.SecureValuePhasePending, createdSecureValue.Status.Phase) + + require.NoError(t, secureValueStorage.SetVersionToActive(ctx, xkube.Namespace(createdSecureValue.Namespace), createdSecureValue.Name, createdSecureValue.Status.Version)) // Read the secure value back readSecureValue, err := secureValueStorage.Read(ctx, xkube.Namespace("default"), "sv-test", contracts.ReadOpts{}) @@ -83,7 +85,6 @@ func Test_SecureValueMetadataStorage_CreateAndRead(t *testing.T) { require.Equal(t, "default", readSecureValue.Namespace) require.Equal(t, "test description", readSecureValue.Spec.Description) require.Equal(t, keeperName, *readSecureValue.Spec.Keeper) - require.Equal(t, secretv0alpha1.SecureValuePhasePending, readSecureValue.Status.Phase) // List secure values and verify our value is in the list secureValues, err := secureValueStorage.List(ctx, xkube.Namespace("default")) @@ -98,7 +99,6 @@ func Test_SecureValueMetadataStorage_CreateAndRead(t *testing.T) { require.Equal(t, "default", sv.Namespace) require.Equal(t, "test description", sv.Spec.Description) require.Equal(t, keeperName, *sv.Spec.Keeper) - require.Equal(t, secretv0alpha1.SecureValuePhasePending, sv.Status.Phase) break } } @@ -125,6 +125,8 @@ func Test_SecureValueMetadataStorage_CreateAndRead(t *testing.T) { require.NoError(t, err) require.NotNil(t, createdSecureValue) + require.NoError(t, secureValueStorage.SetVersionToActive(ctx, xkube.Namespace(createdSecureValue.Namespace), createdSecureValue.Name, createdSecureValue.Status.Version)) + // Read the secure value to verify it exists readSecureValue, err := secureValueStorage.Read(ctx, xkube.Namespace("default"), "sv-test-2", contracts.ReadOpts{}) require.NoError(t, err) @@ -132,7 +134,7 @@ func Test_SecureValueMetadataStorage_CreateAndRead(t *testing.T) { require.Equal(t, "sv-test-2", readSecureValue.Name) // Delete the secure value - err = secureValueStorage.Delete(ctx, xkube.Namespace("default"), "sv-test-2") + err = secureValueStorage.SetVersionToInactive(ctx, xkube.Namespace("default"), "sv-test-2", readSecureValue.Status.Version) require.NoError(t, err) // Try to read the deleted secure value - should return error diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_create-create-not-null.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_create-create-not-null.sql index 8dea7db9fa8..aadea1d47a9 100755 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_create-create-not-null.sql +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_create-create-not-null.sql @@ -8,8 +8,8 @@ INSERT INTO `secret_secure_value` ( `created_by`, `updated`, `updated_by`, - `status_phase`, - `status_message`, + `active`, + `version`, `description`, `keeper`, `decrypters`, @@ -25,8 +25,8 @@ INSERT INTO `secret_secure_value` ( 'user:ryan', 5678, 'user:cameron', - 'creating', - 'message_test', + FALSE, + 1, 'description', 'keeper_test', 'decrypters_test', diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_create-create-null.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_create-create-null.sql index fcaa4271d49..ff0875fc55c 100755 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_create-create-null.sql +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_create-create-null.sql @@ -8,7 +8,8 @@ INSERT INTO `secret_secure_value` ( `created_by`, `updated`, `updated_by`, - `status_phase`, + `active`, + `version`, `description`, `external_id` ) VALUES ( @@ -21,7 +22,8 @@ INSERT INTO `secret_secure_value` ( 'user:ryan', 5678, 'user:cameron', - 'creating', + FALSE, + 1, 'description', 'extId' ); diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_delete-delete.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_delete-delete.sql deleted file mode 100755 index e8597c9fc8b..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_delete-delete.sql +++ /dev/null @@ -1,4 +0,0 @@ -DELETE FROM `secret_secure_value` -WHERE `namespace` = 'ns' AND - `name` = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_get_latest_version-get latest secure value version.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_get_latest_version-get latest secure value version.sql new file mode 100755 index 00000000000..8118fc81489 --- /dev/null +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_get_latest_version-get latest secure value version.sql @@ -0,0 +1,10 @@ +SELECT + `version` +FROM + `secret_secure_value` +WHERE + `namespace` = 'ns' AND + `name` = 'name' +ORDER BY `version` DESC +LIMIT 1 +; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_list-list.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_list-list.sql index c47a02c16b2..d73828bfae8 100755 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_list-list.sql +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_list-list.sql @@ -8,15 +8,17 @@ SELECT `created_by`, `updated`, `updated_by`, - `status_phase`, - `status_message`, `description`, `keeper`, `decrypters`, `ref`, - `external_id` + `external_id`, + `version`, + `active` FROM `secret_secure_value` -WHERE `namespace` = 'ns' +WHERE + `namespace` = 'ns' AND + `active` = true ORDER BY `updated` DESC ; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_listByName-list.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_listByName-list.sql index 91ac79af6ae..91850979fdb 100755 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_listByName-list.sql +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_listByName-list.sql @@ -3,7 +3,9 @@ SELECT `keeper` FROM `secret_secure_value` -WHERE `namespace` = 'ns' AND - `name` IN ('a', 'b') +WHERE + `namespace` = 'ns' AND + `name` IN ('a', 'b') AND + `active` = true FOR UPDATE ; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-all-fields-present.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-all-fields-present.sql deleted file mode 100755 index a1cff11dd5d..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-all-fields-present.sql +++ /dev/null @@ -1,21 +0,0 @@ -INSERT INTO `secret_secure_value_outbox` ( - `request_id`, - `message_type`, - `name`, - `namespace`, - `encrypted_secret`, - `keeper_name`, - `external_id`, - `receive_count`, - `created` -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'keeper', - '', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-encrypted-secret.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-encrypted-secret.sql deleted file mode 100755 index 139d262d49a..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-encrypted-secret.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO `secret_secure_value_outbox` ( - `request_id`, - `message_type`, - `name`, - `namespace`, - `keeper_name`, - `external_id`, - `receive_count`, - `created` -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'keeper', - 'external-id', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-external-id.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-external-id.sql deleted file mode 100755 index 62af967a284..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-external-id.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO `secret_secure_value_outbox` ( - `request_id`, - `message_type`, - `name`, - `namespace`, - `encrypted_secret`, - `keeper_name`, - `receive_count`, - `created` -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'keeper', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-keeper-name.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-keeper-name.sql deleted file mode 100755 index 924b7d6277f..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_append-no-keeper-name.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO `secret_secure_value_outbox` ( - `request_id`, - `message_type`, - `name`, - `namespace`, - `encrypted_secret`, - `external_id`, - `receive_count`, - `created` -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'external-id', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_delete-basic.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_delete-basic.sql deleted file mode 100755 index 2a6fc52ea18..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_delete-basic.sql +++ /dev/null @@ -1,5 +0,0 @@ -DELETE FROM - `secret_secure_value_outbox` -WHERE - `id` = 1 -; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_fetch_message_ids-basic.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_fetch_message_ids-basic.sql deleted file mode 100755 index 47b006df9e3..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_fetch_message_ids-basic.sql +++ /dev/null @@ -1,6 +0,0 @@ -SELECT - `id` -FROM `secret_secure_value_outbox` -ORDER BY id ASC -LIMIT 10 -; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_receiveN-basic.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_receiveN-basic.sql deleted file mode 100755 index 710f96bf187..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_receiveN-basic.sql +++ /dev/null @@ -1,19 +0,0 @@ -SELECT - `request_id`, - `id`, - `message_type`, - `name`, - `namespace`, - `encrypted_secret`, - `keeper_name`, - `external_id`, - `receive_count`, - `created` -FROM - `secret_secure_value_outbox` -WHERE - `id` IN (1, 2, 3) -ORDER BY - `id` ASC -FOR UPDATE SKIP LOCKED -; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_update_receive_count-update-receive-count.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_update_receive_count-update-receive-count.sql deleted file mode 100755 index e9df2c03014..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_outbox_update_receive_count-update-receive-count.sql +++ /dev/null @@ -1,7 +0,0 @@ -UPDATE - `secret_secure_value_outbox` -SET - `receive_count` = `receive_count` + 1 -WHERE - `id` IN (1, 2, 3) -; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_read-read-for-update.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_read-read-for-update.sql index 8f433497d22..4d8525dd0a0 100755 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_read-read-for-update.sql +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_read-read-for-update.sql @@ -8,16 +8,18 @@ SELECT `created_by`, `updated`, `updated_by`, - `status_phase`, - `status_message`, `description`, `keeper`, `decrypters`, `ref`, - `external_id` + `external_id`, + `active`, + `version` FROM `secret_secure_value` -WHERE `namespace` = 'ns' AND - `name` = 'name' +WHERE + `namespace` = 'ns' AND + `name` = 'name' AND + `active` = true FOR UPDATE ; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_read-read.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_read-read.sql index b45713eb594..c42fd0037c5 100755 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_read-read.sql +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_read-read.sql @@ -8,15 +8,17 @@ SELECT `created_by`, `updated`, `updated_by`, - `status_phase`, - `status_message`, `description`, `keeper`, `decrypters`, `ref`, - `external_id` + `external_id`, + `active`, + `version` FROM `secret_secure_value` -WHERE `namespace` = 'ns' AND - `name` = 'name' +WHERE + `namespace` = 'ns' AND + `name` = 'name' AND + `active` = true ; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_read_for_decrypt-read-for-decrypt.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_read_for_decrypt-read-for-decrypt.sql index 2694f0376d8..9d9095cf1e7 100755 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_read_for_decrypt-read-for-decrypt.sql +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_read_for_decrypt-read-for-decrypt.sql @@ -2,9 +2,12 @@ SELECT `keeper`, `decrypters`, `ref`, - `external_id` + `external_id`, + `active` FROM `secret_secure_value` -WHERE `namespace` = 'ns' AND - `name` = 'name' +WHERE + `namespace` = 'ns' AND + `name` = 'name' AND + `active` = true ; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_set_version_to_active-set secure value version to active.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_set_version_to_active-set secure value version to active.sql new file mode 100755 index 00000000000..ce98578b8b5 --- /dev/null +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_set_version_to_active-set secure value version to active.sql @@ -0,0 +1,8 @@ +UPDATE + `secret_secure_value` +SET + `active` = (`version` = 1) +WHERE + `namespace` = 'ns' AND + `name` = 'name' +; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_update-update-not-null.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_update-update-not-null.sql deleted file mode 100755 index 6b39e09d23f..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_update-update-not-null.sql +++ /dev/null @@ -1,22 +0,0 @@ -UPDATE - `secret_secure_value` -SET - `guid` = 'abc', - `name` = 'name', - `namespace` = 'ns', - `annotations` = '{"x":"XXXX"}', - `labels` = '{"a":"AAA", "b", "BBBB"}', - `created` = 1234, - `created_by` = 'user:ryan', - `updated` = 5678, - `updated_by` = 'user:cameron', - `status_phase` = 'creating', - `status_message` = 'message_test', - `description` = 'description', - `keeper` = 'keeper_test', - `decrypters` = 'decrypters_test', - `ref` = 'ref_test', - `external_id` = 'extId' -WHERE `namespace` = 'ns' AND - `name` = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_update-update-null.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_update-update-null.sql deleted file mode 100755 index 378a2934ec3..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_update-update-null.sql +++ /dev/null @@ -1,18 +0,0 @@ -UPDATE - `secret_secure_value` -SET - `guid` = 'abc', - `name` = 'name', - `namespace` = 'ns', - `annotations` = '{"x":"XXXX"}', - `labels` = '{"a":"AAA", "b", "BBBB"}', - `created` = 1234, - `created_by` = 'user:ryan', - `updated` = 5678, - `updated_by` = 'user:cameron', - `status_phase` = 'creating', - `description` = 'description', - `external_id` = 'extId' -WHERE `namespace` = 'ns' AND - `name` = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_updateExternalId-updateExternalId.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_updateExternalId-updateExternalId.sql index d6d7db45247..eb862fcb072 100755 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_updateExternalId-updateExternalId.sql +++ b/pkg/storage/secret/metadata/testdata/mysql--secure_value_updateExternalId-updateExternalId.sql @@ -2,6 +2,8 @@ UPDATE `secret_secure_value` SET `external_id` = 'extId' -WHERE `namespace` = 'ns' AND - `name` = 'name' +WHERE + `namespace` = 'ns' AND + `name` = 'name' AND + `version` = 0 ; diff --git a/pkg/storage/secret/metadata/testdata/mysql--secure_value_updateStatus-updateStatus.sql b/pkg/storage/secret/metadata/testdata/mysql--secure_value_updateStatus-updateStatus.sql deleted file mode 100755 index 25815855c68..00000000000 --- a/pkg/storage/secret/metadata/testdata/mysql--secure_value_updateStatus-updateStatus.sql +++ /dev/null @@ -1,8 +0,0 @@ -UPDATE - `secret_secure_value` -SET - `status_phase` = 'Succeeded', - `status_message` = 'message-1' -WHERE `namespace` = 'ns' AND - `name` = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_create-create-not-null.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_create-create-not-null.sql index d9f191a9c63..cf43e0c130c 100755 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_create-create-not-null.sql +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_create-create-not-null.sql @@ -8,8 +8,8 @@ INSERT INTO "secret_secure_value" ( "created_by", "updated", "updated_by", - "status_phase", - "status_message", + "active", + "version", "description", "keeper", "decrypters", @@ -25,8 +25,8 @@ INSERT INTO "secret_secure_value" ( 'user:ryan', 5678, 'user:cameron', - 'creating', - 'message_test', + FALSE, + 1, 'description', 'keeper_test', 'decrypters_test', diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_create-create-null.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_create-create-null.sql index 69dd74be229..564c5728f14 100755 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_create-create-null.sql +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_create-create-null.sql @@ -8,7 +8,8 @@ INSERT INTO "secret_secure_value" ( "created_by", "updated", "updated_by", - "status_phase", + "active", + "version", "description", "external_id" ) VALUES ( @@ -21,7 +22,8 @@ INSERT INTO "secret_secure_value" ( 'user:ryan', 5678, 'user:cameron', - 'creating', + FALSE, + 1, 'description', 'extId' ); diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_delete-delete.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_delete-delete.sql deleted file mode 100755 index f2fbdc59f70..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_delete-delete.sql +++ /dev/null @@ -1,4 +0,0 @@ -DELETE FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_get_latest_version-get latest secure value version.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_get_latest_version-get latest secure value version.sql new file mode 100755 index 00000000000..1549114582d --- /dev/null +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_get_latest_version-get latest secure value version.sql @@ -0,0 +1,10 @@ +SELECT + "version" +FROM + "secret_secure_value" +WHERE + "namespace" = 'ns' AND + "name" = 'name' +ORDER BY "version" DESC +LIMIT 1 +; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_list-list.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_list-list.sql index 681ee5708cd..40ee42ebcf7 100755 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_list-list.sql +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_list-list.sql @@ -8,15 +8,17 @@ SELECT "created_by", "updated", "updated_by", - "status_phase", - "status_message", "description", "keeper", "decrypters", "ref", - "external_id" + "external_id", + "version", + "active" FROM "secret_secure_value" -WHERE "namespace" = 'ns' +WHERE + "namespace" = 'ns' AND + "active" = true ORDER BY "updated" DESC ; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_listByName-list.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_listByName-list.sql index 93a449fa17a..d476e297129 100755 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_listByName-list.sql +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_listByName-list.sql @@ -3,7 +3,9 @@ SELECT "keeper" FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" IN ('a', 'b') +WHERE + "namespace" = 'ns' AND + "name" IN ('a', 'b') AND + "active" = true FOR UPDATE ; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-all-fields-present.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-all-fields-present.sql deleted file mode 100755 index 3c2b2588c08..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-all-fields-present.sql +++ /dev/null @@ -1,21 +0,0 @@ -INSERT INTO "secret_secure_value_outbox" ( - "request_id", - "message_type", - "name", - "namespace", - "encrypted_secret", - "keeper_name", - "external_id", - "receive_count", - "created" -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'keeper', - '', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-encrypted-secret.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-encrypted-secret.sql deleted file mode 100755 index bcecf30a749..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-encrypted-secret.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO "secret_secure_value_outbox" ( - "request_id", - "message_type", - "name", - "namespace", - "keeper_name", - "external_id", - "receive_count", - "created" -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'keeper', - 'external-id', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-external-id.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-external-id.sql deleted file mode 100755 index 81eb522e3a8..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-external-id.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO "secret_secure_value_outbox" ( - "request_id", - "message_type", - "name", - "namespace", - "encrypted_secret", - "keeper_name", - "receive_count", - "created" -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'keeper', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-keeper-name.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-keeper-name.sql deleted file mode 100755 index 3c0e3abf5e8..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_append-no-keeper-name.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO "secret_secure_value_outbox" ( - "request_id", - "message_type", - "name", - "namespace", - "encrypted_secret", - "external_id", - "receive_count", - "created" -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'external-id', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_delete-basic.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_delete-basic.sql deleted file mode 100755 index f0c8984c8a0..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_delete-basic.sql +++ /dev/null @@ -1,5 +0,0 @@ -DELETE FROM - "secret_secure_value_outbox" -WHERE - "id" = 1 -; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_fetch_message_ids-basic.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_fetch_message_ids-basic.sql deleted file mode 100755 index 4c590706948..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_fetch_message_ids-basic.sql +++ /dev/null @@ -1,6 +0,0 @@ -SELECT - "id" -FROM "secret_secure_value_outbox" -ORDER BY id ASC -LIMIT 10 -; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_receiveN-basic.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_receiveN-basic.sql deleted file mode 100755 index f4602caba07..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_receiveN-basic.sql +++ /dev/null @@ -1,19 +0,0 @@ -SELECT - "request_id", - "id", - "message_type", - "name", - "namespace", - "encrypted_secret", - "keeper_name", - "external_id", - "receive_count", - "created" -FROM - "secret_secure_value_outbox" -WHERE - "id" IN (1, 2, 3) -ORDER BY - "id" ASC -FOR UPDATE SKIP LOCKED -; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_update_receive_count-update-receive-count.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_update_receive_count-update-receive-count.sql deleted file mode 100755 index d9404fd8212..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_outbox_update_receive_count-update-receive-count.sql +++ /dev/null @@ -1,7 +0,0 @@ -UPDATE - "secret_secure_value_outbox" -SET - "receive_count" = "receive_count" + 1 -WHERE - "id" IN (1, 2, 3) -; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_read-read-for-update.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_read-read-for-update.sql index 76ca4a8c155..cce38e6db7a 100755 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_read-read-for-update.sql +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_read-read-for-update.sql @@ -8,16 +8,18 @@ SELECT "created_by", "updated", "updated_by", - "status_phase", - "status_message", "description", "keeper", "decrypters", "ref", - "external_id" + "external_id", + "active", + "version" FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" = 'name' +WHERE + "namespace" = 'ns' AND + "name" = 'name' AND + "active" = true FOR UPDATE ; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_read-read.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_read-read.sql index d7fbc77a21b..2d16c211a85 100755 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_read-read.sql +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_read-read.sql @@ -8,15 +8,17 @@ SELECT "created_by", "updated", "updated_by", - "status_phase", - "status_message", "description", "keeper", "decrypters", "ref", - "external_id" + "external_id", + "active", + "version" FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" = 'name' +WHERE + "namespace" = 'ns' AND + "name" = 'name' AND + "active" = true ; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_read_for_decrypt-read-for-decrypt.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_read_for_decrypt-read-for-decrypt.sql index 999e79c2fa1..2a764e2677a 100755 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_read_for_decrypt-read-for-decrypt.sql +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_read_for_decrypt-read-for-decrypt.sql @@ -2,9 +2,12 @@ SELECT "keeper", "decrypters", "ref", - "external_id" + "external_id", + "active" FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" = 'name' +WHERE + "namespace" = 'ns' AND + "name" = 'name' AND + "active" = true ; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_set_version_to_active-set secure value version to active.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_set_version_to_active-set secure value version to active.sql new file mode 100755 index 00000000000..d659f944431 --- /dev/null +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_set_version_to_active-set secure value version to active.sql @@ -0,0 +1,8 @@ +UPDATE + "secret_secure_value" +SET + "active" = ("version" = 1) +WHERE + "namespace" = 'ns' AND + "name" = 'name' +; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_update-update-not-null.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_update-update-not-null.sql deleted file mode 100755 index 7371f13f6e5..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_update-update-not-null.sql +++ /dev/null @@ -1,22 +0,0 @@ -UPDATE - "secret_secure_value" -SET - "guid" = 'abc', - "name" = 'name', - "namespace" = 'ns', - "annotations" = '{"x":"XXXX"}', - "labels" = '{"a":"AAA", "b", "BBBB"}', - "created" = 1234, - "created_by" = 'user:ryan', - "updated" = 5678, - "updated_by" = 'user:cameron', - "status_phase" = 'creating', - "status_message" = 'message_test', - "description" = 'description', - "keeper" = 'keeper_test', - "decrypters" = 'decrypters_test', - "ref" = 'ref_test', - "external_id" = 'extId' -WHERE "namespace" = 'ns' AND - "name" = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_update-update-null.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_update-update-null.sql deleted file mode 100755 index 0524e525096..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_update-update-null.sql +++ /dev/null @@ -1,18 +0,0 @@ -UPDATE - "secret_secure_value" -SET - "guid" = 'abc', - "name" = 'name', - "namespace" = 'ns', - "annotations" = '{"x":"XXXX"}', - "labels" = '{"a":"AAA", "b", "BBBB"}', - "created" = 1234, - "created_by" = 'user:ryan', - "updated" = 5678, - "updated_by" = 'user:cameron', - "status_phase" = 'creating', - "description" = 'description', - "external_id" = 'extId' -WHERE "namespace" = 'ns' AND - "name" = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_updateExternalId-updateExternalId.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_updateExternalId-updateExternalId.sql index 3d9f474776e..29bedaa7afe 100755 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_updateExternalId-updateExternalId.sql +++ b/pkg/storage/secret/metadata/testdata/postgres--secure_value_updateExternalId-updateExternalId.sql @@ -2,6 +2,8 @@ UPDATE "secret_secure_value" SET "external_id" = 'extId' -WHERE "namespace" = 'ns' AND - "name" = 'name' +WHERE + "namespace" = 'ns' AND + "name" = 'name' AND + "version" = 0 ; diff --git a/pkg/storage/secret/metadata/testdata/postgres--secure_value_updateStatus-updateStatus.sql b/pkg/storage/secret/metadata/testdata/postgres--secure_value_updateStatus-updateStatus.sql deleted file mode 100755 index c5cf29a5e7a..00000000000 --- a/pkg/storage/secret/metadata/testdata/postgres--secure_value_updateStatus-updateStatus.sql +++ /dev/null @@ -1,8 +0,0 @@ -UPDATE - "secret_secure_value" -SET - "status_phase" = 'Succeeded', - "status_message" = 'message-1' -WHERE "namespace" = 'ns' AND - "name" = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_create-create-not-null.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_create-create-not-null.sql index d9f191a9c63..cf43e0c130c 100755 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_create-create-not-null.sql +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_create-create-not-null.sql @@ -8,8 +8,8 @@ INSERT INTO "secret_secure_value" ( "created_by", "updated", "updated_by", - "status_phase", - "status_message", + "active", + "version", "description", "keeper", "decrypters", @@ -25,8 +25,8 @@ INSERT INTO "secret_secure_value" ( 'user:ryan', 5678, 'user:cameron', - 'creating', - 'message_test', + FALSE, + 1, 'description', 'keeper_test', 'decrypters_test', diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_create-create-null.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_create-create-null.sql index 69dd74be229..564c5728f14 100755 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_create-create-null.sql +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_create-create-null.sql @@ -8,7 +8,8 @@ INSERT INTO "secret_secure_value" ( "created_by", "updated", "updated_by", - "status_phase", + "active", + "version", "description", "external_id" ) VALUES ( @@ -21,7 +22,8 @@ INSERT INTO "secret_secure_value" ( 'user:ryan', 5678, 'user:cameron', - 'creating', + FALSE, + 1, 'description', 'extId' ); diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_delete-delete.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_delete-delete.sql deleted file mode 100755 index f2fbdc59f70..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_delete-delete.sql +++ /dev/null @@ -1,4 +0,0 @@ -DELETE FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_get_latest_version-get latest secure value version.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_get_latest_version-get latest secure value version.sql new file mode 100755 index 00000000000..1549114582d --- /dev/null +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_get_latest_version-get latest secure value version.sql @@ -0,0 +1,10 @@ +SELECT + "version" +FROM + "secret_secure_value" +WHERE + "namespace" = 'ns' AND + "name" = 'name' +ORDER BY "version" DESC +LIMIT 1 +; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_list-list.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_list-list.sql index 681ee5708cd..40ee42ebcf7 100755 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_list-list.sql +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_list-list.sql @@ -8,15 +8,17 @@ SELECT "created_by", "updated", "updated_by", - "status_phase", - "status_message", "description", "keeper", "decrypters", "ref", - "external_id" + "external_id", + "version", + "active" FROM "secret_secure_value" -WHERE "namespace" = 'ns' +WHERE + "namespace" = 'ns' AND + "active" = true ORDER BY "updated" DESC ; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_listByName-list.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_listByName-list.sql index 48ae01800ae..22d2006de82 100755 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_listByName-list.sql +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_listByName-list.sql @@ -3,6 +3,8 @@ SELECT "keeper" FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" IN ('a', 'b') +WHERE + "namespace" = 'ns' AND + "name" IN ('a', 'b') AND + "active" = true ; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-all-fields-present.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-all-fields-present.sql deleted file mode 100755 index 3c2b2588c08..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-all-fields-present.sql +++ /dev/null @@ -1,21 +0,0 @@ -INSERT INTO "secret_secure_value_outbox" ( - "request_id", - "message_type", - "name", - "namespace", - "encrypted_secret", - "keeper_name", - "external_id", - "receive_count", - "created" -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'keeper', - '', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-encrypted-secret.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-encrypted-secret.sql deleted file mode 100755 index bcecf30a749..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-encrypted-secret.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO "secret_secure_value_outbox" ( - "request_id", - "message_type", - "name", - "namespace", - "keeper_name", - "external_id", - "receive_count", - "created" -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'keeper', - 'external-id', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-external-id.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-external-id.sql deleted file mode 100755 index 81eb522e3a8..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-external-id.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO "secret_secure_value_outbox" ( - "request_id", - "message_type", - "name", - "namespace", - "encrypted_secret", - "keeper_name", - "receive_count", - "created" -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'keeper', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-keeper-name.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-keeper-name.sql deleted file mode 100755 index 3c0e3abf5e8..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_append-no-keeper-name.sql +++ /dev/null @@ -1,19 +0,0 @@ -INSERT INTO "secret_secure_value_outbox" ( - "request_id", - "message_type", - "name", - "namespace", - "encrypted_secret", - "external_id", - "receive_count", - "created" -) VALUES ( - '', - 'some-type', - 'name', - 'namespace', - 'encrypted', - 'external-id', - 0, - 1234 -); diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_delete-basic.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_delete-basic.sql deleted file mode 100755 index f0c8984c8a0..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_delete-basic.sql +++ /dev/null @@ -1,5 +0,0 @@ -DELETE FROM - "secret_secure_value_outbox" -WHERE - "id" = 1 -; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_fetch_message_ids-basic.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_fetch_message_ids-basic.sql deleted file mode 100755 index 4c590706948..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_fetch_message_ids-basic.sql +++ /dev/null @@ -1,6 +0,0 @@ -SELECT - "id" -FROM "secret_secure_value_outbox" -ORDER BY id ASC -LIMIT 10 -; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_receiveN-basic.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_receiveN-basic.sql deleted file mode 100755 index 62b16f507ba..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_receiveN-basic.sql +++ /dev/null @@ -1,18 +0,0 @@ -SELECT - "request_id", - "id", - "message_type", - "name", - "namespace", - "encrypted_secret", - "keeper_name", - "external_id", - "receive_count", - "created" -FROM - "secret_secure_value_outbox" -WHERE - "id" IN (1, 2, 3) -ORDER BY - "id" ASC -; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_update_receive_count-update-receive-count.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_update_receive_count-update-receive-count.sql deleted file mode 100755 index d9404fd8212..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_outbox_update_receive_count-update-receive-count.sql +++ /dev/null @@ -1,7 +0,0 @@ -UPDATE - "secret_secure_value_outbox" -SET - "receive_count" = "receive_count" + 1 -WHERE - "id" IN (1, 2, 3) -; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read-read-for-update.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read-read-for-update.sql index d7fbc77a21b..2d16c211a85 100755 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read-read-for-update.sql +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read-read-for-update.sql @@ -8,15 +8,17 @@ SELECT "created_by", "updated", "updated_by", - "status_phase", - "status_message", "description", "keeper", "decrypters", "ref", - "external_id" + "external_id", + "active", + "version" FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" = 'name' +WHERE + "namespace" = 'ns' AND + "name" = 'name' AND + "active" = true ; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read-read.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read-read.sql index d7fbc77a21b..2d16c211a85 100755 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read-read.sql +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read-read.sql @@ -8,15 +8,17 @@ SELECT "created_by", "updated", "updated_by", - "status_phase", - "status_message", "description", "keeper", "decrypters", "ref", - "external_id" + "external_id", + "active", + "version" FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" = 'name' +WHERE + "namespace" = 'ns' AND + "name" = 'name' AND + "active" = true ; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read_for_decrypt-read-for-decrypt.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read_for_decrypt-read-for-decrypt.sql index 999e79c2fa1..2a764e2677a 100755 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read_for_decrypt-read-for-decrypt.sql +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_read_for_decrypt-read-for-decrypt.sql @@ -2,9 +2,12 @@ SELECT "keeper", "decrypters", "ref", - "external_id" + "external_id", + "active" FROM "secret_secure_value" -WHERE "namespace" = 'ns' AND - "name" = 'name' +WHERE + "namespace" = 'ns' AND + "name" = 'name' AND + "active" = true ; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_set_version_to_active-set secure value version to active.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_set_version_to_active-set secure value version to active.sql new file mode 100755 index 00000000000..d659f944431 --- /dev/null +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_set_version_to_active-set secure value version to active.sql @@ -0,0 +1,8 @@ +UPDATE + "secret_secure_value" +SET + "active" = ("version" = 1) +WHERE + "namespace" = 'ns' AND + "name" = 'name' +; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_update-update-not-null.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_update-update-not-null.sql deleted file mode 100755 index 7371f13f6e5..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_update-update-not-null.sql +++ /dev/null @@ -1,22 +0,0 @@ -UPDATE - "secret_secure_value" -SET - "guid" = 'abc', - "name" = 'name', - "namespace" = 'ns', - "annotations" = '{"x":"XXXX"}', - "labels" = '{"a":"AAA", "b", "BBBB"}', - "created" = 1234, - "created_by" = 'user:ryan', - "updated" = 5678, - "updated_by" = 'user:cameron', - "status_phase" = 'creating', - "status_message" = 'message_test', - "description" = 'description', - "keeper" = 'keeper_test', - "decrypters" = 'decrypters_test', - "ref" = 'ref_test', - "external_id" = 'extId' -WHERE "namespace" = 'ns' AND - "name" = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_update-update-null.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_update-update-null.sql deleted file mode 100755 index 0524e525096..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_update-update-null.sql +++ /dev/null @@ -1,18 +0,0 @@ -UPDATE - "secret_secure_value" -SET - "guid" = 'abc', - "name" = 'name', - "namespace" = 'ns', - "annotations" = '{"x":"XXXX"}', - "labels" = '{"a":"AAA", "b", "BBBB"}', - "created" = 1234, - "created_by" = 'user:ryan', - "updated" = 5678, - "updated_by" = 'user:cameron', - "status_phase" = 'creating', - "description" = 'description', - "external_id" = 'extId' -WHERE "namespace" = 'ns' AND - "name" = 'name' -; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_updateExternalId-updateExternalId.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_updateExternalId-updateExternalId.sql index 3d9f474776e..29bedaa7afe 100755 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_updateExternalId-updateExternalId.sql +++ b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_updateExternalId-updateExternalId.sql @@ -2,6 +2,8 @@ UPDATE "secret_secure_value" SET "external_id" = 'extId' -WHERE "namespace" = 'ns' AND - "name" = 'name' +WHERE + "namespace" = 'ns' AND + "name" = 'name' AND + "version" = 0 ; diff --git a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_updateStatus-updateStatus.sql b/pkg/storage/secret/metadata/testdata/sqlite--secure_value_updateStatus-updateStatus.sql deleted file mode 100755 index c5cf29a5e7a..00000000000 --- a/pkg/storage/secret/metadata/testdata/sqlite--secure_value_updateStatus-updateStatus.sql +++ /dev/null @@ -1,8 +0,0 @@ -UPDATE - "secret_secure_value" -SET - "status_phase" = 'Succeeded', - "status_message" = 'message-1' -WHERE "namespace" = 'ns' AND - "name" = 'name' -; diff --git a/pkg/storage/secret/migrator/migrator.go b/pkg/storage/secret/migrator/migrator.go index f453d6dd3af..6ee7209bc8a 100644 --- a/pkg/storage/secret/migrator/migrator.go +++ b/pkg/storage/secret/migrator/migrator.go @@ -12,11 +12,10 @@ import ( ) const ( - TableNameKeeper = "secret_keeper" - TableNameSecureValue = "secret_secure_value" - TableNameSecureValueOutbox = "secret_secure_value_outbox" - TableNameDataKey = "secret_data_key" - TableNameEncryptedValue = "secret_encrypted_value" + TableNameKeeper = "secret_keeper" + TableNameSecureValue = "secret_secure_value" + TableNameDataKey = "secret_data_key" + TableNameEncryptedValue = "secret_encrypted_value" ) type SecretDB struct { @@ -61,18 +60,19 @@ func (*SecretDB) AddMigration(mg *migrator.Migrator) { {Name: "updated_by", Type: migrator.DB_Text, Nullable: false}, // Kubernetes Status - {Name: "status_phase", Type: migrator.DB_Text, Nullable: false}, - {Name: "status_message", Type: migrator.DB_Text, Nullable: true}, + {Name: "external_id", Type: migrator.DB_Text, Nullable: false}, + {Name: "active", Type: migrator.DB_Bool, Nullable: false}, + {Name: "version", Type: migrator.DB_BigInt, Nullable: false}, // Spec {Name: "description", Type: migrator.DB_NVarchar, Length: 253, Nullable: false}, // Chosen arbitrarily, but should be enough. {Name: "keeper", Type: migrator.DB_NVarchar, Length: 253, Nullable: true}, // Keeper name, if not set, use default keeper. {Name: "decrypters", Type: migrator.DB_Text, Nullable: true}, {Name: "ref", Type: migrator.DB_NVarchar, Length: 1024, Nullable: true}, // Reference to third-party storage secret path.Chosen arbitrarily, but should be enough. - {Name: "external_id", Type: migrator.DB_Text, Nullable: false}, }, Indices: []*migrator.Index{ - {Cols: []string{"namespace", "name"}, Type: migrator.UniqueIndex}, + {Cols: []string{"namespace", "name", "version", "active"}, Type: migrator.UniqueIndex}, + {Cols: []string{"namespace", "name", "version"}, Type: migrator.UniqueIndex}, }, }) @@ -130,27 +130,6 @@ func (*SecretDB) AddMigration(mg *migrator.Migrator) { Indices: []*migrator.Index{}, // TODO: add indexes based on the queries we make. }) - tables = append(tables, migrator.Table{ - Name: TableNameSecureValueOutbox, - Columns: []*migrator.Column{ - {Name: "request_id", Type: migrator.DB_NVarchar, Length: 1024, Nullable: false}, // Safer upper limit because we hex-encode traceparent+tracestate to form the request_id. - {Name: "id", Type: migrator.DB_BigInt, Length: 36, IsPrimaryKey: true, IsAutoIncrement: true}, - {Name: "message_type", Type: migrator.DB_NVarchar, Length: 16, Nullable: false}, - {Name: "name", Type: migrator.DB_NVarchar, Length: 253, Nullable: false}, // Limit enforced by K8s. - {Name: "namespace", Type: migrator.DB_NVarchar, Length: 253, Nullable: false}, // Limit enforced by K8s. - {Name: "encrypted_secret", Type: migrator.DB_Blob, Nullable: true}, - {Name: "keeper_name", Type: migrator.DB_NVarchar, Length: 253, Nullable: true}, // Keeper name, if not set, use default keeper. - {Name: "external_id", Type: migrator.DB_NVarchar, Length: 36, Nullable: true}, // Fixed size of a UUID. - {Name: "receive_count", Type: migrator.DB_SmallInt, Nullable: false}, - {Name: "created", Type: migrator.DB_BigInt, Nullable: false}, - }, - Indices: []*migrator.Index{ - // There's only one operation per secret in the queue at all times, - // meaning the namespace + name combination should be unique - {Cols: []string{"namespace", "name"}, Type: migrator.UniqueIndex}, - }, - }) - // Initialize all tables for t := range tables { mg.AddMigration("drop table "+tables[t].Name, migrator.NewDropTableMigration(tables[t].Name)) diff --git a/pkg/storage/unified/apistore/watcher_test.go b/pkg/storage/unified/apistore/watcher_test.go index c68415bca97..91a251b04d0 100644 --- a/pkg/storage/unified/apistore/watcher_test.go +++ b/pkg/storage/unified/apistore/watcher_test.go @@ -40,6 +40,7 @@ import ( "github.com/grafana/grafana/pkg/storage/unified/resourcepb" "github.com/grafana/grafana/pkg/storage/unified/sql" "github.com/grafana/grafana/pkg/storage/unified/sql/db/dbimpl" + "github.com/grafana/grafana/pkg/tests" "github.com/grafana/grafana/pkg/tests/testsuite" ) @@ -134,9 +135,7 @@ func testSetup(t testing.TB, opts ...setupOption) (context.Context, storage.Inte _, err = server.IsHealthy(ctx, &resourcepb.HealthCheckRequest{}) require.NoError(t, err) case StorageTypeUnified: - if testing.Short() { - t.Skip("skipping integration test") - } + tests.SkipIntegrationTestInShortMode(t) dbstore := infraDB.InitTestDB(t) cfg := setting.NewCfg() @@ -190,7 +189,7 @@ func testSetup(t testing.TB, opts ...setupOption) (context.Context, storage.Inte return ctx, store, destroyFunc, nil } -func TestWatch(t *testing.T) { +func TestIntegrationWatch(t *testing.T) { for _, s := range []StorageType{StorageTypeFile, StorageTypeUnified} { t.Run(string(s), func(t *testing.T) { ctx, store, destroyFunc, err := testSetup(t, withStorageType(s)) diff --git a/pkg/storage/unified/search/bleve_integration_test.go b/pkg/storage/unified/search/bleve_integration_test.go index 6c28d560087..f76f89255e0 100644 --- a/pkg/storage/unified/search/bleve_integration_test.go +++ b/pkg/storage/unified/search/bleve_integration_test.go @@ -13,10 +13,6 @@ import ( ) func TestBleveSearchBackend(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } - // Run the search backend test suite unitest.RunSearchBackendTest(t, func(ctx context.Context) resource.SearchBackend { tempDir := t.TempDir() diff --git a/pkg/storage/unified/sql/db/mocks/DB.go b/pkg/storage/unified/sql/db/mocks/DB.go index ceda9e2865d..0177a0b3c1e 100644 --- a/pkg/storage/unified/sql/db/mocks/DB.go +++ b/pkg/storage/unified/sql/db/mocks/DB.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -83,7 +83,7 @@ func (_c *DB_BeginTx_Call) RunAndReturn(run func(context.Context, *sql.TxOptions return _c } -// DriverName provides a mock function with given fields: +// DriverName provides a mock function with no fields func (_m *DB) DriverName() string { ret := _m.Called() @@ -374,7 +374,7 @@ func (_c *DB_QueryRowContext_Call) RunAndReturn(run func(context.Context, string return _c } -// Stats provides a mock function with given fields: +// Stats provides a mock function with no fields func (_m *DB) Stats() sql.DBStats { ret := _m.Called() diff --git a/pkg/storage/unified/sql/db/mocks/Row.go b/pkg/storage/unified/sql/db/mocks/Row.go index 26b1b68c178..b4d0228d3c1 100644 --- a/pkg/storage/unified/sql/db/mocks/Row.go +++ b/pkg/storage/unified/sql/db/mocks/Row.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -17,7 +17,7 @@ func (_m *Row) EXPECT() *Row_Expecter { return &Row_Expecter{mock: &_m.Mock} } -// Err provides a mock function with given fields: +// Err provides a mock function with no fields func (_m *Row) Err() error { ret := _m.Called() diff --git a/pkg/storage/unified/sql/db/mocks/Rows.go b/pkg/storage/unified/sql/db/mocks/Rows.go index 33beddd5eed..dd653194844 100644 --- a/pkg/storage/unified/sql/db/mocks/Rows.go +++ b/pkg/storage/unified/sql/db/mocks/Rows.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -17,7 +17,7 @@ func (_m *Rows) EXPECT() *Rows_Expecter { return &Rows_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Rows) Close() error { ret := _m.Called() @@ -62,7 +62,7 @@ func (_c *Rows_Close_Call) RunAndReturn(run func() error) *Rows_Close_Call { return _c } -// Err provides a mock function with given fields: +// Err provides a mock function with no fields func (_m *Rows) Err() error { ret := _m.Called() @@ -107,7 +107,7 @@ func (_c *Rows_Err_Call) RunAndReturn(run func() error) *Rows_Err_Call { return _c } -// Next provides a mock function with given fields: +// Next provides a mock function with no fields func (_m *Rows) Next() bool { ret := _m.Called() @@ -152,7 +152,7 @@ func (_c *Rows_Next_Call) RunAndReturn(run func() bool) *Rows_Next_Call { return _c } -// NextResultSet provides a mock function with given fields: +// NextResultSet provides a mock function with no fields func (_m *Rows) NextResultSet() bool { ret := _m.Called() diff --git a/pkg/storage/unified/sql/db/mocks/Tx.go b/pkg/storage/unified/sql/db/mocks/Tx.go index 342e12a493c..4f70231aae3 100644 --- a/pkg/storage/unified/sql/db/mocks/Tx.go +++ b/pkg/storage/unified/sql/db/mocks/Tx.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -24,7 +24,7 @@ func (_m *Tx) EXPECT() *Tx_Expecter { return &Tx_Expecter{mock: &_m.Mock} } -// Commit provides a mock function with given fields: +// Commit provides a mock function with no fields func (_m *Tx) Commit() error { ret := _m.Called() @@ -269,7 +269,7 @@ func (_c *Tx_QueryRowContext_Call) RunAndReturn(run func(context.Context, string return _c } -// Rollback provides a mock function with given fields: +// Rollback provides a mock function with no fields func (_m *Tx) Rollback() error { ret := _m.Called() diff --git a/pkg/storage/unified/sql/db/mocks/result.go b/pkg/storage/unified/sql/db/mocks/result.go index 73aa331cd82..6999e42e194 100644 --- a/pkg/storage/unified/sql/db/mocks/result.go +++ b/pkg/storage/unified/sql/db/mocks/result.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -17,7 +17,7 @@ func (_m *Result) EXPECT() *Result_Expecter { return &Result_Expecter{mock: &_m.Mock} } -// LastInsertId provides a mock function with given fields: +// LastInsertId provides a mock function with no fields func (_m *Result) LastInsertId() (int64, error) { ret := _m.Called() @@ -72,7 +72,7 @@ func (_c *Result_LastInsertId_Call) RunAndReturn(run func() (int64, error)) *Res return _c } -// RowsAffected provides a mock function with given fields: +// RowsAffected provides a mock function with no fields func (_m *Result) RowsAffected() (int64, error) { ret := _m.Called() diff --git a/pkg/storage/unified/sql/sqltemplate/mocks/SQLTemplateIface.go b/pkg/storage/unified/sql/sqltemplate/mocks/SQLTemplate.go similarity index 97% rename from pkg/storage/unified/sql/sqltemplate/mocks/SQLTemplateIface.go rename to pkg/storage/unified/sql/sqltemplate/mocks/SQLTemplate.go index 86cbb32fd5b..baeb4d1542e 100644 --- a/pkg/storage/unified/sql/sqltemplate/mocks/SQLTemplateIface.go +++ b/pkg/storage/unified/sql/sqltemplate/mocks/SQLTemplate.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -171,7 +171,7 @@ func (_c *SQLTemplate_ArgPlaceholder_Call) RunAndReturn(run func(int) string) *S return _c } -// CurrentEpoch provides a mock function with given fields: +// CurrentEpoch provides a mock function with no fields func (_m *SQLTemplate) CurrentEpoch() string { ret := _m.Called() @@ -216,7 +216,7 @@ func (_c *SQLTemplate_CurrentEpoch_Call) RunAndReturn(run func() string) *SQLTem return _c } -// DialectName provides a mock function with given fields: +// DialectName provides a mock function with no fields func (_m *SQLTemplate) DialectName() string { ret := _m.Called() @@ -261,7 +261,7 @@ func (_c *SQLTemplate_DialectName_Call) RunAndReturn(run func() string) *SQLTemp return _c } -// GetArgs provides a mock function with given fields: +// GetArgs provides a mock function with no fields func (_m *SQLTemplate) GetArgs() []interface{} { ret := _m.Called() @@ -308,7 +308,7 @@ func (_c *SQLTemplate_GetArgs_Call) RunAndReturn(run func() []interface{}) *SQLT return _c } -// GetColNames provides a mock function with given fields: +// GetColNames provides a mock function with no fields func (_m *SQLTemplate) GetColNames() []string { ret := _m.Called() @@ -355,7 +355,7 @@ func (_c *SQLTemplate_GetColNames_Call) RunAndReturn(run func() []string) *SQLTe return _c } -// GetScanDest provides a mock function with given fields: +// GetScanDest provides a mock function with no fields func (_m *SQLTemplate) GetScanDest() []interface{} { ret := _m.Called() @@ -515,7 +515,7 @@ func (_c *SQLTemplate_Into_Call) RunAndReturn(run func(reflect.Value, string) (s return _c } -// Reset provides a mock function with given fields: +// Reset provides a mock function with no fields func (_m *SQLTemplate) Reset() { _m.Called() } @@ -543,7 +543,7 @@ func (_c *SQLTemplate_Reset_Call) Return() *SQLTemplate_Reset_Call { } func (_c *SQLTemplate_Reset_Call) RunAndReturn(run func()) *SQLTemplate_Reset_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -645,11 +645,11 @@ func (_c *SQLTemplate_SetDialect_Call) Return() *SQLTemplate_SetDialect_Call { } func (_c *SQLTemplate_SetDialect_Call) RunAndReturn(run func(sqltemplate.Dialect)) *SQLTemplate_SetDialect_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Validate provides a mock function with given fields: +// Validate provides a mock function with no fields func (_m *SQLTemplate) Validate() error { ret := _m.Called() diff --git a/pkg/storage/unified/sql/sqltemplate/mocks/WithResults.go b/pkg/storage/unified/sql/sqltemplate/mocks/WithResults.go index 50f71da1e28..c109512de5d 100644 --- a/pkg/storage/unified/sql/sqltemplate/mocks/WithResults.go +++ b/pkg/storage/unified/sql/sqltemplate/mocks/WithResults.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -171,7 +171,7 @@ func (_c *WithResults_ArgPlaceholder_Call[T]) RunAndReturn(run func(int) string) return _c } -// CurrentEpoch provides a mock function with given fields: +// CurrentEpoch provides a mock function with no fields func (_m *WithResults[T]) CurrentEpoch() string { ret := _m.Called() @@ -216,7 +216,7 @@ func (_c *WithResults_CurrentEpoch_Call[T]) RunAndReturn(run func() string) *Wit return _c } -// DialectName provides a mock function with given fields: +// DialectName provides a mock function with no fields func (_m *WithResults[T]) DialectName() string { ret := _m.Called() @@ -261,7 +261,7 @@ func (_c *WithResults_DialectName_Call[T]) RunAndReturn(run func() string) *With return _c } -// GetArgs provides a mock function with given fields: +// GetArgs provides a mock function with no fields func (_m *WithResults[T]) GetArgs() []interface{} { ret := _m.Called() @@ -308,7 +308,7 @@ func (_c *WithResults_GetArgs_Call[T]) RunAndReturn(run func() []interface{}) *W return _c } -// GetColNames provides a mock function with given fields: +// GetColNames provides a mock function with no fields func (_m *WithResults[T]) GetColNames() []string { ret := _m.Called() @@ -355,7 +355,7 @@ func (_c *WithResults_GetColNames_Call[T]) RunAndReturn(run func() []string) *Wi return _c } -// GetScanDest provides a mock function with given fields: +// GetScanDest provides a mock function with no fields func (_m *WithResults[T]) GetScanDest() []interface{} { ret := _m.Called() @@ -515,7 +515,7 @@ func (_c *WithResults_Into_Call[T]) RunAndReturn(run func(reflect.Value, string) return _c } -// Reset provides a mock function with given fields: +// Reset provides a mock function with no fields func (_m *WithResults[T]) Reset() { _m.Called() } @@ -543,11 +543,11 @@ func (_c *WithResults_Reset_Call[T]) Return() *WithResults_Reset_Call[T] { } func (_c *WithResults_Reset_Call[T]) RunAndReturn(run func()) *WithResults_Reset_Call[T] { - _c.Call.Return(run) + _c.Run(run) return _c } -// Results provides a mock function with given fields: +// Results provides a mock function with no fields func (_m *WithResults[T]) Results() (T, error) { ret := _m.Called() @@ -563,7 +563,9 @@ func (_m *WithResults[T]) Results() (T, error) { if rf, ok := ret.Get(0).(func() T); ok { r0 = rf() } else { - r0 = ret.Get(0).(T) + if ret.Get(0) != nil { + r0 = ret.Get(0).(T) + } } if rf, ok := ret.Get(1).(func() error); ok { @@ -700,11 +702,11 @@ func (_c *WithResults_SetDialect_Call[T]) Return() *WithResults_SetDialect_Call[ } func (_c *WithResults_SetDialect_Call[T]) RunAndReturn(run func(sqltemplate.Dialect)) *WithResults_SetDialect_Call[T] { - _c.Call.Return(run) + _c.Run(run) return _c } -// Validate provides a mock function with given fields: +// Validate provides a mock function with no fields func (_m *WithResults[T]) Validate() error { ret := _m.Called() diff --git a/pkg/storage/unified/sql/test/benchmark_test.go b/pkg/storage/unified/sql/test/benchmark_test.go index d937abb70ab..88f9ed2c955 100644 --- a/pkg/storage/unified/sql/test/benchmark_test.go +++ b/pkg/storage/unified/sql/test/benchmark_test.go @@ -17,6 +17,7 @@ import ( "github.com/grafana/grafana/pkg/storage/unified/sql" "github.com/grafana/grafana/pkg/storage/unified/sql/db/dbimpl" test "github.com/grafana/grafana/pkg/storage/unified/testing" + "github.com/grafana/grafana/pkg/tests" ) func newTestBackend(b testing.TB) resource.StorageBackend { @@ -38,9 +39,7 @@ func newTestBackend(b testing.TB) resource.StorageBackend { } func TestIntegrationBenchmarkSQLStorageBackend(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test in short mode") - } + tests.SkipIntegrationTestInShortMode(t) opts := test.DefaultBenchmarkOptions() if db.IsTestDbSQLite() { opts.Concurrency = 1 // to avoid SQLite database is locked error @@ -49,9 +48,7 @@ func TestIntegrationBenchmarkSQLStorageBackend(t *testing.T) { } func TestIntegrationBenchmarkResourceServer(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test in short mode") - } + tests.SkipIntegrationTestInShortMode(t) ctx := context.Background() opts := &test.BenchmarkOptions{ diff --git a/pkg/storage/unified/sql/test/integration_test.go b/pkg/storage/unified/sql/test/integration_test.go index 99ff031aab1..e33af48713f 100644 --- a/pkg/storage/unified/sql/test/integration_test.go +++ b/pkg/storage/unified/sql/test/integration_test.go @@ -26,6 +26,7 @@ import ( "github.com/grafana/grafana/pkg/storage/unified/sql" "github.com/grafana/grafana/pkg/storage/unified/sql/db/dbimpl" unitest "github.com/grafana/grafana/pkg/storage/unified/testing" + "github.com/grafana/grafana/pkg/tests" "github.com/grafana/grafana/pkg/tests/testsuite" "github.com/grafana/grafana/pkg/util/testutil" ) @@ -95,9 +96,7 @@ func TestIntegrationSQLStorageBackend(t *testing.T) { } func TestIntegrationSearchAndStorage(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test in short mode") - } + tests.SkipIntegrationTestInShortMode(t) ctx := context.Background() diff --git a/pkg/storage/unified/testing/kv.go b/pkg/storage/unified/testing/kv.go index 5c205697e69..0c3b745fdf0 100644 --- a/pkg/storage/unified/testing/kv.go +++ b/pkg/storage/unified/testing/kv.go @@ -43,10 +43,6 @@ func GenerateRandomKVPrefix() string { // RunKVTest runs the KV test suite func RunKVTest(t *testing.T, newKV NewKVFunc, opts *KVTestOptions) { - if testing.Short() { - t.Skip("skipping integration test") - } - if opts == nil { opts = &KVTestOptions{} } diff --git a/pkg/storage/unified/testing/search_backend.go b/pkg/storage/unified/testing/search_backend.go index 505e1b1a43d..57d887682c6 100644 --- a/pkg/storage/unified/testing/search_backend.go +++ b/pkg/storage/unified/testing/search_backend.go @@ -24,10 +24,6 @@ type NewSearchBackendFunc func(ctx context.Context) resource.SearchBackend // RunSearchBackendTest runs the search backend test suite func RunSearchBackendTest(t *testing.T, newBackend NewSearchBackendFunc, opts *TestOptions) { - if testing.Short() { - t.Skip("skipping integration test") - } - if opts == nil { opts = &TestOptions{} } diff --git a/pkg/tests/api/plugins/data/expectedListResp.json b/pkg/tests/api/plugins/data/expectedListResp.json index 45b82107af4..e74d718d9bf 100644 --- a/pkg/tests/api/plugins/data/expectedListResp.json +++ b/pkg/tests/api/plugins/data/expectedListResp.json @@ -22,8 +22,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/alertlist/img/icn-singlestat-panel.svg", - "large": "public/app/plugins/panel/alertlist/img/icn-singlestat-panel.svg" + "small": "public/plugins/alertlist/img/icn-singlestat-panel.svg", + "large": "public/plugins/alertlist/img/icn-singlestat-panel.svg" }, "build": {}, "screenshots": null, @@ -76,8 +76,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/alertmanager/img/logo.svg", - "large": "public/app/plugins/datasource/alertmanager/img/logo.svg" + "small": "public/plugins/alertmanager/img/logo.svg", + "large": "public/plugins/alertmanager/img/logo.svg" }, "build": {}, "screenshots": null, @@ -133,8 +133,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/annolist/img/icn-annolist-panel.svg", - "large": "public/app/plugins/panel/annolist/img/icn-annolist-panel.svg" + "small": "public/plugins/annolist/img/icn-annolist-panel.svg", + "large": "public/plugins/annolist/img/icn-annolist-panel.svg" }, "build": {}, "screenshots": null, @@ -191,22 +191,22 @@ } ], "logos": { - "small": "public/app/plugins/datasource/azuremonitor/img/logo.jpg", - "large": "public/app/plugins/datasource/azuremonitor/img/logo.jpg" + "small": "public/plugins/grafana-azure-monitor-datasource/img/logo.jpg", + "large": "public/plugins/grafana-azure-monitor-datasource/img/logo.jpg" }, "build": {}, "screenshots": [ { "name": "Azure Contoso Loans", - "path": "public/app/plugins/datasource/azuremonitor/img/contoso_loans_grafana_dashboard.png" + "path": "public/plugins/grafana-azure-monitor-datasource/img/contoso_loans_grafana_dashboard.png" }, { "name": "Azure Monitor Network", - "path": "public/app/plugins/datasource/azuremonitor/img/azure_monitor_network.png" + "path": "public/plugins/grafana-azure-monitor-datasource/img/azure_monitor_network.png" }, { "name": "Azure Monitor CPU", - "path": "public/app/plugins/datasource/azuremonitor/img/azure_monitor_cpu.png" + "path": "public/plugins/grafana-azure-monitor-datasource/img/azure_monitor_cpu.png" } ], "version": "12.1.0-pre", @@ -260,8 +260,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/barchart/img/barchart.svg", - "large": "public/app/plugins/panel/barchart/img/barchart.svg" + "small": "public/plugins/barchart/img/barchart.svg", + "large": "public/plugins/barchart/img/barchart.svg" }, "build": {}, "screenshots": null, @@ -310,8 +310,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/bargauge/img/icon_bar_gauge.svg", - "large": "public/app/plugins/panel/bargauge/img/icon_bar_gauge.svg" + "small": "public/plugins/bargauge/img/icon_bar_gauge.svg", + "large": "public/plugins/bargauge/img/icon_bar_gauge.svg" }, "build": {}, "screenshots": null, @@ -360,8 +360,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/candlestick/img/candlestick.svg", - "large": "public/app/plugins/panel/candlestick/img/candlestick.svg" + "small": "public/plugins/candlestick/img/candlestick.svg", + "large": "public/plugins/candlestick/img/candlestick.svg" }, "build": {}, "screenshots": null, @@ -415,8 +415,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/canvas/img/icn-canvas.svg", - "large": "public/app/plugins/panel/canvas/img/icn-canvas.svg" + "small": "public/plugins/canvas/img/icn-canvas.svg", + "large": "public/plugins/canvas/img/icn-canvas.svg" }, "build": {}, "screenshots": null, @@ -465,8 +465,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", - "large": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png" + "small": "public/plugins/cloudwatch/img/amazon-web-services.png", + "large": "public/plugins/cloudwatch/img/amazon-web-services.png" }, "build": {}, "screenshots": null, @@ -518,8 +518,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/dashlist/img/icn-dashlist-panel.svg", - "large": "public/app/plugins/panel/dashlist/img/icn-dashlist-panel.svg" + "small": "public/plugins/dashlist/img/icn-dashlist-panel.svg", + "large": "public/plugins/dashlist/img/icn-dashlist-panel.svg" }, "build": {}, "screenshots": null, @@ -568,8 +568,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/datagrid/img/icn-table-panel.svg", - "large": "public/app/plugins/panel/datagrid/img/icn-table-panel.svg" + "small": "public/plugins/datagrid/img/icn-table-panel.svg", + "large": "public/plugins/datagrid/img/icn-table-panel.svg" }, "build": {}, "screenshots": null, @@ -622,8 +622,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/elasticsearch/img/elasticsearch.svg", - "large": "public/app/plugins/datasource/elasticsearch/img/elasticsearch.svg" + "small": "public/plugins/elasticsearch/img/elasticsearch.svg", + "large": "public/plugins/elasticsearch/img/elasticsearch.svg" }, "build": {}, "screenshots": null, @@ -679,8 +679,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/flamegraph/img/icn-flamegraph.svg", - "large": "public/app/plugins/panel/flamegraph/img/icn-flamegraph.svg" + "small": "public/plugins/flamegraph/img/icn-flamegraph.svg", + "large": "public/plugins/flamegraph/img/icn-flamegraph.svg" }, "build": {}, "screenshots": null, @@ -729,8 +729,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/gauge/img/icon_gauge.svg", - "large": "public/app/plugins/panel/gauge/img/icon_gauge.svg" + "small": "public/plugins/gauge/img/icon_gauge.svg", + "large": "public/plugins/gauge/img/icon_gauge.svg" }, "build": {}, "screenshots": null, @@ -779,8 +779,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/geomap/img/icn-geomap.svg", - "large": "public/app/plugins/panel/geomap/img/icn-geomap.svg" + "small": "public/plugins/geomap/img/icn-geomap.svg", + "large": "public/plugins/geomap/img/icn-geomap.svg" }, "build": {}, "screenshots": null, @@ -825,8 +825,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/gettingstarted/img/icn-dashlist-panel.svg", - "large": "public/app/plugins/panel/gettingstarted/img/icn-dashlist-panel.svg" + "small": "public/plugins/gettingstarted/img/icn-dashlist-panel.svg", + "large": "public/plugins/gettingstarted/img/icn-dashlist-panel.svg" }, "build": {}, "screenshots": null, @@ -875,8 +875,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/cloud-monitoring/img/cloud_monitoring_logo.svg", - "large": "public/app/plugins/datasource/cloud-monitoring/img/cloud_monitoring_logo.svg" + "small": "public/plugins/stackdriver/img/cloud_monitoring_logo.svg", + "large": "public/plugins/stackdriver/img/cloud_monitoring_logo.svg" }, "build": {}, "screenshots": null, @@ -929,8 +929,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/grafana-pyroscope-datasource/img/grafana_pyroscope_icon.svg", - "large": "public/app/plugins/datasource/grafana-pyroscope-datasource/img/grafana_pyroscope_icon.svg" + "small": "public/plugins/grafana-pyroscope-datasource/img/grafana_pyroscope_icon.svg", + "large": "public/plugins/grafana-pyroscope-datasource/img/grafana_pyroscope_icon.svg" }, "build": {}, "screenshots": null, @@ -995,8 +995,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/graphite/img/graphite_logo.png", - "large": "public/app/plugins/datasource/graphite/img/graphite_logo.png" + "small": "public/plugins/graphite/img/graphite_logo.png", + "large": "public/plugins/graphite/img/graphite_logo.png" }, "build": {}, "screenshots": null, @@ -1045,8 +1045,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/heatmap/img/icn-heatmap-panel.svg", - "large": "public/app/plugins/panel/heatmap/img/icn-heatmap-panel.svg" + "small": "public/plugins/heatmap/img/icn-heatmap-panel.svg", + "large": "public/plugins/heatmap/img/icn-heatmap-panel.svg" }, "build": {}, "screenshots": null, @@ -1095,8 +1095,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/histogram/img/histogram.svg", - "large": "public/app/plugins/panel/histogram/img/histogram.svg" + "small": "public/plugins/histogram/img/histogram.svg", + "large": "public/plugins/histogram/img/histogram.svg" }, "build": {}, "screenshots": null, @@ -1150,8 +1150,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/influxdb/img/influxdb_logo.svg", - "large": "public/app/plugins/datasource/influxdb/img/influxdb_logo.svg" + "small": "public/plugins/influxdb/img/influxdb_logo.svg", + "large": "public/plugins/influxdb/img/influxdb_logo.svg" }, "build": {}, "screenshots": null, @@ -1212,8 +1212,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/jaeger/img/jaeger_logo.svg", - "large": "public/app/plugins/datasource/jaeger/img/jaeger_logo.svg" + "small": "public/plugins/jaeger/img/jaeger_logo.svg", + "large": "public/plugins/jaeger/img/jaeger_logo.svg" }, "build": {}, "screenshots": null, @@ -1262,8 +1262,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/logs/img/icn-logs-panel.svg", - "large": "public/app/plugins/panel/logs/img/icn-logs-panel.svg" + "small": "public/plugins/logs/img/icn-logs-panel.svg", + "large": "public/plugins/logs/img/icn-logs-panel.svg" }, "build": {}, "screenshots": null, @@ -1320,8 +1320,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/loki/img/loki_icon.svg", - "large": "public/app/plugins/datasource/loki/img/loki_icon.svg" + "small": "public/plugins/loki/img/loki_icon.svg", + "large": "public/plugins/loki/img/loki_icon.svg" }, "build": {}, "screenshots": null, @@ -1370,8 +1370,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/mssql/img/sql_server_logo.svg", - "large": "public/app/plugins/datasource/mssql/img/sql_server_logo.svg" + "small": "public/plugins/mssql/img/sql_server_logo.svg", + "large": "public/plugins/mssql/img/sql_server_logo.svg" }, "build": {}, "screenshots": null, @@ -1420,8 +1420,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/mysql/img/mysql_logo.svg", - "large": "public/app/plugins/datasource/mysql/img/mysql_logo.svg" + "small": "public/plugins/mysql/img/mysql_logo.svg", + "large": "public/plugins/mysql/img/mysql_logo.svg" }, "build": {}, "screenshots": null, @@ -1470,8 +1470,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/news/img/news.svg", - "large": "public/app/plugins/panel/news/img/news.svg" + "small": "public/plugins/news/img/news.svg", + "large": "public/plugins/news/img/news.svg" }, "build": {}, "screenshots": null, @@ -1520,8 +1520,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/nodeGraph/img/icn-node-graph.svg", - "large": "public/app/plugins/panel/nodeGraph/img/icn-node-graph.svg" + "small": "public/plugins/nodeGraph/img/icn-node-graph.svg", + "large": "public/plugins/nodeGraph/img/icn-node-graph.svg" }, "build": {}, "screenshots": null, @@ -1570,8 +1570,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/opentsdb/img/opentsdb_logo.png", - "large": "public/app/plugins/datasource/opentsdb/img/opentsdb_logo.png" + "small": "public/plugins/opentsdb/img/opentsdb_logo.png", + "large": "public/plugins/opentsdb/img/opentsdb_logo.png" }, "build": {}, "screenshots": null, @@ -1624,8 +1624,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/parca/img/logo-small.svg", - "large": "public/app/plugins/datasource/parca/img/logo-small.svg" + "small": "public/plugins/parca/img/logo-small.svg", + "large": "public/plugins/parca/img/logo-small.svg" }, "build": {}, "screenshots": null, @@ -1679,8 +1679,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/piechart/img/icon_piechart.svg", - "large": "public/app/plugins/panel/piechart/img/icon_piechart.svg" + "small": "public/plugins/piechart/img/icon_piechart.svg", + "large": "public/plugins/piechart/img/icon_piechart.svg" }, "build": {}, "screenshots": null, @@ -1729,8 +1729,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/grafana-postgresql-datasource/img/postgresql_logo.svg", - "large": "public/app/plugins/datasource/grafana-postgresql-datasource/img/postgresql_logo.svg" + "small": "public/plugins/grafana-postgresql-datasource/img/postgresql_logo.svg", + "large": "public/plugins/grafana-postgresql-datasource/img/postgresql_logo.svg" }, "build": {}, "screenshots": null, @@ -1783,8 +1783,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/prometheus/img/prometheus_logo.svg", - "large": "public/app/plugins/datasource/prometheus/img/prometheus_logo.svg" + "small": "public/plugins/prometheus/img/prometheus_logo.svg", + "large": "public/plugins/prometheus/img/prometheus_logo.svg" }, "build": {}, "screenshots": null, @@ -1833,8 +1833,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/stat/img/icn-singlestat-panel.svg", - "large": "public/app/plugins/panel/stat/img/icn-singlestat-panel.svg" + "small": "public/plugins/stat/img/icn-singlestat-panel.svg", + "large": "public/plugins/stat/img/icn-singlestat-panel.svg" }, "build": {}, "screenshots": null, @@ -1883,8 +1883,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/state-timeline/img/timeline.svg", - "large": "public/app/plugins/panel/state-timeline/img/timeline.svg" + "small": "public/plugins/state-timeline/img/timeline.svg", + "large": "public/plugins/state-timeline/img/timeline.svg" }, "build": {}, "screenshots": null, @@ -1933,8 +1933,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/status-history/img/status.svg", - "large": "public/app/plugins/panel/status-history/img/status.svg" + "small": "public/plugins/status-history/img/status.svg", + "large": "public/plugins/status-history/img/status.svg" }, "build": {}, "screenshots": null, @@ -1983,8 +1983,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/table/img/icn-table-panel.svg", - "large": "public/app/plugins/panel/table/img/icn-table-panel.svg" + "small": "public/plugins/table/img/icn-table-panel.svg", + "large": "public/plugins/table/img/icn-table-panel.svg" }, "build": {}, "screenshots": null, @@ -2037,8 +2037,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/tempo/img/tempo_logo.svg", - "large": "public/app/plugins/datasource/tempo/img/tempo_logo.svg" + "small": "public/plugins/tempo/img/tempo_logo.svg", + "large": "public/plugins/tempo/img/tempo_logo.svg" }, "build": {}, "screenshots": null, @@ -2087,8 +2087,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/grafana-testdata-datasource/img/testdata.svg", - "large": "public/app/plugins/datasource/grafana-testdata-datasource/img/testdata.svg" + "small": "public/plugins/grafana-testdata-datasource/img/testdata.svg", + "large": "public/plugins/grafana-testdata-datasource/img/testdata.svg" }, "build": {}, "screenshots": null, @@ -2137,8 +2137,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/text/img/icn-text-panel.svg", - "large": "public/app/plugins/panel/text/img/icn-text-panel.svg" + "small": "public/plugins/text/img/icn-text-panel.svg", + "large": "public/plugins/text/img/icn-text-panel.svg" }, "build": {}, "screenshots": null, @@ -2187,8 +2187,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/timeseries/img/icn-timeseries-panel.svg", - "large": "public/app/plugins/panel/timeseries/img/icn-timeseries-panel.svg" + "small": "public/plugins/timeseries/img/icn-timeseries-panel.svg", + "large": "public/plugins/timeseries/img/icn-timeseries-panel.svg" }, "build": {}, "screenshots": null, @@ -2237,8 +2237,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/traces/img/traces-panel.svg", - "large": "public/app/plugins/panel/traces/img/traces-panel.svg" + "small": "public/plugins/traces/img/traces-panel.svg", + "large": "public/plugins/traces/img/traces-panel.svg" }, "build": {}, "screenshots": null, @@ -2287,8 +2287,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/trend/img/trend.svg", - "large": "public/app/plugins/panel/trend/img/trend.svg" + "small": "public/plugins/trend/img/trend.svg", + "large": "public/plugins/trend/img/trend.svg" }, "build": {}, "screenshots": null, @@ -2333,8 +2333,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/welcome/img/icn-dashlist-panel.svg", - "large": "public/app/plugins/panel/welcome/img/icn-dashlist-panel.svg" + "small": "public/plugins/welcome/img/icn-dashlist-panel.svg", + "large": "public/plugins/welcome/img/icn-dashlist-panel.svg" }, "build": {}, "screenshots": null, @@ -2383,8 +2383,8 @@ } ], "logos": { - "small": "public/app/plugins/panel/xychart/img/icn-xychart.svg", - "large": "public/app/plugins/panel/xychart/img/icn-xychart.svg" + "small": "public/plugins/xychart/img/icn-xychart.svg", + "large": "public/plugins/xychart/img/icn-xychart.svg" }, "build": {}, "screenshots": null, @@ -2440,8 +2440,8 @@ } ], "logos": { - "small": "public/app/plugins/datasource/zipkin/img/zipkin-logo.svg", - "large": "public/app/plugins/datasource/zipkin/img/zipkin-logo.svg" + "small": "public/plugins/zipkin/img/zipkin-logo.svg", + "large": "public/plugins/zipkin/img/zipkin-logo.svg" }, "build": {}, "screenshots": null, @@ -2467,4 +2467,4 @@ "signatureOrg": "", "angularDetected": false } -] \ No newline at end of file +] diff --git a/pkg/tests/apis/dashboard/integration/api_validation_test.go b/pkg/tests/apis/dashboard/integration/api_validation_test.go index 2215808970c..26e86c8f510 100644 --- a/pkg/tests/apis/dashboard/integration/api_validation_test.go +++ b/pkg/tests/apis/dashboard/integration/api_validation_test.go @@ -71,6 +71,7 @@ func TestIntegrationValidation(t *testing.T) { EnableFeatureToggles: []string{ featuremgmt.FlagKubernetesClientDashboardsFolders, // Enable dashboard feature featuremgmt.FlagUnifiedStorageSearch, + featuremgmt.FlagKubernetesDashboards, // Enable FE-only dashboard feature flag }, UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ "dashboards.dashboard.grafana.app": { @@ -81,6 +82,36 @@ func TestIntegrationValidation(t *testing.T) { testIntegrationValidationForServer(t, helper, dualWriterMode) }) } + + for _, dualWriterMode := range dualWriterModes { + t.Run(fmt.Sprintf("DualWriterMode %d - kubernetesDashboards disabled", dualWriterMode), func(t *testing.T) { + // Create a K8sTestHelper which will set up a real API server + helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ + DisableAnonymous: true, + EnableFeatureToggles: []string{ + featuremgmt.FlagKubernetesClientDashboardsFolders, // Enable dashboard feature + featuremgmt.FlagUnifiedStorageSearch, + }, + DisableFeatureToggles: []string{ + featuremgmt.FlagKubernetesDashboards, + }, + UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ + "dashboards.dashboard.grafana.app": { + DualWriterMode: dualWriterMode, + }, + }}) + + t.Cleanup(func() { + helper.Shutdown() + }) + + org1Ctx := createTestContext(t, helper, helper.Org1, dualWriterMode) + + t.Run("Dashboard permission tests", func(t *testing.T) { + runDashboardPermissionTests(t, org1Ctx, false) + }) + }) + } } func testIntegrationValidationForServer(t *testing.T, helper *apis.K8sTestHelper, dualWriterMode rest.DualWriterMode) { @@ -106,7 +137,7 @@ func testIntegrationValidationForServer(t *testing.T, helper *apis.K8sTestHelper }) t.Run("Dashboard permission tests", func(t *testing.T) { - runDashboardPermissionTests(t, org1Ctx) + runDashboardPermissionTests(t, org1Ctx, true) }) t.Run("Dashboard LIST API test", func(t *testing.T) { @@ -1225,7 +1256,7 @@ func runAuthorizationTests(t *testing.T, ctx TestContext) { } // Run tests for dashboard permissions -func runDashboardPermissionTests(t *testing.T, ctx TestContext) { +func runDashboardPermissionTests(t *testing.T, ctx TestContext, kubernetesDashboardsEnabled bool) { t.Helper() // Get clients for each user @@ -1348,8 +1379,22 @@ func runDashboardPermissionTests(t *testing.T, ctx TestContext) { // Clean up dashboard err = adminClient.Resource.Delete(context.Background(), dash.GetName(), v1.DeleteOptions{}) require.NoError(t, err) - err = viewerClient.Resource.Delete(context.Background(), dashViewer.GetName(), v1.DeleteOptions{}) - require.NoError(t, err) + + if kubernetesDashboardsEnabled { + // In case kubernetesDashboards feature flag is set to true, + // we don't grant admin permission to dashboard creator on nested folders. + // This means that the viewer will not be able to delete the dashboard. + err = viewerClient.Resource.Delete(context.Background(), dashViewer.GetName(), v1.DeleteOptions{}) + require.Error(t, err) + err = adminClient.Resource.Delete(context.Background(), dashViewer.GetName(), v1.DeleteOptions{}) + require.NoError(t, err) + } else { + // In case kubernetesDashboards feature flag is set to false, + // we grant admin permission to dashboard creator on nested folders. + // This means that the viewer will be able to delete the dashboard. + err = viewerClient.Resource.Delete(context.Background(), dashViewer.GetName(), v1.DeleteOptions{}) + require.NoError(t, err) + } // Clean up the folder err = adminFolderClient.Resource.Delete(context.Background(), folderUID, v1.DeleteOptions{}) diff --git a/pkg/tests/apis/folder/folders_test.go b/pkg/tests/apis/folder/folders_test.go index 24459c08963..68ffb9f3a4d 100644 --- a/pkg/tests/apis/folder/folders_test.go +++ b/pkg/tests/apis/folder/folders_test.go @@ -1026,6 +1026,7 @@ func TestIntegrationFoldersGetAPIEndpointK8S(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } + t.Skip("not working yet") type testCase struct { description string diff --git a/pkg/tests/utils.go b/pkg/tests/utils.go index f81683c80f4..4ea428df9f7 100644 --- a/pkg/tests/utils.go +++ b/pkg/tests/utils.go @@ -5,10 +5,13 @@ import ( "crypto/tls" "net/url" "os" + "strings" "testing" "github.com/go-openapi/strfmt" goapi "github.com/grafana/grafana-openapi-client-go/client" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" @@ -19,9 +22,18 @@ import ( "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user/userimpl" "github.com/grafana/grafana/pkg/setting" - "github.com/stretchr/testify/require" ) +func SkipIntegrationTestInShortMode(t testing.TB) { + t.Helper() + if !strings.HasPrefix(t.Name(), "TestIntegration") { + t.Fatal("test is not an integration test") + } + if testing.Short() { + t.Skip("skipping integration test in short mode") + } +} + func CreateUser(t *testing.T, db db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { t.Helper() diff --git a/pkg/tsdb/cloudwatch/cloudwatch.go b/pkg/tsdb/cloudwatch/cloudwatch.go index 28567e4e5d5..919b853887e 100644 --- a/pkg/tsdb/cloudwatch/cloudwatch.go +++ b/pkg/tsdb/cloudwatch/cloudwatch.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "net/http" "slices" "time" @@ -73,6 +74,7 @@ func (ds *DataSource) newAWSConfig(ctx context.Context, region string) (aws.Conf Region: region, AccessKey: ds.Settings.AccessKey, SecretKey: ds.Settings.SecretKey, + HTTPClient: &http.Client{}, } if ds.Settings.GrafanaSettings.SecureSocksDSProxyEnabled && ds.Settings.SecureSocksProxyEnabled { authSettings.ProxyOptions = ds.ProxyOpts diff --git a/pkg/util/testutil/mocks/T.go b/pkg/util/testutil/mocks/T.go index 2e2c110fb82..d85781703b0 100644 --- a/pkg/util/testutil/mocks/T.go +++ b/pkg/util/testutil/mocks/T.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.1. DO NOT EDIT. +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks @@ -50,11 +50,11 @@ func (_c *T_Cleanup_Call) Return() *T_Cleanup_Call { } func (_c *T_Cleanup_Call) RunAndReturn(run func(func())) *T_Cleanup_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Deadline provides a mock function with given fields: +// Deadline provides a mock function with no fields func (_m *T) Deadline() (time.Time, bool) { ret := _m.Called() @@ -149,11 +149,11 @@ func (_c *T_Errorf_Call) Return() *T_Errorf_Call { } func (_c *T_Errorf_Call) RunAndReturn(run func(string, ...interface{})) *T_Errorf_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// FailNow provides a mock function with given fields: +// FailNow provides a mock function with no fields func (_m *T) FailNow() { _m.Called() } @@ -181,11 +181,11 @@ func (_c *T_FailNow_Call) Return() *T_FailNow_Call { } func (_c *T_FailNow_Call) RunAndReturn(run func()) *T_FailNow_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Helper provides a mock function with given fields: +// Helper provides a mock function with no fields func (_m *T) Helper() { _m.Called() } @@ -213,7 +213,7 @@ func (_c *T_Helper_Call) Return() *T_Helper_Call { } func (_c *T_Helper_Call) RunAndReturn(run func()) *T_Helper_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/public/api-enterprise-spec.json b/public/api-enterprise-spec.json index d431451f492..6d5885e3bdd 100644 --- a/public/api-enterprise-spec.json +++ b/public/api-enterprise-spec.json @@ -5764,6 +5764,8 @@ "errorCode": { "type": "string", "enum": [ + "ALERT_RULES_QUOTA_REACHED", + "ALERT_RULES_GROUP_QUOTA_REACHED", "DATASOURCE_NAME_CONFLICT", "DATASOURCE_INVALID_URL", "DATASOURCE_ALREADY_MANAGED", diff --git a/public/api-merged.json b/public/api-merged.json index 0706252d551..0778d9d6d3d 100644 --- a/public/api-merged.json +++ b/public/api-merged.json @@ -17319,6 +17319,8 @@ "errorCode": { "type": "string", "enum": [ + "ALERT_RULES_QUOTA_REACHED", + "ALERT_RULES_GROUP_QUOTA_REACHED", "DATASOURCE_NAME_CONFLICT", "DATASOURCE_INVALID_URL", "DATASOURCE_ALREADY_MANAGED", diff --git a/public/app/api/utils.ts b/public/app/api/utils.ts index 0815c34d288..1ad0ff690e5 100644 --- a/public/app/api/utils.ts +++ b/public/app/api/utils.ts @@ -1,8 +1,8 @@ import { config, isFetchError } from '@grafana/runtime'; +import { ThunkDispatch } from 'app/types/store'; import { notifyApp } from '../core/actions'; import { createErrorNotification } from '../core/copy/appNotification'; -import { ThunkDispatch } from '../types'; export const getAPINamespace = () => config.namespace; diff --git a/public/app/core/actions/cleanUp.ts b/public/app/core/actions/cleanUp.ts index 4322612bda0..854b10ec5c3 100644 --- a/public/app/core/actions/cleanUp.ts +++ b/public/app/core/actions/cleanUp.ts @@ -1,6 +1,6 @@ import { createAction } from '@reduxjs/toolkit'; -import { StoreState } from '../../types'; +import { StoreState } from 'app/types/store'; export type CleanUpAction = (state: StoreState) => void; diff --git a/public/app/core/components/AccessControl/AddPermission.tsx b/public/app/core/components/AccessControl/AddPermission.tsx index c7569ff09f6..f49988dcc1a 100644 --- a/public/app/core/components/AccessControl/AddPermission.tsx +++ b/public/app/core/components/AccessControl/AddPermission.tsx @@ -1,12 +1,12 @@ import { useEffect, useMemo, useState } from 'react'; +import { OrgRole } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Button, Select, Stack } from '@grafana/ui'; import { CloseButton } from 'app/core/components/CloseButton/CloseButton'; import { ServiceAccountPicker } from 'app/core/components/Select/ServiceAccountPicker'; import { TeamPicker } from 'app/core/components/Select/TeamPicker'; import { UserPicker } from 'app/core/components/Select/UserPicker'; -import { OrgRole } from 'app/types/acl'; import { Assignments, PermissionTarget, SetPermission } from './types'; diff --git a/public/app/core/components/AccessControl/types.ts b/public/app/core/components/AccessControl/types.ts index c061bc77138..dcc69b58df4 100644 --- a/public/app/core/components/AccessControl/types.ts +++ b/public/app/core/components/AccessControl/types.ts @@ -1,4 +1,4 @@ -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; export type ResourcePermission = { id: number; diff --git a/public/app/core/components/AppChrome/AppChromeService.tsx b/public/app/core/components/AppChrome/AppChromeService.tsx index 8c91066066b..fc6c062b782 100644 --- a/public/app/core/components/AppChrome/AppChromeService.tsx +++ b/public/app/core/components/AppChrome/AppChromeService.tsx @@ -7,7 +7,7 @@ import { config, locationService, reportInteraction } from '@grafana/runtime'; import appEvents from 'app/core/app_events'; import store from 'app/core/store'; import { isShallowEqual } from 'app/core/utils/isShallowEqual'; -import { KioskMode } from 'app/types'; +import { KioskMode } from 'app/types/dashboard'; import { RouteDescriptor } from '../../navigation/types'; import { buildBreadcrumbs } from '../Breadcrumbs/utils'; diff --git a/public/app/core/components/AppChrome/MegaMenu/MegaMenu.tsx b/public/app/core/components/AppChrome/MegaMenu/MegaMenu.tsx index 9f85383b4d8..1c8b3959230 100644 --- a/public/app/core/components/AppChrome/MegaMenu/MegaMenu.tsx +++ b/public/app/core/components/AppChrome/MegaMenu/MegaMenu.tsx @@ -11,7 +11,7 @@ import { ScrollContainer, useStyles2 } from '@grafana/ui'; import { useGrafana } from 'app/core/context/GrafanaContext'; import { setBookmark } from 'app/core/reducers/navBarTree'; import { usePatchUserPreferencesMutation } from 'app/features/preferences/api/index'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { InviteUserButton } from '../../InviteUserButton/InviteUserButton'; import { shouldRenderInviteUserButton } from '../../InviteUserButton/utils'; diff --git a/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSelect.tsx b/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSelect.tsx index 2a33cf03123..e2e1d35a962 100644 --- a/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSelect.tsx +++ b/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSelect.tsx @@ -5,7 +5,7 @@ import { SelectableValue, GrafanaTheme2 } from '@grafana/data'; import { t } from '@grafana/i18n'; import { Icon, Select, useStyles2 } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; -import { UserOrg } from 'app/types'; +import { UserOrg } from 'app/types/user'; import { OrganizationBaseProps } from './types'; diff --git a/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSwitcher.test.tsx b/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSwitcher.test.tsx index d7897786e3e..79b9ab19f02 100644 --- a/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSwitcher.test.tsx +++ b/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSwitcher.test.tsx @@ -4,7 +4,7 @@ import { TestProvider } from 'test/helpers/TestProvider'; import { OrgRole } from '@grafana/data'; import { ContextSrv, setContextSrv } from 'app/core/services/context_srv'; import { getUserOrganizations } from 'app/features/org/state/actions'; -import * as appTypes from 'app/types'; +import { StoreState } from 'app/types/store'; import { OrganizationSwitcher } from './OrganizationSwitcher'; @@ -14,12 +14,12 @@ jest.mock('app/features/org/state/actions', () => ({ setUserOrganization: jest.fn(), })); -jest.mock('app/types', () => ({ - ...jest.requireActual('app/types'), +jest.mock('app/types/store', () => ({ + ...jest.requireActual('app/types/store'), useDispatch: () => jest.fn(), })); -const renderWithProvider = ({ initialState }: { initialState?: Partial }) => { +const renderWithProvider = ({ initialState }: { initialState?: Partial }) => { render( diff --git a/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSwitcher.tsx b/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSwitcher.tsx index 4138e69733b..67ad47cded0 100644 --- a/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSwitcher.tsx +++ b/public/app/core/components/AppChrome/OrganizationSwitcher/OrganizationSwitcher.tsx @@ -5,7 +5,8 @@ import { locationService } from '@grafana/runtime'; import { Space, Text } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; import { getUserOrganizations, setUserOrganization } from 'app/features/org/state/actions'; -import { useDispatch, useSelector, UserOrg } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; +import { UserOrg } from 'app/types/user'; import { Branding } from '../../Branding/Branding'; diff --git a/public/app/core/components/AppChrome/OrganizationSwitcher/types.ts b/public/app/core/components/AppChrome/OrganizationSwitcher/types.ts index 3b2afef009b..0687bf2ca6c 100644 --- a/public/app/core/components/AppChrome/OrganizationSwitcher/types.ts +++ b/public/app/core/components/AppChrome/OrganizationSwitcher/types.ts @@ -1,5 +1,5 @@ import { SelectableValue } from '@grafana/data'; -import { UserOrg } from 'app/types'; +import { UserOrg } from 'app/types/user'; export interface OrganizationBaseProps { orgs: UserOrg[]; diff --git a/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx b/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx index a528a0c8341..0a9a48ac6ed 100644 --- a/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx +++ b/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx @@ -4,7 +4,7 @@ import { t } from '@grafana/i18n'; import { reportInteraction } from '@grafana/runtime'; import { Menu, Dropdown, ToolbarButton } from '@grafana/ui'; import { getExternalUserMngLinkUrl } from 'app/features/users/utils'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { performInviteUserClick, shouldRenderInviteUserButton } from '../../InviteUserButton/utils'; import { NavToolbarSeparator } from '../NavToolbar/NavToolbarSeparator'; diff --git a/public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx b/public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx index 0f26fdeeba1..6766d757b49 100644 --- a/public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx +++ b/public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx @@ -13,7 +13,7 @@ import { useGrafana } from 'app/core/context/GrafanaContext'; import { contextSrv } from 'app/core/core'; import { useMediaQueryMinWidth } from 'app/core/hooks/useMediaQueryMinWidth'; import { HOME_NAV_ID } from 'app/core/reducers/navModel'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { Branding } from '../../Branding/Branding'; import { Breadcrumbs } from '../../Breadcrumbs/Breadcrumbs'; diff --git a/public/app/core/components/AppNotifications/AppNotificationItem.tsx b/public/app/core/components/AppNotifications/AppNotificationItem.tsx index 2d3ad8ea0f7..13575340b6a 100644 --- a/public/app/core/components/AppNotifications/AppNotificationItem.tsx +++ b/public/app/core/components/AppNotifications/AppNotificationItem.tsx @@ -4,7 +4,7 @@ import { useEffectOnce } from 'react-use'; import { GrafanaTheme2 } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { Alert, useStyles2 } from '@grafana/ui'; -import { AppNotification, timeoutMap } from 'app/types'; +import { AppNotification, timeoutMap } from 'app/types/appNotifications'; interface Props { appNotification: AppNotification; diff --git a/public/app/core/components/AppNotifications/AppNotificationList.tsx b/public/app/core/components/AppNotifications/AppNotificationList.tsx index edb686f0d55..bb473dd0905 100644 --- a/public/app/core/components/AppNotifications/AppNotificationList.tsx +++ b/public/app/core/components/AppNotifications/AppNotificationList.tsx @@ -6,7 +6,7 @@ import { useStyles2, Stack } from '@grafana/ui'; import { notifyApp, hideAppNotification } from 'app/core/actions'; import appEvents from 'app/core/app_events'; import { selectVisible } from 'app/core/reducers/appNotification'; -import { useSelector, useDispatch } from 'app/types'; +import { useSelector, useDispatch } from 'app/types/store'; import { createErrorNotification, diff --git a/public/app/core/components/FolderFilter/FolderFilter.tsx b/public/app/core/components/FolderFilter/FolderFilter.tsx index b427eed4569..2d310a6609b 100644 --- a/public/app/core/components/FolderFilter/FolderFilter.tsx +++ b/public/app/core/components/FolderFilter/FolderFilter.tsx @@ -9,7 +9,8 @@ import { config } from 'app/core/config'; import { getBackendSrv } from 'app/core/services/backend_srv'; import { getGrafanaSearcher } from 'app/features/search/service/searcher'; import { DashboardSearchItemType } from 'app/features/search/types'; -import { FolderInfo, PermissionLevelString } from 'app/types'; +import { PermissionLevelString } from 'app/types/acl'; +import { FolderInfo } from 'app/types/folders'; export interface FolderFilterProps { onChange: (folder: FolderInfo[]) => void; diff --git a/public/app/core/components/InviteUserButton/utils.ts b/public/app/core/components/InviteUserButton/utils.ts index 708e5ff88d5..6fb774a059b 100644 --- a/public/app/core/components/InviteUserButton/utils.ts +++ b/public/app/core/components/InviteUserButton/utils.ts @@ -2,7 +2,7 @@ import { reportInteraction } from '@grafana/runtime'; import { config } from 'app/core/config'; import { contextSrv } from 'app/core/services/context_srv'; import { getExternalUserMngLinkUrl } from 'app/features/users/utils'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; export const shouldRenderInviteUserButton = config.featureToggles.inviteUserExperimental && diff --git a/public/app/core/components/NestedFolderPicker/FolderRepo.tsx b/public/app/core/components/NestedFolderPicker/FolderRepo.tsx index 02f2f108e30..e149f84c75d 100644 --- a/public/app/core/components/NestedFolderPicker/FolderRepo.tsx +++ b/public/app/core/components/NestedFolderPicker/FolderRepo.tsx @@ -2,7 +2,7 @@ import { t } from '@grafana/i18n'; import { Badge } from '@grafana/ui'; import { useIsProvisionedInstance } from 'app/features/provisioning/hooks/useIsProvisionedInstance'; import { NestedFolderDTO } from 'app/features/search/service/types'; -import { FolderDTO, FolderListItemDTO } from 'app/types'; +import { FolderDTO, FolderListItemDTO } from 'app/types/folders'; export interface Props { folder?: FolderListItemDTO | NestedFolderDTO | FolderDTO; diff --git a/public/app/core/components/NestedFolderPicker/NestedFolderList.tsx b/public/app/core/components/NestedFolderPicker/NestedFolderList.tsx index 4a322b6ee27..46ef137c53f 100644 --- a/public/app/core/components/NestedFolderPicker/NestedFolderList.tsx +++ b/public/app/core/components/NestedFolderPicker/NestedFolderList.tsx @@ -12,7 +12,7 @@ import { Indent } from 'app/core/components/Indent/Indent'; import { childrenByParentUIDSelector, rootItemsSelector } from 'app/features/browse-dashboards/state/hooks'; import { DashboardsTreeItem } from 'app/features/browse-dashboards/types'; import { DashboardViewItem } from 'app/features/search/types'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { FolderRepo } from './FolderRepo'; diff --git a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx index 28305640a2a..38d241c61e2 100644 --- a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx +++ b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx @@ -15,7 +15,7 @@ import { getGrafanaSearcher } from 'app/features/search/service/searcher'; import { QueryResponse } from 'app/features/search/service/types'; import { queryResultToViewItem } from 'app/features/search/service/utils'; import { DashboardViewItem } from 'app/features/search/types'; -import { PermissionLevelString } from 'app/types'; +import { PermissionLevelString } from 'app/types/acl'; import { FolderRepo } from './FolderRepo'; import { getDOMId, NestedFolderList } from './NestedFolderList'; diff --git a/public/app/core/components/NestedFolderPicker/useFoldersQuery.ts b/public/app/core/components/NestedFolderPicker/useFoldersQuery.ts index bd3b6ba9098..6fe4c0ef440 100644 --- a/public/app/core/components/NestedFolderPicker/useFoldersQuery.ts +++ b/public/app/core/components/NestedFolderPicker/useFoldersQuery.ts @@ -1,6 +1,5 @@ import { config } from '@grafana/runtime'; - -import { PermissionLevelString } from '../../../types'; +import { PermissionLevelString } from 'app/types/acl'; import { useFoldersQueryAppPlatform } from './useFoldersQueryAppPlatform'; import { useFoldersQueryLegacy } from './useFoldersQueryLegacy'; diff --git a/public/app/core/components/NestedFolderPicker/useFoldersQueryLegacy.ts b/public/app/core/components/NestedFolderPicker/useFoldersQueryLegacy.ts index 6b1286895bd..8381c61d1f2 100644 --- a/public/app/core/components/NestedFolderPicker/useFoldersQueryLegacy.ts +++ b/public/app/core/components/NestedFolderPicker/useFoldersQueryLegacy.ts @@ -7,7 +7,8 @@ import { ListFolderQueryArgs, browseDashboardsAPI } from 'app/features/browse-da import { PAGE_SIZE } from 'app/features/browse-dashboards/api/services'; import { getPaginationPlaceholders } from 'app/features/browse-dashboards/state/utils'; import { DashboardViewItemWithUIItems, DashboardsTreeItem } from 'app/features/browse-dashboards/types'; -import { FolderListItemDTO, PermissionLevelString } from 'app/types'; +import { PermissionLevelString } from 'app/types/acl'; +import { FolderListItemDTO } from 'app/types/folders'; import { useDispatch, useSelector } from 'app/types/store'; import { ROOT_FOLDER_ITEM } from './utils'; diff --git a/public/app/core/components/Page/usePageNav.ts b/public/app/core/components/Page/usePageNav.ts index da6bd0da218..66899e442da 100644 --- a/public/app/core/components/Page/usePageNav.ts +++ b/public/app/core/components/Page/usePageNav.ts @@ -3,7 +3,7 @@ import { createSelector } from 'reselect'; import { NavModel } from '@grafana/data'; import { getNavModel } from 'app/core/selectors/navModel'; import { store } from 'app/store/store'; -import { StoreState, useSelector } from 'app/types'; +import { StoreState, useSelector } from 'app/types/store'; export function usePageNav(navId?: string, oldProp?: NavModel): NavModel | undefined { if (oldProp) { diff --git a/public/app/core/components/Page/usePageTitle.ts b/public/app/core/components/Page/usePageTitle.ts index c2e53b23251..4c338a77ef0 100644 --- a/public/app/core/components/Page/usePageTitle.ts +++ b/public/app/core/components/Page/usePageTitle.ts @@ -2,7 +2,7 @@ import { useEffect } from 'react'; import { NavModel, NavModelItem } from '@grafana/data'; import { HOME_NAV_ID } from 'app/core/reducers/navModel'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { Branding } from '../Branding/Branding'; import { buildBreadcrumbs } from '../Breadcrumbs/utils'; diff --git a/public/app/core/components/RolePicker/BuiltinRoleSelector.tsx b/public/app/core/components/RolePicker/BuiltinRoleSelector.tsx index c0fa457d8c2..70e18b2a9c8 100644 --- a/public/app/core/components/RolePicker/BuiltinRoleSelector.tsx +++ b/public/app/core/components/RolePicker/BuiltinRoleSelector.tsx @@ -1,8 +1,7 @@ -import { SelectableValue } from '@grafana/data'; +import { OrgRole, SelectableValue } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { Icon, RadioButtonList, Tooltip, useStyles2, useTheme2, PopoverContent } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { OrgRole } from 'app/types'; import { getStyles } from './styles'; diff --git a/public/app/core/components/RolePicker/RoleMenuGroupsSection.tsx b/public/app/core/components/RolePicker/RoleMenuGroupsSection.tsx index 79e44be57e6..b4b3e30d738 100644 --- a/public/app/core/components/RolePicker/RoleMenuGroupsSection.tsx +++ b/public/app/core/components/RolePicker/RoleMenuGroupsSection.tsx @@ -1,7 +1,7 @@ import { forwardRef, useCallback, useState } from 'react'; import { useStyles2, getSelectStyles, useTheme2 } from '@grafana/ui'; -import { Role } from 'app/types'; +import { Role } from 'app/types/accessControl'; import { RoleMenuGroupOption } from './RoleMenuGroupOption'; import { RoleMenuOption } from './RoleMenuOption'; diff --git a/public/app/core/components/RolePicker/RoleMenuOption.tsx b/public/app/core/components/RolePicker/RoleMenuOption.tsx index 7700b00bdae..6e020ad6018 100644 --- a/public/app/core/components/RolePicker/RoleMenuOption.tsx +++ b/public/app/core/components/RolePicker/RoleMenuOption.tsx @@ -4,7 +4,7 @@ import { forwardRef, FormEvent } from 'react'; import { t } from '@grafana/i18n'; import { Checkbox, Icon, Tooltip, useStyles2, useTheme2 } from '@grafana/ui'; import { getSelectStyles } from '@grafana/ui/internal'; -import { Role } from 'app/types'; +import { Role } from 'app/types/accessControl'; import { getStyles } from './styles'; diff --git a/public/app/core/components/RolePicker/RolePicker.tsx b/public/app/core/components/RolePicker/RolePicker.tsx index 6cbf2e0450d..25cff0889a1 100644 --- a/public/app/core/components/RolePicker/RolePicker.tsx +++ b/public/app/core/components/RolePicker/RolePicker.tsx @@ -1,7 +1,8 @@ import { FormEvent, useCallback, useEffect, useState, useRef } from 'react'; +import { OrgRole } from '@grafana/data'; import { ClickOutsideWrapper, Portal, useTheme2 } from '@grafana/ui'; -import { Role, OrgRole } from 'app/types'; +import { Role } from 'app/types/accessControl'; import { RolePickerInput } from './RolePickerInput'; import { RolePickerMenu } from './RolePickerMenu'; diff --git a/public/app/core/components/RolePicker/RolePickerInput.tsx b/public/app/core/components/RolePicker/RolePickerInput.tsx index 9acb2630745..9aaa4b447f5 100644 --- a/public/app/core/components/RolePicker/RolePickerInput.tsx +++ b/public/app/core/components/RolePicker/RolePickerInput.tsx @@ -6,8 +6,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { useStyles2, getInputStyles, sharedInputStyle, Tooltip, Icon, Spinner } from '@grafana/ui'; import { getFocusStyles } from '@grafana/ui/internal'; - -import { Role } from '../../../types'; +import { Role } from 'app/types/accessControl'; import { ValueContainer } from './ValueContainer'; import { ROLE_PICKER_WIDTH } from './constants'; diff --git a/public/app/core/components/RolePicker/RolePickerMenu.tsx b/public/app/core/components/RolePicker/RolePickerMenu.tsx index 23cf52de471..81c38519ae6 100644 --- a/public/app/core/components/RolePicker/RolePickerMenu.tsx +++ b/public/app/core/components/RolePicker/RolePickerMenu.tsx @@ -1,10 +1,11 @@ import { css, cx } from '@emotion/css'; import { useEffect, useRef, useState } from 'react'; +import { OrgRole } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Button, ScrollContainer, Stack, TextLink, useStyles2, useTheme2 } from '@grafana/ui'; import { getSelectStyles } from '@grafana/ui/internal'; -import { OrgRole, Role } from 'app/types'; +import { Role } from 'app/types/accessControl'; import { BuiltinRoleSelector } from './BuiltinRoleSelector'; import { RoleMenuGroupsSection } from './RoleMenuGroupsSection'; diff --git a/public/app/core/components/RolePicker/RolePickerSubMenu.tsx b/public/app/core/components/RolePicker/RolePickerSubMenu.tsx index fdcd22224b9..3dff3fc88be 100644 --- a/public/app/core/components/RolePicker/RolePickerSubMenu.tsx +++ b/public/app/core/components/RolePicker/RolePickerSubMenu.tsx @@ -3,7 +3,7 @@ import { cx } from '@emotion/css'; import { Trans, t } from '@grafana/i18n'; import { Button, ScrollContainer, Stack, useStyles2, useTheme2 } from '@grafana/ui'; import { getSelectStyles } from '@grafana/ui/internal'; -import { Role } from 'app/types'; +import { Role } from 'app/types/accessControl'; import { RoleMenuOption } from './RoleMenuOption'; import { MENU_MAX_HEIGHT } from './constants'; diff --git a/public/app/core/components/RolePicker/TeamRolePicker.tsx b/public/app/core/components/RolePicker/TeamRolePicker.tsx index 83552236334..78e3b0f2c82 100644 --- a/public/app/core/components/RolePicker/TeamRolePicker.tsx +++ b/public/app/core/components/RolePicker/TeamRolePicker.tsx @@ -2,7 +2,7 @@ import { useEffect } from 'react'; import { useAsyncFn } from 'react-use'; import { contextSrv } from 'app/core/core'; -import { Role, AccessControlAction } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; import { RolePicker } from './RolePicker'; import { fetchTeamRoles, updateTeamRoles } from './api'; diff --git a/public/app/core/components/RolePicker/UserRolePicker.tsx b/public/app/core/components/RolePicker/UserRolePicker.tsx index 5fa3c94286f..a4232f4b61a 100644 --- a/public/app/core/components/RolePicker/UserRolePicker.tsx +++ b/public/app/core/components/RolePicker/UserRolePicker.tsx @@ -1,8 +1,9 @@ import { useEffect } from 'react'; import { useAsyncFn } from 'react-use'; +import { OrgRole } from '@grafana/data'; import { contextSrv } from 'app/core/core'; -import { Role, OrgRole, AccessControlAction } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; import { RolePicker } from './RolePicker'; import { fetchUserRoles, updateUserRoles } from './api'; diff --git a/public/app/core/components/RolePicker/api.ts b/public/app/core/components/RolePicker/api.ts index 00e1926eea5..596463b4a9d 100644 --- a/public/app/core/components/RolePicker/api.ts +++ b/public/app/core/components/RolePicker/api.ts @@ -1,5 +1,5 @@ import { getBackendSrv, isFetchError } from '@grafana/runtime'; -import { Role } from 'app/types'; +import { Role } from 'app/types/accessControl'; import { addDisplayNameForFixedRole, addFilteredDisplayName } from './utils'; diff --git a/public/app/core/components/RolePicker/hooks.ts b/public/app/core/components/RolePicker/hooks.ts index 071f31eddaa..0b66a36c94f 100644 --- a/public/app/core/components/RolePicker/hooks.ts +++ b/public/app/core/components/RolePicker/hooks.ts @@ -4,7 +4,7 @@ import { useDeepCompareEffect } from 'react-use'; import useAsync from 'react-use/lib/useAsync'; import { contextSrv } from 'app/core/core'; -import { Role, AccessControlAction } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; import { fetchRoleOptions } from './api'; diff --git a/public/app/core/components/RolePicker/utils.ts b/public/app/core/components/RolePicker/utils.ts index ed1021f2d8c..413671f0090 100644 --- a/public/app/core/components/RolePicker/utils.ts +++ b/public/app/core/components/RolePicker/utils.ts @@ -1,4 +1,4 @@ -import { Role } from 'app/types'; +import { Role } from 'app/types/accessControl'; export const isNotDelegatable = (role: Role) => { return role.delegatable !== undefined && !role.delegatable; diff --git a/public/app/core/components/RolePickerDrawer/RolePickerBadges.tsx b/public/app/core/components/RolePickerDrawer/RolePickerBadges.tsx index 57789ebb518..522f752b9a6 100644 --- a/public/app/core/components/RolePickerDrawer/RolePickerBadges.tsx +++ b/public/app/core/components/RolePickerDrawer/RolePickerBadges.tsx @@ -5,7 +5,7 @@ import { FormProvider, useForm } from 'react-hook-form'; import { GrafanaTheme2 } from '@grafana/data'; import { t } from '@grafana/i18n'; import { useStyles2, Badge, Stack } from '@grafana/ui'; -import { OrgUser } from 'app/types'; +import { OrgUser } from 'app/types/user'; import { RolePickerDrawer } from './RolePickerDrawer'; diff --git a/public/app/core/components/RolePickerDrawer/RolePickerDrawer.tsx b/public/app/core/components/RolePickerDrawer/RolePickerDrawer.tsx index 9b327449519..75afc684eab 100644 --- a/public/app/core/components/RolePickerDrawer/RolePickerDrawer.tsx +++ b/public/app/core/components/RolePickerDrawer/RolePickerDrawer.tsx @@ -1,9 +1,8 @@ import { Controller, useFormContext } from 'react-hook-form'; -import { toOption } from '@grafana/data'; +import { OrgRole, toOption } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Drawer, Field, RadioButtonGroup, TextLink } from '@grafana/ui'; -import { OrgRole } from 'app/types'; const roleOptions = Object.keys(OrgRole).map(toOption); diff --git a/public/app/core/components/Select/DashboardPicker.test.tsx b/public/app/core/components/Select/DashboardPicker.test.tsx index 2f662fe586b..b46c1f9d2df 100644 --- a/public/app/core/components/Select/DashboardPicker.test.tsx +++ b/public/app/core/components/Select/DashboardPicker.test.tsx @@ -10,7 +10,7 @@ import { import { backendSrv } from 'app/core/services/backend_srv'; import { DashboardWithAccessInfo } from 'app/features/dashboard/api/types'; import { DashboardSearchItemType } from 'app/features/search/types'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; import { DashboardPicker } from './DashboardPicker'; diff --git a/public/app/core/components/Select/DashboardPicker.tsx b/public/app/core/components/Select/DashboardPicker.tsx index dfbb2458ade..bfb965a73bd 100644 --- a/public/app/core/components/Select/DashboardPicker.tsx +++ b/public/app/core/components/Select/DashboardPicker.tsx @@ -8,7 +8,7 @@ import { AnnoKeyFolder, AnnoKeyFolderTitle } from 'app/features/apiserver/types' import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; import { isDashboardV2Resource } from 'app/features/dashboard/api/utils'; import { DashboardSearchItem } from 'app/features/search/types'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; interface Props extends Omit, 'value' | 'onChange' | 'loadOptions' | ''> { value?: DashboardPickerDTO['uid']; diff --git a/public/app/core/components/Select/OldFolderPicker.tsx b/public/app/core/components/Select/OldFolderPicker.tsx index e5e684b7713..13ddca85986 100644 --- a/public/app/core/components/Select/OldFolderPicker.tsx +++ b/public/app/core/components/Select/OldFolderPicker.tsx @@ -13,7 +13,8 @@ import appEvents from 'app/core/app_events'; import { contextSrv } from 'app/core/services/context_srv'; import { createFolder, getFolderByUid, searchFolders } from 'app/features/manage-dashboards/state/actions'; import { DashboardSearchHit } from 'app/features/search/types'; -import { AccessControlAction, PermissionLevelString, SearchQueryType } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { PermissionLevelString, SearchQueryType } from 'app/types/acl'; export type FolderPickerFilter = (hits: DashboardSearchHit[]) => DashboardSearchHit[]; diff --git a/public/app/core/components/Select/OrgPicker.tsx b/public/app/core/components/Select/OrgPicker.tsx index bc064c83d98..81ed7132d02 100644 --- a/public/app/core/components/Select/OrgPicker.tsx +++ b/public/app/core/components/Select/OrgPicker.tsx @@ -5,7 +5,8 @@ import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { getBackendSrv } from '@grafana/runtime'; import { AsyncSelect } from '@grafana/ui'; -import { Organization, UserOrg } from 'app/types'; +import { Organization } from 'app/types/organization'; +import { UserOrg } from 'app/types/user'; export type OrgSelectItem = SelectableValue; diff --git a/public/app/core/components/Select/ServiceAccountPicker.tsx b/public/app/core/components/Select/ServiceAccountPicker.tsx index b86a451dea1..037404dcb2b 100644 --- a/public/app/core/components/Select/ServiceAccountPicker.tsx +++ b/public/app/core/components/Select/ServiceAccountPicker.tsx @@ -6,7 +6,7 @@ import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { getBackendSrv } from '@grafana/runtime'; import { AsyncSelect } from '@grafana/ui'; -import { ServiceAccountDTO, ServiceAccountsState } from 'app/types'; +import { ServiceAccountDTO, ServiceAccountsState } from 'app/types/serviceaccount'; export interface Props { onSelected: (user: SelectableValue) => void; diff --git a/public/app/core/components/Select/TeamPicker.tsx b/public/app/core/components/Select/TeamPicker.tsx index b3608b80105..3f374fc8930 100644 --- a/public/app/core/components/Select/TeamPicker.tsx +++ b/public/app/core/components/Select/TeamPicker.tsx @@ -6,7 +6,7 @@ import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { getBackendSrv } from '@grafana/runtime'; import { AsyncSelect } from '@grafana/ui'; -import { Team } from 'app/types'; +import { Team } from 'app/types/teams'; export interface Props { onSelected: (team: SelectableValue) => void; diff --git a/public/app/core/components/Select/UserPicker.tsx b/public/app/core/components/Select/UserPicker.tsx index 0b1b5cb129f..5284cbeca5f 100644 --- a/public/app/core/components/Select/UserPicker.tsx +++ b/public/app/core/components/Select/UserPicker.tsx @@ -6,7 +6,7 @@ import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { getBackendSrv } from '@grafana/runtime'; import { AsyncSelect } from '@grafana/ui'; -import { OrgUser } from 'app/types'; +import { OrgUser } from 'app/types/user'; export interface Props { onSelected: (user: SelectableValue) => void; diff --git a/public/app/core/copy/appNotification.ts b/public/app/core/copy/appNotification.ts index 9f2fff8641f..3f1dd8f484f 100644 --- a/public/app/core/copy/appNotification.ts +++ b/public/app/core/copy/appNotification.ts @@ -3,7 +3,8 @@ import { v4 as uuidv4 } from 'uuid'; import { getMessageFromError } from 'app/core/utils/errors'; import { dispatch as storeDispatch } from 'app/store/store'; -import { AppNotification, AppNotificationSeverity, useDispatch } from 'app/types'; +import { AppNotificationSeverity, AppNotification } from 'app/types/appNotifications'; +import { useDispatch } from 'app/types/store'; import { notifyApp } from '../actions'; diff --git a/public/app/core/history/RichHistoryLocalStorage.test.ts b/public/app/core/history/RichHistoryLocalStorage.test.ts index 8899a7cc509..8cf739514e2 100644 --- a/public/app/core/history/RichHistoryLocalStorage.test.ts +++ b/public/app/core/history/RichHistoryLocalStorage.test.ts @@ -1,8 +1,8 @@ import { DataQuery } from '@grafana/data'; import store from 'app/core/store'; +import { RichHistoryQuery } from 'app/types/explore'; import { DatasourceSrv } from '../../features/plugins/datasource_srv'; -import { RichHistoryQuery } from '../../types'; import { backendSrv } from '../services/backend_srv'; import { RichHistorySearchFilters, RichHistorySettings, SortOrder } from '../utils/richHistoryTypes'; diff --git a/public/app/core/history/RichHistoryLocalStorage.ts b/public/app/core/history/RichHistoryLocalStorage.ts index 4396b73a1fa..165c2f06eac 100644 --- a/public/app/core/history/RichHistoryLocalStorage.ts +++ b/public/app/core/history/RichHistoryLocalStorage.ts @@ -2,8 +2,8 @@ import { find, isEqual, omit } from 'lodash'; import { DataQuery, SelectableValue } from '@grafana/data'; import { RichHistorySearchFilters, RichHistorySettings } from 'app/core/utils/richHistory'; +import { RichHistoryQuery } from 'app/types/explore'; -import { RichHistoryQuery } from '../../types'; import store from '../store'; import RichHistoryStorage, { RichHistoryServiceError, RichHistoryStorageWarning } from './RichHistoryStorage'; diff --git a/public/app/core/history/RichHistoryRemoteStorage.test.ts b/public/app/core/history/RichHistoryRemoteStorage.test.ts index 766712d1c0a..b99967b09b7 100644 --- a/public/app/core/history/RichHistoryRemoteStorage.test.ts +++ b/public/app/core/history/RichHistoryRemoteStorage.test.ts @@ -1,9 +1,9 @@ import { of } from 'rxjs'; import { Preferences as UserPreferencesDTO } from '@grafana/schema/src/raw/preferences/x/preferences_types.gen'; +import { RichHistoryQuery } from 'app/types/explore'; import { DatasourceSrv } from '../../features/plugins/datasource_srv'; -import { RichHistoryQuery } from '../../types'; import { SortOrder } from '../utils/richHistoryTypes'; import RichHistoryRemoteStorage, { RichHistoryRemoteStorageDTO } from './RichHistoryRemoteStorage'; @@ -45,7 +45,7 @@ jest.mock('../services/PreferencesService', () => ({ })); // FIXME: Tests break unless plugin loader is mocked. This is likely due to a circular dependency -jest.mock('app/features/plugins/plugin_loader', () => ({})); +jest.mock('app/features/plugins/pluginLoader', () => ({})); describe('RichHistoryRemoteStorage', () => { let storage: RichHistoryRemoteStorage; diff --git a/public/app/core/history/RichHistoryStorage.ts b/public/app/core/history/RichHistoryStorage.ts index 13d89a05172..158a5e7d6cb 100644 --- a/public/app/core/history/RichHistoryStorage.ts +++ b/public/app/core/history/RichHistoryStorage.ts @@ -1,6 +1,5 @@ import { RichHistorySearchBackendFilters, RichHistorySettings } from 'app/core/utils/richHistoryTypes'; - -import { RichHistoryQuery } from '../../types'; +import { RichHistoryQuery } from 'app/types/explore'; /** * Errors are used when the operation on Rich History was not successful. diff --git a/public/app/core/history/localStorageConverter.test.ts b/public/app/core/history/localStorageConverter.test.ts index 20b8701a258..ffefb2ce8d4 100644 --- a/public/app/core/history/localStorageConverter.test.ts +++ b/public/app/core/history/localStorageConverter.test.ts @@ -1,6 +1,6 @@ import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; +import { RichHistoryQuery } from 'app/types/explore'; -import { RichHistoryQuery } from '../../types'; import { backendSrv } from '../services/backend_srv'; import { RichHistoryLocalStorageDTO } from './RichHistoryLocalStorage'; diff --git a/public/app/core/history/localStorageConverter.ts b/public/app/core/history/localStorageConverter.ts index 62be110bcdd..485ebf3a1a3 100644 --- a/public/app/core/history/localStorageConverter.ts +++ b/public/app/core/history/localStorageConverter.ts @@ -1,6 +1,5 @@ import { getDataSourceSrv } from '@grafana/runtime'; - -import { RichHistoryQuery } from '../../types'; +import { RichHistoryQuery } from 'app/types/explore'; import { RichHistoryLocalStorageDTO } from './RichHistoryLocalStorage'; diff --git a/public/app/core/history/remoteStorageConverter.test.ts b/public/app/core/history/remoteStorageConverter.test.ts index 6e42cc507ac..dd8f927ec66 100644 --- a/public/app/core/history/remoteStorageConverter.test.ts +++ b/public/app/core/history/remoteStorageConverter.test.ts @@ -1,5 +1,6 @@ +import { RichHistoryQuery } from 'app/types/explore'; + import { DatasourceSrv } from '../../features/plugins/datasource_srv'; -import { RichHistoryQuery } from '../../types'; import { backendSrv } from '../services/backend_srv'; import { RichHistoryRemoteStorageDTO } from './RichHistoryRemoteStorage'; diff --git a/public/app/core/history/remoteStorageConverter.ts b/public/app/core/history/remoteStorageConverter.ts index 6a743016e64..a4d15a677c3 100644 --- a/public/app/core/history/remoteStorageConverter.ts +++ b/public/app/core/history/remoteStorageConverter.ts @@ -1,6 +1,5 @@ import { getDataSourceSrv } from '@grafana/runtime'; - -import { RichHistoryQuery } from '../../types'; +import { RichHistoryQuery } from 'app/types/explore'; import { RichHistoryRemoteStorageDTO } from './RichHistoryRemoteStorage'; diff --git a/public/app/core/history/richHistoryLocalStorageUtils.test.ts b/public/app/core/history/richHistoryLocalStorageUtils.test.ts index 7687f3f1bb5..29a4b7d79d2 100644 --- a/public/app/core/history/richHistoryLocalStorageUtils.test.ts +++ b/public/app/core/history/richHistoryLocalStorageUtils.test.ts @@ -1,7 +1,6 @@ import { DataQuery } from '@grafana/data'; import { SortOrder } from 'app/core/utils/richHistory'; - -import { RichHistoryQuery } from '../../types'; +import { RichHistoryQuery } from 'app/types/explore'; import { filterAndSortQueries } from './richHistoryLocalStorageUtils'; diff --git a/public/app/core/history/richHistoryLocalStorageUtils.ts b/public/app/core/history/richHistoryLocalStorageUtils.ts index d22b4816781..caefdd7f45d 100644 --- a/public/app/core/history/richHistoryLocalStorageUtils.ts +++ b/public/app/core/history/richHistoryLocalStorageUtils.ts @@ -1,8 +1,8 @@ import { omit } from 'lodash'; import { DateTime, dateTime, dateTimeForTimeZone } from '@grafana/data'; +import { RichHistoryQuery } from 'app/types/explore'; -import { RichHistoryQuery } from '../../types'; import { SortOrder } from '../utils/richHistoryTypes'; /** diff --git a/public/app/core/hooks/useCleanup.ts b/public/app/core/hooks/useCleanup.ts index 86696b829d2..6cec29424d1 100644 --- a/public/app/core/hooks/useCleanup.ts +++ b/public/app/core/hooks/useCleanup.ts @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { cleanUpAction, CleanUpAction } from '../actions/cleanUp'; diff --git a/public/app/core/hooks/useNavModel.ts b/public/app/core/hooks/useNavModel.ts index 047654109cc..a872f1a59f1 100644 --- a/public/app/core/hooks/useNavModel.ts +++ b/public/app/core/hooks/useNavModel.ts @@ -1,5 +1,5 @@ import { NavModel } from '@grafana/data'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { getNavModel } from '../selectors/navModel'; diff --git a/public/app/core/navigation/kiosk.ts b/public/app/core/navigation/kiosk.ts index 36c66c7eeeb..0e7ddfb3f3c 100644 --- a/public/app/core/navigation/kiosk.ts +++ b/public/app/core/navigation/kiosk.ts @@ -1,6 +1,5 @@ import { UrlQueryMap } from '@grafana/data'; - -import { KioskMode } from '../../types'; +import { KioskMode } from 'app/types/dashboard'; // TODO Remove after topnav feature toggle is permanent and old NavBar is removed export function getKioskMode(queryParams: UrlQueryMap): KioskMode | null { diff --git a/public/app/core/reducers/appNotification.test.ts b/public/app/core/reducers/appNotification.test.ts index 6094e1ac7bc..f9bb79baab0 100644 --- a/public/app/core/reducers/appNotification.test.ts +++ b/public/app/core/reducers/appNotification.test.ts @@ -1,4 +1,4 @@ -import { AppNotificationSeverity, AppNotificationsState } from 'app/types/'; +import { AppNotificationSeverity, AppNotificationsState } from 'app/types/appNotifications'; import { appNotificationsReducer, clearNotification, notifyApp } from './appNotification'; diff --git a/public/app/core/reducers/appNotification.ts b/public/app/core/reducers/appNotification.ts index d9f563d364e..aedb2d0a0fc 100644 --- a/public/app/core/reducers/appNotification.ts +++ b/public/app/core/reducers/appNotification.ts @@ -1,6 +1,6 @@ import { createSelector, createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { AppNotification, AppNotificationSeverity, AppNotificationsState } from 'app/types/'; +import { AppNotification, AppNotificationSeverity, AppNotificationsState } from 'app/types/appNotifications'; const MAX_STORED_NOTIFICATIONS = 25; export const STORAGE_KEY = 'notifications'; diff --git a/public/app/core/reducers/root.test.ts b/public/app/core/reducers/root.test.ts index 6b584776233..c9f5d5068bf 100644 --- a/public/app/core/reducers/root.test.ts +++ b/public/app/core/reducers/root.test.ts @@ -1,6 +1,7 @@ +import { Team } from 'app/types/teams'; + import { reducerTester } from '../../../test/core/redux/reducerTester'; import { initialTeamsState, teamsLoaded } from '../../features/teams/state/reducers'; -import { Team } from '../../types'; import { StoreState } from '../../types/store'; import { cleanUpAction } from '../actions/cleanUp'; diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index ac0d13d1051..f518dc83df7 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -25,7 +25,8 @@ import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { DashboardSearchItem } from 'app/features/search/types'; import { TokenRevokedModal } from 'app/features/users/TokenRevokedModal'; -import { DashboardDTO, FolderDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; +import { FolderDTO } from 'app/types/folders'; import { ShowModalReactEvent } from '../../types/events'; import { isContentTypeJson, parseInitFromOptions, parseResponseBody, parseUrlFromOptions } from '../utils/fetch'; diff --git a/public/app/core/services/context_srv.ts b/public/app/core/services/context_srv.ts index 513b5a97699..8374d4b7bf1 100644 --- a/public/app/core/services/context_srv.ts +++ b/public/app/core/services/context_srv.ts @@ -11,7 +11,7 @@ import { } from '@grafana/data'; import { featureEnabled, getBackendSrv } from '@grafana/runtime'; import { getSessionExpiry } from 'app/core/utils/auth'; -import { AccessControlAction, UserPermission } from 'app/types'; +import { UserPermission, AccessControlAction } from 'app/types/accessControl'; import { CurrentUserInternal } from 'app/types/config'; import config from '../../core/config'; diff --git a/public/app/core/utils/richHistory.test.ts b/public/app/core/utils/richHistory.test.ts index 0c6a95b981d..0fba9ac1352 100644 --- a/public/app/core/utils/richHistory.test.ts +++ b/public/app/core/utils/richHistory.test.ts @@ -1,7 +1,7 @@ import { dateTime, DataQuery } from '@grafana/data'; import store from 'app/core/store'; +import { RichHistoryQuery } from 'app/types/explore'; -import { RichHistoryQuery } from '../../types'; import RichHistoryStorage, { RichHistoryStorageWarning } from '../history/RichHistoryStorage'; import { diff --git a/public/app/dev-utils.ts b/public/app/dev-utils.ts index 478af4f8f64..07a656735c1 100644 --- a/public/app/dev-utils.ts +++ b/public/app/dev-utils.ts @@ -3,7 +3,7 @@ import store from 'app/core/store'; import { sendAppNotification } from './core/copy/appNotification'; import { PreferencesService } from './core/services/PreferencesService'; -import { AppNotificationSeverity } from './types'; +import { AppNotificationSeverity } from './types/appNotifications'; export const STORAGE_MOCK_API_KEY = 'grafana.dev.mockApi'; diff --git a/public/app/features/admin/AdminEditOrgPage.tsx b/public/app/features/admin/AdminEditOrgPage.tsx index 34b0d477523..fb6039792dc 100644 --- a/public/app/features/admin/AdminEditOrgPage.tsx +++ b/public/app/features/admin/AdminEditOrgPage.tsx @@ -3,12 +3,13 @@ import { useForm } from 'react-hook-form'; import { useParams } from 'react-router-dom-v5-compat'; import { useAsyncFn } from 'react-use'; -import { NavModelItem } from '@grafana/data'; +import { NavModelItem, OrgRole } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Field, Input, Button, Legend, Alert } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; -import { OrgUser, AccessControlAction, OrgRole } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { OrgUser } from 'app/types/user'; import { OrgUsersTable } from './Users/OrgUsersTable'; import { getOrg, getOrgUsers, getUsersRoles, removeOrgUser, updateOrgName, updateOrgUserRole } from './api'; diff --git a/public/app/features/admin/AdminListOrgsPage.tsx b/public/app/features/admin/AdminListOrgsPage.tsx index be3ef8f2624..48da226edaf 100644 --- a/public/app/features/admin/AdminListOrgsPage.tsx +++ b/public/app/features/admin/AdminListOrgsPage.tsx @@ -6,7 +6,8 @@ import { getBackendSrv, isFetchError } from '@grafana/runtime'; import { LinkButton } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction, Organization } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { Organization } from 'app/types/organization'; import { AdminOrgsTable } from './AdminOrgsTable'; diff --git a/public/app/features/admin/AdminOrgsTable.tsx b/public/app/features/admin/AdminOrgsTable.tsx index 9feba68ae31..d85dcccfea5 100644 --- a/public/app/features/admin/AdminOrgsTable.tsx +++ b/public/app/features/admin/AdminOrgsTable.tsx @@ -7,7 +7,8 @@ import { Trans, t } from '@grafana/i18n'; import { Button, ConfirmModal, useStyles2 } from '@grafana/ui'; import { SkeletonComponent, attachSkeleton } from '@grafana/ui/unstable'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, Organization } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { Organization } from 'app/types/organization'; interface Props { orgs: Organization[]; diff --git a/public/app/features/admin/ServerStats.tsx b/public/app/features/admin/ServerStats.tsx index a7f62ec72c1..f3d8e4d0a66 100644 --- a/public/app/features/admin/ServerStats.tsx +++ b/public/app/features/admin/ServerStats.tsx @@ -5,7 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { config, GrafanaBootConfig } from '@grafana/runtime'; import { LinkButton, Stack, useStyles2 } from '@grafana/ui'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { contextSrv } from '../../core/services/context_srv'; diff --git a/public/app/features/admin/UpgradePage.tsx b/public/app/features/admin/UpgradePage.tsx index 3a8b8ed7f02..61925407cbd 100644 --- a/public/app/features/admin/UpgradePage.tsx +++ b/public/app/features/admin/UpgradePage.tsx @@ -6,6 +6,7 @@ import { GrafanaTheme2, NavModel } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { LinkButton, useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; +import { StoreState } from 'app/types/store'; import checkmarkSvg from 'img/licensing/checkmark.svg'; import customerSupportSvg from 'img/licensing/customer_support.svg'; import handinhandSupportSvg from 'img/licensing/handinhand_support.svg'; @@ -13,7 +14,6 @@ import pluginEnterpriseSvg from 'img/licensing/plugin_enterprise.svg'; import slaSvg from 'img/licensing/sla.svg'; import { getNavModel } from '../../core/selectors/navModel'; -import { StoreState } from '../../types'; import { LicenseChrome } from './LicenseChrome'; import { ServerStats } from './ServerStats'; diff --git a/public/app/features/admin/UserAdminPage.tsx b/public/app/features/admin/UserAdminPage.tsx index 8a2f2c84aa8..1642c3259e8 100644 --- a/public/app/features/admin/UserAdminPage.tsx +++ b/public/app/features/admin/UserAdminPage.tsx @@ -8,7 +8,10 @@ import { featureEnabled } from '@grafana/runtime'; import { Stack } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; -import { StoreState, UserDTO, UserOrg, UserSession, SyncInfo, UserAdminError, AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { SyncInfo } from 'app/types/ldap'; +import { StoreState } from 'app/types/store'; +import { UserDTO, UserOrg, UserSession, UserAdminError } from 'app/types/user'; import { UserLdapSyncInfo } from './UserLdapSyncInfo'; import { UserOrgs } from './UserOrgs'; diff --git a/public/app/features/admin/UserLdapSyncInfo.tsx b/public/app/features/admin/UserLdapSyncInfo.tsx index 387cc3eb9fa..ca1d0ec148a 100644 --- a/public/app/features/admin/UserLdapSyncInfo.tsx +++ b/public/app/features/admin/UserLdapSyncInfo.tsx @@ -4,7 +4,9 @@ import { dateTimeFormat } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Button, LinkButton } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, SyncInfo, UserDTO } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { SyncInfo } from 'app/types/ldap'; +import { UserDTO } from 'app/types/user'; import { TagBadge } from '../../core/components/TagFilter/TagBadge'; diff --git a/public/app/features/admin/UserListAdminPage.tsx b/public/app/features/admin/UserListAdminPage.tsx index d4b485c3ada..215fd281f3e 100644 --- a/public/app/features/admin/UserListAdminPage.tsx +++ b/public/app/features/admin/UserListAdminPage.tsx @@ -8,8 +8,9 @@ import { Trans, t } from '@grafana/i18n'; import { LinkButton, RadioButtonGroup, useStyles2, FilterInput, EmptyState } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; - -import { AccessControlAction, StoreState, UserFilter } from '../../types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { StoreState } from 'app/types/store'; +import { UserFilter } from 'app/types/user'; import { EnterpriseAuthFeaturesCard } from './EnterpriseAuthFeaturesCard'; import { UsersTable } from './Users/UsersTable'; diff --git a/public/app/features/admin/UserListAnonymousPage.tsx b/public/app/features/admin/UserListAnonymousPage.tsx index c2cd0404dd8..eec26483830 100644 --- a/public/app/features/admin/UserListAnonymousPage.tsx +++ b/public/app/features/admin/UserListAnonymousPage.tsx @@ -7,8 +7,7 @@ import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src'; import { t } from '@grafana/i18n'; import { RadioButtonGroup, useStyles2, FilterInput } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; - -import { StoreState } from '../../types'; +import { StoreState } from 'app/types/store'; import { AnonUsersDevicesTable } from './Users/AnonUsersTable'; import { fetchUsersAnonymousDevices, changeAnonUserSort, changeAnonPage, changeAnonQuery } from './state/actions'; diff --git a/public/app/features/admin/UserListPage.tsx b/public/app/features/admin/UserListPage.tsx index 97184596de4..a2357b4aecf 100644 --- a/public/app/features/admin/UserListPage.tsx +++ b/public/app/features/admin/UserListPage.tsx @@ -9,9 +9,9 @@ import { config } from '@grafana/runtime'; import { useStyles2, TabsBar, Tab } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; import { isEmailSharingEnabled } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; +import { AccessControlAction } from 'app/types/accessControl'; import { Page } from '../../core/components/Page/Page'; -import { AccessControlAction } from '../../types'; import { UsersListPageContent } from '../users/UsersListPage'; import { UserListAdminPageContent } from './UserListAdminPage'; diff --git a/public/app/features/admin/UserOrgs.tsx b/public/app/features/admin/UserOrgs.tsx index 6aac4d1721c..201df124ec8 100644 --- a/public/app/features/admin/UserOrgs.tsx +++ b/public/app/features/admin/UserOrgs.tsx @@ -1,7 +1,7 @@ import { css, cx } from '@emotion/css'; import { createRef, PureComponent, ReactElement } from 'react'; -import { GrafanaTheme2 } from '@grafana/data'; +import { GrafanaTheme2, OrgRole } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Button, @@ -20,7 +20,9 @@ import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker'; import { fetchRoleOptions, updateUserRoles } from 'app/core/components/RolePicker/api'; import { OrgPicker, OrgSelectItem } from 'app/core/components/Select/OrgPicker'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, Organization, OrgRole, Role, UserDTO, UserOrg } from 'app/types'; +import { AccessControlAction, Role } from 'app/types/accessControl'; +import { Organization } from 'app/types/organization'; +import { UserOrg, UserDTO } from 'app/types/user'; import { OrgRolePicker } from './OrgRolePicker'; diff --git a/public/app/features/admin/UserPermissions.tsx b/public/app/features/admin/UserPermissions.tsx index ea658a48e49..4d36d628768 100644 --- a/public/app/features/admin/UserPermissions.tsx +++ b/public/app/features/admin/UserPermissions.tsx @@ -6,7 +6,7 @@ import { Trans, t } from '@grafana/i18n'; import { ConfirmButton, RadioButtonGroup, Icon, useStyles2 } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; import { ExternalUserTooltip } from 'app/features/admin/UserOrgs'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; interface Props { isGrafanaAdmin: boolean; diff --git a/public/app/features/admin/UserProfile.tsx b/public/app/features/admin/UserProfile.tsx index 9b9522a084a..1fb9da50d77 100644 --- a/public/app/features/admin/UserProfile.tsx +++ b/public/app/features/admin/UserProfile.tsx @@ -5,7 +5,8 @@ import * as React from 'react'; import { Trans, t } from '@grafana/i18n'; import { Button, ConfirmButton, ConfirmModal, Input, LegacyInputStatus, Stack } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, UserDTO } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { UserDTO } from 'app/types/user'; interface Props { user: UserDTO; diff --git a/public/app/features/admin/UserSessions.tsx b/public/app/features/admin/UserSessions.tsx index 2ee811676d4..f05278d7884 100644 --- a/public/app/features/admin/UserSessions.tsx +++ b/public/app/features/admin/UserSessions.tsx @@ -5,7 +5,8 @@ import { ConfirmButton, ConfirmModal, Button, Stack } from '@grafana/ui'; import { TagBadge } from 'app/core/components/TagFilter/TagBadge'; import { contextSrv } from 'app/core/core'; import { formatDate } from 'app/core/internationalization/dates'; -import { AccessControlAction, UserSession } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { UserSession } from 'app/types/user'; interface Props { sessions: UserSession[]; diff --git a/public/app/features/admin/Users/AnonUsersTable.tsx b/public/app/features/admin/Users/AnonUsersTable.tsx index b4a4882314f..ba540e280a6 100644 --- a/public/app/features/admin/Users/AnonUsersTable.tsx +++ b/public/app/features/admin/Users/AnonUsersTable.tsx @@ -13,7 +13,7 @@ import { FetchDataFunc, } from '@grafana/ui'; import { EmptyArea } from 'app/features/alerting/unified/components/EmptyArea'; -import { UserAnonymousDeviceDTO } from 'app/types'; +import { UserAnonymousDeviceDTO } from 'app/types/user'; type Cell = CellProps< UserAnonymousDeviceDTO, diff --git a/public/app/features/admin/Users/OrgUnits.tsx b/public/app/features/admin/Users/OrgUnits.tsx index 5dc25622fed..b029df9e19e 100644 --- a/public/app/features/admin/Users/OrgUnits.tsx +++ b/public/app/features/admin/Users/OrgUnits.tsx @@ -2,7 +2,7 @@ import { forwardRef, PropsWithChildren } from 'react'; import { IconName } from '@grafana/data'; import { Icon, Tooltip, Box, Stack } from '@grafana/ui'; -import { Unit } from 'app/types'; +import { Unit } from 'app/types/user'; type OrgUnitProps = { units?: Unit[]; icon: IconName }; diff --git a/public/app/features/admin/Users/OrgUsersTable.test.tsx b/public/app/features/admin/Users/OrgUsersTable.test.tsx index ea64232081e..8fa183441db 100644 --- a/public/app/features/admin/Users/OrgUsersTable.test.tsx +++ b/public/app/features/admin/Users/OrgUsersTable.test.tsx @@ -1,7 +1,8 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { OrgUser } from '../../../types'; +import { OrgUser } from 'app/types/user'; + import { getMockUsers } from '../../users/mocks/userMocks'; import { OrgUsersTable, Props } from './OrgUsersTable'; diff --git a/public/app/features/admin/Users/OrgUsersTable.tsx b/public/app/features/admin/Users/OrgUsersTable.tsx index d83485531db..42f69b89cf2 100644 --- a/public/app/features/admin/Users/OrgUsersTable.tsx +++ b/public/app/features/admin/Users/OrgUsersTable.tsx @@ -25,7 +25,8 @@ import { fetchRoleOptions, updateUserRoles } from 'app/core/components/RolePicke import { RolePickerBadges } from 'app/core/components/RolePickerDrawer/RolePickerBadges'; import { TagBadge } from 'app/core/components/TagFilter/TagBadge'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, OrgUser, Role } from 'app/types'; +import { AccessControlAction, Role } from 'app/types/accessControl'; +import { OrgUser } from 'app/types/user'; import { OrgRolePicker } from '../OrgRolePicker'; diff --git a/public/app/features/admin/Users/UsersTable.test.tsx b/public/app/features/admin/Users/UsersTable.test.tsx index 667aca52b89..61c8210a56f 100644 --- a/public/app/features/admin/Users/UsersTable.test.tsx +++ b/public/app/features/admin/Users/UsersTable.test.tsx @@ -1,7 +1,7 @@ import { render } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom-v5-compat'; -import { UserDTO } from '../../../types'; +import { UserDTO } from 'app/types/user'; import { UsersTable, UsersTableProps } from './UsersTable'; diff --git a/public/app/features/admin/Users/UsersTable.tsx b/public/app/features/admin/Users/UsersTable.tsx index 7deb4480fd4..a3a1f6be297 100644 --- a/public/app/features/admin/Users/UsersTable.tsx +++ b/public/app/features/admin/Users/UsersTable.tsx @@ -17,7 +17,7 @@ import { Tooltip, } from '@grafana/ui'; import { TagBadge } from 'app/core/components/TagFilter/TagBadge'; -import { UserDTO } from 'app/types'; +import { UserDTO } from 'app/types/user'; import { OrgUnits } from './OrgUnits'; diff --git a/public/app/features/admin/api.ts b/public/app/features/admin/api.ts index 0db8de7ed13..f1e4f5419d4 100644 --- a/public/app/features/admin/api.ts +++ b/public/app/features/admin/api.ts @@ -2,7 +2,8 @@ import { UrlQueryValue } from '@grafana/data'; import { getBackendSrv } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; import { accessControlQueryParam } from 'app/core/utils/accessControl'; -import { OrgUser, AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { OrgUser } from 'app/types/user'; const perPage = 30; diff --git a/public/app/features/admin/ldap/LdapConnectionStatus.tsx b/public/app/features/admin/ldap/LdapConnectionStatus.tsx index 59dc679d197..268ac3ea1b5 100644 --- a/public/app/features/admin/ldap/LdapConnectionStatus.tsx +++ b/public/app/features/admin/ldap/LdapConnectionStatus.tsx @@ -2,7 +2,8 @@ import { useMemo } from 'react'; import { Trans, t } from '@grafana/i18n'; import { Alert, CellProps, Column, Icon, InteractiveTable, Stack, Text, Tooltip } from '@grafana/ui'; -import { AppNotificationSeverity, LdapConnectionInfo, LdapServerInfo } from 'app/types'; +import { AppNotificationSeverity } from 'app/types/appNotifications'; +import { LdapConnectionInfo, LdapServerInfo } from 'app/types/ldap'; interface Props { ldapConnectionInfo: LdapConnectionInfo; diff --git a/public/app/features/admin/ldap/LdapDrawer.tsx b/public/app/features/admin/ldap/LdapDrawer.tsx index cd3e0a1342c..159a66a9ea5 100644 --- a/public/app/features/admin/ldap/LdapDrawer.tsx +++ b/public/app/features/admin/ldap/LdapDrawer.tsx @@ -23,7 +23,7 @@ import { RadioButtonGroup, SecretInput, } from '@grafana/ui'; -import { LdapPayload, MapKeyCertConfigured } from 'app/types'; +import { MapKeyCertConfigured, LdapPayload } from 'app/types/ldap'; import { GroupMappingComponent } from './LdapGroupMapping'; diff --git a/public/app/features/admin/ldap/LdapGroupMapping.tsx b/public/app/features/admin/ldap/LdapGroupMapping.tsx index 6680294e578..1a7b8d9450a 100644 --- a/public/app/features/admin/ldap/LdapGroupMapping.tsx +++ b/public/app/features/admin/ldap/LdapGroupMapping.tsx @@ -1,10 +1,10 @@ import { useFormContext } from 'react-hook-form'; -import { SelectableValue } from '@grafana/data'; +import { OrgRole, SelectableValue } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Box, Button, Field, Input, RadioButtonGroup, Switch } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { LdapPayload, OrgRole } from 'app/types'; +import { LdapPayload } from 'app/types/ldap'; const roleOptions: Array> = Object.keys(OrgRole).map((key) => { return { label: key, value: key }; diff --git a/public/app/features/admin/ldap/LdapPage.tsx b/public/app/features/admin/ldap/LdapPage.tsx index ce1ba188936..4c6bc32f0e7 100644 --- a/public/app/features/admin/ldap/LdapPage.tsx +++ b/public/app/features/admin/ldap/LdapPage.tsx @@ -9,15 +9,10 @@ import { Alert, Button, Field, Input, Stack } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; -import { - AppNotificationSeverity, - LdapError, - LdapUser, - StoreState, - SyncInfo, - LdapConnectionInfo, - AccessControlAction, -} from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { AppNotificationSeverity } from 'app/types/appNotifications'; +import { LdapConnectionInfo, LdapUser, SyncInfo, LdapError } from 'app/types/ldap'; +import { StoreState } from 'app/types/store'; import { loadLdapState, diff --git a/public/app/features/admin/ldap/LdapSettingsPage.tsx b/public/app/features/admin/ldap/LdapSettingsPage.tsx index 7ba327c1ce0..b100c9386fb 100644 --- a/public/app/features/admin/ldap/LdapSettingsPage.tsx +++ b/public/app/features/admin/ldap/LdapSettingsPage.tsx @@ -27,7 +27,8 @@ import { FormPrompt } from 'app/core/components/FormPrompt/FormPrompt'; import { Page } from 'app/core/components/Page/Page'; import config from 'app/core/config'; import { Loader } from 'app/features/plugins/admin/components/Loader'; -import { LdapPayload, MapKeyCertConfigured, StoreState } from 'app/types'; +import { LdapPayload, MapKeyCertConfigured } from 'app/types/ldap'; +import { StoreState } from 'app/types/store'; import { LdapDrawerComponent } from './LdapDrawer'; diff --git a/public/app/features/admin/ldap/LdapSyncInfo.tsx b/public/app/features/admin/ldap/LdapSyncInfo.tsx index 11a1db488b5..c4aacb5a7ad 100644 --- a/public/app/features/admin/ldap/LdapSyncInfo.tsx +++ b/public/app/features/admin/ldap/LdapSyncInfo.tsx @@ -1,7 +1,7 @@ import { dateTimeFormat } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { InteractiveTable, Text } from '@grafana/ui'; -import { SyncInfo } from 'app/types'; +import { SyncInfo } from 'app/types/ldap'; interface Props { ldapSyncInfo: SyncInfo; diff --git a/public/app/features/admin/ldap/LdapUserGroups.tsx b/public/app/features/admin/ldap/LdapUserGroups.tsx index d2e82b83e3e..7f0ff635a44 100644 --- a/public/app/features/admin/ldap/LdapUserGroups.tsx +++ b/public/app/features/admin/ldap/LdapUserGroups.tsx @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import { Trans, t } from '@grafana/i18n'; import { Tooltip, Icon, InteractiveTable, type CellProps, Column, Stack } from '@grafana/ui'; -import { LdapRole } from 'app/types'; +import { LdapRole } from 'app/types/ldap'; interface Props { groups: LdapRole[]; diff --git a/public/app/features/admin/ldap/LdapUserInfo.tsx b/public/app/features/admin/ldap/LdapUserInfo.tsx index 0877216ca6f..73d6a79a87b 100644 --- a/public/app/features/admin/ldap/LdapUserInfo.tsx +++ b/public/app/features/admin/ldap/LdapUserInfo.tsx @@ -1,6 +1,6 @@ import { Trans } from '@grafana/i18n'; import { Box, Stack, Text } from '@grafana/ui'; -import { LdapUser } from 'app/types'; +import { LdapUser } from 'app/types/ldap'; import { LdapUserGroups } from './LdapUserGroups'; import { LdapUserMappingInfo } from './LdapUserMappingInfo'; diff --git a/public/app/features/admin/ldap/LdapUserMappingInfo.tsx b/public/app/features/admin/ldap/LdapUserMappingInfo.tsx index 534ea3cf0a7..e4485a9d3c2 100644 --- a/public/app/features/admin/ldap/LdapUserMappingInfo.tsx +++ b/public/app/features/admin/ldap/LdapUserMappingInfo.tsx @@ -1,7 +1,7 @@ import { useMemo } from 'react'; import { InteractiveTable } from '@grafana/ui'; -import { LdapUserInfo } from 'app/types'; +import { LdapUserInfo } from 'app/types/ldap'; interface Props { info: LdapUserInfo; diff --git a/public/app/features/admin/ldap/LdapUserPermissions.tsx b/public/app/features/admin/ldap/LdapUserPermissions.tsx index e426a4e090b..57dc65f4c96 100644 --- a/public/app/features/admin/ldap/LdapUserPermissions.tsx +++ b/public/app/features/admin/ldap/LdapUserPermissions.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { Trans } from '@grafana/i18n'; import { Column, Icon, InteractiveTable } from '@grafana/ui'; -import { LdapPermissions } from 'app/types'; +import { LdapPermissions } from 'app/types/ldap'; interface Props { permissions: LdapPermissions; diff --git a/public/app/features/admin/ldap/LdapUserTeams.tsx b/public/app/features/admin/ldap/LdapUserTeams.tsx index 39f9f779710..b37cad73034 100644 --- a/public/app/features/admin/ldap/LdapUserTeams.tsx +++ b/public/app/features/admin/ldap/LdapUserTeams.tsx @@ -1,7 +1,7 @@ import { useMemo } from 'react'; import { Column, InteractiveTable, CellProps } from '@grafana/ui'; -import { LdapTeam } from 'app/types'; +import { LdapTeam } from 'app/types/ldap'; interface Props { teams: LdapTeam[]; diff --git a/public/app/features/admin/state/actions.ts b/public/app/features/admin/state/actions.ts index ede0ed15dd6..7dd57ea1e72 100644 --- a/public/app/features/admin/state/actions.ts +++ b/public/app/features/admin/state/actions.ts @@ -6,15 +6,10 @@ import { FetchDataArgs } from '@grafana/ui'; import config from 'app/core/config'; import { contextSrv } from 'app/core/core'; import { accessControlQueryParam } from 'app/core/utils/accessControl'; -import { - ThunkResult, - LdapUser, - UserSession, - UserDTO, - AccessControlAction, - UserFilter, - AnonUserFilter, -} from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { LdapUser } from 'app/types/ldap'; +import { ThunkResult } from 'app/types/store'; +import { UserDTO, UserSession, UserFilter, AnonUserFilter } from 'app/types/user'; import { userAdminPageLoadedAction, diff --git a/public/app/features/admin/state/reducers.test.ts b/public/app/features/admin/state/reducers.test.ts index 8b504a62935..67652835859 100644 --- a/public/app/features/admin/state/reducers.test.ts +++ b/public/app/features/admin/state/reducers.test.ts @@ -1,6 +1,7 @@ import { reducerTester } from 'test/core/redux/reducerTester'; -import { LdapState, LdapUser, UserAdminState, UserDTO, UserListAdminState } from 'app/types'; +import { LdapState, LdapUser } from 'app/types/ldap'; +import { UserAdminState, UserListAdminState, UserDTO } from 'app/types/user'; import { clearUserMappingInfoAction, diff --git a/public/app/features/admin/state/reducers.ts b/public/app/features/admin/state/reducers.ts index 550e3de57b6..67f71dec9f3 100644 --- a/public/app/features/admin/state/reducers.ts +++ b/public/app/features/admin/state/reducers.ts @@ -1,22 +1,18 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { LdapState, LdapConnectionInfo, LdapError, SyncInfo, LdapUser } from 'app/types/ldap'; import { - LdapConnectionInfo, - LdapError, - LdapState, - LdapUser, - SyncInfo, - UserAdminError, UserAdminState, UserDTO, UserOrg, UserSession, + UserAdminError, UserListAdminState, UserFilter, UserListAnonymousDevicesState, UserAnonymousDeviceDTO, AnonUserFilter, -} from 'app/types'; +} from 'app/types/user'; const initialLdapState: LdapState = { connectionInfo: [], diff --git a/public/app/features/alerting/routes.tsx b/public/app/features/alerting/routes.tsx index 12a8dbfbadf..e51fd7cc27e 100644 --- a/public/app/features/alerting/routes.tsx +++ b/public/app/features/alerting/routes.tsx @@ -3,7 +3,7 @@ import { Navigate } from 'react-router-dom-v5-compat'; import { SafeDynamicImport } from 'app/core/components/DynamicImports/SafeDynamicImport'; import { config } from 'app/core/config'; import { GrafanaRouteComponent, RouteDescriptor } from 'app/core/navigation/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PERMISSIONS_CONTACT_POINTS } from './unified/components/contact-points/permissions'; import { @@ -314,8 +314,16 @@ export function getAlertingRoutes(cfg = config): RouteDescriptor[] { ), }, { + // This route is for backward compatibility + // Previously we had a single admin page containing only the alertmanager settings + // We now have a separate route for the alertmanager settings and other settings can be added as extensions path: '/alerting/admin', roles: () => ['Admin'], + component: () => , + }, + { + path: '/alerting/admin/alertmanager', + roles: () => ['Admin'], component: importAlertingComponent( () => import(/* webpackChunkName: "AlertingSettings" */ 'app/features/alerting/unified/Settings') ), diff --git a/public/app/features/alerting/state/reducers.test.ts b/public/app/features/alerting/state/reducers.test.ts index ac9b9acda67..7afd5eee5e7 100644 --- a/public/app/features/alerting/state/reducers.test.ts +++ b/public/app/features/alerting/state/reducers.test.ts @@ -1,5 +1,5 @@ import { dateTime } from '@grafana/data'; -import { AlertRuleDTO, AlertRulesState, NotificationChannelState, NotifierDTO } from 'app/types'; +import { AlertRuleDTO, AlertRulesState, NotificationChannelState, NotifierDTO } from 'app/types/alerting'; import { reducerTester } from '../../../../test/core/redux/reducerTester'; diff --git a/public/app/features/alerting/state/reducers.ts b/public/app/features/alerting/state/reducers.ts index f4c9b798bc2..ffba9aa8c89 100644 --- a/public/app/features/alerting/state/reducers.ts +++ b/public/app/features/alerting/state/reducers.ts @@ -8,7 +8,7 @@ import { NotificationChannelOption, NotificationChannelState, NotifierDTO, -} from 'app/types'; +} from 'app/types/alerting'; import unifiedAlertingReducer from '../unified/state/reducers'; diff --git a/public/app/features/alerting/state/selectors.test.ts b/public/app/features/alerting/state/selectors.test.ts index b279c1ebd41..0463a99be8e 100644 --- a/public/app/features/alerting/state/selectors.test.ts +++ b/public/app/features/alerting/state/selectors.test.ts @@ -1,4 +1,5 @@ -import { AlertRulesState, StoreState } from 'app/types'; +import { AlertRulesState } from 'app/types/alerting'; +import { StoreState } from 'app/types/store'; import { getAlertRuleItems, getSearchQuery } from './selectors'; diff --git a/public/app/features/alerting/state/selectors.ts b/public/app/features/alerting/state/selectors.ts index f51e66ce8a4..0e2c897e7bb 100644 --- a/public/app/features/alerting/state/selectors.ts +++ b/public/app/features/alerting/state/selectors.ts @@ -1,4 +1,5 @@ -import { AlertRule, AlertRulesState, NotificationChannelState, StoreState } from 'app/types'; +import { AlertRule, AlertRulesState, NotificationChannelState } from 'app/types/alerting'; +import { StoreState } from 'app/types/store'; export const getSearchQuery = (state: AlertRulesState) => state.searchQuery; diff --git a/public/app/features/alerting/unified/AlertGroups.test.tsx b/public/app/features/alerting/unified/AlertGroups.test.tsx index a39b0348f15..dbf38615d33 100644 --- a/public/app/features/alerting/unified/AlertGroups.test.tsx +++ b/public/app/features/alerting/unified/AlertGroups.test.tsx @@ -3,7 +3,7 @@ import { byRole, byTestId, byText } from 'testing-library-selector'; import { selectors } from '@grafana/e2e-selectors'; import { setupDataSources } from 'app/features/alerting/unified/testSetup/datasources'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import AlertGroups from './AlertGroups'; import { fetchAlertGroups } from './api/alertmanager'; diff --git a/public/app/features/alerting/unified/AlertGroups.tsx b/public/app/features/alerting/unified/AlertGroups.tsx index a72d973645b..0ca50b2c7c9 100644 --- a/public/app/features/alerting/unified/AlertGroups.tsx +++ b/public/app/features/alerting/unified/AlertGroups.tsx @@ -3,7 +3,7 @@ import { Fragment, useEffect } from 'react'; import { Trans, t } from '@grafana/i18n'; import { Alert, Box, LoadingPlaceholder, Text } from '@grafana/ui'; import { useQueryParams } from 'app/core/hooks/useQueryParams'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { AlertmanagerChoice } from '../../../plugins/datasource/alertmanager/types'; diff --git a/public/app/features/alerting/unified/AlertsFolderView.tsx b/public/app/features/alerting/unified/AlertsFolderView.tsx index 8e13f93435a..ec39dcdde18 100644 --- a/public/app/features/alerting/unified/AlertsFolderView.tsx +++ b/public/app/features/alerting/unified/AlertsFolderView.tsx @@ -8,7 +8,7 @@ import { Trans, t } from '@grafana/i18n'; import { Card, FilterInput, Icon, Pagination, Select, Stack, TagList, useStyles2 } from '@grafana/ui'; import { DEFAULT_PER_PAGE_PAGINATION } from 'app/core/constants'; import { getQueryParamValue } from 'app/core/utils/query'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { GrafanaRuleDefinition, RulerGrafanaRuleDTO } from 'app/types/unified-alerting-dto'; import { usePagination } from './hooks/usePagination'; diff --git a/public/app/features/alerting/unified/MuteTimings.test.tsx b/public/app/features/alerting/unified/MuteTimings.test.tsx index 0b69e95653e..fc44b90a59f 100644 --- a/public/app/features/alerting/unified/MuteTimings.test.tsx +++ b/public/app/features/alerting/unified/MuteTimings.test.tsx @@ -14,7 +14,7 @@ import { } from 'app/features/alerting/unified/mocks/server/handlers/k8s/timeIntervals.k8s'; import { setupDataSources } from 'app/features/alerting/unified/testSetup/datasources'; import { AlertManagerCortexConfig, MuteTimeInterval } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import EditMuteTimingPage from './components/mute-timings/EditMuteTiming'; import NewMuteTimingPage from './components/mute-timings/NewMuteTiming'; diff --git a/public/app/features/alerting/unified/NotificationPoliciesPage.test.tsx b/public/app/features/alerting/unified/NotificationPoliciesPage.test.tsx index f48f3eb16fe..90bfe88ad4b 100644 --- a/public/app/features/alerting/unified/NotificationPoliciesPage.test.tsx +++ b/public/app/features/alerting/unified/NotificationPoliciesPage.test.tsx @@ -29,7 +29,7 @@ import { MatcherOperator, RouteWithID, } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import NotificationPolicies from './NotificationPoliciesPage'; import { findRoutesMatchingFilters } from './components/notification-policies/NotificationPoliciesList'; diff --git a/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx b/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx index 9e01d77d060..dfe3549eeee 100644 --- a/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx +++ b/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx @@ -7,7 +7,7 @@ import config from 'app/core/config'; import { setupDataSources } from 'app/features/alerting/unified/testSetup/datasources'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { AlertQuery, PromRulesResponse } from 'app/types/unified-alerting-dto'; import { PanelAlertTabContent } from './PanelAlertTabContent'; diff --git a/public/app/features/alerting/unified/Receivers.test.tsx b/public/app/features/alerting/unified/Receivers.test.tsx index 0363e772509..f831a707bb3 100644 --- a/public/app/features/alerting/unified/Receivers.test.tsx +++ b/public/app/features/alerting/unified/Receivers.test.tsx @@ -10,7 +10,7 @@ import { import { setupMswServer } from 'app/features/alerting/unified/mockApi'; import { grantUserPermissions } from 'app/features/alerting/unified/mocks'; import { setupDataSources } from 'app/features/alerting/unified/testSetup/datasources'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import ContactPoints from './components/contact-points/ContactPoints'; import EditContactPoint from './components/contact-points/EditContactPoint'; diff --git a/public/app/features/alerting/unified/RuleEditorGrafanaRecordingRules.test.tsx b/public/app/features/alerting/unified/RuleEditorGrafanaRecordingRules.test.tsx index 196ee8b0583..fcc74629ca1 100644 --- a/public/app/features/alerting/unified/RuleEditorGrafanaRecordingRules.test.tsx +++ b/public/app/features/alerting/unified/RuleEditorGrafanaRecordingRules.test.tsx @@ -9,7 +9,7 @@ import { FeatureToggles } from '@grafana/data'; import { contextSrv } from 'app/core/services/context_srv'; import { setupMswServer } from 'app/features/alerting/unified/mockApi'; import { PROMETHEUS_DATASOURCE_UID } from 'app/features/alerting/unified/mocks/server/constants'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { grantUserPermissions, mockDataSource } from './mocks'; import { grafanaRulerGroup } from './mocks/grafanaRulerApi'; diff --git a/public/app/features/alerting/unified/RuleList.test.tsx b/public/app/features/alerting/unified/RuleList.test.tsx index 5868e5b4c13..905920cbf1d 100644 --- a/public/app/features/alerting/unified/RuleList.test.tsx +++ b/public/app/features/alerting/unified/RuleList.test.tsx @@ -12,7 +12,7 @@ import { setAlertmanagerChoices } from 'app/features/alerting/unified/mocks/serv import * as actions from 'app/features/alerting/unified/state/actions'; import { setupDataSources } from 'app/features/alerting/unified/testSetup/datasources'; import { AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PromAlertingRuleState, PromApplication } from 'app/types/unified-alerting-dto'; import RuleList from './RuleList'; diff --git a/public/app/features/alerting/unified/Settings.test.tsx b/public/app/features/alerting/unified/Settings.test.tsx index 0d362c74b45..cba6f0a0308 100644 --- a/public/app/features/alerting/unified/Settings.test.tsx +++ b/public/app/features/alerting/unified/Settings.test.tsx @@ -7,6 +7,7 @@ import DataSourcesResponse from './components/settings/mocks/api/datasources.jso import { setupGrafanaManagedServer, withExternalOnlySetting } from './components/settings/mocks/server'; import { setupMswServer } from './mockApi'; import { grantUserRole } from './mocks'; +import { addSettingsSection, clearSettingsExtensions } from './settings/extensions'; jest.mock('@grafana/runtime', () => ({ ...jest.requireActual('@grafana/runtime'), @@ -35,12 +36,23 @@ const ui = { versionsTab: byRole('tab', { name: /versions/i }), provisionedBadge: byText(/^Provisioned$/), + + // New selectors for extension tabs + alertmanagerTab: byRole('tab', { name: 'Alert managers' }), + enrichmentTab: byRole('tab', { name: 'Enrichment' }), + notificationsTab: byRole('tab', { name: 'Notifications' }), + customTab: (name: string) => byRole('tab', { name }), }; describe('Alerting settings', () => { beforeEach(() => { grantUserRole('ServerAdmin'); setupGrafanaManagedServer(server); + clearSettingsExtensions(); + }); + + afterEach(() => { + clearSettingsExtensions(); }); it('should render the page with Built-in only enabled, others disabled', async () => { @@ -131,4 +143,118 @@ describe('Alerting settings', () => { expect(enableButton).not.toBeInTheDocument(); expect(disableButton).not.toBeInTheDocument(); }); + + it('should display additional tabs when settings extensions are registered', async () => { + // Register extensions before rendering + addSettingsSection({ + id: 'enrichment', + text: 'Enrichment', + url: '/alerting/admin/enrichment', + icon: 'star', + }); + + addSettingsSection({ + id: 'notifications', + text: 'Notifications', + url: '/alerting/admin/notifications', + icon: 'bell', + }); + + render(, { + historyOptions: { + initialEntries: ['/alerting/admin/alertmanager'], + }, + }); + + // Wait for the page to load + await waitFor(() => expect(ui.builtInAlertmanagerSection.get()).toBeInTheDocument()); + + // Check that the extension tabs are visible + expect(ui.enrichmentTab.get()).toBeInTheDocument(); + expect(ui.notificationsTab.get()).toBeInTheDocument(); + }); + + it('should correctly show active state for extension tabs based on route', async () => { + // Register an extension + addSettingsSection({ + id: 'enrichment', + text: 'Enrichment', + url: '/alerting/admin/enrichment', + icon: 'star', + }); + + // Render with the extension route as active + render(, { + historyOptions: { + initialEntries: ['/alerting/admin/enrichment'], + }, + }); + + // Wait for the page to load + await waitFor(() => expect(ui.builtInAlertmanagerSection.get()).toBeInTheDocument()); + + // Check that the extension tab is visible and active + const enrichmentTab = ui.enrichmentTab.get(); + expect(enrichmentTab).toBeInTheDocument(); + expect(enrichmentTab).toHaveAttribute('aria-selected', 'true'); + + // Check that the default alertmanager tab is not active + const alertmanagerTab = ui.alertmanagerTab.get(); + expect(alertmanagerTab).toHaveAttribute('aria-selected', 'false'); + }); + + it('should handle multiple extensions correctly', async () => { + // Register multiple extensions + addSettingsSection({ + id: 'enrichment', + text: 'Enrichment', + url: '/alerting/admin/enrichment', + icon: 'star', + }); + + addSettingsSection({ + id: 'notifications', + text: 'Notifications', + url: '/alerting/admin/notifications', + icon: 'bell', + }); + + addSettingsSection({ + id: 'custom-settings', + text: 'Custom Settings', + url: '/alerting/admin/custom', + icon: 'cog', + }); + + render(, { + historyOptions: { + initialEntries: ['/alerting/admin/alertmanager'], + }, + }); + + // Wait for the page to load + await waitFor(() => expect(ui.builtInAlertmanagerSection.get()).toBeInTheDocument()); + + // Check that all tabs are visible + expect(ui.alertmanagerTab.get()).toBeInTheDocument(); + expect(ui.enrichmentTab.get()).toBeInTheDocument(); + expect(ui.notificationsTab.get()).toBeInTheDocument(); + expect(ui.customTab('Custom Settings').get()).toBeInTheDocument(); + }); + + it('should not show extension tabs when no extensions are registered', async () => { + render(, { + historyOptions: { + initialEntries: ['/alerting/admin/alertmanager'], + }, + }); + + // Wait for the page to load + await waitFor(() => expect(ui.builtInAlertmanagerSection.get()).toBeInTheDocument()); + + // Check that only the default alertmanager tab is visible + expect(ui.alertmanagerTab.get()).toBeInTheDocument(); + expect(ui.enrichmentTab.query()).not.toBeInTheDocument(); + expect(ui.notificationsTab.query()).not.toBeInTheDocument(); + }); }); diff --git a/public/app/features/alerting/unified/Settings.tsx b/public/app/features/alerting/unified/Settings.tsx index e1a1eea1679..f09e9036fd3 100644 --- a/public/app/features/alerting/unified/Settings.tsx +++ b/public/app/features/alerting/unified/Settings.tsx @@ -7,24 +7,28 @@ import { useEditConfigurationDrawer } from './components/settings/ConfigurationD import { ExternalAlertmanagers } from './components/settings/ExternalAlertmanagers'; import InternalAlertmanager from './components/settings/InternalAlertmanager'; import { SettingsProvider, useSettings } from './components/settings/SettingsContext'; +import { useSettingsPageNav } from './settings/navigation'; import { withPageErrorBoundary } from './withPageErrorBoundary'; -function SettingsPage() { +function AlertmanagerSettingsPage() { return ( - + ); } -function SettingsContent() { +function AlertmanagerSettingsContent() { const [configurationDrawer, showConfiguration] = useEditConfigurationDrawer(); const { isLoading } = useSettings(); + const { navId, pageNav } = useSettingsPageNav(); + return ( { +const MenuItemPauseRule = ({ uid, isPaused, groupIdentifier, onPauseChange }: Props) => { const notifyApp = useAppNotification(); const [pauseRule, updateState] = usePauseRuleInGroup(); - const [icon, title] = isPausedRule(rule) - ? ['play' as const, 'Resume evaluation'] - : ['pause' as const, 'Pause evaluation']; + const [icon, title] = isPaused ? ['play' as const, 'Resume evaluation'] : ['pause' as const, 'Pause evaluation']; /** * Triggers API call to update the current rule to the new `is_paused` state */ const setRulePause = async (newIsPaused: boolean) => { try { - await pauseRule.execute(groupIdentifier, rule.grafana_alert.uid, newIsPaused); + await pauseRule.execute(groupIdentifier, uid, newIsPaused); } catch (error) { notifyApp.error(`Failed to ${newIsPaused ? 'pause' : 'resume'} the rule: ${stringifyErrorLike(error)}`); return; @@ -49,7 +46,7 @@ const MenuItemPauseRule = ({ rule, groupIdentifier, onPauseChange }: Props) => { icon={icon} disabled={isLoading(updateState)} onClick={() => { - setRulePause(!rule.grafana_alert.is_paused); + setRulePause(!isPaused); }} /> ); diff --git a/public/app/features/alerting/unified/components/alert-groups/AlertDetails.tsx b/public/app/features/alerting/unified/components/alert-groups/AlertDetails.tsx index 3177a8aa6e7..642c47a3f9d 100644 --- a/public/app/features/alerting/unified/components/alert-groups/AlertDetails.tsx +++ b/public/app/features/alerting/unified/components/alert-groups/AlertDetails.tsx @@ -5,7 +5,7 @@ import { Trans, t } from '@grafana/i18n'; import { LinkButton, useStyles2 } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; import { AlertState, AlertmanagerAlert } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { AlertmanagerAction } from '../../hooks/useAbilities'; import { isGrafanaRulesSource } from '../../utils/datasource'; diff --git a/public/app/features/alerting/unified/components/contact-points/ContactPoints.test.tsx b/public/app/features/alerting/unified/components/contact-points/ContactPoints.test.tsx index 87f1ebfff59..79cec523d69 100644 --- a/public/app/features/alerting/unified/components/contact-points/ContactPoints.test.tsx +++ b/public/app/features/alerting/unified/components/contact-points/ContactPoints.test.tsx @@ -7,7 +7,7 @@ import { MIMIR_DATASOURCE_UID } from 'app/features/alerting/unified/mocks/server import { flushMicrotasks } from 'app/features/alerting/unified/test/test-utils'; import { K8sAnnotations } from 'app/features/alerting/unified/utils/k8s/constants'; import { AlertManagerDataSourceJsonData, AlertManagerImplementation } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../../mockApi'; import { grantUserPermissions, mockDataSource } from '../../mocks'; diff --git a/public/app/features/alerting/unified/components/contact-points/ContactPoints.tsx b/public/app/features/alerting/unified/components/contact-points/ContactPoints.tsx index a9bbbf29845..6f2423e424d 100644 --- a/public/app/features/alerting/unified/components/contact-points/ContactPoints.tsx +++ b/public/app/features/alerting/unified/components/contact-points/ContactPoints.tsx @@ -17,7 +17,7 @@ import { import { contextSrv } from 'app/core/core'; import { shouldUseK8sApi } from 'app/features/alerting/unified/utils/k8s/utils'; import { makeAMLink, stringifyErrorLike } from 'app/features/alerting/unified/utils/misc'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { AlertmanagerAction, useAlertmanagerAbility } from '../../hooks/useAbilities'; import { usePagination } from '../../hooks/usePagination'; diff --git a/public/app/features/alerting/unified/components/contact-points/EditContactPoint.test.tsx b/public/app/features/alerting/unified/components/contact-points/EditContactPoint.test.tsx index b43671ce874..04f6fcdb435 100644 --- a/public/app/features/alerting/unified/components/contact-points/EditContactPoint.test.tsx +++ b/public/app/features/alerting/unified/components/contact-points/EditContactPoint.test.tsx @@ -4,7 +4,7 @@ import { clickSelectOption } from 'test/helpers/selectOptionInTest'; import { render, screen, within } from 'test/test-utils'; import EditContactPoint from 'app/features/alerting/unified/components/contact-points/EditContactPoint'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../../mockApi'; import { grantUserPermissions } from '../../mocks'; diff --git a/public/app/features/alerting/unified/components/contact-points/NotificationTemplates.test.tsx b/public/app/features/alerting/unified/components/contact-points/NotificationTemplates.test.tsx index ee5cd458b8d..479d6453c26 100644 --- a/public/app/features/alerting/unified/components/contact-points/NotificationTemplates.test.tsx +++ b/public/app/features/alerting/unified/components/contact-points/NotificationTemplates.test.tsx @@ -1,7 +1,7 @@ import { render, screen, within } from 'test/test-utils'; import { AppNotificationList } from 'app/core/components/AppNotifications/AppNotificationList'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../../mockApi'; import { grantUserPermissions } from '../../mocks'; diff --git a/public/app/features/alerting/unified/components/contact-points/permissions.ts b/public/app/features/alerting/unified/components/contact-points/permissions.ts index 48ba46a10c5..48686fc5fb1 100644 --- a/public/app/features/alerting/unified/components/contact-points/permissions.ts +++ b/public/app/features/alerting/unified/components/contact-points/permissions.ts @@ -1,4 +1,4 @@ -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; /** * List of granular permissions that allow viewing contact points diff --git a/public/app/features/alerting/unified/components/contact-points/useContactPoints.test.tsx b/public/app/features/alerting/unified/components/contact-points/useContactPoints.test.tsx index 59f38e5a4fe..2ac9c04f981 100644 --- a/public/app/features/alerting/unified/components/contact-points/useContactPoints.test.tsx +++ b/public/app/features/alerting/unified/components/contact-points/useContactPoints.test.tsx @@ -6,7 +6,7 @@ import { disablePlugin } from 'app/features/alerting/unified/mocks/server/config import { setOnCallIntegrations } from 'app/features/alerting/unified/mocks/server/handlers/plugins/configure-plugins'; import { SupportedPlugin } from 'app/features/alerting/unified/types/pluginBridges'; import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../../mockApi'; import { grantUserPermissions } from '../../mocks'; diff --git a/public/app/features/alerting/unified/components/contact-points/utils.ts b/public/app/features/alerting/unified/components/contact-points/utils.ts index f45535df9dc..034ee098894 100644 --- a/public/app/features/alerting/unified/components/contact-points/utils.ts +++ b/public/app/features/alerting/unified/components/contact-points/utils.ts @@ -11,7 +11,7 @@ import { Receiver, Route, } from 'app/plugins/datasource/alertmanager/types'; -import { NotifierDTO, NotifierStatus, ReceiversStateDTO } from 'app/types'; +import { NotifierDTO, NotifierStatus, ReceiversStateDTO } from 'app/types/alerting'; import { OnCallIntegrationDTO } from '../../api/onCallApi'; import { computeInheritedTree } from '../../utils/notification-policies'; diff --git a/public/app/features/alerting/unified/components/create-folder/CreateNewFolder.tsx b/public/app/features/alerting/unified/components/create-folder/CreateNewFolder.tsx index 0f61f8c7a42..a8e3d4d3fba 100644 --- a/public/app/features/alerting/unified/components/create-folder/CreateNewFolder.tsx +++ b/public/app/features/alerting/unified/components/create-folder/CreateNewFolder.tsx @@ -8,7 +8,7 @@ import { Button, Field, Input, Label, Modal, Stack, useStyles2 } from '@grafana/ import { useAppNotification } from 'app/core/copy/appNotification'; import { contextSrv } from 'app/core/core'; import { useNewFolderMutation } from 'app/features/browse-dashboards/api/browseDashboardsAPI'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { Folder } from '../../types/rule-form'; diff --git a/public/app/features/alerting/unified/components/export/GrafanaRuleFolderExporter.tsx b/public/app/features/alerting/unified/components/export/GrafanaRuleFolderExporter.tsx index cefe9fa5530..b240743f672 100644 --- a/public/app/features/alerting/unified/components/export/GrafanaRuleFolderExporter.tsx +++ b/public/app/features/alerting/unified/components/export/GrafanaRuleFolderExporter.tsx @@ -2,8 +2,8 @@ import { useState } from 'react'; import { t } from '@grafana/i18n'; import { LoadingPlaceholder } from '@grafana/ui'; +import { FolderDTO } from 'app/types/folders'; -import { FolderDTO } from '../../../../../types'; import { alertRuleApi } from '../../api/alertRuleApi'; import { FileExportPreview } from './FileExportPreview'; diff --git a/public/app/features/alerting/unified/components/folder-actions/FolderActionsButton.tsx b/public/app/features/alerting/unified/components/folder-actions/FolderActionsButton.tsx index d677309fb51..14988605dbe 100644 --- a/public/app/features/alerting/unified/components/folder-actions/FolderActionsButton.tsx +++ b/public/app/features/alerting/unified/components/folder-actions/FolderActionsButton.tsx @@ -3,7 +3,7 @@ import { useState } from 'react'; import { t } from '@grafana/i18n'; import { config, locationService } from '@grafana/runtime'; import { Dropdown, Menu } from '@grafana/ui'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { alertingFolderActionsApi } from '../../api/alertingFolderActionsApi'; import { shouldUseAlertingListViewV2, shouldUsePrometheusRulesPrimary } from '../../featureToggles'; diff --git a/public/app/features/alerting/unified/components/import-to-gma/ImportToGMARules.test.tsx b/public/app/features/alerting/unified/components/import-to-gma/ImportToGMARules.test.tsx index ad0d4feb52f..da2fbd63528 100644 --- a/public/app/features/alerting/unified/components/import-to-gma/ImportToGMARules.test.tsx +++ b/public/app/features/alerting/unified/components/import-to-gma/ImportToGMARules.test.tsx @@ -2,7 +2,7 @@ import { render, waitFor } from 'test/test-utils'; import { byLabelText, byRole } from 'testing-library-selector'; import { setPluginComponentsHook, setPluginLinksHook } from '@grafana/runtime'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../../mockApi'; import { grantUserPermissions } from '../../mocks'; diff --git a/public/app/features/alerting/unified/components/import-to-gma/hooks.ts b/public/app/features/alerting/unified/components/import-to-gma/hooks.ts index 0d41f413a2b..a15d6f85218 100644 --- a/public/app/features/alerting/unified/components/import-to-gma/hooks.ts +++ b/public/app/features/alerting/unified/components/import-to-gma/hooks.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from 'react'; import { lastValueFrom } from 'rxjs'; import { getBackendSrv } from '@grafana/runtime'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { RulerRulesConfigDTO } from 'app/types/unified-alerting-dto'; import { alertRuleApi } from '../../api/alertRuleApi'; diff --git a/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx b/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx index a60d1902d7b..d9d611d7a00 100644 --- a/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx +++ b/public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.test.tsx @@ -7,7 +7,7 @@ import { } from 'app/features/alerting/unified/mocks/server/configure'; import { setAlertmanagerConfig } from 'app/features/alerting/unified/mocks/server/entities/alertmanagers'; import { captureRequests } from 'app/features/alerting/unified/mocks/server/events'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { grantUserPermissions } from '../../mocks'; import { TIME_INTERVAL_UID_HAPPY_PATH } from '../../mocks/server/handlers/k8s/timeIntervals.k8s'; diff --git a/public/app/features/alerting/unified/components/mute-timings/permissions.ts b/public/app/features/alerting/unified/components/mute-timings/permissions.ts index 5cbf687c636..b2891d4b251 100644 --- a/public/app/features/alerting/unified/components/mute-timings/permissions.ts +++ b/public/app/features/alerting/unified/components/mute-timings/permissions.ts @@ -1,4 +1,4 @@ -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; /** * List of granular permissions that allow viewing contact points diff --git a/public/app/features/alerting/unified/components/notification-policies/EditDefaultPolicyForm.test.tsx b/public/app/features/alerting/unified/components/notification-policies/EditDefaultPolicyForm.test.tsx index e7ed08151a5..f426b2ad737 100644 --- a/public/app/features/alerting/unified/components/notification-policies/EditDefaultPolicyForm.test.tsx +++ b/public/app/features/alerting/unified/components/notification-policies/EditDefaultPolicyForm.test.tsx @@ -6,7 +6,7 @@ import { Button } from '@grafana/ui'; import { setupMswServer } from 'app/features/alerting/unified/mockApi'; import { grantUserPermissions } from 'app/features/alerting/unified/mocks'; import { AlertmanagerProvider } from 'app/features/alerting/unified/state/AlertmanagerContext'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RouteWithID } from '../../../../../plugins/datasource/alertmanager/types'; import { FormAmRoute } from '../../types/amroutes'; diff --git a/public/app/features/alerting/unified/components/notification-policies/EditNotificationPolicyForm.test.tsx b/public/app/features/alerting/unified/components/notification-policies/EditNotificationPolicyForm.test.tsx index c83c0813cf1..171e4349bf3 100644 --- a/public/app/features/alerting/unified/components/notification-policies/EditNotificationPolicyForm.test.tsx +++ b/public/app/features/alerting/unified/components/notification-policies/EditNotificationPolicyForm.test.tsx @@ -6,7 +6,7 @@ import { Button } from '@grafana/ui'; import { setupMswServer } from 'app/features/alerting/unified/mockApi'; import { grantUserPermissions } from 'app/features/alerting/unified/mocks'; import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RouteWithID } from '../../../../../plugins/datasource/alertmanager/types'; import { AlertmanagerProvider } from '../../state/AlertmanagerContext'; diff --git a/public/app/features/alerting/unified/components/notification-policies/Policy.tsx b/public/app/features/alerting/unified/components/notification-policies/Policy.tsx index 346a9de008e..ff037ca21f2 100644 --- a/public/app/features/alerting/unified/components/notification-policies/Policy.tsx +++ b/public/app/features/alerting/unified/components/notification-policies/Policy.tsx @@ -32,7 +32,7 @@ import { Receiver, RouteWithID, } from 'app/plugins/datasource/alertmanager/types'; -import { ReceiversState } from 'app/types'; +import { ReceiversState } from 'app/types/alerting'; import { AlertmanagerAction, useAlertmanagerAbilities, useAlertmanagerAbility } from '../../hooks/useAbilities'; import { getAmMatcherFormatter } from '../../utils/alertmanager'; diff --git a/public/app/features/alerting/unified/components/notification-policies/permissions.ts b/public/app/features/alerting/unified/components/notification-policies/permissions.ts index c685357df3e..bcbcae681ab 100644 --- a/public/app/features/alerting/unified/components/notification-policies/permissions.ts +++ b/public/app/features/alerting/unified/components/notification-policies/permissions.ts @@ -1,4 +1,4 @@ -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; /** * List of granular permissions that allow viewing notification policies diff --git a/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.test.tsx b/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.test.tsx index 08fb0f52c8e..89b8886fb4e 100644 --- a/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.test.tsx +++ b/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.test.tsx @@ -9,8 +9,8 @@ import * as analytics from '../../Analytics'; import { NewRuleFromPanelButton } from './NewRuleFromPanelButton'; -jest.mock('app/types', () => { - const original = jest.requireActual('app/types'); +jest.mock('app/types/store', () => { + const original = jest.requireActual('app/types/store'); return { ...original, useSelector: jest.fn(), diff --git a/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx b/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx index 714f42a9a8a..ccd057e4526 100644 --- a/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx +++ b/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx @@ -6,7 +6,7 @@ import { Trans, t } from '@grafana/i18n'; import { Alert, Button, LinkButton } from '@grafana/ui'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { LogMessages, logInfo } from '../../Analytics'; import { panelToRuleFormValues } from '../../utils/rule-form'; diff --git a/public/app/features/alerting/unified/components/receivers/GlobalConfigForm.tsx b/public/app/features/alerting/unified/components/receivers/GlobalConfigForm.tsx index 12fefb5a4d3..9ec9d6f9b03 100644 --- a/public/app/features/alerting/unified/components/receivers/GlobalConfigForm.tsx +++ b/public/app/features/alerting/unified/components/receivers/GlobalConfigForm.tsx @@ -4,7 +4,7 @@ import { Trans, t } from '@grafana/i18n'; import { Alert, Button, LinkButton, Stack } from '@grafana/ui'; import { useCleanup } from 'app/core/hooks/useCleanup'; import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector'; import { updateAlertManagerConfigAction } from '../../state/actions'; diff --git a/public/app/features/alerting/unified/components/receivers/NewReceiverView.test.tsx b/public/app/features/alerting/unified/components/receivers/NewReceiverView.test.tsx index 3929c478053..e1a1aa5aeba 100644 --- a/public/app/features/alerting/unified/components/receivers/NewReceiverView.test.tsx +++ b/public/app/features/alerting/unified/components/receivers/NewReceiverView.test.tsx @@ -3,7 +3,7 @@ import { render, screen } from 'test/test-utils'; import { byLabelText, byPlaceholderText, byRole, byTestId } from 'testing-library-selector'; import { captureRequests } from 'app/features/alerting/unified/mocks/server/events'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../../mockApi'; import { grantUserPermissions } from '../../mocks'; diff --git a/public/app/features/alerting/unified/components/receivers/form/ChannelOptions.tsx b/public/app/features/alerting/unified/components/receivers/form/ChannelOptions.tsx index e402c4f8875..e65dd9f0f38 100644 --- a/public/app/features/alerting/unified/components/receivers/form/ChannelOptions.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/ChannelOptions.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { DeepMap, FieldError, FieldErrors, useFormContext } from 'react-hook-form'; import { Field, SecretInput } from '@grafana/ui'; -import { NotificationChannelOption, NotificationChannelSecureFields, OptionMeta } from 'app/types'; +import { NotificationChannelOption, NotificationChannelSecureFields, OptionMeta } from 'app/types/alerting'; import { ChannelValues, diff --git a/public/app/features/alerting/unified/components/receivers/form/ChannelSubForm.tsx b/public/app/features/alerting/unified/components/receivers/form/ChannelSubForm.tsx index 7e47f08b5a2..93dfa812d85 100644 --- a/public/app/features/alerting/unified/components/receivers/form/ChannelSubForm.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/ChannelSubForm.tsx @@ -7,7 +7,7 @@ import { Controller, FieldErrors, useFormContext } from 'react-hook-form'; import { GrafanaTheme2, SelectableValue } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Alert, Button, Field, Select, Stack, Text, useStyles2 } from '@grafana/ui'; -import { NotificationChannelOption } from 'app/types'; +import { NotificationChannelOption } from 'app/types/alerting'; import { useUnifiedAlertingSelector } from '../../../hooks/useUnifiedAlertingSelector'; import { diff --git a/public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.test.tsx b/public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.test.tsx index 937c64f4afb..af23e5dc423 100644 --- a/public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.test.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.test.tsx @@ -13,7 +13,7 @@ import { import { AlertmanagerProvider } from 'app/features/alerting/unified/state/AlertmanagerContext'; import { SupportedPlugin } from 'app/features/alerting/unified/types/pluginBridges'; import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { AlertmanagerConfigBuilder, setupMswServer } from '../../../mockApi'; import { grantUserPermissions } from '../../../mocks'; diff --git a/public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.tsx b/public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.tsx index 5a7a4d72d4b..44da5c3588b 100644 --- a/public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.tsx @@ -15,7 +15,7 @@ import { GrafanaManagedReceiverConfig, TestReceiversAlert, } from 'app/plugins/datasource/alertmanager/types'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { alertmanagerApi } from '../../../api/alertmanagerApi'; import { testReceiversAction } from '../../../state/actions'; diff --git a/public/app/features/alerting/unified/components/receivers/form/fields/OptionField.tsx b/public/app/features/alerting/unified/components/receivers/form/fields/OptionField.tsx index 62db9294dc3..4bad7a8639f 100644 --- a/public/app/features/alerting/unified/components/receivers/form/fields/OptionField.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/fields/OptionField.tsx @@ -14,7 +14,7 @@ import { TextArea, useStyles2, } from '@grafana/ui'; -import { NotificationChannelOption, NotificationChannelSecureFields, OptionMeta } from 'app/types'; +import { NotificationChannelOption, NotificationChannelSecureFields, OptionMeta } from 'app/types/alerting'; import { KeyValueMapInput } from './KeyValueMapInput'; import { StringArrayInput } from './StringArrayInput'; diff --git a/public/app/features/alerting/unified/components/receivers/form/fields/SubformArrayField.tsx b/public/app/features/alerting/unified/components/receivers/form/fields/SubformArrayField.tsx index 00533179299..02177df1bae 100644 --- a/public/app/features/alerting/unified/components/receivers/form/fields/SubformArrayField.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/fields/SubformArrayField.tsx @@ -3,7 +3,7 @@ import { DeepMap, FieldError, useFormContext } from 'react-hook-form'; import { Trans, t } from '@grafana/i18n'; import { Button, useStyles2 } from '@grafana/ui'; import { useControlledFieldArray } from 'app/features/alerting/unified/hooks/useControlledFieldArray'; -import { NotificationChannelOption, NotificationChannelSecureFields, OptionMeta } from 'app/types'; +import { NotificationChannelOption, NotificationChannelSecureFields, OptionMeta } from 'app/types/alerting'; import { ActionIcon } from '../../../rules/ActionIcon'; import { CollapsibleSection } from '../CollapsibleSection'; diff --git a/public/app/features/alerting/unified/components/receivers/form/fields/SubformField.tsx b/public/app/features/alerting/unified/components/receivers/form/fields/SubformField.tsx index e836f4522f8..32118e6bc4c 100644 --- a/public/app/features/alerting/unified/components/receivers/form/fields/SubformField.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/fields/SubformField.tsx @@ -3,7 +3,7 @@ import { DeepMap, FieldError, useFormContext } from 'react-hook-form'; import { Trans, t } from '@grafana/i18n'; import { Button, useStyles2 } from '@grafana/ui'; -import { NotificationChannelOption, NotificationChannelSecureFields, OptionMeta } from 'app/types'; +import { NotificationChannelOption, NotificationChannelSecureFields, OptionMeta } from 'app/types/alerting'; import { ActionIcon } from '../../../rules/ActionIcon'; diff --git a/public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.test.tsx b/public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.test.tsx index e8a58495887..74f574ac549 100644 --- a/public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.test.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.test.tsx @@ -9,7 +9,8 @@ import { AlertmanagerProvider } from 'app/features/alerting/unified/state/Alertm import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource'; import { PROVENANCE_NONE } from 'app/features/alerting/unified/utils/k8s/constants'; import { DEFAULT_TEMPLATES } from 'app/features/alerting/unified/utils/template-constants'; -import { AccessControlAction, NotificationChannelOption } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { NotificationChannelOption } from 'app/types/alerting'; import { TemplatesPicker, getTemplateOptions } from './TemplateSelector'; import { parseTemplates } from './utils'; diff --git a/public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.tsx b/public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.tsx index de3cd0e3503..6cfea24cd83 100644 --- a/public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.tsx +++ b/public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.tsx @@ -28,7 +28,7 @@ import { useNotificationTemplates, } from 'app/features/alerting/unified/components/contact-points/useNotificationTemplates'; import { useAlertmanager } from 'app/features/alerting/unified/state/AlertmanagerContext'; -import { NotificationChannelOption } from 'app/types'; +import { NotificationChannelOption } from 'app/types/alerting'; import { defaultPayloadString } from '../../TemplateForm'; diff --git a/public/app/features/alerting/unified/components/receivers/form/notifiers.ts b/public/app/features/alerting/unified/components/receivers/form/notifiers.ts index 15baf45aabe..d84e8bc2f9d 100644 --- a/public/app/features/alerting/unified/components/receivers/form/notifiers.ts +++ b/public/app/features/alerting/unified/components/receivers/form/notifiers.ts @@ -1,6 +1,6 @@ import { ReactElement } from 'react'; -import { NotifierDTO } from '../../../../../../types'; +import { NotifierDTO } from 'app/types/alerting'; export interface NotifierMetadata { enabled: boolean; diff --git a/public/app/features/alerting/unified/components/receivers/grafanaAppReceivers/onCall/useOnCallIntegration.tsx b/public/app/features/alerting/unified/components/receivers/grafanaAppReceivers/onCall/useOnCallIntegration.tsx index b30545e604b..2f84d394b9f 100644 --- a/public/app/features/alerting/unified/components/receivers/grafanaAppReceivers/onCall/useOnCallIntegration.tsx +++ b/public/app/features/alerting/unified/components/receivers/grafanaAppReceivers/onCall/useOnCallIntegration.tsx @@ -6,10 +6,10 @@ import { t } from '@grafana/i18n'; import { isFetchError } from '@grafana/runtime'; import { Badge } from '@grafana/ui'; import { getIrmIfPresentOrOnCallPluginId } from 'app/features/alerting/unified/utils/config'; +import { NotifierDTO } from 'app/types/alerting'; import { useAppNotification } from '../../../../../../../core/copy/appNotification'; import { Receiver } from '../../../../../../../plugins/datasource/alertmanager/types'; -import { NotifierDTO } from '../../../../../../../types'; import { ONCALL_INTEGRATION_V2_FEATURE, onCallApi } from '../../../../api/onCallApi'; import { usePluginBridge } from '../../../../hooks/usePluginBridge'; import { option } from '../../../../utils/notifier-types'; diff --git a/public/app/features/alerting/unified/components/rule-editor/DashboardAnnotationField.tsx b/public/app/features/alerting/unified/components/rule-editor/DashboardAnnotationField.tsx index ee9992d4f1b..26d32af3104 100644 --- a/public/app/features/alerting/unified/components/rule-editor/DashboardAnnotationField.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/DashboardAnnotationField.tsx @@ -3,7 +3,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { Icon, Text, useStyles2 } from '@grafana/ui'; -import { DashboardDataDTO } from 'app/types'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { makeDashboardLink, makePanelLink } from '../../utils/misc'; diff --git a/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/SimplifiedRuleEditor.test.tsx b/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/SimplifiedRuleEditor.test.tsx index c2d7fd5b240..d56b5b5ea01 100644 --- a/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/SimplifiedRuleEditor.test.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/SimplifiedRuleEditor.test.tsx @@ -17,7 +17,7 @@ import { setupDataSources } from 'app/features/alerting/unified/testSetup/dataso import { DataSourceType } from 'app/features/alerting/unified/utils/datasource'; import { MANUAL_ROUTING_KEY, SIMPLIFIED_QUERY_EDITOR_KEY } from 'app/features/alerting/unified/utils/rule-form'; import { AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { grafanaRulerGroup } from '../../../../mocks/grafanaRulerApi'; diff --git a/public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/utils.ts b/public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/utils.ts index 6ad5dac7d73..138db1979bf 100644 --- a/public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/utils.ts +++ b/public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/utils.ts @@ -2,7 +2,7 @@ import { DataSourceInstanceSettings } from '@grafana/data'; import { DataSourceJsonData } from '@grafana/schema/dist/esm/index'; import { contextSrv } from 'app/core/core'; import { ExpressionDatasourceUID } from 'app/features/expressions/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { AlertQuery } from 'app/types/unified-alerting-dto'; import { RuleFormType } from '../../../types/rule-form'; diff --git a/public/app/features/alerting/unified/components/rule-editor/useDashboardQuery.ts b/public/app/features/alerting/unified/components/rule-editor/useDashboardQuery.ts index 27bfb98c6a8..bf84e8eb110 100644 --- a/public/app/features/alerting/unified/components/rule-editor/useDashboardQuery.ts +++ b/public/app/features/alerting/unified/components/rule-editor/useDashboardQuery.ts @@ -1,6 +1,7 @@ import memoizeOne from 'memoize-one'; -import { DashboardDTO } from '../../../../../types'; +import { DashboardDTO } from 'app/types/dashboard'; + import { DashboardModel } from '../../../../dashboard/state/DashboardModel'; import { dashboardApi } from '../../api/dashboardApi'; diff --git a/public/app/features/alerting/unified/components/rule-viewer/AlertRuleMenu.tsx b/public/app/features/alerting/unified/components/rule-viewer/AlertRuleMenu.tsx index 77e751238cf..0ad498ebc65 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/AlertRuleMenu.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/AlertRuleMenu.tsx @@ -7,7 +7,7 @@ import appEvents from 'app/core/app_events'; import MenuItemPauseRule from 'app/features/alerting/unified/components/MenuItemPauseRule'; import MoreButton from 'app/features/alerting/unified/components/MoreButton'; import { useRulePluginLinkExtension } from 'app/features/alerting/unified/plugins/useRulePluginLinkExtensions'; -import { Rule, RuleGroupIdentifierV2, RuleIdentifier } from 'app/types/unified-alerting'; +import { EditableRuleIdentifier, Rule, RuleGroupIdentifierV2, RuleIdentifier } from 'app/types/unified-alerting'; import { PromAlertingRuleState, RulerRuleDTO } from 'app/types/unified-alerting-dto'; import { @@ -18,7 +18,13 @@ import { } from '../../hooks/useAbilities'; import { createShareLink, isLocalDevEnv, isOpenSourceEdition } from '../../utils/misc'; import * as ruleId from '../../utils/rule-id'; -import { prometheusRuleType, rulerRuleType } from '../../utils/rules'; +import { + getRuleUID, + isEditableRuleIdentifier, + isPausedRule, + prometheusRuleType, + rulerRuleType, +} from '../../utils/rules'; import { createRelativeUrl } from '../../utils/url'; import { DeclareIncidentMenuItem } from '../bridges/DeclareIncidentButton'; @@ -28,7 +34,7 @@ interface Props { identifier: RuleIdentifier; groupIdentifier: RuleGroupIdentifierV2; handleSilence: () => void; - handleDelete: (rule: RulerRuleDTO, groupIdentifier: RuleGroupIdentifierV2) => void; + handleDelete: (identifier: EditableRuleIdentifier, groupIdentifier: RuleGroupIdentifierV2) => void; handleDuplicateRule: (identifier: RuleIdentifier) => void; onPauseChange?: () => void; buttonSize?: ComponentSize; @@ -118,10 +124,22 @@ const AlertRuleMenu = ({ const showDivider = [canPause, canSilence, shouldShowDeclareIncidentButton, canDuplicate].some(Boolean) && [canExport].some(Boolean); + // grab the UID from either rulerRule or promRule + const ruleUid = getRuleUID(rulerRule ?? promRule); + + const isPaused = + (rulerRuleType.grafana.rule(rulerRule) && isPausedRule(rulerRule)) || + (prometheusRuleType.grafana.rule(promRule) && promRule.isPaused); + const menuItems = ( <> - {canPause && rulerRuleType.grafana.rule(rulerRule) && groupIdentifier.groupOrigin === 'grafana' && ( - + {canPause && ruleUid && groupIdentifier.groupOrigin === 'grafana' && ( + )} {canSilence && ( )} - {canDelete && rulerRule && ( + {canDelete && ( <> handleDelete(rulerRule, groupIdentifier)} + onClick={() => { + // if the identifier is not for a editable rule I wonder how you even got here. + if (isEditableRuleIdentifier(identifier)) { + handleDelete(identifier, groupIdentifier); + } + }} /> )} diff --git a/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx b/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx index a3125ccca53..cf642620c14 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx @@ -5,7 +5,7 @@ import { byLabelText, byRole, byText } from 'testing-library-selector'; import { setPluginLinksHook } from '@grafana/runtime'; import { setupMswServer } from 'app/features/alerting/unified/mockApi'; import { AlertManagerDataSourceJsonData } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { CombinedRule, RuleIdentifier } from 'app/types/unified-alerting'; import { diff --git a/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx b/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx index 5a4b4da2178..7a3f89a2526 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx @@ -40,10 +40,10 @@ import { useRuleGroupConsistencyCheck } from '../../hooks/usePrometheusConsisten import { useReturnTo } from '../../hooks/useReturnTo'; import { PluginOriginBadge } from '../../plugins/PluginOriginBadge'; import { Annotation } from '../../utils/constants'; -import { ruleIdentifierToRuleSourceIdentifier } from '../../utils/datasource'; +import { getRulesSourceUid, ruleIdentifierToRuleSourceIdentifier } from '../../utils/datasource'; import { labelsSize } from '../../utils/labels'; import { makeDashboardLink, makePanelLink, stringifyErrorLike } from '../../utils/misc'; -import { createListFilterLink } from '../../utils/navigation'; +import { createListFilterLink, groups } from '../../utils/navigation'; import { RulePluginOrigin, getRulePluginOrigin, @@ -422,6 +422,11 @@ function usePageNav(rule: CombinedRule) { const isGrafanaRecordingRule = rulerRuleType.grafana.recordingRule(rulerRule); const isRecordingRuleType = prometheusRuleType.recordingRule(promRule); + const dataSourceUID = getRulesSourceUid(rule.namespace.rulesSource); + const namespaceString = getNamespaceString(rule); + + const groupDetailsUrl = groups.detailsPageLink(dataSourceUID, namespaceString, groupName); + const pageNav: NavModelItem = { ...defaultPageNav, text: rule.name, @@ -470,10 +475,7 @@ function usePageNav(rule: CombinedRule) { ], parentItem: { text: groupName, - url: createListFilterLink([ - ['namespace', namespaceName], - ['group', groupName], - ]), + url: groupDetailsUrl, // @TODO support nested folders here parentItem: { text: namespaceName, @@ -523,4 +525,33 @@ function isValidRunbookURL(url: string) { return isRelative || isAbsolute; } +function getNamespaceString(rule: CombinedRule): string { + // try rule.namespace.uid + if (rule.namespace.uid) { + return rule.namespace.uid; + } + + // if datasource managed, use rule.namespace.name; + const isDataSourceManagedRulerRule = rulerRuleType.dataSource.rule(rule.rulerRule); + const isDataSourceManagedPromRule = + prometheusRuleType.rule(rule.promRule) && !prometheusRuleType.grafana.rule(rule.promRule); + + if (isDataSourceManagedRulerRule || isDataSourceManagedPromRule) { + return rule.namespace.name; + } + + // try rulerRule definition if grafana ruler rule; + if (rulerRuleType.grafana.rule(rule.rulerRule)) { + return rule.rulerRule?.grafana_alert.namespace_uid; + } + + // try promRule definition if grafana prom rule; + if (prometheusRuleType.grafana.rule(rule.promRule)) { + return rule.promRule.folderUid; + } + + // fell back to whatever the name is of the namespace assigned to the combined rule + return rule.namespace.name; +} + export default RuleViewer; diff --git a/public/app/features/alerting/unified/components/rules/Filter/RulesFilter.v1.tsx b/public/app/features/alerting/unified/components/rules/Filter/RulesFilter.v1.tsx index 61dc5f119e7..ca70ddaa984 100644 --- a/public/app/features/alerting/unified/components/rules/Filter/RulesFilter.v1.tsx +++ b/public/app/features/alerting/unified/components/rules/Filter/RulesFilter.v1.tsx @@ -8,7 +8,7 @@ import { Trans, t } from '@grafana/i18n'; import { Button, Field, Icon, Input, Label, RadioButtonGroup, Stack, Tooltip, useStyles2 } from '@grafana/ui'; import { DashboardPicker } from 'app/core/components/Select/DashboardPicker'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PromAlertingRuleState, PromRuleType } from 'app/types/unified-alerting-dto'; import { diff --git a/public/app/features/alerting/unified/components/rules/RuleActionsButtons.test.tsx b/public/app/features/alerting/unified/components/rules/RuleActionsButtons.test.tsx index 57725b1975b..5de673ccb14 100644 --- a/public/app/features/alerting/unified/components/rules/RuleActionsButtons.test.tsx +++ b/public/app/features/alerting/unified/components/rules/RuleActionsButtons.test.tsx @@ -15,7 +15,7 @@ import { mockPromAlertingRule, } from 'app/features/alerting/unified/mocks'; import { MIMIR_DATASOURCE_UID } from 'app/features/alerting/unified/mocks/server/constants'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PromAlertingRuleState } from 'app/types/unified-alerting-dto'; import { setupDataSources } from '../../testSetup/datasources'; diff --git a/public/app/features/alerting/unified/components/rules/RuleActionsButtons.tsx b/public/app/features/alerting/unified/components/rules/RuleActionsButtons.tsx index 9e4d8c25a46..c6bcd640657 100644 --- a/public/app/features/alerting/unified/components/rules/RuleActionsButtons.tsx +++ b/public/app/features/alerting/unified/components/rules/RuleActionsButtons.tsx @@ -1,3 +1,4 @@ +import { isString } from 'lodash'; import { useState } from 'react'; import { Trans, t } from '@grafana/i18n'; @@ -7,7 +8,7 @@ import { useDeleteModal } from 'app/features/alerting/unified/components/rule-vi import { INSTANCES_DISPLAY_LIMIT } from 'app/features/alerting/unified/components/rules/RuleDetails'; import SilenceGrafanaRuleDrawer from 'app/features/alerting/unified/components/silences/SilenceGrafanaRuleDrawer'; import { useRulesFilter } from 'app/features/alerting/unified/hooks/useFilteredRules'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { CombinedRule, RuleIdentifier, RulesSource } from 'app/types/unified-alerting'; import { AlertRuleAction, useAlertRuleAbility } from '../../hooks/useAbilities'; @@ -16,7 +17,7 @@ import { GRAFANA_RULES_SOURCE_NAME, getRulesSourceName } from '../../utils/datas import { groupIdentifier } from '../../utils/groupIdentifier'; import { createViewLink } from '../../utils/misc'; import * as ruleId from '../../utils/rule-id'; -import { rulerRuleType } from '../../utils/rules'; +import { getRuleUID, prometheusRuleType, rulerRuleType } from '../../utils/rules'; import { createRelativeUrl } from '../../utils/url'; import { RedirectToCloneRule } from './CloneRule'; @@ -104,6 +105,12 @@ export const RuleActionsButtons = ({ compact, showViewButton, rule, rulesSource return null; } + // determine if this rule can be silenced by checking for Grafana Alert rule type and extracting the UID + const ruleUid = getRuleUID(rule.rulerRule ?? rule.promRule); + const silenceableRule = + isString(ruleUid) && + (rulerRuleType.grafana.alertingRule(rule.rulerRule) || prometheusRuleType.grafana.alertingRule(rule.promRule)); + return ( {buttons} @@ -132,8 +139,8 @@ export const RuleActionsButtons = ({ compact, showViewButton, rule, rulesSource buttonSize={buttonSize} /> {deleteModal} - {rulerRuleType.grafana.alertingRule(rule.rulerRule) && showSilenceDrawer && ( - setShowSilenceDrawer(false)} /> + {silenceableRule && showSilenceDrawer && ( + setShowSilenceDrawer(false)} /> )} {redirectToClone?.identifier && ( void; }; @@ -17,32 +16,26 @@ type Props = { * For a given Grafana managed rule, renders a drawer containing silences editor and Alertmanager selection */ const SilenceGrafanaRuleDrawer = React.memo( - ({ rulerRule, onClose }: Props) => { - const { uid } = rulerRule.grafana_alert; - - return ( - - - - - - - - ); - }, - (prevProps, nextProps) => { - return prevProps.rulerRule.grafana_alert.uid === nextProps.rulerRule.grafana_alert.uid; - } + ({ ruleUid, onClose }: Props) => ( + + + + + + + + ), + (prevProps, nextProps) => prevProps.ruleUid === nextProps.ruleUid ); export default SilenceGrafanaRuleDrawer; diff --git a/public/app/features/alerting/unified/components/templates/permissions.ts b/public/app/features/alerting/unified/components/templates/permissions.ts index a92758f1a1d..82bef452e94 100644 --- a/public/app/features/alerting/unified/components/templates/permissions.ts +++ b/public/app/features/alerting/unified/components/templates/permissions.ts @@ -1,4 +1,4 @@ -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; /** * List of all permissions that allow templates read/write functionality diff --git a/public/app/features/alerting/unified/group-details/GroupDetailsPage.test.tsx b/public/app/features/alerting/unified/group-details/GroupDetailsPage.test.tsx index a1606965fd2..90485290325 100644 --- a/public/app/features/alerting/unified/group-details/GroupDetailsPage.test.tsx +++ b/public/app/features/alerting/unified/group-details/GroupDetailsPage.test.tsx @@ -1,13 +1,16 @@ -import { HttpResponse } from 'msw'; +import { uniqueId } from 'lodash'; +import { HttpResponse, http } from 'msw'; import { Route, Routes } from 'react-router-dom-v5-compat'; import { Props } from 'react-virtualized-auto-sizer'; import { render, screen, waitFor, within } from 'test/test-utils'; import { byRole, byTestId } from 'testing-library-selector'; -import { AccessControlAction } from 'app/types'; +import { setPluginLinksHook } from '@grafana/runtime'; +import { AccessControlAction } from 'app/types/accessControl'; +import { GrafanaPromRuleGroupDTO, GrafanaPromRulesResponse } from 'app/types/unified-alerting-dto'; import { setupMswServer } from '../mockApi'; -import { grantUserPermissions, mockRulerGrafanaRule, mockRulerRuleGroup } from '../mocks'; +import { grantUserPermissions, mockGrafanaPromAlertingRule, mockRulerGrafanaRule, mockRulerRuleGroup } from '../mocks'; import { mimirDataSource, setFolderResponse, @@ -38,8 +41,7 @@ const ui = { header: byRole('heading', { level: 1 }), editLink: byRole('link', { name: 'Edit' }), exportButton: byRole('button', { name: 'Export' }), - tableRow: byTestId('row'), - rowsTable: byTestId('dynamic-table'), + ruleItem: byRole('treeitem'), export: { dialog: byRole('dialog', { name: /Drawer title Export .* rules/ }), jsonTab: byRole('tab', { name: /JSON/ }), @@ -50,10 +52,16 @@ const ui = { }, }; -setupMswServer(); +const server = setupMswServer(); describe('GroupDetailsPage', () => { beforeEach(() => { + // mock this... + setPluginLinksHook(() => ({ + links: [], + isLoading: false, + })); + grantUserPermissions([ AccessControlAction.AlertingRuleRead, AccessControlAction.AlertingRuleUpdate, @@ -63,25 +71,71 @@ describe('GroupDetailsPage', () => { }); describe('Grafana managed rules', () => { - const rule1 = mockRulerGrafanaRule({ for: '10m' }, { title: 'High CPU Usage' }); - const rule2 = mockRulerGrafanaRule({ for: '5m' }, { title: 'Memory Pressure' }); - const provisionedRule = mockRulerGrafanaRule({ for: '10m' }, { title: 'Provisioned Rule', provenance: 'api' }); + const folder = { uid: 'test-folder-uid', canSave: true, title: 'test-folder-title' } as const; + + const rule1 = mockRulerGrafanaRule({ for: '10m' }, { title: 'High CPU Usage', uid: uniqueId() }); + const rule2 = mockRulerGrafanaRule({ for: '5m' }, { title: 'Memory Pressure', uid: uniqueId() }); + + const provisionedRule = mockRulerGrafanaRule( + { for: '10m' }, + { uid: uniqueId(), title: 'Provisioned Rule', provenance: 'api' } + ); const group = mockRulerRuleGroup({ name: 'test-group-cpu', interval: '3m', rules: [rule1, rule2], }); + const promGroup: GrafanaPromRuleGroupDTO = { + name: group.name, + rules: [ + mockGrafanaPromAlertingRule({ + uid: rule1.grafana_alert.uid, + name: rule1.grafana_alert.title, + }), + mockGrafanaPromAlertingRule({ + uid: rule2.grafana_alert.uid, + name: rule2.grafana_alert.title, + }), + ], + interval: 180, + folderUid: folder.uid, + file: folder.title, + }; const provisionedGroup = mockRulerRuleGroup({ name: 'provisioned-group-cpu', interval: '15m', rules: [provisionedRule], }); + const promProvisionedGroup: GrafanaPromRuleGroupDTO = { + name: provisionedGroup.name, + interval: 900, + rules: [ + mockGrafanaPromAlertingRule({ + uid: provisionedRule.grafana_alert.uid, + name: provisionedRule.grafana_alert.title, + provenance: provisionedRule.grafana_alert.provenance, + }), + ], + folderUid: folder.uid, + file: folder.title, + }; beforeEach(() => { setRulerRuleGroupHandler({ response: HttpResponse.json(group) }); - setFolderResponse({ uid: 'test-folder-uid', canSave: true, title: 'test-folder-title' }); + server.use( + http.get('/api/prometheus/grafana/api/v1/rules', () => + HttpResponse.json({ + status: 'success', + data: { + groups: [promGroup], + }, + }) + ) + ); + + setFolderResponse(folder); setGrafanaRuleGroupExportResolver(({ request }) => { const url = new URL(request.url); return HttpResponse.text( @@ -106,22 +160,24 @@ describe('GroupDetailsPage', () => { '/alerting/grafana/namespaces/test-folder-uid/groups/test-group-cpu/edit?returnTo=%2Falerting%2Fgrafana%2Fnamespaces%2Ftest-folder-uid%2Fgroups%2Ftest-group-cpu%2Fview' ); - const tableRows = await ui.tableRow.findAll(await ui.rowsTable.find()); - expect(tableRows).toHaveLength(2); + expect(await screen.findByRole('treeitem', { name: rule1.grafana_alert.title })).toBeInTheDocument(); - expect(within(tableRows[0]).getByRole('link', { name: rule1.grafana_alert.title })).toHaveAttribute( + const alertRuleItems = await ui.ruleItem.findAll(); + expect(alertRuleItems).toHaveLength(2); + + // assert rule 1 + expect(within(alertRuleItems[0]).getByRole('link', { name: rule1.grafana_alert.title })).toHaveAttribute( 'href', `/alerting/grafana/${rule1.grafana_alert.uid}/view` ); - expect(tableRows[0]).toHaveTextContent(String(rule1.for)); - expect(tableRows[0]).toHaveTextContent('5'); + expect(alertRuleItems[0]).toHaveTextContent(rule1.grafana_alert.title); - expect(within(tableRows[1]).getByRole('link', { name: rule2.grafana_alert.title })).toHaveAttribute( + // assert rule 2 + expect(within(alertRuleItems[1]).getByRole('link', { name: rule2.grafana_alert.title })).toHaveAttribute( 'href', `/alerting/grafana/${rule2.grafana_alert.uid}/view` ); - expect(tableRows[1]).toHaveTextContent(String(rule2.for)); - expect(tableRows[1]).toHaveTextContent('3'); + expect(alertRuleItems[1]).toHaveTextContent(rule2.grafana_alert.title); }); it('should render error alert when API returns an error', async () => { @@ -164,10 +220,12 @@ describe('GroupDetailsPage', () => { // Act renderGroupDetailsPage('grafana', 'test-folder-uid', group.name); - const tableRows = await ui.tableRow.findAll(await ui.rowsTable.find()); + // Wait until rule items are rendered + expect(await screen.findByRole('treeitem', { name: rule1.grafana_alert.title })).toBeInTheDocument(); + const alertRuleItems = ui.ruleItem.getAll(); // Assert - expect(tableRows).toHaveLength(2); + expect(alertRuleItems).toHaveLength(2); expect(ui.editLink.query()).not.toBeInTheDocument(); // Edit button should not be present }); @@ -177,24 +235,39 @@ describe('GroupDetailsPage', () => { // Act renderGroupDetailsPage('grafana', 'test-folder-uid', group.name); - const tableRows = await ui.tableRow.findAll(await ui.rowsTable.find()); + // wait for rule items to render + expect(await screen.findByRole('treeitem', { name: rule1.grafana_alert.title })).toBeInTheDocument(); + + const alertRuleItems = await ui.ruleItem.findAll(); // Assert - expect(tableRows).toHaveLength(2); + expect(alertRuleItems).toHaveLength(2); expect(ui.editLink.query()).not.toBeInTheDocument(); // Edit button should not be present }); it('should not allow editing if the group is provisioned', async () => { setRulerRuleGroupHandler({ response: HttpResponse.json(provisionedGroup) }); + server.use( + http.get('/api/prometheus/grafana/api/v1/rules', () => + HttpResponse.json({ + status: 'success', + data: { + groups: [promProvisionedGroup], + }, + }) + ) + ); // Act renderGroupDetailsPage('grafana', 'test-folder-uid', provisionedGroup.name); + // wait for rule items to render + expect(await screen.findByRole('treeitem', { name: provisionedRule.grafana_alert.title })).toBeInTheDocument(); - const tableRows = await ui.tableRow.findAll(await ui.rowsTable.find()); + const alertRuleItems = await ui.ruleItem.findAll(); // Assert - expect(tableRows).toHaveLength(1); - expect(tableRows[0]).toHaveTextContent('Provisioned Rule'); + expect(alertRuleItems).toHaveLength(1); + expect(alertRuleItems[0]).toHaveTextContent('Provisioned Rule'); expect(ui.editLink.query()).not.toBeInTheDocument(); expect(ui.exportButton.query()).toBeInTheDocument(); }); diff --git a/public/app/features/alerting/unified/group-details/GroupDetailsPage.tsx b/public/app/features/alerting/unified/group-details/GroupDetailsPage.tsx index f05e9c1a19d..997b1bd44b7 100644 --- a/public/app/features/alerting/unified/group-details/GroupDetailsPage.tsx +++ b/public/app/features/alerting/unified/group-details/GroupDetailsPage.tsx @@ -1,35 +1,28 @@ import { skipToken } from '@reduxjs/toolkit/query'; -import { useMemo, useState } from 'react'; +import { useState } from 'react'; import { useParams } from 'react-router-dom-v5-compat'; import { Trans, t } from '@grafana/i18n'; -import { Alert, Badge, Button, LinkButton, Text, TextLink, withErrorBoundary } from '@grafana/ui'; +import { Alert, Button, Dropdown, Icon, LinkButton, Menu, TextLink, withErrorBoundary } from '@grafana/ui'; import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound'; -import { FolderDTO } from 'app/types'; -import { GrafanaRulesSourceSymbol, RuleGroup } from 'app/types/unified-alerting'; -import { PromRuleType, RulerRuleGroupDTO } from 'app/types/unified-alerting-dto'; +import { FolderDTO } from 'app/types/folders'; +import { GrafanaRulesSourceSymbol } from 'app/types/unified-alerting'; +import { RulerRuleGroupDTO } from 'app/types/unified-alerting-dto'; import { alertRuleApi } from '../api/alertRuleApi'; import { RulesSourceFeatures, featureDiscoveryApi } from '../api/featureDiscoveryApi'; import { AlertingPageWrapper } from '../components/AlertingPageWrapper'; -import { DynamicTable, DynamicTableColumnProps } from '../components/DynamicTable'; import { GrafanaRuleGroupExporter } from '../components/export/GrafanaRuleGroupExporter'; import { useFolder } from '../hooks/useFolder'; import { DEFAULT_GROUP_EVALUATION_INTERVAL } from '../rule-editor/formDefaults'; -import { createViewLinkFromIdentifier } from '../rule-list/DataSourceRuleListItem'; +import { DataSourceGroupLoader } from '../rule-list/DataSourceGroupLoader'; +import { GrafanaGroupLoader } from '../rule-list/GrafanaGroupLoader'; import { useRulesAccess } from '../utils/accessControlHooks'; import { GRAFANA_RULES_SOURCE_NAME, getDataSourceByUid } from '../utils/datasource'; import { makeFolderLink, stringifyErrorLike } from '../utils/misc'; import { createListFilterLink, groups } from '../utils/navigation'; -import { fromRule, fromRulerRule } from '../utils/rule-id'; -import { - calcRuleEvalsToStartAlerting, - getRuleName, - isFederatedRuleGroup, - isProvisionedRuleGroup, - rulerRuleType, -} from '../utils/rules'; -import { formatPrometheusDuration, safeParsePrometheusDuration } from '../utils/time'; +import { isFederatedRuleGroup, isProvisionedRuleGroup } from '../utils/rules'; +import { formatPrometheusDuration } from '../utils/time'; import { Title } from './Title'; @@ -111,6 +104,7 @@ function GroupDetailsPage() { }, }} renderTitle={(title) => } + subTitle={t('alerting.titles.group-view.subtitle', 'Manage alert rules, recording rules and evaluation interval')} info={[ { label: namespaceLabel, value: namespaceValue }, { label: t('alerting.group-details.interval', 'Interval'), value: groupInterval }, @@ -150,13 +144,33 @@ function GroupDetailsPage() { <div>{stringifyErrorLike(ruleNamespacesError || ruleGroupError)}</div> </Alert> )} - {promGroup && ruleSourceName && ( - <GroupDetails group={promRuleGroupToRuleGroupDetails(ruleSourceName, namespaceName, promGroup)} /> - )} - {rulerGroup && ruleSourceName && ( - <GroupDetails group={rulerRuleGroupToRuleGroupDetails(ruleSourceName, namespaceName, rulerGroup)} /> - )} {!promGroup && !rulerGroup && <EntityNotFound entity={`${namespaceId}/${groupName}`} />} + + {ruleSourceName && ( + <ul role="tree"> + {isGrafanaRuleGroup ? ( + <GrafanaGroupLoader + groupIdentifier={{ groupName, groupOrigin: 'grafana', namespace: { uid: namespaceId } }} + namespaceName={namespaceName} + /> + ) : ( + <DataSourceGroupLoader + groupIdentifier={{ + groupName, + groupOrigin: 'datasource', + namespace: { + name: namespaceName, + }, + rulesSource: { + name: ruleSourceName, + uid: dataSourceUid, + ruleSourceType: 'datasource', + }, + }} + /> + )} + </ul> + )} </> </AlertingPageWrapper> ); @@ -195,13 +209,39 @@ function GroupActions({ dsFeatures, namespaceId, groupName, folder, rulerGroup } </Button> )} {canEdit && ( - <LinkButton - icon="pen" - href={groups.editPageLink(dsFeatures.uid, namespaceId, groupName, { includeReturnTo: true })} - variant="secondary" - > - <Trans i18nKey="alerting.group-details.edit">Edit</Trans> - </LinkButton> + <> + <LinkButton + icon="pen" + href={groups.editPageLink(dsFeatures.uid, namespaceId, groupName, { includeReturnTo: true })} + variant="secondary" + > + <Trans i18nKey="alerting.group-details.edit">Edit</Trans> + </LinkButton> + {/* Data source managed requires different URLs, a hassle to implement for now */} + {isGrafanaSource && ( + <Dropdown + overlay={ + <Menu> + <Menu.Item + icon="bell" + url={groups.newAlertRuleLink(folder?.title, folder?.uid, groupName)} + label={t('alerting.alert-rule.term', 'Alert rule')} + /> + <Menu.Item + icon="record-audio" + url={groups.newRecordingRuleLink(folder?.title, folder?.uid, groupName)} + label={t('alerting.recording-rule.term', 'Recording rule')} + /> + </Menu> + } + > + <Button variant="primary"> + {t('alerting.group-details.new', 'New')} + <Icon name="angle-down" /> + </Button> + </Dropdown> + )} + </> )} {folder && isExporting && ( <GrafanaRuleGroupExporter folderUid={folder.uid} groupName={groupName} onClose={() => setIsExporting(false)} /> @@ -210,158 +250,4 @@ function GroupActions({ dsFeatures, namespaceId, groupName, folder, rulerGroup } ); } -/** An common interface for both Prometheus and Ruler rule groups */ -interface RuleGroupDetails { - name: string; - interval: string; - rules: RuleDetails[]; -} - -interface AlertingRuleDetails { - name: string; - href?: string; - type: 'alerting'; - pendingPeriod: string; - evaluationsToFire: number; -} -interface RecordingRuleDetails { - name: string; - href?: string; - type: 'recording'; -} - -type RuleDetails = AlertingRuleDetails | RecordingRuleDetails; - -interface GroupDetailsProps { - group: RuleGroupDetails; -} - -function GroupDetails({ group }: GroupDetailsProps) { - return ( - <div> - <RulesTable rules={group.rules} /> - </div> - ); -} - -function RulesTable({ rules }: { rules: RuleDetails[] }) { - const rows = rules.map((rule: RuleDetails, index) => ({ - id: index, - data: rule, - })); - - const columns: Array<DynamicTableColumnProps<RuleDetails>> = useMemo(() => { - return [ - { - id: 'alertName', - label: t('alerting.group-details.rule-name', 'Rule name'), - renderCell: ({ data: { name, href } }) => { - if (href) { - return ( - <TextLink href={href} inline={false} color="primary"> - {name} - </TextLink> - ); - } - - return <Text truncate>{name}</Text>; - }, - size: 0.4, - }, - { - id: 'for', - label: t('alerting.group-details.pending-period', 'Pending period'), - renderCell: ({ data }) => { - switch (data.type) { - case 'alerting': - return <>{data.pendingPeriod}</>; - case 'recording': - return <Badge text={t('alerting.group-details.recording', 'Recording')} color="purple" />; - } - }, - size: 0.3, - }, - { - id: 'numberEvaluations', - label: t('alerting.group-details.evaluations-to-fire', 'Evaluation cycles to fire'), - renderCell: ({ data }) => { - switch (data.type) { - case 'alerting': - return <>{data.evaluationsToFire}</>; - case 'recording': - return null; - } - }, - size: 0.3, - }, - ]; - }, []); - - return <DynamicTable items={rows} cols={columns} />; -} - -function promRuleGroupToRuleGroupDetails( - ruleSourceName: string, - namespaceName: string, - group: RuleGroup -): RuleGroupDetails { - const groupIntervalMs = group.interval * 1000; - - return { - name: group.name, - interval: formatPrometheusDuration(group.interval * 1000), - rules: group.rules.map<RuleDetails>((rule) => { - const ruleIdentifier = fromRule(ruleSourceName, namespaceName, group.name, rule); - const href = ruleIdentifier ? createViewLinkFromIdentifier(ruleIdentifier) : undefined; - - switch (rule.type) { - case PromRuleType.Alerting: - return { - name: rule.name, - href, - type: 'alerting', - pendingPeriod: formatPrometheusDuration(rule.duration ? rule.duration * 1000 : 0), - evaluationsToFire: calcRuleEvalsToStartAlerting(rule.duration ? rule.duration * 1000 : 0, groupIntervalMs), - }; - case PromRuleType.Recording: - return { name: rule.name, href, type: 'recording' }; - } - }), - }; -} - -function rulerRuleGroupToRuleGroupDetails( - ruleSourceName: string, - namespaceName: string, - group: RulerRuleGroupDTO -): RuleGroupDetails { - const groupIntervalMs = safeParsePrometheusDuration(group.interval ?? DEFAULT_GROUP_EVALUATION_INTERVAL); - - return { - name: group.name, - interval: group.interval ?? DEFAULT_GROUP_EVALUATION_INTERVAL, - rules: group.rules.map<RuleDetails>((rule) => { - const name = getRuleName(rule); - - const ruleIdentifier = fromRulerRule(ruleSourceName, namespaceName, group.name, rule); - const href = createViewLinkFromIdentifier(ruleIdentifier); - - if (rulerRuleType.any.alertingRule(rule)) { - return { - name, - href, - type: 'alerting', - pendingPeriod: rule.for ?? '0s', - evaluationsToFire: calcRuleEvalsToStartAlerting( - rule.for ? safeParsePrometheusDuration(rule.for) : 0, - groupIntervalMs - ), - }; - } - - return { name, href, type: 'recording' }; - }), - }; -} - export default withErrorBoundary(GroupDetailsPage, { style: 'page' }); diff --git a/public/app/features/alerting/unified/group-details/GroupEditPage.test.tsx b/public/app/features/alerting/unified/group-details/GroupEditPage.test.tsx index 2240d26dc55..bafd72ddedd 100644 --- a/public/app/features/alerting/unified/group-details/GroupEditPage.test.tsx +++ b/public/app/features/alerting/unified/group-details/GroupEditPage.test.tsx @@ -5,7 +5,7 @@ import { byRole, byTestId, byText } from 'testing-library-selector'; import { locationService } from '@grafana/runtime'; import { AppNotificationList } from 'app/core/components/AppNotifications/AppNotificationList'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RulerRuleGroupDTO } from 'app/types/unified-alerting-dto'; import { setupMswServer } from '../mockApi'; diff --git a/public/app/features/alerting/unified/group-details/GroupEditPage.tsx b/public/app/features/alerting/unified/group-details/GroupEditPage.tsx index 1a2ece20bc4..a68f230d8cb 100644 --- a/public/app/features/alerting/unified/group-details/GroupEditPage.tsx +++ b/public/app/features/alerting/unified/group-details/GroupEditPage.tsx @@ -20,7 +20,7 @@ import { } from '@grafana/ui'; import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound'; import { useAppNotification } from 'app/core/copy/appNotification'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { GrafanaRulesSourceSymbol, RuleGroupIdentifierV2, RulerDataSourceConfig } from 'app/types/unified-alerting'; import { RulerRuleGroupDTO } from 'app/types/unified-alerting-dto'; diff --git a/public/app/features/alerting/unified/hooks/ruleGroup/useDeleteRuleFromGroup.test.tsx b/public/app/features/alerting/unified/hooks/ruleGroup/useDeleteRuleFromGroup.test.tsx index 538d02d1a38..552c401b6d0 100644 --- a/public/app/features/alerting/unified/hooks/ruleGroup/useDeleteRuleFromGroup.test.tsx +++ b/public/app/features/alerting/unified/hooks/ruleGroup/useDeleteRuleFromGroup.test.tsx @@ -3,7 +3,7 @@ import { render } from 'test/test-utils'; import { byRole, byText } from 'testing-library-selector'; import server from '@grafana/test-utils/server'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { CombinedRule } from 'app/types/unified-alerting'; import { setupMswServer } from '../../mockApi'; diff --git a/public/app/features/alerting/unified/hooks/ruleGroup/usePauseAlertRule.test.tsx b/public/app/features/alerting/unified/hooks/ruleGroup/usePauseAlertRule.test.tsx index 1b7f1f89db3..df57efb9ac5 100644 --- a/public/app/features/alerting/unified/hooks/ruleGroup/usePauseAlertRule.test.tsx +++ b/public/app/features/alerting/unified/hooks/ruleGroup/usePauseAlertRule.test.tsx @@ -3,7 +3,7 @@ import { HttpResponse } from 'msw'; import { render } from 'test/test-utils'; import { byRole, byText } from 'testing-library-selector'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RulerGrafanaRuleDTO } from 'app/types/unified-alerting-dto'; import { setupMswServer } from '../../mockApi'; diff --git a/public/app/features/alerting/unified/hooks/ruleGroup/useUpdateRuleGroup.test.tsx b/public/app/features/alerting/unified/hooks/ruleGroup/useUpdateRuleGroup.test.tsx index 4d5fa6d556f..e74178297fb 100644 --- a/public/app/features/alerting/unified/hooks/ruleGroup/useUpdateRuleGroup.test.tsx +++ b/public/app/features/alerting/unified/hooks/ruleGroup/useUpdateRuleGroup.test.tsx @@ -1,7 +1,7 @@ import { render } from 'test/test-utils'; import { byRole, byText } from 'testing-library-selector'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RuleGroupIdentifier } from 'app/types/unified-alerting'; import { setupMswServer } from '../../mockApi'; diff --git a/public/app/features/alerting/unified/hooks/useAbilities.test.tsx b/public/app/features/alerting/unified/hooks/useAbilities.test.tsx index a7b550e0b68..3fdd05e6c63 100644 --- a/public/app/features/alerting/unified/hooks/useAbilities.test.tsx +++ b/public/app/features/alerting/unified/hooks/useAbilities.test.tsx @@ -5,7 +5,7 @@ import { setupMswServer } from 'app/features/alerting/unified/mockApi'; import { setFolderAccessControl } from 'app/features/alerting/unified/mocks/server/configure'; import { MIMIR_DATASOURCE_UID } from 'app/features/alerting/unified/mocks/server/constants'; import { AlertManagerDataSourceJsonData, AlertManagerImplementation } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { CombinedRule } from 'app/types/unified-alerting'; import { getCloudRule, getGrafanaRule, grantUserPermissions, mockDataSource } from '../mocks'; diff --git a/public/app/features/alerting/unified/hooks/useAbilities.ts b/public/app/features/alerting/unified/hooks/useAbilities.ts index 91fbe9cc603..5dd43d6db63 100644 --- a/public/app/features/alerting/unified/hooks/useAbilities.ts +++ b/public/app/features/alerting/unified/hooks/useAbilities.ts @@ -12,7 +12,7 @@ import { } from 'app/features/alerting/unified/components/notification-policies/permissions'; import { useFolder } from 'app/features/alerting/unified/hooks/useFolder'; import { AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { CombinedRule, RuleGroupIdentifierV2 } from 'app/types/unified-alerting'; import { GrafanaPromRuleDTO, RulerRuleDTO } from 'app/types/unified-alerting-dto'; diff --git a/public/app/features/alerting/unified/hooks/useFolder.ts b/public/app/features/alerting/unified/hooks/useFolder.ts index 7b06bf92020..804c9c12b25 100644 --- a/public/app/features/alerting/unified/hooks/useFolder.ts +++ b/public/app/features/alerting/unified/hooks/useFolder.ts @@ -1,7 +1,7 @@ import { skipToken } from '@reduxjs/toolkit/query/react'; import { useGetFolderQuery } from 'app/features/browse-dashboards/api/browseDashboardsAPI'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; interface ReturnBag { folder?: FolderDTO; diff --git a/public/app/features/alerting/unified/hooks/useIsRuleEditable.test.tsx b/public/app/features/alerting/unified/hooks/useIsRuleEditable.test.tsx index 36d2d6f06d1..ff0c9b61a1c 100644 --- a/public/app/features/alerting/unified/hooks/useIsRuleEditable.test.tsx +++ b/public/app/features/alerting/unified/hooks/useIsRuleEditable.test.tsx @@ -5,7 +5,8 @@ import { Provider } from 'react-redux'; import { contextSrv } from 'app/core/services/context_srv'; import { MIMIR_DATASOURCE_UID } from 'app/features/alerting/unified/mocks/server/constants'; import { configureStore } from 'app/store/configureStore'; -import { AccessControlAction, FolderDTO } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { FolderDTO } from 'app/types/folders'; import { setupMswServer } from '../mockApi'; import { mockDataSource, mockFolder, mockRulerAlertingRule, mockRulerGrafanaRule } from '../mocks'; diff --git a/public/app/features/alerting/unified/hooks/useManagedAlertStateHistory.ts b/public/app/features/alerting/unified/hooks/useManagedAlertStateHistory.ts index e7902fcf507..8230954063c 100644 --- a/public/app/features/alerting/unified/hooks/useManagedAlertStateHistory.ts +++ b/public/app/features/alerting/unified/hooks/useManagedAlertStateHistory.ts @@ -1,6 +1,6 @@ import { useEffect } from 'react'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { StateHistoryItem } from 'app/types/unified-alerting'; import { fetchGrafanaAnnotationsAction } from '../state/actions'; diff --git a/public/app/features/alerting/unified/hooks/useUnifiedAlertingSelector.ts b/public/app/features/alerting/unified/hooks/useUnifiedAlertingSelector.ts index 5e6daa81e8b..ed65c6ea4a9 100644 --- a/public/app/features/alerting/unified/hooks/useUnifiedAlertingSelector.ts +++ b/public/app/features/alerting/unified/hooks/useUnifiedAlertingSelector.ts @@ -1,6 +1,6 @@ import { createSelector } from 'reselect'; -import { StoreState, useSelector } from 'app/types'; +import { StoreState, useSelector } from 'app/types/store'; import { UnifiedAlertingState } from '../state/reducers'; diff --git a/public/app/features/alerting/unified/mockApi.ts b/public/app/features/alerting/unified/mockApi.ts index ae0e9c385b0..614c8235dd0 100644 --- a/public/app/features/alerting/unified/mockApi.ts +++ b/public/app/features/alerting/unified/mockApi.ts @@ -9,7 +9,8 @@ import { setupAlertmanagerStatusMapDefaultState, } from 'app/features/alerting/unified/mocks/server/entities/alertmanagers'; import { resetRoutingTreeMap } from 'app/features/alerting/unified/mocks/server/entities/k8s/routingtrees'; -import { DashboardDTO, FolderDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; +import { FolderDTO } from 'app/types/folders'; import { PromRulesResponse, RulerGrafanaRuleDTO, diff --git a/public/app/features/alerting/unified/mockGrafanaNotifiers.ts b/public/app/features/alerting/unified/mockGrafanaNotifiers.ts index 08bc5d4d90d..fd058176867 100644 --- a/public/app/features/alerting/unified/mockGrafanaNotifiers.ts +++ b/public/app/features/alerting/unified/mockGrafanaNotifiers.ts @@ -1,4 +1,4 @@ -import { GrafanaNotifierType, NotifierDTO } from 'app/types'; +import { GrafanaNotifierType, NotifierDTO } from 'app/types/alerting'; export const grafanaAlertNotifiers: Record<GrafanaNotifierType, NotifierDTO> = { dingding: { diff --git a/public/app/features/alerting/unified/mocks.ts b/public/app/features/alerting/unified/mocks.ts index e8d3bc2e2ab..0202406bf8e 100644 --- a/public/app/features/alerting/unified/mocks.ts +++ b/public/app/features/alerting/unified/mocks.ts @@ -26,7 +26,11 @@ import { SilenceState, } from 'app/plugins/datasource/alertmanager/types'; import { configureStore } from 'app/store/configureStore'; -import { AccessControlAction, DashboardDTO, FolderDTO, NotifiersState, ReceiversState, StoreState } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { NotifiersState, ReceiversState } from 'app/types/alerting'; +import { DashboardDTO } from 'app/types/dashboard'; +import { FolderDTO } from 'app/types/folders'; +import { StoreState } from 'app/types/store'; import { Alert, AlertingRule, diff --git a/public/app/features/alerting/unified/mocks/server/configure.ts b/public/app/features/alerting/unified/mocks/server/configure.ts index f21833e4866..3e3043d9331 100644 --- a/public/app/features/alerting/unified/mocks/server/configure.ts +++ b/public/app/features/alerting/unified/mocks/server/configure.ts @@ -22,7 +22,7 @@ import { import { SupportedPlugin } from 'app/features/alerting/unified/types/pluginBridges'; import { clearPluginSettingsCache } from 'app/features/plugins/pluginSettings'; import { AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { RulerDataSourceConfig } from 'app/types/unified-alerting'; import { GrafanaPromRuleGroupDTO, PromRuleGroupDTO, RulerRuleGroupDTO } from 'app/types/unified-alerting-dto'; diff --git a/public/app/features/alerting/unified/mocks/server/db.ts b/public/app/features/alerting/unified/mocks/server/db.ts index a100519b4b4..05cbf225981 100644 --- a/public/app/features/alerting/unified/mocks/server/db.ts +++ b/public/app/features/alerting/unified/mocks/server/db.ts @@ -4,7 +4,7 @@ import { uniqueId } from 'lodash'; import { DataSourceInstanceSettings, PluginType } from '@grafana/data'; import { config } from '@grafana/runtime'; import { GrafanaManagedContactPoint, GrafanaManagedReceiverConfig } from 'app/plugins/datasource/alertmanager/types'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { GrafanaAlertStateDecision, GrafanaAlertingRuleDefinition, diff --git a/public/app/features/alerting/unified/mocks/server/handlers/accessControl.ts b/public/app/features/alerting/unified/mocks/server/handlers/accessControl.ts index 9e73c77f671..3a79aa4824d 100644 --- a/public/app/features/alerting/unified/mocks/server/handlers/accessControl.ts +++ b/public/app/features/alerting/unified/mocks/server/handlers/accessControl.ts @@ -1,7 +1,7 @@ import { HttpResponse, http } from 'msw'; import { Description, ResourcePermission } from 'app/core/components/AccessControl/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; // TODO: Expand this out to more realistic use cases as we work on RBAC for contact points const resourceDescriptionsMap: Record<string, Description> = { diff --git a/public/app/features/alerting/unified/mocks/server/handlers/folders.ts b/public/app/features/alerting/unified/mocks/server/handlers/folders.ts index a1599b815e1..7a295222077 100644 --- a/public/app/features/alerting/unified/mocks/server/handlers/folders.ts +++ b/public/app/features/alerting/unified/mocks/server/handlers/folders.ts @@ -2,7 +2,7 @@ import { HttpResponse, http } from 'msw'; import { mockFolder } from 'app/features/alerting/unified/mocks'; import { grafanaRulerRule } from 'app/features/alerting/unified/mocks/grafanaRulerApi'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; export const DEFAULT_FOLDERS: FolderDTO[] = [ mockFolder({ diff --git a/public/app/features/alerting/unified/rule-editor/CloneRuleEditor.test.tsx b/public/app/features/alerting/unified/rule-editor/CloneRuleEditor.test.tsx index fd04f5c3b8e..8bd3b28e933 100644 --- a/public/app/features/alerting/unified/rule-editor/CloneRuleEditor.test.tsx +++ b/public/app/features/alerting/unified/rule-editor/CloneRuleEditor.test.tsx @@ -5,7 +5,7 @@ import { byRole, byTestId } from 'testing-library-selector'; import { MIMIR_DATASOURCE_UID } from 'app/features/alerting/unified/mocks/server/constants'; import { DashboardSearchItemType } from 'app/features/search/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RuleWithLocation } from 'app/types/unified-alerting'; import { RulerAlertingRuleDTO, diff --git a/public/app/features/alerting/unified/rule-editor/RuleEditorCloudOnlyAllowed.test.tsx b/public/app/features/alerting/unified/rule-editor/RuleEditorCloudOnlyAllowed.test.tsx index 86d92dac4fe..d21d660cc66 100644 --- a/public/app/features/alerting/unified/rule-editor/RuleEditorCloudOnlyAllowed.test.tsx +++ b/public/app/features/alerting/unified/rule-editor/RuleEditorCloudOnlyAllowed.test.tsx @@ -3,7 +3,7 @@ import { screen } from 'test/test-utils'; import { byText } from 'testing-library-selector'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PromApiFeatures, PromApplication } from 'app/types/unified-alerting-dto'; import { discoverFeaturesByUid } from '../api/buildInfo'; diff --git a/public/app/features/alerting/unified/rule-editor/RuleEditorCloudRules.test.tsx b/public/app/features/alerting/unified/rule-editor/RuleEditorCloudRules.test.tsx index ac0668721cb..7e823431f87 100644 --- a/public/app/features/alerting/unified/rule-editor/RuleEditorCloudRules.test.tsx +++ b/public/app/features/alerting/unified/rule-editor/RuleEditorCloudRules.test.tsx @@ -3,7 +3,7 @@ import { clickSelectOption } from 'test/helpers/selectOptionInTest'; import { screen } from 'test/test-utils'; import { selectors } from '@grafana/e2e-selectors'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ExpressionEditorProps } from '../components/rule-editor/ExpressionEditor'; import { setupMswServer } from '../mockApi'; diff --git a/public/app/features/alerting/unified/rule-editor/RuleEditorExisting.test.tsx b/public/app/features/alerting/unified/rule-editor/RuleEditorExisting.test.tsx index 9a99b587bcd..eab7a703499 100644 --- a/public/app/features/alerting/unified/rule-editor/RuleEditorExisting.test.tsx +++ b/public/app/features/alerting/unified/rule-editor/RuleEditorExisting.test.tsx @@ -6,7 +6,7 @@ import { contextSrv } from 'app/core/services/context_srv'; import { setFolderResponse } from 'app/features/alerting/unified/mocks/server/configure'; import { captureRequests } from 'app/features/alerting/unified/mocks/server/events'; import { DashboardSearchItemType } from 'app/features/search/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../mockApi'; import { grantUserPermissions, mockDataSource, mockFolder } from '../mocks'; diff --git a/public/app/features/alerting/unified/rule-editor/RuleEditorGrafanaRules.test.tsx b/public/app/features/alerting/unified/rule-editor/RuleEditorGrafanaRules.test.tsx index fedb898f955..632904914b1 100644 --- a/public/app/features/alerting/unified/rule-editor/RuleEditorGrafanaRules.test.tsx +++ b/public/app/features/alerting/unified/rule-editor/RuleEditorGrafanaRules.test.tsx @@ -8,7 +8,7 @@ import { contextSrv } from 'app/core/services/context_srv'; import { setupMswServer } from 'app/features/alerting/unified/mockApi'; import { PROMETHEUS_DATASOURCE_UID } from 'app/features/alerting/unified/mocks/server/constants'; import { DashboardSearchItemType } from 'app/features/search/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { grantUserPermissions, mockDataSource, mockFolder } from '../mocks'; import { grafanaRulerGroup, grafanaRulerGroup2, grafanaRulerRule } from '../mocks/grafanaRulerApi'; diff --git a/public/app/features/alerting/unified/rule-editor/RuleEditorRecordingRule.test.tsx b/public/app/features/alerting/unified/rule-editor/RuleEditorRecordingRule.test.tsx index 19166c01ea4..cd1f40deb43 100644 --- a/public/app/features/alerting/unified/rule-editor/RuleEditorRecordingRule.test.tsx +++ b/public/app/features/alerting/unified/rule-editor/RuleEditorRecordingRule.test.tsx @@ -5,7 +5,7 @@ import { clickSelectOption } from 'test/helpers/selectOptionInTest'; import { byText } from 'testing-library-selector'; import { setupMswServer } from 'app/features/alerting/unified/mockApi'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RecordingRuleEditorProps } from '../components/rule-editor/RecordingRuleEditor'; import { grantUserPermissions } from '../mocks'; diff --git a/public/app/features/alerting/unified/rule-list/DataSourceGroupLoader.test.tsx b/public/app/features/alerting/unified/rule-list/DataSourceGroupLoader.test.tsx index c1fe5eeec29..2c8411e09a9 100644 --- a/public/app/features/alerting/unified/rule-list/DataSourceGroupLoader.test.tsx +++ b/public/app/features/alerting/unified/rule-list/DataSourceGroupLoader.test.tsx @@ -3,7 +3,7 @@ import { byRole } from 'testing-library-selector'; import { DataSourceInstanceSettings } from '@grafana/data'; import { setPluginComponentsHook, setPluginLinksHook } from '@grafana/runtime'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { DataSourceRuleGroupIdentifier, DataSourceRulesSourceIdentifier } from 'app/types/unified-alerting'; import { PromRuleGroupDTO, RulerRuleDTO } from 'app/types/unified-alerting-dto'; diff --git a/public/app/features/alerting/unified/rule-list/FilterView.test.tsx b/public/app/features/alerting/unified/rule-list/FilterView.test.tsx index b9120e57eb1..b37e08dda81 100644 --- a/public/app/features/alerting/unified/rule-list/FilterView.test.tsx +++ b/public/app/features/alerting/unified/rule-list/FilterView.test.tsx @@ -2,7 +2,7 @@ import { mockIntersectionObserver } from 'jsdom-testing-mocks'; import { act, render, screen, waitForElementToBeRemoved } from 'test/test-utils'; import { setPluginComponentsHook, setPluginLinksHook } from '@grafana/runtime'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../mockApi'; import { grantUserPermissions } from '../mocks'; diff --git a/public/app/features/alerting/unified/rule-list/GrafanaGroupLoader.test.tsx b/public/app/features/alerting/unified/rule-list/GrafanaGroupLoader.test.tsx index 68913940e8e..3169996b88c 100644 --- a/public/app/features/alerting/unified/rule-list/GrafanaGroupLoader.test.tsx +++ b/public/app/features/alerting/unified/rule-list/GrafanaGroupLoader.test.tsx @@ -2,7 +2,7 @@ import { render } from 'test/test-utils'; import { byRole, byTitle } from 'testing-library-selector'; import { setPluginComponentsHook, setPluginLinksHook } from '@grafana/runtime'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { GrafanaRuleGroupIdentifier } from 'app/types/unified-alerting'; import { GrafanaPromRuleDTO, @@ -40,6 +40,7 @@ const ui = { copyLink: () => byRole('menuitem', { name: /copy link/i }), export: () => byRole('menuitem', { name: /export/i }), delete: () => byRole('menuitem', { name: /delete/i }), + pause: () => byRole('menuitem', { name: /pause/i }), }, }; @@ -188,7 +189,7 @@ describe('GrafanaGroupLoader', () => { const menu = byRole('menu').get(); expect(menu).toBeInTheDocument(); - // With proper permissions, all 4 menu actions should be available: + // With proper permissions, all 6 menu actions should be available: // 1. Silence notifications - available for alerting rules (AlertingSilenceCreate permission) expect(ui.menuItems.silence().get()).toBeInTheDocument(); @@ -202,9 +203,15 @@ describe('GrafanaGroupLoader', () => { // 4. Export - should be available for Grafana alerting rules (AlertingRuleRead permission) expect(ui.menuItems.export().get()).toBeInTheDocument(); - // Verify that the menu contains all 4 expected menu items + // 5. Delete - should be available for Grafana alerting rules (AlertingRuleDelete permission) + expect(ui.menuItems.delete().get()).toBeInTheDocument(); + + // 6. Pause - should be available for Grafana alerting rules (AlertingRuleUpdate permission) + expect(ui.menuItems.pause().get()).toBeInTheDocument(); + + // Verify that the menu contains all 6 expected menu items const menuItems = byRole('menuitem').getAll(); - expect(menuItems.length).toBe(4); + expect(menuItems.length).toBe(6); }); }); diff --git a/public/app/features/alerting/unified/rule-list/GroupedView.test.tsx b/public/app/features/alerting/unified/rule-list/GroupedView.test.tsx index 361d017b4d2..63723b06bdd 100644 --- a/public/app/features/alerting/unified/rule-list/GroupedView.test.tsx +++ b/public/app/features/alerting/unified/rule-list/GroupedView.test.tsx @@ -2,7 +2,7 @@ import { render, screen, waitFor, within } from 'test/test-utils'; import { byRole } from 'testing-library-selector'; import { setPluginComponentsHook, setPluginLinksHook, setReturnToPreviousHook } from '@grafana/runtime'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../mockApi'; import { grantUserPermissions } from '../mocks'; diff --git a/public/app/features/alerting/unified/rule-list/RuleList.v1.tsx b/public/app/features/alerting/unified/rule-list/RuleList.v1.tsx index d9df8e007d4..8e80dd0eff3 100644 --- a/public/app/features/alerting/unified/rule-list/RuleList.v1.tsx +++ b/public/app/features/alerting/unified/rule-list/RuleList.v1.tsx @@ -7,7 +7,7 @@ import { Trans, t } from '@grafana/i18n'; import { logInfo } from '@grafana/runtime'; import { Button, LinkButton, Stack } from '@grafana/ui'; import { useQueryParams } from 'app/core/hooks/useQueryParams'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { CombinedRuleNamespace } from 'app/types/unified-alerting'; import { LogMessages, trackRuleListNavigation } from '../Analytics'; diff --git a/public/app/features/alerting/unified/rule-list/RuleList.v2.test.tsx b/public/app/features/alerting/unified/rule-list/RuleList.v2.test.tsx index e29d4c2f65b..1f2f4c0b02e 100644 --- a/public/app/features/alerting/unified/rule-list/RuleList.v2.test.tsx +++ b/public/app/features/alerting/unified/rule-list/RuleList.v2.test.tsx @@ -2,7 +2,7 @@ import { render } from 'test/test-utils'; import { byRole, byTestId } from 'testing-library-selector'; import { setPluginComponentsHook, setPluginLinksHook } from '@grafana/runtime'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { setupMswServer } from '../mockApi'; import { grantUserPermissions } from '../mocks'; diff --git a/public/app/features/alerting/unified/rule-list/components/AlertRuleListItemLoader.tsx b/public/app/features/alerting/unified/rule-list/components/AlertRuleListItemLoader.tsx index db56bb9af9f..e8abce41ed8 100644 --- a/public/app/features/alerting/unified/rule-list/components/AlertRuleListItemLoader.tsx +++ b/public/app/features/alerting/unified/rule-list/components/AlertRuleListItemLoader.tsx @@ -17,6 +17,7 @@ export function AlertRuleListItemSkeleton() { description={<Skeleton width={256} />} actions={<RuleActionsSkeleton />} data-testid="alert-rule-list-item-loader" + aria-disabled={true} /> ); } diff --git a/public/app/features/alerting/unified/rule-list/components/RuleActionsButtons.V2.tsx b/public/app/features/alerting/unified/rule-list/components/RuleActionsButtons.V2.tsx index 37e56db4058..4570b3dd8e9 100644 --- a/public/app/features/alerting/unified/rule-list/components/RuleActionsButtons.V2.tsx +++ b/public/app/features/alerting/unified/rule-list/components/RuleActionsButtons.V2.tsx @@ -1,3 +1,4 @@ +import { isString } from 'lodash'; import { useState } from 'react'; import { RequireAtLeastOne } from 'type-fest'; @@ -19,7 +20,13 @@ import { RulerRuleDTO } from 'app/types/unified-alerting-dto'; import { logWarning } from '../../Analytics'; import { AlertRuleAction, skipToken, useGrafanaPromRuleAbility, useRulerRuleAbility } from '../../hooks/useAbilities'; import * as ruleId from '../../utils/rule-id'; -import { isProvisionedPromRule, isProvisionedRule, prometheusRuleType, rulerRuleType } from '../../utils/rules'; +import { + getRuleUID, + isProvisionedPromRule, + isProvisionedRule, + prometheusRuleType, + rulerRuleType, +} from '../../utils/rules'; import { createRelativeUrl } from '../../utils/url'; type RuleProps = RequireAtLeastOne<{ @@ -69,6 +76,12 @@ export function RuleActionsButtons({ compact, rule, promRule, groupIdentifier }: return null; } + // determine if this rule can be silenced by checking for Grafana Alert rule type and extracting the UID + const ruleUid = getRuleUID(rule ?? promRule); + const silenceableRule = + isString(ruleUid) && + (rulerRuleType.grafana.alertingRule(rule) || prometheusRuleType.grafana.alertingRule(promRule)); + if (canEditRule) { const editURL = createRelativeUrl(`/alerting/${encodeURIComponent(ruleId.stringifyIdentifier(identifier))}/edit`); @@ -96,13 +109,13 @@ export function RuleActionsButtons({ compact, rule, promRule, groupIdentifier }: promRule={promRule} groupIdentifier={groupIdentifier} identifier={identifier} - handleDelete={() => showDeleteModal(identifier, groupIdentifier)} + handleDelete={(identifier, groupIdentifier) => showDeleteModal(identifier, groupIdentifier)} handleSilence={() => setShowSilenceDrawer(true)} handleDuplicateRule={() => setRedirectToClone({ identifier, isProvisioned })} /> {deleteModal} - {rulerRuleType.grafana.alertingRule(rule) && showSilenceDrawer && ( - <SilenceGrafanaRuleDrawer rulerRule={rule} onClose={() => setShowSilenceDrawer(false)} /> + {silenceableRule && showSilenceDrawer && ( + <SilenceGrafanaRuleDrawer ruleUid={ruleUid} onClose={() => setShowSilenceDrawer(false)} /> )} {redirectToClone?.identifier && ( <RedirectToCloneRule diff --git a/public/app/features/alerting/unified/settings/extensions.ts b/public/app/features/alerting/unified/settings/extensions.ts new file mode 100644 index 00000000000..c6cb202849f --- /dev/null +++ b/public/app/features/alerting/unified/settings/extensions.ts @@ -0,0 +1,50 @@ +import { useLocation } from 'react-router-dom-v5-compat'; + +import { NavModelItem } from '@grafana/data'; +import { useSelector } from 'app/types/store'; + +type SettingsSectionUrl = `/alerting/admin/${string}`; +type SettingsSectionNav = Pick<NavModelItem, 'id' | 'text' | 'icon'> & { + url: SettingsSectionUrl; +}; + +const settingsExtensions: Map<SettingsSectionUrl, { nav: SettingsSectionNav }> = new Map(); + +/** + * Registers a new settings section that will appear as a tab in the alerting settings page. + * @param pageNav - The navigation configuration for the settings section + */ +export function addSettingsSection(pageNav: SettingsSectionNav) { + if (settingsExtensions.has(pageNav.url)) { + console.warn('Unable to add settings page, PageNav must have an unique url'); + return; + } + settingsExtensions.set(pageNav.url, { nav: pageNav }); +} + +/** + * Returns the navigation configuration for all settings extensions. + */ +export function useSettingsExtensionsNav(): NavModelItem[] { + const location = useLocation(); + + const navIndex = useSelector((state) => state.navIndex); + const settingsNav = navIndex['alerting-admin']; + + // Build extension tabs from settingsExtensions + const extensionTabs: NavModelItem[] = Array.from(settingsExtensions.entries()).map(([url, { nav }]) => ({ + ...nav, + active: location.pathname === url, + url: url, + parentItem: settingsNav, + })); + + return extensionTabs; +} + +/** + * ONLY USE FOR TESTING. Clears all settings extensions. + */ +export function clearSettingsExtensions() { + settingsExtensions.clear(); +} diff --git a/public/app/features/alerting/unified/settings/navigation.test.ts b/public/app/features/alerting/unified/settings/navigation.test.ts new file mode 100644 index 00000000000..c4b4c4678ef --- /dev/null +++ b/public/app/features/alerting/unified/settings/navigation.test.ts @@ -0,0 +1,111 @@ +import { renderHook } from '@testing-library/react'; +import { getWrapper } from 'test/test-utils'; + +import { addSettingsSection, clearSettingsExtensions } from './extensions'; +import { useSettingsPageNav } from './navigation'; + +describe('useSettingsPageNav', () => { + const mockNavIndex = { + 'alerting-admin': { + id: 'alerting-admin', + text: 'Settings', + url: '/alerting/admin', + }, + }; + + const defaultPreloadedState = { + navIndex: mockNavIndex, + }; + + it('should return settings page nav with alertmanager child when no extensions are present', () => { + const wrapper = getWrapper({ + preloadedState: defaultPreloadedState, + renderWithRouter: true, + historyOptions: { + initialEntries: ['/alerting/admin/alertmanager'], + }, + }); + + const { result } = renderHook(() => useSettingsPageNav(), { wrapper }); + + expect(result.current.navId).toBe('alerting'); + + // Check the structure + // eslint-disable-next-line testing-library/no-node-access + expect(result.current.pageNav.children).toHaveLength(1); + // eslint-disable-next-line testing-library/no-node-access + expect(result.current.pageNav.children).toEqual([ + expect.objectContaining({ + id: 'alertmanager', + text: 'Alert managers', + url: '/alerting/admin/alertmanager', + active: true, + icon: 'cloud', + parentItem: undefined, + }), + ]); + }); + + it('should include extensions when added via addSettingsSection', () => { + // Clear any existing extensions + clearSettingsExtensions(); + + // Add two extensions + addSettingsSection({ + id: 'enrichment', + text: 'Enrichment', + url: '/alerting/admin/enrichment', + icon: 'star', + }); + + addSettingsSection({ + id: 'notifications', + text: 'Notifications', + url: '/alerting/admin/notifications', + icon: 'bell', + }); + + const wrapper = getWrapper({ + preloadedState: defaultPreloadedState, + renderWithRouter: true, + historyOptions: { + initialEntries: ['/alerting/admin/enrichment'], + }, + }); + + const { result } = renderHook(() => useSettingsPageNav(), { wrapper }); + + expect(result.current.navId).toBe('alerting'); + + // Should have 3 children: alertmanager + 2 extensions + // eslint-disable-next-line testing-library/no-node-access + expect(result.current.pageNav.children).toHaveLength(3); + // eslint-disable-next-line testing-library/no-node-access + expect(result.current.pageNav.children).toEqual([ + expect.objectContaining({ + id: 'alertmanager', + text: 'Alert managers', + url: '/alerting/admin/alertmanager', + active: false, + icon: 'cloud', + parentItem: undefined, + }), + expect.objectContaining({ + id: 'enrichment', + text: 'Enrichment', + url: '/alerting/admin/enrichment', + active: true, + icon: 'star', + parentItem: undefined, + }), + expect.objectContaining({ + id: 'notifications', + text: 'Notifications', + url: '/alerting/admin/notifications', + active: false, + icon: 'bell', + parentItem: undefined, + }), + ]); + }); +}); diff --git a/public/app/features/alerting/unified/settings/navigation.ts b/public/app/features/alerting/unified/settings/navigation.ts new file mode 100644 index 00000000000..85513269e1f --- /dev/null +++ b/public/app/features/alerting/unified/settings/navigation.ts @@ -0,0 +1,40 @@ +import { useLocation } from 'react-router-dom-v5-compat'; + +import { NavModelItem } from '@grafana/data'; +import { t } from '@grafana/i18n'; +import { useSelector } from 'app/types/store'; + +import { useSettingsExtensionsNav } from './extensions'; + +export function useSettingsPageNav() { + const location = useLocation(); + + const navIndex = useSelector((state) => state.navIndex); + const settingsNav = navIndex['alerting-admin']; + + const extensionTabs = useSettingsExtensionsNav(); + + // All available tabs including the main alertmanager tab + const allTabs: NavModelItem[] = [ + { + id: 'alertmanager', + text: t('alerting.settings.tabs.alert-managers', 'Alert managers'), + url: '/alerting/admin/alertmanager', + active: location.pathname === '/alerting/admin/alertmanager', + icon: 'cloud', + parentItem: settingsNav, + }, + ...extensionTabs, + ]; + + // Create pageNav that represents the Settings page with tabs as children + const pageNav: NavModelItem = { + ...settingsNav, + children: allTabs, + }; + + return { + navId: 'alerting', + pageNav, + }; +} diff --git a/public/app/features/alerting/unified/state/actions.ts b/public/app/features/alerting/unified/state/actions.ts index f45b7ff1dde..90ccc17db20 100644 --- a/public/app/features/alerting/unified/state/actions.ts +++ b/public/app/features/alerting/unified/state/actions.ts @@ -9,7 +9,7 @@ import { Receiver, TestReceiversAlert, } from 'app/plugins/datasource/alertmanager/types'; -import { ThunkResult } from 'app/types'; +import { ThunkResult } from 'app/types/store'; import { RuleIdentifier, RuleNamespace, StateHistoryItem } from 'app/types/unified-alerting'; import { RulerRuleDTO, RulerRulesConfigDTO } from 'app/types/unified-alerting-dto'; diff --git a/public/app/features/alerting/unified/test/test-utils.ts b/public/app/features/alerting/unified/test/test-utils.ts index 66598dea083..0dea7f9eb58 100644 --- a/public/app/features/alerting/unified/test/test-utils.ts +++ b/public/app/features/alerting/unified/test/test-utils.ts @@ -2,7 +2,7 @@ import { act } from '@testing-library/react'; import { FeatureToggles } from '@grafana/data'; import { config } from '@grafana/runtime'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { grantUserPermissions } from '../mocks'; import { setFolderAccessControl } from '../mocks/server/configure'; diff --git a/public/app/features/alerting/unified/types/receiver-form.ts b/public/app/features/alerting/unified/types/receiver-form.ts index e17aa9d05f0..d2045a2c2a6 100644 --- a/public/app/features/alerting/unified/types/receiver-form.ts +++ b/public/app/features/alerting/unified/types/receiver-form.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { GrafanaManagedReceiverConfig } from 'app/plugins/datasource/alertmanager/types'; -import { CloudNotifierType, NotifierType } from 'app/types'; +import { CloudNotifierType, NotifierType } from 'app/types/alerting'; import { ControlledField } from '../hooks/useControlledFieldArray'; diff --git a/public/app/features/alerting/unified/utils/access-control.ts b/public/app/features/alerting/unified/utils/access-control.ts index edda81712ae..0821c92963b 100644 --- a/public/app/features/alerting/unified/utils/access-control.ts +++ b/public/app/features/alerting/unified/utils/access-control.ts @@ -1,6 +1,6 @@ import { getConfig } from 'app/core/config'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { GRAFANA_RULES_SOURCE_NAME, isGrafanaRulesSource } from './datasource'; diff --git a/public/app/features/alerting/unified/utils/cloud-alertmanager-notifier-types.ts b/public/app/features/alerting/unified/utils/cloud-alertmanager-notifier-types.ts index 96bc19b4aff..2475248dc34 100644 --- a/public/app/features/alerting/unified/utils/cloud-alertmanager-notifier-types.ts +++ b/public/app/features/alerting/unified/utils/cloud-alertmanager-notifier-types.ts @@ -1,5 +1,5 @@ import { config } from '@grafana/runtime'; -import { CloudNotifierType, NotificationChannelOption, NotifierDTO } from 'app/types'; +import { CloudNotifierType, NotificationChannelOption, NotifierDTO } from 'app/types/alerting'; import { option } from './notifier-types'; diff --git a/public/app/features/alerting/unified/utils/datasource.ts b/public/app/features/alerting/unified/utils/datasource.ts index a50eddcfa50..4bcf3757d2c 100644 --- a/public/app/features/alerting/unified/utils/datasource.ts +++ b/public/app/features/alerting/unified/utils/datasource.ts @@ -8,7 +8,7 @@ import { AlertManagerImplementation, AlertmanagerChoice, } from 'app/plugins/datasource/alertmanager/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { DataSourceRulesSourceIdentifier as DataSourceRulesSourceIdentifier, GrafanaRulesSourceIdentifier, diff --git a/public/app/features/alerting/unified/utils/navigation.ts b/public/app/features/alerting/unified/utils/navigation.ts index 15081fb8b4e..259207f41b7 100644 --- a/public/app/features/alerting/unified/utils/navigation.ts +++ b/public/app/features/alerting/unified/utils/navigation.ts @@ -45,6 +45,32 @@ export const groups = { { skipSubPath: options?.skipSubPath } ); }, + newAlertRuleLink: (folderName?: string, folderUid?: string, groupName?: string) => { + const returnTo = createReturnTo(); + + const defaults = JSON.stringify({ + folder: { + title: folderName, + uid: folderUid, + }, + group: groupName, + }); + + return createRelativeUrl('/alerting/new', { defaults, returnTo }); + }, + newRecordingRuleLink: (folderName?: string, folderUid?: string, groupName?: string) => { + const returnTo = createReturnTo(); + + const defaults = JSON.stringify({ + folder: { + title: folderName, + uid: folderUid, + }, + group: groupName, + }); + + return createRelativeUrl('/alerting/new/grafana-recording', { defaults, returnTo }); + }, }; export const rulesNav = { diff --git a/public/app/features/alerting/unified/utils/notifier-types.ts b/public/app/features/alerting/unified/utils/notifier-types.ts index f7c9e0054bc..eeb2f30dae9 100644 --- a/public/app/features/alerting/unified/utils/notifier-types.ts +++ b/public/app/features/alerting/unified/utils/notifier-types.ts @@ -1,4 +1,4 @@ -import { NotificationChannelOption } from '../../../../types'; +import { NotificationChannelOption } from 'app/types/alerting'; export function option( propertyName: string, diff --git a/public/app/features/alerting/unified/utils/receiver-form.ts b/public/app/features/alerting/unified/utils/receiver-form.ts index c5ae3b55263..689bfe07c26 100644 --- a/public/app/features/alerting/unified/utils/receiver-form.ts +++ b/public/app/features/alerting/unified/utils/receiver-form.ts @@ -7,7 +7,7 @@ import { GrafanaManagedReceiverSecureFields, Receiver, } from 'app/plugins/datasource/alertmanager/types'; -import { CloudNotifierType, NotificationChannelOption, NotifierDTO, NotifierType } from 'app/types'; +import { CloudNotifierType, NotificationChannelOption, NotifierDTO, NotifierType } from 'app/types/alerting'; import { ChannelValues, diff --git a/public/app/features/alerting/unified/utils/rules.ts b/public/app/features/alerting/unified/utils/rules.ts index 91ca9915e34..033be738e49 100644 --- a/public/app/features/alerting/unified/utils/rules.ts +++ b/public/app/features/alerting/unified/utils/rules.ts @@ -533,3 +533,22 @@ export function isRecordingRuleByType(type?: RuleFormType) { export function isDataSourceManagedRuleByType(type?: RuleFormType) { return isCloudAlertingRuleByType(type) || isCloudRecordingRuleByType(type); } + +/* + * Grab the UID from either a rulerRule definition or a Prometheus rule definition, only Grafana-managed rules will have a UID. + */ +export function getRuleUID(rule?: RulerRuleDTO | Rule) { + if (!rule) { + return; + } + + let ruleUid: string | undefined; + + if ('grafana_alert' in rule && rulerRuleType.grafana.rule(rule)) { + ruleUid = rule.grafana_alert.uid; + } else if ('uid' in rule && prometheusRuleType.grafana.rule(rule)) { + ruleUid = rule.uid; + } + + return ruleUid; +} diff --git a/public/app/features/auth-config/AuthDrawer.tsx b/public/app/features/auth-config/AuthDrawer.tsx index 06d1ebc948c..e6a3892bc1c 100644 --- a/public/app/features/auth-config/AuthDrawer.tsx +++ b/public/app/features/auth-config/AuthDrawer.tsx @@ -6,7 +6,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Button, Drawer, Text, TextLink, Switch, useStyles2 } from '@grafana/ui'; import { useAppNotification } from 'app/core/copy/appNotification'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { loadSettings, saveSettings } from './state/actions'; diff --git a/public/app/features/auth-config/AuthProvidersListPage.tsx b/public/app/features/auth-config/AuthProvidersListPage.tsx index d0ae5e73ab7..37fdf7c5cfe 100644 --- a/public/app/features/auth-config/AuthProvidersListPage.tsx +++ b/public/app/features/auth-config/AuthProvidersListPage.tsx @@ -7,7 +7,7 @@ import { reportInteraction } from '@grafana/runtime'; import { Grid, TextLink, ToolbarButton } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { config } from 'app/core/config'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import AuthDrawer from './AuthDrawer'; import ConfigureAuthCTA from './components/ConfigureAuthCTA'; diff --git a/public/app/features/auth-config/ErrorContainer.tsx b/public/app/features/auth-config/ErrorContainer.tsx index 79cf6514569..336dde9716a 100644 --- a/public/app/features/auth-config/ErrorContainer.tsx +++ b/public/app/features/auth-config/ErrorContainer.tsx @@ -1,7 +1,7 @@ import { connect, ConnectedProps } from 'react-redux'; import { Alert } from '@grafana/ui'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { resetError, resetWarning } from './state/reducers'; diff --git a/public/app/features/auth-config/ProviderConfigPage.tsx b/public/app/features/auth-config/ProviderConfigPage.tsx index 617626660fa..34614ddb746 100644 --- a/public/app/features/auth-config/ProviderConfigPage.tsx +++ b/public/app/features/auth-config/ProviderConfigPage.tsx @@ -6,7 +6,7 @@ import { t } from '@grafana/i18n'; import { Badge, Stack, Text } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { PageNotFound } from 'app/core/components/PageNotFound/PageNotFound'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { ProviderConfigForm } from './ProviderConfigForm'; import { UIMap } from './constants'; diff --git a/public/app/features/auth-config/index.ts b/public/app/features/auth-config/index.ts index c927b22e701..69113401661 100644 --- a/public/app/features/auth-config/index.ts +++ b/public/app/features/auth-config/index.ts @@ -1,7 +1,8 @@ import config from 'app/core/config'; import { contextSrv } from 'app/core/core'; import { getBackendSrv } from 'app/core/services/backend_srv'; -import { AccessControlAction, Settings, SettingsSection } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { Settings, SettingsSection } from 'app/types/settings'; import { AuthProviderInfo, GetStatusHook, AuthProviderStatus } from './types'; diff --git a/public/app/features/auth-config/state/actions.ts b/public/app/features/auth-config/state/actions.ts index 074cb6b894f..cf1cdd8d7f7 100644 --- a/public/app/features/auth-config/state/actions.ts +++ b/public/app/features/auth-config/state/actions.ts @@ -2,7 +2,9 @@ import { lastValueFrom } from 'rxjs'; import { getBackendSrv, isFetchError } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, Settings, ThunkResult, UpdateSettingsQuery } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { Settings, UpdateSettingsQuery } from 'app/types/settings'; +import { ThunkResult } from 'app/types/store'; import { getAuthProviderStatus, getRegisteredAuthProviders, SSOProvider } from '..'; import { AuthProviderStatus, SettingsError } from '../types'; diff --git a/public/app/features/auth-config/state/reducers.ts b/public/app/features/auth-config/state/reducers.ts index 0194ed538d0..0dac91d70a6 100644 --- a/public/app/features/auth-config/state/reducers.ts +++ b/public/app/features/auth-config/state/reducers.ts @@ -1,6 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { Settings } from 'app/types'; +import { Settings } from 'app/types/settings'; import { SettingsError, AuthProviderStatus, AuthConfigState, SSOProvider } from '../types'; diff --git a/public/app/features/auth-config/types.ts b/public/app/features/auth-config/types.ts index b14336f06ab..6b6fd5c5a4e 100644 --- a/public/app/features/auth-config/types.ts +++ b/public/app/features/auth-config/types.ts @@ -2,7 +2,7 @@ import { ReactElement } from 'react'; import { Validate, UseFormSetValue } from 'react-hook-form'; import { IconName, SelectableValue } from '@grafana/data'; -import { Settings } from 'app/types'; +import { Settings } from 'app/types/settings'; export interface AuthProviderInfo { id: string; type: string; diff --git a/public/app/features/bookmarks/BookmarksPage.tsx b/public/app/features/bookmarks/BookmarksPage.tsx index 6a4c1b704df..6b7f9ab08ae 100644 --- a/public/app/features/bookmarks/BookmarksPage.tsx +++ b/public/app/features/bookmarks/BookmarksPage.tsx @@ -7,7 +7,7 @@ import { usePinnedItems } from 'app/core/components/AppChrome/MegaMenu/hooks'; import { findByUrl } from 'app/core/components/AppChrome/MegaMenu/utils'; import { NavLandingPageCard } from 'app/core/components/NavLandingPage/NavLandingPageCard'; import { Page } from 'app/core/components/Page/Page'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; export function BookmarksPage() { const styles = useStyles2(getStyles); diff --git a/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx b/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx index 7a58ec579ae..e392e6a3f53 100644 --- a/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx +++ b/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx @@ -10,7 +10,7 @@ import { config, reportInteraction } from '@grafana/runtime'; import { LinkButton, FilterInput, useStyles2, Text, Stack } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { getConfig } from 'app/core/config'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { FolderRepo } from '../../core/components/NestedFolderPicker/FolderRepo'; import { contextSrv } from '../../core/services/context_srv'; diff --git a/public/app/features/browse-dashboards/RecentlyDeletedPage.tsx b/public/app/features/browse-dashboards/RecentlyDeletedPage.tsx index 06fc910a683..3e18b71d399 100644 --- a/public/app/features/browse-dashboards/RecentlyDeletedPage.tsx +++ b/public/app/features/browse-dashboards/RecentlyDeletedPage.tsx @@ -8,8 +8,7 @@ import { FilterInput, useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { ActionRow } from 'app/features/search/page/components/ActionRow'; import { getGrafanaSearcher } from 'app/features/search/service/searcher'; - -import { useDispatch } from '../../types'; +import { useDispatch } from 'app/types/store'; import { useRecentlyDeletedStateManager } from './api/useRecentlyDeletedStateManager'; import { RecentlyDeletedActions } from './components/RecentlyDeletedActions'; diff --git a/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts b/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts index fdd091aecc3..b9f5f4c9323 100644 --- a/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts +++ b/public/app/features/browse-dashboards/api/browseDashboardsAPI.ts @@ -15,15 +15,9 @@ import { isDashboardV2Resource, isV1DashboardCommand, isV2DashboardCommand } fro import { SaveDashboardCommand } from 'app/features/dashboard/components/SaveDashboard/types'; import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher'; import { dispatch } from 'app/store/store'; -import { - DescendantCount, - DescendantCountDTO, - FolderDTO, - FolderListItemDTO, - ImportDashboardResponseDTO, - PermissionLevelString, - SaveDashboardResponseDTO, -} from 'app/types'; +import { PermissionLevelString } from 'app/types/acl'; +import { SaveDashboardResponseDTO, ImportDashboardResponseDTO } from 'app/types/dashboard'; +import { FolderListItemDTO, FolderDTO, DescendantCount, DescendantCountDTO } from 'app/types/folders'; import { refetchChildren, refreshParents } from '../state/actions'; import { DashboardTreeSelection } from '../types'; diff --git a/public/app/features/browse-dashboards/api/isProvisioned.ts b/public/app/features/browse-dashboards/api/isProvisioned.ts index 7df88e77de3..f0b948d4d5e 100644 --- a/public/app/features/browse-dashboards/api/isProvisioned.ts +++ b/public/app/features/browse-dashboards/api/isProvisioned.ts @@ -1,6 +1,6 @@ import { Folder } from 'app/api/clients/folder/v1beta1'; import { AnnoKeyManagerKind, ManagerKind } from 'app/features/apiserver/types'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; import { DashboardWithAccessInfo } from '../../dashboard/api/types'; diff --git a/public/app/features/browse-dashboards/api/services.ts b/public/app/features/browse-dashboards/api/services.ts index c5eb2375b65..a6a511ba0f7 100644 --- a/public/app/features/browse-dashboards/api/services.ts +++ b/public/app/features/browse-dashboards/api/services.ts @@ -4,9 +4,9 @@ import { getGrafanaSearcher } from 'app/features/search/service/searcher'; import { NestedFolderDTO } from 'app/features/search/service/types'; import { queryResultToViewItem } from 'app/features/search/service/utils'; import { DashboardViewItem } from 'app/features/search/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { contextSrv } from '../../../core/core'; -import { AccessControlAction } from '../../../types'; import { getFolderURL, isSharedWithMe } from '../components/utils'; export const PAGE_SIZE = 50; diff --git a/public/app/features/browse-dashboards/components/BrowseActions/BrowseActions.tsx b/public/app/features/browse-dashboards/components/BrowseActions/BrowseActions.tsx index 931c66cfd74..3dd60457c77 100644 --- a/public/app/features/browse-dashboards/components/BrowseActions/BrowseActions.tsx +++ b/public/app/features/browse-dashboards/components/BrowseActions/BrowseActions.tsx @@ -5,8 +5,8 @@ import { config, reportInteraction } from '@grafana/runtime'; import { Button, Stack, Tooltip } from '@grafana/ui'; import appEvents from 'app/core/app_events'; import { useSearchStateManager } from 'app/features/search/state/SearchStateManager'; -import { useDispatch } from 'app/types'; import { ShowModalReactEvent } from 'app/types/events'; +import { useDispatch } from 'app/types/store'; import { useDeleteItemsMutation, useMoveItemsMutation } from '../../api/browseDashboardsAPI'; import { useActionSelectionState } from '../../state/hooks'; diff --git a/public/app/features/browse-dashboards/components/BrowseView.tsx b/public/app/features/browse-dashboards/components/BrowseView.tsx index 2a6c55a4ed3..b20fa522fc7 100644 --- a/public/app/features/browse-dashboards/components/BrowseView.tsx +++ b/public/app/features/browse-dashboards/components/BrowseView.tsx @@ -3,7 +3,7 @@ import { useCallback } from 'react'; import { Trans, t } from '@grafana/i18n'; import { CallToActionCard, EmptyState, LinkButton, TextLink } from '@grafana/ui'; import { DashboardViewItem } from 'app/features/search/types'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { PAGE_SIZE } from '../api/services'; import { fetchNextChildrenPage } from '../state/actions'; diff --git a/public/app/features/browse-dashboards/components/CreateNewButton.test.tsx b/public/app/features/browse-dashboards/components/CreateNewButton.test.tsx index 902f3b0ef2a..e5635cdfd4d 100644 --- a/public/app/features/browse-dashboards/components/CreateNewButton.test.tsx +++ b/public/app/features/browse-dashboards/components/CreateNewButton.test.tsx @@ -2,7 +2,7 @@ import { render as rtlRender, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { TestProvider } from 'test/helpers/TestProvider'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { mockFolderDTO } from '../fixtures/folder.fixture'; diff --git a/public/app/features/browse-dashboards/components/CreateNewButton.tsx b/public/app/features/browse-dashboards/components/CreateNewButton.tsx index bb00a254d31..d1c487da4f8 100644 --- a/public/app/features/browse-dashboards/components/CreateNewButton.tsx +++ b/public/app/features/browse-dashboards/components/CreateNewButton.tsx @@ -12,7 +12,7 @@ import { getNewFolderPhrase, getNewPhrase, } from 'app/features/search/tempI18nPhrases'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { ManagerKind } from '../../apiserver/types'; import { useNewFolderMutation } from '../api/browseDashboardsAPI'; diff --git a/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.test.tsx b/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.test.tsx index f56e50bf023..0412efd0c18 100644 --- a/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.test.tsx +++ b/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.test.tsx @@ -2,7 +2,7 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { RepositoryView, useDeleteRepositoryFilesWithPathMutation } from 'app/api/clients/provisioning/v0alpha1'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { ProvisionedFolderFormDataResult, useProvisionedFolderFormData } from '../hooks/useProvisionedFolderFormData'; diff --git a/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.tsx b/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.tsx index 995f68bbd23..2b4a6ebb92f 100644 --- a/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.tsx +++ b/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.tsx @@ -10,7 +10,7 @@ import { RepositoryView, useDeleteRepositoryFilesWithPathMutation } from 'app/ap import { AnnoKeySourcePath } from 'app/features/apiserver/types'; import { ResourceEditFormSharedFields } from 'app/features/dashboard-scene/components/Provisioned/ResourceEditFormSharedFields'; import { BaseProvisionedFormData } from 'app/features/dashboard-scene/saving/shared'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { useProvisionedFolderFormData } from '../hooks/useProvisionedFolderFormData'; diff --git a/public/app/features/browse-dashboards/components/FolderActionsButton.tsx b/public/app/features/browse-dashboards/components/FolderActionsButton.tsx index d5cef0b3aa1..9640314aec9 100644 --- a/public/app/features/browse-dashboards/components/FolderActionsButton.tsx +++ b/public/app/features/browse-dashboards/components/FolderActionsButton.tsx @@ -5,8 +5,8 @@ import { config, locationService, reportInteraction } from '@grafana/runtime'; import { Button, Drawer, Dropdown, Icon, Menu, MenuItem } from '@grafana/ui'; import { Permissions } from 'app/core/components/AccessControl'; import { appEvents } from 'app/core/core'; -import { FolderDTO } from 'app/types'; import { ShowModalReactEvent } from 'app/types/events'; +import { FolderDTO } from 'app/types/folders'; import { ManagerKind } from '../../apiserver/types'; import { useDeleteFolderMutation, useMoveFolderMutation } from '../api/browseDashboardsAPI'; diff --git a/public/app/features/browse-dashboards/components/NewProvisionedFolderForm.test.tsx b/public/app/features/browse-dashboards/components/NewProvisionedFolderForm.test.tsx index e4c7527c079..a983a66ada0 100644 --- a/public/app/features/browse-dashboards/components/NewProvisionedFolderForm.test.tsx +++ b/public/app/features/browse-dashboards/components/NewProvisionedFolderForm.test.tsx @@ -6,8 +6,8 @@ import { getAppEvents } from '@grafana/runtime'; import { useCreateRepositoryFilesWithPathMutation } from 'app/api/clients/provisioning/v0alpha1'; import { validationSrv } from 'app/features/manage-dashboards/services/ValidationSrv'; import { usePullRequestParam } from 'app/features/provisioning/hooks/usePullRequestParam'; +import { FolderDTO } from 'app/types/folders'; -import { FolderDTO } from '../../../types'; import { ProvisionedFolderFormDataResult, useProvisionedFolderFormData } from '../hooks/useProvisionedFolderFormData'; import { NewProvisionedFolderForm } from './NewProvisionedFolderForm'; diff --git a/public/app/features/browse-dashboards/components/NewProvisionedFolderForm.tsx b/public/app/features/browse-dashboards/components/NewProvisionedFolderForm.tsx index 291696baeeb..f79cb371636 100644 --- a/public/app/features/browse-dashboards/components/NewProvisionedFolderForm.tsx +++ b/public/app/features/browse-dashboards/components/NewProvisionedFolderForm.tsx @@ -14,7 +14,7 @@ import { BaseProvisionedFormData } from 'app/features/dashboard-scene/saving/sha import { validationSrv } from 'app/features/manage-dashboards/services/ValidationSrv'; import { PROVISIONING_URL } from 'app/features/provisioning/constants'; import { usePullRequestParam } from 'app/features/provisioning/hooks/usePullRequestParam'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { useProvisionedFolderFormData } from '../hooks/useProvisionedFolderFormData'; interface FormProps extends Props { diff --git a/public/app/features/browse-dashboards/components/ProvisionedFolderPreviewBanner.tsx b/public/app/features/browse-dashboards/components/ProvisionedFolderPreviewBanner.tsx index 57443939fa6..32068d49077 100644 --- a/public/app/features/browse-dashboards/components/ProvisionedFolderPreviewBanner.tsx +++ b/public/app/features/browse-dashboards/components/ProvisionedFolderPreviewBanner.tsx @@ -12,11 +12,11 @@ export function ProvisionedFolderPreviewBanner({ queryParams }: CommonBannerProp } if (prURL) { - return <PreviewBannerViewPR prParam={prURL} isFolder />; + return <PreviewBannerViewPR prParam={prURL} />; } if (newPrURL) { - return <PreviewBannerViewPR prParam={newPrURL} isFolder isNewPr />; + return <PreviewBannerViewPR prParam={newPrURL} isNewPr />; } return null; diff --git a/public/app/features/browse-dashboards/components/RecentlyDeletedActions.tsx b/public/app/features/browse-dashboards/components/RecentlyDeletedActions.tsx index 158c8d9fa71..18cc800213e 100644 --- a/public/app/features/browse-dashboards/components/RecentlyDeletedActions.tsx +++ b/public/app/features/browse-dashboards/components/RecentlyDeletedActions.tsx @@ -6,8 +6,8 @@ import { Button, Stack } from '@grafana/ui'; import appEvents from 'app/core/app_events'; import { AnnoKeyFolder } from 'app/features/apiserver/types'; import { GENERAL_FOLDER_UID } from 'app/features/search/constants'; -import { useDispatch } from 'app/types'; import { ShowModalReactEvent } from 'app/types/events'; +import { useDispatch } from 'app/types/store'; import { deletedDashboardsCache } from '../../search/service/deletedDashboardsCache'; import { useListDeletedDashboardsQuery, useRestoreDashboardMutation } from '../api/browseDashboardsAPI'; diff --git a/public/app/features/browse-dashboards/components/SearchView.tsx b/public/app/features/browse-dashboards/components/SearchView.tsx index 203d46a4307..281455f140e 100644 --- a/public/app/features/browse-dashboards/components/SearchView.tsx +++ b/public/app/features/browse-dashboards/components/SearchView.tsx @@ -7,7 +7,7 @@ import { useKeyNavigationListener } from 'app/features/search/hooks/useSearchKey import { SearchResultsProps, SearchResultsTable } from 'app/features/search/page/components/SearchResultsTable'; import { SearchStateManager } from 'app/features/search/state/SearchStateManager'; import { DashboardViewItemKind, SearchState } from 'app/features/search/types'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { useHasSelection } from '../state/hooks'; import { setAllSelection, setItemSelectionState } from '../state/slice'; diff --git a/public/app/features/browse-dashboards/fixtures/folder.fixture.ts b/public/app/features/browse-dashboards/fixtures/folder.fixture.ts index 14cb3a83652..bab54a40975 100644 --- a/public/app/features/browse-dashboards/fixtures/folder.fixture.ts +++ b/public/app/features/browse-dashboards/fixtures/folder.fixture.ts @@ -1,6 +1,6 @@ import { Chance } from 'chance'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; export function mockFolderDTO(seed = 1, partial?: Partial<FolderDTO>): FolderDTO { const random = Chance(seed); diff --git a/public/app/features/browse-dashboards/permissions.ts b/public/app/features/browse-dashboards/permissions.ts index 49eff8d69ff..d589af9480a 100644 --- a/public/app/features/browse-dashboards/permissions.ts +++ b/public/app/features/browse-dashboards/permissions.ts @@ -1,6 +1,7 @@ import { config } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, FolderDTO } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { FolderDTO } from 'app/types/folders'; function checkFolderPermission(action: AccessControlAction, folderDTO?: FolderDTO) { return folderDTO ? contextSrv.hasPermissionInMetadata(action, folderDTO) : contextSrv.hasPermission(action); diff --git a/public/app/features/browse-dashboards/state/actions.ts b/public/app/features/browse-dashboards/state/actions.ts index 88073d0e518..f738493b342 100644 --- a/public/app/features/browse-dashboards/state/actions.ts +++ b/public/app/features/browse-dashboards/state/actions.ts @@ -1,6 +1,6 @@ import { GENERAL_FOLDER_UID } from 'app/features/search/constants'; import { DashboardViewItem, DashboardViewItemKind } from 'app/features/search/types'; -import { createAsyncThunk } from 'app/types'; +import { createAsyncThunk } from 'app/types/store'; import { listDashboards, listFolders, PAGE_SIZE } from '../api/services'; import { DashboardViewItemWithUIItems, UIDashboardViewItem } from '../types'; diff --git a/public/app/features/browse-dashboards/state/hooks.test.ts b/public/app/features/browse-dashboards/state/hooks.test.ts index 373a6c0a0f7..d5fd74b4bb0 100644 --- a/public/app/features/browse-dashboards/state/hooks.test.ts +++ b/public/app/features/browse-dashboards/state/hooks.test.ts @@ -1,13 +1,13 @@ import { configureStore } from 'app/store/configureStore'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { fullyLoadedViewItemCollection } from '../fixtures/state.fixtures'; import { BrowseDashboardsState } from '../types'; import { useBrowseLoadingStatus } from './hooks'; -jest.mock('app/types', () => { - const original = jest.requireActual('app/types'); +jest.mock('app/types/store', () => { + const original = jest.requireActual('app/types/store'); return { ...original, useSelector: jest.fn(), diff --git a/public/app/features/browse-dashboards/state/hooks.ts b/public/app/features/browse-dashboards/state/hooks.ts index d46f0b44708..2c0bee62a98 100644 --- a/public/app/features/browse-dashboards/state/hooks.ts +++ b/public/app/features/browse-dashboards/state/hooks.ts @@ -2,7 +2,7 @@ import { useCallback, useRef } from 'react'; import { createSelector } from 'reselect'; import { DashboardViewItem } from 'app/features/search/types'; -import { useSelector, StoreState, useDispatch } from 'app/types'; +import { useSelector, StoreState, useDispatch } from 'app/types/store'; import { PAGE_SIZE } from '../api/services'; import { isSharedWithMe } from '../components/utils'; diff --git a/public/app/features/commandPalette/actions/staticActions.ts b/public/app/features/commandPalette/actions/staticActions.ts index d3304f0db78..e7e8c8d6734 100644 --- a/public/app/features/commandPalette/actions/staticActions.ts +++ b/public/app/features/commandPalette/actions/staticActions.ts @@ -6,8 +6,8 @@ import { enrichHelpItem } from 'app/core/components/AppChrome/MegaMenu/utils'; import { performInviteUserClick, shouldRenderInviteUserButton } from 'app/core/components/InviteUserButton/utils'; import { changeTheme } from 'app/core/services/theme'; import { currentMockApiState, toggleMockApiAndReload, togglePseudoLocale } from 'app/dev-utils'; +import { useSelector } from 'app/types/store'; -import { useSelector } from '../../../types'; import { CommandPaletteAction } from '../types'; import { ACTIONS_PRIORITY, DEFAULT_PRIORITY, PREFERENCES_PRIORITY } from '../values'; diff --git a/public/app/features/connections/Connections.tsx b/public/app/features/connections/Connections.tsx index 5515e9bf96b..e4119a6bf3f 100644 --- a/public/app/features/connections/Connections.tsx +++ b/public/app/features/connections/Connections.tsx @@ -1,6 +1,6 @@ import { Navigate, Routes, Route, useLocation } from 'react-router-dom-v5-compat'; -import { StoreState, useSelector } from 'app/types'; +import { StoreState, useSelector } from 'app/types/store'; import { ROUTES } from './constants'; import { AddNewConnectionPage } from './pages/AddNewConnectionPage'; diff --git a/public/app/features/connections/components/ConnectionsRedirectNotice/ConnectionsRedirectNotice.tsx b/public/app/features/connections/components/ConnectionsRedirectNotice/ConnectionsRedirectNotice.tsx index f9bb04c72de..438868f7751 100644 --- a/public/app/features/connections/components/ConnectionsRedirectNotice/ConnectionsRedirectNotice.tsx +++ b/public/app/features/connections/components/ConnectionsRedirectNotice/ConnectionsRedirectNotice.tsx @@ -4,9 +4,9 @@ import { useState } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Alert, LinkButton, useStyles2 } from '@grafana/ui'; +import { AccessControlAction } from 'app/types/accessControl'; import { contextSrv } from '../../../../core/core'; -import { AccessControlAction } from '../../../../types'; import { ROUTES } from '../../constants'; const getStyles = (theme: GrafanaTheme2) => ({ diff --git a/public/app/features/connections/hooks/useDataSourceSettingsNav.ts b/public/app/features/connections/hooks/useDataSourceSettingsNav.ts index d5898d370d2..72c4a09059a 100644 --- a/public/app/features/connections/hooks/useDataSourceSettingsNav.ts +++ b/public/app/features/connections/hooks/useDataSourceSettingsNav.ts @@ -7,7 +7,7 @@ import { getNavModel } from 'app/core/selectors/navModel'; import { useDataSource, useDataSourceMeta, useDataSourceSettings } from 'app/features/datasources/state/hooks'; import { getDataSourceLoadingNav, buildNavModel, getDataSourceNav } from 'app/features/datasources/state/navModel'; import { useGetSingle } from 'app/features/plugins/admin/state/hooks'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; export function useDataSourceSettingsNav(pageIdParam?: string) { const { uid = '' } = useParams<{ uid: string }>(); diff --git a/public/app/features/connections/pages/DataSourceDetailsPage.tsx b/public/app/features/connections/pages/DataSourceDetailsPage.tsx index be345ee77ed..f7223abc418 100644 --- a/public/app/features/connections/pages/DataSourceDetailsPage.tsx +++ b/public/app/features/connections/pages/DataSourceDetailsPage.tsx @@ -3,7 +3,8 @@ import { useParams } from 'react-router-dom-v5-compat'; import { Trans, t } from '@grafana/i18n'; import { Alert, Badge, TextLink } from '@grafana/ui'; import { PluginDetailsPage } from 'app/features/plugins/admin/components/PluginDetailsPage'; -import { StoreState, useSelector, AppNotificationSeverity } from 'app/types'; +import { AppNotificationSeverity } from 'app/types/appNotifications'; +import { StoreState, useSelector } from 'app/types/store'; import { ROUTES } from '../constants'; diff --git a/public/app/features/connections/pages/DataSourcesListPage.tsx b/public/app/features/connections/pages/DataSourcesListPage.tsx index 5c67b07da24..7ec9062b1d7 100644 --- a/public/app/features/connections/pages/DataSourcesListPage.tsx +++ b/public/app/features/connections/pages/DataSourcesListPage.tsx @@ -3,7 +3,7 @@ import { AdvisorRedirectNotice } from 'app/features/connections/components/Advis import { DataSourceAddButton } from 'app/features/datasources/components/DataSourceAddButton'; import { DataSourcesList } from 'app/features/datasources/components/DataSourcesList'; import { getDataSourcesCount } from 'app/features/datasources/state/selectors'; -import { StoreState, useSelector } from 'app/types'; +import { StoreState, useSelector } from 'app/types/store'; export function DataSourcesListPage() { const dataSourcesCount = useSelector(({ dataSources }: StoreState) => getDataSourcesCount(dataSources)); diff --git a/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx b/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx index 0215b463ca9..a4dabd2bbf9 100644 --- a/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx +++ b/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx @@ -7,7 +7,7 @@ import { locationService } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; import { getCatalogPluginMock, getPluginsStateMock } from 'app/features/plugins/admin/mocks/mockHelpers'; import { CatalogPlugin } from 'app/features/plugins/admin/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { AddNewConnection } from './ConnectData'; diff --git a/public/app/features/connections/tabs/ConnectData/ConnectData.tsx b/public/app/features/connections/tabs/ConnectData/ConnectData.tsx index 30f0464b7ce..3668047af9f 100644 --- a/public/app/features/connections/tabs/ConnectData/ConnectData.tsx +++ b/public/app/features/connections/tabs/ConnectData/ConnectData.tsx @@ -14,7 +14,7 @@ import { SearchField } from 'app/features/plugins/admin/components/SearchField'; import { Sorters } from 'app/features/plugins/admin/helpers'; import { useHistory } from 'app/features/plugins/admin/hooks/useHistory'; import { useGetAll, useIsRemotePluginsAvailable } from 'app/features/plugins/admin/state/hooks'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ROUTES } from '../../constants'; diff --git a/public/app/features/correlations/CorrelationsPage.tsx b/public/app/features/correlations/CorrelationsPage.tsx index bab13964ae6..60ce5a5b166 100644 --- a/public/app/features/correlations/CorrelationsPage.tsx +++ b/public/app/features/correlations/CorrelationsPage.tsx @@ -22,7 +22,7 @@ import { import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; import { useNavModel } from 'app/core/hooks/useNavModel'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { AddCorrelationForm } from './Forms/AddCorrelationForm'; import { EditCorrelationForm } from './Forms/EditCorrelationForm'; diff --git a/public/app/features/correlations/utils.ts b/public/app/features/correlations/utils.ts index 1a6f97157da..37c81fc6728 100644 --- a/public/app/features/correlations/utils.ts +++ b/public/app/features/correlations/utils.ts @@ -9,7 +9,7 @@ import { getBackendSrv, getDataSourceSrv, } from '@grafana/runtime'; -import { ExploreItemState } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; import { formatValueName } from '../explore/PrometheusListView/ItemLabels'; import { parseLogsFrame } from '../logs/logsFrame'; diff --git a/public/app/features/dashboard-scene/addToDashboard/AddToDashboardForm.tsx b/public/app/features/dashboard-scene/addToDashboard/AddToDashboardForm.tsx index d437e1308ce..17ecf87eb8f 100644 --- a/public/app/features/dashboard-scene/addToDashboard/AddToDashboardForm.tsx +++ b/public/app/features/dashboard-scene/addToDashboard/AddToDashboardForm.tsx @@ -9,7 +9,7 @@ import { Panel } from '@grafana/schema'; import { Alert, Button, Field, Modal, RadioButtonGroup } from '@grafana/ui'; import { DashboardPicker } from 'app/core/components/Select/DashboardPicker'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { addToDashboard, SubmissionError } from './addToDashboard'; diff --git a/public/app/features/dashboard-scene/addToDashboard/addPanelsOnLoadBehavior.ts b/public/app/features/dashboard-scene/addToDashboard/addPanelsOnLoadBehavior.ts index 7cad2fc7c3d..90afde16cd4 100644 --- a/public/app/features/dashboard-scene/addToDashboard/addPanelsOnLoadBehavior.ts +++ b/public/app/features/dashboard-scene/addToDashboard/addPanelsOnLoadBehavior.ts @@ -1,7 +1,7 @@ import { SceneTimeRange } from '@grafana/scenes'; import store from 'app/core/store'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; -import { DASHBOARD_FROM_LS_KEY, DashboardDTO } from 'app/types'; +import { DASHBOARD_FROM_LS_KEY, DashboardDTO } from 'app/types/dashboard'; import { DashboardScene } from '../scene/DashboardScene'; import { buildGridItemForPanel } from '../serialization/transformSaveModelToScene'; diff --git a/public/app/features/dashboard-scene/addToDashboard/addToDashboard.ts b/public/app/features/dashboard-scene/addToDashboard/addToDashboard.ts index e0f929c6f2e..e22feb9a502 100644 --- a/public/app/features/dashboard-scene/addToDashboard/addToDashboard.ts +++ b/public/app/features/dashboard-scene/addToDashboard/addToDashboard.ts @@ -4,7 +4,7 @@ import { config, locationService } from '@grafana/runtime'; import { Panel } from '@grafana/schema'; import store from 'app/core/store'; import { DASHBOARD_SCHEMA_VERSION } from 'app/features/dashboard/state/DashboardMigrator'; -import { DASHBOARD_FROM_LS_KEY, DashboardDTO } from 'app/types'; +import { DASHBOARD_FROM_LS_KEY, DashboardDTO } from 'app/types/dashboard'; export enum GenericError { UNKNOWN = 'unknown-error', diff --git a/public/app/features/dashboard-scene/embedding/EmbeddedDashboard.tsx b/public/app/features/dashboard-scene/embedding/EmbeddedDashboard.tsx index 90b1524c1d2..ae55db117d0 100644 --- a/public/app/features/dashboard-scene/embedding/EmbeddedDashboard.tsx +++ b/public/app/features/dashboard-scene/embedding/EmbeddedDashboard.tsx @@ -7,7 +7,7 @@ import { EmbeddedDashboardProps } from '@grafana/runtime'; import { SceneObjectStateChangedEvent, sceneUtils } from '@grafana/scenes'; import { Spinner, Alert, useStyles2 } from '@grafana/ui'; import { getMessageFromError } from 'app/core/utils/errors'; -import { DashboardRoutes } from 'app/types'; +import { DashboardRoutes } from 'app/types/dashboard'; import { getDashboardScenePageStateManager } from '../pages/DashboardScenePageStateManager'; import { DashboardScene } from '../scene/DashboardScene'; diff --git a/public/app/features/dashboard-scene/inspect/HelpWizard/HelpWizard.tsx b/public/app/features/dashboard-scene/inspect/HelpWizard/HelpWizard.tsx index e6a1c1ffbf4..cab5eaf608c 100644 --- a/public/app/features/dashboard-scene/inspect/HelpWizard/HelpWizard.tsx +++ b/public/app/features/dashboard-scene/inspect/HelpWizard/HelpWizard.tsx @@ -24,7 +24,7 @@ import { TextLink, } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ShowMessage, SnapshotTab, SupportSnapshotService } from './SupportSnapshotService'; diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePage.test.tsx b/public/app/features/dashboard-scene/pages/DashboardScenePage.test.tsx index b2776dc9414..016e72010bf 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePage.test.tsx +++ b/public/app/features/dashboard-scene/pages/DashboardScenePage.test.tsx @@ -15,7 +15,7 @@ import { getRouteComponentProps } from 'app/core/navigation/mocks/routeProps'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; import store from 'app/core/store'; import { DashboardLoaderSrv, setDashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv'; -import { DASHBOARD_FROM_LS_KEY, DashboardRoutes } from 'app/types'; +import { DASHBOARD_FROM_LS_KEY, DashboardRoutes } from 'app/types/dashboard'; import { dashboardSceneGraph } from '../utils/dashboardSceneGraph'; import { setupLoadDashboardMockReject, setupLoadDashboardRuntimeErrorMock } from '../utils/test-utils'; diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx b/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx index bcdcff100ec..ef1ec38b653 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx +++ b/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx @@ -11,7 +11,7 @@ import PageLoader from 'app/core/components/PageLoader/PageLoader'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; import { DashboardPageError } from 'app/features/dashboard/containers/DashboardPageError'; import { DashboardPageRouteParams, DashboardPageRouteSearchParams } from 'app/features/dashboard/containers/types'; -import { DashboardRoutes } from 'app/types'; +import { DashboardRoutes } from 'app/types/dashboard'; import { DashboardPrompt } from '../saving/DashboardPrompt'; import { DashboardPreviewBanner } from '../saving/provisioned/DashboardPreviewBanner'; diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts index a38fe4fb66f..1b971c981ee 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts +++ b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts @@ -14,7 +14,7 @@ import { setDashboardLoaderSrv, } from 'app/features/dashboard/services/DashboardLoaderSrv'; import { getDashboardSnapshotSrv } from 'app/features/dashboard/services/SnapshotSrv'; -import { DASHBOARD_FROM_LS_KEY, DashboardDataDTO, DashboardDTO, DashboardRoutes } from 'app/types'; +import { DASHBOARD_FROM_LS_KEY, DashboardDataDTO, DashboardDTO, DashboardRoutes } from 'app/types/dashboard'; import { DashboardScene } from '../scene/DashboardScene'; import { setupLoadDashboardMock, setupLoadDashboardMockReject } from '../utils/test-utils'; diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts index e6c2cb3e0a8..1039767ed95 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts +++ b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts @@ -27,7 +27,7 @@ import { DashboardRoutes, HomeDashboardRedirectDTO, isRedirectResponse, -} from 'app/types'; +} from 'app/types/dashboard'; import { PanelEditor } from '../panel-edit/PanelEditor'; import { DashboardScene } from '../scene/DashboardScene'; diff --git a/public/app/features/dashboard-scene/pages/PublicDashboardScenePage.tsx b/public/app/features/dashboard-scene/pages/PublicDashboardScenePage.tsx index f7c88b2815a..07bcf478336 100644 --- a/public/app/features/dashboard-scene/pages/PublicDashboardScenePage.tsx +++ b/public/app/features/dashboard-scene/pages/PublicDashboardScenePage.tsx @@ -16,7 +16,7 @@ import { PublicDashboardPageRouteParams, PublicDashboardPageRouteSearchParams, } from 'app/features/dashboard/containers/types'; -import { AppNotificationSeverity } from 'app/types'; +import { AppNotificationSeverity } from 'app/types/appNotifications'; import { DashboardRoutes } from 'app/types/dashboard'; import { DashboardScene } from '../scene/DashboardScene'; diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx index 7f2b930b208..06573cc06ef 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx @@ -25,7 +25,8 @@ import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { configureStore } from 'app/store/configureStore'; -import { AccessControlAction, DashboardDataDTO } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { AlertQuery, PromRulesResponse } from 'app/types/unified-alerting-dto'; import { createDashboardSceneFromDashboardModel } from '../../serialization/transformSaveModelToScene'; diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.test.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.test.tsx index c76896c4afd..241b37165b5 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.test.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.test.tsx @@ -22,7 +22,7 @@ import { config, locationService } from '@grafana/runtime'; import { PANEL_EDIT_LAST_USED_DATASOURCE } from 'app/features/dashboard/utils/dashboard'; import { InspectTab } from 'app/features/inspector/types'; import { SHARED_DASHBOARD_QUERY, DASHBOARD_DATASOURCE_PLUGIN_ID } from 'app/plugins/datasource/dashboard/constants'; -import { DashboardDataDTO } from 'app/types'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { PanelTimeRange, PanelTimeRangeState } from '../../scene/PanelTimeRange'; import { transformSaveModelToScene } from '../../serialization/transformSaveModelToScene'; diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx index 19a1e3af6c5..ce2784758be 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx @@ -26,7 +26,7 @@ import { QueryEditorRows } from 'app/features/query/components/QueryEditorRows'; import { QueryGroupTopSection } from 'app/features/query/components/QueryGroup'; import { updateQueries } from 'app/features/query/state/updateQueries'; import { isSharedDashboardQuery } from 'app/plugins/datasource/dashboard/runSharedRequest'; -import { QueryGroupOptions } from 'app/types'; +import { QueryGroupOptions } from 'app/types/query'; import { MIXED_DATASOURCE_NAME } from '../../../../plugins/datasource/mixed/MixedDataSource'; import { useQueryLibraryContext } from '../../../explore/QueryLibrary/QueryLibraryContext'; diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataTransformationsTab.test.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataTransformationsTab.test.tsx index 7ff6453297a..e06b9fc6da2 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataTransformationsTab.test.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataTransformationsTab.test.tsx @@ -14,7 +14,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { SceneDataTransformer, SceneQueryRunner } from '@grafana/scenes'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { getStandardTransformers } from 'app/features/transformers/standardTransformers'; -import { DashboardDataDTO } from 'app/types'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { transformSaveModelToScene } from '../../serialization/transformSaveModelToScene'; import { DashboardModelCompatibilityWrapper } from '../../utils/DashboardModelCompatibilityWrapper'; diff --git a/public/app/features/dashboard-scene/saving/SaveDashboardDrawer.test.tsx b/public/app/features/dashboard-scene/saving/SaveDashboardDrawer.test.tsx index d78b4971bfe..dd4d6734919 100644 --- a/public/app/features/dashboard-scene/saving/SaveDashboardDrawer.test.tsx +++ b/public/app/features/dashboard-scene/saving/SaveDashboardDrawer.test.tsx @@ -6,7 +6,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { config } from '@grafana/runtime'; import { sceneGraph, SceneRefreshPicker } from '@grafana/scenes'; import { AnnoKeyManagerKind, ManagerKind } from 'app/features/apiserver/types'; -import { SaveDashboardResponseDTO } from 'app/types'; +import { SaveDashboardResponseDTO } from 'app/types/dashboard'; import { DashboardSceneState } from '../scene/DashboardScene'; import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene'; diff --git a/public/app/features/dashboard-scene/saving/getDashboardChanges.ts b/public/app/features/dashboard-scene/saving/getDashboardChanges.ts index b47c88473ef..17ef35baa60 100644 --- a/public/app/features/dashboard-scene/saving/getDashboardChanges.ts +++ b/public/app/features/dashboard-scene/saving/getDashboardChanges.ts @@ -10,7 +10,7 @@ import { } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; import { ResponseTransformers } from 'app/features/dashboard/api/ResponseTransformers'; import { isDashboardV2Spec } from 'app/features/dashboard/api/utils'; -import { DashboardDataDTO, DashboardDTO } from 'app/types'; +import { DashboardDataDTO, DashboardDTO } from 'app/types/dashboard'; import { validateFiltersOrigin } from '../serialization/sceneVariablesSetToVariables'; import { jsonDiff } from '../settings/version-history/utils'; diff --git a/public/app/features/dashboard-scene/saving/provisioned/DashboardPreviewBanner.tsx b/public/app/features/dashboard-scene/saving/provisioned/DashboardPreviewBanner.tsx index ee306bad2f9..f44552cbd69 100644 --- a/public/app/features/dashboard-scene/saving/provisioned/DashboardPreviewBanner.tsx +++ b/public/app/features/dashboard-scene/saving/provisioned/DashboardPreviewBanner.tsx @@ -4,7 +4,7 @@ import { Alert } from '@grafana/ui'; import { useGetRepositoryFilesWithPathQuery } from 'app/api/clients/provisioning/v0alpha1'; import { DashboardPageRouteSearchParams } from 'app/features/dashboard/containers/types'; import { usePullRequestParam } from 'app/features/provisioning/hooks/usePullRequestParam'; -import { DashboardRoutes } from 'app/types'; +import { DashboardRoutes } from 'app/types/dashboard'; import { PreviewBannerViewPR } from './PreviewBannerViewPR'; diff --git a/public/app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR.test.tsx b/public/app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR.test.tsx index de716143ac0..94964f8004a 100644 --- a/public/app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR.test.tsx +++ b/public/app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR.test.tsx @@ -60,14 +60,14 @@ describe('PreviewBannerViewPR', () => { setup({ prParam: 'test-url', isFolder: false, isNewPr: true }); expect(screen.getByRole('status')).toBeInTheDocument(); - expect(screen.getByText('This dashboard is loaded from a branch in GitHub.')).toBeInTheDocument(); + expect(screen.getByText('A new resource has been created in a branch in GitHub.')).toBeInTheDocument(); }); it('should render correct text for existing PR dashboard', () => { setup({ prParam: 'test-url', isFolder: false, isNewPr: false }); expect(screen.getByRole('status')).toBeInTheDocument(); - expect(screen.getByText('This dashboard is loaded from a pull request in GitHub.')).toBeInTheDocument(); + expect(screen.getByText('This resource is loaded from a pull request in GitHub.')).toBeInTheDocument(); }); it('should render correct button text for new PR dashboard', () => { @@ -88,14 +88,14 @@ describe('PreviewBannerViewPR', () => { setup({ prParam: 'test-url', isFolder: true, isNewPr: true }); expect(screen.getByRole('status')).toBeInTheDocument(); - expect(screen.getByText('A new folder has been created in a branch in GitHub.')).toBeInTheDocument(); + expect(screen.getByText('A new resource has been created in a branch in GitHub.')).toBeInTheDocument(); }); it('should render correct text for existing PR folder', () => { setup({ prParam: 'test-url', isFolder: true, isNewPr: false }); expect(screen.getByRole('status')).toBeInTheDocument(); - expect(screen.getByText('A new folder has been created in a pull request in GitHub.')).toBeInTheDocument(); + expect(screen.getByText('This resource is loaded from a pull request in GitHub.')).toBeInTheDocument(); }); it('should render correct button text for new PR folder', () => { diff --git a/public/app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR.tsx b/public/app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR.tsx index 2188c4029a0..e1da054147f 100644 --- a/public/app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR.tsx +++ b/public/app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR.tsx @@ -8,33 +8,22 @@ import { commonAlertProps } from './DashboardPreviewBanner'; interface Props { prParam: string; - isFolder?: boolean; isNewPr?: boolean; } /** * @description This component is used to display a banner when a provisioned dashboard/folder is created or loaded from a new branch in Github. */ -export function PreviewBannerViewPR({ prParam, isFolder = false, isNewPr }: Props) { - const titleText = isFolder - ? isNewPr - ? t( - 'provisioned-resource-preview-banner.title-folder-created-branch-git-hub', - 'A new folder has been created in a branch in GitHub.' - ) - : t( - 'provisioned-resource-preview-banner.title-folder-created-pull-request-git-hub', - 'A new folder has been created in a pull request in GitHub.' - ) - : isNewPr - ? t( - 'provisioned-resource-preview-banner.title-dashboard-loaded-branch-git-hub', - 'This dashboard is loaded from a branch in GitHub.' - ) - : t( - 'provisioned-resource-preview-banner.title-dashboard-loaded-pull-request-git-hub', - 'This dashboard is loaded from a pull request in GitHub.' - ); +export function PreviewBannerViewPR({ prParam, isNewPr }: Props) { + const titleText = isNewPr + ? t( + 'provisioned-resource-preview-banner.title-created-branch-git-hub', + 'A new resource has been created in a branch in GitHub.' + ) + : t( + 'provisioned-resource-preview-banner.title-loaded-pull-request-git-hub', + 'This resource is loaded from a pull request in GitHub.' + ); return ( <Alert diff --git a/public/app/features/dashboard-scene/saving/provisioned/hooks.ts b/public/app/features/dashboard-scene/saving/provisioned/hooks.ts index a274c9c7f88..e82ebcee548 100644 --- a/public/app/features/dashboard-scene/saving/provisioned/hooks.ts +++ b/public/app/features/dashboard-scene/saving/provisioned/hooks.ts @@ -4,7 +4,7 @@ import { RepositoryView } from 'app/api/clients/provisioning/v0alpha1'; import { useUrlParams } from 'app/core/navigation/hooks'; import { AnnoKeyManagerIdentity, AnnoKeyManagerKind, AnnoKeySourcePath } from 'app/features/apiserver/types'; import { useGetResourceRepositoryView } from 'app/features/provisioning/hooks/useGetResourceRepositoryView'; -import { DashboardMeta } from 'app/types'; +import { DashboardMeta } from 'app/types/dashboard'; import { DashboardScene } from '../../scene/DashboardScene'; import { ProvisionedDashboardFormData } from '../shared'; diff --git a/public/app/features/dashboard-scene/saving/useSaveDashboard.ts b/public/app/features/dashboard-scene/saving/useSaveDashboard.ts index 97a50aa3621..8f75ecf0751 100644 --- a/public/app/features/dashboard-scene/saving/useSaveDashboard.ts +++ b/public/app/features/dashboard-scene/saving/useSaveDashboard.ts @@ -10,8 +10,8 @@ import { useAppNotification } from 'app/core/copy/appNotification'; import { updateDashboardName } from 'app/core/reducers/navBarTree'; import { useSaveDashboardMutation } from 'app/features/browse-dashboards/api/browseDashboardsAPI'; import { SaveDashboardAsOptions, SaveDashboardOptions } from 'app/features/dashboard/components/SaveDashboard/types'; -import { useDispatch } from 'app/types'; import { DashboardSavedEvent } from 'app/types/events'; +import { useDispatch } from 'app/types/store'; import { updateDashboardUidLastUsedDatasource } from '../../dashboard/utils/dashboard'; import { DashboardScene } from '../scene/DashboardScene'; diff --git a/public/app/features/dashboard-scene/scene/AlertStatesDataLayer.ts b/public/app/features/dashboard-scene/scene/AlertStatesDataLayer.ts index 643ea0ac56f..f939f4a2a24 100644 --- a/public/app/features/dashboard-scene/scene/AlertStatesDataLayer.ts +++ b/public/app/features/dashboard-scene/scene/AlertStatesDataLayer.ts @@ -19,7 +19,7 @@ import { Annotation } from 'app/features/alerting/unified/utils/constants'; import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource'; import { prometheusRuleType } from 'app/features/alerting/unified/utils/rules'; import { dispatch } from 'app/store/store'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RuleNamespace } from 'app/types/unified-alerting'; import { PromAlertingRuleState, PromRuleGroupDTO } from 'app/types/unified-alerting-dto'; diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 2d5a2901b06..46e67142648 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -31,7 +31,7 @@ import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher'; import { DashboardJson } from 'app/features/manage-dashboards/types'; import { VariablesChanged } from 'app/features/variables/types'; -import { DashboardDTO, DashboardMeta, KioskMode, SaveDashboardResponseDTO } from 'app/types'; +import { DashboardMeta, KioskMode, SaveDashboardResponseDTO, DashboardDTO } from 'app/types/dashboard'; import { ShowConfirmModalEvent } from 'app/types/events'; import { diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx index bd300a5bbd3..19a6916552c 100644 --- a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx @@ -6,7 +6,7 @@ import { ScopesContext } from '@grafana/runtime'; import { SceneComponentProps } from '@grafana/scenes'; import { Page } from 'app/core/components/Page/Page'; import { getNavModel } from 'app/core/selectors/navModel'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { DashboardEditPaneSplitter } from '../edit-pane/DashboardEditPaneSplitter'; diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.test.ts b/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.test.ts index 4a7e9fca190..9dbd47cf919 100644 --- a/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.test.ts +++ b/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.test.ts @@ -1,7 +1,7 @@ import { AppEvents } from '@grafana/data'; import { SceneQueryRunner, VizPanel } from '@grafana/scenes'; import appEvents from 'app/core/app_events'; -import { KioskMode } from 'app/types'; +import { KioskMode } from 'app/types/dashboard'; import { getCloneKey } from '../utils/clone'; diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.ts b/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.ts index 1740fe87c8a..3d9acceed0b 100644 --- a/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.ts +++ b/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.ts @@ -5,7 +5,7 @@ import { config, locationService } from '@grafana/runtime'; import { SceneObjectUrlSyncHandler, SceneObjectUrlValues, VizPanel } from '@grafana/scenes'; import appEvents from 'app/core/app_events'; import { contextSrv } from 'app/core/core'; -import { KioskMode } from 'app/types'; +import { KioskMode } from 'app/types/dashboard'; import { PanelInspectDrawer } from '../inspect/PanelInspectDrawer'; import { buildPanelEditScene } from '../panel-edit/PanelEditor'; diff --git a/public/app/features/dashboard-scene/scene/ManagedDashboardNavBarBadge.tsx b/public/app/features/dashboard-scene/scene/ManagedDashboardNavBarBadge.tsx index 3e6761dfed0..fe025098988 100644 --- a/public/app/features/dashboard-scene/scene/ManagedDashboardNavBarBadge.tsx +++ b/public/app/features/dashboard-scene/scene/ManagedDashboardNavBarBadge.tsx @@ -1,6 +1,6 @@ import { Badge } from '@grafana/ui'; import { AnnoKeyManagerIdentity, AnnoKeyManagerKind, ManagerKind } from 'app/features/apiserver/types'; -import { DashboardMeta } from 'app/types'; +import { DashboardMeta } from 'app/types/dashboard'; export default function ManagedDashboardNavBarBadge({ meta }: { meta: DashboardMeta }) { const obj = meta.k8s; diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx index abca5175425..3a6e2f7935c 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.test.tsx @@ -7,7 +7,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { LocationServiceProvider, config, locationService } from '@grafana/runtime'; import { SceneQueryRunner, SceneTimeRange, UrlSyncContextProvider, VizPanel } from '@grafana/scenes'; import { playlistSrv } from 'app/features/playlist/PlaylistSrv'; -import { DashboardMeta } from 'app/types'; +import { DashboardMeta } from 'app/types/dashboard'; import { buildPanelEditScene } from '../panel-edit/PanelEditor'; diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx index 2e36a248586..49b4a3c9f53 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx @@ -13,7 +13,7 @@ import { LS_PANEL_COPY_KEY } from 'app/core/constants'; import { contextSrv } from 'app/core/core'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { playlistSrv } from 'app/features/playlist/PlaylistSrv'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { shareDashboardType } from '../../dashboard/components/ShareModal/utils'; import { selectFolderRepository } from '../../provisioning/utils/selectors'; diff --git a/public/app/features/dashboard-scene/scene/PanelMenuBehavior.test.tsx b/public/app/features/dashboard-scene/scene/PanelMenuBehavior.test.tsx index 998541edf80..10191b32a58 100644 --- a/public/app/features/dashboard-scene/scene/PanelMenuBehavior.test.tsx +++ b/public/app/features/dashboard-scene/scene/PanelMenuBehavior.test.tsx @@ -23,7 +23,7 @@ import { GetExploreUrlArguments } from 'app/core/utils/explore'; import { grantUserPermissions } from 'app/features/alerting/unified/mocks'; import { scenesPanelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form'; import * as storeModule from 'app/store/store'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { buildPanelEditScene } from '../panel-edit/PanelEditor'; diff --git a/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx b/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx index 8b07ede1cb8..d10b2ab5b65 100644 --- a/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx +++ b/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx @@ -29,7 +29,7 @@ import { pluginExtensionRegistries } from 'app/features/plugins/extensions/regis import { GetPluginExtensions } from 'app/features/plugins/extensions/types'; import { createExtensionSubMenu } from 'app/features/plugins/extensions/utils'; import { dispatch } from 'app/store/store'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ShowConfirmModalEvent } from 'app/types/events'; import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer'; diff --git a/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts b/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts index cde032a413e..0d7ad8f85a8 100644 --- a/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts +++ b/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts @@ -4,7 +4,7 @@ import { sceneGraph, VizPanel } from '@grafana/scenes'; import appEvents from 'app/core/app_events'; import { KeybindingSet } from 'app/core/services/KeybindingSet'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { shareDashboardType } from '../../dashboard/components/ShareModal/utils'; import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer'; diff --git a/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.ts b/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.ts index e96284c1008..9e73bed659e 100644 --- a/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.ts +++ b/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.ts @@ -12,7 +12,7 @@ import { getV2SchemaVariables, } from 'app/features/dashboard/utils/tracking'; import { DashboardJson } from 'app/features/manage-dashboards/types'; -import { DashboardMeta, SaveDashboardResponseDTO } from 'app/types'; +import { DashboardMeta, SaveDashboardResponseDTO } from 'app/types/dashboard'; import { getRawDashboardChanges, getRawDashboardV2Changes } from '../saving/getDashboardChanges'; import { DashboardChangeInfo } from '../saving/shared'; diff --git a/public/app/features/dashboard-scene/serialization/buildNewDashboardSaveModel.ts b/public/app/features/dashboard-scene/serialization/buildNewDashboardSaveModel.ts index 705ab15ddee..436563c8379 100644 --- a/public/app/features/dashboard-scene/serialization/buildNewDashboardSaveModel.ts +++ b/public/app/features/dashboard-scene/serialization/buildNewDashboardSaveModel.ts @@ -13,7 +13,7 @@ import { import { AnnoKeyFolder } from 'app/features/apiserver/types'; import { DashboardWithAccessInfo } from 'app/features/dashboard/api/types'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; export async function buildNewDashboardSaveModel(urlFolderUid?: string): Promise<DashboardDTO> { let variablesList = defaultDashboard.templating?.list; diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts index f37598bb45e..12f14fee511 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts @@ -51,7 +51,7 @@ import { DeprecatedInternalId, } from 'app/features/apiserver/types'; import { DashboardWithAccessInfo } from 'app/features/dashboard/api/types'; -import { DashboardMeta } from 'app/types'; +import { DashboardMeta } from 'app/types/dashboard'; import { addPanelsOnLoadBehavior } from '../addToDashboard/addPanelsOnLoadBehavior'; import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer'; diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts index cc1e2ee2ec1..ef03bdd17ee 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts @@ -25,7 +25,7 @@ import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { createPanelSaveModel } from 'app/features/dashboard/state/__fixtures__/dashboardFixtures'; import { SHARED_DASHBOARD_QUERY, DASHBOARD_DATASOURCE_PLUGIN_ID } from 'app/plugins/datasource/dashboard/constants'; -import { DashboardDataDTO } from 'app/types'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet'; import { LibraryPanelBehavior } from '../scene/LibraryPanelBehavior'; diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts index 2c51bee4427..2936ccfcf49 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts @@ -25,7 +25,7 @@ import { contextSrv } from 'app/core/core'; import { K8S_V1_DASHBOARD_API_CONFIG } from 'app/features/dashboard/api/v1'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { DashboardDTO, DashboardDataDTO } from 'app/types'; +import { DashboardDTO, DashboardDataDTO } from 'app/types/dashboard'; import { addPanelsOnLoadBehavior } from '../addToDashboard/addPanelsOnLoadBehavior'; import { AlertStatesDataLayer } from '../scene/AlertStatesDataLayer'; diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts index 9b6ec578234..9d4fbea9aa2 100644 --- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts +++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts @@ -21,7 +21,7 @@ import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { getTimeRange } from 'app/features/dashboard/utils/timeRange'; import { reduceTransformRegistryItem } from 'app/features/transformers/editors/ReduceTransformerEditor'; import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard/constants'; -import { DashboardDataDTO } from 'app/types'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet'; import { LibraryPanelBehavior } from '../scene/LibraryPanelBehavior'; diff --git a/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx b/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx index 228240f721b..ad47d202db9 100644 --- a/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx +++ b/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx @@ -31,9 +31,16 @@ import { dashboardSceneGraph } from '../utils/dashboardSceneGraph'; import { getDashboardSceneFor } from '../utils/utils'; import { DeleteDashboardButton } from './DeleteDashboardButton'; +import { MoveProvisionedDashboardDrawer } from './MoveProvisionedDashboardDrawer'; import { DashboardEditView, DashboardEditViewState, useDashboardEditPageNav } from './utils'; -export interface GeneralSettingsEditViewState extends DashboardEditViewState {} +export interface GeneralSettingsEditViewState extends DashboardEditViewState { + showMoveModal?: boolean; + moveModalProps?: { + targetFolderUID?: string; + targetFolderTitle?: string; + }; +} export class GeneralSettingsEditView extends SceneObjectBase<GeneralSettingsEditViewState> @@ -156,10 +163,40 @@ export class GeneralSettingsEditView public onDeleteDashboard = () => {}; + public onProvisionedFolderChange = async (newUID?: string, newTitle?: string) => { + if (newUID !== this._dashboard.state.meta.folderUid) { + this.setState({ + showMoveModal: true, + moveModalProps: { + targetFolderUID: newUID, + targetFolderTitle: newTitle, + }, + }); + } + }; + + public onMoveModalDismiss = () => { + this.setState({ + showMoveModal: false, + moveModalProps: undefined, + }); + }; + + private onMoveSuccess = (folderUID: string, folderTitle: string) => { + const newMeta = { + ...this._dashboard.state.meta, + folderUid: folderUID, + folderTitle: folderTitle, + }; + this._dashboard.setState({ meta: newMeta }); + this.onMoveModalDismiss(); + }; + static Component = ({ model }: SceneComponentProps<GeneralSettingsEditView>) => { const dashboard = model.getDashboard(); const { navModel, pageNav } = useDashboardEditPageNav(dashboard, model.getUrlKey()); const { title, description, tags, meta, editable } = dashboard.useState(); + const { showMoveModal, moveModalProps } = model.useState(); const { sync: graphTooltip } = model.getCursorSync()?.useState() || {}; const { timeZone, weekStart, UNSAFE_nowDelay: nowDelay } = model.getTimeRange().useState(); const { intervals } = model.getRefreshPicker().useState(); @@ -201,8 +238,9 @@ export class GeneralSettingsEditView <Page navModel={navModel} pageNav={pageNav} layout={PageLayoutType.Standard}> <NavToolbarActions dashboard={dashboard} /> <div style={{ maxWidth: '600px' }}> - <Box marginBottom={5}> + <Box display="flex" direction="column" gap={2} marginBottom={5}> <Field + noMargin label={ <Stack justifyContent="space-between"> <Label htmlFor="title-input"> @@ -222,6 +260,7 @@ export class GeneralSettingsEditView /> </Field> <Field + noMargin label={ <Stack justifyContent="space-between"> <Label htmlFor="description-input"> @@ -240,18 +279,18 @@ export class GeneralSettingsEditView onChange={(e: ChangeEvent<HTMLTextAreaElement>) => model.onDescriptionChange(e.target.value)} /> </Field> - <Field label={t('dashboard-settings.general.tags-label', 'Tags')}> + <Field noMargin label={t('dashboard-settings.general.tags-label', 'Tags')}> <TagsInput id="tags-input" tags={tags} onChange={model.onTagsChange} width={40} /> </Field> - <Field label={t('dashboard-settings.general.folder-label', 'Folder')}> - {dashboard.isManagedRepository() ? ( - <Input readOnly value={meta.folderTitle} /> - ) : ( - <FolderPicker value={meta.folderUid} onChange={model.onFolderChange} /> - )} + <Field noMargin label={t('dashboard-settings.general.folder-label', 'Folder')}> + <FolderPicker + value={meta.folderUid} + onChange={dashboard.isManagedRepository() ? model.onProvisionedFolderChange : model.onFolderChange} + /> </Field> <Field + noMargin label={t('dashboard-settings.general.editable-label', 'Editable')} description={t( 'dashboard-settings.general.editable-description', @@ -282,33 +321,51 @@ export class GeneralSettingsEditView label={t('dashboard-settings.general.panel-options-label', 'Panel options')} isOpen={true} > - <Field - label={t('dashboard-settings.general.panel-options-graph-tooltip-label', 'Graph tooltip')} - description={t( - 'dashboard-settings.general.panel-options-graph-tooltip-description', - 'Controls tooltip and hover highlight behavior across different panels. Reload the dashboard for changes to take effect' - )} - > - <RadioButtonGroup onChange={model.onTooltipChange} options={GRAPH_TOOLTIP_OPTIONS} value={graphTooltip} /> - </Field> + <Stack direction="column" gap={2}> + <Field + noMargin + label={t('dashboard-settings.general.panel-options-graph-tooltip-label', 'Graph tooltip')} + description={t( + 'dashboard-settings.general.panel-options-graph-tooltip-description', + 'Controls tooltip and hover highlight behavior across different panels. Reload the dashboard for changes to take effect' + )} + > + <RadioButtonGroup + onChange={model.onTooltipChange} + options={GRAPH_TOOLTIP_OPTIONS} + value={graphTooltip} + /> + </Field> - <Field - label={t('dashboard-settings.general.panels-preload-label', 'Preload panels')} - description={t( - 'dashboard-settings.general.panels-preload-description', - 'When enabled all panels will start loading as soon as the dashboard has been loaded.' - )} - > - <Switch - id="preload-panels-dashboards-toggle" - value={dashboard.state.preload} - onChange={(e) => model.onPreloadChange(e.currentTarget.checked)} - /> - </Field> + <Field + noMargin + label={t('dashboard-settings.general.panels-preload-label', 'Preload panels')} + description={t( + 'dashboard-settings.general.panels-preload-description', + 'When enabled all panels will start loading as soon as the dashboard has been loaded.' + )} + > + <Switch + id="preload-panels-dashboards-toggle" + value={dashboard.state.preload} + onChange={(e) => model.onPreloadChange(e.currentTarget.checked)} + /> + </Field> + </Stack> </CollapsableSection> <Box marginTop={3}>{meta.canDelete && <DeleteDashboardButton dashboard={dashboard} />}</Box> </div> + + {showMoveModal && moveModalProps && ( + <MoveProvisionedDashboardDrawer + dashboard={dashboard} + targetFolderUID={moveModalProps.targetFolderUID} + targetFolderTitle={moveModalProps.targetFolderTitle} + onDismiss={model.onMoveModalDismiss} + onSuccess={model.onMoveSuccess} + /> + )} </Page> ); }; diff --git a/public/app/features/dashboard-scene/settings/JsonModelEditView.tsx b/public/app/features/dashboard-scene/settings/JsonModelEditView.tsx index 803068b979d..c6b40b81ff0 100644 --- a/public/app/features/dashboard-scene/settings/JsonModelEditView.tsx +++ b/public/app/features/dashboard-scene/settings/JsonModelEditView.tsx @@ -11,7 +11,7 @@ import { Page } from 'app/core/components/Page/Page'; import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; import { isDashboardV2Spec } from 'app/features/dashboard/api/utils'; import { getPrettyJSON } from 'app/features/inspector/utils/utils'; -import { DashboardDataDTO, SaveDashboardResponseDTO } from 'app/types'; +import { DashboardDataDTO, SaveDashboardResponseDTO } from 'app/types/dashboard'; import { NameAlreadyExistsError, diff --git a/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardDrawer.tsx b/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardDrawer.tsx new file mode 100644 index 00000000000..b1caef27bf5 --- /dev/null +++ b/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardDrawer.tsx @@ -0,0 +1,43 @@ +import { useProvisionedDashboardData } from '../saving/provisioned/hooks'; +import { DashboardScene } from '../scene/DashboardScene'; + +import { MoveProvisionedDashboardForm } from './MoveProvisionedDashboardForm'; + +export interface Props { + dashboard: DashboardScene; + targetFolderUID?: string; + targetFolderTitle?: string; + onDismiss: () => void; + onSuccess: (folderUID: string, folderTitle: string) => void; +} + +export function MoveProvisionedDashboardDrawer({ + dashboard, + targetFolderUID, + targetFolderTitle, + onDismiss, + onSuccess, +}: Props) { + const { defaultValues, loadedFromRef, readOnly, isGitHub, workflowOptions, isNew } = + useProvisionedDashboardData(dashboard); + + if (!defaultValues) { + return null; + } + + return ( + <MoveProvisionedDashboardForm + dashboard={dashboard} + defaultValues={defaultValues} + loadedFromRef={loadedFromRef} + readOnly={readOnly} + isGitHub={isGitHub} + isNew={isNew} + workflowOptions={workflowOptions} + targetFolderUID={targetFolderUID} + targetFolderTitle={targetFolderTitle} + onDismiss={onDismiss} + onSuccess={onSuccess} + /> + ); +} diff --git a/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardForm.test.tsx b/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardForm.test.tsx new file mode 100644 index 00000000000..1e6496d4229 --- /dev/null +++ b/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardForm.test.tsx @@ -0,0 +1,241 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { getAppEvents } from '@grafana/runtime'; +import { useGetFolderQuery } from 'app/api/clients/folder/v1beta1'; +import { + useCreateRepositoryFilesWithPathMutation, + useDeleteRepositoryFilesWithPathMutation, + useGetRepositoryFilesWithPathQuery, +} from 'app/api/clients/provisioning/v0alpha1'; +import { AnnoKeySourcePath } from 'app/features/apiserver/types'; + +import { DashboardScene } from '../scene/DashboardScene'; +import { useProvisionedRequestHandler } from '../utils/useProvisionedRequestHandler'; + +import { MoveProvisionedDashboardForm, Props } from './MoveProvisionedDashboardForm'; + +jest.mock('@grafana/runtime', () => { + const actual = jest.requireActual('@grafana/runtime'); + return { + ...actual, + getAppEvents: jest.fn(), + }; +}); + +jest.mock('app/api/clients/provisioning/v0alpha1', () => ({ + useGetRepositoryFilesWithPathQuery: jest.fn(), + useCreateRepositoryFilesWithPathMutation: jest.fn(), + useDeleteRepositoryFilesWithPathMutation: jest.fn(), +})); + +jest.mock('app/api/clients/folder/v1beta1', () => ({ + useGetFolderQuery: jest.fn(), +})); + +jest.mock('../utils/useProvisionedRequestHandler', () => ({ + useProvisionedRequestHandler: jest.fn(), +})); + +jest.mock('react-router-dom-v5-compat', () => ({ + useNavigate: () => jest.fn(), +})); + +jest.mock('../components/Provisioned/ResourceEditFormSharedFields', () => ({ + ResourceEditFormSharedFields: () => <div data-testid="resource-edit-form" />, +})); + +function setup(props: Partial<Props> = {}) { + const user = userEvent.setup(); + + const mockDashboard = { + useState: jest.fn().mockReturnValue({ + editPanel: null, + }), + state: { + title: 'Test Dashboard', + }, + } as unknown as DashboardScene; + + const defaultProps: Props = { + dashboard: mockDashboard, + defaultValues: { + repo: 'test-repo', + path: 'folder1/dashboard.json', + ref: 'main', + workflow: 'write', + comment: '', + title: 'Test Dashboard', + description: '', + folder: { uid: '', title: '' }, + }, + readOnly: false, + isGitHub: true, + workflowOptions: [ + { label: 'Write', value: 'write' }, + { label: 'Branch', value: 'branch' }, + ], + targetFolderUID: 'target-folder-uid', + targetFolderTitle: 'Target Folder', + onDismiss: jest.fn(), + onSuccess: jest.fn(), + ...props, + }; + + return { + user, + ...render(<MoveProvisionedDashboardForm {...defaultProps} />), + props: defaultProps, + }; +} + +const mockCreateRequest = { + isSuccess: false, + isError: false, + isLoading: false, + error: null, +}; + +const mockDeleteRequest = { + isSuccess: false, + isError: false, + isLoading: false, + error: null, +}; + +describe('MoveProvisionedDashboardForm', () => { + beforeEach(() => { + jest.clearAllMocks(); + + // Setup default mocks + const mockAppEvents = { + publish: jest.fn(), + }; + (getAppEvents as jest.Mock).mockReturnValue(mockAppEvents); + + // Mock hooks + (useGetRepositoryFilesWithPathQuery as jest.Mock).mockReturnValue({ + data: { + resource: { + file: { spec: { title: 'Test Dashboard' } }, + dryRun: { + metadata: { + annotations: { + [AnnoKeySourcePath]: 'folder1/dashboard.json', + }, + }, + }, + }, + }, + isLoading: false, + }); + + (useGetFolderQuery as jest.Mock).mockReturnValue({ + data: { + metadata: { + annotations: { + [AnnoKeySourcePath]: 'target-folder', + }, + }, + }, + isLoading: false, + }); + + (useCreateRepositoryFilesWithPathMutation as jest.Mock).mockReturnValue([jest.fn(), mockCreateRequest]); + + (useDeleteRepositoryFilesWithPathMutation as jest.Mock).mockReturnValue([jest.fn(), mockDeleteRequest]); + + (useProvisionedRequestHandler as jest.Mock).mockReturnValue(undefined); + }); + + it('should render the form with correct title and subtitle', () => { + setup(); + + expect(screen.getByText('Move Provisioned Dashboard')).toBeInTheDocument(); + expect(screen.getByText('Test Dashboard')).toBeInTheDocument(); + }); + + it('should render form even when currentFileData is not available', () => { + (useGetRepositoryFilesWithPathQuery as jest.Mock).mockReturnValue({ + data: null, + isLoading: false, + }); + + setup(); + + // Form should still render, but move button should be disabled + expect(screen.getByText('Move Provisioned Dashboard')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /move dashboard/i })).toBeDisabled(); + }); + + it('should show loading spinner when file data is loading', () => { + (useGetRepositoryFilesWithPathQuery as jest.Mock).mockReturnValue({ + data: null, + isLoading: true, + }); + + setup(); + + expect(screen.getByText('Loading dashboard data')).toBeInTheDocument(); + }); + + it('should show read-only alert when repository is read-only', () => { + setup({ readOnly: true }); + + expect(screen.getByText('This repository is read only')).toBeInTheDocument(); + expect(screen.getByText(/This dashboard cannot be moved directly from Grafana/)).toBeInTheDocument(); + }); + + it('should show target path input with calculated path', () => { + setup(); + + expect(screen.getByDisplayValue('target-folder/dashboard.json')).toBeInTheDocument(); + }); + + it('should show error alert when file data has errors', () => { + (useGetRepositoryFilesWithPathQuery as jest.Mock).mockReturnValue({ + data: { + errors: ['File not found', 'Permission denied'], + resource: null, + }, + isLoading: false, + }); + + setup(); + + expect(screen.getByText('Error loading dashboard')).toBeInTheDocument(); + expect(screen.getByText('File not found')).toBeInTheDocument(); + expect(screen.getByText('Permission denied')).toBeInTheDocument(); + }); + + it('should disable move button when form is submitting', () => { + (useCreateRepositoryFilesWithPathMutation as jest.Mock).mockReturnValue([ + jest.fn(), + { + ...mockCreateRequest, + isLoading: true, + }, + ]); + + setup(); + + const moveButton = screen.getByRole('button', { name: /moving/i }); + expect(moveButton).toBeDisabled(); + expect(moveButton).toHaveTextContent('Moving...'); + }); + + it('should show move dashboard button when not loading', () => { + setup(); + + expect(screen.getByRole('button', { name: /move dashboard/i })).toBeInTheDocument(); + }); + + it('should call onDismiss when cancel button is clicked', async () => { + const { user, props } = setup(); + + const cancelButton = screen.getByRole('button', { name: /cancel/i }); + await user.click(cancelButton); + + expect(props.onDismiss).toHaveBeenCalled(); + }); +}); diff --git a/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardForm.tsx b/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardForm.tsx new file mode 100644 index 00000000000..6a17c8df03b --- /dev/null +++ b/public/app/features/dashboard-scene/settings/MoveProvisionedDashboardForm.tsx @@ -0,0 +1,238 @@ +import { useEffect, useState } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { useNavigate } from 'react-router-dom-v5-compat'; + +import { AppEvents } from '@grafana/data'; +import { Trans, t } from '@grafana/i18n'; +import { getAppEvents } from '@grafana/runtime'; +import { Alert, Button, Drawer, Field, Input, Spinner, Stack } from '@grafana/ui'; +import { useGetFolderQuery } from 'app/api/clients/folder/v1beta1'; +import { + useCreateRepositoryFilesWithPathMutation, + useDeleteRepositoryFilesWithPathMutation, + useGetRepositoryFilesWithPathQuery, +} from 'app/api/clients/provisioning/v0alpha1'; +import { AnnoKeySourcePath } from 'app/features/apiserver/types'; + +import { ResourceEditFormSharedFields } from '../components/Provisioned/ResourceEditFormSharedFields'; +import { ProvisionedDashboardFormData } from '../saving/shared'; +import { DashboardScene } from '../scene/DashboardScene'; +import { useProvisionedRequestHandler } from '../utils/useProvisionedRequestHandler'; + +export interface Props { + dashboard: DashboardScene; + defaultValues: ProvisionedDashboardFormData; + readOnly: boolean; + isGitHub: boolean; + isNew?: boolean; + workflowOptions: Array<{ label: string; value: string }>; + loadedFromRef?: string; + targetFolderUID?: string; + targetFolderTitle?: string; + onDismiss: () => void; + onSuccess: (folderUID: string, folderTitle: string) => void; +} + +export function MoveProvisionedDashboardForm({ + dashboard, + defaultValues, + loadedFromRef, + readOnly, + isGitHub, + isNew, + workflowOptions, + targetFolderUID, + targetFolderTitle, + onDismiss, + onSuccess, +}: Props) { + const methods = useForm<ProvisionedDashboardFormData>({ defaultValues }); + const { editPanel: panelEditor } = dashboard.useState(); + const { handleSubmit, watch } = methods; + const appEvents = getAppEvents(); + + const [ref, workflow] = watch(['ref', 'workflow']); + + const { data: currentFileData, isLoading: isLoadingFileData } = useGetRepositoryFilesWithPathQuery({ + name: defaultValues.repo, + path: defaultValues.path, + }); + + const { data: targetFolder } = useGetFolderQuery({ name: targetFolderUID! }, { skip: !targetFolderUID }); + + const [createFile, createRequest] = useCreateRepositoryFilesWithPathMutation(); + const [deleteFile, deleteRequest] = useDeleteRepositoryFilesWithPathMutation(); + const [targetPath, setTargetPath] = useState<string>(''); + + const navigate = useNavigate(); + + useEffect(() => { + const currentSourcePath = currentFileData?.resource?.dryRun?.metadata?.annotations?.[AnnoKeySourcePath]; + if (!targetFolderUID || !targetFolder || !currentSourcePath) { + return; + } + + const folderAnnotations = targetFolder.metadata.annotations || {}; + const targetFolderPath = folderAnnotations[AnnoKeySourcePath] || targetFolderTitle; + + const filename = currentSourcePath.split('/').pop(); + const newPath = `${targetFolderPath}/${filename}`; + + setTargetPath(newPath); + }, [currentFileData, targetFolder, targetFolderUID, targetFolderTitle]); + + const handleSubmitForm = async ({ repo, path, comment }: ProvisionedDashboardFormData) => { + if (!currentFileData?.resource?.file) { + appEvents.publish({ + type: AppEvents.alertError.name, + payload: [ + t( + 'dashboard-scene.move-provisioned-dashboard-form.current-file-not-found', + 'Current dashboard file could not be found' + ), + ], + }); + return; + } + + const branchRef = workflow === 'write' ? loadedFromRef : ref; + const commitMessage = comment || `Move dashboard: ${dashboard.state.title}`; + + try { + await createFile({ + name: repo, + path: targetPath, + ref: branchRef, + message: commitMessage, + body: currentFileData.resource.file, + }).unwrap(); + + await deleteFile({ + name: repo, + path: path, + ref: branchRef, + message: commitMessage, + }).unwrap(); + } catch (error) { + if (createRequest.isSuccess && !deleteRequest.isSuccess) { + appEvents.publish({ + type: AppEvents.alertWarning.name, + payload: [ + t( + 'dashboard-scene.move-provisioned-dashboard-form.partial-failure-warning', + 'Dashboard was created at new location but could not be deleted from original location. Please manually remove the old file.' + ), + ], + }); + } + appEvents.publish({ + type: AppEvents.alertError.name, + payload: [t('dashboard-scene.move-provisioned-dashboard-form.api-error', 'Failed to move dashboard'), error], + }); + } + }; + + const onWriteSuccess = () => { + panelEditor?.onDiscard(); + if (targetFolderUID && targetFolderTitle) { + onSuccess(targetFolderUID, targetFolderTitle); + } + navigate('/dashboards'); + }; + + const onBranchSuccess = () => { + panelEditor?.onDiscard(); + navigate(`/dashboards?new_pull_request_url=${createRequest.data?.urls?.newPullRequestURL}`); + }; + + useProvisionedRequestHandler({ + dashboard, + request: createRequest, + workflow, + handlers: { + onBranchSuccess, + onWriteSuccess, + }, + }); + + const isLoading = createRequest.isLoading || deleteRequest.isLoading; + + return ( + <Drawer + title={t('dashboard-scene.move-provisioned-dashboard-form.drawer-title', 'Move Provisioned Dashboard')} + subtitle={dashboard.state.title} + onClose={onDismiss} + > + <FormProvider {...methods}> + <form onSubmit={handleSubmit(handleSubmitForm)}> + <Stack direction="column" gap={2}> + {readOnly && ( + <Alert + title={t( + 'dashboard-scene.move-provisioned-dashboard-form.title-this-repository-is-read-only', + 'This repository is read only' + )} + > + <Trans i18nKey="dashboard-scene.move-provisioned-dashboard-form.move-read-only-message"> + This dashboard cannot be moved directly from Grafana because the repository is read-only. To move this + dashboard, please move the file in your Git repository. + </Trans> + </Alert> + )} + + {isLoadingFileData && ( + <Stack alignItems="center" gap={2}> + <Spinner /> + <div> + {t('dashboard-scene.move-provisioned-dashboard-form.loading-file-data', 'Loading dashboard data')} + </div> + </Stack> + )} + + {currentFileData?.errors?.length && currentFileData.errors.length > 0 && ( + <Alert + title={t('dashboard-scene.move-provisioned-dashboard-form.file-load-error', 'Error loading dashboard')} + severity="error" + > + {currentFileData.errors.map((error, index) => ( + <div key={index}>{error}</div> + ))} + </Alert> + )} + + <Field + noMargin + label={t('dashboard-scene.move-provisioned-dashboard-form.target-path-label', 'Target path')} + > + <Input readOnly value={targetPath} /> + </Field> + + <ResourceEditFormSharedFields + resourceType="dashboard" + isNew={isNew} + readOnly={readOnly} + workflow={workflow} + workflowOptions={workflowOptions} + isGitHub={isGitHub} + /> + + <Stack gap={2}> + <Button + variant="primary" + type="submit" + disabled={isLoading || readOnly || !currentFileData || isLoadingFileData} + > + {isLoading + ? t('dashboard-scene.move-provisioned-dashboard-form.moving', 'Moving...') + : t('dashboard-scene.move-provisioned-dashboard-form.move-action', 'Move dashboard')} + </Button> + <Button variant="secondary" onClick={onDismiss} fill="outline"> + <Trans i18nKey="dashboard-scene.move-provisioned-dashboard-form.cancel-action">Cancel</Trans> + </Button> + </Stack> + </Stack> + </form> + </FormProvider> + </Drawer> + ); +} diff --git a/public/app/features/dashboard-scene/settings/PermissionsEditView.tsx b/public/app/features/dashboard-scene/settings/PermissionsEditView.tsx index 5dfa1a49659..d438ff9e694 100644 --- a/public/app/features/dashboard-scene/settings/PermissionsEditView.tsx +++ b/public/app/features/dashboard-scene/settings/PermissionsEditView.tsx @@ -3,7 +3,7 @@ import { SceneComponentProps, SceneObjectBase } from '@grafana/scenes'; import { Permissions } from 'app/core/components/AccessControl'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { DashboardScene } from '../scene/DashboardScene'; import { NavToolbarActions } from '../scene/NavToolbarActions'; diff --git a/public/app/features/dashboard-scene/settings/utils.ts b/public/app/features/dashboard-scene/settings/utils.ts index 907612875c8..88011f08b00 100644 --- a/public/app/features/dashboard-scene/settings/utils.ts +++ b/public/app/features/dashboard-scene/settings/utils.ts @@ -5,7 +5,8 @@ import { t } from '@grafana/i18n'; import { SceneObject, SceneObjectState } from '@grafana/scenes'; import { contextSrv } from 'app/core/core'; import { getNavModel } from 'app/core/selectors/navModel'; -import { AccessControlAction, useSelector } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { useSelector } from 'app/types/store'; import { DashboardScene } from '../scene/DashboardScene'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/ShareMenu.test.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/ShareMenu.test.tsx index 91439fe662a..c049579fb38 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/ShareMenu.test.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/ShareMenu.test.tsx @@ -3,9 +3,9 @@ import { render, screen } from '@testing-library/react'; import { selectors as e2eSelectors } from '@grafana/e2e-selectors'; import { SceneTimeRange, VizPanel } from '@grafana/scenes'; import { contextSrv } from 'app/core/services/context_srv'; +import { AccessControlAction } from 'app/types/accessControl'; import { config } from '../../../../core/config'; -import { AccessControlAction } from '../../../../types'; import { grantUserPermissions } from '../../../alerting/unified/mocks'; import { DashboardScene, DashboardSceneState } from '../../scene/DashboardScene'; import { DefaultGridLayoutManager } from '../../scene/layout-default/DefaultGridLayoutManager'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/ShareMenu.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/ShareMenu.tsx index bd8c983e1c8..0a50fb9530e 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/ShareMenu.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/ShareMenu.tsx @@ -7,7 +7,7 @@ import { config, locationService } from '@grafana/runtime'; import { VizPanel } from '@grafana/scenes'; import { IconName, Menu } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { isPublicDashboardsEnabled } from '../../../dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; import { getTrackingSource, shareDashboardType } from '../../../dashboard/components/ShareModal/utils'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/ConfigEmailSharing/ConfigEmailSharing.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/ConfigEmailSharing/ConfigEmailSharing.tsx index d2affefd482..4d6ca049b89 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/ConfigEmailSharing/ConfigEmailSharing.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/ConfigEmailSharing/ConfigEmailSharing.tsx @@ -7,7 +7,7 @@ import { contextSrv } from 'app/core/core'; import { publicDashboardApi, useAddRecipientMutation } from 'app/features/dashboard/api/publicDashboardApi'; import { validEmailRegex } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { useShareDrawerContext } from '../../../../ShareDrawer/ShareDrawerContext'; import ShareConfiguration from '../../ShareConfiguration'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/CreateEmailSharing.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/CreateEmailSharing.tsx index 3f1c51db7b8..4c482660047 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/CreateEmailSharing.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/CreateEmailSharing.tsx @@ -9,7 +9,7 @@ import { contextSrv } from 'app/core/core'; import { useCreatePublicDashboardMutation } from 'app/features/dashboard/api/publicDashboardApi'; import { PublicDashboardShareType } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { EmailSharingPricingAlert } from '../../../../../dashboard/components/ShareModal/SharePublicDashboard/ModalAlerts/EmailSharingPricingAlert'; import { useShareDrawerContext } from '../../../ShareDrawer/ShareDrawerContext'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/PublicShare/CreatePublicSharing.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/PublicShare/CreatePublicSharing.tsx index 8352e8a9495..c871537e4c4 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/PublicShare/CreatePublicSharing.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/PublicShare/CreatePublicSharing.tsx @@ -9,7 +9,7 @@ import { contextSrv } from 'app/core/core'; import { useCreatePublicDashboardMutation } from 'app/features/dashboard/api/publicDashboardApi'; import { PublicDashboardShareType } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PublicDashboardAlert } from '../../../../../dashboard/components/ShareModal/SharePublicDashboard/ModalAlerts/PublicDashboardAlert'; import { useShareDrawerContext } from '../../../ShareDrawer/ShareDrawerContext'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareAlerts.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareAlerts.tsx index 9e74065d62e..6c7b0d55ec7 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareAlerts.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareAlerts.tsx @@ -7,7 +7,7 @@ import { PublicDashboard, PublicDashboardShareType, } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { NoUpsertPermissionsAlert } from '../../../../dashboard/components/ShareModal/SharePublicDashboard/ModalAlerts/NoUpsertPermissionsAlert'; import { PublicDashboardAlert } from '../../../../dashboard/components/ShareModal/SharePublicDashboard/ModalAlerts/PublicDashboardAlert'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareConfiguration.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareConfiguration.tsx index 57d2423e167..62d22223663 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareConfiguration.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareConfiguration.tsx @@ -10,7 +10,7 @@ import { contextSrv } from 'app/core/core'; import { publicDashboardApi, useUpdatePublicDashboardMutation } from 'app/features/dashboard/api/publicDashboardApi'; import { ConfigPublicDashboardForm } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/ConfigPublicDashboard'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { useShareDrawerContext } from '../../ShareDrawer/ShareDrawerContext'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareExternally.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareExternally.tsx index ca95eee9110..41637090ad0 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareExternally.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareExternally.tsx @@ -21,7 +21,7 @@ import { } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; import { getDashboardSceneFor } from 'app/features/dashboard-scene/utils/utils'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ShareDrawerConfirmAction } from '../../ShareDrawer/ShareDrawerConfirmAction'; import { useShareDrawerContext } from '../../ShareDrawer/ShareDrawerContext'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareTypeSelect.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareTypeSelect.tsx index f58c16298ca..89e14df3c5f 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareTypeSelect.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/share-externally/ShareTypeSelect.tsx @@ -14,7 +14,7 @@ import { PublicDashboardShareType, } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { useShareDrawerContext } from '../../ShareDrawer/ShareDrawerContext'; diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/share-snapshot/ShareSnapshot.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/share-snapshot/ShareSnapshot.tsx index 89285aa03a6..75861e9ee92 100644 --- a/public/app/features/dashboard-scene/sharing/ShareButton/share-snapshot/ShareSnapshot.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareButton/share-snapshot/ShareSnapshot.tsx @@ -6,7 +6,7 @@ import { Trans, t } from '@grafana/i18n'; import { SceneComponentProps } from '@grafana/scenes'; import { Alert, Button, ClipboardButton, Spinner, Stack, TextLink } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { SnapshotSharingOptions } from '../../../../dashboard/services/SnapshotSrv'; import { ShareDrawerConfirmAction } from '../../ShareDrawer/ShareDrawerConfirmAction'; diff --git a/public/app/features/dashboard-scene/sharing/ShareModal.tsx b/public/app/features/dashboard-scene/sharing/ShareModal.tsx index db5f89a32fb..f389382cbaf 100644 --- a/public/app/features/dashboard-scene/sharing/ShareModal.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareModal.tsx @@ -6,7 +6,7 @@ import { SceneComponentProps, SceneObjectBase, SceneObjectRef, SceneObjectState, import { Modal, ModalTabsHeader, TabContent } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; import { isPublicDashboardsEnabled } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { getTrackingSource } from '../../dashboard/components/ShareModal/utils'; import { DashboardInteractions } from '../utils/interactions'; diff --git a/public/app/features/dashboard-scene/sharing/public-dashboards/ConfigPublicDashboard.tsx b/public/app/features/dashboard-scene/sharing/public-dashboards/ConfigPublicDashboard.tsx index 303492f492f..99f55253598 100644 --- a/public/app/features/dashboard-scene/sharing/public-dashboards/ConfigPublicDashboard.tsx +++ b/public/app/features/dashboard-scene/sharing/public-dashboards/ConfigPublicDashboard.tsx @@ -8,7 +8,7 @@ import { contextSrv } from 'app/core/core'; import { useDeletePublicDashboardMutation } from 'app/features/dashboard/api/publicDashboardApi'; import { ConfigPublicDashboardBase } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/ConfigPublicDashboard'; import { PublicDashboard } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { shareDashboardType } from '../../../dashboard/components/ShareModal/utils'; import { getDashboardSceneFor } from '../../utils/utils'; diff --git a/public/app/features/dashboard-scene/solo/SoloPanelPage.tsx b/public/app/features/dashboard-scene/solo/SoloPanelPage.tsx index 6de468e798b..e38fd63e5d1 100644 --- a/public/app/features/dashboard-scene/solo/SoloPanelPage.tsx +++ b/public/app/features/dashboard-scene/solo/SoloPanelPage.tsx @@ -11,7 +11,7 @@ import PageLoader from 'app/core/components/PageLoader/PageLoader'; import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; import { DashboardPageRouteParams } from 'app/features/dashboard/containers/types'; -import { DashboardRoutes } from 'app/types'; +import { DashboardRoutes } from 'app/types/dashboard'; import { getDashboardScenePageStateManager } from '../pages/DashboardScenePageStateManager'; import { DashboardScene } from '../scene/DashboardScene'; diff --git a/public/app/features/dashboard-scene/utils/dashboardSessionState.test.ts b/public/app/features/dashboard-scene/utils/dashboardSessionState.test.ts index 9c5badd54f7..fe93bb0a479 100644 --- a/public/app/features/dashboard-scene/utils/dashboardSessionState.test.ts +++ b/public/app/features/dashboard-scene/utils/dashboardSessionState.test.ts @@ -1,6 +1,6 @@ import { config, locationService } from '@grafana/runtime'; import { CustomVariable, UrlSyncManager } from '@grafana/scenes'; -import { DashboardDataDTO } from 'app/types'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene'; diff --git a/public/app/features/dashboard-scene/utils/test-utils.ts b/public/app/features/dashboard-scene/utils/test-utils.ts index 40a547f68e1..7576d80f18c 100644 --- a/public/app/features/dashboard-scene/utils/test-utils.ts +++ b/public/app/features/dashboard-scene/utils/test-utils.ts @@ -14,7 +14,7 @@ import { } from '@grafana/scenes'; import { DashboardLoaderSrv, setDashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv'; import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/constants'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks'; import { DashboardGridItem, RepeatDirection } from '../scene/layout-default/DashboardGridItem'; diff --git a/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx b/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx index 4eb8476eaa5..aa4c06d3684 100644 --- a/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx +++ b/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx @@ -11,7 +11,7 @@ import { Form } from 'app/core/components/Form/Form'; import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; import { SaveDashboardCommand } from 'app/features/dashboard/components/SaveDashboard/types'; import { clearLoadedDashboard } from 'app/features/manage-dashboards/state/actions'; -import { useDispatch, useSelector, StoreState } from 'app/types'; +import { useDispatch, useSelector, StoreState } from 'app/types/store'; import { ImportDashboardFormV2 } from './ImportDashboardFormV2'; diff --git a/public/app/features/dashboard/api/ResponseTransformers.test.ts b/public/app/features/dashboard/api/ResponseTransformers.test.ts index 432aaa300c6..51a0cb00f36 100644 --- a/public/app/features/dashboard/api/ResponseTransformers.test.ts +++ b/public/app/features/dashboard/api/ResponseTransformers.test.ts @@ -25,7 +25,7 @@ import { transformVariableHideToEnum, transformVariableRefreshToEnum, } from 'app/features/dashboard-scene/serialization/transformToV2TypesUtils'; -import { DashboardDataDTO, DashboardDTO } from 'app/types'; +import { DashboardDataDTO, DashboardDTO } from 'app/types/dashboard'; import { getDefaultDatasource, diff --git a/public/app/features/dashboard/api/ResponseTransformers.ts b/public/app/features/dashboard/api/ResponseTransformers.ts index 66dbbb8fdec..aba26fbb7e4 100644 --- a/public/app/features/dashboard/api/ResponseTransformers.ts +++ b/public/app/features/dashboard/api/ResponseTransformers.ts @@ -75,7 +75,7 @@ import { transformVariableHideToEnum, transformVariableRefreshToEnum, } from 'app/features/dashboard-scene/serialization/transformToV2TypesUtils'; -import { DashboardDataDTO, DashboardDTO } from 'app/types'; +import { DashboardDataDTO, DashboardDTO } from 'app/types/dashboard'; import { DashboardWithAccessInfo } from './types'; import { isDashboardResource, isDashboardV0Spec, isDashboardV2Resource } from './utils'; diff --git a/public/app/features/dashboard/api/UnifiedDashboardAPI.test.ts b/public/app/features/dashboard/api/UnifiedDashboardAPI.test.ts index 6dc00b3190f..8b9e3cd2f47 100644 --- a/public/app/features/dashboard/api/UnifiedDashboardAPI.test.ts +++ b/public/app/features/dashboard/api/UnifiedDashboardAPI.test.ts @@ -4,7 +4,7 @@ import { defaultSpec as defaultDashboardV2Spec, } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; import { ResourceList } from 'app/features/apiserver/types'; -import { DashboardDataDTO, DashboardDTO } from 'app/types'; +import { DashboardDataDTO, DashboardDTO } from 'app/types/dashboard'; import { SaveDashboardCommand } from '../components/SaveDashboard/types'; diff --git a/public/app/features/dashboard/api/UnifiedDashboardAPI.ts b/public/app/features/dashboard/api/UnifiedDashboardAPI.ts index 344f3ba9cd2..6851a6c0f76 100644 --- a/public/app/features/dashboard/api/UnifiedDashboardAPI.ts +++ b/public/app/features/dashboard/api/UnifiedDashboardAPI.ts @@ -2,7 +2,7 @@ import { Dashboard } from '@grafana/schema'; import { Spec as DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; import { isResource } from 'app/features/apiserver/guards'; import { Resource, ResourceList } from 'app/features/apiserver/types'; -import { DashboardDataDTO, DashboardDTO } from 'app/types'; +import { DashboardDataDTO, DashboardDTO } from 'app/types/dashboard'; import { SaveDashboardCommand } from '../components/SaveDashboard/types'; diff --git a/public/app/features/dashboard/api/dashboard_api.ts b/public/app/features/dashboard/api/dashboard_api.ts index fb930516a0e..c4a73deccb7 100644 --- a/public/app/features/dashboard/api/dashboard_api.ts +++ b/public/app/features/dashboard/api/dashboard_api.ts @@ -1,6 +1,6 @@ import { Dashboard } from '@grafana/schema'; import { Spec as DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; import { UnifiedDashboardAPI } from './UnifiedDashboardAPI'; import { LegacyDashboardAPI } from './legacy'; diff --git a/public/app/features/dashboard/api/legacy.test.ts b/public/app/features/dashboard/api/legacy.test.ts index b62450fd0ea..ce81f685afb 100644 --- a/public/app/features/dashboard/api/legacy.test.ts +++ b/public/app/features/dashboard/api/legacy.test.ts @@ -1,5 +1,5 @@ import { UrlQueryMap } from '@grafana/data'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; import { LegacyDashboardAPI } from './legacy'; diff --git a/public/app/features/dashboard/api/legacy.ts b/public/app/features/dashboard/api/legacy.ts index 5ce46cdf442..5a9e0b9707c 100644 --- a/public/app/features/dashboard/api/legacy.ts +++ b/public/app/features/dashboard/api/legacy.ts @@ -6,7 +6,7 @@ import appEvents from 'app/core/app_events'; import { Resource, ResourceList } from 'app/features/apiserver/types'; import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher'; import { DeleteDashboardResponse } from 'app/features/manage-dashboards/types'; -import { SaveDashboardResponseDTO, DashboardDTO } from 'app/types'; +import { SaveDashboardResponseDTO, DashboardDTO } from 'app/types/dashboard'; import { SaveDashboardCommand } from '../components/SaveDashboard/types'; diff --git a/public/app/features/dashboard/api/types.ts b/public/app/features/dashboard/api/types.ts index 568fcfcf4a5..90c16d527dc 100644 --- a/public/app/features/dashboard/api/types.ts +++ b/public/app/features/dashboard/api/types.ts @@ -2,7 +2,7 @@ import { UrlQueryMap } from '@grafana/data'; import { Status } from '@grafana/schema/src/schema/dashboard/v2alpha1/types.status.gen'; import { ListOptions, Resource, ResourceList } from 'app/features/apiserver/types'; import { DeleteDashboardResponse } from 'app/features/manage-dashboards/types'; -import { AnnotationsPermissions, SaveDashboardResponseDTO } from 'app/types'; +import { AnnotationsPermissions, SaveDashboardResponseDTO } from 'app/types/dashboard'; import { SaveDashboardCommand } from '../components/SaveDashboard/types'; diff --git a/public/app/features/dashboard/api/utils.ts b/public/app/features/dashboard/api/utils.ts index f49fcb9de12..ea9ba97cf57 100644 --- a/public/app/features/dashboard/api/utils.ts +++ b/public/app/features/dashboard/api/utils.ts @@ -3,7 +3,7 @@ import { Dashboard } from '@grafana/schema/dist/esm/index.gen'; import { Spec as DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; import { Status } from '@grafana/schema/src/schema/dashboard/v2alpha1/types.status.gen'; import { Resource } from 'app/features/apiserver/types'; -import { DashboardDataDTO, DashboardDTO } from 'app/types'; +import { DashboardDataDTO, DashboardDTO } from 'app/types/dashboard'; import { SaveDashboardCommand } from '../components/SaveDashboard/types'; diff --git a/public/app/features/dashboard/api/v1.test.ts b/public/app/features/dashboard/api/v1.test.ts index a037136eeb9..7cdadd0995a 100644 --- a/public/app/features/dashboard/api/v1.test.ts +++ b/public/app/features/dashboard/api/v1.test.ts @@ -1,7 +1,7 @@ import { GrafanaConfig, locationUtil } from '@grafana/data'; import { backendSrv } from 'app/core/services/backend_srv'; import { AnnoKeyFolder } from 'app/features/apiserver/types'; -import { DashboardDataDTO } from 'app/types'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { DashboardWithAccessInfo } from './types'; import { K8sDashboardAPI } from './v1'; diff --git a/public/app/features/dashboard/api/v1.ts b/public/app/features/dashboard/api/v1.ts index 58708bcdcd8..f196e9d71e2 100644 --- a/public/app/features/dashboard/api/v1.ts +++ b/public/app/features/dashboard/api/v1.ts @@ -21,7 +21,7 @@ import { } from 'app/features/apiserver/types'; import { getDashboardUrl } from 'app/features/dashboard-scene/utils/getDashboardUrl'; import { DeleteDashboardResponse } from 'app/features/manage-dashboards/types'; -import { DashboardDataDTO, DashboardDTO, SaveDashboardResponseDTO } from 'app/types'; +import { DashboardDataDTO, DashboardDTO, SaveDashboardResponseDTO } from 'app/types/dashboard'; import { SaveDashboardCommand } from '../components/SaveDashboard/types'; diff --git a/public/app/features/dashboard/api/v2.ts b/public/app/features/dashboard/api/v2.ts index 0a0830e4ffa..676f7b26e27 100644 --- a/public/app/features/dashboard/api/v2.ts +++ b/public/app/features/dashboard/api/v2.ts @@ -19,7 +19,7 @@ import { } from 'app/features/apiserver/types'; import { getDashboardUrl } from 'app/features/dashboard-scene/utils/getDashboardUrl'; import { DeleteDashboardResponse } from 'app/features/manage-dashboards/types'; -import { DashboardDTO, SaveDashboardResponseDTO } from 'app/types'; +import { DashboardDTO, SaveDashboardResponseDTO } from 'app/types/dashboard'; import { SaveDashboardCommand } from '../components/SaveDashboard/types'; diff --git a/public/app/features/dashboard/components/AddPanelButton/AddPanelMenu.test.tsx b/public/app/features/dashboard/components/AddPanelButton/AddPanelMenu.test.tsx index 8b634dab7f0..75cedae0807 100644 --- a/public/app/features/dashboard/components/AddPanelButton/AddPanelMenu.test.tsx +++ b/public/app/features/dashboard/components/AddPanelButton/AddPanelMenu.test.tsx @@ -13,8 +13,8 @@ import { import AddPanelMenu from './AddPanelMenu'; -jest.mock('app/types', () => ({ - ...jest.requireActual('app/types'), +jest.mock('app/types/store', () => ({ + ...jest.requireActual('app/types/store'), useDispatch: () => jest.fn(), useSelector: () => jest.fn(), })); diff --git a/public/app/features/dashboard/components/AddPanelButton/AddPanelMenu.tsx b/public/app/features/dashboard/components/AddPanelButton/AddPanelMenu.tsx index 560f924a8a3..138f2bf285d 100644 --- a/public/app/features/dashboard/components/AddPanelButton/AddPanelMenu.tsx +++ b/public/app/features/dashboard/components/AddPanelButton/AddPanelMenu.tsx @@ -13,7 +13,7 @@ import { onPasteCopiedPanel, } from 'app/features/dashboard/utils/dashboard'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { setInitialDatasource } from '../../state/reducers'; diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index aeb072faf93..78dd8c02a40 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -31,8 +31,9 @@ import { PublicDashboardBadgeLegacy } from 'app/features/dashboard-scene/scene/n import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; import { playlistSrv } from 'app/features/playlist/PlaylistSrv'; import { updateTimeZoneForSession } from 'app/features/profile/state/reducers'; -import { KioskMode, StoreState } from 'app/types'; +import { KioskMode } from 'app/types/dashboard'; import { DashboardMetaChangedEvent, ShowModalReactEvent } from 'app/types/events'; +import { StoreState } from 'app/types/store'; import { DynamicDashNavButtonModel, diff --git a/public/app/features/dashboard/components/DashboardLoading/DashboardFailed.tsx b/public/app/features/dashboard/components/DashboardLoading/DashboardFailed.tsx index 9601c1a026f..69fd629ccd6 100644 --- a/public/app/features/dashboard/components/DashboardLoading/DashboardFailed.tsx +++ b/public/app/features/dashboard/components/DashboardLoading/DashboardFailed.tsx @@ -2,7 +2,8 @@ import { css } from '@emotion/css'; import { Alert } from '@grafana/ui'; import { getMessageFromError } from 'app/core/utils/errors'; -import { DashboardInitError, AppNotificationSeverity } from 'app/types'; +import { AppNotificationSeverity } from 'app/types/appNotifications'; +import { DashboardInitError } from 'app/types/dashboard'; export interface Props { initError?: DashboardInitError; diff --git a/public/app/features/dashboard/components/DashboardLoading/DashboardLoading.tsx b/public/app/features/dashboard/components/DashboardLoading/DashboardLoading.tsx index 5dcb8d870f5..f5e279e5af1 100644 --- a/public/app/features/dashboard/components/DashboardLoading/DashboardLoading.tsx +++ b/public/app/features/dashboard/components/DashboardLoading/DashboardLoading.tsx @@ -4,7 +4,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { locationService } from '@grafana/runtime'; import { Button, HorizontalGroup, Spinner, useStyles2, VerticalGroup } from '@grafana/ui'; -import { DashboardInitPhase } from 'app/types'; +import { DashboardInitPhase } from 'app/types/dashboard'; export interface Props { initPhase: DashboardInitPhase; diff --git a/public/app/features/dashboard/components/DashboardPermissions/AccessControlDashboardPermissions.tsx b/public/app/features/dashboard/components/DashboardPermissions/AccessControlDashboardPermissions.tsx index 6b31090b447..479521c91bd 100644 --- a/public/app/features/dashboard/components/DashboardPermissions/AccessControlDashboardPermissions.tsx +++ b/public/app/features/dashboard/components/DashboardPermissions/AccessControlDashboardPermissions.tsx @@ -1,7 +1,7 @@ import { Permissions } from 'app/core/components/AccessControl'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { SettingsPageProps } from '../DashboardSettings/types'; diff --git a/public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.tsx b/public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.tsx index 5514f11da67..96c63448806 100644 --- a/public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.tsx +++ b/public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.tsx @@ -10,8 +10,8 @@ import { Prompt } from 'app/core/components/FormPrompt/Prompt'; import { contextSrv } from 'app/core/services/context_srv'; import { SaveLibraryPanelModal } from 'app/features/library-panels/components/SaveLibraryPanelModal/SaveLibraryPanelModal'; import { PanelModelWithLibraryPanel } from 'app/features/library-panels/types'; -import { useDispatch } from 'app/types'; import { DashboardSavedEvent } from 'app/types/events'; +import { useDispatch } from 'app/types/store'; import { DashboardModel } from '../../state/DashboardModel'; import { discardPanelChanges, exitPanelEditor } from '../PanelEditor/state/actions'; diff --git a/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx b/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx index 063eccf4ebc..26d52f52a63 100644 --- a/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx +++ b/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx @@ -10,7 +10,7 @@ import { Button, Stack, Text, ToolbarButtonRow } from '@grafana/ui'; import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { DashboardMetaChangedEvent } from 'app/types/events'; import { VariableEditorContainer } from '../../../variables/editor/VariableEditorContainer'; diff --git a/public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx b/public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx index b7eefcba85a..ff10cbf0367 100644 --- a/public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx +++ b/public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx @@ -23,7 +23,7 @@ import { } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ShowMessage, SnapshotTab, SupportSnapshotService } from './SupportSnapshotService'; diff --git a/public/app/features/dashboard/components/Inspector/PanelInspector.tsx b/public/app/features/dashboard/components/Inspector/PanelInspector.tsx index cbd6b6c4e3f..a60e02d2ae0 100644 --- a/public/app/features/dashboard/components/Inspector/PanelInspector.tsx +++ b/public/app/features/dashboard/components/Inspector/PanelInspector.tsx @@ -8,7 +8,7 @@ import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { InspectTab } from 'app/features/inspector/types'; import { getPanelStateForModel } from 'app/features/panel/state/selectors'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { GetDataOptions } from '../../../query/state/PanelQueryRunner'; import { HelpWizard } from '../HelpWizard/HelpWizard'; diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPane.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPane.tsx index d44d699c978..cacdb672a11 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPane.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPane.tsx @@ -3,7 +3,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { useStyles2 } from '@grafana/ui'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { OptionsPaneOptions } from './OptionsPaneOptions'; import { VisualizationButton } from './VisualizationButton'; diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index 81e184b7e59..76c38e695d9 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -30,8 +30,8 @@ import { SaveLibraryPanelModal } from 'app/features/library-panels/components/Sa import { PanelModelWithLibraryPanel } from 'app/features/library-panels/types'; import { getPanelStateForModel } from 'app/features/panel/state/selectors'; import { updateTimeZoneForSession } from 'app/features/profile/state/reducers'; -import { StoreState } from 'app/types'; import { PanelOptionsChangedEvent, ShowModalReactEvent } from 'app/types/events'; +import { StoreState } from 'app/types/store'; import { notifyApp } from '../../../../core/actions'; import { UnlinkModal } from '../../../dashboard-scene/scene/UnlinkModal'; diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditorQueries.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditorQueries.tsx index 020eea8d8e8..b24344519db 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditorQueries.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditorQueries.tsx @@ -5,7 +5,7 @@ import { locationService } from '@grafana/runtime'; import { storeLastUsedDataSourceInLocalStorage } from 'app/features/datasources/components/picker/utils'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { QueryGroup } from 'app/features/query/components/QueryGroup'; -import { QueryGroupDataSource, QueryGroupOptions } from 'app/types'; +import { QueryGroupDataSource, QueryGroupOptions } from 'app/types/query'; import { getDashboardSrv } from '../../services/DashboardSrv'; import { PanelModel } from '../../state/PanelModel'; diff --git a/public/app/features/dashboard/components/PanelEditor/VisualizationButton.tsx b/public/app/features/dashboard/components/PanelEditor/VisualizationButton.tsx index d98b0ae99c2..51a84846f1d 100644 --- a/public/app/features/dashboard/components/PanelEditor/VisualizationButton.tsx +++ b/public/app/features/dashboard/components/PanelEditor/VisualizationButton.tsx @@ -3,7 +3,7 @@ import { css } from '@emotion/css'; import { selectors } from '@grafana/e2e-selectors'; import { t } from '@grafana/i18n'; import { ToolbarButton, ButtonGroup } from '@grafana/ui'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { PanelModel } from '../../state/PanelModel'; import { getPanelPluginWithFallback } from '../../state/selectors'; diff --git a/public/app/features/dashboard/components/PanelEditor/VisualizationSelectPane.tsx b/public/app/features/dashboard/components/PanelEditor/VisualizationSelectPane.tsx index 0edd8c13fe0..ffa32a42254 100644 --- a/public/app/features/dashboard/components/PanelEditor/VisualizationSelectPane.tsx +++ b/public/app/features/dashboard/components/PanelEditor/VisualizationSelectPane.tsx @@ -10,7 +10,7 @@ import { LS_VISUALIZATION_SELECT_TAB_KEY } from 'app/core/constants'; import { PanelLibraryOptionsGroup } from 'app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup'; import { VisualizationSuggestions } from 'app/features/panel/components/VizTypePicker/VisualizationSuggestions'; import { VizTypeChangeDetails } from 'app/features/panel/components/VizTypePicker/types'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { VizTypePicker } from '../../../panel/components/VizTypePicker/VizTypePicker'; import { changePanelPlugin } from '../../../panel/state/actions'; diff --git a/public/app/features/dashboard/components/PanelEditor/state/actions.ts b/public/app/features/dashboard/components/PanelEditor/state/actions.ts index 00a96421aea..f1313156cb0 100644 --- a/public/app/features/dashboard/components/PanelEditor/state/actions.ts +++ b/public/app/features/dashboard/components/PanelEditor/state/actions.ts @@ -4,7 +4,7 @@ import store from 'app/core/store'; import { removePanel } from 'app/features/dashboard/utils/panel'; import { cleanUpPanelState } from 'app/features/panel/state/actions'; import { panelModelAndPluginReady } from 'app/features/panel/state/reducers'; -import { ThunkResult } from 'app/types'; +import { ThunkResult } from 'app/types/store'; import { DashboardModel } from '../../../state/DashboardModel'; import { PanelModel } from '../../../state/PanelModel'; diff --git a/public/app/features/dashboard/components/RepeatRowSelect/RepeatRowSelect.tsx b/public/app/features/dashboard/components/RepeatRowSelect/RepeatRowSelect.tsx index cafa4578540..de68a822e3a 100644 --- a/public/app/features/dashboard/components/RepeatRowSelect/RepeatRowSelect.tsx +++ b/public/app/features/dashboard/components/RepeatRowSelect/RepeatRowSelect.tsx @@ -4,7 +4,7 @@ import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { SceneObject, sceneGraph } from '@grafana/scenes'; import { Combobox, ComboboxOption, Select } from '@grafana/ui'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { getLastKey, getVariablesByKey } from '../../../variables/state/selectors'; diff --git a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.test.tsx b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.test.tsx index 264a2640ebf..de5b14e257c 100644 --- a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.test.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.test.tsx @@ -3,7 +3,7 @@ import { render, screen } from 'test/test-utils'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import * as api from 'app/features/manage-dashboards/state/actions'; -import { SaveDashboardResponseDTO } from 'app/types'; +import { SaveDashboardResponseDTO } from 'app/types/dashboard'; import { SaveDashboardAsForm, SaveDashboardAsFormProps } from './SaveDashboardAsForm'; diff --git a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.test.tsx b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.test.tsx index 3c2ec091317..0f50238b88b 100644 --- a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.test.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.test.tsx @@ -4,7 +4,7 @@ import userEvent from '@testing-library/user-event'; import { Dashboard } from '@grafana/schema'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { createDashboardModelFixture } from 'app/features/dashboard/state/__fixtures__/dashboardFixtures'; -import { SaveDashboardResponseDTO } from 'app/types'; +import { SaveDashboardResponseDTO } from 'app/types/dashboard'; import { SaveDashboardOptions } from '../types'; diff --git a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.tsx b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.tsx index 510222479bd..18f0c61f02e 100644 --- a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.tsx @@ -8,7 +8,7 @@ import { config } from '@grafana/runtime'; import { Dashboard } from '@grafana/schema'; import { Button, Checkbox, TextArea, useStyles2, Stack } from '@grafana/ui'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; -import { SaveDashboardResponseDTO } from 'app/types'; +import { SaveDashboardResponseDTO } from 'app/types/dashboard'; import { GenAIDashboardChangesButton } from '../../GenAI/GenAIDashboardChangesButton'; import { SaveDashboardData, SaveDashboardOptions } from '../types'; diff --git a/public/app/features/dashboard/components/SaveDashboard/types.ts b/public/app/features/dashboard/components/SaveDashboard/types.ts index 7e8eccc605f..05c6356f61f 100644 --- a/public/app/features/dashboard/components/SaveDashboard/types.ts +++ b/public/app/features/dashboard/components/SaveDashboard/types.ts @@ -2,7 +2,7 @@ import { Dashboard } from '@grafana/schema'; import { ObjectMeta } from 'app/features/apiserver/types'; import { CloneOptions, DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { Diffs } from 'app/features/dashboard-scene/settings/version-history/utils'; -import { SaveDashboardResponseDTO } from 'app/types'; +import { SaveDashboardResponseDTO } from 'app/types/dashboard'; export interface SaveDashboardData { clone: Dashboard; // cloned copy diff --git a/public/app/features/dashboard/components/SaveDashboard/useDashboardSave.tsx b/public/app/features/dashboard/components/SaveDashboard/useDashboardSave.tsx index 18435bc1e31..33b036e05a8 100644 --- a/public/app/features/dashboard/components/SaveDashboard/useDashboardSave.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/useDashboardSave.tsx @@ -10,8 +10,8 @@ import { useAppNotification } from 'app/core/copy/appNotification'; import { updateDashboardName } from 'app/core/reducers/navBarTree'; import { useSaveDashboardMutation } from 'app/features/browse-dashboards/api/browseDashboardsAPI'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; -import { useDispatch } from 'app/types'; import { DashboardSavedEvent } from 'app/types/events'; +import { useDispatch } from 'app/types/store'; import { updateDashboardUidLastUsedDatasource } from '../../utils/dashboard'; diff --git a/public/app/features/dashboard/components/ShareModal/ShareModal.tsx b/public/app/features/dashboard/components/ShareModal/ShareModal.tsx index 73597b197f2..16d6220adcc 100644 --- a/public/app/features/dashboard/components/ShareModal/ShareModal.tsx +++ b/public/app/features/dashboard/components/ShareModal/ShareModal.tsx @@ -10,7 +10,7 @@ import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; import { isPanelModelLibraryPanel } from 'app/features/library-panels/guard'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ShareEmbed } from './ShareEmbed'; import { ShareExport } from './ShareExport'; diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/ConfigPublicDashboard.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/ConfigPublicDashboard.tsx index b08aebc934e..ae88d932140 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/ConfigPublicDashboard.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/ConfigPublicDashboard.tsx @@ -26,9 +26,10 @@ import { getTimeRange } from 'app/features/dashboard/utils/timeRange'; import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; import { DeletePublicDashboardModal } from 'app/features/manage-dashboards/components/PublicDashboardListTable/DeletePublicDashboardModal'; +import { AccessControlAction } from 'app/types/accessControl'; +import { useSelector } from 'app/types/store'; import { contextSrv } from '../../../../../../core/services/context_srv'; -import { AccessControlAction, useSelector } from '../../../../../../types'; import { useIsDesktop } from '../../../../utils/screen'; import { ShareModal } from '../../ShareModal'; import { shareDashboardType } from '../../utils'; diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/EmailSharingConfiguration.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/EmailSharingConfiguration.tsx index 930953f859e..c63628c8d17 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/EmailSharingConfiguration.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/EmailSharingConfiguration.tsx @@ -17,7 +17,7 @@ import { import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PublicDashboard, PublicDashboardShareType, validEmailRegex } from '../SharePublicDashboardUtils'; diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/CreatePublicDashboard/CreatePublicDashboard.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/CreatePublicDashboard/CreatePublicDashboard.tsx index 3d4d098023d..7cbc1b6b9f6 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/CreatePublicDashboard/CreatePublicDashboard.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/CreatePublicDashboard/CreatePublicDashboard.tsx @@ -10,7 +10,8 @@ import { useCreatePublicDashboardMutation } from 'app/features/dashboard/api/pub import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { AccessControlAction, useSelector } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { useSelector } from 'app/types/store'; import { NoUpsertPermissionsAlert } from '../ModalAlerts/NoUpsertPermissionsAlert'; import { UnsupportedDataSourcesAlert } from '../ModalAlerts/UnsupportedDataSourcesAlert'; diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.tsx index 1df31f7b635..9636e2dd6ef 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.tsx @@ -6,7 +6,7 @@ import { Spinner, useStyles2 } from '@grafana/ui'; import { useGetPublicDashboardQuery } from 'app/features/dashboard/api/publicDashboardApi'; import { publicDashboardPersisted } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; import { ShareModalTabProps } from 'app/features/dashboard/components/ShareModal/types'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { HorizontalGroup } from '../../../../plugins/admin/components/HorizontalGroup'; diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/utilsTest.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/utilsTest.tsx index f1a2eb97686..993fc55ae8e 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/utilsTest.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/utilsTest.tsx @@ -3,8 +3,9 @@ import { http, HttpResponse } from 'msw'; import * as React from 'react'; import { Provider } from 'react-redux'; +import { DashboardInitPhase } from 'app/types/dashboard'; + import { configureStore } from '../../../../../store/configureStore'; -import { DashboardInitPhase } from '../../../../../types'; import { DashboardModel } from '../../../state/DashboardModel'; import { PanelModel } from '../../../state/PanelModel'; import { createDashboardModelFixture } from '../../../state/__fixtures__/dashboardFixtures'; diff --git a/public/app/features/dashboard/components/SubMenu/SubMenu.tsx b/public/app/features/dashboard/components/SubMenu/SubMenu.tsx index fdc83c449d8..3ec288df413 100644 --- a/public/app/features/dashboard/components/SubMenu/SubMenu.tsx +++ b/public/app/features/dashboard/components/SubMenu/SubMenu.tsx @@ -7,8 +7,8 @@ import { AnnotationQuery, DataQuery, TypedVariableModel, GrafanaTheme2 } from '@ import { t } from '@grafana/i18n'; import { DashboardLink } from '@grafana/schema'; import { stylesFactory, Themeable2, withTheme2 } from '@grafana/ui'; +import { StoreState } from 'app/types/store'; -import { StoreState } from '../../../../types'; import { getSubMenuVariables, getVariablesState } from '../../../variables/state/selectors'; import { DashboardModel } from '../../state/DashboardModel'; diff --git a/public/app/features/dashboard/components/VersionHistory/useDashboardRestore.tsx b/public/app/features/dashboard/components/VersionHistory/useDashboardRestore.tsx index f95568f8159..53c7633fbaa 100644 --- a/public/app/features/dashboard/components/VersionHistory/useDashboardRestore.tsx +++ b/public/app/features/dashboard/components/VersionHistory/useDashboardRestore.tsx @@ -5,7 +5,7 @@ import { locationUtil } from '@grafana/data'; import { config, locationService } from '@grafana/runtime'; import { useAppNotification } from 'app/core/copy/appNotification'; import { historySrv } from 'app/features/dashboard-scene/settings/version-history/HistorySrv'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { dashboardWatcher } from '../../../live/dashboard/dashboardWatcher'; import { DashboardModel } from '../../state/DashboardModel'; diff --git a/public/app/features/dashboard/containers/DashboardPage.test.tsx b/public/app/features/dashboard/containers/DashboardPage.test.tsx index 19e245cf03b..da7454a6d02 100644 --- a/public/app/features/dashboard/containers/DashboardPage.test.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.test.tsx @@ -14,7 +14,7 @@ import { AppChrome } from 'app/core/components/AppChrome/AppChrome'; import { getRouteComponentProps } from 'app/core/navigation/mocks/routeProps'; import { RouteDescriptor } from 'app/core/navigation/types'; import { HOME_NAV_ID } from 'app/core/reducers/navModel'; -import { DashboardInitPhase, DashboardMeta, DashboardRoutes } from 'app/types'; +import { DashboardInitPhase, DashboardMeta, DashboardRoutes } from 'app/types/dashboard'; import { Props as LazyLoaderProps } from '../dashgrid/LazyLoader'; import { DashboardSrv, setDashboardSrv } from '../services/DashboardSrv'; diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index bb4ad2a995c..16ed48ea618 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -17,8 +17,9 @@ import { ID_PREFIX } from 'app/core/reducers/navBarTree'; import { getNavModel } from 'app/core/selectors/navModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher'; -import { KioskMode, StoreState } from 'app/types'; +import { KioskMode } from 'app/types/dashboard'; import { PanelEditEnteredEvent, PanelEditExitedEvent } from 'app/types/events'; +import { StoreState } from 'app/types/store'; import { cancelVariables, templateVarsChangedInUrl } from '../../variables/state/actions'; import { findTemplateVarChanges } from '../../variables/utils'; diff --git a/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx b/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx index ee38959345f..e26b1099d2d 100644 --- a/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx +++ b/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx @@ -13,7 +13,7 @@ import { setupLoadDashboardMockReject, setupLoadDashboardRuntimeErrorMock, } from 'app/features/dashboard-scene/utils/test-utils'; -import { DashboardDTO, DashboardRoutes } from 'app/types'; +import { DashboardDTO, DashboardRoutes } from 'app/types/dashboard'; import { DashboardLoaderSrv, setDashboardLoaderSrv } from '../services/DashboardLoaderSrv'; diff --git a/public/app/features/dashboard/containers/DashboardPageProxy.tsx b/public/app/features/dashboard/containers/DashboardPageProxy.tsx index a574ceb1e7e..2e37c4b3749 100644 --- a/public/app/features/dashboard/containers/DashboardPageProxy.tsx +++ b/public/app/features/dashboard/containers/DashboardPageProxy.tsx @@ -5,7 +5,7 @@ import { config } from '@grafana/runtime'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; import DashboardScenePage from 'app/features/dashboard-scene/pages/DashboardScenePage'; import { getDashboardScenePageStateManager } from 'app/features/dashboard-scene/pages/DashboardScenePageStateManager'; -import { DashboardRoutes } from 'app/types'; +import { DashboardRoutes } from 'app/types/dashboard'; import { isDashboardV2Resource } from '../api/utils'; diff --git a/public/app/features/dashboard/containers/NewDashboardWithDS.tsx b/public/app/features/dashboard/containers/NewDashboardWithDS.tsx index f247b8865d5..46064030ca2 100644 --- a/public/app/features/dashboard/containers/NewDashboardWithDS.tsx +++ b/public/app/features/dashboard/containers/NewDashboardWithDS.tsx @@ -4,7 +4,7 @@ import { useParams } from 'react-router-dom-v5-compat'; import { Trans } from '@grafana/i18n'; import { getDataSourceSrv, locationService } from '@grafana/runtime'; import { Page } from 'app/core/components/Page/Page'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { setInitialDatasource } from '../state/reducers'; diff --git a/public/app/features/dashboard/containers/PublicDashboardPage.test.tsx b/public/app/features/dashboard/containers/PublicDashboardPage.test.tsx index 6b3ebdcbee8..d9038bf1f2b 100644 --- a/public/app/features/dashboard/containers/PublicDashboardPage.test.tsx +++ b/public/app/features/dashboard/containers/PublicDashboardPage.test.tsx @@ -8,8 +8,8 @@ import { render } from 'test/test-utils'; import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src'; import { Dashboard, DashboardCursorSync, FieldConfigSource, Panel, ThresholdsMode } from '@grafana/schema/src'; import { getRouteComponentProps } from 'app/core/navigation/mocks/routeProps'; -import * as appTypes from 'app/types'; -import { DashboardInitPhase, DashboardMeta, DashboardRoutes } from 'app/types'; +import { DashboardInitPhase, DashboardMeta, DashboardRoutes } from 'app/types/dashboard'; +import { StoreState } from 'app/types/store'; import { configureStore } from '../../../store/configureStore'; import { Props as LazyLoaderProps } from '../dashgrid/LazyLoader'; @@ -45,12 +45,12 @@ jest.mock('app/features/dashboard/state/initDashboard', () => ({ initDashboard: jest.fn(), })); -jest.mock('app/types', () => ({ - ...jest.requireActual('app/types'), +jest.mock('app/types/store', () => ({ + ...jest.requireActual('app/types/store'), useDispatch: () => jest.fn(), })); -const setup = (propOverrides?: Partial<Props>, initialState?: Partial<appTypes.StoreState>) => { +const setup = (propOverrides?: Partial<Props>, initialState?: Partial<StoreState>) => { const store = configureStore(initialState); const props: Props = { ...getRouteComponentProps({ diff --git a/public/app/features/dashboard/containers/PublicDashboardPage.tsx b/public/app/features/dashboard/containers/PublicDashboardPage.tsx index 4c3957431d8..b6f74800a76 100644 --- a/public/app/features/dashboard/containers/PublicDashboardPage.tsx +++ b/public/app/features/dashboard/containers/PublicDashboardPage.tsx @@ -14,7 +14,8 @@ import { PublicDashboardPageRouteSearchParams, } from 'app/features/dashboard/containers/types'; import { updateTimeZoneForSession } from 'app/features/profile/state/reducers'; -import { useSelector, useDispatch, DashboardInitError } from 'app/types'; +import { DashboardInitError } from 'app/types/dashboard'; +import { useDispatch, useSelector } from 'app/types/store'; import { DashNavTimeControls } from '../components/DashNav/DashNavTimeControls'; import { DashboardFailed } from '../components/DashboardLoading/DashboardFailed'; diff --git a/public/app/features/dashboard/containers/PublicDashboardPageProxy.test.tsx b/public/app/features/dashboard/containers/PublicDashboardPageProxy.test.tsx index 04b3678a0a1..b8ca09b1b4e 100644 --- a/public/app/features/dashboard/containers/PublicDashboardPageProxy.test.tsx +++ b/public/app/features/dashboard/containers/PublicDashboardPageProxy.test.tsx @@ -5,8 +5,7 @@ import { render } from 'test/test-utils'; import { selectors as e2eSelectors } from '@grafana/e2e-selectors'; import { config, locationService } from '@grafana/runtime'; import { backendSrv } from 'app/core/services/backend_srv'; - -import { DashboardRoutes } from '../../../types'; +import { DashboardRoutes } from 'app/types/dashboard'; import PublicDashboardPageProxy, { PublicDashboardPageProxyProps } from './PublicDashboardPageProxy'; diff --git a/public/app/features/dashboard/containers/SoloPanelPage.test.tsx b/public/app/features/dashboard/containers/SoloPanelPage.test.tsx index 2a159054622..421d7456acf 100644 --- a/public/app/features/dashboard/containers/SoloPanelPage.test.tsx +++ b/public/app/features/dashboard/containers/SoloPanelPage.test.tsx @@ -5,7 +5,7 @@ import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock'; import { Dashboard } from '@grafana/schema'; import { GrafanaContext } from 'app/core/context/GrafanaContext'; import { RouteDescriptor } from 'app/core/navigation/types'; -import { DashboardMeta, DashboardRoutes } from 'app/types'; +import { DashboardMeta, DashboardRoutes } from 'app/types/dashboard'; import { getRouteComponentProps } from '../../../core/navigation/mocks/routeProps'; import { Props as DashboardPanelProps } from '../dashgrid/DashboardPanel'; diff --git a/public/app/features/dashboard/containers/SoloPanelPage.tsx b/public/app/features/dashboard/containers/SoloPanelPage.tsx index 7fbb737de76..1904e5eb487 100644 --- a/public/app/features/dashboard/containers/SoloPanelPage.tsx +++ b/public/app/features/dashboard/containers/SoloPanelPage.tsx @@ -10,7 +10,7 @@ import { Alert, useStyles2 } from '@grafana/ui'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { useGrafana } from '../../../core/context/GrafanaContext'; import { DashboardPanel } from '../dashgrid/DashboardPanel'; diff --git a/public/app/features/dashboard/dashgrid/DashboardEmpty.test.tsx b/public/app/features/dashboard/dashgrid/DashboardEmpty.test.tsx index d18120fc5f0..09370002336 100644 --- a/public/app/features/dashboard/dashgrid/DashboardEmpty.test.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardEmpty.test.tsx @@ -8,8 +8,8 @@ import { onCreateNewPanel, onImportDashboard, onAddLibraryPanel } from '../utils import DashboardEmpty, { Props } from './DashboardEmpty'; -jest.mock('app/types', () => ({ - ...jest.requireActual('app/types'), +jest.mock('app/types/store', () => ({ + ...jest.requireActual('app/types/store'), useDispatch: () => jest.fn(), useSelector: () => jest.fn(), })); diff --git a/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx b/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx index 9c82b005616..38f57b344e5 100644 --- a/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx @@ -14,7 +14,7 @@ import { import { buildPanelEditScene } from 'app/features/dashboard-scene/panel-edit/PanelEditor'; import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { setInitialDatasource } from '../state/reducers'; diff --git a/public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx b/public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx index 164d49ba4b8..330b4df5a43 100644 --- a/public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx @@ -7,7 +7,7 @@ import { Dashboard } from '@grafana/schema'; import appEvents from 'app/core/app_events'; import { GetVariables } from 'app/features/variables/state/selectors'; import { VariablesChanged } from 'app/features/variables/types'; -import { DashboardMeta } from 'app/types'; +import { DashboardMeta } from 'app/types/dashboard'; import { DashboardModel } from '../state/DashboardModel'; import { createDashboardModelFixture } from '../state/__fixtures__/dashboardFixtures'; diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index e1ba53b8142..db9f93bb92a 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -1,7 +1,7 @@ import { PureComponent } from 'react'; import { connect, ConnectedProps } from 'react-redux'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { initPanelState } from '../../panel/state/actions'; import { setPanelInstanceState } from '../../panel/state/reducers'; diff --git a/public/app/features/dashboard/routes.ts b/public/app/features/dashboard/routes.ts index 4c20ec7229f..84e7d514b99 100644 --- a/public/app/features/dashboard/routes.ts +++ b/public/app/features/dashboard/routes.ts @@ -1,7 +1,8 @@ +import { DashboardRoutes } from 'app/types/dashboard'; + import { SafeDynamicImport } from '../../core/components/DynamicImports/SafeDynamicImport'; import { config } from '../../core/config'; import { RouteDescriptor } from '../../core/navigation/types'; -import { DashboardRoutes } from '../../types'; export const getPublicDashboardRoutes = (): RouteDescriptor[] => { if (!config.publicDashboardsEnabled) { diff --git a/public/app/features/dashboard/services/DashboardLoaderSrv.ts b/public/app/features/dashboard/services/DashboardLoaderSrv.ts index 22bb842a761..d28f575ce86 100644 --- a/public/app/features/dashboard/services/DashboardLoaderSrv.ts +++ b/public/app/features/dashboard/services/DashboardLoaderSrv.ts @@ -10,7 +10,7 @@ import impressionSrv from 'app/core/services/impression_srv'; import kbn from 'app/core/utils/kbn'; import { getDashboardScenePageStateManager } from 'app/features/dashboard-scene/pages/DashboardScenePageStateManager'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; import { appEvents } from '../../../core/core'; import { ResponseTransformers } from '../api/ResponseTransformers'; diff --git a/public/app/features/dashboard/services/DashboardSrv.ts b/public/app/features/dashboard/services/DashboardSrv.ts index 99d7423e389..0ae57780d81 100644 --- a/public/app/features/dashboard/services/DashboardSrv.ts +++ b/public/app/features/dashboard/services/DashboardSrv.ts @@ -5,7 +5,7 @@ import { Dashboard } from '@grafana/schema'; import { appEvents } from 'app/core/app_events'; import { getBackendSrv } from 'app/core/services/backend_srv'; import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; -import { DashboardMeta } from 'app/types'; +import { DashboardMeta } from 'app/types/dashboard'; import { RemovePanelEvent } from '../../../types/events'; import { DashboardModel } from '../state/DashboardModel'; diff --git a/public/app/features/dashboard/services/SnapshotSrv.ts b/public/app/features/dashboard/services/SnapshotSrv.ts index 1ca4894de22..c9d240ee3b4 100644 --- a/public/app/features/dashboard/services/SnapshotSrv.ts +++ b/public/app/features/dashboard/services/SnapshotSrv.ts @@ -2,7 +2,7 @@ import { lastValueFrom, map } from 'rxjs'; import { config, getBackendSrv, FetchResponse } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; -import { DashboardDataDTO, DashboardDTO } from 'app/types'; +import { DashboardDataDTO, DashboardDTO } from 'app/types/dashboard'; import { getAPINamespace } from '../../../api/utils'; diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index eacc6be7378..cea82ff384a 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -27,8 +27,13 @@ import { sortedDeepCloneWithoutNulls } from 'app/core/utils/object'; import { variableAdapters } from 'app/features/variables/adapters'; import { onTimeRangeUpdated } from 'app/features/variables/state/actions'; import { GetVariables, getVariablesByKey } from 'app/features/variables/state/selectors'; -import { CoreEvents, DashboardMeta } from 'app/types'; -import { DashboardMetaChangedEvent, DashboardPanelsChangedEvent, RenderEvent } from 'app/types/events'; +import { DashboardMeta } from 'app/types/dashboard'; +import { + DashboardMetaChangedEvent, + DashboardPanelsChangedEvent, + RenderEvent, + templateVariableValueUpdated, +} from 'app/types/events'; import { appEvents } from '../../../core/core'; import { dispatch } from '../../../store/store'; @@ -1155,7 +1160,7 @@ export class DashboardModel implements TimeModel { templateVariableValueUpdated() { this.processRepeats(); - this.events.emit(CoreEvents.templateVariableValueUpdated); + this.events.emit(templateVariableValueUpdated); } getPanelByUrlId(panelUrlId: string) { diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 3002dd32134..8556006879d 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -25,13 +25,13 @@ import { getTemplateSrv, RefreshEvent } from '@grafana/runtime'; import { LibraryPanel, LibraryPanelRef } from '@grafana/schema'; import config from 'app/core/config'; import { safeStringifyValue } from 'app/core/utils/explore'; -import { QueryGroupOptions } from 'app/types'; import { PanelOptionsChangedEvent, PanelQueriesChangedEvent, PanelTransformationsChangedEvent, RenderEvent, } from 'app/types/events'; +import { QueryGroupOptions } from 'app/types/query'; import { PanelQueryRunner } from '../../query/state/PanelQueryRunner'; import { TimeOverrideResult } from '../utils/panel'; diff --git a/public/app/features/dashboard/state/__fixtures__/dashboardFixtures.ts b/public/app/features/dashboard/state/__fixtures__/dashboardFixtures.ts index 8dec4d28339..28bc7897330 100644 --- a/public/app/features/dashboard/state/__fixtures__/dashboardFixtures.ts +++ b/public/app/features/dashboard/state/__fixtures__/dashboardFixtures.ts @@ -8,7 +8,7 @@ import { VariableModel, } from '@grafana/schema'; import { GetVariables } from 'app/features/variables/state/selectors'; -import { DashboardMeta } from 'app/types'; +import { DashboardMeta } from 'app/types/dashboard'; import { DashboardModel } from '../DashboardModel'; diff --git a/public/app/features/dashboard/state/actions.ts b/public/app/features/dashboard/state/actions.ts index ed28663f745..0395c6e9201 100644 --- a/public/app/features/dashboard/state/actions.ts +++ b/public/app/features/dashboard/state/actions.ts @@ -7,7 +7,7 @@ import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher'; import { removeAllPanels } from 'app/features/panel/state/reducers'; import { updateTimeZoneForSession, updateWeekStartForSession } from 'app/features/profile/state/reducers'; -import { ThunkResult } from 'app/types'; +import { ThunkResult } from 'app/types/store'; import { loadPluginDashboards } from '../../plugins/admin/state/actions'; import { cancelVariables } from '../../variables/state/actions'; diff --git a/public/app/features/dashboard/state/initDashboard.test.ts b/public/app/features/dashboard/state/initDashboard.test.ts index d291b62f379..123552c6984 100644 --- a/public/app/features/dashboard/state/initDashboard.test.ts +++ b/public/app/features/dashboard/state/initDashboard.test.ts @@ -9,7 +9,7 @@ import { KeybindingSrv } from 'app/core/services/keybindingSrv'; import { variableAdapters } from 'app/features/variables/adapters'; import { createConstantVariableAdapter } from 'app/features/variables/constant/adapter'; import { constantBuilder } from 'app/features/variables/shared/testing/builders'; -import { DashboardInitPhase, DashboardRoutes } from 'app/types'; +import { DashboardInitPhase, DashboardRoutes } from 'app/types/dashboard'; import { Echo } from '../../../core/services/echo/Echo'; import { diff --git a/public/app/features/dashboard/state/initDashboard.ts b/public/app/features/dashboard/state/initDashboard.ts index 92feb552f55..348bb55616c 100644 --- a/public/app/features/dashboard/state/initDashboard.ts +++ b/public/app/features/dashboard/state/initDashboard.ts @@ -27,10 +27,8 @@ import { DashboardRoutes, HomeDashboardRedirectDTO, isRedirectResponse, - StoreState, - ThunkDispatch, - ThunkResult, -} from 'app/types'; +} from 'app/types/dashboard'; +import { StoreState, ThunkDispatch, ThunkResult } from 'app/types/store'; import { createDashboardQueryRunner } from '../../query/state/DashboardQueryRunner/DashboardQueryRunner'; import { initVariablesTransaction } from '../../variables/state/actions'; diff --git a/public/app/features/dashboard/state/reducers.test.ts b/public/app/features/dashboard/state/reducers.test.ts index 0cb8ee5cd32..f2d44fa61fb 100644 --- a/public/app/features/dashboard/state/reducers.test.ts +++ b/public/app/features/dashboard/state/reducers.test.ts @@ -1,4 +1,4 @@ -import { DashboardInitPhase, DashboardState } from 'app/types'; +import { DashboardInitPhase, DashboardState } from 'app/types/dashboard'; import { createDashboardModelFixture, createPanelSaveModel } from './__fixtures__/dashboardFixtures'; import { diff --git a/public/app/features/dashboard/state/reducers.ts b/public/app/features/dashboard/state/reducers.ts index ddc842fc568..c96d82d8bef 100644 --- a/public/app/features/dashboard/state/reducers.ts +++ b/public/app/features/dashboard/state/reducers.ts @@ -3,7 +3,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { PanelPlugin } from '@grafana/data'; import { t } from '@grafana/i18n'; import { defaultDashboard } from '@grafana/schema'; -import { DashboardInitError, DashboardInitPhase, DashboardState } from 'app/types'; +import { DashboardInitError, DashboardInitPhase, DashboardState } from 'app/types/dashboard'; import { DashboardModel } from './DashboardModel'; import { PanelModel } from './PanelModel'; diff --git a/public/app/features/dashboard/state/selectors.ts b/public/app/features/dashboard/state/selectors.ts index 59d486d3a73..d45630812fd 100644 --- a/public/app/features/dashboard/state/selectors.ts +++ b/public/app/features/dashboard/state/selectors.ts @@ -1,5 +1,5 @@ import { PanelPlugin } from '@grafana/data'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { getPanelPluginNotFound } from '../../panel/components/PanelPluginError'; diff --git a/public/app/features/dashboard/utils/getPanelMenu.test.ts b/public/app/features/dashboard/utils/getPanelMenu.test.ts index 496e825cb69..3a18ce049dc 100644 --- a/public/app/features/dashboard/utils/getPanelMenu.test.ts +++ b/public/app/features/dashboard/utils/getPanelMenu.test.ts @@ -6,7 +6,7 @@ import config from 'app/core/config'; import { grantUserPermissions } from 'app/features/alerting/unified/mocks'; import * as actions from 'app/features/explore/state/main'; import { setStore } from 'app/store/store'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PanelModel } from '../state/PanelModel'; import { createDashboardModelFixture } from '../state/__fixtures__/dashboardFixtures'; diff --git a/public/app/features/datasources/components/DashboardsTable.test.tsx b/public/app/features/datasources/components/DashboardsTable.test.tsx index 3aac4b5a6a9..46b8148c992 100644 --- a/public/app/features/datasources/components/DashboardsTable.test.tsx +++ b/public/app/features/datasources/components/DashboardsTable.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { PluginDashboard } from 'app/types'; +import { PluginDashboard } from 'app/types/plugins'; import DashboardsTable, { Props } from './DashboardsTable'; diff --git a/public/app/features/datasources/components/DashboardsTable.tsx b/public/app/features/datasources/components/DashboardsTable.tsx index 0f3424a05df..145114ed6d5 100644 --- a/public/app/features/datasources/components/DashboardsTable.tsx +++ b/public/app/features/datasources/components/DashboardsTable.tsx @@ -1,6 +1,6 @@ import { Trans, t } from '@grafana/i18n'; import { Button, Icon } from '@grafana/ui'; -import { PluginDashboard } from 'app/types'; +import { PluginDashboard } from 'app/types/plugins'; export interface Props { // List of plugin dashboards to show in the table diff --git a/public/app/features/datasources/components/DataSourceAddButton.tsx b/public/app/features/datasources/components/DataSourceAddButton.tsx index f41ad1a657b..627c3695da0 100644 --- a/public/app/features/datasources/components/DataSourceAddButton.tsx +++ b/public/app/features/datasources/components/DataSourceAddButton.tsx @@ -5,7 +5,7 @@ import { config } from '@grafana/runtime'; import { LinkButton } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; import { ROUTES } from 'app/features/connections/constants'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { trackAddNewDsClicked } from '../tracking'; diff --git a/public/app/features/datasources/components/DataSourceCategories.tsx b/public/app/features/datasources/components/DataSourceCategories.tsx index 58fa0e3783f..45eb2623e45 100644 --- a/public/app/features/datasources/components/DataSourceCategories.tsx +++ b/public/app/features/datasources/components/DataSourceCategories.tsx @@ -5,7 +5,7 @@ import { DataSourcePluginMeta, GrafanaTheme2 } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { reportInteraction } from '@grafana/runtime'; import { LinkButton, useStyles2 } from '@grafana/ui'; -import { DataSourcePluginCategory } from 'app/types'; +import { DataSourcePluginCategory } from 'app/types/datasources'; import { ROUTES } from '../../connections/constants'; diff --git a/public/app/features/datasources/components/DataSourceDashboards.tsx b/public/app/features/datasources/components/DataSourceDashboards.tsx index d4011844e4c..0a16c265a02 100644 --- a/public/app/features/datasources/components/DataSourceDashboards.tsx +++ b/public/app/features/datasources/components/DataSourceDashboards.tsx @@ -3,7 +3,8 @@ import { useEffect } from 'react'; import PageLoader from 'app/core/components/PageLoader/PageLoader'; import { importDashboard, removeDashboard } from 'app/features/dashboard/state/actions'; import { loadPluginDashboards } from 'app/features/plugins/admin/state/actions'; -import { PluginDashboard, StoreState, useDispatch, useSelector } from 'app/types'; +import { PluginDashboard } from 'app/types/plugins'; +import { StoreState, useDispatch, useSelector } from 'app/types/store'; import DashboardTable from '../components/DashboardsTable'; import { useInitDataSourceSettings } from '../state/hooks'; diff --git a/public/app/features/datasources/components/DataSourcesList.tsx b/public/app/features/datasources/components/DataSourcesList.tsx index 1437fa395e8..b4337792ebc 100644 --- a/public/app/features/datasources/components/DataSourcesList.tsx +++ b/public/app/features/datasources/components/DataSourcesList.tsx @@ -7,7 +7,8 @@ import { Trans, t } from '@grafana/i18n'; import { config } from '@grafana/runtime'; import { EmptyState, LinkButton, TextLink, useStyles2 } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { StoreState, AccessControlAction, useSelector } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { StoreState, useSelector } from 'app/types/store'; import { ROUTES } from '../../connections/constants'; import { useLoadDataSources } from '../state/hooks'; diff --git a/public/app/features/datasources/components/DataSourcesListHeader.tsx b/public/app/features/datasources/components/DataSourcesListHeader.tsx index f23f8b3cb6b..26db52a7a33 100644 --- a/public/app/features/datasources/components/DataSourcesListHeader.tsx +++ b/public/app/features/datasources/components/DataSourcesListHeader.tsx @@ -3,7 +3,7 @@ import { useCallback, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; import PageActionBar from 'app/core/components/PageActionBar/PageActionBar'; -import { StoreState, useSelector, useDispatch } from 'app/types'; +import { StoreState, useSelector, useDispatch } from 'app/types/store'; import { setDataSourcesSearchQuery, setIsSortAscending } from '../state/reducers'; import { getDataSourcesSearchQuery, getDataSourcesSort } from '../state/selectors'; diff --git a/public/app/features/datasources/components/EditDataSource.tsx b/public/app/features/datasources/components/EditDataSource.tsx index 920979f0cd4..06877e8ad72 100644 --- a/public/app/features/datasources/components/EditDataSource.tsx +++ b/public/app/features/datasources/components/EditDataSource.tsx @@ -13,7 +13,8 @@ import { import { getDataSourceSrv, usePluginComponents, UsePluginComponentsResult } from '@grafana/runtime'; import appEvents from 'app/core/app_events'; import PageLoader from 'app/core/components/PageLoader/PageLoader'; -import { DataSourceSettingsState, useDispatch } from 'app/types'; +import { DataSourceSettingsState } from 'app/types/datasources'; +import { useDispatch } from 'app/types/store'; import { useDataSource, diff --git a/public/app/features/datasources/components/NewDataSource.tsx b/public/app/features/datasources/components/NewDataSource.tsx index 7803caac224..8db925f5e87 100644 --- a/public/app/features/datasources/components/NewDataSource.tsx +++ b/public/app/features/datasources/components/NewDataSource.tsx @@ -5,7 +5,8 @@ import { Trans, t } from '@grafana/i18n'; import { LinkButton, FilterInput } from '@grafana/ui'; import PageLoader from 'app/core/components/PageLoader/PageLoader'; import { PluginsErrorsInfo } from 'app/features/plugins/components/PluginsErrorsInfo'; -import { DataSourcePluginCategory, StoreState, useDispatch, useSelector } from 'app/types'; +import { DataSourcePluginCategory } from 'app/types/datasources'; +import { StoreState, useDispatch, useSelector } from 'app/types/store'; import { ROUTES } from '../../connections/constants'; import { DataSourceCategories } from '../components/DataSourceCategories'; diff --git a/public/app/features/datasources/components/picker/AddNewDataSourceButton.tsx b/public/app/features/datasources/components/picker/AddNewDataSourceButton.tsx index b5489e59cb1..7e03ccf2c8b 100644 --- a/public/app/features/datasources/components/picker/AddNewDataSourceButton.tsx +++ b/public/app/features/datasources/components/picker/AddNewDataSourceButton.tsx @@ -3,7 +3,7 @@ import { Trans, t } from '@grafana/i18n'; import { LinkButton, ButtonVariant } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; import { ROUTES as CONNECTIONS_ROUTES } from 'app/features/connections/constants'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; interface AddNewDataSourceButtonProps { onClick?: () => void; diff --git a/public/app/features/datasources/components/picker/utils.ts b/public/app/features/datasources/components/picker/utils.ts index c626047631c..ff987c26f5b 100644 --- a/public/app/features/datasources/components/picker/utils.ts +++ b/public/app/features/datasources/components/picker/utils.ts @@ -5,7 +5,7 @@ import { setLastUsedDatasourceKeyForDashboard, } from 'app/features/dashboard/utils/dashboard'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { QueryGroupDataSource } from 'app/types'; +import { QueryGroupDataSource } from 'app/types/query'; export function isDataSourceMatch( ds: DataSourceInstanceSettings | undefined, diff --git a/public/app/features/datasources/mocks/dataSourcesMocks.ts b/public/app/features/datasources/mocks/dataSourcesMocks.ts index b58dec19453..807082bd843 100644 --- a/public/app/features/datasources/mocks/dataSourcesMocks.ts +++ b/public/app/features/datasources/mocks/dataSourcesMocks.ts @@ -2,7 +2,8 @@ import { merge } from 'lodash'; import { DataSourceSettings, DataSourcePluginMeta, DataSourceJsonData } from '@grafana/data'; import amazonWebServicesPng from 'app/plugins/datasource/cloudwatch/img/amazon-web-services.png'; -import { DataSourceSettingsState, PluginDashboard } from 'app/types'; +import { DataSourceSettingsState } from 'app/types/datasources'; +import { PluginDashboard } from 'app/types/plugins'; export const getMockDashboard = (override?: Partial<PluginDashboard>) => ({ uid: 'G1btqkgkK', diff --git a/public/app/features/datasources/state/actions.test.ts b/public/app/features/datasources/state/actions.test.ts index 0109a8c70fe..79aaf70a62c 100644 --- a/public/app/features/datasources/state/actions.test.ts +++ b/public/app/features/datasources/state/actions.test.ts @@ -4,7 +4,7 @@ import { AppPluginMeta, DataSourceSettings, PluginMetaInfo, PluginType } from '@ import { DataSourceSrv, FetchError } from '@grafana/runtime'; import { appEvents } from 'app/core/core'; import { getBackendSrv } from 'app/core/services/backend_srv'; -import { ThunkResult, ThunkDispatch } from 'app/types'; +import { ThunkResult, ThunkDispatch } from 'app/types/store'; import * as api from '../api'; import { DATASOURCES_ROUTES } from '../constants'; diff --git a/public/app/features/datasources/state/actions.ts b/public/app/features/datasources/state/actions.ts index 7cd1411b9eb..09835ce72b2 100644 --- a/public/app/features/datasources/state/actions.ts +++ b/public/app/features/datasources/state/actions.ts @@ -23,9 +23,11 @@ import { getBackendSrv } from 'app/core/services/backend_srv'; import { DatasourceAPIVersions } from 'app/features/apiserver/client'; import { ROUTES as CONNECTIONS_ROUTES } from 'app/features/connections/constants'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; +import { importDataSourcePlugin } from 'app/features/plugins/pluginLoader'; import { getPluginSettings } from 'app/features/plugins/pluginSettings'; -import { importDataSourcePlugin } from 'app/features/plugins/plugin_loader'; -import { AccessControlAction, DataSourcePluginCategory, ThunkDispatch, ThunkResult } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { DataSourcePluginCategory } from 'app/types/datasources'; +import { ThunkDispatch, ThunkResult } from 'app/types/store'; import * as api from '../api'; import { DATASOURCES_ROUTES } from '../constants'; diff --git a/public/app/features/datasources/state/buildCategories.ts b/public/app/features/datasources/state/buildCategories.ts index b357798fdaa..ec813a6e1e6 100644 --- a/public/app/features/datasources/state/buildCategories.ts +++ b/public/app/features/datasources/state/buildCategories.ts @@ -1,7 +1,7 @@ import { DataSourcePluginMeta, PluginType } from '@grafana/data'; import { t } from '@grafana/i18n'; import { featureEnabled } from '@grafana/runtime'; -import { DataSourcePluginCategory } from 'app/types'; +import { DataSourcePluginCategory } from 'app/types/datasources'; import grafanaIconSvg from 'img/grafana_icon.svg'; import adobeAnalyticsSvg from 'img/plugins/adobe-analytics.svg'; import appdynamicsSvg from 'img/plugins/appdynamics.svg'; diff --git a/public/app/features/datasources/state/hooks.ts b/public/app/features/datasources/state/hooks.ts index af0c5dd7e6b..61e7be7ae09 100644 --- a/public/app/features/datasources/state/hooks.ts +++ b/public/app/features/datasources/state/hooks.ts @@ -5,8 +5,9 @@ import { t } from '@grafana/i18n'; import { cleanUpAction } from 'app/core/actions/cleanUp'; import appEvents from 'app/core/app_events'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, useDispatch, useSelector } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ShowConfirmModalEvent } from 'app/types/events'; +import { useDispatch, useSelector } from 'app/types/store'; import { ROUTES } from '../../connections/constants'; import { DataSourceRights } from '../types'; diff --git a/public/app/features/datasources/state/navModel.ts b/public/app/features/datasources/state/navModel.ts index c71bff78248..2c685beae68 100644 --- a/public/app/features/datasources/state/navModel.ts +++ b/public/app/features/datasources/state/navModel.ts @@ -5,7 +5,7 @@ import { ProBadge } from 'app/core/components/Upgrade/ProBadge'; import config from 'app/core/config'; import { contextSrv } from 'app/core/core'; import { highlightTrial } from 'app/features/admin/utils'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import icnDatasourceSvg from 'img/icn-datasource.svg'; import { GenericDataSourcePlugin } from '../types'; diff --git a/public/app/features/datasources/state/reducers.test.ts b/public/app/features/datasources/state/reducers.test.ts index 85f6455e837..43555d3208b 100644 --- a/public/app/features/datasources/state/reducers.test.ts +++ b/public/app/features/datasources/state/reducers.test.ts @@ -1,7 +1,7 @@ import { reducerTester } from 'test/core/redux/reducerTester'; import { PluginMeta, PluginMetaInfo, PluginType, LayoutModes } from '@grafana/data'; -import { DataSourceSettingsState, DataSourcesState } from 'app/types'; +import { DataSourceSettingsState, DataSourcesState } from 'app/types/datasources'; import { getMockDataSource, getMockDataSources } from '../mocks/dataSourcesMocks'; import { GenericDataSourcePlugin } from '../types'; diff --git a/public/app/features/datasources/state/reducers.ts b/public/app/features/datasources/state/reducers.ts index e5b2588499c..700f06e6133 100644 --- a/public/app/features/datasources/state/reducers.ts +++ b/public/app/features/datasources/state/reducers.ts @@ -3,7 +3,7 @@ import { AnyAction, createAction } from '@reduxjs/toolkit'; import { DataSourcePluginMeta, DataSourceSettings, LayoutMode, LayoutModes } from '@grafana/data'; import { t } from '@grafana/i18n'; import { TestingStatus } from '@grafana/runtime'; -import { DataSourcesState, DataSourceSettingsState } from 'app/types'; +import { DataSourcesState, DataSourceSettingsState } from 'app/types/datasources'; import { GenericDataSourcePlugin } from '../types'; diff --git a/public/app/features/explore/CorrelationEditorModeBar.tsx b/public/app/features/explore/CorrelationEditorModeBar.tsx index 87d531eb41d..25739ad1b5c 100644 --- a/public/app/features/explore/CorrelationEditorModeBar.tsx +++ b/public/app/features/explore/CorrelationEditorModeBar.tsx @@ -7,7 +7,8 @@ import { Trans, t } from '@grafana/i18n'; import { reportInteraction } from '@grafana/runtime'; import { Button, Icon, Stack, Tooltip, useStyles2 } from '@grafana/ui'; import { Prompt } from 'app/core/components/FormPrompt/Prompt'; -import { CORRELATION_EDITOR_POST_CONFIRM_ACTION, ExploreItemState, useDispatch, useSelector } from 'app/types'; +import { CORRELATION_EDITOR_POST_CONFIRM_ACTION, ExploreItemState } from 'app/types/explore'; +import { useDispatch, useSelector } from 'app/types/store'; import { CorrelationUnsavedChangesModal } from './CorrelationUnsavedChangesModal'; import { showModalMessage } from './correlationEditLogic'; diff --git a/public/app/features/explore/CorrelationHelper.tsx b/public/app/features/explore/CorrelationHelper.tsx index 2444a4dd7b6..bf57509bf63 100644 --- a/public/app/features/explore/CorrelationHelper.tsx +++ b/public/app/features/explore/CorrelationHelper.tsx @@ -19,7 +19,7 @@ import { Icon, Stack, } from '@grafana/ui'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { getTransformationVars } from '../correlations/transformations'; import { generateDefaultLabel } from '../correlations/utils'; diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index bbaf27f3524..57ef823de4d 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -33,7 +33,7 @@ import { import { FILTER_FOR_OPERATOR, FILTER_OUT_OPERATOR } from '@grafana/ui/internal'; import { supportedFeatures } from 'app/core/history/richHistoryStorageProvider'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { getTimeZone } from '../profile/state/selectors'; diff --git a/public/app/features/explore/ExploreActions.tsx b/public/app/features/explore/ExploreActions.tsx index de35e644b4e..376cc25d715 100644 --- a/public/app/features/explore/ExploreActions.tsx +++ b/public/app/features/explore/ExploreActions.tsx @@ -4,7 +4,8 @@ import { useEffect, useState } from 'react'; import { config } from '@grafana/runtime'; import { contextSrv } from 'app/core/services/context_srv'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { AccessControlAction, useDispatch, useSelector } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { useDispatch, useSelector } from 'app/types/store'; import { splitOpen, splitClose, changeCorrelationEditorDetails } from './state/main'; import { runQueries } from './state/query'; diff --git a/public/app/features/explore/ExplorePage.tsx b/public/app/features/explore/ExplorePage.tsx index 6799eddec3b..d5974011bbb 100644 --- a/public/app/features/explore/ExplorePage.tsx +++ b/public/app/features/explore/ExplorePage.tsx @@ -9,8 +9,8 @@ import { SplitPaneWrapper } from 'app/core/components/SplitPaneWrapper/SplitPane import { useGrafana } from 'app/core/context/GrafanaContext'; import { useNavModel } from 'app/core/hooks/useNavModel'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; -import { useSelector } from 'app/types'; import { ExploreQueryParams } from 'app/types/explore'; +import { useSelector } from 'app/types/store'; import { CorrelationEditorModeBar } from './CorrelationEditorModeBar'; import { ExploreActions } from './ExploreActions'; diff --git a/public/app/features/explore/ExplorePaneContainer.tsx b/public/app/features/explore/ExplorePaneContainer.tsx index 07aba1a5a41..d6d9831bbc2 100644 --- a/public/app/features/explore/ExplorePaneContainer.tsx +++ b/public/app/features/explore/ExplorePaneContainer.tsx @@ -5,7 +5,7 @@ import { connect } from 'react-redux'; import { EventBusSrv, getTimeZone } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { stopQueryState } from 'app/core/utils/explore'; -import { StoreState, useSelector } from 'app/types'; +import { StoreState, useSelector } from 'app/types/store'; import Explore from './Explore'; import ExploreQueryInspector from './ExploreQueryInspector'; diff --git a/public/app/features/explore/ExploreQueryInspector.tsx b/public/app/features/explore/ExploreQueryInspector.tsx index 24f73322bc1..70badc6c689 100644 --- a/public/app/features/explore/ExploreQueryInspector.tsx +++ b/public/app/features/explore/ExploreQueryInspector.tsx @@ -15,7 +15,8 @@ import { InspectJSONTab } from 'app/features/inspector/InspectJSONTab'; import { InspectStatsTab } from 'app/features/inspector/InspectStatsTab'; import { QueryInspector } from 'app/features/inspector/QueryInspector'; import { mixedRequestId } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { StoreState, ExploreItemState } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; +import { StoreState } from 'app/types/store'; import { GetDataOptions } from '../query/state/PanelQueryRunner'; diff --git a/public/app/features/explore/ExploreRunQueryButton.test.tsx b/public/app/features/explore/ExploreRunQueryButton.test.tsx index e2b518654e9..0cb9290f62c 100644 --- a/public/app/features/explore/ExploreRunQueryButton.test.tsx +++ b/public/app/features/explore/ExploreRunQueryButton.test.tsx @@ -6,7 +6,7 @@ import { DatasourceSrvMock, MockDataSourceApi } from 'test/mocks/datasource_srv' import { DataSourceApi } from '@grafana/data'; import { DataQuery } from '@grafana/schema'; import { configureStore } from 'app/store/configureStore'; -import { ExploreItemState, ExploreState } from 'app/types'; +import { ExploreItemState, ExploreState } from 'app/types/explore'; import { Props, ExploreRunQueryButton } from './ExploreRunQueryButton'; import { makeExplorePaneState } from './state/utils'; diff --git a/public/app/features/explore/ExploreRunQueryButton.tsx b/public/app/features/explore/ExploreRunQueryButton.tsx index 49a2fe3acaa..78f54525705 100644 --- a/public/app/features/explore/ExploreRunQueryButton.tsx +++ b/public/app/features/explore/ExploreRunQueryButton.tsx @@ -5,7 +5,7 @@ import { t } from '@grafana/i18n'; import { config, reportInteraction } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; import { Button, Dropdown, Menu, ToolbarButton } from '@grafana/ui'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { changeDatasource } from './state/datasource'; import { setQueries } from './state/query'; diff --git a/public/app/features/explore/Graph/ExploreGraph.tsx b/public/app/features/explore/Graph/ExploreGraph.tsx index cd69a11af37..e4dedb3f76c 100644 --- a/public/app/features/explore/Graph/ExploreGraph.tsx +++ b/public/app/features/explore/Graph/ExploreGraph.tsx @@ -31,7 +31,7 @@ import { import { PanelContext, PanelContextProvider, SeriesVisibilityChangeMode, useTheme2 } from '@grafana/ui'; import { defaultGraphConfig, getGraphFieldConfig } from 'app/plugins/panel/timeseries/config'; import { Options as TimeSeriesOptions } from 'app/plugins/panel/timeseries/panelcfg.gen'; -import { ExploreGraphStyle } from 'app/types'; +import { ExploreGraphStyle } from 'app/types/explore'; import { seriesVisibilityConfigFactory } from '../../dashboard/dashgrid/SeriesVisibilityConfigFactory'; import { useExploreDataLinkPostProcessor } from '../hooks/useExploreDataLinkPostProcessor'; diff --git a/public/app/features/explore/Graph/ExploreGraphLabel.tsx b/public/app/features/explore/Graph/ExploreGraphLabel.tsx index a8be709f53b..9b2069546eb 100644 --- a/public/app/features/explore/Graph/ExploreGraphLabel.tsx +++ b/public/app/features/explore/Graph/ExploreGraphLabel.tsx @@ -1,6 +1,6 @@ import { SelectableValue } from '@grafana/data'; import { RadioButtonGroup } from '@grafana/ui'; -import { EXPLORE_GRAPH_STYLES, ExploreGraphStyle } from 'app/types'; +import { EXPLORE_GRAPH_STYLES, ExploreGraphStyle } from 'app/types/explore'; const ALL_GRAPH_STYLE_OPTIONS: Array<SelectableValue<ExploreGraphStyle>> = EXPLORE_GRAPH_STYLES.map((style) => ({ value: style, diff --git a/public/app/features/explore/Graph/GraphContainer.tsx b/public/app/features/explore/Graph/GraphContainer.tsx index b9a9fe44a5f..7cbf420dccf 100644 --- a/public/app/features/explore/Graph/GraphContainer.tsx +++ b/public/app/features/explore/Graph/GraphContainer.tsx @@ -13,7 +13,7 @@ import { } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { GraphThresholdsStyleConfig, PanelChrome, PanelChromeProps } from '@grafana/ui'; -import { ExploreGraphStyle } from 'app/types'; +import { ExploreGraphStyle } from 'app/types/explore'; import { LimitedDataDisclaimer } from '../LimitedDataDisclaimer'; import { storeGraphStyle } from '../state/utils'; diff --git a/public/app/features/explore/Graph/exploreGraphStyleUtils.ts b/public/app/features/explore/Graph/exploreGraphStyleUtils.ts index 224ece64100..6206d387058 100644 --- a/public/app/features/explore/Graph/exploreGraphStyleUtils.ts +++ b/public/app/features/explore/Graph/exploreGraphStyleUtils.ts @@ -2,7 +2,7 @@ import { produce } from 'immer'; import { FieldConfigSource, ThresholdsConfig } from '@grafana/data'; import { GraphDrawStyle, GraphFieldConfig, GraphThresholdsStyleConfig, StackingMode } from '@grafana/schema'; -import { ExploreGraphStyle } from 'app/types'; +import { ExploreGraphStyle } from 'app/types/explore'; export type FieldConfig = FieldConfigSource<GraphFieldConfig>; diff --git a/public/app/features/explore/Graph/utils.ts b/public/app/features/explore/Graph/utils.ts index 3b42e342c1f..38ee661969b 100644 --- a/public/app/features/explore/Graph/utils.ts +++ b/public/app/features/explore/Graph/utils.ts @@ -1,5 +1,5 @@ import store from 'app/core/store'; -import { ExploreGraphStyle, EXPLORE_GRAPH_STYLES } from 'app/types'; +import { ExploreGraphStyle, EXPLORE_GRAPH_STYLES } from 'app/types/explore'; const GRAPH_STYLE_KEY = 'grafana.explore.style.graph'; export const storeGraphStyle = (graphStyle: string): void => { diff --git a/public/app/features/explore/Logs/Logs.tsx b/public/app/features/explore/Logs/Logs.tsx index 897bca4f24d..4507fa9e028 100644 --- a/public/app/features/explore/Logs/Logs.tsx +++ b/public/app/features/explore/Logs/Logs.tsx @@ -60,7 +60,8 @@ import { LokiQueryDirection } from 'app/plugins/datasource/loki/dataquery.gen'; import { isLokiQuery } from 'app/plugins/datasource/loki/queryUtils'; import { GetFieldLinksFn } from 'app/plugins/panel/logs/types'; import { getState } from 'app/store/store'; -import { ExploreItemState, useDispatch } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; +import { useDispatch } from 'app/types/store'; import { contentOutlineTrackPinAdded, diff --git a/public/app/features/explore/Logs/LogsContainer.tsx b/public/app/features/explore/Logs/LogsContainer.tsx index 8ca38ab007d..6ff6c9a248c 100644 --- a/public/app/features/explore/Logs/LogsContainer.tsx +++ b/public/app/features/explore/Logs/LogsContainer.tsx @@ -27,8 +27,8 @@ import { DataQuery } from '@grafana/schema'; import { Collapse } from '@grafana/ui'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; import { GetFieldLinksFn } from 'app/plugins/panel/logs/types'; -import { StoreState } from 'app/types'; import { ExploreItemState } from 'app/types/explore'; +import { StoreState } from 'app/types/store'; import { getTimeZone } from '../../profile/state/selectors'; import { diff --git a/public/app/features/explore/NoDataSourceCallToAction.tsx b/public/app/features/explore/NoDataSourceCallToAction.tsx index 822da87b1c6..5d67b2d1475 100644 --- a/public/app/features/explore/NoDataSourceCallToAction.tsx +++ b/public/app/features/explore/NoDataSourceCallToAction.tsx @@ -4,7 +4,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { LinkButton, CallToActionCard, Icon, useStyles2 } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; function getCardStyles(theme: GrafanaTheme2) { return css({ diff --git a/public/app/features/explore/NodeGraph/NodeGraphContainer.tsx b/public/app/features/explore/NodeGraph/NodeGraphContainer.tsx index c0e15131f0d..5c73e85776f 100644 --- a/public/app/features/explore/NodeGraph/NodeGraphContainer.tsx +++ b/public/app/features/explore/NodeGraph/NodeGraphContainer.tsx @@ -8,11 +8,11 @@ import { Trans, t } from '@grafana/i18n'; import { config, reportInteraction } from '@grafana/runtime'; import { useStyles2, useTheme2, PanelChrome } from '@grafana/ui'; import { layeredLayoutThreshold } from 'app/plugins/panel/nodeGraph/NodeGraph'; +import { StoreState } from 'app/types/store'; import { NodeGraph } from '../../../plugins/panel/nodeGraph'; import { LayoutAlgorithm } from '../../../plugins/panel/nodeGraph/panelcfg.gen'; import { useCategorizeFrames } from '../../../plugins/panel/nodeGraph/useCategorizeFrames'; -import { StoreState } from '../../../types'; import { useLinks } from '../utils/links'; const getStyles = (theme: GrafanaTheme2) => ({ diff --git a/public/app/features/explore/QueriesDrawer/QueriesDrawerContext.tsx b/public/app/features/explore/QueriesDrawer/QueriesDrawerContext.tsx index abcbc468bd5..67cf1055912 100644 --- a/public/app/features/explore/QueriesDrawer/QueriesDrawerContext.tsx +++ b/public/app/features/explore/QueriesDrawer/QueriesDrawerContext.tsx @@ -1,6 +1,6 @@ import { PropsWithChildren, useState, createContext, useContext, useEffect } from 'react'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { selectRichHistorySettings } from '../state/selectors'; diff --git a/public/app/features/explore/QueryRows.test.tsx b/public/app/features/explore/QueryRows.test.tsx index 8acb5e80b71..03989ec2950 100644 --- a/public/app/features/explore/QueryRows.test.tsx +++ b/public/app/features/explore/QueryRows.test.tsx @@ -5,7 +5,7 @@ import { DataSourceApi } from '@grafana/data'; import { DataSourceSrv, setDataSourceSrv } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; import { configureStore } from 'app/store/configureStore'; -import { ExploreState } from 'app/types'; +import { ExploreState } from 'app/types/explore'; import { UserState } from '../profile/state/reducers'; diff --git a/public/app/features/explore/QueryRows.tsx b/public/app/features/explore/QueryRows.tsx index 42b39a20f6b..084c180544f 100644 --- a/public/app/features/explore/QueryRows.tsx +++ b/public/app/features/explore/QueryRows.tsx @@ -4,7 +4,7 @@ import { useCallback, useMemo } from 'react'; import { CoreApp, getNextRefId } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime'; import { DataQuery, DataSourceRef } from '@grafana/schema'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { getDatasourceSrv } from '../plugins/datasource_srv'; import { QueryEditorRows } from '../query/components/QueryEditorRows'; diff --git a/public/app/features/explore/RawPrometheus/RawPrometheusContainer.test.tsx b/public/app/features/explore/RawPrometheus/RawPrometheusContainer.test.tsx index 7efd5f866e9..c1f0ed2aad2 100644 --- a/public/app/features/explore/RawPrometheus/RawPrometheusContainer.test.tsx +++ b/public/app/features/explore/RawPrometheus/RawPrometheusContainer.test.tsx @@ -2,7 +2,7 @@ import { fireEvent, render, screen, within } from '@testing-library/react'; import { FieldType, getDefaultTimeRange, InternalTimeZones, toDataFrame, LoadingState } from '@grafana/data'; import { getTemplateSrv } from 'app/features/templating/template_srv'; -import { TABLE_RESULTS_STYLE } from 'app/types'; +import { TABLE_RESULTS_STYLE } from 'app/types/explore'; import { RawPrometheusContainer } from './RawPrometheusContainer'; diff --git a/public/app/features/explore/RawPrometheus/RawPrometheusContainer.tsx b/public/app/features/explore/RawPrometheus/RawPrometheusContainer.tsx index 4269c1d7724..5ba8c1a9e2b 100644 --- a/public/app/features/explore/RawPrometheus/RawPrometheusContainer.tsx +++ b/public/app/features/explore/RawPrometheus/RawPrometheusContainer.tsx @@ -8,8 +8,8 @@ import { TimeZone } from '@grafana/schema'; import { RadioButtonGroup, Table, AdHocFilterItem, PanelChrome } from '@grafana/ui'; import { config } from 'app/core/config'; import { PANEL_BORDER } from 'app/core/constants'; -import { StoreState, TABLE_RESULTS_STYLE } from 'app/types'; -import { ExploreItemState, TABLE_RESULTS_STYLES, TableResultsStyle } from 'app/types/explore'; +import { ExploreItemState, TABLE_RESULTS_STYLE, TABLE_RESULTS_STYLES, TableResultsStyle } from 'app/types/explore'; +import { StoreState } from 'app/types/store'; import { MetaInfoText } from '../MetaInfoText'; import RawListContainer from '../PrometheusListView/RawListContainer'; diff --git a/public/app/features/explore/ResponseErrorContainer.tsx b/public/app/features/explore/ResponseErrorContainer.tsx index e0724c1a666..8124d2e68d1 100644 --- a/public/app/features/explore/ResponseErrorContainer.tsx +++ b/public/app/features/explore/ResponseErrorContainer.tsx @@ -1,5 +1,5 @@ import { LoadingState } from '@grafana/data'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { ErrorContainer } from './ErrorContainer'; diff --git a/public/app/features/explore/RichHistory/RichHistory.tsx b/public/app/features/explore/RichHistory/RichHistory.tsx index d78a69d14f5..b4fdc2b28e6 100644 --- a/public/app/features/explore/RichHistory/RichHistory.tsx +++ b/public/app/features/explore/RichHistory/RichHistory.tsx @@ -11,8 +11,8 @@ import { RichHistorySettings, createDatasourcesList, } from 'app/core/utils/richHistory'; -import { useSelector } from 'app/types'; import { RichHistoryQuery } from 'app/types/explore'; +import { useSelector } from 'app/types/store'; import { supportedFeatures } from '../../../core/history/richHistoryStorageProvider'; import { Tabs } from '../QueriesDrawer/QueriesDrawerContext'; diff --git a/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx b/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx index f0a9d5410f3..669f7d0dd4a 100644 --- a/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx @@ -6,8 +6,8 @@ import { DataSourceApi, DataSourceInstanceSettings, DataSourcePluginMeta } from import { DataQuery, DataSourceRef } from '@grafana/schema'; import { MixedDatasource } from 'app/plugins/datasource/mixed/MixedDataSource'; import { configureStore } from 'app/store/configureStore'; -import { ExploreState, RichHistoryQuery } from 'app/types'; import { ShowConfirmModalEvent } from 'app/types/events'; +import { ExploreState, RichHistoryQuery } from 'app/types/explore'; import { RichHistoryCard, Props } from './RichHistoryCard'; diff --git a/public/app/features/explore/RichHistory/RichHistoryContainer.tsx b/public/app/features/explore/RichHistory/RichHistoryContainer.tsx index a08c439aa33..6d622353d38 100644 --- a/public/app/features/explore/RichHistory/RichHistoryContainer.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryContainer.tsx @@ -6,7 +6,7 @@ import { Trans } from '@grafana/i18n'; import { config, reportInteraction } from '@grafana/runtime'; import { useTheme2 } from '@grafana/ui'; // Types -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; // Components, enums import { useQueriesDrawerContext } from '../QueriesDrawer/QueriesDrawerContext'; diff --git a/public/app/features/explore/RichHistory/RichHistoryStarredTab.tsx b/public/app/features/explore/RichHistory/RichHistoryStarredTab.tsx index 542f3b3d9e1..51c8f36851b 100644 --- a/public/app/features/explore/RichHistory/RichHistoryStarredTab.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryStarredTab.tsx @@ -12,8 +12,8 @@ import { RichHistorySearchFilters, RichHistorySettings, } from 'app/core/utils/richHistory'; -import { useSelector } from 'app/types'; import { RichHistoryQuery } from 'app/types/explore'; +import { useSelector } from 'app/types/store'; import { selectExploreDSMaps } from '../state/selectors'; diff --git a/public/app/features/explore/SecondaryActions.tsx b/public/app/features/explore/SecondaryActions.tsx index e1f378bf262..cd9d25b860b 100644 --- a/public/app/features/explore/SecondaryActions.tsx +++ b/public/app/features/explore/SecondaryActions.tsx @@ -4,7 +4,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { Trans, t } from '@grafana/i18n'; import { ToolbarButton, useTheme2 } from '@grafana/ui'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { createDatasourcesList } from '../../core/utils/richHistory'; import { MIXED_DATASOURCE_NAME } from '../../plugins/datasource/mixed/MixedDataSource'; diff --git a/public/app/features/explore/ShortLinkButtonMenu.tsx b/public/app/features/explore/ShortLinkButtonMenu.tsx index 11ba51875e8..6764e007e3b 100644 --- a/public/app/features/explore/ShortLinkButtonMenu.tsx +++ b/public/app/features/explore/ShortLinkButtonMenu.tsx @@ -6,7 +6,7 @@ import { reportInteraction, config } from '@grafana/runtime'; import { Dropdown, Menu, MenuGroup, ButtonGroup, Button } from '@grafana/ui'; import { copyStringToClipboard } from 'app/core/utils/explore'; import { createAndCopyShortLink } from 'app/core/utils/shortLinks'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { selectPanes } from './state/selectors'; import { constructAbsoluteUrl } from './utils/links'; diff --git a/public/app/features/explore/Table/TableContainer.tsx b/public/app/features/explore/Table/TableContainer.tsx index 802c5602861..b0a203bd22a 100644 --- a/public/app/features/explore/Table/TableContainer.tsx +++ b/public/app/features/explore/Table/TableContainer.tsx @@ -12,8 +12,8 @@ import { hasDeprecatedParentRowIndex, migrateFromParentRowIndexToNestedFrames, } from 'app/plugins/panel/table/migrations'; -import { StoreState } from 'app/types'; import { ExploreItemState } from 'app/types/explore'; +import { StoreState } from 'app/types/store'; import { LimitedDataDisclaimer } from '../LimitedDataDisclaimer'; import { MetaInfoText } from '../MetaInfoText'; diff --git a/public/app/features/explore/TraceView/TraceView.tsx b/public/app/features/explore/TraceView/TraceView.tsx index 4afbe1d6b4a..ecb71ee92a8 100644 --- a/public/app/features/explore/TraceView/TraceView.tsx +++ b/public/app/features/explore/TraceView/TraceView.tsx @@ -23,7 +23,7 @@ import { useStyles2 } from '@grafana/ui'; import { TempoQuery } from '@grafana-plugins/tempo/types'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { getTimeZone } from 'app/features/profile/state/selectors'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { changePanelState } from '../state/explorePane'; diff --git a/public/app/features/explore/TraceView/TraceViewContainer.tsx b/public/app/features/explore/TraceView/TraceViewContainer.tsx index 5fbcd3ba4a5..9eff3de76f2 100644 --- a/public/app/features/explore/TraceView/TraceViewContainer.tsx +++ b/public/app/features/explore/TraceView/TraceViewContainer.tsx @@ -3,7 +3,7 @@ import { useMemo } from 'react'; import { DataFrame, SplitOpen, TimeRange } from '@grafana/data'; import { t } from '@grafana/i18n'; import { PanelChrome } from '@grafana/ui'; -import { StoreState, useSelector } from 'app/types'; +import { StoreState, useSelector } from 'app/types/store'; import { TraceView } from './TraceView'; import { transformDataFrames } from './utils/transform'; diff --git a/public/app/features/explore/correlationEditLogic.test.ts b/public/app/features/explore/correlationEditLogic.test.ts index dd3c37e95c6..fa80b340226 100644 --- a/public/app/features/explore/correlationEditLogic.test.ts +++ b/public/app/features/explore/correlationEditLogic.test.ts @@ -1,4 +1,4 @@ -import { CORRELATION_EDITOR_POST_CONFIRM_ACTION } from 'app/types'; +import { CORRELATION_EDITOR_POST_CONFIRM_ACTION } from 'app/types/explore'; import { showModalMessage } from './correlationEditLogic'; diff --git a/public/app/features/explore/correlationEditLogic.ts b/public/app/features/explore/correlationEditLogic.ts index 326389505c7..0e507453306 100644 --- a/public/app/features/explore/correlationEditLogic.ts +++ b/public/app/features/explore/correlationEditLogic.ts @@ -1,6 +1,6 @@ import { template } from 'lodash'; -import { CORRELATION_EDITOR_POST_CONFIRM_ACTION } from 'app/types'; +import { CORRELATION_EDITOR_POST_CONFIRM_ACTION } from 'app/types/explore'; enum CONSEQUENCES { SOURCE_TARGET_CHANGE = 'cause the query in the right pane to be re-ran and links added to that data', diff --git a/public/app/features/explore/extensions/AddToDashboard/ExploreToDashboardPanel.tsx b/public/app/features/explore/extensions/AddToDashboard/ExploreToDashboardPanel.tsx index 87dbc64f5ac..a3c5f1a22fb 100644 --- a/public/app/features/explore/extensions/AddToDashboard/ExploreToDashboardPanel.tsx +++ b/public/app/features/explore/extensions/AddToDashboard/ExploreToDashboardPanel.tsx @@ -1,7 +1,7 @@ import { type ReactElement } from 'react'; import { AddToDashboardForm } from 'app/features/dashboard-scene/addToDashboard/AddToDashboardForm'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { getExploreItemSelector } from '../../state/selectors'; diff --git a/public/app/features/explore/extensions/AddToDashboard/addToDashboard.test.ts b/public/app/features/explore/extensions/AddToDashboard/addToDashboard.test.ts index 1c7c8912a17..2f42709c2b0 100644 --- a/public/app/features/explore/extensions/AddToDashboard/addToDashboard.test.ts +++ b/public/app/features/explore/extensions/AddToDashboard/addToDashboard.test.ts @@ -1,6 +1,6 @@ import { getDefaultTimeRange, MutableDataFrame } from '@grafana/data'; import { DataQuery, LoadingState } from '@grafana/schema'; -import { ExplorePanelData } from 'app/types'; +import { ExplorePanelData } from 'app/types/explore'; import { buildDashboardPanelFromExploreState } from './addToDashboard'; diff --git a/public/app/features/explore/extensions/AddToDashboard/addToDashboard.ts b/public/app/features/explore/extensions/AddToDashboard/addToDashboard.ts index ac2e9cca741..ea78a8f81ff 100644 --- a/public/app/features/explore/extensions/AddToDashboard/addToDashboard.ts +++ b/public/app/features/explore/extensions/AddToDashboard/addToDashboard.ts @@ -2,7 +2,7 @@ import { DataFrame, ExplorePanelsState } from '@grafana/data'; import { t } from '@grafana/i18n'; import { DataQuery, DataSourceRef, Panel } from '@grafana/schema'; import { DataTransformerConfig } from '@grafana/schema/dist/esm/raw/dashboard/x/dashboard_types.gen'; -import { ExplorePanelData } from 'app/types'; +import { ExplorePanelData } from 'app/types/explore'; interface ExploreToDashboardPanelOptions { queries: DataQuery[]; diff --git a/public/app/features/explore/extensions/AddToDashboard/getAddToDashboardTitle.ts b/public/app/features/explore/extensions/AddToDashboard/getAddToDashboardTitle.ts index d528956cb9f..ed90ef5aff7 100644 --- a/public/app/features/explore/extensions/AddToDashboard/getAddToDashboardTitle.ts +++ b/public/app/features/explore/extensions/AddToDashboard/getAddToDashboardTitle.ts @@ -1,5 +1,5 @@ import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; export function getAddToDashboardTitle(): string { const canCreateDashboard = contextSrv.hasPermission(AccessControlAction.DashboardsCreate); diff --git a/public/app/features/explore/extensions/AddToDashboard/index.test.tsx b/public/app/features/explore/extensions/AddToDashboard/index.test.tsx index 79a51c929cb..32d84a9466b 100644 --- a/public/app/features/explore/extensions/AddToDashboard/index.test.tsx +++ b/public/app/features/explore/extensions/AddToDashboard/index.test.tsx @@ -8,7 +8,7 @@ import { DataQuery } from '@grafana/schema'; import { contextSrv } from 'app/core/services/context_srv'; import { Echo } from 'app/core/services/echo/Echo'; import { configureStore } from 'app/store/configureStore'; -import { ExploreState } from 'app/types'; +import { ExploreState } from 'app/types/explore'; import { createEmptyQueryResponse } from '../../state/utils'; diff --git a/public/app/features/explore/extensions/AddToDashboard/index.tsx b/public/app/features/explore/extensions/AddToDashboard/index.tsx index 32277343c17..ef3278a58e9 100644 --- a/public/app/features/explore/extensions/AddToDashboard/index.tsx +++ b/public/app/features/explore/extensions/AddToDashboard/index.tsx @@ -2,7 +2,7 @@ import { useCallback, useState } from 'react'; import { t } from '@grafana/i18n'; import { Modal, ToolbarButton } from '@grafana/ui'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { getExploreItemSelector } from '../../state/selectors'; diff --git a/public/app/features/explore/extensions/ToolbarExtensionPoint.test.tsx b/public/app/features/explore/extensions/ToolbarExtensionPoint.test.tsx index 3adcc8ca6fb..0a72d621269 100644 --- a/public/app/features/explore/extensions/ToolbarExtensionPoint.test.tsx +++ b/public/app/features/explore/extensions/ToolbarExtensionPoint.test.tsx @@ -8,7 +8,7 @@ import { usePluginLinks } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; import { contextSrv } from 'app/core/services/context_srv'; import { configureStore } from 'app/store/configureStore'; -import { ExplorePanelData, ExploreState } from 'app/types'; +import { ExplorePanelData, ExploreState } from 'app/types/explore'; import { createEmptyQueryResponse } from '../state/utils'; diff --git a/public/app/features/explore/extensions/ToolbarExtensionPoint.tsx b/public/app/features/explore/extensions/ToolbarExtensionPoint.tsx index df78195ab3d..3c3a5f2286a 100644 --- a/public/app/features/explore/extensions/ToolbarExtensionPoint.tsx +++ b/public/app/features/explore/extensions/ToolbarExtensionPoint.tsx @@ -4,7 +4,9 @@ import { type PluginExtensionLink, PluginExtensionPoints, RawTimeRange, getTimeZ import { config, reportInteraction, usePluginLinks } from '@grafana/runtime'; import { DataQuery, TimeZone } from '@grafana/schema'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction, ExplorePanelData, useSelector } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { ExplorePanelData } from 'app/types/explore'; +import { useSelector } from 'app/types/store'; import { getExploreItemSelector, isLeftPaneSelector, selectCorrelationDetails } from '../state/selectors'; diff --git a/public/app/features/explore/extensions/getExploreExtensionConfigs.tsx b/public/app/features/explore/extensions/getExploreExtensionConfigs.tsx index 9be348955cf..7bbade45ad9 100644 --- a/public/app/features/explore/extensions/getExploreExtensionConfigs.tsx +++ b/public/app/features/explore/extensions/getExploreExtensionConfigs.tsx @@ -1,7 +1,7 @@ import { PluginExtensionAddedLinkConfig, PluginExtensionPoints } from '@grafana/data'; import { contextSrv } from 'app/core/core'; import { dispatch } from 'app/store/store'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { log } from '../../plugins/extensions/logs/log'; import { createAddedLinkConfig } from '../../plugins/extensions/utils'; diff --git a/public/app/features/explore/hooks/useExplorePageTitle.ts b/public/app/features/explore/hooks/useExplorePageTitle.ts index 804b2cf69d9..564064ef8dc 100644 --- a/public/app/features/explore/hooks/useExplorePageTitle.ts +++ b/public/app/features/explore/hooks/useExplorePageTitle.ts @@ -4,7 +4,7 @@ import { getDataSourceSrv } from '@grafana/runtime'; import { Branding } from 'app/core/components/Branding/Branding'; import { useGrafana } from 'app/core/context/GrafanaContext'; import { useNavModel } from 'app/core/hooks/useNavModel'; -import { ExploreQueryParams } from 'app/types'; +import { ExploreQueryParams } from 'app/types/explore'; import { isFulfilled, hasKey } from './utils'; diff --git a/public/app/features/explore/hooks/useKeyboardShortcuts.ts b/public/app/features/explore/hooks/useKeyboardShortcuts.ts index bd90b13e3f2..9ff1e32e5ed 100644 --- a/public/app/features/explore/hooks/useKeyboardShortcuts.ts +++ b/public/app/features/explore/hooks/useKeyboardShortcuts.ts @@ -3,8 +3,8 @@ import { Unsubscribable } from 'rxjs'; import { getAppEvents } from '@grafana/runtime'; import { useGrafana } from 'app/core/context/GrafanaContext'; -import { useDispatch } from 'app/types'; import { AbsoluteTimeEvent, CopyTimeEvent, PasteTimeEvent, ShiftTimeEvent, ZoomOutEvent } from 'app/types/events'; +import { useDispatch } from 'app/types/store'; import { copyTimeRangeToClipboard, diff --git a/public/app/features/explore/hooks/useSplitSizeUpdater.ts b/public/app/features/explore/hooks/useSplitSizeUpdater.ts index ea2f6279b8a..81c9fa2edeb 100644 --- a/public/app/features/explore/hooks/useSplitSizeUpdater.ts +++ b/public/app/features/explore/hooks/useSplitSizeUpdater.ts @@ -2,7 +2,7 @@ import { inRange } from 'lodash'; import { useState } from 'react'; import { useWindowSize } from 'react-use'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { splitSizeUpdateAction } from '../state/main'; import { isSplit, selectPanesEntries } from '../state/selectors'; diff --git a/public/app/features/explore/hooks/useStateSync/external.utils.ts b/public/app/features/explore/hooks/useStateSync/external.utils.ts index e691ba13b33..2df25f0dfde 100644 --- a/public/app/features/explore/hooks/useStateSync/external.utils.ts +++ b/public/app/features/explore/hooks/useStateSync/external.utils.ts @@ -2,7 +2,7 @@ import { isEmpty, isObject, mapValues, omitBy } from 'lodash'; import { ExploreUrlState, toURLRange } from '@grafana/data'; import { clearQueryKeys } from 'app/core/utils/explore'; -import { ExploreItemState } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; export function getUrlStateFromPaneState(pane: ExploreItemState): ExploreUrlState { return { diff --git a/public/app/features/explore/hooks/useStateSync/index.ts b/public/app/features/explore/hooks/useStateSync/index.ts index 348a12b0ac4..44462fa0d35 100644 --- a/public/app/features/explore/hooks/useStateSync/index.ts +++ b/public/app/features/explore/hooks/useStateSync/index.ts @@ -2,7 +2,8 @@ import { useEffect, useRef } from 'react'; import { useGrafana } from 'app/core/context/GrafanaContext'; import { useAppNotification } from 'app/core/copy/appNotification'; -import { addListener, ExploreQueryParams, useDispatch, useSelector } from 'app/types'; +import { ExploreQueryParams } from 'app/types/explore'; +import { addListener, useDispatch, useSelector } from 'app/types/store'; import { selectPanes } from '../../state/selectors'; diff --git a/public/app/features/explore/hooks/useStateSync/parseURL.ts b/public/app/features/explore/hooks/useStateSync/parseURL.ts index 4325630c1a9..ca40e024e0f 100644 --- a/public/app/features/explore/hooks/useStateSync/parseURL.ts +++ b/public/app/features/explore/hooks/useStateSync/parseURL.ts @@ -1,4 +1,4 @@ -import { ExploreQueryParams } from 'app/types'; +import { ExploreQueryParams } from 'app/types/explore'; import { v0Migrator } from './migrators/v0'; import { ExploreURLV1, v1Migrator } from './migrators/v1'; diff --git a/public/app/features/explore/hooks/useStateSync/synchronizer/fromURL.ts b/public/app/features/explore/hooks/useStateSync/synchronizer/fromURL.ts index 5497f481407..c196320a859 100644 --- a/public/app/features/explore/hooks/useStateSync/synchronizer/fromURL.ts +++ b/public/app/features/explore/hooks/useStateSync/synchronizer/fromURL.ts @@ -8,7 +8,8 @@ import { cancelQueries, runQueries, setQueriesAction } from 'app/features/explor import { updateTime } from 'app/features/explore/state/time'; import { fromURLRange } from 'app/features/explore/state/utils'; import { withUniqueRefIds } from 'app/features/explore/utils/queries'; -import { ExploreItemState, ThunkDispatch } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; +import { ThunkDispatch } from 'app/types/store'; import { getUrlStateFromPaneState } from '../index'; import { urlDiff } from '../internal.utils'; diff --git a/public/app/features/explore/hooks/useStateSync/synchronizer/init.ts b/public/app/features/explore/hooks/useStateSync/synchronizer/init.ts index dae7cd105d3..f4dec0dcecb 100644 --- a/public/app/features/explore/hooks/useStateSync/synchronizer/init.ts +++ b/public/app/features/explore/hooks/useStateSync/synchronizer/init.ts @@ -9,7 +9,7 @@ import { clearPanes, syncTimesAction } from 'app/features/explore/state/main'; import { fromURLRange } from 'app/features/explore/state/utils'; import { withUniqueRefIds } from 'app/features/explore/utils/queries'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { ThunkDispatch } from 'app/types'; +import { ThunkDispatch } from 'app/types/store'; import { getUrlStateFromPaneState } from '../index'; import { diff --git a/public/app/features/explore/hooks/useStateSync/synchronizer/toURL.ts b/public/app/features/explore/hooks/useStateSync/synchronizer/toURL.ts index ba164419822..9485eef2446 100644 --- a/public/app/features/explore/hooks/useStateSync/synchronizer/toURL.ts +++ b/public/app/features/explore/hooks/useStateSync/synchronizer/toURL.ts @@ -9,7 +9,7 @@ import { changePanelsStateAction } from 'app/features/explore/state/explorePane' import { splitClose, splitOpen } from 'app/features/explore/state/main'; import { runQueries } from 'app/features/explore/state/query'; import { changeRangeAction } from 'app/features/explore/state/time'; -import { ExploreState } from 'app/types'; +import { ExploreState } from 'app/types/explore'; import { getUrlStateFromPaneState } from '../index'; import { InitState } from '../internal.utils'; diff --git a/public/app/features/explore/mocks/data.ts b/public/app/features/explore/mocks/data.ts index 46f9355c104..3cf601b623f 100644 --- a/public/app/features/explore/mocks/data.ts +++ b/public/app/features/explore/mocks/data.ts @@ -1,8 +1,7 @@ import { Observable, of } from 'rxjs'; import { getDefaultTimeRange, LoadingState, LogsModel } from '@grafana/data'; - -import { ExplorePanelData } from '../../../types'; +import { ExplorePanelData } from 'app/types/explore'; type MockProps = { logsResult?: Partial<LogsModel>; diff --git a/public/app/features/explore/spec/helper/setup.tsx b/public/app/features/explore/spec/helper/setup.tsx index de530b584cc..647284ad25c 100644 --- a/public/app/features/explore/spec/helper/setup.tsx +++ b/public/app/features/explore/spec/helper/setup.tsx @@ -39,11 +39,11 @@ import { Echo } from 'app/core/services/echo/Echo'; import { setLastUsedDatasourceUID } from 'app/core/utils/explore'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; import { configureStore } from 'app/store/configureStore'; +import { ExploreQueryParams } from 'app/types/explore'; import { RichHistoryRemoteStorageDTO } from '../../../../core/history/RichHistoryRemoteStorage'; import { LokiDatasource } from '../../../../plugins/datasource/loki/datasource'; import { LokiQuery } from '../../../../plugins/datasource/loki/types'; -import { ExploreQueryParams } from '../../../../types'; import { initialUserState } from '../../../profile/state/reducers'; import ExplorePage from '../../ExplorePage'; import { QueriesDrawerContextProvider } from '../../QueriesDrawer/QueriesDrawerContext'; diff --git a/public/app/features/explore/state/correlations.ts b/public/app/features/explore/state/correlations.ts index 4e093ca3669..cc99f6388b7 100644 --- a/public/app/features/explore/state/correlations.ts +++ b/public/app/features/explore/state/correlations.ts @@ -7,7 +7,7 @@ import { createErrorNotification } from 'app/core/copy/appNotification'; import { CreateCorrelationParams } from 'app/features/correlations/types'; import { getCorrelationsBySourceUIDs, createCorrelation, generateDefaultLabel } from 'app/features/correlations/utils'; import { store } from 'app/store/store'; -import { ThunkResult } from 'app/types'; +import { ThunkResult } from 'app/types/store'; import { saveCorrelationsAction } from './explorePane'; import { splitClose } from './main'; diff --git a/public/app/features/explore/state/datasource.test.ts b/public/app/features/explore/state/datasource.test.ts index b024fdb35dd..44e6d7c74e5 100644 --- a/public/app/features/explore/state/datasource.test.ts +++ b/public/app/features/explore/state/datasource.test.ts @@ -1,6 +1,6 @@ import { DataSourceApi } from '@grafana/data'; import { DataQuery } from '@grafana/schema'; -import { ExploreItemState } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; import { updateDatasourceInstanceAction, datasourceReducer } from './datasource'; import { createEmptyQueryResponse } from './utils'; diff --git a/public/app/features/explore/state/datasource.ts b/public/app/features/explore/state/datasource.ts index 762aebe3ee8..0cea9e1126c 100644 --- a/public/app/features/explore/state/datasource.ts +++ b/public/app/features/explore/state/datasource.ts @@ -7,7 +7,8 @@ import { DataSourceRef } from '@grafana/schema'; import { RefreshPicker } from '@grafana/ui'; import { stopQueryState } from 'app/core/utils/explore'; import { getCorrelationsBySourceUIDs } from 'app/features/correlations/utils'; -import { ExploreItemState, createAsyncThunk } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; +import { createAsyncThunk } from 'app/types/store'; import { loadSupplementaryQueries } from '../utils/supplementaryQueries'; diff --git a/public/app/features/explore/state/explorePane.ts b/public/app/features/explore/state/explorePane.ts index 601ceea2dae..9835b9f3e09 100644 --- a/public/app/features/explore/state/explorePane.ts +++ b/public/app/features/explore/state/explorePane.ts @@ -16,8 +16,8 @@ import { DataQuery, DataSourceRef } from '@grafana/schema'; import { getQueryKeys } from 'app/core/utils/explore'; import { getCorrelationsBySourceUIDs } from 'app/features/correlations/utils'; import { getTimeZone } from 'app/features/profile/state/selectors'; -import { createAsyncThunk, ThunkResult } from 'app/types'; import { ExploreItemState } from 'app/types/explore'; +import { createAsyncThunk, ThunkResult } from 'app/types/store'; import { datasourceReducer } from './datasource'; import { queryReducer, runQueries } from './query'; diff --git a/public/app/features/explore/state/history.ts b/public/app/features/explore/state/history.ts index d582ef42878..4168668091d 100644 --- a/public/app/features/explore/state/history.ts +++ b/public/app/features/explore/state/history.ts @@ -12,7 +12,8 @@ import { updateRichHistorySettings, updateStarredInRichHistory, } from 'app/core/utils/richHistory'; -import { RichHistoryQuery, ThunkResult } from 'app/types'; +import { RichHistoryQuery } from 'app/types/explore'; +import { ThunkResult } from 'app/types/store'; import { supportedFeatures } from '../../../core/history/richHistoryStorageProvider'; import { RichHistorySearchFilters, RichHistorySettings } from '../../../core/utils/richHistoryTypes'; diff --git a/public/app/features/explore/state/main.test.ts b/public/app/features/explore/state/main.test.ts index d52a1be7211..7d504613831 100644 --- a/public/app/features/explore/state/main.test.ts +++ b/public/app/features/explore/state/main.test.ts @@ -3,11 +3,12 @@ import { thunkTester } from 'test/core/thunk/thunkTester'; import { dateTime, ExploreUrlState, serializeStateToUrlParam } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; +import { ExploreItemState, ExploreState } from 'app/types/explore'; +import { StoreState, ThunkDispatch } from 'app/types/store'; import { reducerTester } from '../../../../test/core/redux/reducerTester'; import { MockDataSourceApi } from '../../../../test/mocks/datasource_srv'; import { configureStore } from '../../../store/configureStore'; -import { ExploreItemState, ExploreState, StoreState, ThunkDispatch } from '../../../types'; import { exploreReducer, navigateToExplore, splitClose, splitOpen } from './main'; diff --git a/public/app/features/explore/state/main.ts b/public/app/features/explore/state/main.ts index 42a3a054d7f..d64ec7eca95 100644 --- a/public/app/features/explore/state/main.ts +++ b/public/app/features/explore/state/main.ts @@ -8,10 +8,10 @@ import { generateExploreId, GetExploreUrlArguments } from 'app/core/utils/explor import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { getTemplateSrv } from 'app/features/templating/template_srv'; import { CorrelationEditorDetailsUpdate, ExploreItemState, ExploreState } from 'app/types/explore'; +import { createAsyncThunk, ThunkResult } from 'app/types/store'; import { RichHistoryResults } from '../../../core/history/RichHistoryStorage'; import { RichHistorySearchFilters, RichHistorySettings } from '../../../core/utils/richHistoryTypes'; -import { createAsyncThunk, ThunkResult } from '../../../types'; import { withUniqueRefIds } from '../utils/queries'; import { DEFAULT_RANGE } from './constants'; diff --git a/public/app/features/explore/state/query.test.ts b/public/app/features/explore/state/query.test.ts index 8a4f3b96be0..42e486fa978 100644 --- a/public/app/features/explore/state/query.test.ts +++ b/public/app/features/explore/state/query.test.ts @@ -18,7 +18,8 @@ import { import { DataQuery, DataSourceRef } from '@grafana/schema'; import config from 'app/core/config'; import { queryLogsSample, queryLogsVolume } from 'app/features/logs/logsModel'; -import { createAsyncThunk, ExploreItemState, StoreState, ThunkDispatch } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; +import { createAsyncThunk, StoreState, ThunkDispatch } from 'app/types/store'; import { reducerTester } from '../../../../test/core/redux/reducerTester'; import * as richHistory from '../../../core/utils/richHistory'; diff --git a/public/app/features/explore/state/query.ts b/public/app/features/explore/state/query.ts index a070253ebc3..63091242c47 100644 --- a/public/app/features/explore/state/query.ts +++ b/public/app/features/explore/state/query.ts @@ -39,15 +39,14 @@ import { getFiscalYearStartMonth, getTimeZone } from 'app/features/profile/state import { SupportingQueryType } from 'app/plugins/datasource/loki/types'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; import { - createAsyncThunk, ExploreItemState, ExplorePanelData, + ExploreState, + QueryOptions, QueryTransaction, - StoreState, - ThunkDispatch, - ThunkResult, -} from 'app/types'; -import { ExploreState, QueryOptions, SupplementaryQueries } from 'app/types/explore'; + SupplementaryQueries, +} from 'app/types/explore'; +import { createAsyncThunk, StoreState, ThunkDispatch, ThunkResult } from 'app/types/store'; import { notifyApp } from '../../../core/actions'; import { createErrorNotification } from '../../../core/copy/appNotification'; diff --git a/public/app/features/explore/state/selectors.test.ts b/public/app/features/explore/state/selectors.test.ts index 7e3bd990fe1..12531a34fec 100644 --- a/public/app/features/explore/state/selectors.test.ts +++ b/public/app/features/explore/state/selectors.test.ts @@ -1,7 +1,7 @@ import { DataSourceApi, DataSourceJsonData } from '@grafana/data'; import { DataQuery } from '@grafana/schema/dist/esm/index'; import { configureStore } from 'app/store/configureStore'; -import { StoreState, ThunkDispatch } from 'app/types'; +import { StoreState, ThunkDispatch } from 'app/types/store'; import { selectExploreDSMaps } from './selectors'; import { createDefaultInitialState } from './testHelpers'; diff --git a/public/app/features/explore/state/selectors.ts b/public/app/features/explore/state/selectors.ts index 9f5ea7f86df..c184d3745c5 100644 --- a/public/app/features/explore/state/selectors.ts +++ b/public/app/features/explore/state/selectors.ts @@ -2,7 +2,8 @@ import { createSelector } from '@reduxjs/toolkit'; import { flatten, uniqBy } from 'lodash'; import { DataSourceRef } from '@grafana/schema'; -import { ExploreItemState, StoreState } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; +import { StoreState } from 'app/types/store'; export const selectPanes = (state: Pick<StoreState, 'explore'>) => state.explore.panes; export const selectExploreRoot = (state: Pick<StoreState, 'explore'>) => state.explore; diff --git a/public/app/features/explore/state/time.test.ts b/public/app/features/explore/state/time.test.ts index 1a382acbf17..43e0643ab9b 100644 --- a/public/app/features/explore/state/time.test.ts +++ b/public/app/features/explore/state/time.test.ts @@ -2,7 +2,7 @@ import { reducerTester } from 'test/core/redux/reducerTester'; import { dateTime } from '@grafana/data'; import { configureStore } from 'app/store/configureStore'; -import { ExploreItemState } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; import { createDefaultInitialState } from './testHelpers'; import { changeRangeAction, timeReducer, updateTime } from './time'; diff --git a/public/app/features/explore/state/time.ts b/public/app/features/explore/state/time.ts index f975a59d44f..536c51f9f96 100644 --- a/public/app/features/explore/state/time.ts +++ b/public/app/features/explore/state/time.ts @@ -17,7 +17,8 @@ import { getCopiedTimeRange, getShiftedTimeRange, getZoomedTimeRange } from 'app import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { sortLogsResult } from 'app/features/logs/utils'; import { getFiscalYearStartMonth, getTimeZone } from 'app/features/profile/state/selectors'; -import { ExploreItemState, ThunkDispatch, ThunkResult } from 'app/types'; +import { ExploreItemState } from 'app/types/explore'; +import { ThunkDispatch, ThunkResult } from 'app/types/store'; import { syncTimesAction } from './main'; import { runLoadMoreLogsQueries, runQueries } from './query'; diff --git a/public/app/features/explore/state/utils.ts b/public/app/features/explore/state/utils.ts index 45b8b39e0e4..4aba4a85f35 100644 --- a/public/app/features/explore/state/utils.ts +++ b/public/app/features/explore/state/utils.ts @@ -25,8 +25,8 @@ import { DataQuery, DataSourceJsonData, DataSourceRef, TimeZone } from '@grafana import { getLocalRichHistoryStorage } from 'app/core/history/richHistoryStorageProvider'; import { SortOrder } from 'app/core/utils/richHistoryTypes'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { ExplorePanelData, StoreState } from 'app/types'; -import { ExploreItemState, RichHistoryQuery } from 'app/types/explore'; +import { ExploreItemState, ExplorePanelData, RichHistoryQuery } from 'app/types/explore'; +import { StoreState } from 'app/types/store'; import store from '../../../core/store'; import { setLastUsedDatasourceUID } from '../../../core/utils/explore'; diff --git a/public/app/features/explore/useLiveTailControls.ts b/public/app/features/explore/useLiveTailControls.ts index 42837521e05..e78c1272ad7 100644 --- a/public/app/features/explore/useLiveTailControls.ts +++ b/public/app/features/explore/useLiveTailControls.ts @@ -2,7 +2,7 @@ import { useCallback } from 'react'; import * as React from 'react'; import { RefreshPicker } from '@grafana/ui'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { setPausedStateAction, runQueries, clearLogs } from './state/query'; import { changeRefreshInterval } from './state/time'; diff --git a/public/app/features/explore/utils/decorators.test.ts b/public/app/features/explore/utils/decorators.test.ts index 5e2e1517eee..3be590a31f5 100644 --- a/public/app/features/explore/utils/decorators.test.ts +++ b/public/app/features/explore/utils/decorators.test.ts @@ -13,7 +13,7 @@ import { import { CorrelationData } from '@grafana/runtime'; import { DataSourceJsonData, DataQuery } from '@grafana/schema'; import TableModel from 'app/core/TableModel'; -import { ExplorePanelData } from 'app/types'; +import { ExplorePanelData } from 'app/types/explore'; import { decorateWithCorrelations, diff --git a/public/app/features/explore/utils/decorators.ts b/public/app/features/explore/utils/decorators.ts index 08dc24b6a7d..5a877294649 100644 --- a/public/app/features/explore/utils/decorators.ts +++ b/public/app/features/explore/utils/decorators.ts @@ -16,9 +16,9 @@ import { } from '@grafana/data'; import { config, CorrelationData } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; +import { ExplorePanelData } from 'app/types/explore'; import { refreshIntervalToSortOrder } from '../../../core/utils/explore'; -import { ExplorePanelData } from '../../../types'; import { attachCorrelationsToDataFrames } from '../../correlations/utils'; import { dataFrameToLogsModel } from '../../logs/logsModel'; import { sortLogsResult } from '../../logs/utils'; diff --git a/public/app/features/explore/utils/supplementaryQueries.test.ts b/public/app/features/explore/utils/supplementaryQueries.test.ts index 8d274f162b1..ebc1be38292 100644 --- a/public/app/features/explore/utils/supplementaryQueries.test.ts +++ b/public/app/features/explore/utils/supplementaryQueries.test.ts @@ -17,10 +17,10 @@ import { DataQueryResponse, } from '@grafana/data'; import { DataQuery } from '@grafana/schema'; +import { ExplorePanelData } from 'app/types/explore'; import { MockDataSourceApi } from '../../../../test/mocks/datasource_srv'; import { MockDataQueryRequest, MockQuery } from '../../../../test/mocks/query'; -import { ExplorePanelData } from '../../../types'; import { mockExplorePanelData } from '../mocks/data'; import { getSupplementaryQueryProvider } from './supplementaryQueries'; diff --git a/public/app/features/explore/utils/supplementaryQueries.ts b/public/app/features/explore/utils/supplementaryQueries.ts index ae25b8902b4..a705c8193fb 100644 --- a/public/app/features/explore/utils/supplementaryQueries.ts +++ b/public/app/features/explore/utils/supplementaryQueries.ts @@ -16,7 +16,7 @@ import { SupplementaryQueryType, } from '@grafana/data'; import store from 'app/core/store'; -import { ExplorePanelData, SupplementaryQueries } from 'app/types'; +import { ExplorePanelData, SupplementaryQueries } from 'app/types/explore'; import { makeDataFramesForLogs, queryLogsSample, queryLogsVolume } from '../../logs/logsModel'; diff --git a/public/app/features/explore/utils/supplementaryQueries_legacy.test.ts b/public/app/features/explore/utils/supplementaryQueries_legacy.test.ts index 6d6735a12c5..da43739db79 100644 --- a/public/app/features/explore/utils/supplementaryQueries_legacy.test.ts +++ b/public/app/features/explore/utils/supplementaryQueries_legacy.test.ts @@ -22,10 +22,10 @@ import { } from '@grafana/data'; import { getDataSourceSrv } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; +import { ExplorePanelData } from 'app/types/explore'; import { MockDataSourceApi } from '../../../../test/mocks/datasource_srv'; import { MockDataQueryRequest, MockQuery } from '../../../../test/mocks/query'; -import { ExplorePanelData } from '../../../types'; import { mockExplorePanelData } from '../mocks/data'; import { getSupplementaryQueryProvider } from './supplementaryQueries'; diff --git a/public/app/features/folders/state/actions.ts b/public/app/features/folders/state/actions.ts index e79c97f97f5..27b22a3102d 100644 --- a/public/app/features/folders/state/actions.ts +++ b/public/app/features/folders/state/actions.ts @@ -1,6 +1,7 @@ import { updateNavIndex } from 'app/core/actions'; import { backendSrv } from 'app/core/services/backend_srv'; -import { FolderDTO, ThunkResult } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; +import { ThunkResult } from 'app/types/store'; import { buildNavModel } from './navModel'; import { loadFolder } from './reducers'; diff --git a/public/app/features/folders/state/navModel.ts b/public/app/features/folders/state/navModel.ts index 7db065815b2..49a5167652f 100644 --- a/public/app/features/folders/state/navModel.ts +++ b/public/app/features/folders/state/navModel.ts @@ -3,7 +3,8 @@ import { t } from '@grafana/i18n'; import { config } from '@grafana/runtime'; import { contextSrv } from 'app/core/services/context_srv'; import { getNavSubTitle } from 'app/core/utils/navBarItem-translations'; -import { AccessControlAction, FolderDTO, FolderParent } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { FolderDTO, FolderParent } from 'app/types/folders'; export const FOLDER_ID = 'manage-folder'; diff --git a/public/app/features/folders/state/reducers.test.ts b/public/app/features/folders/state/reducers.test.ts index 2665316f39e..33f9fe0e4e9 100644 --- a/public/app/features/folders/state/reducers.test.ts +++ b/public/app/features/folders/state/reducers.test.ts @@ -1,4 +1,4 @@ -import { FolderDTO, FolderState } from 'app/types'; +import { FolderDTO, FolderState } from 'app/types/folders'; import { reducerTester } from '../../../../test/core/redux/reducerTester'; diff --git a/public/app/features/folders/state/reducers.ts b/public/app/features/folders/state/reducers.ts index f544fde391a..849f57e7631 100644 --- a/public/app/features/folders/state/reducers.ts +++ b/public/app/features/folders/state/reducers.ts @@ -1,7 +1,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { endpoints } from 'app/features/browse-dashboards/api/browseDashboardsAPI'; -import { FolderDTO, FolderState } from 'app/types'; +import { FolderState, FolderDTO } from 'app/types/folders'; export const initialState: FolderState = { id: 0, diff --git a/public/app/features/invites/InviteeRow.tsx b/public/app/features/invites/InviteeRow.tsx index dd819e7ddbb..d5fd484e083 100644 --- a/public/app/features/invites/InviteeRow.tsx +++ b/public/app/features/invites/InviteeRow.tsx @@ -3,7 +3,7 @@ import { connect, ConnectedProps } from 'react-redux'; import { t } from '@grafana/i18n'; import { Button, ClipboardButton } from '@grafana/ui'; -import { Invitee } from 'app/types'; +import { Invitee } from 'app/types/user'; import { revokeInvite } from './state/actions'; diff --git a/public/app/features/invites/InviteesTable.tsx b/public/app/features/invites/InviteesTable.tsx index 2bab93ecfdb..04fc9544562 100644 --- a/public/app/features/invites/InviteesTable.tsx +++ b/public/app/features/invites/InviteesTable.tsx @@ -1,7 +1,7 @@ import { PureComponent } from 'react'; import { Trans } from '@grafana/i18n'; -import { Invitee } from 'app/types'; +import { Invitee } from 'app/types/user'; import InviteeRow from './InviteeRow'; diff --git a/public/app/features/invites/state/actions.ts b/public/app/features/invites/state/actions.ts index d4af5d085b1..72a40840bd6 100644 --- a/public/app/features/invites/state/actions.ts +++ b/public/app/features/invites/state/actions.ts @@ -1,7 +1,9 @@ import { getBackendSrv } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; import { FormModel } from 'app/features/org/UserInviteForm'; -import { AccessControlAction, createAsyncThunk, Invitee } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { createAsyncThunk } from 'app/types/store'; +import { Invitee } from 'app/types/user'; export const fetchInvitees = createAsyncThunk('users/fetchInvitees', async () => { if (!contextSrv.hasPermission(AccessControlAction.OrgUsersAdd)) { diff --git a/public/app/features/invites/state/reducers.ts b/public/app/features/invites/state/reducers.ts index 35ac54eeca0..00a5701cba8 100644 --- a/public/app/features/invites/state/reducers.ts +++ b/public/app/features/invites/state/reducers.ts @@ -1,6 +1,6 @@ import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'; -import { Invitee } from 'app/types'; +import { Invitee } from 'app/types/user'; import { fetchInvitees, revokeInvite } from './actions'; diff --git a/public/app/features/invites/state/selectors.ts b/public/app/features/invites/state/selectors.ts index 5722ecb263f..4f5af894ee9 100644 --- a/public/app/features/invites/state/selectors.ts +++ b/public/app/features/invites/state/selectors.ts @@ -1,6 +1,6 @@ import { EntityState, createSelector } from '@reduxjs/toolkit'; -import { Invitee } from 'app/types'; +import { Invitee } from 'app/types/user'; import { selectors } from './reducers'; diff --git a/public/app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch.tsx b/public/app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch.tsx index 9c6ca73c898..d86f7a55517 100644 --- a/public/app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch.tsx +++ b/public/app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch.tsx @@ -5,7 +5,7 @@ import { useDebounce } from 'react-use'; import { GrafanaTheme2, PanelPluginMeta, SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { useStyles2, VerticalGroup, FilterInput } from '@grafana/ui'; -import { FolderInfo } from 'app/types'; +import { FolderInfo } from 'app/types/folders'; import { FolderFilter } from '../../../../core/components/FolderFilter/FolderFilter'; import { PanelTypeFilter } from '../../../../core/components/PanelTypeFilter/PanelTypeFilter'; diff --git a/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx b/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx index 4d3820e6609..d9dafffe82d 100644 --- a/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx +++ b/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx @@ -7,7 +7,7 @@ import { Button, VerticalGroup } from '@grafana/ui'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { changeToLibraryPanel } from 'app/features/panel/state/actions'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { PanelTypeFilter } from '../../../../core/components/PanelTypeFilter/PanelTypeFilter'; import { LibraryElementDTO } from '../../types'; diff --git a/public/app/features/logs/components/log-context/LogRowContextModal.test.tsx b/public/app/features/logs/components/log-context/LogRowContextModal.test.tsx index 29cf6c6c5e3..f6446e804e1 100644 --- a/public/app/features/logs/components/log-context/LogRowContextModal.test.tsx +++ b/public/app/features/logs/components/log-context/LogRowContextModal.test.tsx @@ -57,8 +57,8 @@ const dfAfter = createDataFrame({ let getRowContext = jest.fn(); const dispatchMock = jest.fn(); -jest.mock('app/types', () => ({ - ...jest.requireActual('app/types'), +jest.mock('app/types/store', () => ({ + ...jest.requireActual('app/types/store'), useDispatch: () => dispatchMock, })); diff --git a/public/app/features/logs/components/log-context/LogRowContextModal.tsx b/public/app/features/logs/components/log-context/LogRowContextModal.tsx index 5956c892c40..c7aaa58a3af 100644 --- a/public/app/features/logs/components/log-context/LogRowContextModal.tsx +++ b/public/app/features/logs/components/log-context/LogRowContextModal.tsx @@ -24,7 +24,7 @@ import { Button, Modal, useTheme2 } from '@grafana/ui'; import store from 'app/core/store'; import { SETTINGS_KEYS } from 'app/features/explore/Logs/utils/logs'; import { splitOpen } from 'app/features/explore/state/main'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { dataFrameToLogsModel } from '../../logsModel'; import { sortLogRows } from '../../utils'; diff --git a/public/app/features/logs/components/panel/LogLine.test.tsx b/public/app/features/logs/components/panel/LogLine.test.tsx index 1a099f950e9..3ab836aaa18 100644 --- a/public/app/features/logs/components/panel/LogLine.test.tsx +++ b/public/app/features/logs/components/panel/LogLine.test.tsx @@ -8,13 +8,14 @@ import { createLogLine } from '../mocks/logRow'; import { getGridTemplateColumns, getStyles, LogLine, Props } from './LogLine'; import { LogListFontSize } from './LogList'; -import { LogListContextProvider } from './LogListContext'; +import { LogListContextProvider, LogListContext } from './LogListContext'; import { LogListSearchContext } from './LogListSearchContext'; -import { defaultProps } from './__mocks__/LogListContext'; +import { defaultProps, defaultValue } from './__mocks__/LogListContext'; import { LogListModel } from './processing'; import { LogLineVirtualization } from './virtualization'; jest.mock('./LogListContext'); +jest.mock('../LogDetails'); const theme = createTheme(); const virtualization = new LogLineVirtualization(theme, 'default'); @@ -424,6 +425,40 @@ describe.each(fontSizes)('LogLine', (fontSize: LogListFontSize) => { expect(screen.getByText('un')).toBeInTheDocument(); }); }); + + describe('Inline details', () => { + test('Details are not rendered if details mode is not inline', () => { + render( + <LogListContext.Provider + value={{ + ...defaultValue, + showDetails: [log], + detailsMode: 'sidebar', + detailsDisplayed: jest.fn().mockReturnValue(true), + }} + > + <LogLine {...defaultProps} /> + </LogListContext.Provider> + ); + expect(screen.queryByPlaceholderText('Search field names and values')).not.toBeInTheDocument(); + }); + + test('Details are rendered if details mode is inline', () => { + render( + <LogListContext.Provider + value={{ + ...defaultValue, + showDetails: [log], + detailsMode: 'inline', + detailsDisplayed: jest.fn().mockReturnValue(true), + }} + > + <LogLine {...defaultProps} /> + </LogListContext.Provider> + ); + expect(screen.getByPlaceholderText('Search field names and values')).toBeInTheDocument(); + }); + }); }); describe('getGridTemplateColumns', () => { diff --git a/public/app/features/logs/components/panel/LogLine.tsx b/public/app/features/logs/components/panel/LogLine.tsx index ec3062ee3b5..9f96fb3a3b7 100644 --- a/public/app/features/logs/components/panel/LogLine.tsx +++ b/public/app/features/logs/components/panel/LogLine.tsx @@ -10,6 +10,7 @@ import { Button, Icon, Tooltip } from '@grafana/ui'; import { LOG_LINE_BODY_FIELD_NAME } from '../LogDetailsBody'; import { LogMessageAnsi } from '../LogMessageAnsi'; +import { InlineLogLineDetails } from './LogLineDetails'; import { LogLineMenu } from './LogLineMenu'; import { useLogIsPermalinked, useLogIsPinned, useLogListContext } from './LogListContext'; import { useLogListSearchContext } from './LogListSearchContext'; @@ -50,7 +51,7 @@ export const LogLine = ({ wrapLogMessage, }: Props) => { return ( - <div style={style}> + <div style={wrapLogMessage ? style : { ...style, width: 'max-content', minWidth: '100%' }}> <LogLineComponent displayedFields={displayedFields} height={style.height} @@ -88,6 +89,7 @@ const LogLineComponent = memo( }: LogLineComponentProps) => { const { detailsDisplayed, + detailsMode, dedupStrategy, enableLogDetails, fontSize, @@ -235,6 +237,7 @@ const LogLineComponent = memo( </Button> </div> )} + {detailsMode === 'inline' && detailsShown && <InlineLogLineDetails logs={[]} />} </> ); } diff --git a/public/app/features/logs/components/panel/LogLineDetails.tsx b/public/app/features/logs/components/panel/LogLineDetails.tsx index 212da50add7..dbd2990ea6b 100644 --- a/public/app/features/logs/components/panel/LogLineDetails.tsx +++ b/public/app/features/logs/components/panel/LogLineDetails.tsx @@ -17,9 +17,11 @@ export interface Props { onResize(): void; } +export type LogLineDetailsMode = 'inline' | 'sidebar'; + export const LogLineDetails = ({ containerElement, focusLogLine, logs, onResize }: Props) => { - const { detailsWidth, logOptionsStorageKey, setDetailsWidth, showDetails } = useLogListContext(); - const styles = useStyles2(getStyles); + const { detailsWidth, setDetailsWidth, showDetails } = useLogListContext(); + const styles = useStyles2(getStyles, 'sidebar'); const dragStyles = useStyles2(getDragStyles); const containerRef = useRef<HTMLDivElement | null>(null); @@ -54,20 +56,51 @@ export const LogLineDetails = ({ containerElement, focusLogLine, logs, onResize > <div className={styles.container} ref={containerRef}> <div className={styles.scrollContainer}> - <LogLineDetailsComponent log={showDetails[0]} logOptionsStorageKey={logOptionsStorageKey} logs={logs} /> + <LogLineDetailsComponent log={showDetails[0]} logs={logs} /> </div> </div> </Resizable> ); }; -const getStyles = (theme: GrafanaTheme2) => ({ +export interface InlineLogLineDetailsProps { + logs: LogListModel[]; +} + +export const InlineLogLineDetails = ({ logs }: InlineLogLineDetailsProps) => { + const { showDetails } = useLogListContext(); + const styles = useStyles2(getStyles, 'inline'); + + if (!showDetails.length) { + return null; + } + + return ( + <div className={`${styles.inlineWrapper} log-line-inline-details`}> + <div className={styles.container}> + <div className={styles.scrollContainer}> + <LogLineDetailsComponent log={showDetails[0]} logs={logs} /> + </div> + </div> + </div> + ); +}; + +export const LOG_LINE_DETAILS_HEIGHT = 35; + +const getStyles = (theme: GrafanaTheme2, mode: LogLineDetailsMode) => ({ + inlineWrapper: css({ + gridColumn: '1 / -1', + height: `${LOG_LINE_DETAILS_HEIGHT}vh`, + paddingBottom: theme.spacing(0.5), + marginRight: 1, + }), container: css({ overflow: 'auto', height: '100%', boxShadow: theme.shadows.z1, border: `1px solid ${theme.colors.border.medium}`, - borderRight: 'none', + borderRight: mode === 'sidebar' ? 'none' : undefined, }), scrollContainer: css({ overflow: 'auto', diff --git a/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx b/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx index fefd7004879..0024860a93a 100644 --- a/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx +++ b/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx @@ -18,12 +18,11 @@ import { LogListModel } from './processing'; interface LogLineDetailsComponentProps { log: LogListModel; - logOptionsStorageKey?: string; logs: LogListModel[]; } -export const LogLineDetailsComponent = ({ log, logOptionsStorageKey, logs }: LogLineDetailsComponentProps) => { - const { displayedFields, setDisplayedFields } = useLogListContext(); +export const LogLineDetailsComponent = ({ log, logs }: LogLineDetailsComponentProps) => { + const { displayedFields, logOptionsStorageKey, setDisplayedFields } = useLogListContext(); const [search, setSearch] = useState(''); const inputRef = useRef(''); const styles = useStyles2(getStyles); diff --git a/public/app/features/logs/components/panel/LogLineDetailsHeader.tsx b/public/app/features/logs/components/panel/LogLineDetailsHeader.tsx index 2c76d814cb6..140a7f86fca 100644 --- a/public/app/features/logs/components/panel/LogLineDetailsHeader.tsx +++ b/public/app/features/logs/components/panel/LogLineDetailsHeader.tsx @@ -1,13 +1,14 @@ import { css } from '@emotion/css'; import { useCallback, useMemo, MouseEvent, useRef, ChangeEvent } from 'react'; -import { colorManipulator, GrafanaTheme2, LogRowModel } from '@grafana/data'; +import { colorManipulator, GrafanaTheme2, LogRowModel, store } from '@grafana/data'; import { t } from '@grafana/i18n'; import { IconButton, Input, useStyles2 } from '@grafana/ui'; import { copyText, handleOpenLogsContextClick } from '../../utils'; import { LOG_LINE_BODY_FIELD_NAME } from '../LogDetailsBody'; +import { LogLineDetailsMode } from './LogLineDetails'; import { useLogIsPinned, useLogListContext } from './LogListContext'; import { LogListModel } from './processing'; @@ -20,18 +21,22 @@ interface Props { export const LogLineDetailsHeader = ({ log, search, onSearch }: Props) => { const { closeDetails, + detailsMode, displayedFields, getRowContextQuery, + logOptionsStorageKey, logSupportsContext, + setDetailsMode, onClickHideField, onClickShowField, onOpenContext, onPermalinkClick, onPinLine, onUnpinLine, + wrapLogMessage, } = useLogListContext(); const pinned = useLogIsPinned(log); - const styles = useStyles2(getStyles); + const styles = useStyles2(getStyles, detailsMode, wrapLogMessage); const containerRef = useRef<HTMLDivElement | null>(null); const inputRef = useRef<HTMLInputElement | null>(null); @@ -66,6 +71,15 @@ export const LogLineDetailsHeader = ({ log, search, onSearch }: Props) => { const showLogLineToggle = onClickHideField && onClickShowField && displayedFields.length > 0; const logLineDisplayed = displayedFields.includes(LOG_LINE_BODY_FIELD_NAME); + const toggleDetailsMode = useCallback(() => { + const newMode = detailsMode === 'inline' ? 'sidebar' : 'inline'; + if (logOptionsStorageKey) { + store.set(`${logOptionsStorageKey}.detailsMode`, newMode); + } + + setDetailsMode(newMode); + }, [detailsMode, logOptionsStorageKey, setDetailsMode]); + const toggleLogLine = useCallback(() => { if (logLineDisplayed) { onClickHideField?.(LOG_LINE_BODY_FIELD_NAME); @@ -121,65 +135,76 @@ export const LogLineDetailsHeader = ({ log, search, onSearch }: Props) => { variant={logLineDisplayed ? 'primary' : undefined} /> )} - <IconButton - tooltip={t('logs.log-line-details.copy-to-clipboard', 'Copy to clipboard')} - tooltipPlacement="top" - size="md" - name="copy" - onClick={copyLogLine} - tabIndex={0} - /> - {onPermalinkClick && log.rowId !== undefined && log.uid && ( + <div className={styles.icons}> <IconButton - tooltip={t('logs.log-line-details.copy-shortlink', 'Copy shortlink')} + tooltip={t('logs.log-line-details.copy-to-clipboard', 'Copy to clipboard')} tooltipPlacement="top" size="md" - name="share-alt" - onClick={copyLinkToLogLine} + name="copy" + onClick={copyLogLine} tabIndex={0} /> - )} - {pinned && onUnpinLine && ( + {onPermalinkClick && log.rowId !== undefined && log.uid && ( + <IconButton + tooltip={t('logs.log-line-details.copy-shortlink', 'Copy shortlink')} + tooltipPlacement="top" + size="md" + name="share-alt" + onClick={copyLinkToLogLine} + tabIndex={0} + /> + )} + {pinned && onUnpinLine && ( + <IconButton + size="md" + name="gf-pin" + onClick={togglePinning} + tooltip={t('logs.log-line-details.unpin-line', 'Unpin log')} + tooltipPlacement="top" + tabIndex={0} + variant="primary" + /> + )} + {!pinned && onPinLine && ( + <IconButton + size="md" + name="gf-pin" + onClick={togglePinning} + tooltip={t('logs.log-line-details.pin-line', 'Pin log')} + tooltipPlacement="top" + tabIndex={0} + /> + )} + {shouldlogSupportsContext && ( + <IconButton + size="md" + name="gf-show-context" + onClick={showContext} + tooltip={t('logs.log-line-details.show-context', 'Show context')} + tooltipPlacement="top" + tabIndex={0} + /> + )} <IconButton - size="md" - name="gf-pin" - onClick={togglePinning} - tooltip={t('logs.log-line-details.unpin-line', 'Unpin log')} - tooltipPlacement="top" - tabIndex={0} - variant="primary" + name={detailsMode === 'inline' ? 'columns' : 'gf-layout-simple'} + tooltip={ + detailsMode === 'inline' + ? t('logs.log-line-details.sidebar-mode', 'Anchor to the right') + : t('logs.log-line-details.inline-mode', 'Display inline') + } + onClick={toggleDetailsMode} /> - )} - {!pinned && onPinLine && ( <IconButton - size="md" - name="gf-pin" - onClick={togglePinning} - tooltip={t('logs.log-line-details.pin-line', 'Pin log')} - tooltipPlacement="top" - tabIndex={0} + name="times" + aria-label={t('logs.log-line-details.close', 'Close log details')} + onClick={closeDetails} /> - )} - {shouldlogSupportsContext && ( - <IconButton - size="md" - name="gf-show-context" - onClick={showContext} - tooltip={t('logs.log-line-details.show-context', 'Show context')} - tooltipPlacement="top" - tabIndex={0} - /> - )} - <IconButton - name="times" - aria-label={t('logs.log-line-details.close', 'Close log details')} - onClick={closeDetails} - /> + </div> </div> ); }; -const getStyles = (theme: GrafanaTheme2) => ({ +const getStyles = (theme: GrafanaTheme2, mode: LogLineDetailsMode, wrapLogMessage: boolean) => ({ container: css({ overflow: 'auto', height: '100%', @@ -192,7 +217,7 @@ const getStyles = (theme: GrafanaTheme2) => ({ alignItems: 'center', background: theme.colors.background.canvas, display: 'flex', - flexDirection: 'row', + flexDirection: !wrapLogMessage && mode === 'inline' ? 'row-reverse' : 'row', gap: theme.spacing(0.75), zIndex: theme.zIndex.navbarFixed, height: theme.spacing(5.5), @@ -201,6 +226,10 @@ const getStyles = (theme: GrafanaTheme2) => ({ position: 'sticky', top: 0, }), + icons: css({ + display: 'flex', + gap: theme.spacing(0.75), + }), copyLogButton: css({ padding: 0, height: theme.spacing(4), diff --git a/public/app/features/logs/components/panel/LogList.test.tsx b/public/app/features/logs/components/panel/LogList.test.tsx index 17eda97f4f6..fde0ea89dec 100644 --- a/public/app/features/logs/components/panel/LogList.test.tsx +++ b/public/app/features/logs/components/panel/LogList.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { CoreApp, getDefaultTimeRange, LogRowModel, LogsDedupStrategy, LogsSortOrder } from '@grafana/data'; +import { CoreApp, getDefaultTimeRange, LogRowModel, LogsDedupStrategy, LogsSortOrder, store } from '@grafana/data'; import { disablePopoverMenu, enablePopoverMenu, isPopoverMenuDisabled } from '../../utils'; import { createLogRow } from '../mocks/logRow'; @@ -75,6 +75,12 @@ describe('LogList', () => { }); test('Supports showing log details', async () => { + jest.spyOn(store, 'get').mockImplementation((option: string) => { + if (option === 'storage-key.detailsMode') { + return 'sidebar'; + } + return undefined; + }); const onClickFilterLabel = jest.fn(); const onClickFilterOutLabel = jest.fn(); const onClickShowField = jest.fn(); @@ -86,6 +92,50 @@ describe('LogList', () => { onClickFilterLabel={onClickFilterLabel} onClickFilterOutLabel={onClickFilterOutLabel} onClickShowField={onClickShowField} + logOptionsStorageKey="storage-key" + /> + ); + + await userEvent.click(screen.getByText('log message 1')); + await screen.findByText('Fields'); + + expect(screen.getByText('name_of_the_label')).toBeInTheDocument(); + expect(screen.getByText('value of the label')).toBeInTheDocument(); + + await userEvent.click(screen.getByLabelText('Filter for value in query A')); + expect(onClickFilterLabel).toHaveBeenCalledTimes(1); + + await userEvent.click(screen.getByLabelText('Filter out value in query A')); + expect(onClickFilterOutLabel).toHaveBeenCalledTimes(1); + + await userEvent.click(screen.getByLabelText('Show this field instead of the message')); + expect(onClickShowField).toHaveBeenCalledTimes(1); + + await userEvent.click(screen.getByLabelText('Close log details')); + + expect(screen.queryByText('Fields')).not.toBeInTheDocument(); + expect(screen.queryByText('Close log details')).not.toBeInTheDocument(); + }); + + test('Supports showing inline log details', async () => { + jest.spyOn(store, 'get').mockImplementation((option: string) => { + if (option === 'storage-key.detailsMode') { + return 'inline'; + } + return undefined; + }); + const onClickFilterLabel = jest.fn(); + const onClickFilterOutLabel = jest.fn(); + const onClickShowField = jest.fn(); + + render( + <LogList + {...defaultProps} + enableLogDetails={true} + onClickFilterLabel={onClickFilterLabel} + onClickFilterOutLabel={onClickFilterOutLabel} + onClickShowField={onClickShowField} + logOptionsStorageKey="storage-key" /> ); diff --git a/public/app/features/logs/components/panel/LogList.tsx b/public/app/features/logs/components/panel/LogList.tsx index 489741fd59b..a5115f5e447 100644 --- a/public/app/features/logs/components/panel/LogList.tsx +++ b/public/app/features/logs/components/panel/LogList.tsx @@ -26,7 +26,7 @@ import { GetFieldLinksFn } from 'app/plugins/panel/logs/types'; import { InfiniteScroll } from './InfiniteScroll'; import { getGridTemplateColumns } from './LogLine'; -import { LogLineDetails } from './LogLineDetails'; +import { LogLineDetails, LogLineDetailsMode } from './LogLineDetails'; import { GetRowContextQueryFn, LogLineMenuCustomItem } from './LogLineMenu'; import { LogListContextProvider, LogListState, useLogListContext } from './LogListContext'; import { LogListControls } from './LogListControls'; @@ -41,6 +41,7 @@ export interface Props { app: CoreApp; containerElement: HTMLDivElement; dedupStrategy: LogsDedupStrategy; + detailsMode?: LogLineDetailsMode; displayedFields: string[]; enableLogDetails: boolean; eventBus?: EventBus; @@ -105,11 +106,12 @@ export const LogList = ({ app, displayedFields, containerElement, + logOptionsStorageKey, + detailsMode = logOptionsStorageKey ? (store.get(`${logOptionsStorageKey}.detailsMode`) ?? 'sidebar') : 'sidebar', dedupStrategy, enableLogDetails, eventBus, filterLevels, - logOptionsStorageKey, fontSize = logOptionsStorageKey ? (store.get(`${logOptionsStorageKey}.fontSize`) ?? 'default') : 'default', getFieldLinks, getRowContextQuery, @@ -152,6 +154,7 @@ export const LogList = ({ app={app} containerElement={containerElement} dedupStrategy={dedupStrategy} + detailsMode={detailsMode} displayedFields={displayedFields} enableLogDetails={enableLogDetails} filterLevels={filterLevels} @@ -222,6 +225,7 @@ const LogListComponent = ({ app, displayedFields, dedupStrategy, + detailsMode, filterLevels, fontSize, forceEscape, @@ -456,9 +460,11 @@ const LogListComponent = ({ height={listHeight} itemCount={itemCount} itemSize={getLogLineSize.bind(null, virtualization, filteredLogs, widthContainer, displayedFields, { + detailsMode, hasLogsWithErrors, hasSampledLogs, showDuplicates: dedupStrategy !== LogsDedupStrategy.none, + showDetails, showTime, wrap: wrapLogMessage, })} @@ -476,7 +482,7 @@ const LogListComponent = ({ )} </InfiniteScroll> </div> - {showDetails.length > 0 && ( + {detailsMode === 'sidebar' && showDetails.length > 0 && ( <LogLineDetails containerElement={containerElement} focusLogLine={focusLogLine} @@ -501,6 +507,9 @@ function getStyles( '& .unwrapped-log-line': { display: 'grid', gridTemplateColumns: getGridTemplateColumns(columns, displayedFields), + '& .field': { + overflow: 'hidden', + }, }, }), logListContainer: css({ diff --git a/public/app/features/logs/components/panel/LogListContext.tsx b/public/app/features/logs/components/panel/LogListContext.tsx index 1ca6100a1d1..d27fe27d56c 100644 --- a/public/app/features/logs/components/panel/LogListContext.tsx +++ b/public/app/features/logs/components/panel/LogListContext.tsx @@ -26,6 +26,7 @@ import { PopoverContent } from '@grafana/ui'; import { DownloadFormat, checkLogsError, checkLogsSampled, downloadLogs as download } from '../../utils'; +import { LogLineDetailsMode } from './LogLineDetails'; import { GetRowContextQueryFn, LogLineMenuCustomItem } from './LogLineMenu'; import { LogListFontSize } from './LogList'; import { LogListModel } from './processing'; @@ -34,6 +35,7 @@ import { LOG_LIST_MIN_WIDTH } from './virtualization'; export interface LogListContextData extends Omit<Props, 'containerElement' | 'logs' | 'logsMeta' | 'showControls'> { closeDetails: () => void; detailsDisplayed: (log: LogListModel) => boolean; + detailsMode: LogLineDetailsMode; detailsWidth: number; downloadLogs: (format: DownloadFormat) => void; enableLogDetails: boolean; @@ -43,6 +45,7 @@ export interface LogListContextData extends Omit<Props, 'containerElement' | 'lo hasUnescapedContent?: boolean; logLineMenuCustomItems?: LogLineMenuCustomItem[]; setDedupStrategy: (dedupStrategy: LogsDedupStrategy) => void; + setDetailsMode: (mode: LogLineDetailsMode) => void; setDetailsWidth: (width: number) => void; setFilterLevels: (filterLevels: LogLevel[]) => void; setFontSize: (size: LogListFontSize) => void; @@ -64,6 +67,7 @@ export const LogListContext = createContext<LogListContextData>({ closeDetails: () => {}, dedupStrategy: LogsDedupStrategy.none, detailsDisplayed: () => false, + detailsMode: 'sidebar', detailsWidth: 0, displayedFields: [], downloadLogs: () => {}, @@ -72,6 +76,7 @@ export const LogListContext = createContext<LogListContextData>({ fontSize: 'default', hasUnescapedContent: false, setDedupStrategy: () => {}, + setDetailsMode: () => {}, setDetailsWidth: () => {}, setFilterLevels: () => {}, setFontSize: () => {}, @@ -132,6 +137,7 @@ export interface Props { children?: ReactNode; // Only ControlledLogRows can send an undefined containerElement. See LogList.tsx containerElement?: HTMLDivElement; + detailsMode?: LogLineDetailsMode; dedupStrategy: LogsDedupStrategy; displayedFields: string[]; enableLogDetails: boolean; @@ -176,6 +182,7 @@ export const LogListContextProvider = ({ children, containerElement, enableLogDetails, + detailsMode: detailsModeProp, dedupStrategy, displayedFields, filterLevels, @@ -230,6 +237,7 @@ export const LogListContextProvider = ({ }); const [showDetails, setShowDetails] = useState<LogListModel[]>([]); const [detailsWidth, setDetailsWidthState] = useState(getDetailsWidth(containerElement, logOptionsStorageKey)); + const [detailsMode, setDetailsMode] = useState<LogLineDetailsMode>(detailsModeProp ?? 'sidebar'); useEffect(() => { // Props are updated in the context only of the panel is being externally controlled. @@ -480,6 +488,7 @@ export const LogListContextProvider = ({ closeDetails, detailsDisplayed, dedupStrategy: logListState.dedupStrategy, + detailsMode, detailsWidth, displayedFields, downloadLogs, @@ -511,6 +520,7 @@ export const LogListContextProvider = ({ pinnedLogs: logListState.pinnedLogs, prettifyJSON: logListState.prettifyJSON, setDedupStrategy, + setDetailsMode, setDetailsWidth, setDisplayedFields, setFilterLevels, @@ -563,7 +573,9 @@ function getDetailsWidth( const defaultWidth = containerElement.clientWidth * 0.4; const detailsWidth = currentWidth || - (logOptionsStorageKey ? parseInt(store.get(`${logOptionsStorageKey}.detailsWidth`), 10) : defaultWidth); + (logOptionsStorageKey + ? parseInt(store.get(`${logOptionsStorageKey}.detailsWidth`) ?? defaultWidth, 10) + : defaultWidth); const maxWidth = containerElement.clientWidth - LOG_LIST_MIN_WIDTH; diff --git a/public/app/features/logs/components/panel/__mocks__/LogListContext.tsx b/public/app/features/logs/components/panel/__mocks__/LogListContext.tsx index f0cb9be3ce6..1a991f79ecf 100644 --- a/public/app/features/logs/components/panel/__mocks__/LogListContext.tsx +++ b/public/app/features/logs/components/panel/__mocks__/LogListContext.tsx @@ -3,6 +3,7 @@ import { createContext, useContext } from 'react'; import { CoreApp, LogsDedupStrategy, LogsSortOrder } from '@grafana/data'; import { checkLogsError, checkLogsSampled } from 'app/features/logs/utils'; +import { LogLineDetailsMode } from '../LogLineDetails'; import { LogListContextData, Props } from '../LogListContext'; import { LogListModel } from '../processing'; @@ -37,6 +38,10 @@ export const LogListContext = createContext<LogListContextData>({ syntaxHighlighting: true, toggleDetails: () => {}, wrapLogMessage: false, + detailsMode: 'sidebar', + setDetailsMode: function (mode: LogLineDetailsMode): void { + throw new Error('Function not implemented.'); + }, }); export const useLogListContextData = (key: keyof LogListContextData) => { @@ -59,6 +64,8 @@ export const useLogIsPermalinked = (log: LogListModel) => { }; export const defaultValue: LogListContextData = { + detailsMode: 'sidebar', + setDetailsMode: jest.fn(), setDedupStrategy: jest.fn(), setFilterLevels: jest.fn(), setFontSize: jest.fn(), diff --git a/public/app/features/logs/components/panel/virtualization.test.ts b/public/app/features/logs/components/panel/virtualization.test.ts index 75534d4e170..479b7b4a746 100644 --- a/public/app/features/logs/components/panel/virtualization.test.ts +++ b/public/app/features/logs/components/panel/virtualization.test.ts @@ -3,14 +3,17 @@ import { createTheme, LogsSortOrder } from '@grafana/data'; import { LOG_LINE_BODY_FIELD_NAME } from '../LogDetailsBody'; import { createLogLine } from '../mocks/logRow'; +import { LOG_LINE_DETAILS_HEIGHT } from './LogLineDetails'; import { LogListModel, PreProcessOptions } from './processing'; -import { LogLineVirtualization, getLogLineSize, DisplayOptions } from './virtualization'; +import { LogLineVirtualization, getLogLineSize, DisplayOptions, FIELD_GAP_MULTIPLIER } from './virtualization'; describe('Virtualization', () => { let log: LogListModel, container: HTMLDivElement; let virtualization = new LogLineVirtualization(createTheme(), 'default'); + const GAP = virtualization.getGridSize() * FIELD_GAP_MULTIPLIER; + const DETAILS_HEIGHT = window.innerHeight * (LOG_LINE_DETAILS_HEIGHT / 100) + GAP / 2; const PADDING_BOTTOM = 6; const LINE_HEIGHT = virtualization.getLineHeight(); const SINGLE_LINE_HEIGHT = LINE_HEIGHT + PADDING_BOTTOM; @@ -21,8 +24,10 @@ describe('Virtualization', () => { let TWO_LINES_OF_CHARACTERS: number; const defaultOptions: DisplayOptions = { + detailsMode: 'sidebar', wrap: false, showTime: false, + showDetails: [], showDuplicates: false, hasLogsWithErrors: false, hasSampledLogs: false, @@ -50,6 +55,18 @@ describe('Virtualization', () => { expect(size).toBe(SINGLE_LINE_HEIGHT); }); + test('Returns the a single line plus inline details if the display mode is unwrapped', () => { + const size = getLogLineSize( + virtualization, + [log], + container, + [], + { ...defaultOptions, showTime: true, showDetails: [log], detailsMode: 'inline' }, + 0 + ); + expect(size).toBe(SINGLE_LINE_HEIGHT + DETAILS_HEIGHT); + }); + test('Returns the a single line if the line is not loaded yet', () => { const logs = [log]; const size = getLogLineSize( @@ -78,6 +95,21 @@ describe('Virtualization', () => { expect(size).toBe((virtualization.getTruncationLineCount() + 1) * LINE_HEIGHT); }); + test('Returns the size of a truncated long line with inline details', () => { + // Very small container + log.collapsed = true; + jest.spyOn(container, 'clientWidth', 'get').mockReturnValue(10); + const size = getLogLineSize( + virtualization, + [log], + container, + [], + { ...defaultOptions, wrap: true, showTime: true, showDetails: [log], detailsMode: 'inline' }, + 0 + ); + expect(size).toBe((virtualization.getTruncationLineCount() + 1) * LINE_HEIGHT + DETAILS_HEIGHT); + }); + test.each([true, false])('Measures a log line with controls %s and displayed time %s', (showTime: boolean) => { const size = getLogLineSize(virtualization, [log], container, [], { ...defaultOptions, wrap: true, showTime }, 0); expect(size).toBe(SINGLE_LINE_HEIGHT); @@ -115,6 +147,24 @@ describe('Virtualization', () => { expect(size).toBe(THREE_LINES_HEIGHT); }); + test('Measures a multi-line log line with level, controls, displayed time, and inline details', () => { + log = createLogLine( + { labels: { place: 'luna' }, entry: new Array(TWO_LINES_OF_CHARACTERS).fill('e').join('') }, + preProcessOptions + ); + + const size = getLogLineSize( + virtualization, + [log], + container, + [], + { ...defaultOptions, wrap: true, showTime: true, showDetails: [log], detailsMode: 'inline' }, + 0 + ); + // Two lines for the log and one extra for level and time + expect(size).toBe(THREE_LINES_HEIGHT + DETAILS_HEIGHT); + }); + test('Measures a multi-line log line with displayed fields', () => { log = createLogLine( { diff --git a/public/app/features/logs/components/panel/virtualization.ts b/public/app/features/logs/components/panel/virtualization.ts index 2f9b6b6773a..f9e7676a5f5 100644 --- a/public/app/features/logs/components/panel/virtualization.ts +++ b/public/app/features/logs/components/panel/virtualization.ts @@ -2,6 +2,7 @@ import ansicolor from 'ansicolor'; import { BusEventWithPayload, GrafanaTheme2 } from '@grafana/data'; +import { LOG_LINE_DETAILS_HEIGHT, LogLineDetailsMode } from './LogLineDetails'; import { LogListFontSize } from './LogList'; import { LogListModel } from './processing'; @@ -232,8 +233,10 @@ export class LogLineVirtualization { } export interface DisplayOptions { + detailsMode: LogLineDetailsMode; hasLogsWithErrors?: boolean; hasSampledLogs?: boolean; + showDetails: LogListModel[]; showDuplicates: boolean; showTime: boolean; wrap: boolean; @@ -244,20 +247,25 @@ export function getLogLineSize( logs: LogListModel[], container: HTMLDivElement | null, displayedFields: string[], - { hasLogsWithErrors, hasSampledLogs, showDuplicates, showTime, wrap }: DisplayOptions, + { detailsMode, hasLogsWithErrors, hasSampledLogs, showDuplicates, showDetails, showTime, wrap }: DisplayOptions, index: number ) { if (!container) { return 0; } + const gap = virtualization.getGridSize() * FIELD_GAP_MULTIPLIER; + const detailsHeight = + detailsMode === 'inline' && showDetails.findIndex((log) => log.uid === logs[index].uid) >= 0 + ? window.innerHeight * (LOG_LINE_DETAILS_HEIGHT / 100) + gap / 2 + : 0; // !logs[index] means the line is not yet loaded by infinite scrolling if (!wrap || !logs[index]) { - return virtualization.getLineHeight() + virtualization.getPaddingBottom(); + return virtualization.getLineHeight() + virtualization.getPaddingBottom() + detailsHeight; } // If a long line is collapsed, we show the line count + an extra line for the expand/collapse control logs[index].updateCollapsedState(displayedFields, container); if (logs[index].collapsed) { - return (virtualization.getTruncationLineCount() + 1) * virtualization.getLineHeight(); + return (virtualization.getTruncationLineCount() + 1) * virtualization.getLineHeight() + detailsHeight; } const storedSize = virtualization.retrieveLogLineSize(logs[index].uid, container); @@ -266,7 +274,6 @@ export function getLogLineSize( } let textToMeasure = ''; - const gap = virtualization.getGridSize() * FIELD_GAP_MULTIPLIER; const iconsGap = virtualization.getGridSize() * 0.5; let optionsWidth = 0; if (showDuplicates) { @@ -296,7 +303,9 @@ export function getLogLineSize( const { height } = virtualization.measureTextHeight(textToMeasure, getLogContainerWidth(container), optionsWidth); // When the log is collapsed, add an extra line for the expand/collapse control - return logs[index].collapsed === false ? height + virtualization.getLineHeight() : height; + return logs[index].collapsed === false + ? height + virtualization.getLineHeight() + detailsHeight + : height + detailsHeight; } export interface LogFieldDimension { @@ -313,14 +322,28 @@ export function hasUnderOrOverflow( if (collapsed !== undefined && calculatedHeight) { calculatedHeight -= virtualization.getLineHeight(); } + const inlineDetails = element.parentElement + ? Array.from(element.parentElement.children).filter((element) => + element.classList.contains('log-line-inline-details') + ) + : undefined; + const detailsHeight = inlineDetails?.length ? inlineDetails[0].clientHeight : 0; + + // Line overflows container + let measuredHeight = element.scrollHeight + detailsHeight; const height = calculatedHeight ?? element.clientHeight; - if (element.scrollHeight > height) { - return collapsed !== undefined ? element.scrollHeight + virtualization.getLineHeight() : element.scrollHeight; + if (measuredHeight > height) { + return collapsed !== undefined ? measuredHeight + virtualization.getLineHeight() : measuredHeight; } + + // Line is smaller than container const child = element.children[1]; - if (child instanceof HTMLDivElement && child.clientHeight < height) { - return collapsed !== undefined ? child.clientHeight + virtualization.getLineHeight() : child.clientHeight; + measuredHeight = child.clientHeight + detailsHeight; + if (child instanceof HTMLDivElement && measuredHeight < height) { + return collapsed !== undefined ? measuredHeight + virtualization.getLineHeight() : measuredHeight; } + + // No overflow or undermeasurement return null; } diff --git a/public/app/features/manage-dashboards/DashboardImportPage.tsx b/public/app/features/manage-dashboards/DashboardImportPage.tsx index cf23c94f73e..4652a4811bd 100644 --- a/public/app/features/manage-dashboards/DashboardImportPage.tsx +++ b/public/app/features/manage-dashboards/DashboardImportPage.tsx @@ -28,7 +28,7 @@ import { Form } from 'app/core/components/Form/Form'; import { Page } from 'app/core/components/Page/Page'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; import { dispatch } from 'app/store/store'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { cleanUpAction } from '../../core/actions/cleanUp'; import { ImportDashboardOverviewV2 } from '../dashboard-scene/v2schema/ImportDashboardOverviewV2'; diff --git a/public/app/features/manage-dashboards/components/ImportDashboardOverview.tsx b/public/app/features/manage-dashboards/components/ImportDashboardOverview.tsx index 314954ca16c..66508d4b07f 100644 --- a/public/app/features/manage-dashboards/components/ImportDashboardOverview.tsx +++ b/public/app/features/manage-dashboards/components/ImportDashboardOverview.tsx @@ -6,7 +6,7 @@ import { Trans } from '@grafana/i18n'; import { locationService, reportInteraction } from '@grafana/runtime'; import { Box, Legend, TextLink } from '@grafana/ui'; import { Form } from 'app/core/components/Form/Form'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { clearLoadedDashboard, importDashboard } from '../state/actions'; import { DashboardSource, ImportDashboardDTO } from '../state/reducers'; diff --git a/public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.tsx b/public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.tsx index 79676bc4a19..282227e4f31 100644 --- a/public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.tsx +++ b/public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.tsx @@ -27,7 +27,7 @@ import { generatePublicDashboardConfigUrl, generatePublicDashboardUrl, } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PublicDashboardListResponse } from '../../types'; diff --git a/public/app/features/manage-dashboards/components/SnapshotListTableRow.test.tsx b/public/app/features/manage-dashboards/components/SnapshotListTableRow.test.tsx index f6268790dcf..29d062da35d 100644 --- a/public/app/features/manage-dashboards/components/SnapshotListTableRow.test.tsx +++ b/public/app/features/manage-dashboards/components/SnapshotListTableRow.test.tsx @@ -4,7 +4,7 @@ import userEvent from '@testing-library/user-event'; import { contextSrv } from 'app/core/services/context_srv'; import { grantUserPermissions } from 'app/features/alerting/unified/mocks'; import { Snapshot } from 'app/features/dashboard/services/SnapshotSrv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { SnapshotListTableRow } from './SnapshotListTableRow'; diff --git a/public/app/features/manage-dashboards/components/SnapshotListTableRow.tsx b/public/app/features/manage-dashboards/components/SnapshotListTableRow.tsx index 5e0c08b7395..6a217ca63ce 100644 --- a/public/app/features/manage-dashboards/components/SnapshotListTableRow.tsx +++ b/public/app/features/manage-dashboards/components/SnapshotListTableRow.tsx @@ -6,7 +6,7 @@ import { Button, LinkButton, useStyles2 } from '@grafana/ui'; import { SkeletonComponent, attachSkeleton } from '@grafana/ui/unstable'; import { contextSrv } from 'app/core/services/context_srv'; import { Snapshot } from 'app/features/dashboard/services/SnapshotSrv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; export interface Props { snapshot: Snapshot; diff --git a/public/app/features/manage-dashboards/state/actions.ts b/public/app/features/manage-dashboards/state/actions.ts index fad40fbec18..191ec9c2657 100644 --- a/public/app/features/manage-dashboards/state/actions.ts +++ b/public/app/features/manage-dashboards/state/actions.ts @@ -10,7 +10,8 @@ import { notifyApp } from 'app/core/actions'; import { createErrorNotification } from 'app/core/copy/appNotification'; import { browseDashboardsAPI, ImportInputs } from 'app/features/browse-dashboards/api/browseDashboardsAPI'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { PermissionLevelString, SearchQueryType, ThunkResult } from 'app/types'; +import { PermissionLevelString, SearchQueryType } from 'app/types/acl'; +import { ThunkResult } from 'app/types/store'; import { Input, diff --git a/public/app/features/manage-dashboards/utils/validation.test.ts b/public/app/features/manage-dashboards/utils/validation.test.ts index 40d1a8ee2b4..d6fb178bf80 100644 --- a/public/app/features/manage-dashboards/utils/validation.test.ts +++ b/public/app/features/manage-dashboards/utils/validation.test.ts @@ -5,7 +5,7 @@ import { import { AnnoKeyFolder, AnnoKeyFolderTitle } from 'app/features/apiserver/types'; import { setDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; import { DashboardWithAccessInfo } from 'app/features/dashboard/api/types'; -import { DashboardDTO } from 'app/types'; +import { DashboardDTO } from 'app/types/dashboard'; import { validateUid } from './validation'; diff --git a/public/app/features/migrate-to-cloud/api/endpoints.gen.ts b/public/app/features/migrate-to-cloud/api/endpoints.gen.ts index c6a3bae02da..339184f1635 100644 --- a/public/app/features/migrate-to-cloud/api/endpoints.gen.ts +++ b/public/app/features/migrate-to-cloud/api/endpoints.gen.ts @@ -206,6 +206,8 @@ export type CreateSnapshotRequestDto = { }; export type MigrateDataResponseItemDto = { errorCode?: + | 'ALERT_RULES_QUOTA_REACHED' + | 'ALERT_RULES_GROUP_QUOTA_REACHED' | 'DATASOURCE_NAME_CONFLICT' | 'DATASOURCE_INVALID_URL' | 'DATASOURCE_ALREADY_MANAGED' diff --git a/public/app/features/migrate-to-cloud/onprem/ResourceDetailsModal.tsx b/public/app/features/migrate-to-cloud/onprem/ResourceDetailsModal.tsx index a47efe48d43..63c194fbf73 100644 --- a/public/app/features/migrate-to-cloud/onprem/ResourceDetailsModal.tsx +++ b/public/app/features/migrate-to-cloud/onprem/ResourceDetailsModal.tsx @@ -13,6 +13,16 @@ interface ResourceDetailsModalProps { function getTMessage(errorCode: MigrateDataResponseItemDto['errorCode']): string { switch (errorCode) { + case 'ALERT_RULES_QUOTA_REACHED': + return t( + 'migrate-to-cloud.resource-details.error-messages.alert-rules-quota-reached', + 'Maximum number of alert rules reached: Delete some alert rules or upgrade your plan and try again.' + ); + case 'ALERT_RULES_GROUP_QUOTA_REACHED': + return t( + 'migrate-to-cloud.resource-details.error-messages.alert-rules-group-quota-reached', + 'Maximum number of alert rule groups reached: Delete some alert rule groups or upgrade your plan and try again.' + ); case 'DATASOURCE_NAME_CONFLICT': return t( 'migrate-to-cloud.resource-details.error-messages.datasource-name-conflict', @@ -106,9 +116,11 @@ export function ResourceDetailsModal(props: ResourceDetailsModalProps) { <> <Text element="p">{msgTitle}</Text> <Text element="p"> - {getTMessage(resource?.errorCode) || - resource?.message || - 'There has been an error while migrating. Please check the cloud migration logs for more information.'} + {getTMessage(resource?.errorCode) || resource?.message || ( + <Trans i18nKey="migrate-to-cloud.resource-details.error-messages.generic-error"> + There has been an error while migrating. Please check the cloud migration logs for more information. + </Trans> + )} </Text> </> ) : ( diff --git a/public/app/features/notifications/StoredNotifications.tsx b/public/app/features/notifications/StoredNotifications.tsx index 5443458036e..b5db2d1327a 100644 --- a/public/app/features/notifications/StoredNotifications.tsx +++ b/public/app/features/notifications/StoredNotifications.tsx @@ -14,7 +14,7 @@ import { selectWarningsAndErrors, selectLastReadTimestamp, } from 'app/core/reducers/appNotification'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; export function StoredNotifications() { const dispatch = useDispatch(); diff --git a/public/app/features/org/OrgDetailsPage.test.tsx b/public/app/features/org/OrgDetailsPage.test.tsx index 0fc7ab9e728..c71bfd1eff8 100644 --- a/public/app/features/org/OrgDetailsPage.test.tsx +++ b/public/app/features/org/OrgDetailsPage.test.tsx @@ -4,9 +4,9 @@ import { mockToolkitActionCreator } from 'test/core/redux/mocks'; import { TestProvider } from 'test/helpers/TestProvider'; import { NavModel } from '@grafana/data'; +import { Organization } from 'app/types/organization'; import { backendSrv } from '../../core/services/backend_srv'; -import { Organization } from '../../types'; import { OrgDetailsPage, Props } from './OrgDetailsPage'; import { setOrganizationName } from './state/reducers'; diff --git a/public/app/features/org/OrgDetailsPage.tsx b/public/app/features/org/OrgDetailsPage.tsx index d97faf6636b..bffc18ef3c7 100644 --- a/public/app/features/org/OrgDetailsPage.tsx +++ b/public/app/features/org/OrgDetailsPage.tsx @@ -7,8 +7,9 @@ import { Page } from 'app/core/components/Page/Page'; import SharedPreferences from 'app/core/components/SharedPreferences/SharedPreferences'; import { appEvents, contextSrv } from 'app/core/core'; import { getNavModel } from 'app/core/selectors/navModel'; -import { AccessControlAction, StoreState } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { ShowConfirmModalEvent } from 'app/types/events'; +import { StoreState } from 'app/types/store'; import OrgProfile from './OrgProfile'; import { loadOrganization, updateOrganization } from './state/actions'; diff --git a/public/app/features/org/OrgProfile.tsx b/public/app/features/org/OrgProfile.tsx index 23d56e2d92a..46b5cfa0c9b 100644 --- a/public/app/features/org/OrgProfile.tsx +++ b/public/app/features/org/OrgProfile.tsx @@ -2,7 +2,7 @@ import { Trans, t } from '@grafana/i18n'; import { Input, Field, FieldSet, Button } from '@grafana/ui'; import { Form } from 'app/core/components/Form/Form'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; export interface Props { orgName: string; diff --git a/public/app/features/org/SelectOrgPage.tsx b/public/app/features/org/SelectOrgPage.tsx index f9d93c63e93..3990613cbf8 100644 --- a/public/app/features/org/SelectOrgPage.tsx +++ b/public/app/features/org/SelectOrgPage.tsx @@ -5,7 +5,8 @@ import { Trans } from '@grafana/i18n'; import { config } from '@grafana/runtime'; import { Button, Stack } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; -import { StoreState, UserOrg } from 'app/types'; +import { StoreState } from 'app/types/store'; +import { UserOrg } from 'app/types/user'; import { getUserOrganizations, setUserOrganization } from './state/actions'; diff --git a/public/app/features/org/UserInviteForm.tsx b/public/app/features/org/UserInviteForm.tsx index b4bc4bf67c2..1a0ad769b76 100644 --- a/public/app/features/org/UserInviteForm.tsx +++ b/public/app/features/org/UserInviteForm.tsx @@ -1,6 +1,6 @@ import { Controller } from 'react-hook-form'; -import { locationUtil, SelectableValue } from '@grafana/data'; +import { locationUtil, OrgRole, SelectableValue } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { locationService } from '@grafana/runtime'; import { @@ -18,7 +18,7 @@ import { Stack, } from '@grafana/ui'; import { getConfig } from 'app/core/config'; -import { OrgRole, useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { Form } from '../../core/components/Form/Form'; import { addInvitee } from '../invites/state/actions'; diff --git a/public/app/features/org/state/actions.test.ts b/public/app/features/org/state/actions.test.ts index dedda1a8fb5..b624430697a 100644 --- a/public/app/features/org/state/actions.test.ts +++ b/public/app/features/org/state/actions.test.ts @@ -1,8 +1,8 @@ import { thunkTester } from 'test/core/thunk/thunkTester'; +import { OrgRole } from '@grafana/data'; import { BackendSrv } from '@grafana/runtime'; import { updateConfigurationSubtitle } from 'app/core/actions'; -import { OrgRole } from 'app/types'; import { updateOrganization, setUserOrganization, getUserOrganizations } from './actions'; diff --git a/public/app/features/org/state/actions.ts b/public/app/features/org/state/actions.ts index af1b46f49b0..1d580c5b3ae 100644 --- a/public/app/features/org/state/actions.ts +++ b/public/app/features/org/state/actions.ts @@ -1,6 +1,7 @@ import { getBackendSrv } from '@grafana/runtime'; import { updateConfigurationSubtitle } from 'app/core/actions'; -import { ThunkResult, UserOrg } from 'app/types'; +import { ThunkResult } from 'app/types/store'; +import { UserOrg } from 'app/types/user'; import { organizationLoaded, userOrganizationsLoaded } from './reducers'; diff --git a/public/app/features/org/state/reducers.test.ts b/public/app/features/org/state/reducers.test.ts index b99e2ce762f..6bcc44a6aac 100644 --- a/public/app/features/org/state/reducers.test.ts +++ b/public/app/features/org/state/reducers.test.ts @@ -1,5 +1,7 @@ +import { OrgRole } from '@grafana/data'; +import { OrganizationState } from 'app/types/organization'; + import { reducerTester } from '../../../../test/core/redux/reducerTester'; -import { OrganizationState, OrgRole } from '../../../types'; import { initialState, diff --git a/public/app/features/org/state/reducers.ts b/public/app/features/org/state/reducers.ts index d43850ffb2b..151c8cb40f0 100644 --- a/public/app/features/org/state/reducers.ts +++ b/public/app/features/org/state/reducers.ts @@ -1,6 +1,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { Organization, OrganizationState, UserOrg } from 'app/types'; +import { OrganizationState, Organization } from 'app/types/organization'; +import { UserOrg } from 'app/types/user'; export const initialState: OrganizationState = { organization: {} as Organization, diff --git a/public/app/features/panel/components/PanelDataErrorView.tsx b/public/app/features/panel/components/PanelDataErrorView.tsx index 339a33d84a2..ba2ddcf7f8d 100644 --- a/public/app/features/panel/components/PanelDataErrorView.tsx +++ b/public/app/features/panel/components/PanelDataErrorView.tsx @@ -20,7 +20,7 @@ import { VisualizationSelectPaneTab } from 'app/features/dashboard/components/Pa import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; import { findVizPanelByKey, getVizPanelKeyForPanelId } from 'app/features/dashboard-scene/utils/utils'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { changePanelPlugin } from '../state/actions'; diff --git a/public/app/features/panel/components/PanelPluginError.tsx b/public/app/features/panel/components/PanelPluginError.tsx index d4edf2d1027..39ec1eec5d0 100644 --- a/public/app/features/panel/components/PanelPluginError.tsx +++ b/public/app/features/panel/components/PanelPluginError.tsx @@ -5,7 +5,7 @@ import { PureComponent, ReactNode } from 'react'; import { PanelProps, PanelPlugin, PluginType, PanelPluginMeta } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Alert } from '@grafana/ui'; -import { AppNotificationSeverity } from 'app/types'; +import { AppNotificationSeverity } from 'app/types/appNotifications'; import grafanaIconSvg from 'img/grafana_icon.svg'; interface Props { diff --git a/public/app/features/panel/state/actions.ts b/public/app/features/panel/state/actions.ts index 6bde8fc0480..24d7c2b1a92 100644 --- a/public/app/features/panel/state/actions.ts +++ b/public/app/features/panel/state/actions.ts @@ -4,8 +4,8 @@ import { getLibraryPanel } from 'app/features/library-panels/state/api'; import { LibraryElementDTO } from 'app/features/library-panels/types'; import { getPanelPluginNotFound } from 'app/features/panel/components/PanelPluginError'; import { loadPanelPlugin } from 'app/features/plugins/admin/state/actions'; -import { ThunkResult } from 'app/types'; import { DashboardPanelsChangedEvent, PanelOptionsChangedEvent, PanelQueriesChangedEvent } from 'app/types/events'; +import { ThunkResult } from 'app/types/store'; import { changePanelKey, panelModelAndPluginReady, removePanel } from './reducers'; diff --git a/public/app/features/panel/state/selectors.ts b/public/app/features/panel/state/selectors.ts index 6851c061940..492e73af8e0 100644 --- a/public/app/features/panel/state/selectors.ts +++ b/public/app/features/panel/state/selectors.ts @@ -1,5 +1,5 @@ import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { PanelState } from './reducers'; diff --git a/public/app/features/plugins/admin/components/ConnectionsTab.test.tsx b/public/app/features/plugins/admin/components/ConnectionsTab.test.tsx index 340e455e14b..c7e4bb6cb02 100644 --- a/public/app/features/plugins/admin/components/ConnectionsTab.test.tsx +++ b/public/app/features/plugins/admin/components/ConnectionsTab.test.tsx @@ -5,7 +5,7 @@ import { DataSourceSettings } from '@grafana/data'; import { config } from '@grafana/runtime'; import { ContextSrv, setContextSrv } from 'app/core/services/context_srv'; import { getMockDataSources } from 'app/features/datasources/mocks/dataSourcesMocks'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { datasourcePlugin } from '../mocks/catalogPlugin.mock'; diff --git a/public/app/features/plugins/admin/components/ConnectionsTab.tsx b/public/app/features/plugins/admin/components/ConnectionsTab.tsx index a7b82b35774..70a2a26f900 100644 --- a/public/app/features/plugins/admin/components/ConnectionsTab.tsx +++ b/public/app/features/plugins/admin/components/ConnectionsTab.tsx @@ -8,7 +8,8 @@ import { ViewProps } from 'app/features/datasources/components/DataSourcesList'; import { DataSourcesListCard } from 'app/features/datasources/components/DataSourcesListCard'; import { useLoadDataSources } from 'app/features/datasources/state/hooks'; import { getDataSources } from 'app/features/datasources/state/selectors'; -import { AccessControlAction, useSelector } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { useSelector } from 'app/types/store'; import { CatalogPlugin } from '../types'; diff --git a/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithApp.tsx b/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithApp.tsx index 6e0ab172f3a..f15eefad873 100644 --- a/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithApp.tsx +++ b/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithApp.tsx @@ -5,7 +5,7 @@ import { Trans } from '@grafana/i18n'; import { reportInteraction } from '@grafana/runtime'; import { Button } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { updatePluginSettings } from '../../api'; import { usePluginConfig } from '../../hooks/usePluginConfig'; diff --git a/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.test.tsx b/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.test.tsx index a1b80773d8a..b36b4a936b9 100644 --- a/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.test.tsx +++ b/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.test.tsx @@ -4,7 +4,7 @@ import { TestProvider } from 'test/helpers/TestProvider'; import { PluginSignatureStatus } from '@grafana/data'; import { config } from '@grafana/runtime'; import { ContextSrv, setContextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { CatalogPlugin } from '../../types'; diff --git a/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx b/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx index 13b490c3797..eba64519719 100644 --- a/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx +++ b/public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx @@ -7,7 +7,7 @@ import { config } from '@grafana/runtime'; import { Button } from '@grafana/ui'; import { ROUTES } from 'app/features/connections/constants'; import { addDataSource } from 'app/features/datasources/state/actions'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { isDataSourceEditor } from '../../permissions'; import { CatalogPlugin } from '../../types'; diff --git a/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx b/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx index b4774e0dadd..5e5a61b0365 100644 --- a/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx +++ b/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx @@ -9,7 +9,7 @@ import { Button, ConfirmModal, LinkButton, Stack } from '@grafana/ui'; import appEvents from 'app/core/app_events'; import { useQueryParams } from 'app/core/hooks/useQueryParams'; import { removePluginFromNavTree } from 'app/core/reducers/navBarTree'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { getExternalManageLink, isDisabledAngularPlugin } from '../../helpers'; import { diff --git a/public/app/features/plugins/admin/components/InstallControls/InstallControlsWarning.tsx b/public/app/features/plugins/admin/components/InstallControls/InstallControlsWarning.tsx index 1ccdc6e5311..99a198c1455 100644 --- a/public/app/features/plugins/admin/components/InstallControls/InstallControlsWarning.tsx +++ b/public/app/features/plugins/admin/components/InstallControls/InstallControlsWarning.tsx @@ -6,7 +6,7 @@ import { Trans, t } from '@grafana/i18n'; import { config, featureEnabled } from '@grafana/runtime'; import { LinkButton, useStyles2, Alert, TextLink, Stack } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { getExternalManageLink } from '../../helpers'; import { useIsRemotePluginsAvailable } from '../../state/hooks'; diff --git a/public/app/features/plugins/admin/components/PluginDashboards.tsx b/public/app/features/plugins/admin/components/PluginDashboards.tsx index fafd1b19874..8d5caba5861 100644 --- a/public/app/features/plugins/admin/components/PluginDashboards.tsx +++ b/public/app/features/plugins/admin/components/PluginDashboards.tsx @@ -6,7 +6,7 @@ import { Trans } from '@grafana/i18n'; import { getBackendSrv } from '@grafana/runtime'; import { appEvents } from 'app/core/core'; import DashboardsTable from 'app/features/datasources/components/DashboardsTable'; -import { PluginDashboard } from 'app/types'; +import { PluginDashboard } from 'app/types/plugins'; interface Props { plugin: PluginMeta; diff --git a/public/app/features/plugins/admin/components/PluginDetailsPage.tsx b/public/app/features/plugins/admin/components/PluginDetailsPage.tsx index ef6f56c0559..d5a69de88ec 100644 --- a/public/app/features/plugins/admin/components/PluginDetailsPage.tsx +++ b/public/app/features/plugins/admin/components/PluginDetailsPage.tsx @@ -8,7 +8,7 @@ import { Trans, t } from '@grafana/i18n'; import { config } from '@grafana/runtime'; import { Alert, Box, Stack, TabContent, TextLink, useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; -import { AppNotificationSeverity } from 'app/types'; +import { AppNotificationSeverity } from 'app/types/appNotifications'; import { Loader } from '../components/Loader'; import { PluginDetailsBody } from '../components/PluginDetailsBody'; diff --git a/public/app/features/plugins/admin/helpers.ts b/public/app/features/plugins/admin/helpers.ts index b13716b8ca2..171644b2546 100644 --- a/public/app/features/plugins/admin/helpers.ts +++ b/public/app/features/plugins/admin/helpers.ts @@ -3,7 +3,7 @@ import uFuzzy from '@leeoniya/ufuzzy'; import { PluginSignatureStatus, dateTimeParse, PluginError, PluginType, PluginErrorCode } from '@grafana/data'; import { config, featureEnabled } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { CatalogPlugin, diff --git a/public/app/features/plugins/admin/hooks/usePluginDetailsTabs.tsx b/public/app/features/plugins/admin/hooks/usePluginDetailsTabs.tsx index 26c700658ff..f0eebd3bd0a 100644 --- a/public/app/features/plugins/admin/hooks/usePluginDetailsTabs.tsx +++ b/public/app/features/plugins/admin/hooks/usePluginDetailsTabs.tsx @@ -5,7 +5,7 @@ import { GrafanaPlugin, NavModelItem, PluginIncludeType, PluginType } from '@gra import { t } from '@grafana/i18n'; import { config } from '@grafana/runtime'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { usePluginConfig } from '../hooks/usePluginConfig'; import { CatalogPlugin, PluginTabIds, PluginTabLabels } from '../types'; diff --git a/public/app/features/plugins/admin/pages/Browse.tsx b/public/app/features/plugins/admin/pages/Browse.tsx index 4cc44785f5b..a8b0ee559e7 100644 --- a/public/app/features/plugins/admin/pages/Browse.tsx +++ b/public/app/features/plugins/admin/pages/Browse.tsx @@ -10,7 +10,7 @@ import { Page } from 'app/core/components/Page/Page'; import { getNavModel } from 'app/core/selectors/navModel'; import { AdvisorRedirectNotice } from 'app/features/connections/components/AdvisorRedirectNotice/AdvisorRedirectNotice'; import { ROUTES as CONNECTIONS_ROUTES } from 'app/features/connections/constants'; -import { useSelector } from 'app/types'; +import { useSelector } from 'app/types/store'; import { HorizontalGroup } from '../components/HorizontalGroup'; import { PluginList } from '../components/PluginList'; diff --git a/public/app/features/plugins/admin/permissions.ts b/public/app/features/plugins/admin/permissions.ts index e0b7d752881..4ea5eccdd34 100644 --- a/public/app/features/plugins/admin/permissions.ts +++ b/public/app/features/plugins/admin/permissions.ts @@ -1,6 +1,6 @@ import { config } from 'app/core/config'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; export function isGrafanaAdmin(): boolean { return config.bootData.user.isGrafanaAdmin; diff --git a/public/app/features/plugins/admin/routes.tsx b/public/app/features/plugins/admin/routes.tsx index ab7fb2d13ce..6b85ddc14e7 100644 --- a/public/app/features/plugins/admin/routes.tsx +++ b/public/app/features/plugins/admin/routes.tsx @@ -1,7 +1,7 @@ import { SafeDynamicImport } from 'app/core/components/DynamicImports/SafeDynamicImport'; import { contextSrv } from 'app/core/core'; import { RouteDescriptor } from 'app/core/navigation/types'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PluginAdminRoutes } from './types'; diff --git a/public/app/features/plugins/admin/state/actions.ts b/public/app/features/plugins/admin/state/actions.ts index 6f2c5400cf0..599a588d160 100644 --- a/public/app/features/plugins/admin/state/actions.ts +++ b/public/app/features/plugins/admin/state/actions.ts @@ -5,7 +5,7 @@ import { PanelPlugin, PluginError } from '@grafana/data'; import { config, getBackendSrv, isFetchError } from '@grafana/runtime'; import { Settings } from 'app/core/config'; import { importPanelPlugin } from 'app/features/plugins/importPanelPlugin'; -import { StoreState, ThunkResult } from 'app/types'; +import { StoreState, ThunkResult } from 'app/types/store'; import { invalidatePluginInCache } from '../../loader/cache'; import { diff --git a/public/app/features/plugins/admin/state/hooks.ts b/public/app/features/plugins/admin/state/hooks.ts index 457f2f1d73e..2185ec99465 100644 --- a/public/app/features/plugins/admin/state/hooks.ts +++ b/public/app/features/plugins/admin/state/hooks.ts @@ -1,7 +1,7 @@ import { useEffect, useMemo } from 'react'; import { PluginError, PluginType } from '@grafana/data'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { sortPlugins, Sorters, isPluginUpdatable } from '../helpers'; import { CatalogPlugin, PluginStatus } from '../types'; diff --git a/public/app/features/plugins/admin/types.ts b/public/app/features/plugins/admin/types.ts index 791a6d4eb28..eaedf1766ee 100644 --- a/public/app/features/plugins/admin/types.ts +++ b/public/app/features/plugins/admin/types.ts @@ -9,7 +9,8 @@ import { WithAccessControlMetadata, } from '@grafana/data'; import { IconName } from '@grafana/ui'; -import { StoreState, PluginsState } from 'app/types'; +import { PluginsState } from 'app/types/plugins'; +import { StoreState } from 'app/types/store'; export type PluginTypeCode = 'app' | 'panel' | 'datasource'; diff --git a/public/app/features/plugins/components/AppRootPage.test.tsx b/public/app/features/plugins/components/AppRootPage.test.tsx index bef9ed62306..1b054508724 100644 --- a/public/app/features/plugins/components/AppRootPage.test.tsx +++ b/public/app/features/plugins/components/AppRootPage.test.tsx @@ -15,15 +15,15 @@ import { AddedComponentsRegistry } from '../extensions/registry/AddedComponentsR import { AddedFunctionsRegistry } from '../extensions/registry/AddedFunctionsRegistry'; import { AddedLinksRegistry } from '../extensions/registry/AddedLinksRegistry'; import { ExposedComponentsRegistry } from '../extensions/registry/ExposedComponentsRegistry'; +import { importAppPlugin } from '../pluginLoader'; import { getPluginSettings } from '../pluginSettings'; -import { importAppPlugin } from '../plugin_loader'; import AppRootPage from './AppRootPage'; jest.mock('../pluginSettings', () => ({ getPluginSettings: jest.fn(), })); -jest.mock('../plugin_loader', () => ({ +jest.mock('../pluginLoader', () => ({ importAppPlugin: jest.fn(), })); diff --git a/public/app/features/plugins/components/AppRootPage.tsx b/public/app/features/plugins/components/AppRootPage.tsx index c6cdc47e810..7210f0ff471 100644 --- a/public/app/features/plugins/components/AppRootPage.tsx +++ b/public/app/features/plugins/components/AppRootPage.tsx @@ -32,8 +32,8 @@ import { useExposedComponentsRegistry, useAddedFunctionsRegistry, } from '../extensions/ExtensionRegistriesContext'; +import { importAppPlugin } from '../pluginLoader'; import { getPluginSettings } from '../pluginSettings'; -import { importAppPlugin } from '../plugin_loader'; import { buildPluginSectionNav, pluginsLogger } from '../utils'; import { PluginErrorBoundary } from './PluginErrorBoundary'; diff --git a/public/app/features/plugins/datasource_srv.test.ts b/public/app/features/plugins/datasource_srv.test.ts index 94e714ce35c..9734aaa9b02 100644 --- a/public/app/features/plugins/datasource_srv.test.ts +++ b/public/app/features/plugins/datasource_srv.test.ts @@ -61,7 +61,7 @@ class TestRuntimeDataSource extends RuntimeDataSource { } } -jest.mock('./plugin_loader', () => ({ +jest.mock('./pluginLoader', () => ({ importDataSourcePlugin: (meta: DataSourcePluginMeta) => { return Promise.resolve(new DataSourcePlugin(TestDataSource as any)); }, diff --git a/public/app/features/plugins/datasource_srv.ts b/public/app/features/plugins/datasource_srv.ts index f434681943f..a7d081244c6 100644 --- a/public/app/features/plugins/datasource_srv.ts +++ b/public/app/features/plugins/datasource_srv.ts @@ -29,7 +29,7 @@ import { } from 'app/features/expressions/ExpressionDatasource'; import { ExpressionDatasourceUID } from 'app/features/expressions/types'; -import { importDataSourcePlugin } from './plugin_loader'; +import { importDataSourcePlugin } from './pluginLoader'; export class DatasourceSrv implements DataSourceService { private datasources: Record<string, DataSourceApi> = {}; // UID diff --git a/public/app/features/plugins/importPanelPlugin.ts b/public/app/features/plugins/importPanelPlugin.ts index a8f770acdd5..3afee6fa4c3 100644 --- a/public/app/features/plugins/importPanelPlugin.ts +++ b/public/app/features/plugins/importPanelPlugin.ts @@ -3,7 +3,7 @@ import config from 'app/core/config'; import { getPanelPluginLoadError } from '../panel/components/PanelPluginError'; -import { importPluginModule } from './plugin_loader'; +import { importPluginModule } from './pluginLoader'; const promiseCache: Record<string, Promise<PanelPlugin>> = {}; const panelPluginCache: Record<string, PanelPlugin> = {}; diff --git a/public/app/features/plugins/loader/utils.ts b/public/app/features/plugins/loader/utils.ts index 2407852f6ee..b8986e8ade3 100644 --- a/public/app/features/plugins/loader/utils.ts +++ b/public/app/features/plugins/loader/utils.ts @@ -1,6 +1,6 @@ import { config } from '@grafana/runtime'; -import { sandboxPluginDependencies } from '../sandbox/plugin_dependencies'; +import { sandboxPluginDependencies } from '../sandbox/pluginDependencies'; import { SHARED_DEPENDENCY_PREFIX } from './constants'; import { SystemJS } from './systemjs'; diff --git a/public/app/features/plugins/plugin_loader.test.ts b/public/app/features/plugins/pluginLoader.test.ts similarity index 98% rename from public/app/features/plugins/plugin_loader.test.ts rename to public/app/features/plugins/pluginLoader.test.ts index 8fa6b6901e2..e715f1b9d35 100644 --- a/public/app/features/plugins/plugin_loader.test.ts +++ b/public/app/features/plugins/pluginLoader.test.ts @@ -5,9 +5,9 @@ import * as i18nModule from '@grafana/i18n/internal'; import { server } from './loader/pluginLoader.mock'; import { SystemJS } from './loader/systemjs'; import { SystemJSWithLoaderHooks } from './loader/types'; -import { addTranslationsToI18n } from './plugin_loader'; +import { addTranslationsToI18n } from './pluginLoader'; -describe('plugin_loader', () => { +describe('pluginLoader', () => { describe('addTranslationsToI18n', () => { const systemJSPrototype: SystemJSWithLoaderHooks = SystemJS.constructor.prototype; const originalFetch = systemJSPrototype.fetch; diff --git a/public/app/features/plugins/plugin_loader.ts b/public/app/features/plugins/pluginLoader.ts similarity index 98% rename from public/app/features/plugins/plugin_loader.ts rename to public/app/features/plugins/pluginLoader.ts index a5e642ffe06..15f00ac400f 100644 --- a/public/app/features/plugins/plugin_loader.ts +++ b/public/app/features/plugins/pluginLoader.ts @@ -30,8 +30,8 @@ import { sharedDependenciesMap } from './loader/sharedDependencies'; import { decorateSystemJSFetch, decorateSystemJSResolve, decorateSystemJsOnload } from './loader/systemjsHooks'; import { SystemJSWithLoaderHooks } from './loader/types'; import { buildImportMap, resolveModulePath } from './loader/utils'; -import { importPluginModuleInSandbox } from './sandbox/sandbox_plugin_loader'; -import { shouldLoadPluginInFrontendSandbox } from './sandbox/sandbox_plugin_loader_registry'; +import { importPluginModuleInSandbox } from './sandbox/sandboxPluginLoader'; +import { shouldLoadPluginInFrontendSandbox } from './sandbox/sandboxPluginLoaderRegistry'; import { pluginsLogger } from './utils'; const imports = buildImportMap(sharedDependenciesMap); diff --git a/public/app/features/plugins/pluginPreloader.test.ts b/public/app/features/plugins/pluginPreloader.test.ts index 2aab1cd3dc3..4890184a638 100644 --- a/public/app/features/plugins/pluginPreloader.test.ts +++ b/public/app/features/plugins/pluginPreloader.test.ts @@ -11,8 +11,8 @@ import { import type { AppPluginConfig } from '@grafana/runtime'; import { getPluginSettings } from 'app/features/plugins/pluginSettings'; +import { importAppPlugin } from './pluginLoader'; import { clearPreloadedPluginsCache, preloadPlugins } from './pluginPreloader'; -import { importAppPlugin } from './plugin_loader'; jest.mock('app/core/services/context_srv', () => ({ contextSrv: { @@ -26,7 +26,7 @@ jest.mock('app/features/plugins/pluginSettings', () => ({ getPluginSettings: jest.fn(), })); -jest.mock('./plugin_loader', () => ({ +jest.mock('./pluginLoader', () => ({ importAppPlugin: jest.fn(), })); diff --git a/public/app/features/plugins/pluginPreloader.ts b/public/app/features/plugins/pluginPreloader.ts index b8284584a5c..f1bec151de1 100644 --- a/public/app/features/plugins/pluginPreloader.ts +++ b/public/app/features/plugins/pluginPreloader.ts @@ -7,7 +7,7 @@ import type { AppPluginConfig } from '@grafana/runtime'; import { contextSrv } from 'app/core/services/context_srv'; import { getPluginSettings } from 'app/features/plugins/pluginSettings'; -import { importAppPlugin } from './plugin_loader'; +import { importAppPlugin } from './pluginLoader'; export type PluginPreloadResult = { pluginId: string; diff --git a/public/app/features/plugins/sandbox/code_loader.ts b/public/app/features/plugins/sandbox/codeLoader.ts similarity index 100% rename from public/app/features/plugins/sandbox/code_loader.ts rename to public/app/features/plugins/sandbox/codeLoader.ts diff --git a/public/app/features/plugins/sandbox/distortion_map.ts b/public/app/features/plugins/sandbox/distortions.ts similarity index 99% rename from public/app/features/plugins/sandbox/distortion_map.ts rename to public/app/features/plugins/sandbox/distortions.ts index 902f87afc09..b258f36978e 100644 --- a/public/app/features/plugins/sandbox/distortion_map.ts +++ b/public/app/features/plugins/sandbox/distortions.ts @@ -4,9 +4,9 @@ import { cloneDeep, isFunction } from 'lodash'; import { Monaco } from '@grafana/ui'; -import { loadScriptIntoSandbox } from './code_loader'; +import { loadScriptIntoSandbox } from './codeLoader'; import { forbiddenElements } from './constants'; -import { recursivePatchObjectAsLiveTarget } from './document_sandbox'; +import { recursivePatchObjectAsLiveTarget } from './documentSandbox'; import { SandboxEnvironment, SandboxPluginMeta } from './types'; import { logWarning, unboxRegexesFromMembraneProxy } from './utils'; diff --git a/public/app/features/plugins/sandbox/document_sandbox.ts b/public/app/features/plugins/sandbox/documentSandbox.ts similarity index 100% rename from public/app/features/plugins/sandbox/document_sandbox.ts rename to public/app/features/plugins/sandbox/documentSandbox.ts diff --git a/public/app/features/plugins/sandbox/plugin_dependencies.ts b/public/app/features/plugins/sandbox/pluginDependencies.ts similarity index 100% rename from public/app/features/plugins/sandbox/plugin_dependencies.ts rename to public/app/features/plugins/sandbox/pluginDependencies.ts diff --git a/public/app/features/plugins/sandbox/sandbox_components.tsx b/public/app/features/plugins/sandbox/sandboxComponents.tsx similarity index 100% rename from public/app/features/plugins/sandbox/sandbox_components.tsx rename to public/app/features/plugins/sandbox/sandboxComponents.tsx diff --git a/public/app/features/plugins/sandbox/sandbox_plugin_loader.ts b/public/app/features/plugins/sandbox/sandboxPluginLoader.ts similarity index 97% rename from public/app/features/plugins/sandbox/sandbox_plugin_loader.ts rename to public/app/features/plugins/sandbox/sandboxPluginLoader.ts index 791e791ec3a..5b62216ff63 100644 --- a/public/app/features/plugins/sandbox/sandbox_plugin_loader.ts +++ b/public/app/features/plugins/sandbox/sandboxPluginLoader.ts @@ -5,8 +5,8 @@ import { BootData } from '@grafana/data'; import { config } from '@grafana/runtime'; import { defaultTrustedTypesPolicy } from 'app/core/trustedTypePolicies'; -import { getPluginCode, getPluginLoadData, patchSandboxEnvironmentPrototype } from './code_loader'; -import { getGeneralSandboxDistortionMap, distortLiveApis } from './distortion_map'; +import { getPluginCode, getPluginLoadData, patchSandboxEnvironmentPrototype } from './codeLoader'; +import { getGeneralSandboxDistortionMap, distortLiveApis } from './distortions'; import { getSafeSandboxDomElement, isDomElement, @@ -14,9 +14,9 @@ import { markDomElementStyleAsALiveTarget, patchObjectAsLiveTarget, patchWebAPIs, -} from './document_sandbox'; -import { sandboxPluginDependencies } from './plugin_dependencies'; -import { sandboxPluginComponents } from './sandbox_components'; +} from './documentSandbox'; +import { sandboxPluginDependencies } from './pluginDependencies'; +import { sandboxPluginComponents } from './sandboxComponents'; import { CompartmentDependencyModule, PluginFactoryFunction, SandboxEnvironment, SandboxPluginMeta } from './types'; import { logError, logInfo } from './utils'; diff --git a/public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.test.ts b/public/app/features/plugins/sandbox/sandboxPluginLoaderRegistry.test.ts similarity index 99% rename from public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.test.ts rename to public/app/features/plugins/sandbox/sandboxPluginLoaderRegistry.test.ts index e7164a5a860..a36480579d7 100644 --- a/public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.test.ts +++ b/public/app/features/plugins/sandbox/sandboxPluginLoaderRegistry.test.ts @@ -11,7 +11,7 @@ import { setSandboxEnabledCheck, isPluginFrontendSandboxEnabled, isPluginFrontendSandboxEligible, -} from './sandbox_plugin_loader_registry'; +} from './sandboxPluginLoaderRegistry'; jest.mock('@grafana/runtime', () => ({ config: { diff --git a/public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.ts b/public/app/features/plugins/sandbox/sandboxPluginLoaderRegistry.ts similarity index 100% rename from public/app/features/plugins/sandbox/sandbox_plugin_loader_registry.ts rename to public/app/features/plugins/sandbox/sandboxPluginLoaderRegistry.ts diff --git a/public/app/features/plugins/tests/plugin_loader.test.ts b/public/app/features/plugins/tests/plugin_loader.test.ts index 9f6c2e3739b..860d509bdcd 100644 --- a/public/app/features/plugins/tests/plugin_loader.test.ts +++ b/public/app/features/plugins/tests/plugin_loader.test.ts @@ -11,7 +11,7 @@ import { AppPluginMeta, PluginMetaInfo, PluginType, AppPlugin } from '@grafana/d // Loaded after the `unmock` above import { addedComponentsRegistry, addedLinksRegistry, exposedComponentsRegistry } from '../extensions/registry/setup'; import { SystemJS } from '../loader/systemjs'; -import { importAppPlugin } from '../plugin_loader'; +import { importAppPlugin } from '../pluginLoader'; jest.mock('../extensions/registry/setup'); diff --git a/public/app/features/plugins/utils.ts b/public/app/features/plugins/utils.ts index 845785ce876..9961ee71016 100644 --- a/public/app/features/plugins/utils.ts +++ b/public/app/features/plugins/utils.ts @@ -2,8 +2,8 @@ import { GrafanaPlugin, NavModel, NavModelItem, PanelPluginMeta, PluginType } fr import { createMonitoringLogger } from '@grafana/runtime'; import { importPanelPluginFromMeta } from './importPanelPlugin'; +import { importAppPlugin, importDataSourcePlugin } from './pluginLoader'; import { getPluginSettings } from './pluginSettings'; -import { importAppPlugin, importDataSourcePlugin } from './plugin_loader'; export async function loadPlugin(pluginId: string): Promise<GrafanaPlugin> { const info = await getPluginSettings(pluginId); diff --git a/public/app/features/profile/ChangePasswordForm.tsx b/public/app/features/profile/ChangePasswordForm.tsx index fd7d7e58974..6f4ae223651 100644 --- a/public/app/features/profile/ChangePasswordForm.tsx +++ b/public/app/features/profile/ChangePasswordForm.tsx @@ -9,7 +9,7 @@ import { strongPasswordValidationRegister, } from 'app/core/components/ValidationLabels/ValidationLabels'; import config from 'app/core/config'; -import { UserDTO } from 'app/types'; +import { UserDTO } from 'app/types/user'; import { PasswordField } from '../../core/components/PasswordField/PasswordField'; diff --git a/public/app/features/profile/ChangePasswordPage.tsx b/public/app/features/profile/ChangePasswordPage.tsx index 3b7452cbfc5..0be35c8c0fc 100644 --- a/public/app/features/profile/ChangePasswordPage.tsx +++ b/public/app/features/profile/ChangePasswordPage.tsx @@ -2,7 +2,7 @@ import { connect, ConnectedProps } from 'react-redux'; import { useMount } from 'react-use'; import { Page } from 'app/core/components/Page/Page'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { ChangePasswordForm } from './ChangePasswordForm'; import { changePassword, loadUser } from './state/actions'; diff --git a/public/app/features/profile/UserOrganizations.tsx b/public/app/features/profile/UserOrganizations.tsx index 43638455d41..8f808173438 100644 --- a/public/app/features/profile/UserOrganizations.tsx +++ b/public/app/features/profile/UserOrganizations.tsx @@ -3,7 +3,7 @@ import { PureComponent } from 'react'; import { selectors } from '@grafana/e2e-selectors'; import { Trans, t } from '@grafana/i18n'; import { Button, LoadingPlaceholder, ScrollContainer } from '@grafana/ui'; -import { UserDTO, UserOrg } from 'app/types'; +import { UserDTO, UserOrg } from 'app/types/user'; export interface Props { user: UserDTO | null; diff --git a/public/app/features/profile/UserProfileEditForm.tsx b/public/app/features/profile/UserProfileEditForm.tsx index 3b99618268d..25b8c9a0b2b 100644 --- a/public/app/features/profile/UserProfileEditForm.tsx +++ b/public/app/features/profile/UserProfileEditForm.tsx @@ -3,7 +3,7 @@ import { Trans, t } from '@grafana/i18n'; import { Button, Field, FieldSet, Icon, Input, Tooltip } from '@grafana/ui'; import { Form } from 'app/core/components/Form/Form'; import config from 'app/core/config'; -import { UserDTO } from 'app/types'; +import { UserDTO } from 'app/types/user'; import { ProfileUpdateFields } from './types'; diff --git a/public/app/features/profile/UserProfileEditPage.tsx b/public/app/features/profile/UserProfileEditPage.tsx index c5f84818cb2..1dfa6045e81 100644 --- a/public/app/features/profile/UserProfileEditPage.tsx +++ b/public/app/features/profile/UserProfileEditPage.tsx @@ -6,7 +6,7 @@ import { usePluginComponents } from '@grafana/runtime'; import { Stack } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import SharedPreferences from 'app/core/components/SharedPreferences/SharedPreferences'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import UserOrganizations from './UserOrganizations'; import UserProfileEditForm from './UserProfileEditForm'; diff --git a/public/app/features/profile/UserSessions.tsx b/public/app/features/profile/UserSessions.tsx index 0eac0199b33..375db224fd0 100644 --- a/public/app/features/profile/UserSessions.tsx +++ b/public/app/features/profile/UserSessions.tsx @@ -6,7 +6,7 @@ import { Trans, t } from '@grafana/i18n'; import { Button, Icon, LoadingPlaceholder, ScrollContainer } from '@grafana/ui'; import { TagBadge } from 'app/core/components/TagFilter/TagBadge'; import { formatDate } from 'app/core/internationalization/dates'; -import { UserSession } from 'app/types'; +import { UserSession } from 'app/types/user'; interface Props { sessions: UserSession[]; diff --git a/public/app/features/profile/UserTeams.tsx b/public/app/features/profile/UserTeams.tsx index 65d14160d7b..74b9c1e9aff 100644 --- a/public/app/features/profile/UserTeams.tsx +++ b/public/app/features/profile/UserTeams.tsx @@ -2,7 +2,7 @@ import { PureComponent } from 'react'; import { Trans, t } from '@grafana/i18n'; import { LoadingPlaceholder, ScrollContainer } from '@grafana/ui'; -import { Team } from 'app/types'; +import { Team } from 'app/types/teams'; export interface Props { teams: Team[]; diff --git a/public/app/features/profile/api.ts b/public/app/features/profile/api.ts index bb7e30d6b34..a5ab3247c9e 100644 --- a/public/app/features/profile/api.ts +++ b/public/app/features/profile/api.ts @@ -1,6 +1,6 @@ import { getBackendSrv } from '@grafana/runtime'; - -import { Team, UserDTO, UserOrg, UserSession } from '../../types'; +import { Team } from 'app/types/teams'; +import { UserDTO, UserOrg, UserSession } from 'app/types/user'; import { ChangePasswordFields, ProfileUpdateFields } from './types'; diff --git a/public/app/features/profile/state/actions.ts b/public/app/features/profile/state/actions.ts index e1e5f25600c..c98d764be78 100644 --- a/public/app/features/profile/state/actions.ts +++ b/public/app/features/profile/state/actions.ts @@ -1,6 +1,7 @@ import { config } from '@grafana/runtime'; +import { ThunkResult } from 'app/types/store'; +import { UserOrg } from 'app/types/user'; -import { ThunkResult, UserOrg } from '../../../types'; import { api } from '../api'; import { ChangePasswordFields, ProfileUpdateFields } from '../types'; diff --git a/public/app/features/profile/state/reducers.test.ts b/public/app/features/profile/state/reducers.test.ts index 67ff64f9e56..226b8e94d88 100644 --- a/public/app/features/profile/state/reducers.test.ts +++ b/public/app/features/profile/state/reducers.test.ts @@ -1,5 +1,6 @@ +import { OrgRole } from '@grafana/data'; + import { reducerTester } from '../../../../test/core/redux/reducerTester'; -import { OrgRole } from '../../../types'; import { getMockTeam } from '../../teams/mocks/teamMocks'; import { diff --git a/public/app/features/profile/state/reducers.ts b/public/app/features/profile/state/reducers.ts index f4de9c34f0b..6d1bb9096e6 100644 --- a/public/app/features/profile/state/reducers.ts +++ b/public/app/features/profile/state/reducers.ts @@ -5,7 +5,9 @@ import { dateTimeFormatTimeAgo, setWeekStart, TimeZone } from '@grafana/data'; import { getWeekStart, WeekStart } from '@grafana/ui'; import config from 'app/core/config'; import { contextSrv } from 'app/core/core'; -import { Team, ThunkResult, UserDTO, UserOrg, UserSession } from 'app/types'; +import { ThunkResult } from 'app/types/store'; +import { Team } from 'app/types/teams'; +import { UserDTO, UserOrg, UserSession } from 'app/types/user'; export interface UserState { orgId: number; diff --git a/public/app/features/provisioning/utils/routes.ts b/public/app/features/provisioning/utils/routes.ts index c0e828a66a6..891ecd090d9 100644 --- a/public/app/features/provisioning/utils/routes.ts +++ b/public/app/features/provisioning/utils/routes.ts @@ -1,6 +1,6 @@ import { SafeDynamicImport } from 'app/core/components/DynamicImports/SafeDynamicImport'; import { RouteDescriptor } from 'app/core/navigation/types'; -import { DashboardRoutes } from 'app/types'; +import { DashboardRoutes } from 'app/types/dashboard'; import { checkRequiredFeatures } from '../GettingStarted/features'; import { PROVISIONING_URL, CONNECT_URL, GETTING_STARTED_URL } from '../constants'; diff --git a/public/app/features/query/components/QueryGroup.tsx b/public/app/features/query/components/QueryGroup.tsx index b5275a367e9..8737449101f 100644 --- a/public/app/features/query/components/QueryGroup.tsx +++ b/public/app/features/query/components/QueryGroup.tsx @@ -26,7 +26,7 @@ import { DataSourcePicker } from 'app/features/datasources/components/picker/Dat import { dataSource as expressionDatasource } from 'app/features/expressions/ExpressionDatasource'; import { isSharedDashboardQuery } from 'app/plugins/datasource/dashboard/runSharedRequest'; import { GrafanaQuery } from 'app/plugins/datasource/grafana/types'; -import { QueryGroupOptions } from 'app/types'; +import { QueryGroupOptions } from 'app/types/query'; import { PanelQueryRunner } from '../state/PanelQueryRunner'; import { updateQueries } from '../state/updateQueries'; diff --git a/public/app/features/query/components/QueryGroupOptions.tsx b/public/app/features/query/components/QueryGroupOptions.tsx index b28c4ce7128..2404236e483 100644 --- a/public/app/features/query/components/QueryGroupOptions.tsx +++ b/public/app/features/query/components/QueryGroupOptions.tsx @@ -5,7 +5,7 @@ import { rangeUtil, PanelData, DataSourceApi, GrafanaTheme2 } from '@grafana/dat import { Trans, t } from '@grafana/i18n'; import { Input, InlineSwitch, useStyles2, InlineLabel } from '@grafana/ui'; import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow'; -import { QueryGroupOptions } from 'app/types'; +import { QueryGroupOptions } from 'app/types/query'; interface Props { options: QueryGroupOptions; diff --git a/public/app/features/query/state/DashboardQueryRunner/DashboardQueryRunner.test.ts b/public/app/features/query/state/DashboardQueryRunner/DashboardQueryRunner.test.ts index 3c07c21bf5c..4c0f49aacd9 100644 --- a/public/app/features/query/state/DashboardQueryRunner/DashboardQueryRunner.test.ts +++ b/public/app/features/query/state/DashboardQueryRunner/DashboardQueryRunner.test.ts @@ -12,7 +12,7 @@ import { import { Annotation } from 'app/features/alerting/unified/utils/constants'; import { TimeSrv } from 'app/features/dashboard/services/TimeSrv'; import * as store from 'app/store/store'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { PromAlertingRuleState, PromRulesResponse, PromRuleType } from 'app/types/unified-alerting-dto'; import { silenceConsoleOutput } from '../../../../../test/core/utils/silenceConsoleOutput'; diff --git a/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.ts b/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.ts index 18c001c983c..8610d84f8e1 100644 --- a/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.ts +++ b/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.ts @@ -11,7 +11,7 @@ import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/d import { prometheusRuleType } from 'app/features/alerting/unified/utils/rules'; import { promAlertStateToAlertState } from 'app/features/dashboard-scene/scene/AlertStatesDataLayer'; import { dispatch } from 'app/store/store'; -import { AccessControlAction } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; import { RuleNamespace } from 'app/types/unified-alerting'; import { PromRuleGroupDTO } from 'app/types/unified-alerting-dto'; diff --git a/public/app/features/scopes/tests/utils/render.tsx b/public/app/features/scopes/tests/utils/render.tsx index e4c6993928b..ed126b5b2d7 100644 --- a/public/app/features/scopes/tests/utils/render.tsx +++ b/public/app/features/scopes/tests/utils/render.tsx @@ -8,7 +8,7 @@ import { sceneGraph } from '@grafana/scenes'; import { defaultDashboard } from '@grafana/schema'; import { AppChrome } from 'app/core/components/AppChrome/AppChrome'; import { transformSaveModelToScene } from 'app/features/dashboard-scene/serialization/transformSaveModelToScene'; -import { DashboardDataDTO, DashboardDTO, DashboardMeta } from 'app/types'; +import { DashboardDataDTO, DashboardDTO, DashboardMeta } from 'app/types/dashboard'; import { defaultScopesServices, ScopesContextProvider } from '../../ScopesContextProvider'; diff --git a/public/app/features/search/service/deletedDashboardsCache.ts b/public/app/features/search/service/deletedDashboardsCache.ts index cab6774b97b..7559d00605c 100644 --- a/public/app/features/search/service/deletedDashboardsCache.ts +++ b/public/app/features/search/service/deletedDashboardsCache.ts @@ -1,7 +1,6 @@ import { isResourceList } from 'app/features/apiserver/guards'; import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; - -import { DashboardDataDTO } from '../../../types'; +import { DashboardDataDTO } from 'app/types/dashboard'; import { SearchHit } from './unified'; import { resourceToSearchResult } from './utils'; diff --git a/public/app/features/search/service/sql.ts b/public/app/features/search/service/sql.ts index d8f468ee774..ba0dbc9c894 100644 --- a/public/app/features/search/service/sql.ts +++ b/public/app/features/search/service/sql.ts @@ -2,7 +2,7 @@ import { DataFrame, DataFrameView, FieldType, getDisplayProcessor, SelectableVal import { config } from '@grafana/runtime'; import { TermCount } from 'app/core/components/TagFilter/TagFilter'; import { backendSrv } from 'app/core/services/backend_srv'; -import { PermissionLevelString } from 'app/types'; +import { PermissionLevelString } from 'app/types/acl'; import { DEFAULT_MAX_VALUES, GENERAL_FOLDER_UID, TYPE_KIND_MAP } from '../constants'; import { DashboardSearchHit, DashboardSearchItemType } from '../types'; diff --git a/public/app/features/search/service/types.ts b/public/app/features/search/service/types.ts index cb360ba8deb..3ebda023037 100644 --- a/public/app/features/search/service/types.ts +++ b/public/app/features/search/service/types.ts @@ -1,6 +1,6 @@ import { DataFrameView, SelectableValue } from '@grafana/data'; import { TermCount } from 'app/core/components/TagFilter/TagFilter'; -import { PermissionLevelString } from 'app/types'; +import { PermissionLevelString } from 'app/types/acl'; import { ManagerKind } from '../../apiserver/types'; diff --git a/public/app/features/search/service/utils.ts b/public/app/features/search/service/utils.ts index 94fb1e7d345..981127f6688 100644 --- a/public/app/features/search/service/utils.ts +++ b/public/app/features/search/service/utils.ts @@ -2,8 +2,8 @@ import { DataFrameView, IconName, fuzzySearch } from '@grafana/data'; import { isSharedWithMe } from 'app/features/browse-dashboards/components/utils'; import { DashboardViewItemWithUIItems } from 'app/features/browse-dashboards/types'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; +import { DashboardDataDTO } from 'app/types/dashboard'; -import { DashboardDataDTO } from '../../../types'; import { AnnoKeyFolder, ResourceList } from '../../apiserver/types'; import { DashboardSearchHit, DashboardSearchItemType, DashboardViewItem, DashboardViewItemKind } from '../types'; diff --git a/public/app/features/serviceaccounts/ServiceAccountCreatePage.tsx b/public/app/features/serviceaccounts/ServiceAccountCreatePage.tsx index fb210f4b0c0..b65b380cebf 100644 --- a/public/app/features/serviceaccounts/ServiceAccountCreatePage.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountCreatePage.tsx @@ -1,6 +1,7 @@ import { useCallback, useEffect, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; +import { OrgRole } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { config, getBackendSrv, locationService } from '@grafana/runtime'; import { Button, Input, Field, FieldSet } from '@grafana/ui'; @@ -10,7 +11,8 @@ import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker'; import { fetchRoleOptions, updateUserRoles } from 'app/core/components/RolePicker/api'; import { RolePickerSelect } from 'app/core/components/RolePickerDrawer/RolePickerSelect'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, OrgRole, Role, ServiceAccountCreateApiResponse, ServiceAccountDTO } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; +import { ServiceAccountDTO, ServiceAccountCreateApiResponse } from 'app/types/serviceaccount'; import { OrgRolePicker } from '../admin/OrgRolePicker'; diff --git a/public/app/features/serviceaccounts/ServiceAccountPage.test.tsx b/public/app/features/serviceaccounts/ServiceAccountPage.test.tsx index ee61c2af792..4de16f29479 100644 --- a/public/app/features/serviceaccounts/ServiceAccountPage.test.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountPage.test.tsx @@ -2,7 +2,9 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { TestProvider } from 'test/helpers/TestProvider'; -import { ApiKey, OrgRole, ServiceAccountDTO } from 'app/types'; +import { OrgRole } from '@grafana/data'; +import { ApiKey } from 'app/types/apiKeys'; +import { ServiceAccountDTO } from 'app/types/serviceaccount'; import { ServiceAccountPageUnconnected, Props } from './ServiceAccountPage'; diff --git a/public/app/features/serviceaccounts/ServiceAccountPage.tsx b/public/app/features/serviceaccounts/ServiceAccountPage.tsx index ccc445fae5e..b21f6c9fe6d 100644 --- a/public/app/features/serviceaccounts/ServiceAccountPage.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountPage.tsx @@ -7,7 +7,10 @@ import { Trans, t } from '@grafana/i18n'; import { Button, ConfirmModal, IconButton, Stack } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, ApiKey, ServiceAccountDTO, StoreState } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { ApiKey } from 'app/types/apiKeys'; +import { ServiceAccountDTO } from 'app/types/serviceaccount'; +import { StoreState } from 'app/types/store'; import { ServiceAccountPermissions } from './ServiceAccountPermissions'; import { CreateTokenModal, ServiceAccountToken } from './components/CreateTokenModal'; diff --git a/public/app/features/serviceaccounts/ServiceAccountPermissions.tsx b/public/app/features/serviceaccounts/ServiceAccountPermissions.tsx index e6f3adc78b3..303dfc79716 100644 --- a/public/app/features/serviceaccounts/ServiceAccountPermissions.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountPermissions.tsx @@ -1,8 +1,8 @@ import { t } from '@grafana/i18n'; import { Permissions } from 'app/core/components/AccessControl'; import { contextSrv } from 'app/core/services/context_srv'; - -import { AccessControlAction, ServiceAccountDTO } from '../../types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { ServiceAccountDTO } from 'app/types/serviceaccount'; type ServiceAccountPermissionsProps = { serviceAccount: ServiceAccountDTO; diff --git a/public/app/features/serviceaccounts/ServiceAccountTable.tsx b/public/app/features/serviceaccounts/ServiceAccountTable.tsx index 648cb391fb8..8d7363fa37f 100644 --- a/public/app/features/serviceaccounts/ServiceAccountTable.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountTable.tsx @@ -1,6 +1,7 @@ import { useMemo } from 'react'; import Skeleton from 'react-loading-skeleton'; +import { OrgRole } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Avatar, @@ -16,7 +17,8 @@ import { } from '@grafana/ui'; import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, OrgRole, Role, ServiceAccountDTO } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; +import { ServiceAccountDTO } from 'app/types/serviceaccount'; import { OrgRolePicker } from '../admin/OrgRolePicker'; diff --git a/public/app/features/serviceaccounts/ServiceAccountsListPage.test.tsx b/public/app/features/serviceaccounts/ServiceAccountsListPage.test.tsx index f5f563321af..d4b870c2921 100644 --- a/public/app/features/serviceaccounts/ServiceAccountsListPage.test.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountsListPage.test.tsx @@ -2,7 +2,8 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { TestProvider } from 'test/helpers/TestProvider'; -import { OrgRole, ServiceAccountDTO, ServiceAccountStateFilter } from 'app/types'; +import { OrgRole } from '@grafana/data'; +import { ServiceAccountStateFilter, ServiceAccountDTO } from 'app/types/serviceaccount'; import { Props, ServiceAccountsListPageUnconnected } from './ServiceAccountsListPage'; diff --git a/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx b/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx index ff6218e43e4..9929f0dfe91 100644 --- a/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx @@ -19,7 +19,9 @@ import { import { Page } from 'app/core/components/Page/Page'; import config from 'app/core/config'; import { contextSrv } from 'app/core/core'; -import { StoreState, ServiceAccountDTO, AccessControlAction, ServiceAccountStateFilter } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { ServiceAccountStateFilter, ServiceAccountDTO } from 'app/types/serviceaccount'; +import { StoreState } from 'app/types/store'; import { ServiceAccountTable } from './ServiceAccountTable'; import { CreateTokenModal, ServiceAccountToken } from './components/CreateTokenModal'; diff --git a/public/app/features/serviceaccounts/components/ServiceAccountProfile.tsx b/public/app/features/serviceaccounts/components/ServiceAccountProfile.tsx index 9e52f25df92..563d0d8b89d 100644 --- a/public/app/features/serviceaccounts/components/ServiceAccountProfile.tsx +++ b/public/app/features/serviceaccounts/components/ServiceAccountProfile.tsx @@ -6,7 +6,8 @@ import { Trans, t } from '@grafana/i18n'; import { Label, TextLink, useStyles2 } from '@grafana/ui'; import { fetchRoleOptions } from 'app/core/components/RolePicker/api'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, Role, ServiceAccountDTO } from 'app/types'; +import { AccessControlAction, Role } from 'app/types/accessControl'; +import { ServiceAccountDTO } from 'app/types/serviceaccount'; import { ServiceAccountProfileRow } from './ServiceAccountProfileRow'; import { ServiceAccountRoleRow } from './ServiceAccountRoleRow'; diff --git a/public/app/features/serviceaccounts/components/ServiceAccountRoleRow.tsx b/public/app/features/serviceaccounts/components/ServiceAccountRoleRow.tsx index 015fd003b33..33a33229b87 100644 --- a/public/app/features/serviceaccounts/components/ServiceAccountRoleRow.tsx +++ b/public/app/features/serviceaccounts/components/ServiceAccountRoleRow.tsx @@ -1,9 +1,11 @@ +import { OrgRole } from '@grafana/data'; import { t } from '@grafana/i18n'; import { Label } from '@grafana/ui'; import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker'; import { contextSrv } from 'app/core/core'; import { OrgRolePicker } from 'app/features/admin/OrgRolePicker'; -import { AccessControlAction, OrgRole, Role, ServiceAccountDTO } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; +import { ServiceAccountDTO } from 'app/types/serviceaccount'; interface Props { label: string; diff --git a/public/app/features/serviceaccounts/components/ServiceAccountTokensTable.tsx b/public/app/features/serviceaccounts/components/ServiceAccountTokensTable.tsx index 4c065d0d1df..66b2e818efd 100644 --- a/public/app/features/serviceaccounts/components/ServiceAccountTokensTable.tsx +++ b/public/app/features/serviceaccounts/components/ServiceAccountTokensTable.tsx @@ -3,7 +3,7 @@ import { css, cx } from '@emotion/css'; import { dateTimeFormat, GrafanaTheme2, TimeZone } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { DeleteButton, Icon, Tooltip, useStyles2, useTheme2 } from '@grafana/ui'; -import { ApiKey } from 'app/types'; +import { ApiKey } from 'app/types/apiKeys'; interface Props { tokens: ApiKey[]; diff --git a/public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx b/public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx index e9a2478557b..9bf659f1500 100644 --- a/public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx +++ b/public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx @@ -9,7 +9,8 @@ import { SkeletonComponent, attachSkeleton } from '@grafana/ui/unstable'; import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker'; import { contextSrv } from 'app/core/core'; import { OrgRolePicker } from 'app/features/admin/OrgRolePicker'; -import { AccessControlAction, Role, ServiceAccountDTO } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; +import { ServiceAccountDTO } from 'app/types/serviceaccount'; type ServiceAccountListItemProps = { serviceAccount: ServiceAccountDTO; diff --git a/public/app/features/serviceaccounts/state/actions.ts b/public/app/features/serviceaccounts/state/actions.ts index 06591867aa4..5e75bc5378f 100644 --- a/public/app/features/serviceaccounts/state/actions.ts +++ b/public/app/features/serviceaccounts/state/actions.ts @@ -3,7 +3,9 @@ import { debounce } from 'lodash'; import { getBackendSrv } from '@grafana/runtime'; import { fetchRoleOptions } from 'app/core/components/RolePicker/api'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction, ServiceAccountDTO, ServiceAccountStateFilter, ThunkResult } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { ServiceAccountDTO, ServiceAccountStateFilter } from 'app/types/serviceaccount'; +import { ThunkResult } from 'app/types/store'; import { ServiceAccountToken } from '../components/CreateTokenModal'; diff --git a/public/app/features/serviceaccounts/state/actionsServiceAccountPage.ts b/public/app/features/serviceaccounts/state/actionsServiceAccountPage.ts index 4644d3ae136..0921d2e28c4 100644 --- a/public/app/features/serviceaccounts/state/actionsServiceAccountPage.ts +++ b/public/app/features/serviceaccounts/state/actionsServiceAccountPage.ts @@ -1,6 +1,7 @@ import { getBackendSrv, locationService } from '@grafana/runtime'; import { accessControlQueryParam } from 'app/core/utils/accessControl'; -import { ServiceAccountDTO, ThunkResult } from 'app/types'; +import { ServiceAccountDTO } from 'app/types/serviceaccount'; +import { ThunkResult } from 'app/types/store'; import { ServiceAccountToken } from '../components/CreateTokenModal'; diff --git a/public/app/features/serviceaccounts/state/reducers.ts b/public/app/features/serviceaccounts/state/reducers.ts index 5794233d434..705c07c4287 100644 --- a/public/app/features/serviceaccounts/state/reducers.ts +++ b/public/app/features/serviceaccounts/state/reducers.ts @@ -1,13 +1,13 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { Role } from 'app/types/accessControl'; +import { ApiKey } from 'app/types/apiKeys'; import { - ApiKey, - Role, - ServiceAccountDTO, ServiceAccountProfileState, + ServiceAccountDTO, ServiceAccountsState, ServiceAccountStateFilter, -} from 'app/types'; +} from 'app/types/serviceaccount'; // serviceAccountsProfilePage export const initialStateProfile: ServiceAccountProfileState = { diff --git a/public/app/features/support-bundles/SupportBundles.tsx b/public/app/features/support-bundles/SupportBundles.tsx index 2963dad4d0f..b21604caae0 100644 --- a/public/app/features/support-bundles/SupportBundles.tsx +++ b/public/app/features/support-bundles/SupportBundles.tsx @@ -6,7 +6,8 @@ import { Trans, t } from '@grafana/i18n'; import { LinkButton, Spinner, IconButton } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, StoreState } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { StoreState } from 'app/types/store'; import { loadBundles, removeBundle, checkBundles } from './state/actions'; diff --git a/public/app/features/support-bundles/SupportBundlesCreate.tsx b/public/app/features/support-bundles/SupportBundlesCreate.tsx index 1d916884cb8..4461870556a 100644 --- a/public/app/features/support-bundles/SupportBundlesCreate.tsx +++ b/public/app/features/support-bundles/SupportBundlesCreate.tsx @@ -5,7 +5,7 @@ import { Trans, t } from '@grafana/i18n'; import { Button, Field, Checkbox, LinkButton, Stack, Alert } from '@grafana/ui'; import { Form } from 'app/core/components/Form/Form'; import { Page } from 'app/core/components/Page/Page'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { loadSupportBundleCollectors, createSupportBundle } from './state/actions'; diff --git a/public/app/features/support-bundles/state/actions.ts b/public/app/features/support-bundles/state/actions.ts index f42babe81ec..d3270e1a5da 100644 --- a/public/app/features/support-bundles/state/actions.ts +++ b/public/app/features/support-bundles/state/actions.ts @@ -1,7 +1,8 @@ import { throttle } from 'lodash'; import { getBackendSrv, locationService } from '@grafana/runtime'; -import { SupportBundle, SupportBundleCollector, SupportBundleCreateRequest, ThunkResult } from 'app/types'; +import { ThunkResult } from 'app/types/store'; +import { SupportBundle, SupportBundleCollector, SupportBundleCreateRequest } from 'app/types/supportBundles'; import { collectorsFetchBegin, diff --git a/public/app/features/support-bundles/state/reducers.ts b/public/app/features/support-bundles/state/reducers.ts index 21e32402ec0..81a1e0d5e80 100644 --- a/public/app/features/support-bundles/state/reducers.ts +++ b/public/app/features/support-bundles/state/reducers.ts @@ -1,6 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { SupportBundle, SupportBundleCollector, SupportBundlesState } from 'app/types'; +import { SupportBundlesState, SupportBundle, SupportBundleCollector } from 'app/types/supportBundles'; export const initialState: SupportBundlesState = { supportBundles: [], diff --git a/public/app/features/teams/CreateTeam.tsx b/public/app/features/teams/CreateTeam.tsx index c52a71e4bcb..0744271c048 100644 --- a/public/app/features/teams/CreateTeam.tsx +++ b/public/app/features/teams/CreateTeam.tsx @@ -10,7 +10,8 @@ import { TeamRolePicker } from 'app/core/components/RolePicker/TeamRolePicker'; import { updateTeamRoles } from 'app/core/components/RolePicker/api'; import { useRoleOptions } from 'app/core/components/RolePicker/hooks'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, Role, TeamDTO } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; +import { TeamDTO } from 'app/types/teams'; const pageNav: NavModelItem = { icon: 'users-alt', diff --git a/public/app/features/teams/TeamGroupSync.test.tsx b/public/app/features/teams/TeamGroupSync.test.tsx index 841a85b5d4b..bda03e89d5d 100644 --- a/public/app/features/teams/TeamGroupSync.test.tsx +++ b/public/app/features/teams/TeamGroupSync.test.tsx @@ -1,7 +1,7 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { TeamGroup } from '../../types'; +import { TeamGroup } from 'app/types/teams'; import { Props, TeamGroupSync } from './TeamGroupSync'; import { getMockTeamGroups } from './mocks/teamMocks'; diff --git a/public/app/features/teams/TeamGroupSync.tsx b/public/app/features/teams/TeamGroupSync.tsx index e45c525144f..e87a1d4380f 100644 --- a/public/app/features/teams/TeamGroupSync.tsx +++ b/public/app/features/teams/TeamGroupSync.tsx @@ -9,8 +9,8 @@ import { CloseButton } from 'app/core/components/CloseButton/CloseButton'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import { UpgradeBox, UpgradeContent, UpgradeContentProps } from 'app/core/components/Upgrade/UpgradeBox'; import { highlightTrial } from 'app/features/admin/utils'; - -import { StoreState, TeamGroup } from '../../types'; +import { StoreState } from 'app/types/store'; +import { TeamGroup } from 'app/types/teams'; import { addTeamGroup, loadTeamGroups, removeTeamGroup } from './state/actions'; import { getTeamGroups } from './state/selectors'; diff --git a/public/app/features/teams/TeamList.test.tsx b/public/app/features/teams/TeamList.test.tsx index 4826c2bc24f..a5f8adc3f6e 100644 --- a/public/app/features/teams/TeamList.test.tsx +++ b/public/app/features/teams/TeamList.test.tsx @@ -3,8 +3,7 @@ import userEvent from '@testing-library/user-event'; import { TestProvider } from 'test/helpers/TestProvider'; import { contextSrv } from 'app/core/services/context_srv'; - -import { Team } from '../../types'; +import { Team } from 'app/types/teams'; import { Props, TeamList } from './TeamList'; import { getMockTeam, getMultipleMockTeams } from './mocks/teamMocks'; diff --git a/public/app/features/teams/TeamList.tsx b/public/app/features/teams/TeamList.tsx index dd93bd941e7..b1a5952eca8 100644 --- a/public/app/features/teams/TeamList.tsx +++ b/public/app/features/teams/TeamList.tsx @@ -24,7 +24,9 @@ import { import { Page } from 'app/core/components/Page/Page'; import { fetchRoleOptions } from 'app/core/components/RolePicker/api'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction, Role, StoreState, TeamWithRoles } from 'app/types'; +import { Role, AccessControlAction } from 'app/types/accessControl'; +import { StoreState } from 'app/types/store'; +import { TeamWithRoles } from 'app/types/teams'; import { TeamRolePicker } from '../../core/components/RolePicker/TeamRolePicker'; import { EnterpriseAuthFeaturesCard } from '../admin/EnterpriseAuthFeaturesCard'; diff --git a/public/app/features/teams/TeamPages.tsx b/public/app/features/teams/TeamPages.tsx index 940f6950d1a..89a5cb5e032 100644 --- a/public/app/features/teams/TeamPages.tsx +++ b/public/app/features/teams/TeamPages.tsx @@ -9,7 +9,8 @@ import { UpgradeBox } from 'app/core/components/Upgrade/UpgradeBox'; import config from 'app/core/config'; import { getNavModel } from 'app/core/selectors/navModel'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction, StoreState, useDispatch, useSelector } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { StoreState, useDispatch, useSelector } from 'app/types/store'; import TeamGroupSync, { TeamSyncUpgradeContent } from './TeamGroupSync'; import TeamPermissions from './TeamPermissions'; diff --git a/public/app/features/teams/TeamPermissions.tsx b/public/app/features/teams/TeamPermissions.tsx index 349b2531dab..47823bfcae6 100644 --- a/public/app/features/teams/TeamPermissions.tsx +++ b/public/app/features/teams/TeamPermissions.tsx @@ -1,7 +1,7 @@ import { Permissions } from 'app/core/components/AccessControl'; import { contextSrv } from 'app/core/services/context_srv'; - -import { AccessControlAction, Team } from '../../types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { Team } from 'app/types/teams'; type TeamPermissionsProps = { team: Team; diff --git a/public/app/features/teams/TeamSettings.tsx b/public/app/features/teams/TeamSettings.tsx index fa960f25336..79e9ff95dd9 100644 --- a/public/app/features/teams/TeamSettings.tsx +++ b/public/app/features/teams/TeamSettings.tsx @@ -7,7 +7,8 @@ import { TeamRolePicker } from 'app/core/components/RolePicker/TeamRolePicker'; import { useRoleOptions } from 'app/core/components/RolePicker/hooks'; import { SharedPreferences } from 'app/core/components/SharedPreferences/SharedPreferences'; import { contextSrv } from 'app/core/services/context_srv'; -import { AccessControlAction, Team } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { Team } from 'app/types/teams'; import { updateTeam } from './state/actions'; diff --git a/public/app/features/teams/mocks/teamMocks.ts b/public/app/features/teams/mocks/teamMocks.ts index 3da74f056f1..d6472499cb2 100644 --- a/public/app/features/teams/mocks/teamMocks.ts +++ b/public/app/features/teams/mocks/teamMocks.ts @@ -1,6 +1,7 @@ import { randomBytes } from 'crypto'; -import { Team, TeamGroup, TeamMember, TeamPermissionLevel } from 'app/types'; +import { TeamPermissionLevel } from 'app/types/acl'; +import { Team, TeamMember, TeamGroup } from 'app/types/teams'; function generateShortUid(): string { return randomBytes(3).toString('hex'); // Generate a short UID diff --git a/public/app/features/teams/state/actions.ts b/public/app/features/teams/state/actions.ts index 967c87ac904..e7a6c5a923a 100644 --- a/public/app/features/teams/state/actions.ts +++ b/public/app/features/teams/state/actions.ts @@ -5,7 +5,9 @@ import { FetchDataArgs } from '@grafana/ui'; import { updateNavIndex } from 'app/core/actions'; import { contextSrv } from 'app/core/core'; import { accessControlQueryParam } from 'app/core/utils/accessControl'; -import { AccessControlAction, TeamWithRoles, TeamMember, ThunkResult, Team } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { ThunkResult } from 'app/types/store'; +import { Team, TeamMember, TeamWithRoles } from 'app/types/teams'; import { buildNavModel } from './navModel'; import { diff --git a/public/app/features/teams/state/navModel.ts b/public/app/features/teams/state/navModel.ts index 74decae3e94..b6267c73d0e 100644 --- a/public/app/features/teams/state/navModel.ts +++ b/public/app/features/teams/state/navModel.ts @@ -5,7 +5,9 @@ import { ProBadge } from 'app/core/components/Upgrade/ProBadge'; import config from 'app/core/config'; import { contextSrv } from 'app/core/services/context_srv'; import { highlightTrial } from 'app/features/admin/utils'; -import { AccessControlAction, Team, TeamPermissionLevel } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { TeamPermissionLevel } from 'app/types/acl'; +import { Team } from 'app/types/teams'; import userProfilePng from 'img/user_profile.png'; const loadingTeam = { diff --git a/public/app/features/teams/state/reducers.test.ts b/public/app/features/teams/state/reducers.test.ts index 483b22700f0..e42e467c6b1 100644 --- a/public/app/features/teams/state/reducers.test.ts +++ b/public/app/features/teams/state/reducers.test.ts @@ -1,5 +1,6 @@ +import { TeamsState, TeamState } from 'app/types/teams'; + import { reducerTester } from '../../../../test/core/redux/reducerTester'; -import { TeamsState, TeamState } from '../../../types'; import { getMockTeam, getMockTeamGroups, getMockTeamMember } from '../mocks/teamMocks'; import { diff --git a/public/app/features/teams/state/reducers.ts b/public/app/features/teams/state/reducers.ts index 4602f33540c..b98c6d21095 100644 --- a/public/app/features/teams/state/reducers.ts +++ b/public/app/features/teams/state/reducers.ts @@ -1,6 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { Team, TeamGroup, TeamMember, TeamsState, TeamState } from 'app/types'; +import { TeamsState, Team, TeamState, TeamMember, TeamGroup } from 'app/types/teams'; export const initialTeamsState: TeamsState = { teams: [], diff --git a/public/app/features/teams/state/selectors.test.ts b/public/app/features/teams/state/selectors.test.ts index 58f4dbbeeef..b1fed3d1ef3 100644 --- a/public/app/features/teams/state/selectors.test.ts +++ b/public/app/features/teams/state/selectors.test.ts @@ -1,4 +1,5 @@ -import { TeamState } from '../../../types'; +import { TeamState } from 'app/types/teams'; + import { getMockTeam } from '../mocks/teamMocks'; import { getTeam } from './selectors'; diff --git a/public/app/features/teams/state/selectors.ts b/public/app/features/teams/state/selectors.ts index ec8e6eddfc4..ec99297158c 100644 --- a/public/app/features/teams/state/selectors.ts +++ b/public/app/features/teams/state/selectors.ts @@ -1,4 +1,4 @@ -import { Team, TeamState } from 'app/types'; +import { Team, TeamState } from 'app/types/teams'; export const getTeamGroups = (state: TeamState) => state.groups; diff --git a/public/app/features/users/UsersActionBar.tsx b/public/app/features/users/UsersActionBar.tsx index 79659a9e54f..18ab669a9f0 100644 --- a/public/app/features/users/UsersActionBar.tsx +++ b/public/app/features/users/UsersActionBar.tsx @@ -5,7 +5,8 @@ import { reportInteraction } from '@grafana/runtime'; import { RadioButtonGroup, LinkButton, FilterInput, InlineField } from '@grafana/ui'; import config from 'app/core/config'; import { contextSrv } from 'app/core/core'; -import { AccessControlAction, StoreState } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { StoreState } from 'app/types/store'; import { selectTotal } from '../invites/state/selectors'; diff --git a/public/app/features/users/UsersListPage.test.tsx b/public/app/features/users/UsersListPage.test.tsx index 4f8f88c3c4a..91dc6767767 100644 --- a/public/app/features/users/UsersListPage.test.tsx +++ b/public/app/features/users/UsersListPage.test.tsx @@ -3,7 +3,7 @@ import { Provider } from 'react-redux'; import { mockToolkitActionCreator } from 'test/core/redux/mocks'; import { configureStore } from 'app/store/configureStore'; -import { Invitee, OrgUser } from 'app/types'; +import { Invitee, OrgUser } from 'app/types/user'; import { Props, UsersListPageUnconnected } from './UsersListPage'; import { pageChanged, sortChanged } from './state/reducers'; diff --git a/public/app/features/users/UsersListPage.tsx b/public/app/features/users/UsersListPage.tsx index e1992a7f46a..b362bf81621 100644 --- a/public/app/features/users/UsersListPage.tsx +++ b/public/app/features/users/UsersListPage.tsx @@ -1,11 +1,12 @@ import { useEffect, useState } from 'react'; import { connect, ConnectedProps } from 'react-redux'; -import { renderMarkdown } from '@grafana/data'; +import { OrgRole, renderMarkdown } from '@grafana/data'; import { Alert } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; -import { OrgUser, OrgRole, StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; +import { OrgUser } from 'app/types/user'; import { OrgUsersTable } from '../admin/Users/OrgUsersTable'; import InviteesTable from '../invites/InviteesTable'; diff --git a/public/app/features/users/mocks/userMocks.ts b/public/app/features/users/mocks/userMocks.ts index 68ce9a4bfba..6c0895f1887 100644 --- a/public/app/features/users/mocks/userMocks.ts +++ b/public/app/features/users/mocks/userMocks.ts @@ -1,4 +1,5 @@ -import { OrgRole, OrgUser } from 'app/types'; +import { OrgRole } from '@grafana/data'; +import { OrgUser } from 'app/types/user'; import { UsersFetchResult, initialState } from '../state/reducers'; diff --git a/public/app/features/users/state/actions.ts b/public/app/features/users/state/actions.ts index 9dbc7672f63..b13bf27e223 100644 --- a/public/app/features/users/state/actions.ts +++ b/public/app/features/users/state/actions.ts @@ -4,9 +4,9 @@ import { getBackendSrv } from '@grafana/runtime'; import { FetchDataArgs } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; import { accessControlQueryParam } from 'app/core/utils/accessControl'; -import { OrgUser } from 'app/types'; - -import { AccessControlAction, ThunkResult } from '../../../types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { ThunkResult } from 'app/types/store'; +import { OrgUser } from 'app/types/user'; import { usersLoaded, diff --git a/public/app/features/users/state/reducers.test.ts b/public/app/features/users/state/reducers.test.ts index 5c76c88ba5e..abfc484300b 100644 --- a/public/app/features/users/state/reducers.test.ts +++ b/public/app/features/users/state/reducers.test.ts @@ -1,5 +1,6 @@ +import { UsersState } from 'app/types/user'; + import { reducerTester } from '../../../../test/core/redux/reducerTester'; -import { UsersState } from '../../../types'; import { getMockUsers, getFetchUsersMock } from '../mocks/userMocks'; import { initialState, searchQueryChanged, usersLoaded, usersReducer } from './reducers'; diff --git a/public/app/features/users/state/reducers.ts b/public/app/features/users/state/reducers.ts index f74fea6ad1d..bb7cc4c8ea0 100644 --- a/public/app/features/users/state/reducers.ts +++ b/public/app/features/users/state/reducers.ts @@ -1,7 +1,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import config from 'app/core/config'; -import { OrgUser, UsersState } from 'app/types'; +import { UsersState, OrgUser } from 'app/types/user'; export const initialState: UsersState = { users: [], diff --git a/public/app/features/users/state/selectors.ts b/public/app/features/users/state/selectors.ts index 2d80444a47d..a2ba378aaf4 100644 --- a/public/app/features/users/state/selectors.ts +++ b/public/app/features/users/state/selectors.ts @@ -1,4 +1,4 @@ -import { UsersState } from 'app/types'; +import { UsersState } from 'app/types/user'; export const getUsers = (state: UsersState) => { const regex = new RegExp(state.searchQuery, 'i'); diff --git a/public/app/features/variables/adhoc/AdHocVariableEditor.tsx b/public/app/features/variables/adhoc/AdHocVariableEditor.tsx index 90e99866827..65745e8337f 100644 --- a/public/app/features/variables/adhoc/AdHocVariableEditor.tsx +++ b/public/app/features/variables/adhoc/AdHocVariableEditor.tsx @@ -3,7 +3,7 @@ import { connect, ConnectedProps } from 'react-redux'; import { AdHocVariableModel, DataSourceInstanceSettings, getDataSourceRef } from '@grafana/data'; import { AdHocVariableForm } from 'app/features/dashboard-scene/settings/variables/components/AdHocVariableForm'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { initialVariableEditorState } from '../editor/reducer'; import { getAdhocVariableEditorState } from '../editor/selectors'; diff --git a/public/app/features/variables/adhoc/actions.ts b/public/app/features/variables/adhoc/actions.ts index 4263bd09d3f..7e57e0d6344 100644 --- a/public/app/features/variables/adhoc/actions.ts +++ b/public/app/features/variables/adhoc/actions.ts @@ -2,7 +2,7 @@ import { cloneDeep } from 'lodash'; import { AdHocVariableFilter, AdHocVariableModel, DataSourceRef } from '@grafana/data'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { StoreState, ThunkResult } from 'app/types'; +import { StoreState, ThunkResult } from 'app/types/store'; import { changeVariableEditorExtended } from '../editor/reducer'; import { isAdHoc } from '../guard'; diff --git a/public/app/features/variables/constant/actions.ts b/public/app/features/variables/constant/actions.ts index 87f78229983..17ba4e9699b 100644 --- a/public/app/features/variables/constant/actions.ts +++ b/public/app/features/variables/constant/actions.ts @@ -1,4 +1,4 @@ -import { ThunkResult } from 'app/types'; +import { ThunkResult } from 'app/types/store'; import { validateVariableSelectionState } from '../state/actions'; import { toKeyedAction } from '../state/keyedVariablesReducer'; diff --git a/public/app/features/variables/custom/CustomVariableEditor.tsx b/public/app/features/variables/custom/CustomVariableEditor.tsx index 7488326cec7..82b783542e2 100644 --- a/public/app/features/variables/custom/CustomVariableEditor.tsx +++ b/public/app/features/variables/custom/CustomVariableEditor.tsx @@ -4,7 +4,7 @@ import { MapDispatchToProps, MapStateToProps } from 'react-redux'; import { CustomVariableModel, VariableWithMultiSupport } from '@grafana/data'; import { connectWithStore } from 'app/core/utils/connectWithReduxStore'; import { CustomVariableForm } from 'app/features/dashboard-scene/settings/variables/components/CustomVariableForm'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; import { OnPropChangeArguments, VariableEditorProps } from '../editor/types'; import { changeVariableMultiValue } from '../state/actions'; diff --git a/public/app/features/variables/custom/actions.ts b/public/app/features/variables/custom/actions.ts index d8751dd56ed..73eff38f5f5 100644 --- a/public/app/features/variables/custom/actions.ts +++ b/public/app/features/variables/custom/actions.ts @@ -1,5 +1,5 @@ import { getTemplateSrv } from '@grafana/runtime'; -import { ThunkResult } from 'app/types'; +import { ThunkResult } from 'app/types/store'; import { validateVariableSelectionState } from '../state/actions'; import { toKeyedAction } from '../state/keyedVariablesReducer'; diff --git a/public/app/features/variables/datasource/DataSourceVariableEditor.tsx b/public/app/features/variables/datasource/DataSourceVariableEditor.tsx index 2f9116d4d7b..256c5ff29fd 100644 --- a/public/app/features/variables/datasource/DataSourceVariableEditor.tsx +++ b/public/app/features/variables/datasource/DataSourceVariableEditor.tsx @@ -3,8 +3,8 @@ import { connect, ConnectedProps } from 'react-redux'; import { DataSourceVariableModel, SelectableValue, VariableWithMultiSupport } from '@grafana/data'; import { DataSourceVariableForm } from 'app/features/dashboard-scene/settings/variables/components/DataSourceVariableForm'; +import { StoreState } from 'app/types/store'; -import { StoreState } from '../../../types'; import { initialVariableEditorState } from '../editor/reducer'; import { getDatasourceVariableEditorState } from '../editor/selectors'; import { OnPropChangeArguments, VariableEditorProps } from '../editor/types'; diff --git a/public/app/features/variables/datasource/actions.ts b/public/app/features/variables/datasource/actions.ts index d2786309f44..8daf15ec8bc 100644 --- a/public/app/features/variables/datasource/actions.ts +++ b/public/app/features/variables/datasource/actions.ts @@ -2,8 +2,8 @@ import { chain } from 'lodash'; import { stringToJsRegex } from '@grafana/data'; import { getTemplateSrv } from '@grafana/runtime'; +import { ThunkResult } from 'app/types/store'; -import { ThunkResult } from '../../../types'; import { getDatasourceSrv } from '../../plugins/datasource_srv'; import { changeVariableEditorExtended } from '../editor/reducer'; import { validateVariableSelectionState } from '../state/actions'; diff --git a/public/app/features/variables/editor/VariableEditorContainer.tsx b/public/app/features/variables/editor/VariableEditorContainer.tsx index f810d4bfc88..07398d88f0b 100644 --- a/public/app/features/variables/editor/VariableEditorContainer.tsx +++ b/public/app/features/variables/editor/VariableEditorContainer.tsx @@ -5,8 +5,8 @@ import { bindActionCreators } from 'redux'; import { locationService } from '@grafana/runtime'; import { Page } from 'app/core/components/Page/Page'; import { SettingsPageProps } from 'app/features/dashboard/components/DashboardSettings/types'; +import { StoreState, ThunkDispatch } from 'app/types/store'; -import { StoreState, ThunkDispatch } from '../../../types'; import { VariablesUnknownTable } from '../inspect/VariablesUnknownTable'; import { toKeyedAction } from '../state/keyedVariablesReducer'; import { getEditorVariables, getVariablesState } from '../state/selectors'; diff --git a/public/app/features/variables/editor/VariableEditorEditor.tsx b/public/app/features/variables/editor/VariableEditorEditor.tsx index 07cc03bac26..3a8e4b88c62 100644 --- a/public/app/features/variables/editor/VariableEditorEditor.tsx +++ b/public/app/features/variables/editor/VariableEditorEditor.tsx @@ -8,8 +8,8 @@ import { selectors } from '@grafana/e2e-selectors'; import { Trans, t } from '@grafana/i18n'; import { locationService } from '@grafana/runtime'; import { Button, HorizontalGroup, Icon, Themeable2, withTheme2 } from '@grafana/ui'; +import { StoreState, ThunkDispatch } from 'app/types/store'; -import { StoreState, ThunkDispatch } from '../../../types'; import { VariableHideSelect } from '../../dashboard-scene/settings/variables/components/VariableHideSelect'; import { VariableLegend } from '../../dashboard-scene/settings/variables/components/VariableLegend'; import { VariableTextAreaField } from '../../dashboard-scene/settings/variables/components/VariableTextAreaField'; diff --git a/public/app/features/variables/editor/actions.ts b/public/app/features/variables/editor/actions.ts index 9f99d411b8a..827a951d56a 100644 --- a/public/app/features/variables/editor/actions.ts +++ b/public/app/features/variables/editor/actions.ts @@ -2,8 +2,8 @@ import { cloneDeep } from 'lodash'; import { TypedVariableModel, VariableType } from '@grafana/data'; import { locationService } from '@grafana/runtime'; +import { ThunkResult } from 'app/types/store'; -import { ThunkResult } from '../../../types'; import { variableAdapters } from '../adapters'; import { initInspect } from '../inspect/reducer'; import { createUsagesNetwork, transformUsagesToNetwork } from '../inspect/utils'; diff --git a/public/app/features/variables/editor/getVariableQueryEditor.tsx b/public/app/features/variables/editor/getVariableQueryEditor.tsx index 2e4177ef10d..ad96e78cca1 100644 --- a/public/app/features/variables/editor/getVariableQueryEditor.tsx +++ b/public/app/features/variables/editor/getVariableQueryEditor.tsx @@ -3,7 +3,7 @@ import { useCallback } from 'react'; import { DataQuery, DataSourceApi, DataSourceJsonData, QueryEditorProps, StandardVariableQuery } from '@grafana/data'; import { getTemplateSrv } from '@grafana/runtime'; -import { importDataSourcePlugin } from '../../plugins/plugin_loader'; +import { importDataSourcePlugin } from '../../plugins/pluginLoader'; import { hasCustomVariableSupport, hasDatasourceVariableSupport, diff --git a/public/app/features/variables/interval/actions.ts b/public/app/features/variables/interval/actions.ts index f583eb7df57..3043da16e0d 100644 --- a/public/app/features/variables/interval/actions.ts +++ b/public/app/features/variables/interval/actions.ts @@ -1,6 +1,6 @@ import { rangeUtil } from '@grafana/data'; +import { ThunkResult } from 'app/types/store'; -import { ThunkResult } from '../../../types'; import { getTimeSrv } from '../../dashboard/services/TimeSrv'; import { getTemplateSrv, TemplateSrv } from '../../templating/template_srv'; import { validateVariableSelectionState } from '../state/actions'; diff --git a/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx b/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx index 7a52df41e12..df8736b4935 100644 --- a/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx +++ b/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx @@ -6,7 +6,7 @@ import { bindActionCreators } from 'redux'; import { LoadingState, VariableOption, VariableWithMultiSupport, VariableWithOptions } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { ClickOutsideWrapper } from '@grafana/ui'; -import { StoreState, ThunkDispatch } from 'app/types'; +import { StoreState, ThunkDispatch } from 'app/types/store'; import { VARIABLE_PREFIX } from '../../constants'; import { isMulti } from '../../guard'; diff --git a/public/app/features/variables/pickers/OptionsPicker/actions.ts b/public/app/features/variables/pickers/OptionsPicker/actions.ts index 43ef1fdec6e..e6049b37187 100644 --- a/public/app/features/variables/pickers/OptionsPicker/actions.ts +++ b/public/app/features/variables/pickers/OptionsPicker/actions.ts @@ -1,7 +1,7 @@ import { debounce, trim } from 'lodash'; import { isEmptyObject, containsSearchFilter, VariableWithOptions, VariableOption } from '@grafana/data'; -import { StoreState, ThunkDispatch, ThunkResult } from 'app/types'; +import { StoreState, ThunkDispatch, ThunkResult } from 'app/types/store'; import { variableAdapters } from '../../adapters'; import { hasOptions } from '../../guard'; diff --git a/public/app/features/variables/query/QueryVariableEditor.tsx b/public/app/features/variables/query/QueryVariableEditor.tsx index a10700237bd..5d6a56bdb5a 100644 --- a/public/app/features/variables/query/QueryVariableEditor.tsx +++ b/public/app/features/variables/query/QueryVariableEditor.tsx @@ -10,8 +10,8 @@ import { VariableSort, } from '@grafana/data'; import { QueryVariableEditorForm } from 'app/features/dashboard-scene/settings/variables/components/QueryVariableForm'; +import { StoreState } from 'app/types/store'; -import { StoreState } from '../../../types'; import { getTimeSrv } from '../../dashboard/services/TimeSrv'; import { initialVariableEditorState } from '../editor/reducer'; import { getQueryVariableEditorState } from '../editor/selectors'; diff --git a/public/app/features/variables/query/VariableQueryRunner.ts b/public/app/features/variables/query/VariableQueryRunner.ts index 2a21c3c1226..aae4819e01a 100644 --- a/public/app/features/variables/query/VariableQueryRunner.ts +++ b/public/app/features/variables/query/VariableQueryRunner.ts @@ -12,9 +12,9 @@ import { QueryVariableModel, ScopedVars, } from '@grafana/data'; +import { StoreState, ThunkDispatch } from 'app/types/store'; import { dispatch, getState } from '../../../store/store'; -import { StoreState, ThunkDispatch } from '../../../types'; import { getTimeSrv } from '../../dashboard/services/TimeSrv'; import { runRequest } from '../../query/state/runRequest'; import { getLastKey, getVariable } from '../state/selectors'; diff --git a/public/app/features/variables/query/actions.test.tsx b/public/app/features/variables/query/actions.test.tsx index 72cfc067092..7a203bd4b77 100644 --- a/public/app/features/variables/query/actions.test.tsx +++ b/public/app/features/variables/query/actions.test.tsx @@ -69,7 +69,7 @@ const mocks: Record<string, any> = { setDataSourceSrv(mocks.dataSourceSrv as DataSourceSrv); -jest.mock('../../plugins/plugin_loader', () => ({ +jest.mock('../../plugins/pluginLoader', () => ({ importDataSourcePlugin: () => mocks.pluginLoader.importDataSourcePlugin(), })); diff --git a/public/app/features/variables/query/actions.ts b/public/app/features/variables/query/actions.ts index fe494c17560..90fff7f6a46 100644 --- a/public/app/features/variables/query/actions.ts +++ b/public/app/features/variables/query/actions.ts @@ -2,8 +2,8 @@ import { Subscription } from 'rxjs'; import { DataSourceRef } from '@grafana/data'; import { getDataSourceSrv, toDataQueryError } from '@grafana/runtime'; +import { ThunkResult } from 'app/types/store'; -import { ThunkResult } from '../../../types'; import { getVariableQueryEditor } from '../editor/getVariableQueryEditor'; import { addVariableEditorError, changeVariableEditorExtended, removeVariableEditorError } from '../editor/reducer'; import { getQueryVariableEditorState } from '../editor/selectors'; diff --git a/public/app/features/variables/query/operators.ts b/public/app/features/variables/query/operators.ts index c4bb25960bb..a119b4ebd97 100644 --- a/public/app/features/variables/query/operators.ts +++ b/public/app/features/variables/query/operators.ts @@ -10,8 +10,8 @@ import { PanelData, QueryVariableModel, } from '@grafana/data'; +import { ThunkDispatch } from 'app/types/store'; -import { ThunkDispatch } from '../../../types'; import { validateVariableSelectionState } from '../state/actions'; import { toKeyedAction } from '../state/keyedVariablesReducer'; import { getTemplatedRegex, toKeyedVariableIdentifier, toVariablePayload } from '../utils'; diff --git a/public/app/features/variables/state/actions.ts b/public/app/features/variables/state/actions.ts index fdbc54bbbba..ffc45b6b939 100644 --- a/public/app/features/variables/state/actions.ts +++ b/public/app/features/variables/state/actions.ts @@ -26,12 +26,13 @@ import { contextSrv } from 'app/core/services/context_srv'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { store } from 'app/store/store'; +import { AppNotification } from 'app/types/appNotifications'; +import { ThunkResult, StoreState } from 'app/types/store'; import { createErrorNotification } from '../../../core/copy/appNotification'; import { appEvents } from '../../../core/core'; import { getBackendSrv } from '../../../core/services/backend_srv'; import { Graph, Node } from '../../../core/utils/dag'; -import { AppNotification, StoreState, ThunkResult } from '../../../types'; import { getDatasourceSrv } from '../../plugins/datasource_srv'; import { getTemplateSrv, TemplateSrv } from '../../templating/template_srv'; import { variableAdapters } from '../adapters'; diff --git a/public/app/features/variables/state/helpers.ts b/public/app/features/variables/state/helpers.ts index 9752d6ecf5a..163c6d7acf9 100644 --- a/public/app/features/variables/state/helpers.ts +++ b/public/app/features/variables/state/helpers.ts @@ -9,8 +9,9 @@ import { } from '@grafana/data'; import { VariableRefresh } from '@grafana/schema'; import { dashboardReducer } from 'app/features/dashboard/state/reducers'; +import { DashboardState } from 'app/types/dashboard'; +import { StoreState } from 'app/types/store'; -import { DashboardState, StoreState } from '../../../types'; import { VariableAdapter } from '../adapters'; import { NEW_VARIABLE_ID } from '../constants'; import { initialVariableModelState } from '../types'; diff --git a/public/app/features/variables/state/onTimeRangeUpdated.test.ts b/public/app/features/variables/state/onTimeRangeUpdated.test.ts index 528db0045ec..efed3f1b5ab 100644 --- a/public/app/features/variables/state/onTimeRangeUpdated.test.ts +++ b/public/app/features/variables/state/onTimeRangeUpdated.test.ts @@ -1,12 +1,12 @@ import { dateTime, TimeRange, VariableRefresh } from '@grafana/data'; import { config, DataSourceSrv } from '@grafana/runtime'; import * as runtime from '@grafana/runtime'; +import { DashboardState } from 'app/types/dashboard'; import { reduxTester } from '../../../../test/core/redux/reduxTester'; import { silenceConsoleOutput } from '../../../../test/core/utils/silenceConsoleOutput'; import { appEvents } from '../../../core/core'; import { notifyApp } from '../../../core/reducers/appNotification'; -import { DashboardState } from '../../../types'; import { DashboardModel } from '../../dashboard/state/DashboardModel'; import { createDashboardModelFixture } from '../../dashboard/state/__fixtures__/dashboardFixtures'; import { TemplateSrv } from '../../templating/template_srv'; diff --git a/public/app/features/variables/state/selectors.ts b/public/app/features/variables/state/selectors.ts index d9334fd17c0..31e14318d87 100644 --- a/public/app/features/variables/state/selectors.ts +++ b/public/app/features/variables/state/selectors.ts @@ -1,9 +1,9 @@ import memoizeOne from 'memoize-one'; import { TypedVariableModel } from '@grafana/data'; +import { StoreState } from 'app/types/store'; import { getState } from '../../../store/store'; -import { StoreState } from '../../../types'; import { toStateKey } from '../utils'; import { getInitialTemplatingState, TemplatingState } from './reducers'; diff --git a/public/app/features/variables/state/templateVarsChangedInUrl.test.ts b/public/app/features/variables/state/templateVarsChangedInUrl.test.ts index 8e6f6432599..5d6828877c7 100644 --- a/public/app/features/variables/state/templateVarsChangedInUrl.test.ts +++ b/public/app/features/variables/state/templateVarsChangedInUrl.test.ts @@ -1,6 +1,7 @@ import { TypedVariableModel } from '@grafana/data'; +import { DashboardState } from 'app/types/dashboard'; +import { StoreState } from 'app/types/store'; -import { DashboardState, StoreState } from '../../../types'; import { PanelModel } from '../../dashboard/state/PanelModel'; import { createDashboardModelFixture } from '../../dashboard/state/__fixtures__/dashboardFixtures'; import { initialState } from '../../dashboard/state/reducers'; diff --git a/public/app/features/variables/textbox/TextBoxVariablePicker.tsx b/public/app/features/variables/textbox/TextBoxVariablePicker.tsx index 260a57d972e..143cc6f128d 100644 --- a/public/app/features/variables/textbox/TextBoxVariablePicker.tsx +++ b/public/app/features/variables/textbox/TextBoxVariablePicker.tsx @@ -3,7 +3,7 @@ import { ChangeEvent, FocusEvent, KeyboardEvent, ReactElement, useCallback, useE import { TextBoxVariableModel, isEmptyObject } from '@grafana/data'; import { t } from '@grafana/i18n'; import { Input } from '@grafana/ui'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { variableAdapters } from '../adapters'; import { VARIABLE_PREFIX } from '../constants'; diff --git a/public/app/features/variables/textbox/actions.ts b/public/app/features/variables/textbox/actions.ts index c80cc3dd271..0e3c249614f 100644 --- a/public/app/features/variables/textbox/actions.ts +++ b/public/app/features/variables/textbox/actions.ts @@ -1,6 +1,6 @@ import { UrlQueryValue } from '@grafana/data'; +import { ThunkResult } from 'app/types/store'; -import { ThunkResult } from '../../../types'; import { variableAdapters } from '../adapters'; import { setOptionFromUrl } from '../state/actions'; import { toKeyedAction } from '../state/keyedVariablesReducer'; diff --git a/public/app/features/variables/utils.ts b/public/app/features/variables/utils.ts index 4ab42c8ec5c..6908bb9ce57 100644 --- a/public/app/features/variables/utils.ts +++ b/public/app/features/variables/utils.ts @@ -12,9 +12,9 @@ import { } from '@grafana/data'; import { getTemplateSrv, locationService } from '@grafana/runtime'; import { safeStringifyValue } from 'app/core/utils/explore'; +import { StoreState } from 'app/types/store'; import { getState } from '../../store/store'; -import { StoreState } from '../../types'; import { TimeSrv } from '../dashboard/services/TimeSrv'; import { variableAdapters } from './adapters'; diff --git a/public/app/plugins/datasource/azuremonitor/module.ts b/public/app/plugins/datasource/azuremonitor/module.ts index bf96a78c1b3..b723a0bd50c 100644 --- a/public/app/plugins/datasource/azuremonitor/module.ts +++ b/public/app/plugins/datasource/azuremonitor/module.ts @@ -10,7 +10,11 @@ import { trackAzureMonitorDashboardLoaded } from './tracking'; import { AzureMonitorQuery, AzureQueryType, ResultFormat } from './types/query'; import { AzureMonitorDataSourceJsonData } from './types/types'; -initPluginTranslations(pluginJson.id); +// don't load plugin translations in test environments +// we don't use them anyway, and top-level await won't work currently in jest +if (process.env.NODE_ENV !== 'test') { + await initPluginTranslations(pluginJson.id); +} export const plugin = new DataSourcePlugin<Datasource, AzureMonitorQuery, AzureMonitorDataSourceJsonData>(Datasource) .setConfigEditor(ConfigEditor) diff --git a/public/app/plugins/datasource/azuremonitor/package.json b/public/app/plugins/datasource/azuremonitor/package.json index 1cdbd9eae7b..2619deb5e98 100644 --- a/public/app/plugins/datasource/azuremonitor/package.json +++ b/public/app/plugins/datasource/azuremonitor/package.json @@ -48,9 +48,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development", + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development", "i18n-extract": "i18next --config locales/i18next-parser.config.cjs" }, "packageManager": "yarn@4.9.2" diff --git a/public/app/plugins/datasource/azuremonitor/webpack.config.ts b/public/app/plugins/datasource/azuremonitor/webpack.config.ts index c831a42f307..875ef0a4893 100644 --- a/public/app/plugins/datasource/azuremonitor/webpack.config.ts +++ b/public/app/plugins/datasource/azuremonitor/webpack.config.ts @@ -1,9 +1,9 @@ import type { Configuration } from 'webpack'; import { merge } from 'webpack-merge'; -import grafanaConfig from '@grafana/plugin-configs/webpack.config'; +import grafanaConfig, { type Env } from '@grafana/plugin-configs/webpack.config.ts'; -const config = async (env: Record<string, unknown>): Promise<Configuration> => { +const config = async (env: Env): Promise<Configuration> => { const baseConfig = await grafanaConfig(env); return merge(baseConfig, { diff --git a/public/app/plugins/datasource/cloud-monitoring/package.json b/public/app/plugins/datasource/cloud-monitoring/package.json index dcbf4c251d7..f476c47156c 100644 --- a/public/app/plugins/datasource/cloud-monitoring/package.json +++ b/public/app/plugins/datasource/cloud-monitoring/package.json @@ -6,7 +6,7 @@ "dependencies": { "@emotion/css": "11.13.5", "@grafana/data": "12.1.0-pre", - "@grafana/google-sdk": "0.3.2", + "@grafana/google-sdk": "0.3.4", "@grafana/plugin-ui": "0.10.7", "@grafana/runtime": "12.1.0-pre", "@grafana/schema": "12.1.0-pre", @@ -48,9 +48,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/cloud-monitoring/webpack.config.ts b/public/app/plugins/datasource/cloud-monitoring/webpack.config.ts index 4da5a990cfa..7931eb9cb5c 100644 --- a/public/app/plugins/datasource/cloud-monitoring/webpack.config.ts +++ b/public/app/plugins/datasource/cloud-monitoring/webpack.config.ts @@ -1,3 +1,4 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config from '@grafana/plugin-configs/webpack.config.ts'; +// eslint-disable-next-line no-barrel-files/no-barrel-files export default config; diff --git a/public/app/plugins/datasource/elasticsearch/components/reducerTester.ts b/public/app/plugins/datasource/elasticsearch/components/reducerTester.ts index 38c466afa2b..79e2fddbc2d 100644 --- a/public/app/plugins/datasource/elasticsearch/components/reducerTester.ts +++ b/public/app/plugins/datasource/elasticsearch/components/reducerTester.ts @@ -2,7 +2,7 @@ import { AnyAction } from '@reduxjs/toolkit'; import { cloneDeep } from 'lodash'; import { Action } from 'redux'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; type GrafanaReducer<S = StoreState, A extends Action = AnyAction> = (state: S, action: A) => S; diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json index cc2fde9a4e3..2acfab5815d 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json @@ -33,9 +33,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/webpack.config.ts b/public/app/plugins/datasource/grafana-postgresql-datasource/webpack.config.ts index 55a880fef5c..7931eb9cb5c 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/webpack.config.ts +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/webpack.config.ts @@ -1,4 +1,4 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config from '@grafana/plugin-configs/webpack.config.ts'; // eslint-disable-next-line no-barrel-files/no-barrel-files export default config; diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json index 65be0f55f6c..3fcf2bb95c9 100644 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json +++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json @@ -42,9 +42,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/webpack.config.ts b/public/app/plugins/datasource/grafana-pyroscope-datasource/webpack.config.ts index 8e03497ddb2..f48f8b1a693 100644 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/webpack.config.ts +++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/webpack.config.ts @@ -1,6 +1,6 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config, { type Env } from '@grafana/plugin-configs/webpack.config.ts'; -const configWithFallback = async (env: Record<string, unknown>) => { +const configWithFallback = async (env: Env) => { const response = await config(env); if (response !== undefined && response.resolve !== undefined) { response.resolve.fallback = { diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/package.json b/public/app/plugins/datasource/grafana-testdata-datasource/package.json index 5d1fa9adc72..1c71f41c562 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/package.json +++ b/public/app/plugins/datasource/grafana-testdata-datasource/package.json @@ -41,9 +41,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/webpack.config.ts b/public/app/plugins/datasource/grafana-testdata-datasource/webpack.config.ts index 4da5a990cfa..7931eb9cb5c 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/webpack.config.ts +++ b/public/app/plugins/datasource/grafana-testdata-datasource/webpack.config.ts @@ -1,3 +1,4 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config from '@grafana/plugin-configs/webpack.config.ts'; +// eslint-disable-next-line no-barrel-files/no-barrel-files export default config; diff --git a/public/app/plugins/datasource/jaeger/package.json b/public/app/plugins/datasource/jaeger/package.json index 383c155d43c..d32fdd415c7 100644 --- a/public/app/plugins/datasource/jaeger/package.json +++ b/public/app/plugins/datasource/jaeger/package.json @@ -44,9 +44,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/jaeger/webpack.config.ts b/public/app/plugins/datasource/jaeger/webpack.config.ts index 10ef5bd69a2..0346a64c5f2 100644 --- a/public/app/plugins/datasource/jaeger/webpack.config.ts +++ b/public/app/plugins/datasource/jaeger/webpack.config.ts @@ -1,6 +1,10 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import { createRequire } from 'node:module'; -const configWithFallback = async (env: Record<string, unknown>) => { +import config, { type Env } from '@grafana/plugin-configs/webpack.config.ts'; + +const require = createRequire(import.meta.url); + +const configWithFallback = async (env: Env) => { const response = await config(env); if (response !== undefined && response.resolve !== undefined) { response.resolve.fallback = { diff --git a/public/app/plugins/datasource/loki/package.json b/public/app/plugins/datasource/loki/package.json index 0fe5fbfdd7b..3cd58989823 100644 --- a/public/app/plugins/datasource/loki/package.json +++ b/public/app/plugins/datasource/loki/package.json @@ -44,9 +44,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/loki/webpack.config.ts b/public/app/plugins/datasource/loki/webpack.config.ts index 55a880fef5c..7931eb9cb5c 100644 --- a/public/app/plugins/datasource/loki/webpack.config.ts +++ b/public/app/plugins/datasource/loki/webpack.config.ts @@ -1,4 +1,4 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config from '@grafana/plugin-configs/webpack.config.ts'; // eslint-disable-next-line no-barrel-files/no-barrel-files export default config; diff --git a/public/app/plugins/datasource/mssql/module.ts b/public/app/plugins/datasource/mssql/module.ts index 7cf4eeaafe1..7ba2f9c512f 100644 --- a/public/app/plugins/datasource/mssql/module.ts +++ b/public/app/plugins/datasource/mssql/module.ts @@ -8,7 +8,11 @@ import { MssqlDatasource } from './datasource'; import pluginJson from './plugin.json'; import { MssqlOptions } from './types'; -initPluginTranslations(pluginJson.id, [loadSQLResources]); +// don't load plugin translations in test environments +// we don't use them anyway, and top-level await won't work currently in jest +if (process.env.NODE_ENV !== 'test') { + await initPluginTranslations(pluginJson.id, [loadSQLResources]); +} export const plugin = new DataSourcePlugin<MssqlDatasource, SQLQuery, MssqlOptions>(MssqlDatasource) .setQueryEditor(SqlQueryEditorLazy) diff --git a/public/app/plugins/datasource/mssql/package.json b/public/app/plugins/datasource/mssql/package.json index fa734fad0f5..7b8f678c101 100644 --- a/public/app/plugins/datasource/mssql/package.json +++ b/public/app/plugins/datasource/mssql/package.json @@ -35,9 +35,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development", + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development", "i18n-extract": "i18next --config locales/i18next-parser.config.cjs" }, "packageManager": "yarn@4.9.2" diff --git a/public/app/plugins/datasource/mssql/webpack.config.ts b/public/app/plugins/datasource/mssql/webpack.config.ts index 2e981f9ea7c..8a119f88315 100644 --- a/public/app/plugins/datasource/mssql/webpack.config.ts +++ b/public/app/plugins/datasource/mssql/webpack.config.ts @@ -1,9 +1,9 @@ import type { Configuration } from 'webpack'; import { merge } from 'webpack-merge'; -import grafanaConfig from '@grafana/plugin-configs/webpack.config'; +import grafanaConfig, { type Env } from '@grafana/plugin-configs/webpack.config.ts'; -const config = async (env: Record<string, unknown>): Promise<Configuration> => { +const config = async (env: Env): Promise<Configuration> => { const baseConfig = await grafanaConfig(env); return merge(baseConfig, { diff --git a/public/app/plugins/datasource/mysql/package.json b/public/app/plugins/datasource/mysql/package.json index 78c0d5c95d3..71f24047aa4 100644 --- a/public/app/plugins/datasource/mysql/package.json +++ b/public/app/plugins/datasource/mysql/package.json @@ -33,9 +33,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/mysql/webpack.config.ts b/public/app/plugins/datasource/mysql/webpack.config.ts index 55a880fef5c..7931eb9cb5c 100644 --- a/public/app/plugins/datasource/mysql/webpack.config.ts +++ b/public/app/plugins/datasource/mysql/webpack.config.ts @@ -1,4 +1,4 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config from '@grafana/plugin-configs/webpack.config.ts'; // eslint-disable-next-line no-barrel-files/no-barrel-files export default config; diff --git a/public/app/plugins/datasource/parca/package.json b/public/app/plugins/datasource/parca/package.json index 18c7a72fad7..5690290bb3a 100644 --- a/public/app/plugins/datasource/parca/package.json +++ b/public/app/plugins/datasource/parca/package.json @@ -34,9 +34,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/parca/webpack.config.ts b/public/app/plugins/datasource/parca/webpack.config.ts index 4da5a990cfa..31247bb11af 100644 --- a/public/app/plugins/datasource/parca/webpack.config.ts +++ b/public/app/plugins/datasource/parca/webpack.config.ts @@ -1,3 +1,3 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config from '@grafana/plugin-configs/webpack.config.ts'; export default config; diff --git a/public/app/plugins/datasource/tempo/package.json b/public/app/plugins/datasource/tempo/package.json index e7ac0f7c247..fa1710c1d6b 100644 --- a/public/app/plugins/datasource/tempo/package.json +++ b/public/app/plugins/datasource/tempo/package.json @@ -61,10 +61,10 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", "build:stats": "yarn build --env stats --profile --json=compilation-stats.json", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/tempo/webpack.config.ts b/public/app/plugins/datasource/tempo/webpack.config.ts index 4da5a990cfa..7931eb9cb5c 100644 --- a/public/app/plugins/datasource/tempo/webpack.config.ts +++ b/public/app/plugins/datasource/tempo/webpack.config.ts @@ -1,3 +1,4 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config from '@grafana/plugin-configs/webpack.config.ts'; +// eslint-disable-next-line no-barrel-files/no-barrel-files export default config; diff --git a/public/app/plugins/datasource/zipkin/package.json b/public/app/plugins/datasource/zipkin/package.json index d3e3633e78d..94a2c65a18e 100644 --- a/public/app/plugins/datasource/zipkin/package.json +++ b/public/app/plugins/datasource/zipkin/package.json @@ -37,9 +37,9 @@ "@grafana/runtime": "*" }, "scripts": { - "build": "webpack -c ./webpack.config.ts --env production", - "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", + "build:commit": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", + "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development" }, "packageManager": "yarn@4.9.2" } diff --git a/public/app/plugins/datasource/zipkin/webpack.config.ts b/public/app/plugins/datasource/zipkin/webpack.config.ts index 4da5a990cfa..7931eb9cb5c 100644 --- a/public/app/plugins/datasource/zipkin/webpack.config.ts +++ b/public/app/plugins/datasource/zipkin/webpack.config.ts @@ -1,3 +1,4 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import config from '@grafana/plugin-configs/webpack.config.ts'; +// eslint-disable-next-line no-barrel-files/no-barrel-files export default config; diff --git a/public/app/plugins/panel/alertlist/GroupByWithLoading.tsx b/public/app/plugins/panel/alertlist/GroupByWithLoading.tsx index d864dfaba37..48bc6d561fe 100644 --- a/public/app/plugins/panel/alertlist/GroupByWithLoading.tsx +++ b/public/app/plugins/panel/alertlist/GroupByWithLoading.tsx @@ -10,7 +10,7 @@ import { isAsyncRequestMapSlicePending, isAsyncRequestMapSliceSettled, } from 'app/features/alerting/unified/utils/redux'; -import { useDispatch } from 'app/types'; +import { useDispatch } from 'app/types/store'; import { AlertingRule } from 'app/types/unified-alerting'; import { PromRuleType } from 'app/types/unified-alerting-dto'; diff --git a/public/app/plugins/panel/alertlist/UnifiedAlertList.tsx b/public/app/plugins/panel/alertlist/UnifiedAlertList.tsx index 6043d715801..913ddbfcda6 100644 --- a/public/app/plugins/panel/alertlist/UnifiedAlertList.tsx +++ b/public/app/plugins/panel/alertlist/UnifiedAlertList.tsx @@ -38,7 +38,7 @@ import { flattenCombinedRules, getFirstActiveAt } from 'app/features/alerting/un import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { Matcher } from 'app/plugins/datasource/alertmanager/types'; -import { ThunkDispatch, useDispatch } from 'app/types'; +import { ThunkDispatch, useDispatch } from 'app/types/store'; import { PromAlertingRuleState } from 'app/types/unified-alerting-dto'; import { AlertingAction, useAlertingAbility } from '../../../features/alerting/unified/hooks/useAbilities'; diff --git a/public/app/plugins/panel/dashlist/DashList.tsx b/public/app/plugins/panel/dashlist/DashList.tsx index e3044da47d2..d5c13d5627a 100644 --- a/public/app/plugins/panel/dashlist/DashList.tsx +++ b/public/app/plugins/panel/dashlist/DashList.tsx @@ -23,7 +23,7 @@ import impressionSrv from 'app/core/services/impression_srv'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { DashboardSearchItem } from 'app/features/search/types'; import { VariablesChanged } from 'app/features/variables/types'; -import { useDispatch, useSelector } from 'app/types'; +import { useDispatch, useSelector } from 'app/types/store'; import { Options } from './panelcfg.gen'; import { getStyles } from './styles'; diff --git a/public/app/plugins/panel/dashlist/migrations.ts b/public/app/plugins/panel/dashlist/migrations.ts index 25f420108d2..a48c8f4f736 100644 --- a/public/app/plugins/panel/dashlist/migrations.ts +++ b/public/app/plugins/panel/dashlist/migrations.ts @@ -1,6 +1,6 @@ import { PanelModel } from '@grafana/data'; import { getBackendSrv } from '@grafana/runtime'; -import { FolderDTO } from 'app/types'; +import { FolderDTO } from 'app/types/folders'; import { Options } from './panelcfg.gen'; diff --git a/public/app/plugins/panel/logs/LogsPanel.tsx b/public/app/plugins/panel/logs/LogsPanel.tsx index 709055ce389..ed375de1044 100644 --- a/public/app/plugins/panel/logs/LogsPanel.tsx +++ b/public/app/plugins/panel/logs/LogsPanel.tsx @@ -114,6 +114,12 @@ interface LogsPanelProps extends PanelProps<Options> { * When the feature toggle newLogsPanel is enabled, you can pass extra options to the LogLineMenu component. * These options are an array of items with { label, onClick } or { divider: true } for dividers. * logLineMenuCustomItems?: LogLineMenuCustomItem[]; + * + * Use the default, bigger, font size, or a smaller one. Defaults to "default". + * fontSize?: 'default' | 'small' + * + * Set the mode used by the Log Details panel. Displayed as a sidebar, or inline below the log line. Defaults to "inline". + * detailsMode?: 'inline' | 'sidebar' */ } interface LogsPermalinkUrlState { @@ -153,6 +159,7 @@ export const LogsPanel = ({ onNewLogsReceived, fontSize, syntaxHighlighting, + detailsMode, ...options }, id, @@ -535,6 +542,7 @@ export const LogsPanel = ({ app={isCoreApp(app) ? app : CoreApp.Dashboard} containerElement={scrollElement} dedupStrategy={dedupStrategy} + detailsMode={detailsMode} displayedFields={displayedFields} enableLogDetails={enableLogDetails} fontSize={fontSize} diff --git a/public/app/plugins/panel/logs/module.tsx b/public/app/plugins/panel/logs/module.tsx index 0e339918d65..de1562c4898 100644 --- a/public/app/plugins/panel/logs/module.tsx +++ b/public/app/plugins/panel/logs/module.tsx @@ -108,6 +108,22 @@ export const plugin = new PanelPlugin<Options>(LogsPanel) }, ], }, + }) + .addRadio({ + path: 'detailsMode', + name: t('logs.name-details-mode', 'Log Details panel mode'), + category, + description: '', + settings: { + options: [ + { value: 'inline', label: t('logs.name-details-options.label-inline', 'Inline') }, + { + value: 'sidebar', + label: t('logs.name-details-options.label-sidebar', 'Sidebar'), + }, + ], + }, + defaultValue: 'inline', }); } diff --git a/public/app/plugins/panel/logs/panelcfg.cue b/public/app/plugins/panel/logs/panelcfg.cue index cd21fc2e041..70ddf33b412 100644 --- a/public/app/plugins/panel/logs/panelcfg.cue +++ b/public/app/plugins/panel/logs/panelcfg.cue @@ -40,6 +40,7 @@ composableKinds: PanelCfg: { dedupStrategy: common.LogsDedupStrategy enableInfiniteScrolling?: bool fontSize?: "default" | "small" @cuetsy(kind="enum", memberNames="default|small") + detailsMode?: "inline" | "sidebar" @cuetsy(kind="enum", memberNames="inline|sidebar") // TODO: figure out how to define callbacks onClickFilterLabel?: _ onClickFilterOutLabel?: _ diff --git a/public/app/plugins/panel/logs/panelcfg.gen.ts b/public/app/plugins/panel/logs/panelcfg.gen.ts index 5af4d61f578..a07151c7fda 100644 --- a/public/app/plugins/panel/logs/panelcfg.gen.ts +++ b/public/app/plugins/panel/logs/panelcfg.gen.ts @@ -13,6 +13,7 @@ import * as common from '@grafana/schema'; export interface Options { controlsStorageKey?: string; dedupStrategy: common.LogsDedupStrategy; + detailsMode?: ('inline' | 'sidebar'); displayedFields?: Array<string>; enableInfiniteScrolling?: boolean; enableLogDetails: boolean; diff --git a/public/app/plugins/panel/nodeGraph/Edge.tsx b/public/app/plugins/panel/nodeGraph/Edge.tsx index 7a8a2911c67..ea1fa18f963 100644 --- a/public/app/plugins/panel/nodeGraph/Edge.tsx +++ b/public/app/plugins/panel/nodeGraph/Edge.tsx @@ -17,11 +17,10 @@ interface Props { onClick: (event: MouseEvent<SVGElement>, link: EdgeDatumLayout) => void; onMouseEnter: (id: string) => void; onMouseLeave: (id: string) => void; - processedNodesLength: number; } export const Edge = memo(function Edge(props: Props) { - const { edge, onClick, onMouseEnter, onMouseLeave, hovering, svgIdNamespace, processedNodesLength } = props; + const { edge, onClick, onMouseEnter, onMouseLeave, hovering, svgIdNamespace } = props; // Not great typing but after we do layout these properties are full objects not just references const { source, target, sourceNodeRadius, targetNodeRadius } = edge as { @@ -59,7 +58,6 @@ export const Edge = memo(function Edge(props: Props) { <EdgeArrowMarker id={markerId} fill={edgeColor} headHeight={arrowHeadHeight} /> <EdgeArrowMarker id={coloredMarkerId} fill={highlightedEdgeColor} headHeight={arrowHeadHeight} /> <g - key={`${edge.id}-${edge.source.y ?? ''}-${processedNodesLength}-g`} onClick={(event) => onClick(event, edge)} style={{ cursor: 'pointer' }} aria-label={t('nodeGraph.edge.aria-label-from-to', 'Edge from: {{from}} to: {{to}}', { diff --git a/public/app/plugins/panel/nodeGraph/NodeGraph.tsx b/public/app/plugins/panel/nodeGraph/NodeGraph.tsx index 08a06af7b27..4a398abe7a7 100644 --- a/public/app/plugins/panel/nodeGraph/NodeGraph.tsx +++ b/public/app/plugins/panel/nodeGraph/NodeGraph.tsx @@ -290,6 +290,7 @@ export function NodeGraph({ getLinks, dataFrames, nodeLimit, panelId, zoomMode, onMouseLeave={clearEdgeHover} svgIdNamespace={svgIdNamespace} processedNodesLength={processed.nodes.length} + processedEdgesLength={processed.edges.length} /> )} <Nodes @@ -430,26 +431,28 @@ interface EdgesProps { onMouseEnter: (id: string) => void; onMouseLeave: (id: string) => void; processedNodesLength: number; + processedEdgesLength: number; } const Edges = memo(function Edges(props: EdgesProps) { return ( <> - {props.edges.map((e) => ( - <Edge - key={`${e.id}-${e.source.y ?? ''}-${props.processedNodesLength}`} - edge={e} - hovering={ - (e.source as NodeDatum).id === props.nodeHoveringId || - (e.target as NodeDatum).id === props.nodeHoveringId || - props.edgeHoveringId === e.id - } - onClick={props.onClick} - onMouseEnter={props.onMouseEnter} - onMouseLeave={props.onMouseLeave} - svgIdNamespace={props.svgIdNamespace} - processedNodesLength={props.processedNodesLength} - /> - ))} + {props.edges.map((e, index) => { + return ( + <Edge + key={`${e.id}-${e.source.y ?? ''}-${props.processedNodesLength}-${props.processedEdgesLength}-${index}`} + edge={e} + hovering={ + (e.source as NodeDatum).id === props.nodeHoveringId || + (e.target as NodeDatum).id === props.nodeHoveringId || + props.edgeHoveringId === e.id + } + onClick={props.onClick} + onMouseEnter={props.onMouseEnter} + onMouseLeave={props.onMouseLeave} + svgIdNamespace={props.svgIdNamespace} + /> + ); + })} </> ); }); @@ -462,7 +465,7 @@ interface EdgeLabelsProps { const EdgeLabels = memo(function EdgeLabels(props: EdgeLabelsProps) { return ( <> - {props.edges.map((e, index) => { + {props.edges.map((e) => { // We show the edge label in case user hovers over the edge directly or if they hover over node edge is // connected to. const shouldShow = diff --git a/public/app/plugins/panel/table/table-new/TablePanel.tsx b/public/app/plugins/panel/table/table-new/TablePanel.tsx index d5bf34dd869..78f97127d9c 100644 --- a/public/app/plugins/panel/table/table-new/TablePanel.tsx +++ b/public/app/plugins/panel/table/table-new/TablePanel.tsx @@ -26,7 +26,7 @@ import { Options } from './panelcfg.gen'; interface Props extends PanelProps<Options> {} export function TablePanel(props: Props) { - const { data, height, width, options, fieldConfig, id, timeRange, replaceVariables } = props; + const { data, height, width, options, fieldConfig, id, timeRange, replaceVariables, transparent } = props; useMemo(() => { cacheFieldDisplayNames(data.series); @@ -82,6 +82,7 @@ export function TablePanel(props: Props) { fieldConfig={fieldConfig} getActions={_getActions} structureRev={data.structureRev} + transparent={transparent} /> ); diff --git a/public/app/routes/routes.tsx b/public/app/routes/routes.tsx index e1baf824794..41221a4e772 100644 --- a/public/app/routes/routes.tsx +++ b/public/app/routes/routes.tsx @@ -17,7 +17,8 @@ import { ConfigureIRM } from 'app/features/gops/configuration-tracker/components import { getRoutes as getPluginCatalogRoutes } from 'app/features/plugins/admin/routes'; import { getAppPluginRoutes } from 'app/features/plugins/routes'; import { getProfileRoutes } from 'app/features/profile/routes'; -import { AccessControlAction, DashboardRoutes } from 'app/types'; +import { AccessControlAction } from 'app/types/accessControl'; +import { DashboardRoutes } from 'app/types/dashboard'; import { SafeDynamicImport } from '../core/components/DynamicImports/SafeDynamicImport'; import { RouteDescriptor } from '../core/navigation/types'; diff --git a/public/app/store/store.ts b/public/app/store/store.ts index 496a3e4b081..557ec7566f3 100644 --- a/public/app/store/store.ts +++ b/public/app/store/store.ts @@ -1,7 +1,7 @@ import { Store } from 'redux'; import { initialKeyedVariablesState } from 'app/features/variables/state/keyedVariablesReducer'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; export let store: Store<StoreState>; diff --git a/public/app/types/acl.ts b/public/app/types/acl.ts index 684a3a158b1..a3662165c92 100644 --- a/public/app/types/acl.ts +++ b/public/app/types/acl.ts @@ -1,12 +1,8 @@ -import { OrgRole } from '@grafana/data'; - export enum TeamPermissionLevel { Admin = 4, Member = 0, } -export { OrgRole as OrgRole }; - export type PermissionLevel = 'view' | 'edit' | 'admin'; /** @deprecated Use PermissionLevel instead */ diff --git a/public/app/types/apiKeys.ts b/public/app/types/apiKeys.ts index 37778e66a7a..e732ecc06cd 100644 --- a/public/app/types/apiKeys.ts +++ b/public/app/types/apiKeys.ts @@ -1,6 +1,4 @@ -import { WithAccessControlMetadata } from '@grafana/data'; - -import { OrgRole } from './acl'; +import { OrgRole, WithAccessControlMetadata } from '@grafana/data'; export interface ApiKey extends WithAccessControlMetadata { id?: number; diff --git a/public/app/types/index.ts b/public/app/types/index.ts deleted file mode 100644 index 546c2ab628d..00000000000 --- a/public/app/types/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -export * from './teams'; -export * from './alerting'; -export * from './location'; -export * from './folders'; -export * from './dashboard'; -export * from './acl'; -export * from './apiKeys'; -export * from './user'; -export * from './serviceaccount'; -export * from './datasources'; -export * from './plugins'; -export * from './organization'; -export * from './appNotifications'; -export * from './explore'; -export * from './store'; -export * from './ldap'; -export * from './query'; -export * from './accessControl'; -export * from './supportBundles'; -export * from './settings'; - -import * as CoreEvents from './events'; -export { CoreEvents }; diff --git a/public/app/types/organization.ts b/public/app/types/organization.ts index 926bced7bd5..367c7fcd55c 100644 --- a/public/app/types/organization.ts +++ b/public/app/types/organization.ts @@ -1,4 +1,4 @@ -import { UserOrg } from 'app/types'; +import { UserOrg } from 'app/types/user'; export interface Organization { name: string; diff --git a/public/app/types/serviceaccount.ts b/public/app/types/serviceaccount.ts index 85c2fe1c0de..2d9a56e95b7 100644 --- a/public/app/types/serviceaccount.ts +++ b/public/app/types/serviceaccount.ts @@ -1,6 +1,7 @@ -import { WithAccessControlMetadata } from '@grafana/data'; +import { OrgRole, WithAccessControlMetadata } from '@grafana/data'; -import { ApiKey, OrgRole, Role } from '.'; +import { Role } from './accessControl'; +import { ApiKey } from './apiKeys'; export interface OrgServiceAccount extends WithAccessControlMetadata { serviceAccountId: number; diff --git a/public/app/types/user.ts b/public/app/types/user.ts index 67264b0f298..e5cd1805e7f 100644 --- a/public/app/types/user.ts +++ b/public/app/types/user.ts @@ -1,7 +1,6 @@ -import { SelectableValue, WithAccessControlMetadata } from '@grafana/data'; -import { Role } from 'app/types'; +import { OrgRole, SelectableValue, WithAccessControlMetadata } from '@grafana/data'; -import { OrgRole } from '.'; +import { Role } from './accessControl'; export interface OrgUser extends WithAccessControlMetadata { avatarUrl: string; diff --git a/public/img/plugins/logicmonitor.svg b/public/img/plugins/logicmonitor.svg index f533e96b843..20855d2bb3b 100644 --- a/public/img/plugins/logicmonitor.svg +++ b/public/img/plugins/logicmonitor.svg @@ -1 +1,5 @@ -<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{fill:#fff;}.cls-4{fill:#0076ff;}</style><clipPath id="clip-path"><rect class="cls-1" x="-5" y="29.5" width="1511" height="408"></rect></clipPath></defs><title>svg \ No newline at end of file + + + + + diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index f13ec825abf..07558dd8558 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -508,6 +508,9 @@ } } }, + "alert-rule": { + "term": "Alert rule" + }, "alert-rule-form": { "action-buttons": { "edit-yaml": "Edit YAML", @@ -1505,15 +1508,12 @@ "group-details": { "ds-features-error": "Error loading data source details", "edit": "Edit", - "evaluations-to-fire": "Evaluation cycles to fire", "export": "Export", "folder": "Folder", "group-loading-error": "Error loading the group", "interval": "Interval", "namespace": "Namespace", - "pending-period": "Pending period", - "recording": "Recording", - "rule-name": "Rule name" + "new": "New" }, "group-edit": { "ds-error": "Error loading data source details", @@ -2237,6 +2237,9 @@ "label-export-all": "Export all" } }, + "recording-rule": { + "term": "Recording rule" + }, "recording-rule-editor": { "error-no-query-editor": "Could not load query editor due to: {{errorMessage}}" }, @@ -2650,6 +2653,11 @@ "selecting-data-source-tooltip": { "tooltip-content": "Not finding the data source you want? Some data sources are not supported for alerting. Click on the icon for more information." }, + "settings": { + "tabs": { + "alert-managers": "Alert managers" + } + }, "settings-content": { "add-new-alertmanager": "Add new Alertmanager", "builtin-alertmanager": "Built-in Alertmanager", @@ -2885,6 +2893,11 @@ "timestamp": { "time-ago": "({{time}} ago)" }, + "titles": { + "group-view": { + "subtitle": "Manage alert rules, recording rules and evaluation interval" + } + }, "to-gma": { "confirm-modal": { "body": "The target folder is not empty, some rules may be overwritten or removed. Are you sure you want to import these alert rules to Grafana-managed rules?", @@ -5656,6 +5669,20 @@ "usage-count_one": "Used on {{count}} dashboards", "usage-count_other": "Used on {{count}} dashboards" }, + "move-provisioned-dashboard-form": { + "api-error": "Failed to move dashboard", + "cancel-action": "Cancel", + "current-file-not-found": "Current dashboard file could not be found", + "drawer-title": "Move Provisioned Dashboard", + "file-load-error": "Error loading dashboard", + "loading-file-data": "Loading dashboard data", + "move-action": "Move dashboard", + "move-read-only-message": "This dashboard cannot be moved directly from Grafana because the repository is read-only. To move this dashboard, please move the file in your Git repository.", + "moving": "Moving...", + "partial-failure-warning": "Dashboard was created at new location but could not be deleted from original location. Please manually remove the old file.", + "target-path-label": "Target path", + "title-this-repository-is-read-only": "This repository is read only" + }, "name-already-exists-error": { "body-name-already-exists": "A dashboard with the same name in selected folder already exists. Would you still like to save this dashboard?", "title-name-already-exists": "Name already exists" @@ -7984,6 +8011,9 @@ "filter-popup-match-case": "Match case", "inspect-drawer-title": "Inspect value", "inspect-menu-label": "Inspect value", + "nested-table": { + "no-data": "No data" + }, "no-values-label": "No values", "pagination-summary": "{{itemsRangeStart}} - {{displayedEnd}} of {{numRows}} rows" }, @@ -8712,6 +8742,7 @@ }, "fields-section": "Fields", "hide-log-line": "Hide log line", + "inline-mode": "Display inline", "links-section": "Links", "log-line-field": "Log line", "log-line-section": "Log line", @@ -8724,6 +8755,7 @@ "search-placeholder": "Search field names and values", "show-context": "Show context", "show-log-line": "Show log line", + "sidebar-mode": "Anchor to the right", "unpin-line": "Unpin log" }, "log-line-menu": { @@ -8826,6 +8858,11 @@ }, "name-common-labels": "Common labels", "name-deduplication": "Deduplication", + "name-details-mode": "Log Details panel mode", + "name-details-options": { + "label-inline": "Inline", + "label-sidebar": "Sidebar" + }, "name-enable-infinite-scrolling": "Enable infinite scrolling", "name-enable-log-details": "Enable log details", "name-enable-syntax-highlighting": "Enable syntax highlighting", @@ -9084,6 +9121,8 @@ "resource-details": { "dismiss-button": "OK", "error-messages": { + "alert-rules-group-quota-reached": "Maximum number of alert rule groups reached: Delete some alert rule groups or upgrade your plan and try again.", + "alert-rules-quota-reached": "Maximum number of alert rules reached: Delete some alert rules or upgrade your plan and try again.", "dashboard-already-managed": "Dashboard is already provisioned and managed by Grafana in the cloud instance. We recommend using the provisioned dashboard going forward. If you still wish to copy the dashboard to the cloud instance, then change the dashboard ID in the dashboard JSON, save a new snapshot and upload again.", "datasource-already-managed": "Data source is already provisioned and managed by Grafana in the cloud instance. If this is a different resource, set another UID and try again.", "datasource-invalid-url": "There is a data source which has an invalid URL. Provide a valid URL and try again.", @@ -10313,10 +10352,8 @@ "open-pull-request-in-git-hub": "Open pull request in GitHub", "view-pull-request-in-git-hub": "View pull request in GitHub" }, - "title-dashboard-loaded-branch-git-hub": "This dashboard is loaded from a branch in GitHub.", - "title-dashboard-loaded-pull-request-git-hub": "This dashboard is loaded from a pull request in GitHub.", - "title-folder-created-branch-git-hub": "A new folder has been created in a branch in GitHub.", - "title-folder-created-pull-request-git-hub": "A new folder has been created in a pull request in GitHub." + "title-created-branch-git-hub": "A new resource has been created in a branch in GitHub.", + "title-loaded-pull-request-git-hub": "This resource is loaded from a pull request in GitHub." }, "provisioning": { "banner": { diff --git a/public/openapi3.json b/public/openapi3.json index f44e48250d6..f6a8589a689 100644 --- a/public/openapi3.json +++ b/public/openapi3.json @@ -7360,6 +7360,8 @@ "properties": { "errorCode": { "enum": [ + "ALERT_RULES_QUOTA_REACHED", + "ALERT_RULES_GROUP_QUOTA_REACHED", "DATASOURCE_NAME_CONFLICT", "DATASOURCE_INVALID_URL", "DATASOURCE_ALREADY_MANAGED", diff --git a/public/test/core/redux/reducerTester.ts b/public/test/core/redux/reducerTester.ts index 38c466afa2b..79e2fddbc2d 100644 --- a/public/test/core/redux/reducerTester.ts +++ b/public/test/core/redux/reducerTester.ts @@ -2,7 +2,7 @@ import { AnyAction } from '@reduxjs/toolkit'; import { cloneDeep } from 'lodash'; import { Action } from 'redux'; -import { StoreState } from 'app/types'; +import { StoreState } from 'app/types/store'; type GrafanaReducer = (state: S, action: A) => S; diff --git a/public/test/core/redux/reduxTester.ts b/public/test/core/redux/reduxTester.ts index 787ce13b59b..caf43717f21 100644 --- a/public/test/core/redux/reduxTester.ts +++ b/public/test/core/redux/reduxTester.ts @@ -3,7 +3,7 @@ import { Middleware, Store, StoreEnhancer, UnknownAction } from 'redux'; import { thunk, ThunkDispatch, ThunkMiddleware } from 'redux-thunk'; import { setStore } from '../../../app/store/store'; -import { StoreState } from '../../../app/types'; +import { StoreState } from '../../../app/types/store'; export interface ReduxTesterGiven { givenRootReducer: (rootReducer: Reducer>>) => ReduxTesterWhen; diff --git a/public/test/helpers/convertToStoreState.ts b/public/test/helpers/convertToStoreState.ts index 9f696b0e45a..92982147231 100644 --- a/public/test/helpers/convertToStoreState.ts +++ b/public/test/helpers/convertToStoreState.ts @@ -2,7 +2,7 @@ import { TypedVariableModel } from '@grafana/data'; import { getPreloadedState } from '../../app/features/variables/state/helpers'; import { VariablesState } from '../../app/features/variables/state/types'; -import { StoreState } from '../../app/types'; +import { StoreState } from '../../app/types/store'; export const convertToStoreState = (key: string, models: TypedVariableModel[]): StoreState => { const variables = models.reduce((byName, variable) => { diff --git a/public/test/helpers/getTemplateSrvDependencies.ts b/public/test/helpers/getTemplateSrvDependencies.ts index c1da0c4d247..d602d5aa03d 100644 --- a/public/test/helpers/getTemplateSrvDependencies.ts +++ b/public/test/helpers/getTemplateSrvDependencies.ts @@ -1,7 +1,7 @@ import { TemplateSrvDependencies } from 'app/features/templating/template_srv'; import { getFilteredVariables, getVariables, getVariableWithName } from '../../app/features/variables/state/selectors'; -import { StoreState } from '../../app/types'; +import { StoreState } from '../../app/types/store'; export const getTemplateSrvDependencies = (state: StoreState): TemplateSrvDependencies => ({ getFilteredVariables: (filter) => getFilteredVariables(filter, state), diff --git a/yarn.lock b/yarn.lock index 6f8069078d2..1c0981adc93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1464,7 +1464,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.5, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.25.6, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.7, @babel/runtime@npm:^7.27.0, @babel/runtime@npm:^7.27.6, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.5, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.25.6, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.10, @babel/runtime@npm:^7.26.7, @babel/runtime@npm:^7.27.0, @babel/runtime@npm:^7.27.6, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7": version: 7.27.6 resolution: "@babel/runtime@npm:7.27.6" checksum: 10/cc957a12ba3781241b83d528eb69ddeb86ca5ac43179a825e83aa81263a6b3eb88c57bed8a937cdeacfc3192e07ec24c73acdfea4507d0c0428c8e23d6322bfe @@ -2058,177 +2058,184 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/aix-ppc64@npm:0.25.0" +"@esbuild/aix-ppc64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/aix-ppc64@npm:0.25.6" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-arm64@npm:0.25.0" +"@esbuild/android-arm64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/android-arm64@npm:0.25.6" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-arm@npm:0.25.0" +"@esbuild/android-arm@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/android-arm@npm:0.25.6" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-x64@npm:0.25.0" +"@esbuild/android-x64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/android-x64@npm:0.25.6" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/darwin-arm64@npm:0.25.0" +"@esbuild/darwin-arm64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/darwin-arm64@npm:0.25.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/darwin-x64@npm:0.25.0" +"@esbuild/darwin-x64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/darwin-x64@npm:0.25.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/freebsd-arm64@npm:0.25.0" +"@esbuild/freebsd-arm64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/freebsd-arm64@npm:0.25.6" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/freebsd-x64@npm:0.25.0" +"@esbuild/freebsd-x64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/freebsd-x64@npm:0.25.6" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-arm64@npm:0.25.0" +"@esbuild/linux-arm64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-arm64@npm:0.25.6" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-arm@npm:0.25.0" +"@esbuild/linux-arm@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-arm@npm:0.25.6" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-ia32@npm:0.25.0" +"@esbuild/linux-ia32@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-ia32@npm:0.25.6" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-loong64@npm:0.25.0" +"@esbuild/linux-loong64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-loong64@npm:0.25.6" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-mips64el@npm:0.25.0" +"@esbuild/linux-mips64el@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-mips64el@npm:0.25.6" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-ppc64@npm:0.25.0" +"@esbuild/linux-ppc64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-ppc64@npm:0.25.6" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-riscv64@npm:0.25.0" +"@esbuild/linux-riscv64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-riscv64@npm:0.25.6" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-s390x@npm:0.25.0" +"@esbuild/linux-s390x@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-s390x@npm:0.25.6" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-x64@npm:0.25.0" +"@esbuild/linux-x64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/linux-x64@npm:0.25.6" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/netbsd-arm64@npm:0.25.0" +"@esbuild/netbsd-arm64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/netbsd-arm64@npm:0.25.6" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/netbsd-x64@npm:0.25.0" +"@esbuild/netbsd-x64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/netbsd-x64@npm:0.25.6" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/openbsd-arm64@npm:0.25.0" +"@esbuild/openbsd-arm64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/openbsd-arm64@npm:0.25.6" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/openbsd-x64@npm:0.25.0" +"@esbuild/openbsd-x64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/openbsd-x64@npm:0.25.6" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/sunos-x64@npm:0.25.0" +"@esbuild/openharmony-arm64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/openharmony-arm64@npm:0.25.6" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/sunos-x64@npm:0.25.6" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-arm64@npm:0.25.0" +"@esbuild/win32-arm64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/win32-arm64@npm:0.25.6" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-ia32@npm:0.25.0" +"@esbuild/win32-ia32@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/win32-ia32@npm:0.25.6" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-x64@npm:0.25.0" +"@esbuild/win32-x64@npm:0.25.6": + version: 0.25.6 + resolution: "@esbuild/win32-x64@npm:0.25.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2858,7 +2865,7 @@ __metadata: "@emotion/css": "npm:11.13.5" "@grafana/data": "npm:12.1.0-pre" "@grafana/e2e-selectors": "npm:12.1.0-pre" - "@grafana/google-sdk": "npm:0.3.2" + "@grafana/google-sdk": "npm:0.3.4" "@grafana/plugin-configs": "npm:12.1.0-pre" "@grafana/plugin-ui": "npm:0.10.7" "@grafana/runtime": "npm:12.1.0-pre" @@ -3078,7 +3085,7 @@ __metadata: d3-interpolate: "npm:3.0.1" date-fns: "npm:4.1.0" dompurify: "npm:3.2.6" - esbuild: "npm:0.25.0" + esbuild: "npm:0.25.6" eventemitter3: "npm:5.0.1" fast_array_intersect: "npm:1.1.0" history: "npm:4.10.1" @@ -3117,7 +3124,7 @@ __metadata: "@rollup/plugin-node-resolve": "npm:16.0.1" "@types/node": "npm:22.15.0" "@types/semver": "npm:7.7.0" - esbuild: "npm:0.25.0" + esbuild: "npm:0.25.6" rimraf: "npm:6.0.1" rollup: "npm:^4.22.4" rollup-plugin-esbuild: "npm:6.2.0" @@ -3228,7 +3235,7 @@ __metadata: "@types/tinycolor2": "npm:1.4.6" babel-jest: "npm:29.7.0" d3: "npm:^7.8.5" - esbuild: "npm:0.25.0" + esbuild: "npm:0.25.6" jest: "npm:^29.6.4" jest-canvas-mock: "npm:2.5.2" lodash: "npm:4.17.21" @@ -3249,15 +3256,15 @@ __metadata: languageName: unknown linkType: soft -"@grafana/google-sdk@npm:0.3.2": - version: 0.3.2 - resolution: "@grafana/google-sdk@npm:0.3.2" +"@grafana/google-sdk@npm:0.3.4": + version: 0.3.4 + resolution: "@grafana/google-sdk@npm:0.3.4" peerDependencies: "@grafana/data": ">=10.4.0" "@grafana/ui": ">=10.4.0" react: ^18.2.0 react-dom: ^18.2.0 - checksum: 10/da0b1c7eda95a03da5ea919aaf97e3ae942c219ee0854483f84824837192fad06c302c3f7e87a7819882ba272726039a0633891bd3ded10449227aafac16dfc7 + checksum: 10/6156a07ab9a8e31ac20a689448f7d6bc86bd9d3fd0b22de8182cf5e6f96c05054f8c53a38148de58dca807adb5b0563914b03a22308ec7f770bf1cc71e8f21bd languageName: node linkType: hard @@ -3469,7 +3476,7 @@ __metadata: "@types/semver": "npm:7.7.0" "@types/uuid": "npm:10.0.0" debounce-promise: "npm:3.1.2" - esbuild: "npm:0.25.0" + esbuild: "npm:0.25.6" i18next-parser: "npm:9.3.0" jest: "npm:29.7.0" jest-environment-jsdom: "npm:29.7.0" @@ -3521,7 +3528,7 @@ __metadata: "@types/react": "npm:18.3.18" "@types/react-dom": "npm:18.3.5" "@types/systemjs": "npm:6.15.3" - esbuild: "npm:0.25.0" + esbuild: "npm:0.25.6" history: "npm:4.10.1" lodash: "npm:4.17.21" react: "npm:18.3.1" @@ -3543,10 +3550,10 @@ __metadata: linkType: soft "@grafana/scenes-react@npm:^6.27.0": - version: 6.27.1 - resolution: "@grafana/scenes-react@npm:6.27.1" + version: 6.27.2 + resolution: "@grafana/scenes-react@npm:6.27.2" dependencies: - "@grafana/scenes": "npm:6.27.1" + "@grafana/scenes": "npm:6.27.2" lru-cache: "npm:^10.2.2" react-use: "npm:^17.4.0" peerDependencies: @@ -3558,13 +3565,13 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/1177db57199595f23722b9059ddf21f2679199f423ddde78c41d0a037d0e9c755a47c149541ce89df3694d7c55399e76eabed6a68a02b9b344acb8d3f1d95610 + checksum: 10/415186350304d999a13fa1e66f8bb7675cb28d5174a9449b8cb3d6a25efaecfc74a0e2e69cde9513f6fd9cac9bd2891c12e93a974ec15cfa0d6d04e5b95b5306 languageName: node linkType: hard -"@grafana/scenes@npm:6.27.1, @grafana/scenes@npm:^6.27.0": - version: 6.27.1 - resolution: "@grafana/scenes@npm:6.27.1" +"@grafana/scenes@npm:6.27.2, @grafana/scenes@npm:^6.27.0": + version: 6.27.2 + resolution: "@grafana/scenes@npm:6.27.2" dependencies: "@floating-ui/react": "npm:^0.26.16" "@leeoniya/ufuzzy": "npm:^1.0.16" @@ -3584,7 +3591,7 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/7569db543bdf53483d5960e533cee61e86c25647b30d1290a28038725895dbb7e530bc9fd4520fc8c4e59b9a819f1daeeb87aecdf45c9d8870212c7ef1d65c8d + checksum: 10/8ba3d6c9b29de32a943a4a53511822f27eb51b35270368f0b9d80208eab50ae8767c6b372a7c7779a213618eab24bbb3e441dde42b038fc0a2078989879e0d14 languageName: node linkType: hard @@ -3594,7 +3601,7 @@ __metadata: dependencies: "@grafana/tsconfig": "npm:^2.0.0" "@rollup/plugin-node-resolve": "npm:16.0.1" - esbuild: "npm:0.25.0" + esbuild: "npm:0.25.6" glob: "npm:^11.0.0" rimraf: "npm:6.0.1" rollup: "npm:^4.22.4" @@ -3747,8 +3754,8 @@ __metadata: d3: "npm:7.9.0" date-fns: "npm:4.1.0" downshift: "npm:^9.0.6" - esbuild: "npm:0.25.0" - expose-loader: "npm:5.0.0" + esbuild: "npm:0.25.6" + expose-loader: "npm:5.0.1" fs-extra: "npm:^11.2.0" hoist-non-react-statics: "npm:3.3.2" i18next: "npm:^25.0.0" @@ -12467,13 +12474,13 @@ __metadata: languageName: node linkType: hard -"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1": - version: 1.0.1 - resolution: "call-bind-apply-helpers@npm:1.0.1" +"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind-apply-helpers@npm:1.0.2" dependencies: es-errors: "npm:^1.3.0" function-bind: "npm:^1.1.2" - checksum: 10/6e30c621170e45f1fd6735e84d02ee8e02a3ab95cb109499d5308cbe5d1e84d0cd0e10b48cc43c76aa61450ae1b03a7f89c37c10fc0de8d4998b42aab0f268cc + checksum: 10/00482c1f6aa7cfb30fb1dbeb13873edf81cfac7c29ed67a5957d60635a56b2a4a480f1016ddbdb3395cc37900d46037fb965043a51c5c789ffeab4fc535d18b5 languageName: node linkType: hard @@ -12489,13 +12496,13 @@ __metadata: languageName: node linkType: hard -"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3": - version: 1.0.3 - resolution: "call-bound@npm:1.0.3" +"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" dependencies: - call-bind-apply-helpers: "npm:^1.0.1" - get-intrinsic: "npm:^1.2.6" - checksum: 10/c39a8245f68cdb7c1f5eea7b3b1e3a7a90084ea6efebb78ebc454d698ade2c2bb42ec033abc35f1e596d62496b6100e9f4cdfad1956476c510130e2cda03266d + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10/ef2b96e126ec0e58a7ff694db43f4d0d44f80e641370c21549ed911fecbdbc2df3ebc9bddad918d6bbdefeafb60bb3337902006d5176d72bcd2da74820991af7 languageName: node linkType: hard @@ -15761,12 +15768,12 @@ __metadata: languageName: node linkType: hard -"es-object-atoms@npm:^1.0.0": - version: 1.0.0 - resolution: "es-object-atoms@npm:1.0.0" +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": + version: 1.1.1 + resolution: "es-object-atoms@npm:1.1.1" dependencies: es-errors: "npm:^1.3.0" - checksum: 10/f8910cf477e53c0615f685c5c96210591841850871b81924fcf256bfbaa68c254457d994a4308c60d15b20805e7f61ce6abc669375e01a5349391a8c1767584f + checksum: 10/54fe77de288451dae51c37bfbfe3ec86732dc3778f98f3eb3bdb4bf48063b2c0b8f9c93542656986149d08aa5be3204286e2276053d19582b76753f1a2728867 languageName: node linkType: hard @@ -15866,35 +15873,36 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:0.25.0, esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0, esbuild@npm:^0.25.0": - version: 0.25.0 - resolution: "esbuild@npm:0.25.0" +"esbuild@npm:0.25.6, esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0, esbuild@npm:^0.25.0": + version: 0.25.6 + resolution: "esbuild@npm:0.25.6" dependencies: - "@esbuild/aix-ppc64": "npm:0.25.0" - "@esbuild/android-arm": "npm:0.25.0" - "@esbuild/android-arm64": "npm:0.25.0" - "@esbuild/android-x64": "npm:0.25.0" - "@esbuild/darwin-arm64": "npm:0.25.0" - "@esbuild/darwin-x64": "npm:0.25.0" - "@esbuild/freebsd-arm64": "npm:0.25.0" - "@esbuild/freebsd-x64": "npm:0.25.0" - "@esbuild/linux-arm": "npm:0.25.0" - "@esbuild/linux-arm64": "npm:0.25.0" - "@esbuild/linux-ia32": "npm:0.25.0" - "@esbuild/linux-loong64": "npm:0.25.0" - "@esbuild/linux-mips64el": "npm:0.25.0" - "@esbuild/linux-ppc64": "npm:0.25.0" - "@esbuild/linux-riscv64": "npm:0.25.0" - "@esbuild/linux-s390x": "npm:0.25.0" - "@esbuild/linux-x64": "npm:0.25.0" - "@esbuild/netbsd-arm64": "npm:0.25.0" - "@esbuild/netbsd-x64": "npm:0.25.0" - "@esbuild/openbsd-arm64": "npm:0.25.0" - "@esbuild/openbsd-x64": "npm:0.25.0" - "@esbuild/sunos-x64": "npm:0.25.0" - "@esbuild/win32-arm64": "npm:0.25.0" - "@esbuild/win32-ia32": "npm:0.25.0" - "@esbuild/win32-x64": "npm:0.25.0" + "@esbuild/aix-ppc64": "npm:0.25.6" + "@esbuild/android-arm": "npm:0.25.6" + "@esbuild/android-arm64": "npm:0.25.6" + "@esbuild/android-x64": "npm:0.25.6" + "@esbuild/darwin-arm64": "npm:0.25.6" + "@esbuild/darwin-x64": "npm:0.25.6" + "@esbuild/freebsd-arm64": "npm:0.25.6" + "@esbuild/freebsd-x64": "npm:0.25.6" + "@esbuild/linux-arm": "npm:0.25.6" + "@esbuild/linux-arm64": "npm:0.25.6" + "@esbuild/linux-ia32": "npm:0.25.6" + "@esbuild/linux-loong64": "npm:0.25.6" + "@esbuild/linux-mips64el": "npm:0.25.6" + "@esbuild/linux-ppc64": "npm:0.25.6" + "@esbuild/linux-riscv64": "npm:0.25.6" + "@esbuild/linux-s390x": "npm:0.25.6" + "@esbuild/linux-x64": "npm:0.25.6" + "@esbuild/netbsd-arm64": "npm:0.25.6" + "@esbuild/netbsd-x64": "npm:0.25.6" + "@esbuild/openbsd-arm64": "npm:0.25.6" + "@esbuild/openbsd-x64": "npm:0.25.6" + "@esbuild/openharmony-arm64": "npm:0.25.6" + "@esbuild/sunos-x64": "npm:0.25.6" + "@esbuild/win32-arm64": "npm:0.25.6" + "@esbuild/win32-ia32": "npm:0.25.6" + "@esbuild/win32-x64": "npm:0.25.6" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -15938,6 +15946,8 @@ __metadata: optional: true "@esbuild/openbsd-x64": optional: true + "@esbuild/openharmony-arm64": + optional: true "@esbuild/sunos-x64": optional: true "@esbuild/win32-arm64": @@ -15948,7 +15958,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10/451daf6a442df29ec5d528587caa4ce783d41ff4acb93252da5a852b8d36c22e9f84d17f6721d4fbef9a1ba9855bc9fe1f167dd732c11665fe53032f2b89f114 + checksum: 10/b1c94893d53e39f3be02493c3a082bc9d090ca1702bf6017967ace1391d31e596da4dfd87e02efef3b7b4f0426918dbc5aa6909420a6ba42d51a872266ab6f2e languageName: node linkType: hard @@ -16167,11 +16177,11 @@ __metadata: linkType: hard "eslint-plugin-no-barrel-files@npm:^1.1.1": - version: 1.2.0 - resolution: "eslint-plugin-no-barrel-files@npm:1.2.0" + version: 1.2.1 + resolution: "eslint-plugin-no-barrel-files@npm:1.2.1" dependencies: "@typescript-eslint/utils": "npm:^8.13.0" - checksum: 10/da54a4930ddfd7d14bd82766e857af9eea5315125a2599d5ba03326530214e0d416f78915335d6c239b19df21b989196ffc4146919eff05477cef7e34261b946 + checksum: 10/22a888dd3b49527bed0f92758f4c7f34e78397c9197688db1936d2bdad8369f9ded2a1231a6b85e54791f059784f1d7bcdbeeb21cf0b453399044a1957a153c4 languageName: node linkType: hard @@ -16184,9 +16194,9 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react@npm:7.37.4": - version: 7.37.4 - resolution: "eslint-plugin-react@npm:7.37.4" +"eslint-plugin-react@npm:7.37.5": + version: 7.37.5 + resolution: "eslint-plugin-react@npm:7.37.5" dependencies: array-includes: "npm:^3.1.8" array.prototype.findlast: "npm:^1.2.5" @@ -16198,7 +16208,7 @@ __metadata: hasown: "npm:^2.0.2" jsx-ast-utils: "npm:^2.4.1 || ^3.0.0" minimatch: "npm:^3.1.2" - object.entries: "npm:^1.1.8" + object.entries: "npm:^1.1.9" object.fromentries: "npm:^2.0.8" object.values: "npm:^1.2.1" prop-types: "npm:^15.8.1" @@ -16208,7 +16218,7 @@ __metadata: string.prototype.repeat: "npm:^1.0.0" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 10/c538c10665c87cb90a0bcc4efe53a758570db10997d079d31474a9760116ef5584648fa22403d889ca672df8071bda10b40434ea0499e5ee8360bc5c8aba1679 + checksum: 10/ee1bd4e0ec64f29109d5a625bb703d179c82e0159c86c3f1b52fc1209d2994625a137dae303c333fb308a2e38315e44066d5204998177e31974382f9fda25d5c languageName: node linkType: hard @@ -16595,12 +16605,12 @@ __metadata: languageName: node linkType: hard -"expose-loader@npm:5.0.0": - version: 5.0.0 - resolution: "expose-loader@npm:5.0.0" +"expose-loader@npm:5.0.1": + version: 5.0.1 + resolution: "expose-loader@npm:5.0.1" peerDependencies: webpack: ^5.0.0 - checksum: 10/6a77c79744e41f81fd4da1eb07c319f13a097be85c4078380361fd6c69ac69576539bdd81a07d50b36b44ff1c2c5c97c1f4d2e75f0a14db391153bfb7035709b + checksum: 10/8e7c5eab2ed78f182845425e99b1ab270d71b9dfbf23b032839757d7aa2e8d8ddfd8aaeda996d26f4f6374c34e3293914db1d4b396f53be95241b85226cd40ff languageName: node linkType: hard @@ -17598,21 +17608,21 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7": - version: 1.2.7 - resolution: "get-intrinsic@npm:1.2.7" +"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": + version: 1.3.0 + resolution: "get-intrinsic@npm:1.3.0" dependencies: - call-bind-apply-helpers: "npm:^1.0.1" + call-bind-apply-helpers: "npm:^1.0.2" es-define-property: "npm:^1.0.1" es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" + es-object-atoms: "npm:^1.1.1" function-bind: "npm:^1.1.2" - get-proto: "npm:^1.0.0" + get-proto: "npm:^1.0.1" gopd: "npm:^1.2.0" has-symbols: "npm:^1.1.0" hasown: "npm:^2.0.2" math-intrinsics: "npm:^1.1.0" - checksum: 10/4f7149c9a826723f94c6d49f70bcb3df1d3f9213994fab3668f12f09fa72074681460fb29ebb6f135556ec6372992d63802386098791a8f09cfa6f27090fa67b + checksum: 10/6e9dd920ff054147b6f44cb98104330e87caafae051b6d37b13384a45ba15e71af33c3baeac7cb630a0aaa23142718dcf25b45cfdd86c184c5dcb4e56d953a10 languageName: node linkType: hard @@ -18120,7 +18130,7 @@ __metadata: "@grafana/faro-web-sdk": "npm:^1.13.2" "@grafana/faro-web-tracing": "npm:^1.13.2" "@grafana/flamegraph": "workspace:*" - "@grafana/google-sdk": "npm:0.3.2" + "@grafana/google-sdk": "npm:0.3.4" "@grafana/i18n": "workspace:*" "@grafana/lezer-logql": "npm:0.2.8" "@grafana/llm": "npm:0.22.1" @@ -18269,7 +18279,7 @@ __metadata: date-fns: "npm:4.1.0" debounce-promise: "npm:3.1.2" diff: "npm:^8.0.0" - esbuild: "npm:0.25.0" + esbuild: "npm:0.25.6" esbuild-loader: "npm:4.3.0" esbuild-plugin-browserslist: "npm:^1.0.0" eslint: "npm:9.19.0" @@ -18281,13 +18291,13 @@ __metadata: eslint-plugin-jsx-a11y: "npm:6.10.2" eslint-plugin-lodash: "npm:8.0.0" eslint-plugin-no-barrel-files: "npm:^1.1.1" - eslint-plugin-react: "npm:7.37.4" + eslint-plugin-react: "npm:7.37.5" eslint-plugin-react-hooks: "npm:5.1.0" eslint-plugin-testing-library: "npm:^7.0.0" eslint-plugin-unicorn: "npm:^56.0.0" eslint-scope: "npm:^8.1.0" eslint-webpack-plugin: "npm:4.2.0" - expose-loader: "npm:5.0.0" + expose-loader: "npm:5.0.1" fast-deep-equal: "npm:^3.1.3" fast-json-patch: "npm:3.1.1" file-saver: "npm:2.0.5" @@ -19219,22 +19229,22 @@ __metadata: linkType: hard "i18next@npm:^23.5.1 || ^24.2.0": - version: 24.2.2 - resolution: "i18next@npm:24.2.2" + version: 24.2.3 + resolution: "i18next@npm:24.2.3" dependencies: - "@babel/runtime": "npm:^7.23.2" + "@babel/runtime": "npm:^7.26.10" peerDependencies: typescript: ^5 peerDependenciesMeta: typescript: optional: true - checksum: 10/f66ed9e56d9412e59502f5df39163631daf9f1264774732fb21edbd66a528ca7a6b67dc2e2aec95683c6c7956e42c651587a54bd8ee082bd12008880ce6cd326 + checksum: 10/6c73d964f2a98b1aa2c2717fe6da66fc265bcbbc5fcd52b2bfff51ff013d30d4f7d7449c4eb7f464d27af43e2e73f2e7f1d46a144d731bd3bdb1385d4c199e4c languageName: node linkType: hard "i18next@npm:^25.0.0": - version: 25.3.1 - resolution: "i18next@npm:25.3.1" + version: 25.3.2 + resolution: "i18next@npm:25.3.2" dependencies: "@babel/runtime": "npm:^7.27.6" peerDependencies: @@ -19242,7 +19252,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/f5f38af0f7b7c0055e607d4017dade5aedd1c75c44e091473b4d01537f0849e21a7ae7f66397719a2557fc53767cf9ea96a4da34127b906d3fe5ce21db895224 + checksum: 10/fb6b2035cc8f3bcc89f56e164d22cefbefd54e5a569315b20ddcfa6e1b68c48962307181b271fea7e5ee37ddfaa90721a4a7f7814b739f24bf00a3a670b8eb93 languageName: node linkType: hard @@ -24032,14 +24042,15 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.8": - version: 1.1.8 - resolution: "object.entries@npm:1.1.8" +"object.entries@npm:^1.1.9": + version: 1.1.9 + resolution: "object.entries@npm:1.1.9" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10/2301918fbd1ee697cf6ff7cd94f060c738c0a7d92b22fd24c7c250e9b593642c9707ad2c44d339303c1439c5967d8964251cdfc855f7f6ec55db2dd79e8dc2a7 + es-object-atoms: "npm:^1.1.1" + checksum: 10/24163ab1e1e013796693fc5f5d349e8b3ac0b6a34a7edb6c17d3dd45c6a8854145780c57d302a82512c1582f63720f4b4779d6c1cfba12cbb1420b978802d8a3 languageName: node linkType: hard