diff --git a/.teamcity/components/settings.kt b/.teamcity/components/settings.kt index f7bec51fa917..094dcd5ccc34 100644 --- a/.teamcity/components/settings.kt +++ b/.teamcity/components/settings.kt @@ -59,7 +59,10 @@ var serviceTestConfigurationOverrides = mapOf( // Custom Providers is only available in certain locations "customproviders" to testConfiguration(locationOverride = LocationConfiguration("eastus", "westus2", "westeurope", true)), - // Datadog is available only in WestUS2 region + // Dashboard is only available in certain locations + "dashboard" to testConfiguration(locationOverride = LocationConfiguration("westeurope", "westus2", "eastus2", false)), + + // Datadog is available only in WestUS2 region "datadog" to testConfiguration(locationOverride = LocationConfiguration("westus2", "westus2", "centraluseuap", false)), // data factory uses NC class VMs which are not available in eastus2 diff --git a/internal/services/dashboard/dashboard_grafana_resource.go b/internal/services/dashboard/dashboard_grafana_resource.go index 592acceab246..6a96feada8ed 100644 --- a/internal/services/dashboard/dashboard_grafana_resource.go +++ b/internal/services/dashboard/dashboard_grafana_resource.go @@ -23,6 +23,7 @@ type DashboardGrafanaModel struct { ApiKeyEnabled bool `tfschema:"api_key_enabled"` AutoGeneratedDomainNameLabelScope grafanaresource.AutoGeneratedDomainNameLabelScope `tfschema:"auto_generated_domain_name_label_scope"` DeterministicOutboundIPEnabled bool `tfschema:"deterministic_outbound_ip_enabled"` + GrafanaIntegrations []GrafanaIntegrationsModel `tfschema:"grafana_integrations"` Location string `tfschema:"location"` PublicNetworkAccessEnabled bool `tfschema:"public_network_access_enabled"` Sku string `tfschema:"sku"` @@ -33,6 +34,14 @@ type DashboardGrafanaModel struct { OutboundIPs []string `tfschema:"outbound_ip"` } +type GrafanaIntegrationsModel struct { + AzureMonitorWorkspaceIntegrations []AzureMonitorWorkspaceIntegrationModel `tfschema:"azure_monitor_workspace_integrations"` +} + +type AzureMonitorWorkspaceIntegrationModel struct { + AzureMonitorWorkspaceResourceId string `tfschema:"azure_monitor_workspace_resource_id"` +} + type DashboardGrafanaResource struct{} var _ sdk.ResourceWithUpdate = DashboardGrafanaResource{} @@ -86,6 +95,30 @@ func (r DashboardGrafanaResource) Arguments() map[string]*pluginsdk.Schema { Default: false, }, + "grafana_integrations": { + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "azure_monitor_workspace_integrations": { + Type: pluginsdk.TypeList, + Required: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "azure_monitor_workspace_resource_id": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + }, + }, + }, + }, + "identity": commonschema.SystemAssignedIdentityOptionalForceNew(), "public_network_access_enabled": { @@ -187,6 +220,7 @@ func (r DashboardGrafanaResource) Create() sdk.ResourceFunc { ApiKey: &apiKey, AutoGeneratedDomainNameLabelScope: &model.AutoGeneratedDomainNameLabelScope, DeterministicOutboundIP: &deterministicOutboundIP, + GrafanaIntegrations: expandGrafanaIntegrationsModel(model.GrafanaIntegrations), PublicNetworkAccess: &publicNetworkAccess, ZoneRedundancy: &zoneRedundancy, }, @@ -254,6 +288,10 @@ func (r DashboardGrafanaResource) Update() sdk.ResourceFunc { properties.Properties.DeterministicOutboundIP = &deterministicOutboundIP } + if metadata.ResourceData.HasChange("grafana_integrations") { + properties.Properties.GrafanaIntegrations = expandGrafanaIntegrationsModel(model.GrafanaIntegrations) + } + if metadata.ResourceData.HasChange("public_network_access_enabled") { publicNetworkAccess := grafanaresource.PublicNetworkAccessDisabled if model.PublicNetworkAccessEnabled { @@ -340,6 +378,8 @@ func (r DashboardGrafanaResource) Read() sdk.ResourceFunc { state.Endpoint = *properties.Endpoint } + state.GrafanaIntegrations = flattenGrafanaIntegrationsModel(properties.GrafanaIntegrations) + if properties.GrafanaVersion != nil { state.GrafanaVersion = *properties.GrafanaVersion } @@ -398,6 +438,33 @@ func (r DashboardGrafanaResource) Delete() sdk.ResourceFunc { } } +func expandGrafanaIntegrationsModel(inputList []GrafanaIntegrationsModel) *grafanaresource.GrafanaIntegrations { + if len(inputList) == 0 { + return nil + } + + input := &inputList[0] + output := grafanaresource.GrafanaIntegrations{ + AzureMonitorWorkspaceIntegrations: expandAzureMonitorWorkspaceIntegrationModelArray(input.AzureMonitorWorkspaceIntegrations), + } + + return &output +} + +func expandAzureMonitorWorkspaceIntegrationModelArray(inputList []AzureMonitorWorkspaceIntegrationModel) *[]grafanaresource.AzureMonitorWorkspaceIntegration { + var outputList []grafanaresource.AzureMonitorWorkspaceIntegration + for _, v := range inputList { + input := v + output := grafanaresource.AzureMonitorWorkspaceIntegration{ + AzureMonitorWorkspaceResourceId: &input.AzureMonitorWorkspaceResourceId, + } + + outputList = append(outputList, output) + } + + return &outputList +} + func expandLegacySystemAndUserAssignedMap(input []interface{}) *identity.LegacySystemAndUserAssignedMap { identityValue, err := identity.ExpandSystemAssigned(input) if err != nil { @@ -409,6 +476,38 @@ func expandLegacySystemAndUserAssignedMap(input []interface{}) *identity.LegacyS } } +func flattenGrafanaIntegrationsModel(input *grafanaresource.GrafanaIntegrations) []GrafanaIntegrationsModel { + var outputList []GrafanaIntegrationsModel + if input == nil { + return outputList + } + + output := GrafanaIntegrationsModel{ + AzureMonitorWorkspaceIntegrations: flattenAzureMonitorWorkspaceIntegrationModelArray(input.AzureMonitorWorkspaceIntegrations), + } + + return append(outputList, output) +} + +func flattenAzureMonitorWorkspaceIntegrationModelArray(inputList *[]grafanaresource.AzureMonitorWorkspaceIntegration) []AzureMonitorWorkspaceIntegrationModel { + var outputList []AzureMonitorWorkspaceIntegrationModel + if inputList == nil { + return outputList + } + + for _, input := range *inputList { + output := AzureMonitorWorkspaceIntegrationModel{} + + if input.AzureMonitorWorkspaceResourceId != nil { + output.AzureMonitorWorkspaceResourceId = *input.AzureMonitorWorkspaceResourceId + } + + outputList = append(outputList, output) + } + + return outputList +} + func flattenLegacySystemAndUserAssignedMap(input *identity.LegacySystemAndUserAssignedMap) *[]interface{} { if input == nil { return &[]interface{}{} diff --git a/internal/services/dashboard/dashboard_grafana_resource_test.go b/internal/services/dashboard/dashboard_grafana_resource_test.go index f9aa694a56b3..f72449ba5ffe 100644 --- a/internal/services/dashboard/dashboard_grafana_resource_test.go +++ b/internal/services/dashboard/dashboard_grafana_resource_test.go @@ -138,10 +138,10 @@ resource "azurerm_dashboard_grafana" "import" { func (r DashboardGrafanaResource) complete(data acceptance.TestData) string { template := r.template(data) return fmt.Sprintf(` - %s + %[1]s resource "azurerm_dashboard_grafana" "test" { - name = "a-dg-%d" + name = "a-dg-%[2]d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location api_key_enabled = true @@ -152,6 +152,12 @@ resource "azurerm_dashboard_grafana" "test" { type = "SystemAssigned" } + grafana_integrations { + azure_monitor_workspace_integrations { + azure_monitor_workspace_resource_id = "${azurerm_resource_group.test.id}/providers/microsoft.monitor/accounts/a-mwr-%[2]d" + } + } + tags = { key = "value" } @@ -173,6 +179,16 @@ resource "azurerm_dashboard_grafana" "test" { type = "SystemAssigned" } + grafana_integrations { + azure_monitor_workspace_integrations { + azure_monitor_workspace_resource_id = "${azurerm_resource_group.test.id}/providers/microsoft.monitor/accounts/a-mwr-%[2]d" + } + + azure_monitor_workspace_integrations { + azure_monitor_workspace_resource_id = "${azurerm_resource_group.test.id}/providers/microsoft.monitor/accounts/a-mwr-%[2]d-2" + } + } + tags = { key2 = "value2" } diff --git a/website/docs/r/dashboard_grafana.html.markdown b/website/docs/r/dashboard_grafana.html.markdown index 2449d3eb26bd..935b30ecc106 100644 --- a/website/docs/r/dashboard_grafana.html.markdown +++ b/website/docs/r/dashboard_grafana.html.markdown @@ -52,6 +52,8 @@ The following arguments are supported: * `deterministic_outbound_ip_enabled` - (Optional) Whether to enable the Grafana instance to use deterministic outbound IPs. Defaults to `false`. +* `grafana_integrations` - (Optional) A `grafana_integrations` block as defined below. + * `identity` - (Optional) An `identity` block as defined below. Changing this forces a new Dashboard Grafana to be created. * `public_network_access_enabled` - (Optional) Whether to enable traffic over the public interface. Defaults to `true`. @@ -64,6 +66,18 @@ The following arguments are supported: --- +A `grafana_integrations` block supports the following: + +* `azure_monitor_workspace_integrations` - (Required) An `azure_monitor_workspace_integrations` block as defined below. + +--- + +An `azure_monitor_workspace_integrations` block supports the following: + +* `azure_monitor_workspace_resource_id` - (Required) Specifies the resource ID of the connected Azure Monitor Workspace. + +--- + An `identity` block supports the following: * `type` - (Required) Specifies the type of Managed Service Identity. The only possible values is `SystemAssigned`. Changing this forces a new resource to be created.