diff --git a/internal/services/maintenance/client/client.go b/internal/services/maintenance/client/client.go index ae4c89f5b2dd..5b0d8697c90c 100644 --- a/internal/services/maintenance/client/client.go +++ b/internal/services/maintenance/client/client.go @@ -8,6 +8,7 @@ import ( type Client struct { ConfigurationsClient *maintenance.ConfigurationsClient ConfigurationAssignmentsClient *maintenance.ConfigurationAssignmentsClient + PublicConfigurationsClient *maintenance.PublicMaintenanceConfigurationsClient } func NewClient(o *common.ClientOptions) *Client { @@ -17,8 +18,12 @@ func NewClient(o *common.ClientOptions) *Client { configurationAssignmentsClient := maintenance.NewConfigurationAssignmentsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&configurationAssignmentsClient.Client, o.ResourceManagerAuthorizer) + publicConfigurationsClient := maintenance.NewPublicMaintenanceConfigurationsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&publicConfigurationsClient.Client, o.ResourceManagerAuthorizer) + return &Client{ ConfigurationsClient: &configurationsClient, ConfigurationAssignmentsClient: &configurationAssignmentsClient, + PublicConfigurationsClient: &publicConfigurationsClient, } } diff --git a/internal/services/maintenance/public_maintenance_configurations_data_source.go b/internal/services/maintenance/public_maintenance_configurations_data_source.go new file mode 100644 index 000000000000..9b4f02fd4a88 --- /dev/null +++ b/internal/services/maintenance/public_maintenance_configurations_data_source.go @@ -0,0 +1,222 @@ +package maintenance + +import ( + "fmt" + "time" + + "github.com/Azure/azure-sdk-for-go/services/maintenance/mgmt/2021-05-01/maintenance" + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +const recurMondayToThursday = "Monday-Thursday" +const recurFridayToSunday = "Friday-Sunday" + +func dataSourcePublicMaintenanceConfigurations() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourcePublicMaintenanceConfigurationsRead, + + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + + "location": { + Type: pluginsdk.TypeString, + Optional: true, + StateFunc: azure.NormalizeLocation, + }, + + "scope": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "All", // All is still accepted by the API + string(maintenance.ScopeExtension), + string(maintenance.ScopeHost), + string(maintenance.ScopeInGuestPatch), + string(maintenance.ScopeOSImage), + string(maintenance.ScopeSQLDB), + string(maintenance.ScopeSQLManagedInstance), + }, false), + }, + + "recur_every": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + recurMondayToThursday, + recurFridayToSunday, + }, false), + }, + + "configs": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "location": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "description": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "duration": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "maintenance_scope": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "time_zone": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "recur_every": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourcePublicMaintenanceConfigurationsRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Maintenance.PublicConfigurationsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + resp, err := client.List(ctx) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("no Public Maintenance Configurations were found") + } + return fmt.Errorf("retrieving Public Maintenance Configurations: %+v", err) + } + + filteredPublicConfigs := make([]interface{}, 0) + + recurEveryFilter := d.Get("recur_every").(string) + if recurEveryFilter == recurFridayToSunday { + recurEveryFilter = "week Friday, Saturday, Sunday" + } else if recurEveryFilter == recurMondayToThursday { + recurEveryFilter = "week Monday, Tuesday, Wednesday, Thursday" + } + + locationFilter := azure.NormalizeLocation(d.Get("location").(string)) + scopeFilter := d.Get("scope").(string) + + if resp.Value != nil { + for _, maintenanceConfig := range *resp.Value { + + var configLocation, configRecurEvery, configScope string + if maintenanceConfig.Location != nil { + configLocation = azure.NormalizeLocation(*maintenanceConfig.Location) + } + if props := maintenanceConfig.ConfigurationProperties; props != nil { + if props.Window != nil && props.Window.RecurEvery != nil { + configRecurEvery = *props.Window.RecurEvery + } + if string(props.MaintenanceScope) != "" { + configScope = string(props.MaintenanceScope) + } + } + + if locationFilter != "" && locationFilter != configLocation { + continue + } + if recurEveryFilter != "" && recurEveryFilter != configRecurEvery { + continue + } + if scopeFilter != "" && scopeFilter != configScope { + continue + } + + filteredPublicConfigs = append(filteredPublicConfigs, flattenPublicMaintenanceConfiguration(maintenanceConfig)) + } + } + + if len(filteredPublicConfigs) == 0 { + return fmt.Errorf("no Public Maintenance Configurations were found") + } + + if err := d.Set("configs", filteredPublicConfigs); err != nil { + return fmt.Errorf("setting `configs`: %+v", err) + } + + d.SetId(time.Now().UTC().String()) + return nil +} + +func flattenPublicMaintenanceConfiguration(config maintenance.Configuration) map[string]interface{} { + output := make(map[string]interface{}) + + output["name"] = "" + if config.Name != nil { + output["name"] = *config.Name + } + + output["id"] = "" + if config.ID != nil { + output["id"] = *config.ID + } + + output["location"] = "" + if config.Location != nil { + output["location"] = azure.NormalizeLocation(*config.Location) + } + + output["maintenance_scope"] = string(config.MaintenanceScope) + + var description, recurEvery, timeZone, duration string + if props := config.ConfigurationProperties; props != nil { + if props.ExtensionProperties != nil { + if configDescription, ok := props.ExtensionProperties["description"]; ok { + description = *configDescription + } + } + if props.Window != nil { + if props.Window.RecurEvery != nil { + recurEvery = *props.Window.RecurEvery + } + if props.Window.TimeZone != nil { + timeZone = *props.Window.TimeZone + } + if props.Window.Duration != nil { + duration = *props.Window.Duration + } + } + } + + output["description"] = description + output["recur_every"] = recurEvery + output["time_zone"] = timeZone + output["duration"] = duration + + return output +} diff --git a/internal/services/maintenance/public_maintenance_configurations_data_source_test.go b/internal/services/maintenance/public_maintenance_configurations_data_source_test.go new file mode 100644 index 000000000000..c8c775cf48eb --- /dev/null +++ b/internal/services/maintenance/public_maintenance_configurations_data_source_test.go @@ -0,0 +1,84 @@ +package maintenance_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" +) + +type PublicMaintenanceConfigurationsDataSource struct{} + +func TestAccDataSourcePublicMaintenanceConfigurations_noFilters(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_public_maintenance_configurations", "test") + r := PublicMaintenanceConfigurationsDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.noFilters(), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("configs.30.name").Exists(), + ), + }, + }) +} + +func TestAccDataSourcePublicMaintenanceConfigurations_allFilters(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_public_maintenance_configurations", "test") + r := PublicMaintenanceConfigurationsDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.allFilters(), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("configs.#").HasValue("1"), + check.That(data.ResourceName).Key("configs.0.maintenance_scope").HasValue("SQLManagedInstance"), + check.That(data.ResourceName).Key("configs.0.name").HasValue("SQL_WestEurope_MI_1"), + check.That(data.ResourceName).Key("configs.0.recur_every").HasValue("week Monday, Tuesday, Wednesday, Thursday"), + ), + }, + }) +} + +func TestAccDataSourcePublicMaintenanceConfigurations_recurEvery(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_public_maintenance_configurations", "test") + r := PublicMaintenanceConfigurationsDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.recurEvery(), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("configs.0.maintenance_scope").HasValue("SQLManagedInstance"), + check.That(data.ResourceName).Key("configs.0.recur_every").HasValue("week Friday, Saturday, Sunday"), + ), + }, + }) +} + +func (PublicMaintenanceConfigurationsDataSource) allFilters() string { + return fmt.Sprintf(` +data "azurerm_public_maintenance_configurations" "test" { + location = "West Europe" + scope = "SQLManagedInstance" + recur_every = "Monday-Thursday" +} +`) +} + +func (PublicMaintenanceConfigurationsDataSource) noFilters() string { + return fmt.Sprintf(` +data "azurerm_public_maintenance_configurations" "test" { + +} +`) +} + +func (PublicMaintenanceConfigurationsDataSource) recurEvery() string { + return fmt.Sprintf(` +data "azurerm_public_maintenance_configurations" "test" { + scope = "SQLManagedInstance" + recur_every = "Friday-Sunday" +} +`) +} diff --git a/internal/services/maintenance/registration.go b/internal/services/maintenance/registration.go index f73b3cf04a82..0bf99ffb28aa 100644 --- a/internal/services/maintenance/registration.go +++ b/internal/services/maintenance/registration.go @@ -25,7 +25,8 @@ func (r Registration) WebsiteCategories() []string { func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { return map[string]*pluginsdk.Resource{ - "azurerm_maintenance_configuration": dataSourceMaintenanceConfiguration(), + "azurerm_maintenance_configuration": dataSourceMaintenanceConfiguration(), + "azurerm_public_maintenance_configurations": dataSourcePublicMaintenanceConfigurations(), } } diff --git a/website/docs/d/public_maintenance_configurations.html.markdown b/website/docs/d/public_maintenance_configurations.html.markdown new file mode 100644 index 000000000000..71e4d6c556a4 --- /dev/null +++ b/website/docs/d/public_maintenance_configurations.html.markdown @@ -0,0 +1,65 @@ +--- +subcategory: "Maintenance" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_public_maintenance_configurations" +description: |- + Get information about existing Public Maintenance Configurations. +--- + +# Data Source: azurerm_public_maintenance_configurations + +Use this data source to access information about existing Public Maintenance Configurations. + +## Example Usage + +```hcl +data "azurerm_public_maintenance_configurations" "existing" { + location = "West Europe" + scope = "SQLManagedInstance" + recur_every = "Monday-Thursday" +} + +output "name" { + value = data.azurerm_public_maintenance_configurations.existing.configs[0].name +} +``` + +## Argument Reference + +* `location` - The Azure location to filter the list of Public Maintenance Configurations against. + +* `scope` - The scope to filter the list of Public Maintenance Configurations against. Possible values are `All`, `Extension`, `Host`, `InGuestPatch`, `OSImage`, `SQLDB` and `SQLManagedInstance`. + +* `recur_every` - The recurring window to filter the list of Public Maintenance Configurations against. Possible values are `Monday-Thursday` and `Friday-Sunday` + +## Attributes Reference + +* `configs` - A `configs` block as defined below. + +--- + +A `configs` block exports the following: + +* `name` - The name of the Public Maintenance Configuration. + +* `id` - The id of the Public Maintenance Configuration. + +* `location` - The Azure location of the Public Maintenance Configuration. + +* `description` - A description of the Public Maintenance Configuration. + +* `duration` - The duration of the Public Maintenance Configuration window. + +* `maintenance_scope` - The scope of the Public Maintenance Configuration. + +* `time_zone` - The time zone for the maintenance window. + +* `recur_every` - The rate at which a maintenance window is expected to recur. + +--- + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the Public Maintenance Configuration. diff --git a/website/docs/r/disk_sas_token.html.markdown b/website/docs/r/disk_sas_token.html.markdown index 6c005399f09f..b685a0624348 100644 --- a/website/docs/r/disk_sas_token.html.markdown +++ b/website/docs/r/disk_sas_token.html.markdown @@ -75,4 +75,4 @@ Disk SAS Token can be imported using the `resource id`, e.g. ```shell terraform import azurerm_managed_disk_sas_token.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/microsoft.compute/disks/manageddisk1 -``` \ No newline at end of file +```