Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new resource "azurerm_maintenance_assignment" #6713

Merged
merged 6 commits into from Jun 18, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions azurerm/internal/services/maintenance/client/client.go
Expand Up @@ -6,14 +6,19 @@ import (
)

type Client struct {
ConfigurationsClient *maintenance.ConfigurationsClient
ConfigurationsClient *maintenance.ConfigurationsClient
ConfigurationAssignmentsClient *maintenance.ConfigurationAssignmentsClient
}

func NewClient(o *common.ClientOptions) *Client {
configurationsClient := maintenance.NewConfigurationsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&configurationsClient.Client, o.ResourceManagerAuthorizer)

configurationAssignmentsClient := maintenance.NewConfigurationAssignmentsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&configurationAssignmentsClient.Client, o.ResourceManagerAuthorizer)

return &Client{
ConfigurationsClient: &configurationsClient,
ConfigurationsClient: &configurationsClient,
ConfigurationAssignmentsClient: &configurationAssignmentsClient,
}
}
@@ -0,0 +1,169 @@
package maintenance

import (
"context"
"fmt"
"time"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress"

"github.com/Azure/azure-sdk-for-go/services/preview/maintenance/mgmt/2018-06-01-preview/maintenance"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location"
parseCompute "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute/parse"
validateCompute "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/maintenance/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/maintenance/validate"
azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmMaintenanceAssignmentDedicatedHost() *schema.Resource {
return &schema.Resource{
Create: resourceArmMaintenanceAssignmentDedicatedHostCreate,
Read: resourceArmMaintenanceAssignmentDedicatedHostRead,
Update: nil,
njuCZ marked this conversation as resolved.
Show resolved Hide resolved
Delete: resourceArmMaintenanceAssignmentDedicatedHostDelete,

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Read: schema.DefaultTimeout(5 * time.Minute),
Delete: schema.DefaultTimeout(30 * time.Minute),
},

Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
_, err := parse.MaintenanceAssignmentDedicatedHostID(id)
return err
}),

Schema: map[string]*schema.Schema{
"location": azure.SchemaLocation(),

"maintenance_configuration_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.MaintenanceConfigurationID,
},

"dedicated_host_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateCompute.DedicatedHostID,
DiffSuppressFunc: suppress.CaseDifference,
},
},
}
}

func resourceArmMaintenanceAssignmentDedicatedHostCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Maintenance.ConfigurationAssignmentsClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

dedicatedHostIdRaw := d.Get("dedicated_host_id").(string)
dedicatedHostId, _ := parseCompute.DedicatedHostID(dedicatedHostIdRaw)

existing, err := getMaintenanceAssignmentDedicatedHost(ctx, client, dedicatedHostId, dedicatedHostIdRaw)
if err != nil {
return err
}
if existing.ID != nil && *existing.ID != "" {
return tf.ImportAsExistsError("azurerm_maintenance_assignment_dedicated_host", *existing.ID)
}

maintenanceConfigurationID := d.Get("maintenance_configuration_id").(string)
configurationId, _ := parse.MaintenanceConfigurationID(maintenanceConfigurationID)

// set assignment name to configuration name
assignmentName := configurationId.Name
jackofallops marked this conversation as resolved.
Show resolved Hide resolved
assignment := maintenance.ConfigurationAssignment{
Name: utils.String(assignmentName),
Location: utils.String(location.Normalize(d.Get("location").(string))),
ConfigurationAssignmentProperties: &maintenance.ConfigurationAssignmentProperties{
MaintenanceConfigurationID: utils.String(maintenanceConfigurationID),
ResourceID: utils.String(dedicatedHostIdRaw),
},
}

if _, err := client.CreateOrUpdateParent(ctx, dedicatedHostId.ResourceGroup, "Microsoft.Compute", "hostGroups", dedicatedHostId.HostGroup, "hosts", dedicatedHostId.Name, assignmentName, assignment); err != nil {
return fmt.Errorf("creating Maintenance Assignment (Dedicated Host ID: %q): %+v", dedicatedHostIdRaw, err)
}

resp, err := getMaintenanceAssignmentDedicatedHost(ctx, client, dedicatedHostId, dedicatedHostIdRaw)
if err != nil {
return err
}
if resp.ID == nil || *resp.ID == "" {
return fmt.Errorf("empty or nil ID of Maintenance Assignment (Dedicated Host ID %q)", dedicatedHostIdRaw)
}

d.SetId(*resp.ID)
return resourceArmMaintenanceAssignmentDedicatedHostRead(d, meta)
}

func resourceArmMaintenanceAssignmentDedicatedHostRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Maintenance.ConfigurationAssignmentsClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.MaintenanceAssignmentDedicatedHostID(d.Id())
if err != nil {
return err
}

assignment, err := getMaintenanceAssignmentDedicatedHost(ctx, client, id.DedicatedHostId, id.DedicatedHostIdRaw)
if err != nil {
return err
}
if assignment.ID == nil || *assignment.ID == "" {
return fmt.Errorf("empty or nil ID of Maintenance Assignment (Dedicated Host ID: %q", id.DedicatedHostIdRaw)
}

// in list api, `ResourceID` returned is always nil
d.Set("dedicated_host_id", id.DedicatedHostIdRaw)
if props := assignment.ConfigurationAssignmentProperties; props != nil {
d.Set("maintenance_configuration_id", props.MaintenanceConfigurationID)
}
return nil
}

func resourceArmMaintenanceAssignmentDedicatedHostDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Maintenance.ConfigurationAssignmentsClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.MaintenanceAssignmentDedicatedHostID(d.Id())
if err != nil {
return err
}

if _, err := client.DeleteParent(ctx, id.DedicatedHostId.ResourceGroup, "Microsoft.Compute", "hostGroups", id.DedicatedHostId.HostGroup, "hosts", id.DedicatedHostId.Name, id.Name); err != nil {
return fmt.Errorf("deleting Maintenance Assignment to resource %q: %+v", id.DedicatedHostIdRaw, err)
}

return nil
}

func getMaintenanceAssignmentDedicatedHost(ctx context.Context, client *maintenance.ConfigurationAssignmentsClient, id *parseCompute.DedicatedHostId, dedicatedHostId string) (result maintenance.ConfigurationAssignment, err error) {
resp, err := client.ListParent(ctx, id.ResourceGroup, "Microsoft.Compute", "hostGroups", id.HostGroup, "hosts", id.Name)

if err != nil {
if !utils.ResponseWasNotFound(resp.Response) {
err = fmt.Errorf("checking for presence of existing Maintenance assignment (Dedicated Host ID %q): %+v", dedicatedHostId, err)
return
}
return result, nil
}
if resp.Value == nil || len(*resp.Value) == 0 {
err = fmt.Errorf("could not find Maintenance assignment (Dedicated Host ID %q)", dedicatedHostId)
return
}

return (*resp.Value)[0], nil
jackofallops marked this conversation as resolved.
Show resolved Hide resolved
}
@@ -0,0 +1,169 @@
package maintenance

import (
"context"
"fmt"
"time"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress"

"github.com/Azure/azure-sdk-for-go/services/preview/maintenance/mgmt/2018-06-01-preview/maintenance"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location"
parseCompute "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute/parse"
validateCompute "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/maintenance/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/maintenance/validate"
azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmMaintenanceAssignmentVirtualMachine() *schema.Resource {
return &schema.Resource{
Create: resourceArmMaintenanceAssignmentVirtualMachineCreate,
Read: resourceArmMaintenanceAssignmentVirtualMachineRead,
Update: nil,
Delete: resourceArmMaintenanceAssignmentVirtualMachineDelete,

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Read: schema.DefaultTimeout(5 * time.Minute),
Delete: schema.DefaultTimeout(30 * time.Minute),
},

Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
_, err := parse.MaintenanceAssignmentVirtualMachineID(id)
return err
}),

Schema: map[string]*schema.Schema{
"location": azure.SchemaLocation(),

"maintenance_configuration_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.MaintenanceConfigurationID,
},

"virtual_machine_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateCompute.VirtualMachineID,
DiffSuppressFunc: suppress.CaseDifference,
},
},
}
}

func resourceArmMaintenanceAssignmentVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Maintenance.ConfigurationAssignmentsClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

virtualMachineIdRaw := d.Get("virtual_machine_id").(string)
virtualMachineId, _ := parseCompute.VirtualMachineID(virtualMachineIdRaw)

existing, err := getMaintenanceAssignmentVirtualMachine(ctx, client, virtualMachineId, virtualMachineIdRaw)
if err != nil {
return err
}
if existing.ID != nil && *existing.ID != "" {
return tf.ImportAsExistsError("azurerm_maintenance_assignment_virtual_machine", *existing.ID)
}

maintenanceConfigurationID := d.Get("maintenance_configuration_id").(string)
configurationId, _ := parse.MaintenanceConfigurationID(maintenanceConfigurationID)

// set assignment name to configuration name
assignmentName := configurationId.Name
jackofallops marked this conversation as resolved.
Show resolved Hide resolved
assignment := maintenance.ConfigurationAssignment{
Name: utils.String(assignmentName),
Location: utils.String(location.Normalize(d.Get("location").(string))),
ConfigurationAssignmentProperties: &maintenance.ConfigurationAssignmentProperties{
MaintenanceConfigurationID: utils.String(maintenanceConfigurationID),
ResourceID: utils.String(virtualMachineIdRaw),
},
}

if _, err := client.CreateOrUpdate(ctx, virtualMachineId.ResourceGroup, "Microsoft.Compute", "virtualMachines", virtualMachineId.Name, assignmentName, assignment); err != nil {
return fmt.Errorf("creating Maintenance Assignment (virtual machine ID: %q): %+v", virtualMachineIdRaw, err)
}

resp, err := getMaintenanceAssignmentVirtualMachine(ctx, client, virtualMachineId, virtualMachineIdRaw)
if err != nil {
return err
}
if resp.ID == nil || *resp.ID == "" {
return fmt.Errorf("empty or nil ID of Maintenance Assignment (virtual machine ID %q)", virtualMachineIdRaw)
}

d.SetId(*resp.ID)
return resourceArmMaintenanceAssignmentVirtualMachineRead(d, meta)
}

func resourceArmMaintenanceAssignmentVirtualMachineRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Maintenance.ConfigurationAssignmentsClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.MaintenanceAssignmentVirtualMachineID(d.Id())
if err != nil {
return err
}

assignment, err := getMaintenanceAssignmentVirtualMachine(ctx, client, id.VirtualMachineId, id.VirtualMachineIdRaw)
if err != nil {
return err
}
if assignment.ID == nil || *assignment.ID == "" {
return fmt.Errorf("empty or nil ID of Maintenance Assignment (virtual machine ID id: %q", id.VirtualMachineIdRaw)
}

// in list api, `ResourceID` returned is always nil
d.Set("virtual_machine_id", id.VirtualMachineIdRaw)
if props := assignment.ConfigurationAssignmentProperties; props != nil {
d.Set("maintenance_configuration_id", props.MaintenanceConfigurationID)
}
return nil
}

func resourceArmMaintenanceAssignmentVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Maintenance.ConfigurationAssignmentsClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.MaintenanceAssignmentVirtualMachineID(d.Id())
if err != nil {
return err
}

if _, err := client.Delete(ctx, id.VirtualMachineId.ResourceGroup, "Microsoft.Compute", "virtualMachines", id.VirtualMachineId.Name, id.Name); err != nil {
return fmt.Errorf("deleting Maintenance Assignment to resource %q: %+v", id.VirtualMachineIdRaw, err)
}

return nil
}

func getMaintenanceAssignmentVirtualMachine(ctx context.Context, client *maintenance.ConfigurationAssignmentsClient, id *parseCompute.VirtualMachineId, virtualMachineId string) (result maintenance.ConfigurationAssignment, err error) {
resp, err := client.List(ctx, id.ResourceGroup, "Microsoft.Compute", "virtualMachines", id.Name)

if err != nil {
if !utils.ResponseWasNotFound(resp.Response) {
err = fmt.Errorf("checking for presence of existing Maintenance assignment (virtual machine ID: %q): %+v", virtualMachineId, err)
return
}
return result, nil
}
if resp.Value == nil || len(*resp.Value) == 0 {
err = fmt.Errorf("could not find Maintenance assignment (virtual machine ID: %q)", virtualMachineId)
return
}

return (*resp.Value)[0], nil
jackofallops marked this conversation as resolved.
Show resolved Hide resolved
}
@@ -0,0 +1,33 @@
package parse

import (
"fmt"
"regexp"

parseCompute "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute/parse"
)

type MaintenanceAssignmentDedicatedHostId struct {
DedicatedHostId *parseCompute.DedicatedHostId
DedicatedHostIdRaw string
Name string
}

func MaintenanceAssignmentDedicatedHostID(input string) (*MaintenanceAssignmentDedicatedHostId, error) {
groups := regexp.MustCompile(`^(.+)/providers/Microsoft\.Maintenance/configurationAssignments/([^/]+)$`).FindStringSubmatch(input)
if len(groups) != 3 {
return nil, fmt.Errorf("parsing Maintenance Assignment Dedicated Host ID: %q: Expected 3 groups", input)
njuCZ marked this conversation as resolved.
Show resolved Hide resolved
}

targetResourceId, name := groups[1], groups[2]
dedicatedHostID, err := parseCompute.DedicatedHostID(targetResourceId)
if err != nil {
return nil, fmt.Errorf("parsing Maintenance Assignment Dedicated Host ID: %q: Expected valid Dedicated Host ID", input)
}

return &MaintenanceAssignmentDedicatedHostId{
DedicatedHostId: dedicatedHostID,
DedicatedHostIdRaw: targetResourceId,
Name: name,
}, nil
}