diff --git a/azurerm/internal/services/automation/automation_connection_certificate_resource.go b/azurerm/internal/services/automation/automation_connection_certificate_resource.go new file mode 100644 index 000000000000..bf1e1cd1fff0 --- /dev/null +++ b/azurerm/internal/services/automation/automation_connection_certificate_resource.go @@ -0,0 +1,190 @@ +package automation + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "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/services/automation/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/automation/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 resourceArmAutomationConnectionCertificate() *schema.Resource { + return &schema.Resource{ + Create: resourceArmAutomationConnectionCertificateCreateUpdate, + Read: resourceArmAutomationConnectionCertificateRead, + Update: resourceArmAutomationConnectionCertificateCreateUpdate, + Delete: resourceArmAutomationConnectionCertificateDelete, + + Importer: azSchema.ValidateResourceIDPriorToImportThen(func(id string) error { + _, err := parse.AutomationConnectionID(id) + return err + }, importAutomationConnection("Azure")), + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.AutomationConnectionName, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "automation_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), + }, + + "automation_certificate_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "subscription_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsUUID, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceArmAutomationConnectionCertificateCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for AzureRM Automation Connection creation.") + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + accountName := d.Get("automation_account_name").(string) + + if d.IsNewResource() { + existing, err := client.Get(ctx, resGroup, accountName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing Automation Connection %q (Account %q / Resource Group %q): %s", name, accountName, resGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_automation_connection_certificate", *existing.ID) + } + } + + parameters := automation.ConnectionCreateOrUpdateParameters{ + Name: &name, + ConnectionCreateOrUpdateProperties: &automation.ConnectionCreateOrUpdateProperties{ + Description: utils.String(d.Get("description").(string)), + ConnectionType: &automation.ConnectionTypeAssociationProperty{ + Name: utils.String("Azure"), + }, + FieldDefinitionValues: map[string]*string{ + "AutomationCertificateName": utils.String(d.Get("automation_certificate_name").(string)), + "SubscriptionID": utils.String(d.Get("subscription_id").(string)), + }, + }, + } + + if _, err := client.CreateOrUpdate(ctx, resGroup, accountName, name, parameters); err != nil { + return err + } + + read, err := client.Get(ctx, resGroup, accountName, name) + if err != nil { + return err + } + + if read.ID == nil || *read.ID == "" { + return fmt.Errorf("empty or nil ID for Automation Connection '%s' (resource group %s) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmAutomationConnectionCertificateRead(d, meta) +} + +func resourceArmAutomationConnectionCertificateRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Read request on AzureRM Automation Connection '%s': %+v", id.Name, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", id.ResourceGroup) + d.Set("automation_account_name", id.AccountName) + d.Set("description", resp.Description) + + if props := resp.ConnectionProperties; props != nil { + if v, ok := props.FieldDefinitionValues["AutomationCertificateName"]; ok { + d.Set("automation_certificate_name", v) + } + if v, ok := props.FieldDefinitionValues["SubscriptionID"]; ok { + d.Set("subscription_id", v) + } + } + + return nil +} + +func resourceArmAutomationConnectionCertificateDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Delete(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return fmt.Errorf("deleting Automation Connection '%s': %+v", id.Name, err) + } + + return nil +} diff --git a/azurerm/internal/services/automation/automation_connection_classic_certificate_resource.go b/azurerm/internal/services/automation/automation_connection_classic_certificate_resource.go new file mode 100644 index 000000000000..0adb7811ff3c --- /dev/null +++ b/azurerm/internal/services/automation/automation_connection_classic_certificate_resource.go @@ -0,0 +1,200 @@ +package automation + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "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/services/automation/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/automation/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 resourceArmAutomationConnectionClassicCertificate() *schema.Resource { + return &schema.Resource{ + Create: resourceArmAutomationConnectionClassicCertificateCreateUpdate, + Read: resourceArmAutomationConnectionClassicCertificateRead, + Update: resourceArmAutomationConnectionClassicCertificateCreateUpdate, + Delete: resourceArmAutomationConnectionClassicCertificateDelete, + + Importer: azSchema.ValidateResourceIDPriorToImportThen(func(id string) error { + _, err := parse.AutomationConnectionID(id) + return err + }, importAutomationConnection("AzureClassicCertificate")), + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.AutomationConnectionName, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "automation_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), + }, + + "subscription_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsUUID, + }, + + "subscription_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "certificate_asset_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceArmAutomationConnectionClassicCertificateCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for AzureRM Automation Connection creation.") + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + accountName := d.Get("automation_account_name").(string) + + if d.IsNewResource() { + existing, err := client.Get(ctx, resGroup, accountName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing Automation Connection %q (Account %q / Resource Group %q): %s", name, accountName, resGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_automation_connection_classic_certificate", *existing.ID) + } + } + + parameters := automation.ConnectionCreateOrUpdateParameters{ + Name: &name, + ConnectionCreateOrUpdateProperties: &automation.ConnectionCreateOrUpdateProperties{ + Description: utils.String(d.Get("description").(string)), + ConnectionType: &automation.ConnectionTypeAssociationProperty{ + Name: utils.String("AzureClassicCertificate"), + }, + FieldDefinitionValues: map[string]*string{ + "SubscriptionName": utils.String(d.Get("subscription_name").(string)), + "SubscriptionId": utils.String(d.Get("subscription_id").(string)), + "CertificateAssetName": utils.String(d.Get("certificate_asset_name").(string)), + }, + }, + } + + if _, err := client.CreateOrUpdate(ctx, resGroup, accountName, name, parameters); err != nil { + return err + } + + read, err := client.Get(ctx, resGroup, accountName, name) + if err != nil { + return err + } + + if read.ID == nil || *read.ID == "" { + return fmt.Errorf("empty or nil ID for Automation Connection '%s' (resource group %s) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmAutomationConnectionClassicCertificateRead(d, meta) +} + +func resourceArmAutomationConnectionClassicCertificateRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Read request on AzureRM Automation Connection '%s': %+v", id.Name, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", id.ResourceGroup) + d.Set("automation_account_name", id.AccountName) + d.Set("description", resp.Description) + + if props := resp.ConnectionProperties; props != nil { + if v, ok := props.FieldDefinitionValues["CertificateAssetName"]; ok { + d.Set("certificate_asset_name", v) + } + if v, ok := props.FieldDefinitionValues["SubscriptionId"]; ok { + d.Set("subscription_id", v) + } + if v, ok := props.FieldDefinitionValues["SubscriptionName"]; ok { + d.Set("subscription_name", v) + } + } + + return nil +} + +func resourceArmAutomationConnectionClassicCertificateDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Delete(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return fmt.Errorf("deleting Automation Connection '%s': %+v", id.Name, err) + } + + return nil +} diff --git a/azurerm/internal/services/automation/automation_connection_import.go b/azurerm/internal/services/automation/automation_connection_import.go new file mode 100644 index 000000000000..82a1ff38717f --- /dev/null +++ b/azurerm/internal/services/automation/automation_connection_import.go @@ -0,0 +1,37 @@ +package automation + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/automation/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" +) + +func importAutomationConnection(connectionType string) func(d *schema.ResourceData, meta interface{}) (data []*schema.ResourceData, err error) { + return func(d *schema.ResourceData, meta interface{}) (data []*schema.ResourceData, err error) { + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return []*schema.ResourceData{}, err + } + + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + resp, err := client.Get(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + return []*schema.ResourceData{}, fmt.Errorf("retrieving automation connection %q (Account %q / Resource Group %q): %+v", id.Name, id.AccountName, id.ResourceGroup, err) + } + + if resp.ConnectionProperties == nil || resp.ConnectionProperties.ConnectionType == nil || resp.ConnectionProperties.ConnectionType.Name == nil { + return []*schema.ResourceData{}, fmt.Errorf("retrieving automation connection %q (Account %q / Resource Group %q): `properties`, `properties.connectionType` or `properties.connectionType.name` was nil", id.Name, id.AccountName, id.ResourceGroup) + } + + if *resp.ConnectionProperties.ConnectionType.Name != connectionType { + return nil, fmt.Errorf(`automation connection "type" mismatch, expected "%s", got "%s"`, connectionType, *resp.ConnectionProperties.ConnectionType.Name) + } + return []*schema.ResourceData{d}, nil + } +} diff --git a/azurerm/internal/services/automation/automation_connection_resource.go b/azurerm/internal/services/automation/automation_connection_resource.go new file mode 100644 index 000000000000..d8c511277376 --- /dev/null +++ b/azurerm/internal/services/automation/automation_connection_resource.go @@ -0,0 +1,214 @@ +package automation + +import ( + "fmt" + "log" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "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/services/automation/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/automation/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 resourceArmAutomationConnection() *schema.Resource { + return &schema.Resource{ + Create: resourceArmAutomationConnectionCreateUpdate, + Read: resourceArmAutomationConnectionRead, + Update: resourceArmAutomationConnectionCreateUpdate, + Delete: resourceArmAutomationConnectionDelete, + + Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error { + _, err := parse.AutomationConnectionID(id) + return err + }), + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.AutomationConnectionName, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "automation_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), + }, + + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "values": { + Type: schema.TypeMap, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceArmAutomationConnectionCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + connectionTypeClient := meta.(*clients.Client).Automation.ConnectionTypeClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for AzureRM Automation Connection creation.") + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + accountName := d.Get("automation_account_name").(string) + + if d.IsNewResource() { + existing, err := client.Get(ctx, resGroup, accountName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing Automation Connection %q (Account %q / Resource Group %q): %s", name, accountName, resGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_automation_connection", *existing.ID) + } + } + + connectionTypeName := d.Get("type").(string) + values := utils.ExpandMapStringPtrString(d.Get("values").(map[string]interface{})) + + // check `type` exists and required fields are passed by users + connectionType, err := connectionTypeClient.Get(ctx, resGroup, accountName, connectionTypeName) + if err != nil { + return fmt.Errorf("retrieving Automation Connection type %q (Account %q / Resource Group %q): %s", connectionTypeName, accountName, resGroup, err) + } + if connectionType.ConnectionTypeProperties != nil && connectionType.ConnectionTypeProperties.FieldDefinitions != nil { + var missingFields []string + for key := range connectionType.ConnectionTypeProperties.FieldDefinitions { + if _, ok := values[key]; !ok { + missingFields = append(missingFields, key) + } + } + if len(missingFields) > 0 { + return fmt.Errorf("%q should be specified in `values` when type is %q for `azurerm_automation_connection`", strings.Join(missingFields, ", "), connectionTypeName) + } + } + + parameters := automation.ConnectionCreateOrUpdateParameters{ + Name: &name, + ConnectionCreateOrUpdateProperties: &automation.ConnectionCreateOrUpdateProperties{ + Description: utils.String(d.Get("description").(string)), + ConnectionType: &automation.ConnectionTypeAssociationProperty{ + Name: utils.String(connectionTypeName), + }, + FieldDefinitionValues: values, + }, + } + + if _, err := client.CreateOrUpdate(ctx, resGroup, accountName, name, parameters); err != nil { + return err + } + + read, err := client.Get(ctx, resGroup, accountName, name) + if err != nil { + return err + } + + if read.ID == nil || *read.ID == "" { + return fmt.Errorf("empty or nil ID for Automation Connection '%s' (resource group %s) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmAutomationConnectionRead(d, meta) +} + +func resourceArmAutomationConnectionRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Read request on AzureRM Automation Connection '%s': %+v", id.Name, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", id.ResourceGroup) + d.Set("automation_account_name", id.AccountName) + d.Set("values", resp.FieldDefinitionValues) + d.Set("description", resp.Description) + + if props := resp.ConnectionProperties; props != nil { + if props.ConnectionType != nil { + d.Set("type", resp.ConnectionType.Name) + } + + if err := d.Set("values", utils.FlattenMapStringPtrString(props.FieldDefinitionValues)); err != nil { + return fmt.Errorf("setting `values`: %+v", err) + } + } + + return nil +} + +func resourceArmAutomationConnectionDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Delete(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return fmt.Errorf("deleting Automation Connection '%s': %+v", id.Name, err) + } + + return nil +} diff --git a/azurerm/internal/services/automation/automation_connection_service_principal_resource.go b/azurerm/internal/services/automation/automation_connection_service_principal_resource.go new file mode 100644 index 000000000000..8b3fb2dd4ad5 --- /dev/null +++ b/azurerm/internal/services/automation/automation_connection_service_principal_resource.go @@ -0,0 +1,210 @@ +package automation + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "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/services/automation/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/automation/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 resourceArmAutomationConnectionServicePrincipal() *schema.Resource { + return &schema.Resource{ + Create: resourceArmAutomationConnectionServicePrincipalCreateUpdate, + Read: resourceArmAutomationConnectionServicePrincipalRead, + Update: resourceArmAutomationConnectionServicePrincipalCreateUpdate, + Delete: resourceArmAutomationConnectionServicePrincipalDelete, + + Importer: azSchema.ValidateResourceIDPriorToImportThen(func(id string) error { + _, err := parse.AutomationConnectionID(id) + return err + }, importAutomationConnection("AzureServicePrincipal")), + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.AutomationConnectionName, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "automation_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), + }, + + "application_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsUUID, + }, + + "certificate_thumbprint": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "subscription_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsUUID, + }, + + "tenant_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsUUID, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceArmAutomationConnectionServicePrincipalCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for AzureRM Automation Connection creation.") + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + accountName := d.Get("automation_account_name").(string) + + if d.IsNewResource() { + existing, err := client.Get(ctx, resGroup, accountName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing Automation Connection %q (Account %q / Resource Group %q): %s", name, accountName, resGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_automation_connection_service_principal", *existing.ID) + } + } + + parameters := automation.ConnectionCreateOrUpdateParameters{ + Name: &name, + ConnectionCreateOrUpdateProperties: &automation.ConnectionCreateOrUpdateProperties{ + Description: utils.String(d.Get("description").(string)), + ConnectionType: &automation.ConnectionTypeAssociationProperty{ + Name: utils.String("AzureServicePrincipal"), + }, + FieldDefinitionValues: map[string]*string{ + "ApplicationId": utils.String(d.Get("application_id").(string)), + "CertificateThumbprint": utils.String(d.Get("certificate_thumbprint").(string)), + "SubscriptionId": utils.String(d.Get("subscription_id").(string)), + "TenantId": utils.String(d.Get("tenant_id").(string)), + }, + }, + } + + if _, err := client.CreateOrUpdate(ctx, resGroup, accountName, name, parameters); err != nil { + return err + } + + read, err := client.Get(ctx, resGroup, accountName, name) + if err != nil { + return err + } + + if read.ID == nil || *read.ID == "" { + return fmt.Errorf("empty or nil ID for Automation Connection '%s' (resource group %s) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmAutomationConnectionServicePrincipalRead(d, meta) +} + +func resourceArmAutomationConnectionServicePrincipalRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Read request on AzureRM Automation Connection '%s': %+v", id.Name, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", id.ResourceGroup) + d.Set("automation_account_name", id.AccountName) + d.Set("description", resp.Description) + + if props := resp.ConnectionProperties; props != nil { + if v, ok := props.FieldDefinitionValues["ApplicationId"]; ok { + d.Set("application_id", v) + } + if v, ok := props.FieldDefinitionValues["CertificateThumbprint"]; ok { + d.Set("certificate_thumbprint", v) + } + if v, ok := props.FieldDefinitionValues["SubscriptionId"]; ok { + d.Set("subscription_id", v) + } + if v, ok := props.FieldDefinitionValues["TenantId"]; ok { + d.Set("tenant_id", v) + } + } + + return nil +} + +func resourceArmAutomationConnectionServicePrincipalDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Automation.ConnectionClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.AutomationConnectionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Delete(ctx, id.ResourceGroup, id.AccountName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return fmt.Errorf("deleting Automation Connection '%s': %+v", id.Name, err) + } + + return nil +} diff --git a/azurerm/internal/services/automation/client/client.go b/azurerm/internal/services/automation/client/client.go index 663c6556ea50..fa9ed5f885ba 100644 --- a/azurerm/internal/services/automation/client/client.go +++ b/azurerm/internal/services/automation/client/client.go @@ -9,6 +9,8 @@ type Client struct { AccountClient *automation.AccountClient AgentRegistrationInfoClient *automation.AgentRegistrationInformationClient CertificateClient *automation.CertificateClient + ConnectionClient *automation.ConnectionClient + ConnectionTypeClient *automation.ConnectionTypeClient CredentialClient *automation.CredentialClient DscConfigurationClient *automation.DscConfigurationClient DscNodeConfigurationClient *automation.DscNodeConfigurationClient @@ -30,6 +32,12 @@ func NewClient(o *common.ClientOptions) *Client { certificateClient := automation.NewCertificateClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&certificateClient.Client, o.ResourceManagerAuthorizer) + connectionClient := automation.NewConnectionClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&connectionClient.Client, o.ResourceManagerAuthorizer) + + connectionTypeClient := automation.NewConnectionTypeClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&connectionTypeClient.Client, o.ResourceManagerAuthorizer) + credentialClient := automation.NewCredentialClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&credentialClient.Client, o.ResourceManagerAuthorizer) @@ -61,6 +69,8 @@ func NewClient(o *common.ClientOptions) *Client { AccountClient: &accountClient, AgentRegistrationInfoClient: &agentRegistrationInfoClient, CertificateClient: &certificateClient, + ConnectionClient: &connectionClient, + ConnectionTypeClient: &connectionTypeClient, CredentialClient: &credentialClient, DscConfigurationClient: &dscConfigurationClient, DscNodeConfigurationClient: &dscNodeConfigurationClient, diff --git a/azurerm/internal/services/automation/parse/automation_connection.go b/azurerm/internal/services/automation/parse/automation_connection.go new file mode 100644 index 000000000000..952f6443f9a2 --- /dev/null +++ b/azurerm/internal/services/automation/parse/automation_connection.go @@ -0,0 +1,38 @@ +package parse + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type AutomationConnectionId struct { + ResourceGroup string + AccountName string + Name string +} + +func AutomationConnectionID(input string) (*AutomationConnectionId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, fmt.Errorf("parsing Automation Connection ID %q: %+v", input, err) + } + + connection := AutomationConnectionId{ + ResourceGroup: id.ResourceGroup, + } + + if connection.AccountName, err = id.PopSegment("automationAccounts"); err != nil { + return nil, err + } + + if connection.Name, err = id.PopSegment("connections"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &connection, nil +} diff --git a/azurerm/internal/services/automation/parse/automation_connection_test.go b/azurerm/internal/services/automation/parse/automation_connection_test.go new file mode 100644 index 000000000000..287802a60c35 --- /dev/null +++ b/azurerm/internal/services/automation/parse/automation_connection_test.go @@ -0,0 +1,78 @@ +package parse + +import ( + "testing" +) + +func TestAutomationConnectionID(t *testing.T) { + testData := []struct { + Name string + Input string + Expected *AutomationConnectionId + }{ + { + Name: "Empty", + Input: "", + Expected: nil, + }, + { + Name: "No Resource Groups Segment", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000", + Expected: nil, + }, + { + Name: "No Resource Groups Value", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/", + Expected: nil, + }, + { + Name: "Resource Group ID", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/foo/", + Expected: nil, + }, + { + Name: "Missing Automation Accounts Value", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.Automation/automationAccounts/", + Expected: nil, + }, + { + Name: "Automation Connection ID", + Input: "/subscriptions/85b3dbca-5974-4067-9669-67a141095a76/resourceGroups/resGroup1/providers/Microsoft.Automation/automationAccounts/account1/connections/conn1", + Expected: &AutomationConnectionId{ + AccountName: "account1", + Name: "conn1", + ResourceGroup: "resGroup1", + }, + }, + { + Name: "Wrong Casing", + Input: "/subscriptions/85b3dbca-5974-4067-9669-67a141095a76/resourceGroups/resGroup1/providers/Microsoft.Automation/automationAccounts/account1/Connections/conn1", + Expected: nil, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Name) + + actual, err := AutomationConnectionID(v.Input) + if err != nil { + if v.Expected == nil { + continue + } + + t.Fatalf("Expected a value but got an error: %s", err) + } + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) + } + + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for Resource Group", v.Expected.ResourceGroup, actual.ResourceGroup) + } + } +} diff --git a/azurerm/internal/services/automation/registration.go b/azurerm/internal/services/automation/registration.go index 9c3fb84ac1b0..8cce5c7564b3 100644 --- a/azurerm/internal/services/automation/registration.go +++ b/azurerm/internal/services/automation/registration.go @@ -32,18 +32,22 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource { // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_automation_account": resourceArmAutomationAccount(), - "azurerm_automation_certificate": resourceArmAutomationCertificate(), - "azurerm_automation_credential": resourceArmAutomationCredential(), - "azurerm_automation_dsc_configuration": resourceArmAutomationDscConfiguration(), - "azurerm_automation_dsc_nodeconfiguration": resourceArmAutomationDscNodeConfiguration(), - "azurerm_automation_job_schedule": resourceArmAutomationJobSchedule(), - "azurerm_automation_module": resourceArmAutomationModule(), - "azurerm_automation_runbook": resourceArmAutomationRunbook(), - "azurerm_automation_schedule": resourceArmAutomationSchedule(), - "azurerm_automation_variable_bool": resourceArmAutomationVariableBool(), - "azurerm_automation_variable_datetime": resourceArmAutomationVariableDateTime(), - "azurerm_automation_variable_int": resourceArmAutomationVariableInt(), - "azurerm_automation_variable_string": resourceArmAutomationVariableString(), + "azurerm_automation_account": resourceArmAutomationAccount(), + "azurerm_automation_certificate": resourceArmAutomationCertificate(), + "azurerm_automation_connection": resourceArmAutomationConnection(), + "azurerm_automation_connection_certificate": resourceArmAutomationConnectionCertificate(), + "azurerm_automation_connection_classic_certificate": resourceArmAutomationConnectionClassicCertificate(), + "azurerm_automation_connection_service_principal": resourceArmAutomationConnectionServicePrincipal(), + "azurerm_automation_credential": resourceArmAutomationCredential(), + "azurerm_automation_dsc_configuration": resourceArmAutomationDscConfiguration(), + "azurerm_automation_dsc_nodeconfiguration": resourceArmAutomationDscNodeConfiguration(), + "azurerm_automation_job_schedule": resourceArmAutomationJobSchedule(), + "azurerm_automation_module": resourceArmAutomationModule(), + "azurerm_automation_runbook": resourceArmAutomationRunbook(), + "azurerm_automation_schedule": resourceArmAutomationSchedule(), + "azurerm_automation_variable_bool": resourceArmAutomationVariableBool(), + "azurerm_automation_variable_datetime": resourceArmAutomationVariableDateTime(), + "azurerm_automation_variable_int": resourceArmAutomationVariableInt(), + "azurerm_automation_variable_string": resourceArmAutomationVariableString(), } } diff --git a/azurerm/internal/services/automation/tests/automation_connection_certificate_resource_test.go b/azurerm/internal/services/automation/tests/automation_connection_certificate_resource_test.go new file mode 100644 index 000000000000..0699eb5896b9 --- /dev/null +++ b/azurerm/internal/services/automation/tests/automation_connection_certificate_resource_test.go @@ -0,0 +1,179 @@ +package tests + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccAzureRMAutomationConnectionCertificate_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_certificate", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionCertificate_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMAutomationConnectionCertificate_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_certificate", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionCertificate_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.RequiresImportErrorStep(testAccAzureRMAutomationConnectionCertificate_requiresImport), + }, + }) +} + +func TestAccAzureRMAutomationConnectionCertificate_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_certificate", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionCertificate_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMAutomationConnectionCertificate_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_certificate", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionCertificate_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMAutomationConnectionCertificate_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMAutomationConnectionCertificate_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMAutomationConnectionCertificateDestroy(s *terraform.State) error { + return testCheckAzureRMAutomationConnectionDestroy(s, "certificate") +} + +func testAccAzureRMAutomationConnectionCertificate_basic(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionCertificate_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_certificate" "test" { + name = "acctestACC-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + automation_certificate_name = azurerm_automation_certificate.test.name + subscription_id = data.azurerm_client_config.test.subscription_id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMAutomationConnectionCertificate_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionCertificate_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_certificate" "import" { + name = azurerm_automation_connection_certificate.test.name + resource_group_name = azurerm_automation_connection_certificate.test.resource_group_name + automation_account_name = azurerm_automation_connection_certificate.test.automation_account_name + automation_certificate_name = azurerm_automation_connection_certificate.test.automation_certificate_name + subscription_id = azurerm_automation_connection_certificate.test.subscription_id +} +`, template) +} + +func testAccAzureRMAutomationConnectionCertificate_complete(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionCertificate_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_certificate" "test" { + name = "acctestACC-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + automation_certificate_name = azurerm_automation_certificate.test.name + subscription_id = data.azurerm_client_config.test.subscription_id + description = "acceptance test for automation connection" +} +`, template, data.RandomInteger) +} + +func testAccAzureRMAutomationConnectionCertificate_template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +data "azurerm_client_config" "test" {} + +resource "azurerm_automation_account" "test" { + name = "acctestAA-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "Basic" +} + +resource "azurerm_automation_certificate" "test" { + name = "acctest-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + base64 = filebase64("testdata/automation_certificate_test.pfx") +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} diff --git a/azurerm/internal/services/automation/tests/automation_connection_classic_certificate_resource_test.go b/azurerm/internal/services/automation/tests/automation_connection_classic_certificate_resource_test.go new file mode 100644 index 000000000000..f7b1c4138de6 --- /dev/null +++ b/azurerm/internal/services/automation/tests/automation_connection_classic_certificate_resource_test.go @@ -0,0 +1,175 @@ +package tests + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccAzureRMAutomationConnectionClassicCertificate_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_classic_certificate", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionClassicCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionClassicCertificate_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMAutomationConnectionClassicCertificate_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_classic_certificate", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionClassicCertificate_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.RequiresImportErrorStep(testAccAzureRMAutomationConnectionClassicCertificate_requiresImport), + }, + }) +} + +func TestAccAzureRMAutomationConnectionClassicCertificate_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_classic_certificate", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionClassicCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionClassicCertificate_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMAutomationConnectionClassicCertificate_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_classic_certificate", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionClassicCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionClassicCertificate_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMAutomationConnectionClassicCertificate_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMAutomationConnectionClassicCertificate_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMAutomationConnectionClassicCertificateDestroy(s *terraform.State) error { + return testCheckAzureRMAutomationConnectionDestroy(s, "classic_certificate") +} + +func testAccAzureRMAutomationConnectionClassicCertificate_basic(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionClassicCertificate_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_classic_certificate" "test" { + name = "acctestACCC-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + certificate_asset_name = "cert1" + subscription_name = "subs1" + subscription_id = data.azurerm_client_config.test.subscription_id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMAutomationConnectionClassicCertificate_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionClassicCertificate_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_classic_certificate" "import" { + name = azurerm_automation_connection_classic_certificate.test.name + resource_group_name = azurerm_automation_connection_classic_certificate.test.resource_group_name + automation_account_name = azurerm_automation_connection_classic_certificate.test.automation_account_name + certificate_asset_name = azurerm_automation_connection_classic_certificate.test.certificate_asset_name + subscription_name = azurerm_automation_connection_classic_certificate.test.subscription_name + subscription_id = azurerm_automation_connection_classic_certificate.test.subscription_id +} +`, template) +} + +func testAccAzureRMAutomationConnectionClassicCertificate_complete(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionClassicCertificate_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_classic_certificate" "test" { + name = "acctestACCC-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + certificate_asset_name = "cert1" + subscription_name = "subs1" + subscription_id = data.azurerm_client_config.test.subscription_id + description = "acceptance test for automation connection" +} +`, template, data.RandomInteger) +} + +func testAccAzureRMAutomationConnectionClassicCertificate_template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +data "azurerm_client_config" "test" {} + +resource "azurerm_automation_account" "test" { + name = "acctestAA-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "Basic" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} diff --git a/azurerm/internal/services/automation/tests/automation_connection_resource_test.go b/azurerm/internal/services/automation/tests/automation_connection_resource_test.go new file mode 100644 index 000000000000..ff91a5d6c411 --- /dev/null +++ b/azurerm/internal/services/automation/tests/automation_connection_resource_test.go @@ -0,0 +1,184 @@ +package tests + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccAzureRMAutomationConnection_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionCustomDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnection_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMAutomationConnection_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionCustomDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnection_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.RequiresImportErrorStep(testAccAzureRMAutomationConnection_requiresImport), + }, + }) +} + +func TestAccAzureRMAutomationConnection_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionCustomDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnection_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMAutomationConnection_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionCustomDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnection_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMAutomationConnection_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMAutomationConnection_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMAutomationConnectionCustomDestroy(s *terraform.State) error { + return testCheckAzureRMAutomationConnectionDestroy(s, "") +} + +func testAccAzureRMAutomationConnection_basic(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnection_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection" "test" { + name = "acctestAAC-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + type = "AzureServicePrincipal" + + values = { + "ApplicationId" : "00000000-0000-0000-0000-000000000000" + "TenantId" : data.azurerm_client_config.test.tenant_id + "SubscriptionId" : data.azurerm_client_config.test.subscription_id + "CertificateThumbprint" : file("testdata/automation_certificate_test.thumb") + } +} +`, template, data.RandomInteger) +} + +func testAccAzureRMAutomationConnection_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnection_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection" "import" { + name = azurerm_automation_connection.test.name + resource_group_name = azurerm_automation_connection.test.resource_group_name + automation_account_name = azurerm_automation_connection.test.automation_account_name + type = azurerm_automation_connection.test.type + values = azurerm_automation_connection.test.values +} +`, template) +} + +func testAccAzureRMAutomationConnection_complete(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnection_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection" "test" { + name = "acctestAAC-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + type = "AzureServicePrincipal" + description = "acceptance test for automation connection" + + values = { + "ApplicationId" : "00000000-0000-0000-0000-000000000000" + "TenantId" : data.azurerm_client_config.test.tenant_id + "SubscriptionId" : data.azurerm_client_config.test.subscription_id + "CertificateThumbprint" : file("testdata/automation_certificate_test.thumb") + } +} +`, template, data.RandomInteger) +} + +func testAccAzureRMAutomationConnection_template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +data "azurerm_client_config" "test" {} + +resource "azurerm_automation_account" "test" { + name = "acctestAA-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "Basic" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} diff --git a/azurerm/internal/services/automation/tests/automation_connection_service_principal_resource_test.go b/azurerm/internal/services/automation/tests/automation_connection_service_principal_resource_test.go new file mode 100644 index 000000000000..445cd184cbba --- /dev/null +++ b/azurerm/internal/services/automation/tests/automation_connection_service_principal_resource_test.go @@ -0,0 +1,178 @@ +package tests + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccAzureRMAutomationConnectionServicePrincipal_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_service_principal", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionServicePrincipalDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionServicePrincipal_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMAutomationConnectionServicePrincipal_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_service_principal", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionServicePrincipal_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.RequiresImportErrorStep(testAccAzureRMAutomationConnectionServicePrincipal_requiresImport), + }, + }) +} + +func TestAccAzureRMAutomationConnectionServicePrincipal_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_service_principal", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionServicePrincipalDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionServicePrincipal_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMAutomationConnectionServicePrincipal_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_automation_connection_service_principal", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAutomationConnectionServicePrincipalDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationConnectionServicePrincipal_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMAutomationConnectionServicePrincipal_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMAutomationConnectionServicePrincipal_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationConnectionExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMAutomationConnectionServicePrincipalDestroy(s *terraform.State) error { + return testCheckAzureRMAutomationConnectionDestroy(s, "service_principal") +} + +func testAccAzureRMAutomationConnectionServicePrincipal_basic(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionServicePrincipal_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_service_principal" "test" { + name = "acctestACSP-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + application_id = "00000000-0000-0000-0000-000000000000" + tenant_id = data.azurerm_client_config.test.tenant_id + subscription_id = data.azurerm_client_config.test.subscription_id + certificate_thumbprint = file("testdata/automation_certificate_test.thumb") +} +`, template, data.RandomInteger) +} + +func testAccAzureRMAutomationConnectionServicePrincipal_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionServicePrincipal_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_service_principal" "import" { + name = azurerm_automation_connection_service_principal.test.name + resource_group_name = azurerm_automation_connection_service_principal.test.resource_group_name + automation_account_name = azurerm_automation_connection_service_principal.test.automation_account_name + application_id = azurerm_automation_connection_service_principal.test.application_id + tenant_id = azurerm_automation_connection_service_principal.test.tenant_id + subscription_id = azurerm_automation_connection_service_principal.test.subscription_id + certificate_thumbprint = azurerm_automation_connection_service_principal.test.certificate_thumbprint +} +`, template) +} + +func testAccAzureRMAutomationConnectionServicePrincipal_complete(data acceptance.TestData) string { + template := testAccAzureRMAutomationConnectionServicePrincipal_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_connection_service_principal" "test" { + name = "acctestACSP-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + application_id = "00000000-0000-0000-0000-000000000000" + tenant_id = data.azurerm_client_config.test.tenant_id + subscription_id = data.azurerm_client_config.test.subscription_id + certificate_thumbprint = file("testdata/automation_certificate_test.thumb") + description = "acceptance test for automation connection" +} +`, template, data.RandomInteger) +} + +func testAccAzureRMAutomationConnectionServicePrincipal_template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +data "azurerm_client_config" "test" {} + +resource "azurerm_automation_account" "test" { + name = "acctestAA-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "Basic" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} diff --git a/azurerm/internal/services/automation/tests/automation_connection_test.go b/azurerm/internal/services/automation/tests/automation_connection_test.go new file mode 100644 index 000000000000..07ac80999728 --- /dev/null +++ b/azurerm/internal/services/automation/tests/automation_connection_test.go @@ -0,0 +1,65 @@ +package tests + +import ( + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func testCheckAzureRMAutomationConnectionDestroy(s *terraform.State, varType string) error { + conn := acceptance.AzureProvider.Meta().(*clients.Client).Automation.ConnectionClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + resourceName := "azurerm_automation_connection" + if varType != "" { + resourceName = fmt.Sprintf("azurerm_automation_connection_%s", strings.ToLower(varType)) + } + + for _, rs := range s.RootModule().Resources { + if rs.Type != resourceName { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + accName := rs.Primary.Attributes["automation_account_name"] + + if resp, err := conn.Get(ctx, resourceGroup, accName, name); err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("bad: Get on Automation.ConnectionClient: %+v", err) + } + } + } + + return nil +} + +func testCheckAzureRMAutomationConnectionExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acceptance.AzureProvider.Meta().(*clients.Client).Automation.ConnectionClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + accName := rs.Primary.Attributes["automation_account_name"] + + if resp, err := conn.Get(ctx, resourceGroup, accName, name); err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Automation Connection %q (Resource Group %q / automation account %q) does not exist", name, resourceGroup, accName) + } + return fmt.Errorf("bad: Get on automationConnectionClient: %+v", err) + } + + return nil + } +} diff --git a/azurerm/internal/services/automation/validate/automation_connection.go b/azurerm/internal/services/automation/validate/automation_connection.go new file mode 100644 index 000000000000..8a91ac4ddfce --- /dev/null +++ b/azurerm/internal/services/automation/validate/automation_connection.go @@ -0,0 +1,19 @@ +package validate + +import ( + "fmt" + "regexp" +) + +func AutomationConnectionName(i interface{}, k string) (_ []string, errors []error) { + v, ok := i.(string) + if !ok { + return nil, append(errors, fmt.Errorf("expected type of %s to be string", k)) + } + + if !regexp.MustCompile(`^[\w\-]{1,128}$`).MatchString(v) { + errors = append(errors, fmt.Errorf("%s contain only letters, numbers hyphens and underscore. The value must be between 1 and 128 characters long", k)) + } + + return nil, errors +} diff --git a/azurerm/internal/services/automation/validate/automation_connection_test.go b/azurerm/internal/services/automation/validate/automation_connection_test.go new file mode 100644 index 000000000000..5a860977e760 --- /dev/null +++ b/azurerm/internal/services/automation/validate/automation_connection_test.go @@ -0,0 +1,71 @@ +package validate + +import "testing" + +func TestAutomationConnectionName(t *testing.T) { + testData := []struct { + input string + expected bool + }{ + { + // empty + input: "", + expected: false, + }, + { + // basic example + input: "ab-c", + expected: true, + }, + { + // contain underscore and hyphens + input: "ab_c-abc", + expected: true, + }, + { + // starts with underscore + input: "_abc", + expected: true, + }, + { + // starts with hyphens + input: "-abc", + expected: true, + }, + { + // starts with number + input: "1abc", + expected: true, + }, + { + // can't contain + + input: "ab+c", + expected: false, + }, + { + // can't end with % + input: "ab%c", + expected: false, + }, + { + // 128 chars + input: "abcdefghijklmnopqrstuvwxyzabcdefabcdefghijklmnopqrstuvwxyzabcdefabcdefghijklmnopqrstuvwxyzabcdefabcdefghijklmnopqrstuvwxyzabcdef", + expected: true, + }, + { + // 129 chars + input: "abcdefghijklmnopqrstuvwxyzabcdefabcdefghijklmnopqrstuvwxyzabcdefabcdefghijklmnopqrstuvwxyzabcdefabcdefghijklmnopqrstuvwxyzabcdefa", + expected: false, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q..", v.input) + + _, errors := AutomationConnectionName(v.input, "name") + actual := len(errors) == 0 + if v.expected != actual { + t.Fatalf("Expected %t but got %t", v.expected, actual) + } + } +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 28474f9ca9d1..86948771e560 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -864,6 +864,22 @@ azurerm_automation_certificate +
  • + azurerm_automation_connection +
  • + +
  • + azurerm_automation_connection_certificate +
  • + +
  • + azurerm_automation_connection_classic_certificate +
  • + +
  • + azurerm_automation_connection_service_principal +
  • +
  • azurerm_automation_credential
  • diff --git a/website/docs/r/automation_connection.html.markdown b/website/docs/r/automation_connection.html.markdown new file mode 100644 index 000000000000..eabbcd868b5d --- /dev/null +++ b/website/docs/r/automation_connection.html.markdown @@ -0,0 +1,95 @@ +--- +subcategory: "Automation" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_automation_connection" +description: |- + Manages an Automation Connection. +--- + +# azurerm_automation_connection + +Manages a Automation Connection. + +## Example Usage + +```hcl +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "resourceGroup-example" + location = "West Europe" +} + +data "azurerm_client_config" "example" {} + +resource "azurerm_automation_account" "example" { + name = "account-example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + sku { + name = "Basic" + } +} + +resource "azurerm_automation_connection" "example" { + name = "connection-example" + resource_group_name = azurerm_resource_group.example.name + automation_account_name = azurerm_automation_account.example.name + type = "AzureServicePrincipal" + + values = { + "ApplicationId" : "00000000-0000-0000-0000-000000000000", + "TenantId" : data.azurerm_client_config.example.tenant_id, + "SubscriptionId" : data.azurerm_client_config.example.subscription_id, + "CertificateThumbprint" : "sample-certificate-thumbprint", + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Connection. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the Connection is created. Changing this forces a new resource to be created. + +* `automation_account_name` - (Required) The name of the automation account in which the Connection is created. Changing this forces a new resource to be created. + +* `type` - (Required) The type of the Connection - can be either builtin type `Azure`, `AzureClassicCertificate` `AzureServicePrincipal` or user custom types. Changing this forces a new resource to be created. + +* `values` - (Optional) A mapping of key value pairs passed to the connection. Different `type` needs different parameters in the `values`. Builtin types have required field values as below: + + - `Azure`: parameters `AutomationCertificateName` and `SubscriptionID`. + + - `AzureClassicCertificate`: parameters `SubscriptionName`, `SubscriptionId` and `CertificateAssetName`. + + - `AzureServicePrincipal`: parameters `ApplicationId`, `CertificateThumbprint`, `SubscriptionId` and `TenantId`. + +* `description` - (Optional) A description for this Connection. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Automation Connection ID. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Automation Connection. +* `update` - (Defaults to 30 minutes) Used when updating the Automation Connection. +* `read` - (Defaults to 5 minutes) Used when retrieving the Automation Connection. +* `delete` - (Defaults to 30 minutes) Used when deleting the Automation Connection. + +## Import + +Automation Connection can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_automation_connection.conn1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Automation/automationAccounts/account1/connections/conn1 +``` diff --git a/website/docs/r/automation_connection_certificate.html.markdown b/website/docs/r/automation_connection_certificate.html.markdown new file mode 100644 index 000000000000..a5d30d0ffeac --- /dev/null +++ b/website/docs/r/automation_connection_certificate.html.markdown @@ -0,0 +1,90 @@ +--- +subcategory: "Automation" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_automation_connection_certificate" +description: |- + Manages an Automation Connection with type `Azure`. +--- + +# azurerm_automation_connection_certificate + +Manages a Automation Connection with type `Azure`. + +## Example Usage + +```hcl +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "resourceGroup-example" + location = "West Europe" +} + +data "azurerm_client_config" "example" {} + +resource "azurerm_automation_account" "example" { + name = "account-example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + sku { + name = "Basic" + } +} + +resource "azurerm_automation_certificate" "example" { + name = "certificate-example" + resource_group_name = "${azurerm_resource_group.example.name}" + automation_account_name = "${azurerm_automation_account.example.name}" + base64 = filebase64("certificate.pfx") +} + +resource "azurerm_automation_connection_certificate" "example" { + name = "connection-example" + resource_group_name = azurerm_resource_group.example.name + automation_account_name = azurerm_automation_account.example.name + automation_certificate_name = azurerm_automation_certificate.example.name + subscription_id = data.azurerm_client_config.example.subscription_id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Connection. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the Connection is created. Changing this forces a new resource to be created. + +* `automation_account_name` - (Required) The name of the automation account in which the Connection is created. Changing this forces a new resource to be created. + +* `automation_certificate_name` - (Required) The name of the automation certificate. + +* `subscription_id` - (Required) The id of subscription where the automation certificate exists. + +* `description` - (Optional) A description for this Connection. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Automation Connection ID. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Automation Connection. +* `update` - (Defaults to 30 minutes) Used when updating the Automation Connection. +* `read` - (Defaults to 5 minutes) Used when retrieving the Automation Connection. +* `delete` - (Defaults to 30 minutes) Used when deleting the Automation Connection. + +## Import + +Automation Connection can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_automation_connection_certificate.conn1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Automation/automationAccounts/account1/connections/conn1 +``` diff --git a/website/docs/r/automation_connection_classic_certificate.html.markdown b/website/docs/r/automation_connection_classic_certificate.html.markdown new file mode 100644 index 000000000000..bb42380e1704 --- /dev/null +++ b/website/docs/r/automation_connection_classic_certificate.html.markdown @@ -0,0 +1,86 @@ +--- +subcategory: "Automation" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_automation_connection_classic_certificate" +description: |- + Manages a Automation Connection with type `AzureClassicCertificate`. +--- + +# azurerm_automation_connection_classic_certificate + +Manages a Automation Connection with type `AzureClassicCertificate`. + +## Example Usage + +```hcl +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "resourceGroup-example" + location = "West Europe" +} + +data "azurerm_client_config" "example" {} + +resource "azurerm_automation_account" "example" { + name = "account-example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + sku { + name = "Basic" + } +} + +resource "azurerm_automation_connection_classic_certificate" "example" { + name = "connection-example" + resource_group_name = azurerm_resource_group.example.name + automation_account_name = azurerm_automation_account.example.name + certificate_asset_name = "cert1" + subscription_name = "subs1" + subscription_id = data.azurerm_client_config.example.subscription_id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Connection. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the Connection is created. Changing this forces a new resource to be created. + +* `automation_account_name` - (Required) The name of the automation account in which the Connection is created. Changing this forces a new resource to be created. + +* `certificate_asset_name` - (Required) The name of the certificate asset. + +* `subscription_name` - (Required) The name of subscription. + +* `subscription_id` - (Required) The id of subscription. + +* `description` - (Optional) A description for this Connection. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Automation Connection ID. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Automation Connection. +* `update` - (Defaults to 30 minutes) Used when updating the Automation Connection. +* `read` - (Defaults to 5 minutes) Used when retrieving the Automation Connection. +* `delete` - (Defaults to 30 minutes) Used when deleting the Automation Connection. + +## Import + +Automation Connection can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_automation_connection_classic_certificate.conn1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Automation/automationAccounts/account1/connections/conn1 +``` diff --git a/website/docs/r/automation_connection_service_principal.html.markdown b/website/docs/r/automation_connection_service_principal.html.markdown new file mode 100644 index 000000000000..07ca363cce44 --- /dev/null +++ b/website/docs/r/automation_connection_service_principal.html.markdown @@ -0,0 +1,89 @@ +--- +subcategory: "Automation" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_automation_connection_service_principal" +description: |- + Manages a Automation Connection with type `AzureServicePrincipal`. +--- + +# azurerm_automation_connection_service_principal + +Manages a Automation Connection with type `AzureServicePrincipal`. + +## Example Usage + +```hcl +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "resourceGroup-example" + location = "West Europe" +} + +data "azurerm_client_config" "example" {} + +resource "azurerm_automation_account" "example" { + name = "account-example" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + sku { + name = "Basic" + } +} + +resource "azurerm_automation_connection_service_principal" "example" { + name = "connection-example" + resource_group_name = azurerm_resource_group.example.name + automation_account_name = azurerm_automation_account.example.name + application_id = "00000000-0000-0000-0000-000000000000" + tenant_id = data.azurerm_client_config.example.tenant_id + subscription_id = data.azurerm_client_config.example.subscription_id + certificate_thumbprint = file("automation_certificate_test.thumb") +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Connection. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the Connection is created. Changing this forces a new resource to be created. + +* `automation_account_name` - (Required) The name of the automation account in which the Connection is created. Changing this forces a new resource to be created. + +* `application_id` - (Required) The (Client) ID of the Service Principal. + +* `certificate_thumbprint` - (Required) The thumbprint of the Service Principal Certificate. + +* `subscription_id` - (Required) The subscription GUID. + +* `tenant_id` - (Required) The ID of the Tenant the Service Principal is assigned in. + +* `description` - (Optional) A description for this Connection. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Automation Connection ID. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Automation Connection. +* `update` - (Defaults to 30 minutes) Used when updating the Automation Connection. +* `read` - (Defaults to 5 minutes) Used when retrieving the Automation Connection. +* `delete` - (Defaults to 30 minutes) Used when deleting the Automation Connection. + +## Import + +Automation Connection can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_automation_connection_service_principal.conn1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Automation/automationAccounts/account1/connections/conn1 +```