Skip to content

Commit

Permalink
New Resource: azurerm_automation_software_update_configuration (#17902
Browse files Browse the repository at this point in the history
)

Co-authored-by: xuwu1 <[email protected]>
  • Loading branch information
wuxu92 and wuxu92 authored Sep 22, 2022
1 parent 3ed55f3 commit 85899b4
Show file tree
Hide file tree
Showing 12 changed files with 1,743 additions and 1 deletion.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
package automation_test

import (
"context"
"fmt"
"testing"
"time"

"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type SoftwareUpdateConfigurationResource struct {
startTime string
expireTime string
}

func newSoftwareUpdateConfigurationResource() SoftwareUpdateConfigurationResource {
// The start time of the schedule must be at least 5 minutes after the time you create the schedule,
// so we cannot hardcode the time string.
// we use timezone as UTC so the time string should be in UTC format
ins := SoftwareUpdateConfigurationResource{
startTime: time.Now().Add(time.Hour * 10).In(time.UTC).Format(time.RFC3339),
expireTime: time.Now().Add(time.Hour * 50).In(time.UTC).Format(time.RFC3339),
}
return ins
}

func (a SoftwareUpdateConfigurationResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := parse.SoftwareUpdateConfigurationID(state.ID)
if err != nil {
return nil, err
}
resp, err := client.Automation.SoftwareUpdateConfigClient.GetByName(ctx, id.ResourceGroup, id.AutomationAccountName, id.Name, "")
if err != nil {
return nil, fmt.Errorf("retrieving Type %s: %+v", id, err)
}
return utils.Bool(resp.SoftwareUpdateConfigurationProperties != nil), nil
}

func TestAccSoftwareUpdateConfiguration_basic(t *testing.T) {
data := acceptance.BuildTestData(t, automation.SoftwareUpdateConfigurationResource{}.ResourceType(), "test")
r := newSoftwareUpdateConfigurationResource()
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
// scheduleInfo.advancedSchedule always return null
data.ImportStep("schedule.0.advanced", "schedule.0.monthly_occurrence"),
})
}

func TestAccSoftwareUpdateConfiguration_update(t *testing.T) {
data := acceptance.BuildTestData(t, automation.SoftwareUpdateConfigurationResource{}.ResourceType(), "test")
r := newSoftwareUpdateConfigurationResource()
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
// scheduleInfo.advancedSchedule always return null
data.ImportStep("schedule.0.advanced", "schedule.0.monthly_occurrence"),
{
Config: r.update(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
// scheduleInfo.advancedSchedule always return null
data.ImportStep("schedule.0.advanced", "schedule.0.monthly_occurrence"),
})
}

func (a SoftwareUpdateConfigurationResource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_automation_software_update_configuration" "test" {
automation_account_id = azurerm_automation_account.test.id
name = "acctest-suc-%[2]d"
operating_system = "Linux"
linux {
classification_included = "Security"
excluded_packages = ["apt"]
included_packages = ["vim"]
reboot = "IfRequired"
}
duration = "PT1H1M1S"
virtual_machine_ids = []
target {
azure_query {
scope = [azurerm_resource_group.test.id]
locations = [azurerm_resource_group.test.location]
tags {
tag = "foo"
values = ["barbar2"]
}
tag_filter = "Any"
}
non_azure_query {
function_alias = "savedSearch1"
workspace_id = azurerm_log_analytics_workspace.test.id
}
}
schedule {
description = "foo-schedule"
start_time = "%[3]s"
expiry_time = "%[4]s"
is_enabled = true
interval = 1
frequency = "Hour"
time_zone = "Etc/UTC"
advanced_week_days = ["Monday", "Tuesday"]
advanced_month_days = [1, 10, 15]
monthly_occurrence {
occurrence = 1
day = "Tuesday"
}
}
depends_on = [azurerm_log_analytics_linked_service.test]
}
`, a.template(data), data.RandomInteger, a.startTime, a.expireTime)
}

func (a SoftwareUpdateConfigurationResource) update(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_automation_software_update_configuration" "test" {
automation_account_id = azurerm_automation_account.test.id
name = "acctest-suc-%[2]d"
operating_system = "Linux"
linux {
classification_included = "Security"
excluded_packages = ["apt"]
included_packages = ["vim"]
reboot = "IfRequired"
}
duration = "PT2H2M2S"
virtual_machine_ids = []
target {
azure_query {
scope = [azurerm_resource_group.test.id]
locations = [azurerm_resource_group.test.location]
tags {
tag = "foo"
values = ["barbar2"]
}
tag_filter = "Any"
}
non_azure_query {
function_alias = "savedSearch1"
workspace_id = azurerm_log_analytics_workspace.test.id
}
}
schedule {
description = "foobar-schedule"
start_time = "%[3]s"
expiry_time = "%[4]s"
is_enabled = true
interval = 1
frequency = "Hour"
time_zone = "Etc/UTC"
advanced_week_days = ["Monday", "Tuesday"]
}
depends_on = [azurerm_log_analytics_linked_service.test]
}
`, a.template(data), data.RandomInteger, a.startTime, a.expireTime)
}

// software update need log analytic location map correct, if use a random location like `East US` will cause
// error like `chosen Azure Automation does not have a Log Analytics workspace linked for operation to succeed`.
// so location hardcode as `West US`
// see more https://learn.microsoft.com/en-us/azure/automation/how-to/region-mappings
func (a SoftwareUpdateConfigurationResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-auto-%[1]d"
location = "West US"
}
resource "azurerm_automation_account" "test" {
name = "acctest-%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
sku_name = "Basic"
}
resource "azurerm_log_analytics_workspace" "test" {
name = "acctestLAW-%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
sku = "PerGB2018"
retention_in_days = 30
}
resource "azurerm_log_analytics_linked_service" "test" {
resource_group_name = azurerm_resource_group.test.name
workspace_id = azurerm_log_analytics_workspace.test.id
read_access_id = azurerm_automation_account.test.id
}
`, data.RandomInteger)
}
5 changes: 5 additions & 0 deletions internal/services/automation/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Client struct {
RunBookWgClient *hybridrunbookworkergroup.HybridRunbookWorkerGroupClient
RunbookWorkerClient *hybridrunbookworker.HybridRunbookWorkerClient
ScheduleClient *automation.ScheduleClient
SoftwareUpdateConfigClient *automation.SoftwareUpdateConfigurationsClient
SourceControlClient *automation.SourceControlClient
VariableClient *automation.VariableClient
WatcherClient *automation.WatcherClient
Expand Down Expand Up @@ -79,6 +80,9 @@ func NewClient(o *common.ClientOptions) *Client {
scheduleClient := automation.NewScheduleClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&scheduleClient.Client, o.ResourceManagerAuthorizer)

softUpClient := automation.NewSoftwareUpdateConfigurationsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&softUpClient.Client, o.ResourceManagerAuthorizer)

variableClient := automation.NewVariableClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&variableClient.Client, o.ResourceManagerAuthorizer)

Expand All @@ -104,6 +108,7 @@ func NewClient(o *common.ClientOptions) *Client {
RunBookWgClient: &runbookWgClient,
RunbookWorkerClient: &runbookWorkerClient,
ScheduleClient: &scheduleClient,
SoftwareUpdateConfigClient: &softUpClient,
SourceControlClient: &sourceCtlClient,
VariableClient: &variableClient,
WatcherClient: &watcherClient,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"fmt"
"strings"

"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)

type SoftwareUpdateConfigurationId struct {
SubscriptionId string
ResourceGroup string
AutomationAccountName string
Name string
}

func NewSoftwareUpdateConfigurationID(subscriptionId, resourceGroup, automationAccountName, name string) SoftwareUpdateConfigurationId {
return SoftwareUpdateConfigurationId{
SubscriptionId: subscriptionId,
ResourceGroup: resourceGroup,
AutomationAccountName: automationAccountName,
Name: name,
}
}

func (id SoftwareUpdateConfigurationId) String() string {
segments := []string{
fmt.Sprintf("Name %q", id.Name),
fmt.Sprintf("Automation Account Name %q", id.AutomationAccountName),
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Software Update Configuration", segmentsStr)
}

func (id SoftwareUpdateConfigurationId) ID() string {
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Automation/automationAccounts/%s/softwareUpdateConfigurations/%s"
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.AutomationAccountName, id.Name)
}

// SoftwareUpdateConfigurationID parses a SoftwareUpdateConfiguration ID into an SoftwareUpdateConfigurationId struct
func SoftwareUpdateConfigurationID(input string) (*SoftwareUpdateConfigurationId, error) {
id, err := resourceids.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := SoftwareUpdateConfigurationId{
SubscriptionId: id.SubscriptionID,
ResourceGroup: id.ResourceGroup,
}

if resourceId.SubscriptionId == "" {
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
}

if resourceId.ResourceGroup == "" {
return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
}

if resourceId.AutomationAccountName, err = id.PopSegment("automationAccounts"); err != nil {
return nil, err
}
if resourceId.Name, err = id.PopSegment("softwareUpdateConfigurations"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
Loading

0 comments on commit 85899b4

Please sign in to comment.