diff --git a/public/app/plugins/datasource/azuremonitor/azureMetadata/resourceTypes.ts b/public/app/plugins/datasource/azuremonitor/azureMetadata/resourceTypes.ts index 8f93f887b8a..15c86068c4b 100644 --- a/public/app/plugins/datasource/azuremonitor/azureMetadata/resourceTypes.ts +++ b/public/app/plugins/datasource/azuremonitor/azureMetadata/resourceTypes.ts @@ -14,13 +14,13 @@ To programatically get the list, execute in the browser console: Note: Validate that the output makes sense, the format of the page may change. */ export const resourceTypeDisplayNames: { [k: string]: string } = { - 'microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers/protecteditems': 'Backup Items', - 'microsoft.resources/subscriptions': 'Subscriptions', - 'microsoft.resources/subscriptions/resourcegroups': 'Resource groups', + '84codes.cloudamqp/servers': 'CloudAMQP', 'citrix.services/xenappessentials': 'Citrix Virtual Apps Essentials', 'citrix.services/xendesktopessentials': 'Citrix Virtual Desktops Essentials', 'dynatrace.observability/monitors': 'Dynatrace', 'github.enterprise/accounts': 'GitHub AE', + 'livearena.broadcast/services': 'LiveArena Broadcast', + 'mailjet.email/services': 'Mailjet Email Service', 'microsoft.aad/domainservices': 'Azure AD Domain Services', 'microsoft.aadiam/privatelinkforazuread': 'Private Link for Azure AD', 'microsoft.agfoodplatform/farmbeats': 'Azure FarmBeats', @@ -43,6 +43,7 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'microsoft.azurearcdata/sqlserverinstances': 'SQL Server - Azure Arc', 'microsoft.azuredata/sqlserverregistrations': 'SQL Server registries', 'microsoft.azurepercept/accounts': 'Azure Percept accounts', + 'microsoft.azurestack/registrations': 'Azure Stack Hubs', 'microsoft.azurestackhci/clusters': 'Azure Stack HCI', 'microsoft.azurestackhci/virtualmachines': 'Azure Stack HCI virtual machine - Azure Arc', 'microsoft.baremetal/crayservers': 'Cray Servers', @@ -50,11 +51,13 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'microsoft.baremetalinfrastructure/baremetalinstances': 'BareMetal Instances', 'microsoft.batch/batchaccounts': 'Batch accounts', 'microsoft.bing/accounts': 'Bing Resources', + 'microsoft.blockchain/blockchainmembers': 'Azure Blockchain Service', + 'microsoft.blockchain/cordamembers': 'Corda', 'microsoft.botservice/botservices': 'Bot Services', 'microsoft.cache/redis': 'Azure Cache for Redis', 'microsoft.cache/redisenterprise': 'Redis Enterprise', 'microsoft.cdn/cdnwebapplicationfirewallpolicies': 'Content Delivery Network WAF policies', - 'microsoft.cdn/profiles (front doors standard/premium': 'Preview)', + 'microsoft.cdn/profiles': '(front doors standard/premium Preview)', 'microsoft.cdn/profiles/afdendpoints': 'Endpoints', 'microsoft.cdn/profiles/endpoints': 'Endpoints', 'microsoft.certificateregistration/certificateorders': 'App Service Certificates', @@ -70,6 +73,7 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'microsoft.cloudtest/hostedpools': '1ES Hosted Pools', 'microsoft.cloudtest/images': 'CloudTest Images', 'microsoft.cloudtest/pools': 'CloudTest Pools', + 'microsoft.cognition/syntheticsaccounts': 'Synthetics Accounts', 'microsoft.clusterstor/nodes': 'ClusterStors', 'microsoft.cognitiveservices/accounts': 'Cognitive Services', 'microsoft.compute/availabilitysets': 'Availability sets', @@ -195,12 +199,17 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'microsoft.insights/webtests': 'Availability tests', 'microsoft.insights/workbooks': 'Azure Workbooks', 'microsoft.insights/workbooktemplates': 'Azure Workbook Templates', + 'microsoft.intelligentitdigitaltwin/digitaltwins': 'Minervas', + 'microsoft.intelligentitdigitaltwin/digitaltwins/assets': 'Assets', + 'microsoft.intelligentitdigitaltwin/digitaltwins/executionplans': 'Deployments', + 'microsoft.intelligentitdigitaltwin/digitaltwins/testplans': 'Suites', + 'microsoft.intelligentitdigitaltwin/digitaltwins/tests': 'Scripts', 'microsoft.iotcentral/iotapps': 'IoT Central Applications', 'microsoft.keyvault/vaults': 'Key vaults', 'microsoft.kubernetes/connectedclusters': 'Kubernetes - Azure Arc', 'microsoft.kusto/clusters': 'Azure Data Explorer Clusters', 'microsoft.kusto/clusters/databases': 'Azure Data Explorer Databases', - 'microsoft.labservices/labaccounts': 'Lab accounts', + 'microsoft.labservices/labaccounts': 'Lab Services', 'microsoft.labservices/labplans': 'Lab plans', 'microsoft.labservices/labs': 'Labs', 'microsoft.loadtestservice/loadtests': 'Azure Load Testing', @@ -221,11 +230,13 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'microsoft.managedidentity/userassignedidentities': 'Managed Identities', 'microsoft.maps/accounts': 'Azure Maps Accounts', 'microsoft.maps/accounts/creators': 'Azure Maps Creator Resources', + 'microsoft.marketplaceapps/classicdevservices': 'Classic Dev Services', 'microsoft.media/mediaservices': 'Media Services', 'microsoft.media/mediaservices/liveevents': 'Live events', 'microsoft.media/mediaservices/streamingendpoints': 'Streaming Endpoints', 'microsoft.media/videoanalyzers': 'Video Analyzers', 'microsoft.migrate/projects': 'Migration projects', + 'microsoft.mixedreality/holographicsbroadcastaccounts': 'Holographics Broadcast Accounts', 'microsoft.mixedreality/objectanchorsaccounts': 'Object Anchors Accounts', 'microsoft.mixedreality/objectunderstandingaccounts': 'Object Understanding Accounts', 'microsoft.mixedreality/remoterenderingaccounts': 'Remote Rendering Accounts', @@ -286,7 +297,7 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'microsoft.network/virtualwans': 'Virtual WANs', 'microsoft.notificationhubs/namespaces': 'Notification Hub Namespaces', 'microsoft.notificationhubs/namespaces/notificationhubs': 'Notification Hubs', - 'microsoft.openenergyplatform/energyservices': 'Project Oak Forest', + 'microsoft.openenergyplatform/energyservices': 'Azure OpenEnergy', 'microsoft.openlogisticsplatform/workspaces': 'Open Supply Chain Platform', 'microsoft.operationalinsights/querypacks': 'Log Analytics query packs', 'microsoft.operationalinsights/workspaces': 'Log Analytics workspaces', @@ -298,28 +309,34 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'microsoft.orbital/spacecrafts': 'Spacecrafts', 'microsoft.peering/peerings': 'Peerings', 'microsoft.peering/peeringservices': 'Peering Services', - 'microsoft.playfab/playeraccountpools': 'PlayFab player account pools', + 'microsoft.playfab/playeraccountpools': 'Player account pools', 'microsoft.playfab/titles': 'PlayFab titles', 'microsoft.portal/dashboards': 'Shared dashboards', 'microsoft.powerbidedicated/capacities': 'Power BI Embedded', - 'microsoft.purview/accounts': 'Microsoft Purview accounts', + 'microsoft.purview/accounts': 'Purview accounts', 'microsoft.quantum/workspaces': 'Quantum Workspaces', 'microsoft.recommendationsservice/accounts': 'Intelligent Recommendations Accounts', 'microsoft.recommendationsservice/accounts/modeling': 'Modeling', 'microsoft.recommendationsservice/accounts/serviceendpoints': 'Service Endpoints', 'microsoft.recoveryservices/vaults': 'Recovery Services vaults', + 'microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers/protecteditems': 'Backup Items', 'microsoft.redhatopenshift/openshiftclusters': 'Azure Red Hat OpenShift', 'microsoft.relay/namespaces': 'Relays', 'microsoft.resourceconnector/appliances': 'Resource bridges', 'microsoft.resourcegraph/queries': 'Resource Graph queries', 'microsoft.resources/deploymentscripts': 'Deployment Scripts', + 'microsoft.resources/subscriptions': 'Subscriptions', + 'microsoft.resources/subscriptions/resourcegroups': 'Resource groups', 'microsoft.resources/templatespecs': 'Template specs', 'microsoft.saas/applications': 'Software as a Service (classic)', 'microsoft.saas/resources': 'SaaS', + 'microsoft.scheduler/jobcollections': 'Scheduler Job Collections', 'microsoft.scom/managedinstances': 'Aquila Instances', 'microsoft.scvmm/virtualmachines': 'SCVMM virtual machine - Azure Arc', 'microsoft.scvmm/vmmservers': 'SCVMM management servers', 'microsoft.search/searchservices': 'Search services', + 'microsoft.security/insights/classification': 'Data Sensitivity Security Insights (Preview)', + 'microsoft.security/locations/alerts': 'Security Alerts', 'microsoft.securitydetonation/chambers': 'Security Detonation Chambers', 'microsoft.servicebus/namespaces': 'Service Bus Namespaces', 'microsoft.servicefabric/clusters': 'Service Fabric clusters', @@ -385,7 +402,13 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'microsoft.workloads/sapvirtualinstances/centralinstances': 'SAP central server instances', 'microsoft.workloads/sapvirtualinstances/databaseinstances': 'SAP database server instances', 'nginx.nginxplus/nginxdeployments': 'NGINX Deployment', - 'providers.test/statefulibizaengines': 'VLCentral Help', + 'paraleap.cloudmonix/services': 'CloudMonix', + 'pokitdok.platform/services': 'PokitDok Platform', + 'providers.test/statefulibizaengines': 'My Resources', + 'ravenhq.db/databases': 'RavenHQ', + 'raygun.crashreporting/apps': 'Raygun', + 'sendgrid.email/accounts': 'SendGrid Accounts', + 'trendmicro.deepsecurity/accounts': 'Deep Security SaaS', 'wandisco.fusion/fusiongroups': 'LiveData Planes', 'wandisco.fusion/fusiongroups/azurezones': 'Azure Zones', 'wandisco.fusion/fusiongroups/azurezones/plugins': 'Plugins', @@ -399,8 +422,6 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { 'wandisco.fusion/migrators/metadatatargets': 'Metadata Targets', 'wandisco.fusion/migrators/pathmappings': 'Path Mappings', 'wandisco.fusion/migrators/targets': 'Targets', - 'microsoft.security/insights/classification': 'Data Sensitivity Security Insights (Preview)', - 'microsoft.security/locations/alerts': 'Security Alerts', }; // This list has been manually written using the Azure Portal as the source. @@ -408,10 +429,14 @@ export const resourceTypeDisplayNames: { [k: string]: string } = { // and go to Select a scope > Resource types > Multi-resource compatible (preview) export const multiResourceCompatibleTypes: { [ns: string]: boolean } = { 'microsoft.cache/redis': true, // 'Azure Cache for Redis' + 'microsoft.documentdb/mongoclusters': true, // 'Azure Cosmos DB for MongoDB' 'microsoft.dbforpostgresql/flexibleservers': true, // 'Azure Database for PostgreSQL flexible servers' 'microsoft.storagecache/amlfilesystems': true, // 'Lustre File Systems' + 'microsoft.monitor/accounts': true, // Azure Monitor Workspaces 'microsoft.databoxedge/databoxedgedevices': true, // 'Azure Stack Edge / Data Box Gateway' + 'microsoft.azurestackhci/clusters': true, // 'Azure Stack HCI' 'microsoft.dataprotection/backupvaults': true, // 'Backup vaults' + 'microsoft.networkcloud/baremetalmachines': true, // 'Bare Metal Machines' 'microsoft.netapp/netappaccounts/capacitypools': true, // 'Capacity pools' 'microsoft.netapp/netappaccounts/capacitypools/volumes': true, // 'Capacity pool volumes' 'microsoft.network/networkwatchers/connectionmonitors': true, // 'Connection Monitors' @@ -430,6 +455,7 @@ export const resourceTypes = [ 'microsoft.analysisservices/servers', 'microsoft.apimanagement/service', 'microsoft.app/containerapps', + 'microsoft.app/jobs', 'microsoft.app/managedenvironments', 'microsoft.appconfiguration/configurationstores', 'microsoft.appplatform/spring', @@ -498,13 +524,16 @@ export const resourceTypes = [ 'microsoft.dbforpostgresql/servergroupsv2', 'microsoft.dbforpostgresql/servers', 'microsoft.dbforpostgresql/serversv2', + 'microsoft.devcenter/devcenters', 'microsoft.devices/iothubs', 'microsoft.devices/provisioningservices', + 'microsoft.devopsinfrastructure/pools', 'microsoft.digitaltwins/digitaltwinsinstances', 'microsoft.documentdb/cassandraclusters', 'microsoft.documentdb/databaseaccounts', 'microsoft.documentdb/mongoclusters', 'microsoft.edgezones/edgezones', + 'microsoft.elasticsan/elasticsans', 'microsoft.enterpriseknowledgegraph/services', 'microsoft.eventgrid/domains', 'microsoft.eventgrid/eventsubscriptions', @@ -528,6 +557,7 @@ export const resourceTypes = [ 'microsoft.hybridnetwork/virtualnetworkfunctions', 'microsoft.insights/autoscalesettings', 'microsoft.insights/components', + 'microsoft.insights/datacollectionrules', 'microsoft.iotcentral/iotapps', 'microsoft.iotspaces/graph', 'microsoft.keyvault/managedhsms', @@ -548,10 +578,13 @@ export const resourceTypes = [ 'microsoft.media/mediaservices/liveevents', 'microsoft.media/mediaservices/streamingendpoints', 'microsoft.media/videoanalyzers', + 'microsoft.messagingconnectors/connectors', 'microsoft.mixedreality/remoterenderingaccounts', 'microsoft.mixedreality/spatialanchorsaccounts', + 'microsoft.mobilenetwork/mobilenetworks/sites', 'microsoft.mobilenetwork/packetcorecontrolplanes', 'microsoft.mobilenetwork/packetcorecontrolplanes/packetcoredataplanes', + 'microsoft.mobilenetwork/radioaccessnetworks', 'microsoft.monitor/accounts', 'microsoft.netapp/netappaccounts/capacitypools', 'microsoft.netapp/netappaccounts/capacitypools/volumes', @@ -560,6 +593,7 @@ export const resourceTypes = [ 'microsoft.network/bastionhosts', 'microsoft.network/connections', 'microsoft.network/dnsforwardingrulesets', + 'microsoft.network/dnsresolverpolicies', 'microsoft.network/dnsresolvers', 'microsoft.network/dnszones', 'microsoft.network/expressroutecircuits', @@ -588,6 +622,7 @@ export const resourceTypes = [ 'microsoft.network/vpngateways', 'microsoft.networkanalytics/dataconnectors', 'microsoft.networkcloud/baremetalmachines', + 'microsoft.networkcloud/clustermanagers', 'microsoft.networkcloud/clusters', 'microsoft.networkcloud/storageappliances', 'microsoft.networkfunction/azuretrafficcollectors', @@ -621,6 +656,7 @@ export const resourceTypes = [ 'microsoft.sql/servers/databases', 'microsoft.sql/servers/elasticpools', 'microsoft.sql/servers/jobagents', + 'microsoft.storageactions/storagetasks', 'microsoft.storage/storageaccounts', 'microsoft.storage/storageaccounts/blobservices', 'microsoft.storage/storageaccounts/fileservices', @@ -653,6 +689,9 @@ export const resourceTypes = [ 'microsoft.web/sites/slots', 'microsoft.web/staticsites', 'nginx.nginxplus/nginxdeployments', + 'oracle.database/oracle.database/autonomousdatabases', + 'oracle.database/oracle.database/cloudvmclusters', + 'private.messagingconnectors/private.messagingconnectors/connectors', 'wandisco.fusion/migrators', 'wandisco.fusion/migrators/datatransferagents', 'wandisco.fusion/migrators/livedatamigrations', diff --git a/public/app/plugins/datasource/azuremonitor/components/ResourcePicker/ResourcePicker.test.tsx b/public/app/plugins/datasource/azuremonitor/components/ResourcePicker/ResourcePicker.test.tsx index 63559579ef8..afa79bf94a1 100644 --- a/public/app/plugins/datasource/azuremonitor/components/ResourcePicker/ResourcePicker.test.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/ResourcePicker/ResourcePicker.test.tsx @@ -332,8 +332,9 @@ describe('AzureMonitor ResourcePicker', () => { expect(subscriptionCheckboxAfterClear).toBeInTheDocument(); }); - it('should throw an error if no namespaces are found', async () => { + it('should not throw an error if no namespaces are found - fallback used', async () => { const resourcePickerData = createMockResourcePickerData(['getResourceGroupsBySubscriptionId']); + resourcePickerData.postResource = jest.fn().mockResolvedValueOnce({ data: [] }); render( { ); const subscriptionExpand = await screen.findByLabelText('Expand Primary Subscription'); await userEvent.click(subscriptionExpand); - const error = await screen.findByRole('alert'); - expect(error).toHaveTextContent('An error occurred while requesting resources from Azure Monitor'); - expect(error).toHaveTextContent( - 'Unable to resolve a list of valid metric namespaces. Validate the datasource configuration is correct and required permissions have been granted for all subscriptions. Grafana requires at least the Reader role to be assigned.' - ); + const error = await screen.queryByRole('alert'); + expect(error).toBeNull(); }); it('display a row for a selected resource even if it is not part of the current rows', async () => { diff --git a/public/app/plugins/datasource/azuremonitor/resourcePicker/resourcePickerData.test.ts b/public/app/plugins/datasource/azuremonitor/resourcePicker/resourcePickerData.test.ts index 85cdc304c37..c8a99a18ff9 100644 --- a/public/app/plugins/datasource/azuremonitor/resourcePicker/resourcePickerData.test.ts +++ b/public/app/plugins/datasource/azuremonitor/resourcePicker/resourcePickerData.test.ts @@ -5,6 +5,7 @@ import { } from '../__mocks__/argResourcePickerResponse'; import createMockDatasource from '../__mocks__/datasource'; import { createMockInstanceSetttings } from '../__mocks__/instanceSettings'; +import { resourceTypes } from '../azureMetadata'; import { ResourceRowType } from '../components/ResourcePicker/types'; import { AzureGraphResponse } from '../types'; @@ -19,12 +20,14 @@ jest.mock('@grafana/runtime', () => ({ }), })); -const createResourcePickerData = (responses: AzureGraphResponse[]) => { +const createResourcePickerData = (responses: AzureGraphResponse[], noNamespaces?: boolean) => { const instanceSettings = createMockInstanceSetttings(); const mockDatasource = createMockDatasource(); mockDatasource.azureMonitorDatasource.getMetricNamespaces = jest .fn() - .mockResolvedValueOnce([{ text: 'Microsoft.Storage/storageAccounts', value: 'Microsoft.Storage/storageAccounts' }]); + .mockResolvedValueOnce( + noNamespaces ? [] : [{ text: 'Microsoft.Storage/storageAccounts', value: 'Microsoft.Storage/storageAccounts' }] + ); const resourcePickerData = new ResourcePickerData(instanceSettings, mockDatasource.azureMonitorDatasource); const postResource = jest.fn(); responses.forEach((res) => { @@ -354,6 +357,53 @@ describe('AzureMonitor resourcePickerData', () => { uri: '/subscriptions/subId/resourceGroups/rgName/providers/Microsoft.Compute/virtualMachines/vmname', }); }); + it('metrics searches - fallback namespaces', async () => { + const mockSubscriptionsResponse = createMockARGSubscriptionResponse(); + + const mockResponse = { + data: [ + { + id: '/subscriptions/subId/resourceGroups/rgName/providers/Microsoft.Compute/virtualMachines/vmname', + name: 'vmName', + type: 'microsoft.compute/virtualmachines', + resourceGroup: 'rgName', + subscriptionId: 'subId', + location: 'northeurope', + }, + ], + }; + const { resourcePickerData, postResource, mockDatasource } = createResourcePickerData( + [mockSubscriptionsResponse, mockResponse], + true + ); + await resourcePickerData.search('vmname', 'metrics'); + expect(postResource).toHaveBeenCalledTimes(2); + expect(mockDatasource.azureMonitorDatasource.getMetricNamespaces).toHaveBeenCalledWith( + { + resourceUri: '/subscriptions/1', + }, + false, + 'westeurope' + ); + expect(mockDatasource.azureMonitorDatasource.getMetricNamespaces).toHaveBeenCalledWith( + { + resourceUri: '/subscriptions/1', + }, + false, + 'eastus' + ); + expect(mockDatasource.azureMonitorDatasource.getMetricNamespaces).toHaveBeenCalledWith( + { + resourceUri: '/subscriptions/1', + }, + false, + 'japaneast' + ); + const secondCall = postResource.mock.calls[1]; + const [_, postBody] = secondCall; + const namespaces = (postBody.query as string).match(/\((.*?)\)/)?.[0].split(','); + expect(namespaces?.length).toEqual(resourceTypes.length); + }); it('makes requests for logs searches', async () => { const mockResponse = { data: [ diff --git a/public/app/plugins/datasource/azuremonitor/resourcePicker/resourcePickerData.ts b/public/app/plugins/datasource/azuremonitor/resourcePicker/resourcePickerData.ts index 80282cb71a7..b3b6b73b171 100644 --- a/public/app/plugins/datasource/azuremonitor/resourcePicker/resourcePickerData.ts +++ b/public/app/plugins/datasource/azuremonitor/resourcePicker/resourcePickerData.ts @@ -363,6 +363,11 @@ export default class ResourcePickerData extends DataSourceWithBackend = new Set(); + // Include a predefined set of metric namespaces as a fallback in the case the user cannot query subscriptions + resourceTypes.forEach((namespace) => { + supportedMetricNamespaces.add(`"${namespace}"`); + }); + // We make use of these three regions as they *should* contain every possible namespace const regions = ['westeurope', 'eastus', 'japaneast']; const getNamespacesForRegion = async (region: string) => { @@ -390,10 +395,6 @@ export default class ResourcePickerData extends DataSourceWithBackend { - supportedMetricNamespaces.add(`"${namespace}"`); - }); - this.supportedMetricNamespaces = Array.from(supportedMetricNamespaces).join(','); }