From e11d326451a3868516034504d68347fd16100800 Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Fri, 1 Nov 2019 01:13:34 +0800 Subject: [PATCH 01/13] #3881: azurerm_automation_certificate implementation --- .../internal/services/automation/client.go | 74 +++++ azurerm/provider.go | 1 + .../resource_arm_automation_certificate.go | 220 +++++++++++++ ...esource_arm_automation_certificate_test.go | 292 ++++++++++++++++++ website/azurerm.erb | 4 + .../r/automation_certificate.html.markdown | 69 +++++ 6 files changed, 660 insertions(+) create mode 100644 azurerm/internal/services/automation/client.go create mode 100644 azurerm/resource_arm_automation_certificate.go create mode 100644 azurerm/resource_arm_automation_certificate_test.go create mode 100644 website/docs/r/automation_certificate.html.markdown diff --git a/azurerm/internal/services/automation/client.go b/azurerm/internal/services/automation/client.go new file mode 100644 index 000000000000..63e1a21a8fc6 --- /dev/null +++ b/azurerm/internal/services/automation/client.go @@ -0,0 +1,74 @@ +package automation + +import ( + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common" +) + +type Client struct { + AccountClient *automation.AccountClient + AgentRegistrationInfoClient *automation.AgentRegistrationInformationClient + CertificateClient *automation.CertificateClient + CredentialClient *automation.CredentialClient + DscConfigurationClient *automation.DscConfigurationClient + DscNodeConfigurationClient *automation.DscNodeConfigurationClient + JobScheduleClient *automation.JobScheduleClient + ModuleClient *automation.ModuleClient + RunbookClient *automation.RunbookClient + RunbookDraftClient *automation.RunbookDraftClient + ScheduleClient *automation.ScheduleClient + VariableClient *automation.VariableClient +} + +func BuildClient(o *common.ClientOptions) *Client { + AccountClient := automation.NewAccountClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&AccountClient.Client, o.ResourceManagerAuthorizer) + + AgentRegistrationInfoClient := automation.NewAgentRegistrationInformationClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&AgentRegistrationInfoClient.Client, o.ResourceManagerAuthorizer) + + CertificateClient := automation.NewCertificateClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&CertificateClient.Client, o.ResourceManagerAuthorizer) + + CredentialClient := automation.NewCredentialClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&CredentialClient.Client, o.ResourceManagerAuthorizer) + + DscConfigurationClient := automation.NewDscConfigurationClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&DscConfigurationClient.Client, o.ResourceManagerAuthorizer) + + DscNodeConfigurationClient := automation.NewDscNodeConfigurationClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&DscNodeConfigurationClient.Client, o.ResourceManagerAuthorizer) + + JobScheduleClient := automation.NewJobScheduleClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&JobScheduleClient.Client, o.ResourceManagerAuthorizer) + + ModuleClient := automation.NewModuleClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&ModuleClient.Client, o.ResourceManagerAuthorizer) + + RunbookClient := automation.NewRunbookClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&RunbookClient.Client, o.ResourceManagerAuthorizer) + + ScheduleClient := automation.NewScheduleClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&ScheduleClient.Client, o.ResourceManagerAuthorizer) + + RunbookDraftClient := automation.NewRunbookDraftClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&RunbookDraftClient.Client, o.ResourceManagerAuthorizer) + + VariableClient := automation.NewVariableClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&VariableClient.Client, o.ResourceManagerAuthorizer) + + return &Client{ + AccountClient: &AccountClient, + AgentRegistrationInfoClient: &AgentRegistrationInfoClient, + CertificateClient: &CertificateClient, + CredentialClient: &CredentialClient, + DscConfigurationClient: &DscConfigurationClient, + DscNodeConfigurationClient: &DscNodeConfigurationClient, + JobScheduleClient: &JobScheduleClient, + ModuleClient: &ModuleClient, + RunbookClient: &RunbookClient, + RunbookDraftClient: &RunbookDraftClient, + ScheduleClient: &ScheduleClient, + VariableClient: &VariableClient, + } +} diff --git a/azurerm/provider.go b/azurerm/provider.go index f47b2bb99ac2..9ec3b27cc7a5 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -198,6 +198,7 @@ func Provider() terraform.ResourceProvider { "azurerm_application_insights_web_test": resourceArmApplicationInsightsWebTests(), "azurerm_application_security_group": resourceArmApplicationSecurityGroup(), "azurerm_automation_account": resourceArmAutomationAccount(), + "azurerm_automation_certificate": resourceArmAutomationCertificate(), "azurerm_automation_credential": resourceArmAutomationCredential(), "azurerm_automation_dsc_configuration": resourceArmAutomationDscConfiguration(), "azurerm_automation_dsc_nodeconfiguration": resourceArmAutomationDscNodeConfiguration(), diff --git a/azurerm/resource_arm_automation_certificate.go b/azurerm/resource_arm_automation_certificate.go new file mode 100644 index 000000000000..938592d25004 --- /dev/null +++ b/azurerm/resource_arm_automation_certificate.go @@ -0,0 +1,220 @@ +package azurerm + +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/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/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmAutomationCertificate() *schema.Resource { + return &schema.Resource{ + Create: resourceArmAutomationCertificateCreateUpdate, + Read: resourceArmAutomationCertificateRead, + Update: resourceArmAutomationCertificateUpdate, + Delete: resourceArmAutomationCertificateDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + 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{ + "resource_group_name": azure.SchemaResourceGroupName(), + + "account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + }, + + "base64": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Sensitive: true, + }, + + "is_exportable": { + Type: schema.TypeBool, + Computed: true, + }, + + "thumbprint": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Automation.CertificateClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for AzureRM Automation Certificate creation.") + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + accName := d.Get("account_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resGroup, accName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Automation Certificate %q (Account %q / Resource Group %q): %s", name, accName, resGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_automation_certificate", *existing.ID) + } + } + + base64 := d.Get("base64").(string) + isExportable := d.Get("is_exportable").(bool) + thumbprint := d.Get("thumbprint").(string) + description := d.Get("description").(string) + + parameters := automation.CertificateCreateOrUpdateParameters{ + CertificateCreateOrUpdateProperties: &automation.CertificateCreateOrUpdateProperties{ + Base64Value: &base64, + IsExportable: &isExportable, + Thumbprint: &thumbprint, + Description: &description, + }, + Name: &name, + } + + if _, err := client.CreateOrUpdate(ctx, resGroup, accName, name, parameters); err != nil { + return err + } + + read, err := client.Get(ctx, resGroup, accName, name) + if err != nil { + return err + } + + if read.ID == nil { + return fmt.Errorf("Cannot read Automation Certificate '%s' (resource group %s) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmAutomationCertificateRead(d, meta) +} + +func resourceArmAutomationCertificateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Automation.CertificateClient + ctx, cancel := timeouts.ForUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for AzureRM Automation Certificate update.") + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + accName := d.Get("account_name").(string) + + description := d.Get("description").(string) + + parameters := automation.CertificateUpdateParameters{ + CertificateUpdateProperties: &automation.CertificateUpdateProperties{ + Description: &description, + }, + Name: &name, + } + + read, err := client.Update(ctx, resGroup, accName, name, parameters) + if err != nil { + return err + } + + d.SetId(*read.ID) + + return resourceArmAutomationCertificateRead(d, meta) +} + +func resourceArmAutomationCertificateRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Automation.CertificateClient + ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + accName := id.Path["automationAccounts"] + name := id.Path["certificates"] + + resp, err := client.Get(ctx, resGroup, accName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request on AzureRM Automation Certificate '%s': %+v", name, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", resGroup) + d.Set("account_name", accName) + + if props := resp.CertificateProperties; props != nil { + d.Set("is_exportable", props.IsExportable) + d.Set("thumbprint", props.Thumbprint) + d.Set("description", props.Description) + } + + return nil +} + +func resourceArmAutomationCertificateDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Automation.CertificateClient + ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + accName := id.Path["automationAccounts"] + name := id.Path["certificates"] + + resp, err := client.Delete(ctx, resGroup, accName, name) + if err != nil { + if utils.ResponseWasNotFound(resp) { + return nil + } + + return fmt.Errorf("Error issuing AzureRM delete request for Automation Certificate '%s': %+v", name, err) + } + + return nil +} diff --git a/azurerm/resource_arm_automation_certificate_test.go b/azurerm/resource_arm_automation_certificate_test.go new file mode 100644 index 000000000000..fd9a8f170e15 --- /dev/null +++ b/azurerm/resource_arm_automation_certificate_test.go @@ -0,0 +1,292 @@ +package azurerm + +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/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +// Test certificate generated with: +// openssl req -x509 -nodes -sha256 -days 3650 -subj "/CN=Local" -newkey rsa:2048 -keyout Local.key -out Local.crt +// openssl pkcs12 -export -in Local.crt -inkey Local.key -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -out Local.pfx + +var testCertThumbprint = "F3FF6EA8713C72230933B9152329F7F324E6BF67" +var testCertBase64 = "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" + +func TestAccAzureRMAutomationCertificate_basic(t *testing.T) { + resourceName := "azurerm_automation_certificate.test" + ri := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationCertificate_basic(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationCertificateExists(resourceName), + ), + }, + }, + }) +} + +func TestAccAzureRMAutomationCertificate_requiresImport(t *testing.T) { + if !features.ShouldResourcesBeImported() { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + resourceName := "azurerm_automation_certificate.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationCertificate_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationCertificateExists(resourceName), + ), + }, + { + Config: testAccAzureRMAutomationCertificate_requiresImport(ri, location), + ExpectError: testRequiresImportError("azurerm_automation_certificate"), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"base64"}, + }, + }, + }) +} + +func TestAccAzureRMAutomationCertificate_complete(t *testing.T) { + resourceName := "azurerm_automation_certificate.test" + ri := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationCertificate_complete(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationCertificateExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "base64", testCertBase64), + resource.TestCheckResourceAttr(resourceName, "thumbprint", testCertThumbprint), + resource.TestCheckResourceAttr(resourceName, "is_exportable", "false"), + resource.TestCheckResourceAttr(resourceName, "description", "This is a test certificate for terraform acceptance test"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"base64"}, + }, + }, + }) +} + +func TestAccAzureRMAutomationCertificate_update(t *testing.T) { + resourceName := "azurerm_automation_certificate.test" + ri := tf.AccRandTimeInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationCertificate_basic(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d", ri)), + testCheckAzureRMAutomationCertificateExists(resourceName), + ), + }, + { + Config: testAccAzureRMAutomationCertificate_update(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationCertificateExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d-updated", ri)), + resource.TestCheckResourceAttr(resourceName, "description", "This is a test certificate for terraform acceptance test"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"base64"}, + }, + }, + }) +} + +func testCheckAzureRMAutomationCertificateDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).Automation.CertificateClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_automation_certificate" { + continue + } + + name := rs.Primary.Attributes["name"] + accName := rs.Primary.Attributes["account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Certificate: '%s'", name) + } + + resp, err := conn.Get(ctx, resourceGroup, accName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return fmt.Errorf("Automation Certificate still exists:\n%#v", resp) + } + + return nil +} + +func testCheckAzureRMAutomationCertificateExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + name := rs.Primary.Attributes["name"] + accName := rs.Primary.Attributes["account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Certificate: '%s'", name) + } + + conn := testAccProvider.Meta().(*ArmClient).Automation.CertificateClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := conn.Get(ctx, resourceGroup, accName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Automation Certificate '%s' (resource group: '%s') does not exist", name, resourceGroup) + } + + return fmt.Errorf("Bad: Get on automationCertificateClient: %s\nName: %s, Account name: %s, Resource group: %s OBJECT: %+v", err, name, accName, resourceGroup, rs.Primary) + } + + return nil + } +} + +func testAccAzureRMAutomationCertificate_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_automation_account" "test" { + name = "acctest-%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}" + account_name = "${azurerm_automation_account.test.name}" + base64 = "%s" +} +`, rInt, location, rInt, rInt, testCertBase64) +} + +func testAccAzureRMAutomationCertificate_requiresImport(rInt int, location string) string { + template := testAccAzureRMAutomationCertificate_basic(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_certificate" "import" { + name = "${azurerm_automation_certificate.test.name}" + resource_group_name = "${azurerm_automation_certificate.test.resource_group_name}" + account_name = "${azurerm_automation_certificate.test.account_name}" + base64 = "${azurerm_automation_certificate.test.base64}" + is_exportable = "${azurerm_automation_certificate.test.is_exportable}" + thumbprint = "${azurerm_automation_certificate.test.username}" +} +`, template) +} + +func testAccAzureRMAutomationCertificate_complete(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_automation_account" "test" { + name = "acctest-%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}" + account_name = "${azurerm_automation_account.test.name}" + base64 = "%s" + description = "This is a test certificate for terraform acceptance test" +} +`, rInt, location, rInt, rInt, testCertBase64) +} + +func testAccAzureRMAutomationCertificate_update(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_automation_account" "test" { + name = "acctest-%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-updated" + resource_group_name = "${azurerm_resource_group.test.name}" + account_name = "${azurerm_automation_account.test.name}" + base64 = "%s" + description = "This is a test certificate for terraform acceptance test" +} +`, rInt, location, rInt, rInt, testCertBase64) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 17816308696c..6a1433553b63 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -674,6 +674,10 @@ azurerm_automation_account +
  • + azurerm_automation_certificate +
  • +
  • azurerm_automation_credential
  • diff --git a/website/docs/r/automation_certificate.html.markdown b/website/docs/r/automation_certificate.html.markdown new file mode 100644 index 000000000000..b49833dd7597 --- /dev/null +++ b/website/docs/r/automation_certificate.html.markdown @@ -0,0 +1,69 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_automation_certificate" +sidebar_current: "docs-azurerm-resource-automation-certificate" +description: |- + Manages an Automation Certificate. +--- + +# azurerm_automation_certificate + +Manages an Automation Certificate. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "resourceGroup1" + location = "West Europe" +} + +resource "azurerm_automation_account" "example" { + name = "account1" + location = "${azurerm_resource_group.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" + + sku_name = "Basic" +} + +resource "azurerm_automation_certificate" "example" { + name = "certificate1" + resource_group_name = "${azurerm_resource_group.example.name}" + account_name = "${azurerm_automation_account.example.name}" + + description = "This is an example certificate" + base64 = "${base64encode(file("certificate.pfx"))}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Certificate. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the Certificate is created. Changing this forces a new resource to be created. + +* `account_name` - (Required) The name of the automation account in which the Certificate is created. Changing this forces a new resource to be created. + +* `base64` - (Required) Base64 encoded value of the certificate. + +* `description` - (Optional) The description associated with this Automation Certificate. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Automation Certificate ID. + +* `is_exportable` - The is exportable flag of the certificate. + +* `thumbprint` - The thumbprint for the certificate. + +## Import + +Automation Certificates can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_automation_certificate.certificate1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Automation/automationAccounts/account1/certificates/certificate1 +``` From 6a59e3e91907eeb4186d53a6e482de2ed21e7e53 Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Fri, 1 Nov 2019 14:16:36 +0800 Subject: [PATCH 02/13] Update website/docs/r/automation_certificate.html.markdown Co-Authored-By: kt --- website/docs/r/automation_certificate.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/automation_certificate.html.markdown b/website/docs/r/automation_certificate.html.markdown index b49833dd7597..c77e9c1397aa 100644 --- a/website/docs/r/automation_certificate.html.markdown +++ b/website/docs/r/automation_certificate.html.markdown @@ -48,7 +48,7 @@ The following arguments are supported: * `base64` - (Required) Base64 encoded value of the certificate. -* `description` - (Optional) The description associated with this Automation Certificate. +* `description` - (Optional) The description of this Automation Certificate. ## Attributes Reference From 9b7fe95d34639343160068d826ad799fafcef5bf Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Fri, 1 Nov 2019 14:17:58 +0800 Subject: [PATCH 03/13] Update azurerm/resource_arm_automation_certificate.go Co-Authored-By: kt --- azurerm/resource_arm_automation_certificate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_automation_certificate.go b/azurerm/resource_arm_automation_certificate.go index 938592d25004..9d3ef750c1f8 100644 --- a/azurerm/resource_arm_automation_certificate.go +++ b/azurerm/resource_arm_automation_certificate.go @@ -79,7 +79,7 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i log.Printf("[INFO] preparing arguments for AzureRM Automation Certificate creation.") name := d.Get("name").(string) - resGroup := d.Get("resource_group_name").(string) + resourceGroup := d.Get("resource_group_name").(string) accName := d.Get("account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { From 157991d0274ebd4eed64be56c47f8f92afe0ba2f Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Fri, 1 Nov 2019 14:18:07 +0800 Subject: [PATCH 04/13] Update azurerm/resource_arm_automation_certificate.go Co-Authored-By: kt --- azurerm/resource_arm_automation_certificate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_automation_certificate.go b/azurerm/resource_arm_automation_certificate.go index 9d3ef750c1f8..23979a9da790 100644 --- a/azurerm/resource_arm_automation_certificate.go +++ b/azurerm/resource_arm_automation_certificate.go @@ -80,7 +80,7 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - accName := d.Get("account_name").(string) + accountName := d.Get("account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resGroup, accName, name) From 74352503899c0da14623e53f1952389613c6e1cc Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Wed, 6 Nov 2019 21:08:59 +0800 Subject: [PATCH 05/13] Pull request feedback -- * Validation for schema elements * Stop setting Computed properties on creation * Renamed/ordered variables for readability and consistency --- .../resource_arm_automation_certificate.go | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/azurerm/resource_arm_automation_certificate.go b/azurerm/resource_arm_automation_certificate.go index 23979a9da790..5f68089f7fec 100644 --- a/azurerm/resource_arm_automation_certificate.go +++ b/azurerm/resource_arm_automation_certificate.go @@ -9,6 +9,7 @@ import ( "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/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -33,17 +34,18 @@ func resourceArmAutomationCertificate() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "resource_group_name": azure.SchemaResourceGroupName(), - - "account_name": { + "name": { Type: schema.TypeString, Required: true, - ForceNew: true, }, - "name": { - Type: schema.TypeString, - Required: true, + "resource_group_name": azure.SchemaResourceGroupName(), + + "account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, }, "description": { @@ -52,10 +54,11 @@ func resourceArmAutomationCertificate() *schema.Resource { }, "base64": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Sensitive: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + Sensitive: true, + ValidateFunc: validate.Base64String(), }, "is_exportable": { @@ -83,10 +86,10 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i accountName := d.Get("account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resGroup, accName, name) + existing, err := client.Get(ctx, resourceGroup, accountName, name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Automation Certificate %q (Account %q / Resource Group %q): %s", name, accName, resGroup, err) + return fmt.Errorf("Error checking for presence of existing Automation Certificate %q (Account %q / Resource Group %q): %s", name, accountName, resourceGroup, err) } } @@ -96,31 +99,27 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i } base64 := d.Get("base64").(string) - isExportable := d.Get("is_exportable").(bool) - thumbprint := d.Get("thumbprint").(string) description := d.Get("description").(string) parameters := automation.CertificateCreateOrUpdateParameters{ CertificateCreateOrUpdateProperties: &automation.CertificateCreateOrUpdateProperties{ - Base64Value: &base64, - IsExportable: &isExportable, - Thumbprint: &thumbprint, - Description: &description, + Base64Value: &base64, + Description: &description, }, Name: &name, } - if _, err := client.CreateOrUpdate(ctx, resGroup, accName, name, parameters); err != nil { + if _, err := client.CreateOrUpdate(ctx, resourceGroup, accountName, name, parameters); err != nil { return err } - read, err := client.Get(ctx, resGroup, accName, name) + read, err := client.Get(ctx, resourceGroup, accountName, name) if err != nil { return err } if read.ID == nil { - return fmt.Errorf("Cannot read Automation Certificate '%s' (resource group %s) ID", name, resGroup) + return fmt.Errorf("Cannot read Automation Certificate '%s' (resource group %s) ID", name, resourceGroup) } d.SetId(*read.ID) From 6026485dff628c5bbe4768ec0f1c98d6b2585f99 Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Wed, 6 Nov 2019 23:11:16 +0800 Subject: [PATCH 06/13] Moving test certificate to testdata folder -- * Wrote script to re-generate test certificate --- ...esource_arm_automation_certificate_test.go | 13 +++++--- .../testdata/automation_certificate_test.crt | 16 +++++++++ .../testdata/automation_certificate_test.key | 28 ++++++++++++++++ .../testdata/automation_certificate_test.pfx | Bin 0 -> 2401 bytes .../automation_certificate_test.thumb | 1 + .../automation_certificate_testdata.sh | 31 ++++++++++++++++++ 6 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 azurerm/testdata/automation_certificate_test.crt create mode 100644 azurerm/testdata/automation_certificate_test.key create mode 100644 azurerm/testdata/automation_certificate_test.pfx create mode 100644 azurerm/testdata/automation_certificate_test.thumb create mode 100755 azurerm/testdata/automation_certificate_testdata.sh diff --git a/azurerm/resource_arm_automation_certificate_test.go b/azurerm/resource_arm_automation_certificate_test.go index fd9a8f170e15..d7114340f847 100644 --- a/azurerm/resource_arm_automation_certificate_test.go +++ b/azurerm/resource_arm_automation_certificate_test.go @@ -1,7 +1,11 @@ package azurerm import ( + "encoding/base64" "fmt" + "io/ioutil" + "path/filepath" + "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -11,12 +15,11 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -// Test certificate generated with: -// openssl req -x509 -nodes -sha256 -days 3650 -subj "/CN=Local" -newkey rsa:2048 -keyout Local.key -out Local.crt -// openssl pkcs12 -export -in Local.crt -inkey Local.key -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -out Local.pfx +var testCertThumbprintRaw, _ = ioutil.ReadFile(filepath.Join("testdata", "automation_certificate_test.thumb")) +var testCertRaw, _ = ioutil.ReadFile(filepath.Join("testdata", "automation_certificate_test.pfx")) -var testCertThumbprint = "F3FF6EA8713C72230933B9152329F7F324E6BF67" -var testCertBase64 = "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" +var testCertThumbprint = strings.TrimSpace(string(testCertThumbprintRaw)) +var testCertBase64 = base64.StdEncoding.EncodeToString(testCertRaw) func TestAccAzureRMAutomationCertificate_basic(t *testing.T) { resourceName := "azurerm_automation_certificate.test" diff --git a/azurerm/testdata/automation_certificate_test.crt b/azurerm/testdata/automation_certificate_test.crt new file mode 100644 index 000000000000..8a573d3eaece --- /dev/null +++ b/azurerm/testdata/automation_certificate_test.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAYQCCQCL8XdPvGCY3DANBgkqhkiG9w0BAQsFADAQMQ4wDAYDVQQDDAVM +b2NhbDAeFw0xOTExMDYxNDUzMjhaFw0yOTExMDMxNDUzMjhaMBAxDjAMBgNVBAMM +BUxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArap1ZhMoz6A7 +uaFb/PTYwW1C+cByX4VAPyBxASk0+Lal/DAfdFgX9LpMOOXKZB3O5nU1AG8YNd0I +6+zy1T6mGUxVdZd2/Y0c4LZT3Iib9fDy8YJDap8CJK+FcRLPYNodfnOHBF48G2tP +Ozxf1Hn8F6ilZDsGwIvwpTsCg5sSI+WqcLD6u3I98F/XEbj3dLKfRb+KmxBW0DrH +4PhT4UArweaexHxIUKz76at96TRQcoM2BO+5HK5NpxyHt9sVbYcXBJ02+FT4sYkH +oDC7gVAr4j8PRYlc6U9RUApNfSgM1L6tmYjySGxwTo7UTPE4nElXSoGZ8xD4k8vR +rrh5ZyHe+wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBBobmw043lmMMsrK0FWQ2z +zRykC/bVdyXvKmW9PdkPnAvy+8r7u2M//89USIUTL35weQXwLhBaI49u40IRbn3P +ilTXfPX8BEl2oaFpqIonM4w0iF6HDUgrwnFngCpX0G6AgTc7vLt0ljAG01q65wRi +y9x40eBcyW5D/eZ1GRD2QqUxdNwGQSzWnfmprp2xGkVQ4+7Raf6Af+pfY++epndo +13uL+3lsItPyJsCSQzsiOt341qfwfFXABZpEbH9XOivc+WLisD/rrU/+9V1HxD46 +GvpY0CTL+/UNV1yB/BYxXDQVwdnU0MA6fOgb+Vfbk8qkNf5huhLfXLnu6sz8uEwC +-----END CERTIFICATE----- diff --git a/azurerm/testdata/automation_certificate_test.key b/azurerm/testdata/automation_certificate_test.key new file mode 100644 index 000000000000..09167c5dab31 --- /dev/null +++ b/azurerm/testdata/automation_certificate_test.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCtqnVmEyjPoDu5 +oVv89NjBbUL5wHJfhUA/IHEBKTT4tqX8MB90WBf0ukw45cpkHc7mdTUAbxg13Qjr +7PLVPqYZTFV1l3b9jRzgtlPciJv18PLxgkNqnwIkr4VxEs9g2h1+c4cEXjwba087 +PF/UefwXqKVkOwbAi/ClOwKDmxIj5apwsPq7cj3wX9cRuPd0sp9Fv4qbEFbQOsfg ++FPhQCvB5p7EfEhQrPvpq33pNFBygzYE77kcrk2nHIe32xVthxcEnTb4VPixiQeg +MLuBUCviPw9FiVzpT1FQCk19KAzUvq2ZiPJIbHBOjtRM8TicSVdKgZnzEPiTy9Gu +uHlnId77AgMBAAECggEASMFg7aKZNmKqoto274KkTGS56mf1go8Qm2G79gCNcKUU +ZNLEWrmNT7m8tRmP8OGMDICN8+CXA/nWAwEButTEQVT5eIo8D31O29WGzJ1uuVp4 +bTVliQWUoEnoXbbDqo+2S4OazPmttM8AIpDolNuGAWNl5tfTvFbkOlS+eOQ+dUrR +sSfdNjBDCU2XNwZu6acYPWvxqLqUasxOvvBbuVBdvwg4TzkusfsfKg6NCG6aa9rx +W1DneYmG/ZSZgVS1vJxAVFi3Mx1Vvo/0Ze6tVgz8wJ60nCABDlQkHmgH8YM6/bxu +WZmqp0B4eKlOX8uXRzcr/Hg7jRHzAjQb417W1tQUAQKBgQDTH2Dc/7XDC0W6aWJh +PLnEyhR3aIr6OKA2Cby7ne2R8zEZStQo9U/8M6gGiodfVWtuuYQhR/2CXDRAZU61 +AH3fnE6pOtyBKyOv2R/KSfI9i0s5c6ivyjlmbbmXBKGTOVVQhY82LVFOueGKD0DY +ctN8Ll0hicm/9IF3NWHB0tpDSQKBgQDSlM3kw15CQ9P9lZAd04PgHCbB2THYXWpL +Uis7+hwVMDhJlT3sO1ipbywgoPQ5qzciFuLqFUcqtEXAQWin33ETvzJmPsVdAipj +Nbtt4+Bw5enKh7CqTW71J2xm3d3HxUNbrdvbuW+SbZL3znQwP2enTx/FV0APQm55 +SQ1fW8lMIwKBgQDEbSpjE+rZyHAcqxYkYCp65IU8P+EmQ28UN+UILjyuETU6Ufup +C+xaOvl29IZU9ZWaFDLSADfmhMD8tQUQtJ9oX/Zzz1b/OtLeNkY0oK4oAqR/lJN6 +0syq9yW4U0+9OZed7lW7U1iVxa4JFH4BpHwNytlNbfRuix+1eM42VmZKOQKBgQCe +/m8+jCv9CE1lJ6m6e1sUuOyibCTwYgfBevbdwAe4D8JP/HjWhjB5LVE6CYychiOI +f5MwfoRPP/FyKXClX1V3PWMGQ9qsUNhEM+uiGu35D/6nRjAjRXfDbdKxEE9FaDFl +ZS2dBrOw8T6ID782NolCj8FDNI9Pdi8HMBsCpsCj1QKBgQC7p6yWuMD/k8F/rkAe +eFv6s/Bf0V6nbfGStf0wHS59DnIolEBudo7FjgyUAuaxhj4tHFbSpKvZUSsYbgUi +UcdoS1PfVl4iUYjkNsLDWbb1gBcmlpHB+B7o3OqkFvVQmLwlJgesbEcWVDONMmmc +yPaMshP3a4X+/QyosnmIKn5kVw== +-----END PRIVATE KEY----- diff --git a/azurerm/testdata/automation_certificate_test.pfx b/azurerm/testdata/automation_certificate_test.pfx new file mode 100644 index 0000000000000000000000000000000000000000..b9bc2f627cc0159bd0faf988213dab8b1052ac0b GIT binary patch literal 2401 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 pcL7kbpjp^0|4=7eyX;gyWL3LNJTs6C ${CERT_THUMBPRINT_FILE} \ No newline at end of file From 9448fc2cb6ab65895e82660700ece22c6b77e608 Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Wed, 6 Nov 2019 23:17:08 +0800 Subject: [PATCH 07/13] Fixing missed variable renames from PR feedback --- .../resource_arm_automation_certificate.go | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/azurerm/resource_arm_automation_certificate.go b/azurerm/resource_arm_automation_certificate.go index 5f68089f7fec..19a1d3a43b70 100644 --- a/azurerm/resource_arm_automation_certificate.go +++ b/azurerm/resource_arm_automation_certificate.go @@ -135,8 +135,8 @@ func resourceArmAutomationCertificateUpdate(d *schema.ResourceData, meta interfa log.Printf("[INFO] preparing arguments for AzureRM Automation Certificate update.") name := d.Get("name").(string) - resGroup := d.Get("resource_group_name").(string) - accName := d.Get("account_name").(string) + resourceGroup := d.Get("resource_group_name").(string) + accountName := d.Get("account_name").(string) description := d.Get("description").(string) @@ -147,7 +147,7 @@ func resourceArmAutomationCertificateUpdate(d *schema.ResourceData, meta interfa Name: &name, } - read, err := client.Update(ctx, resGroup, accName, name, parameters) + read, err := client.Update(ctx, resourceGroup, accountName, name, parameters) if err != nil { return err } @@ -166,11 +166,11 @@ func resourceArmAutomationCertificateRead(d *schema.ResourceData, meta interface if err != nil { return err } - resGroup := id.ResourceGroup - accName := id.Path["automationAccounts"] + resourceGroup := id.ResourceGroup + accountName := id.Path["automationAccounts"] name := id.Path["certificates"] - resp, err := client.Get(ctx, resGroup, accName, name) + resp, err := client.Get(ctx, resourceGroup, accountName, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") @@ -181,8 +181,8 @@ func resourceArmAutomationCertificateRead(d *schema.ResourceData, meta interface } d.Set("name", resp.Name) - d.Set("resource_group_name", resGroup) - d.Set("account_name", accName) + d.Set("resource_group_name", resourceGroup) + d.Set("account_name", accountName) if props := resp.CertificateProperties; props != nil { d.Set("is_exportable", props.IsExportable) @@ -202,11 +202,11 @@ func resourceArmAutomationCertificateDelete(d *schema.ResourceData, meta interfa if err != nil { return err } - resGroup := id.ResourceGroup - accName := id.Path["automationAccounts"] + resourceGroup := id.ResourceGroup + accountName := id.Path["automationAccounts"] name := id.Path["certificates"] - resp, err := client.Delete(ctx, resGroup, accName, name) + resp, err := client.Delete(ctx, resourceGroup, accountName, name) if err != nil { if utils.ResponseWasNotFound(resp) { return nil From 7971578972feea34266bd524da914e824ff19eb6 Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Thu, 7 Nov 2019 00:24:44 +0800 Subject: [PATCH 08/13] Certificate name now ForceNew based on API behaviour -- * Adding test for certificate rename * Refactor back into single CreateUpdate method --- .../resource_arm_automation_certificate.go | 45 +++---------- ...esource_arm_automation_certificate_test.go | 64 ++++++++++++++++++- 2 files changed, 71 insertions(+), 38 deletions(-) diff --git a/azurerm/resource_arm_automation_certificate.go b/azurerm/resource_arm_automation_certificate.go index 19a1d3a43b70..0e7d0801ddb2 100644 --- a/azurerm/resource_arm_automation_certificate.go +++ b/azurerm/resource_arm_automation_certificate.go @@ -19,7 +19,7 @@ func resourceArmAutomationCertificate() *schema.Resource { return &schema.Resource{ Create: resourceArmAutomationCertificateCreateUpdate, Read: resourceArmAutomationCertificateRead, - Update: resourceArmAutomationCertificateUpdate, + Update: resourceArmAutomationCertificateCreateUpdate, Delete: resourceArmAutomationCertificateDelete, Importer: &schema.ResourceImporter{ @@ -35,8 +35,10 @@ func resourceArmAutomationCertificate() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, }, "resource_group_name": azure.SchemaResourceGroupName(), @@ -98,17 +100,20 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i } } - base64 := d.Get("base64").(string) description := d.Get("description").(string) parameters := automation.CertificateCreateOrUpdateParameters{ CertificateCreateOrUpdateProperties: &automation.CertificateCreateOrUpdateProperties{ - Base64Value: &base64, Description: &description, }, Name: &name, } + if v, ok := d.GetOk("base64"); ok { + base64 := v.(string) + parameters.CertificateCreateOrUpdateProperties.Base64Value = &base64 + } + if _, err := client.CreateOrUpdate(ctx, resourceGroup, accountName, name, parameters); err != nil { return err } @@ -127,36 +132,6 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i return resourceArmAutomationCertificateRead(d, meta) } -func resourceArmAutomationCertificateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).Automation.CertificateClient - ctx, cancel := timeouts.ForUpdate(meta.(*ArmClient).StopContext, d) - defer cancel() - - log.Printf("[INFO] preparing arguments for AzureRM Automation Certificate update.") - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - accountName := d.Get("account_name").(string) - - description := d.Get("description").(string) - - parameters := automation.CertificateUpdateParameters{ - CertificateUpdateProperties: &automation.CertificateUpdateProperties{ - Description: &description, - }, - Name: &name, - } - - read, err := client.Update(ctx, resourceGroup, accountName, name, parameters) - if err != nil { - return err - } - - d.SetId(*read.ID) - - return resourceArmAutomationCertificateRead(d, meta) -} - func resourceArmAutomationCertificateRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Automation.CertificateClient ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) diff --git a/azurerm/resource_arm_automation_certificate_test.go b/azurerm/resource_arm_automation_certificate_test.go index d7114340f847..4d88dbcf3101 100644 --- a/azurerm/resource_arm_automation_certificate_test.go +++ b/azurerm/resource_arm_automation_certificate_test.go @@ -104,7 +104,7 @@ func TestAccAzureRMAutomationCertificate_complete(t *testing.T) { }) } -func TestAccAzureRMAutomationCertificate_update(t *testing.T) { +func TestAccAzureRMAutomationCertificate_rename(t *testing.T) { resourceName := "azurerm_automation_certificate.test" ri := tf.AccRandTimeInt() @@ -116,15 +116,48 @@ func TestAccAzureRMAutomationCertificate_update(t *testing.T) { { Config: testAccAzureRMAutomationCertificate_basic(ri, testLocation()), Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationCertificateExists(resourceName), resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d", ri)), + ), + }, + { + Config: testAccAzureRMAutomationCertificate_rename(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationCertificateExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d-updated", ri)), + resource.TestCheckResourceAttr(resourceName, "description", "This is a test certificate for terraform acceptance test"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"base64"}, + }, + }, + }) +} + +func TestAccAzureRMAutomationCertificate_update(t *testing.T) { + resourceName := "azurerm_automation_certificate.test" + ri := tf.AccRandTimeInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationCertificate_basic(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( testCheckAzureRMAutomationCertificateExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "description", ""), ), }, { Config: testAccAzureRMAutomationCertificate_update(ri, testLocation()), Check: resource.ComposeTestCheckFunc( testCheckAzureRMAutomationCertificateExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d-updated", ri)), resource.TestCheckResourceAttr(resourceName, "description", "This is a test certificate for terraform acceptance test"), ), }, @@ -269,7 +302,7 @@ resource "azurerm_automation_certificate" "test" { `, rInt, location, rInt, rInt, testCertBase64) } -func testAccAzureRMAutomationCertificate_update(rInt int, location string) string { +func testAccAzureRMAutomationCertificate_rename(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -293,3 +326,28 @@ resource "azurerm_automation_certificate" "test" { } `, rInt, location, rInt, rInt, testCertBase64) } + +func testAccAzureRMAutomationCertificate_update(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_automation_account" "test" { + name = "acctest-%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}" + account_name = "${azurerm_automation_account.test.name}" + base64 = "%s" + description = "This is a test certificate for terraform acceptance test" +} +`, rInt, location, rInt, rInt, testCertBase64) +} From a2d0be0e93ca405db8886874cc974bdef080eeca Mon Sep 17 00:00:00 2001 From: Will Dowling Date: Mon, 9 Dec 2019 19:41:54 +0800 Subject: [PATCH 09/13] Updating for new automation client --- azurerm/internal/services/automation/client/client.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/azurerm/internal/services/automation/client/client.go b/azurerm/internal/services/automation/client/client.go index ff839f29c9fc..f5c21ada4408 100644 --- a/azurerm/internal/services/automation/client/client.go +++ b/azurerm/internal/services/automation/client/client.go @@ -8,6 +8,7 @@ import ( type Client struct { AccountClient *automation.AccountClient AgentRegistrationInfoClient *automation.AgentRegistrationInformationClient + CertificateClient *automation.CertificateClient CredentialClient *automation.CredentialClient DscConfigurationClient *automation.DscConfigurationClient DscNodeConfigurationClient *automation.DscNodeConfigurationClient @@ -26,6 +27,9 @@ func NewClient(o *common.ClientOptions) *Client { agentRegistrationInfoClient := automation.NewAgentRegistrationInformationClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&agentRegistrationInfoClient.Client, o.ResourceManagerAuthorizer) + CertificateClient := automation.NewCertificateClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&CertificateClient.Client, o.ResourceManagerAuthorizer) + credentialClient := automation.NewCredentialClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&credentialClient.Client, o.ResourceManagerAuthorizer) From 674715746d823f583d826077aef25edcec6c2ef9 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Wed, 18 Dec 2019 13:23:53 +0100 Subject: [PATCH 10/13] r/automation_certificate: fixing comments from code review --- .../services/automation/client/client.go | 5 +- .../resource_arm_automation_certificate.go | 26 ++-- ...esource_arm_automation_certificate_test.go | 133 ++++-------------- 3 files changed, 45 insertions(+), 119 deletions(-) diff --git a/azurerm/internal/services/automation/client/client.go b/azurerm/internal/services/automation/client/client.go index f5c21ada4408..663c6556ea50 100644 --- a/azurerm/internal/services/automation/client/client.go +++ b/azurerm/internal/services/automation/client/client.go @@ -27,8 +27,8 @@ func NewClient(o *common.ClientOptions) *Client { agentRegistrationInfoClient := automation.NewAgentRegistrationInformationClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&agentRegistrationInfoClient.Client, o.ResourceManagerAuthorizer) - CertificateClient := automation.NewCertificateClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&CertificateClient.Client, o.ResourceManagerAuthorizer) + certificateClient := automation.NewCertificateClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&certificateClient.Client, o.ResourceManagerAuthorizer) credentialClient := automation.NewCredentialClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&credentialClient.Client, o.ResourceManagerAuthorizer) @@ -60,6 +60,7 @@ func NewClient(o *common.ClientOptions) *Client { return &Client{ AccountClient: &accountClient, AgentRegistrationInfoClient: &agentRegistrationInfoClient, + CertificateClient: &certificateClient, CredentialClient: &credentialClient, DscConfigurationClient: &dscConfigurationClient, DscNodeConfigurationClient: &dscNodeConfigurationClient, diff --git a/azurerm/resource_arm_automation_certificate.go b/azurerm/resource_arm_automation_certificate.go index 0e7d0801ddb2..6dddf156f804 100644 --- a/azurerm/resource_arm_automation_certificate.go +++ b/azurerm/resource_arm_automation_certificate.go @@ -43,7 +43,7 @@ func resourceArmAutomationCertificate() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - "account_name": { + "automation_account_name": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -63,7 +63,7 @@ func resourceArmAutomationCertificate() *schema.Resource { ValidateFunc: validate.Base64String(), }, - "is_exportable": { + "exportable": { Type: schema.TypeBool, Computed: true, }, @@ -85,7 +85,7 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - accountName := d.Get("account_name").(string) + accountName := d.Get("automation_account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resourceGroup, accountName, name) @@ -103,10 +103,10 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i description := d.Get("description").(string) parameters := automation.CertificateCreateOrUpdateParameters{ + Name: &name, CertificateCreateOrUpdateProperties: &automation.CertificateCreateOrUpdateProperties{ Description: &description, }, - Name: &name, } if v, ok := d.GetOk("base64"); ok { @@ -115,16 +115,16 @@ func resourceArmAutomationCertificateCreateUpdate(d *schema.ResourceData, meta i } if _, err := client.CreateOrUpdate(ctx, resourceGroup, accountName, name, parameters); err != nil { - return err + return fmt.Errorf("Error creating/updating Certificate %q (Automation Account %q / Resource Group %q): %+v", name, accountName, resourceGroup, err) } read, err := client.Get(ctx, resourceGroup, accountName, name) if err != nil { - return err + return fmt.Errorf("Error retrieving Certificate %q (Automation Account %q / Resource Group %q): %+v", name, accountName, resourceGroup, err) } if read.ID == nil { - return fmt.Errorf("Cannot read Automation Certificate '%s' (resource group %s) ID", name, resourceGroup) + return fmt.Errorf("ID was nil for Automation Certificate %q (Automation Account %q / Resource Group %q)", name, accountName, resourceGroup) } d.SetId(*read.ID) @@ -152,15 +152,15 @@ func resourceArmAutomationCertificateRead(d *schema.ResourceData, meta interface return nil } - return fmt.Errorf("Error making Read request on AzureRM Automation Certificate '%s': %+v", name, err) + return fmt.Errorf("Error retrieving Certificate %q (Automation Account %q / Resource Group %q): %+v", name, accountName, resourceGroup, err) } d.Set("name", resp.Name) d.Set("resource_group_name", resourceGroup) - d.Set("account_name", accountName) + d.Set("automation_account_name", accountName) if props := resp.CertificateProperties; props != nil { - d.Set("is_exportable", props.IsExportable) + d.Set("exportable", props.IsExportable) d.Set("thumbprint", props.Thumbprint) d.Set("description", props.Description) } @@ -183,11 +183,9 @@ func resourceArmAutomationCertificateDelete(d *schema.ResourceData, meta interfa resp, err := client.Delete(ctx, resourceGroup, accountName, name) if err != nil { - if utils.ResponseWasNotFound(resp) { - return nil + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error deleting Certificate %q (Automation Account %q / Resource Group %q): %+v", name, accountName, resourceGroup, err) } - - return fmt.Errorf("Error issuing AzureRM delete request for Automation Certificate '%s': %+v", name, err) } return nil diff --git a/azurerm/resource_arm_automation_certificate_test.go b/azurerm/resource_arm_automation_certificate_test.go index 4d88dbcf3101..c04a65246ce8 100644 --- a/azurerm/resource_arm_automation_certificate_test.go +++ b/azurerm/resource_arm_automation_certificate_test.go @@ -18,7 +18,6 @@ import ( var testCertThumbprintRaw, _ = ioutil.ReadFile(filepath.Join("testdata", "automation_certificate_test.thumb")) var testCertRaw, _ = ioutil.ReadFile(filepath.Join("testdata", "automation_certificate_test.pfx")) -var testCertThumbprint = strings.TrimSpace(string(testCertThumbprintRaw)) var testCertBase64 = base64.StdEncoding.EncodeToString(testCertRaw) func TestAccAzureRMAutomationCertificate_basic(t *testing.T) { @@ -78,6 +77,7 @@ func TestAccAzureRMAutomationCertificate_requiresImport(t *testing.T) { func TestAccAzureRMAutomationCertificate_complete(t *testing.T) { resourceName := "azurerm_automation_certificate.test" ri := tf.AccRandTimeInt() + testCertThumbprint := strings.TrimSpace(string(testCertThumbprintRaw)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -90,42 +90,6 @@ func TestAccAzureRMAutomationCertificate_complete(t *testing.T) { testCheckAzureRMAutomationCertificateExists(resourceName), resource.TestCheckResourceAttr(resourceName, "base64", testCertBase64), resource.TestCheckResourceAttr(resourceName, "thumbprint", testCertThumbprint), - resource.TestCheckResourceAttr(resourceName, "is_exportable", "false"), - resource.TestCheckResourceAttr(resourceName, "description", "This is a test certificate for terraform acceptance test"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"base64"}, - }, - }, - }) -} - -func TestAccAzureRMAutomationCertificate_rename(t *testing.T) { - resourceName := "azurerm_automation_certificate.test" - ri := tf.AccRandTimeInt() - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMAutomationCertificateDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMAutomationCertificate_basic(ri, testLocation()), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMAutomationCertificateExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d", ri)), - ), - }, - { - Config: testAccAzureRMAutomationCertificate_rename(ri, testLocation()), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMAutomationCertificateExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d-updated", ri)), - resource.TestCheckResourceAttr(resourceName, "description", "This is a test certificate for terraform acceptance test"), ), }, { @@ -181,12 +145,8 @@ func testCheckAzureRMAutomationCertificateDestroy(s *terraform.State) error { } name := rs.Primary.Attributes["name"] - accName := rs.Primary.Attributes["account_name"] - - resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] - if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for Automation Certificate: '%s'", name) - } + accName := rs.Primary.Attributes["automation_account_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] resp, err := conn.Get(ctx, resourceGroup, accName, name) @@ -213,12 +173,8 @@ func testCheckAzureRMAutomationCertificateExists(resourceName string) resource.T } name := rs.Primary.Attributes["name"] - accName := rs.Primary.Attributes["account_name"] - - resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] - if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for Automation Certificate: '%s'", name) - } + accName := rs.Primary.Attributes["automation_account_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] conn := testAccProvider.Meta().(*ArmClient).Automation.CertificateClient ctx := testAccProvider.Meta().(*ArmClient).StopContext @@ -246,17 +202,16 @@ resource "azurerm_resource_group" "test" { resource "azurerm_automation_account" "test" { name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - + 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}" - account_name = "${azurerm_automation_account.test.name}" - base64 = "%s" + name = "acctest-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + base64 = "%s" } `, rInt, location, rInt, rInt, testCertBase64) } @@ -267,12 +222,11 @@ func testAccAzureRMAutomationCertificate_requiresImport(rInt int, location strin %s resource "azurerm_automation_certificate" "import" { - name = "${azurerm_automation_certificate.test.name}" - resource_group_name = "${azurerm_automation_certificate.test.resource_group_name}" - account_name = "${azurerm_automation_certificate.test.account_name}" - base64 = "${azurerm_automation_certificate.test.base64}" - is_exportable = "${azurerm_automation_certificate.test.is_exportable}" - thumbprint = "${azurerm_automation_certificate.test.username}" + name = azurerm_automation_certificate.test.name + resource_group_name = azurerm_automation_certificate.test.resource_group_name + automation_account_name = azurerm_automation_certificate.test.account_name + base64 = azurerm_automation_certificate.test.base64 + thumbprint = azurerm_automation_certificate.test.thumbprint } `, template) } @@ -286,43 +240,17 @@ resource "azurerm_resource_group" "test" { resource "azurerm_automation_account" "test" { name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - + 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}" - account_name = "${azurerm_automation_account.test.name}" - base64 = "%s" - description = "This is a test certificate for terraform acceptance test" -} -`, rInt, location, rInt, rInt, testCertBase64) -} - -func testAccAzureRMAutomationCertificate_rename(rInt int, location string) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_automation_account" "test" { - name = "acctest-%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-updated" - resource_group_name = "${azurerm_resource_group.test.name}" - account_name = "${azurerm_automation_account.test.name}" - base64 = "%s" - description = "This is a test certificate for terraform acceptance test" + name = "acctest-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + base64 = "%s" + description = "This is a test certificate for terraform acceptance test" } `, rInt, location, rInt, rInt, testCertBase64) } @@ -336,18 +264,17 @@ resource "azurerm_resource_group" "test" { resource "azurerm_automation_account" "test" { name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - + 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}" - account_name = "${azurerm_automation_account.test.name}" - base64 = "%s" - description = "This is a test certificate for terraform acceptance test" + name = "acctest-%d" + resource_group_name = azurerm_resource_group.test.name + automation_account_name = azurerm_automation_account.test.name + base64 = "%s" + description = "This is a test certificate for terraform acceptance test" } `, rInt, location, rInt, rInt, testCertBase64) } From 4230533efe1674abfbfcfd85a9b93be909fe2528 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Wed, 18 Dec 2019 14:05:31 +0100 Subject: [PATCH 11/13] r/automation_certificate: minor test fixes --- ...resource_arm_automation_certificate_test.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/azurerm/resource_arm_automation_certificate_test.go b/azurerm/resource_arm_automation_certificate_test.go index c04a65246ce8..d32d7b991a6e 100644 --- a/azurerm/resource_arm_automation_certificate_test.go +++ b/azurerm/resource_arm_automation_certificate_test.go @@ -35,6 +35,12 @@ func TestAccAzureRMAutomationCertificate_basic(t *testing.T) { testCheckAzureRMAutomationCertificateExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"base64"}, + }, }, }) } @@ -64,12 +70,6 @@ func TestAccAzureRMAutomationCertificate_requiresImport(t *testing.T) { Config: testAccAzureRMAutomationCertificate_requiresImport(ri, location), ExpectError: testRequiresImportError("azurerm_automation_certificate"), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"base64"}, - }, }, }) } @@ -118,6 +118,12 @@ func TestAccAzureRMAutomationCertificate_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "description", ""), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"base64"}, + }, { Config: testAccAzureRMAutomationCertificate_update(ri, testLocation()), Check: resource.ComposeTestCheckFunc( From d98d154914240b931eb5b3bcf6d2e3828bbf587b Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Wed, 18 Dec 2019 15:00:28 +0100 Subject: [PATCH 12/13] r/automation_certificate: adding a missing subcategory for registry docs --- website/docs/r/automation_certificate.html.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docs/r/automation_certificate.html.markdown b/website/docs/r/automation_certificate.html.markdown index c77e9c1397aa..bbc61c9b8891 100644 --- a/website/docs/r/automation_certificate.html.markdown +++ b/website/docs/r/automation_certificate.html.markdown @@ -1,4 +1,5 @@ --- +subcategory: "Automation" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_automation_certificate" sidebar_current: "docs-azurerm-resource-automation-certificate" From 86d0f3687583e6b1c30791fc0dc101cc8d527a9a Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Wed, 18 Dec 2019 15:25:42 +0100 Subject: [PATCH 13/13] removing the unused AutomationClient --- .../internal/services/automation/client.go | 74 ------------------- 1 file changed, 74 deletions(-) delete mode 100644 azurerm/internal/services/automation/client.go diff --git a/azurerm/internal/services/automation/client.go b/azurerm/internal/services/automation/client.go deleted file mode 100644 index 63e1a21a8fc6..000000000000 --- a/azurerm/internal/services/automation/client.go +++ /dev/null @@ -1,74 +0,0 @@ -package automation - -import ( - "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common" -) - -type Client struct { - AccountClient *automation.AccountClient - AgentRegistrationInfoClient *automation.AgentRegistrationInformationClient - CertificateClient *automation.CertificateClient - CredentialClient *automation.CredentialClient - DscConfigurationClient *automation.DscConfigurationClient - DscNodeConfigurationClient *automation.DscNodeConfigurationClient - JobScheduleClient *automation.JobScheduleClient - ModuleClient *automation.ModuleClient - RunbookClient *automation.RunbookClient - RunbookDraftClient *automation.RunbookDraftClient - ScheduleClient *automation.ScheduleClient - VariableClient *automation.VariableClient -} - -func BuildClient(o *common.ClientOptions) *Client { - AccountClient := automation.NewAccountClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&AccountClient.Client, o.ResourceManagerAuthorizer) - - AgentRegistrationInfoClient := automation.NewAgentRegistrationInformationClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&AgentRegistrationInfoClient.Client, o.ResourceManagerAuthorizer) - - CertificateClient := automation.NewCertificateClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&CertificateClient.Client, o.ResourceManagerAuthorizer) - - CredentialClient := automation.NewCredentialClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&CredentialClient.Client, o.ResourceManagerAuthorizer) - - DscConfigurationClient := automation.NewDscConfigurationClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&DscConfigurationClient.Client, o.ResourceManagerAuthorizer) - - DscNodeConfigurationClient := automation.NewDscNodeConfigurationClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&DscNodeConfigurationClient.Client, o.ResourceManagerAuthorizer) - - JobScheduleClient := automation.NewJobScheduleClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&JobScheduleClient.Client, o.ResourceManagerAuthorizer) - - ModuleClient := automation.NewModuleClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&ModuleClient.Client, o.ResourceManagerAuthorizer) - - RunbookClient := automation.NewRunbookClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&RunbookClient.Client, o.ResourceManagerAuthorizer) - - ScheduleClient := automation.NewScheduleClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&ScheduleClient.Client, o.ResourceManagerAuthorizer) - - RunbookDraftClient := automation.NewRunbookDraftClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&RunbookDraftClient.Client, o.ResourceManagerAuthorizer) - - VariableClient := automation.NewVariableClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&VariableClient.Client, o.ResourceManagerAuthorizer) - - return &Client{ - AccountClient: &AccountClient, - AgentRegistrationInfoClient: &AgentRegistrationInfoClient, - CertificateClient: &CertificateClient, - CredentialClient: &CredentialClient, - DscConfigurationClient: &DscConfigurationClient, - DscNodeConfigurationClient: &DscNodeConfigurationClient, - JobScheduleClient: &JobScheduleClient, - ModuleClient: &ModuleClient, - RunbookClient: &RunbookClient, - RunbookDraftClient: &RunbookDraftClient, - ScheduleClient: &ScheduleClient, - VariableClient: &VariableClient, - } -}