From 19bc809b0ae32f6accc4e6e31a5c21b4d9c999d6 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 20 Mar 2020 12:52:39 +0800 Subject: [PATCH 1/5] New resource & data source: azurerm_managed_application_definition --- azurerm/internal/clients/client.go | 131 +- azurerm/internal/provider/services.go | 2 + .../managedapplication/client/client.go | 19 + ...a_source_managed_application_definition.go | 138 ++ .../parse/managed_application_definition.go | 31 + .../managed_application_definition_test.go | 81 + .../managedapplication/registration.go | 33 + ...urce_arm_managed_application_definition.go | 311 +++ ...rce_managed_application_definition_test.go | 38 + ...arm_managed_application_definition_test.go | 328 +++ .../managed_application_definition.go | 53 + .../managed_application_definition_test.go | 209 ++ .../application-definition/main.tf | 25 + .../application-definition/variables.tf | 7 + .../applicationdefinitions.go | 668 ++++++ .../managedapplications/applications.go | 1061 +++++++++ .../2019-07-01/managedapplications/client.go | 161 ++ .../managedapplications/jitrequests.go | 546 +++++ .../2019-07-01/managedapplications/models.go | 1944 +++++++++++++++++ .../2019-07-01/managedapplications/version.go | 30 + vendor/modules.txt | 1 + website/allowed-subcategories | 1 + website/azurerm.erb | 8 + ...naged_application_definition.html.markdown | 76 + ...naged_application_definition.html.markdown | 102 + 25 files changed, 5940 insertions(+), 64 deletions(-) create mode 100644 azurerm/internal/services/managedapplication/client/client.go create mode 100644 azurerm/internal/services/managedapplication/data_source_managed_application_definition.go create mode 100644 azurerm/internal/services/managedapplication/parse/managed_application_definition.go create mode 100644 azurerm/internal/services/managedapplication/parse/managed_application_definition_test.go create mode 100644 azurerm/internal/services/managedapplication/registration.go create mode 100644 azurerm/internal/services/managedapplication/resource_arm_managed_application_definition.go create mode 100644 azurerm/internal/services/managedapplication/tests/data_source_managed_application_definition_test.go create mode 100644 azurerm/internal/services/managedapplication/tests/resource_arm_managed_application_definition_test.go create mode 100644 azurerm/internal/services/managedapplication/validate/managed_application_definition.go create mode 100644 azurerm/internal/services/managedapplication/validate/managed_application_definition_test.go create mode 100644 examples/managed-application/application-definition/main.tf create mode 100644 examples/managed-application/application-definition/variables.tf create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications/applicationdefinitions.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications/applications.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications/client.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications/jitrequests.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications/models.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications/version.go create mode 100644 website/docs/d/managed_application_definition.html.markdown create mode 100644 website/docs/r/managed_application_definition.html.markdown diff --git a/azurerm/internal/clients/client.go b/azurerm/internal/clients/client.go index 035ba1388f4d..1a749c6487b2 100644 --- a/azurerm/internal/clients/client.go +++ b/azurerm/internal/clients/client.go @@ -38,6 +38,7 @@ import ( kusto "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/kusto/client" loganalytics "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics/client" logic "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/logic/client" + managedapplication "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managedapplication/client" managementgroup "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managementgroup/client" maps "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/maps/client" mariadb "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb/client" @@ -79,70 +80,71 @@ type Client struct { Account *ResourceManagerAccount Features features.UserFeatures - AnalysisServices *analysisServices.Client - ApiManagement *apiManagement.Client - AppConfiguration *appConfiguration.Client - AppInsights *applicationInsights.Client - Authorization *authorization.Client - Automation *automation.Client - Batch *batch.Client - Bot *bot.Client - Cdn *cdn.Client - Cognitive *cognitiveServices.Client - Compute *compute.Client - Containers *containerServices.Client - Cosmos *cosmosdb.Client - CostManagement *costmanagement.Client - DatabaseMigration *datamigration.Client - DataBricks *databricks.Client - DataFactory *datafactory.Client - Datalake *datalake.Client - DevSpace *devspace.Client - DevTestLabs *devtestlabs.Client - Dns *dns.Client - EventGrid *eventgrid.Client - Eventhub *eventhub.Client - Frontdoor *frontdoor.Client - HDInsight *hdinsight.Client - HealthCare *healthcare.Client - IoTHub *iothub.Client - IoTCentral *iotcentral.Client - KeyVault *keyvault.Client - Kusto *kusto.Client - LogAnalytics *loganalytics.Client - Logic *logic.Client - ManagementGroups *managementgroup.Client - Maps *maps.Client - MariaDB *mariadb.Client - Media *media.Client - MixedReality *mixedreality.Client - Monitor *monitor.Client - MSI *msi.Client - MSSQL *mssql.Client - MySQL *mysql.Client - NetApp *netapp.Client - Network *network.Client - NotificationHubs *notificationhub.Client - Policy *policy.Client - Portal *portal.Client - Postgres *postgres.Client - PowerBI *powerBI.Client - PrivateDns *privatedns.Client - RecoveryServices *recoveryServices.Client - Redis *redis.Client - Relay *relay.Client - Resource *resource.Client - Search *search.Client - SecurityCenter *securityCenter.Client - ServiceBus *serviceBus.Client - ServiceFabric *serviceFabric.Client - SignalR *signalr.Client - Storage *storage.Client - StreamAnalytics *streamAnalytics.Client - Subscription *subscription.Client - Sql *sql.Client - TrafficManager *trafficManager.Client - Web *web.Client + AnalysisServices *analysisServices.Client + ApiManagement *apiManagement.Client + AppConfiguration *appConfiguration.Client + AppInsights *applicationInsights.Client + Authorization *authorization.Client + Automation *automation.Client + Batch *batch.Client + Bot *bot.Client + Cdn *cdn.Client + Cognitive *cognitiveServices.Client + Compute *compute.Client + Containers *containerServices.Client + Cosmos *cosmosdb.Client + CostManagement *costmanagement.Client + DatabaseMigration *datamigration.Client + DataBricks *databricks.Client + DataFactory *datafactory.Client + Datalake *datalake.Client + DevSpace *devspace.Client + DevTestLabs *devtestlabs.Client + Dns *dns.Client + EventGrid *eventgrid.Client + Eventhub *eventhub.Client + Frontdoor *frontdoor.Client + HDInsight *hdinsight.Client + HealthCare *healthcare.Client + IoTHub *iothub.Client + IoTCentral *iotcentral.Client + KeyVault *keyvault.Client + Kusto *kusto.Client + LogAnalytics *loganalytics.Client + Logic *logic.Client + ManagedApplication *managedapplication.Client + ManagementGroups *managementgroup.Client + Maps *maps.Client + MariaDB *mariadb.Client + Media *media.Client + MixedReality *mixedreality.Client + Monitor *monitor.Client + MSI *msi.Client + MSSQL *mssql.Client + MySQL *mysql.Client + NetApp *netapp.Client + Network *network.Client + NotificationHubs *notificationhub.Client + Policy *policy.Client + Portal *portal.Client + Postgres *postgres.Client + PowerBI *powerBI.Client + PrivateDns *privatedns.Client + RecoveryServices *recoveryServices.Client + Redis *redis.Client + Relay *relay.Client + Resource *resource.Client + Search *search.Client + SecurityCenter *securityCenter.Client + ServiceBus *serviceBus.Client + ServiceFabric *serviceFabric.Client + SignalR *signalr.Client + Storage *storage.Client + StreamAnalytics *streamAnalytics.Client + Subscription *subscription.Client + Sql *sql.Client + TrafficManager *trafficManager.Client + Web *web.Client } // NOTE: it should be possible for this method to become Private once the top level Client's removed @@ -185,6 +187,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error client.Kusto = kusto.NewClient(o) client.LogAnalytics = loganalytics.NewClient(o) client.Logic = logic.NewClient(o) + client.ManagedApplication = managedapplication.NewClient(o) client.ManagementGroups = managementgroup.NewClient(o) client.Maps = maps.NewClient(o) client.MariaDB = mariadb.NewClient(o) diff --git a/azurerm/internal/provider/services.go b/azurerm/internal/provider/services.go index cf855e88dc2c..a70fada17342 100644 --- a/azurerm/internal/provider/services.go +++ b/azurerm/internal/provider/services.go @@ -34,6 +34,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/kusto" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/logic" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managedapplication" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managementgroup" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/maps" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb" @@ -104,6 +105,7 @@ func SupportedServices() []common.ServiceRegistration { kusto.Registration{}, loganalytics.Registration{}, logic.Registration{}, + managedapplication.Registration{}, managementgroup.Registration{}, maps.Registration{}, mariadb.Registration{}, diff --git a/azurerm/internal/services/managedapplication/client/client.go b/azurerm/internal/services/managedapplication/client/client.go new file mode 100644 index 000000000000..2fac84201466 --- /dev/null +++ b/azurerm/internal/services/managedapplication/client/client.go @@ -0,0 +1,19 @@ +package client + +import ( + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common" +) + +type Client struct { + ApplicationDefinitionClient *managedapplications.ApplicationDefinitionsClient +} + +func NewClient(o *common.ClientOptions) *Client { + applicationDefinitionClient := managedapplications.NewApplicationDefinitionsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&applicationDefinitionClient.Client, o.ResourceManagerAuthorizer) + + return &Client{ + ApplicationDefinitionClient: &applicationDefinitionClient, + } +} diff --git a/azurerm/internal/services/managedapplication/data_source_managed_application_definition.go b/azurerm/internal/services/managedapplication/data_source_managed_application_definition.go new file mode 100644 index 000000000000..3383815ec81d --- /dev/null +++ b/azurerm/internal/services/managedapplication/data_source_managed_application_definition.go @@ -0,0 +1,138 @@ +package managedapplication + +import ( + "fmt" + "time" + + "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/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managedapplication/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmManagedApplicationDefinition() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmManagedApplicationDefinitionRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.ManagedApplicationDefinitionName, + }, + + "location": azure.SchemaLocationForDataSource(), + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "authorization": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "role_definition_id": { + Type: schema.TypeString, + Computed: true, + }, + "service_principal_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "create_ui_definition": { + Type: schema.TypeString, + Computed: true, + }, + + "description": { + Type: schema.TypeString, + Computed: true, + }, + + "display_name": { + Type: schema.TypeString, + Computed: true, + }, + + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + + "lock_level": { + Type: schema.TypeString, + Computed: true, + }, + + "main_template": { + Type: schema.TypeString, + Computed: true, + }, + + "package_file_uri": { + Type: schema.TypeString, + Computed: true, + }, + + "tags": tags.SchemaDataSource(), + }, + } +} + +func dataSourceArmManagedApplicationDefinitionRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).ManagedApplication.ApplicationDefinitionClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Failed: Managed Application Definition (Managed Application Definition Name %q / Resource Group %q) was not found", name, resourceGroup) + } + return fmt.Errorf("Failure reading Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + if props := resp.ApplicationDefinitionProperties; props != nil { + if err := d.Set("authorization", flattenArmManagedApplicationDefinitionAuthorization(props.Authorizations)); err != nil { + return fmt.Errorf("Failure setting `authorization`: %+v", err) + } + d.Set("description", props.Description) + d.Set("display_name", props.DisplayName) + d.Set("enabled", props.IsEnabled) + d.Set("lock_level", string(props.LockLevel)) + } + if v, ok := d.GetOk("create_ui_definition"); ok { + d.Set("create_ui_definition", v.(string)) + } + if v, ok := d.GetOk("main_template"); ok { + d.Set("main_template", v.(string)) + } + if v, ok := d.GetOk("package_file_uri"); ok { + d.Set("package_file_uri", v.(string)) + } + + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("API returns a nil/empty id on Managed Application Definition %q (Resource Group %q): %+v", name, resourceGroup, err) + } + d.SetId(*resp.ID) + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/managedapplication/parse/managed_application_definition.go b/azurerm/internal/services/managedapplication/parse/managed_application_definition.go new file mode 100644 index 000000000000..4266abef7a8a --- /dev/null +++ b/azurerm/internal/services/managedapplication/parse/managed_application_definition.go @@ -0,0 +1,31 @@ +package parse + +import ( + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type ManagedApplicationDefinitionId struct { + Name string + ResourceGroup string +} + +func ManagedApplicationDefinitionID(input string) (*ManagedApplicationDefinitionId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + account := ManagedApplicationDefinitionId{ + ResourceGroup: id.ResourceGroup, + } + + if account.Name, err = id.PopSegment("applicationDefinitions"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &account, nil +} diff --git a/azurerm/internal/services/managedapplication/parse/managed_application_definition_test.go b/azurerm/internal/services/managedapplication/parse/managed_application_definition_test.go new file mode 100644 index 000000000000..fd62c8929f7e --- /dev/null +++ b/azurerm/internal/services/managedapplication/parse/managed_application_definition_test.go @@ -0,0 +1,81 @@ +package parse + +import ( + "testing" +) + +func TestManagedApplicationDefinitionID(t *testing.T) { + testData := []struct { + input string + expected *ManagedApplicationDefinitionId + }{ + { + input: "", + expected: nil, + }, + { + input: "/subscriptions/00000000-0000-0000-0000-000000000000", + expected: nil, + }, + { + input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups", + expected: nil, + }, + { + input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/hello", + expected: nil, + }, + { + input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/hello/providers", + expected: nil, + }, + { + input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/hello/providers/Microsoft.Solutions", + expected: nil, + }, + { + input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/hello/providers/Microsoft.Solutions/applicationDefinitions", + expected: nil, + }, + { + input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/hello/providers/Microsoft.Solutions/applicationDefinitions/appDef1", + expected: &ManagedApplicationDefinitionId{ + Name: "appDef1", + ResourceGroup: "hello", + }, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q..", v.input) + actual, err := ManagedApplicationDefinitionID(v.input) + + // if we get something there shouldn't be an error + if v.expected != nil && err == nil { + continue + } + + // if nothing's expected we should get an error + if v.expected == nil && err != nil { + continue + } + + if v.expected == nil && actual == nil { + continue + } + + if v.expected == nil && actual != nil { + t.Fatalf("Expected nothing but got %+v", actual) + } + if v.expected != nil && actual == nil { + t.Fatalf("Expected %+v but got nil", actual) + } + + if v.expected.ResourceGroup != actual.ResourceGroup { + t.Fatalf("Expected ResourceGroup to be %q but got %q", v.expected.ResourceGroup, actual.ResourceGroup) + } + if v.expected.Name != actual.Name { + t.Fatalf("Expected Name to be %q but got %q", v.expected.Name, actual.Name) + } + } +} diff --git a/azurerm/internal/services/managedapplication/registration.go b/azurerm/internal/services/managedapplication/registration.go new file mode 100644 index 000000000000..73c8012166e6 --- /dev/null +++ b/azurerm/internal/services/managedapplication/registration.go @@ -0,0 +1,33 @@ +package managedapplication + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +type Registration struct{} + +// Name is the name of this Service +func (r Registration) Name() string { + return "ManagedApplication" +} + +// WebsiteCategories returns a list of categories which can be used for the sidebar +func (r Registration) WebsiteCategories() []string { + return []string{ + "ManagedApplication", + } +} + +// SupportedDataSources returns the supported Data Sources supported by this Service +func (r Registration) SupportedDataSources() map[string]*schema.Resource { + return map[string]*schema.Resource{ + "azurerm_managed_application_definition": dataSourceArmManagedApplicationDefinition(), + } +} + +// SupportedResources returns the supported Resources supported by this Service +func (r Registration) SupportedResources() map[string]*schema.Resource { + return map[string]*schema.Resource{ + "azurerm_managed_application_definition": resourceArmManagedApplicationDefinition(), + } +} diff --git a/azurerm/internal/services/managedapplication/resource_arm_managed_application_definition.go b/azurerm/internal/services/managedapplication/resource_arm_managed_application_definition.go new file mode 100644 index 000000000000..118b2ce2acf7 --- /dev/null +++ b/azurerm/internal/services/managedapplication/resource_arm_managed_application_definition.go @@ -0,0 +1,311 @@ +package managedapplication + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications" + "github.com/hashicorp/go-azure-helpers/response" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/structure" + "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/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managedapplication/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managedapplication/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + 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 resourceArmManagedApplicationDefinition() *schema.Resource { + return &schema.Resource{ + Create: resourceArmManagedApplicationDefinitionCreateUpdate, + Read: resourceArmManagedApplicationDefinitionRead, + Update: resourceArmManagedApplicationDefinitionCreateUpdate, + Delete: resourceArmManagedApplicationDefinitionDelete, + + Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error { + _, err := parse.ManagedApplicationDefinitionID(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.ManagedApplicationDefinitionName, + }, + + "location": azure.SchemaLocation(), + + "resource_group_name": azure.SchemaResourceGroupName(), + + "authorization": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "role_definition_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsUUID, + }, + "service_principal_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsUUID, + }, + }, + }, + }, + + "create_ui_definition": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsJSON, + DiffSuppressFunc: structure.SuppressJsonDiff, + ConflictsWith: []string{"package_file_uri"}, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.ManagedApplicationDefinitionDescription, + }, + + "display_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.ManagedApplicationDefinitionDisplayName, + }, + + "enabled": { + Type: schema.TypeBool, + Optional: true, + }, + + "lock_level": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(managedapplications.CanNotDelete), + string(managedapplications.None), + string(managedapplications.ReadOnly), + }, false), + }, + + "main_template": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsJSON, + DiffSuppressFunc: structure.SuppressJsonDiff, + ConflictsWith: []string{"package_file_uri"}, + }, + + "package_file_uri": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.IsURLWithHTTPS, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmManagedApplicationDefinitionCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).ManagedApplication.ApplicationDefinitionClient + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroupName := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroupName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Failure checking for present of existing Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroupName, err) + } + } + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_managed_application_definition", *existing.ID) + } + } + + location := azure.NormalizeLocation(d.Get("location").(string)) + authorizations := d.Get("authorization").(*schema.Set).List() + displayName := d.Get("display_name").(string) + description := d.Get("description").(string) + enabled := d.Get("enabled").(bool) + lockLevel := d.Get("lock_level").(string) + t := d.Get("tags").(map[string]interface{}) + + parameters := managedapplications.ApplicationDefinition{ + Location: utils.String(location), + ApplicationDefinitionProperties: &managedapplications.ApplicationDefinitionProperties{ + Authorizations: expandArmManagedApplicationDefinitionAuthorization(authorizations), + Description: utils.String(description), + DisplayName: utils.String(displayName), + IsEnabled: utils.Bool(enabled), + LockLevel: managedapplications.ApplicationLockLevel(lockLevel), + }, + Tags: tags.Expand(t), + } + + if v, ok := d.GetOk("create_ui_definition"); ok { + parameters.CreateUIDefinition = utils.String(v.(string)) + } + + if v, ok := d.GetOk("main_template"); ok { + parameters.MainTemplate = utils.String(v.(string)) + } + + if v, ok := d.GetOk("package_file_uri"); ok { + parameters.PackageFileURI = utils.String(v.(string)) + } + + future, err := client.CreateOrUpdate(ctx, resourceGroupName, name, parameters) + if err != nil { + return fmt.Errorf("Failure creating Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroupName, err) + } + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Failure waiting for creation of Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroupName, err) + } + + resp, err := client.Get(ctx, resourceGroupName, name) + if err != nil { + return fmt.Errorf("Failure retrieving Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroupName, err) + } + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("Cannot read Managed Application Definition (Managed Application Definition Name %q / Resource Group %q) ID", name, resourceGroupName) + } + d.SetId(*resp.ID) + + return resourceArmManagedApplicationDefinitionRead(d, meta) +} + +func resourceArmManagedApplicationDefinitionRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).ManagedApplication.ApplicationDefinitionClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.ManagedApplicationDefinitionID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] Managed Application Definition %q does not exist - removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("Failure reading Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + } + + d.Set("name", id.Name) + d.Set("resource_group_name", id.ResourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + if props := resp.ApplicationDefinitionProperties; props != nil { + if err := d.Set("authorization", flattenArmManagedApplicationDefinitionAuthorization(props.Authorizations)); err != nil { + return fmt.Errorf("Failure setting `authorization`: %+v", err) + } + d.Set("description", props.Description) + d.Set("display_name", props.DisplayName) + d.Set("enabled", props.IsEnabled) + d.Set("lock_level", string(props.LockLevel)) + } + if v, ok := d.GetOk("create_ui_definition"); ok { + d.Set("create_ui_definition", v.(string)) + } + if v, ok := d.GetOk("main_template"); ok { + d.Set("main_template", v.(string)) + } + if v, ok := d.GetOk("package_file_uri"); ok { + d.Set("package_file_uri", v.(string)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmManagedApplicationDefinitionDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).ManagedApplication.ApplicationDefinitionClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.ManagedApplicationDefinitionID(d.Id()) + if err != nil { + return err + } + + future, err := client.Delete(ctx, id.ResourceGroup, id.Name) + if err != nil { + return fmt.Errorf("Failure deleting Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + if !response.WasNotFound(future.Response()) { + return fmt.Errorf("Failure waiting for deleting Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + } + } + + return nil +} + +func expandArmManagedApplicationDefinitionAuthorization(input []interface{}) *[]managedapplications.ApplicationAuthorization { + results := make([]managedapplications.ApplicationAuthorization, 0) + for _, item := range input { + v := item.(map[string]interface{}) + result := managedapplications.ApplicationAuthorization{ + RoleDefinitionID: utils.String(v["role_definition_id"].(string)), + PrincipalID: utils.String(v["service_principal_id"].(string)), + } + + results = append(results, result) + } + return &results +} + +func flattenArmManagedApplicationDefinitionAuthorization(input *[]managedapplications.ApplicationAuthorization) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range *input { + servicePrincipalId := "" + if item.PrincipalID != nil { + servicePrincipalId = *item.PrincipalID + } + + roleDefinitionId := "" + if item.RoleDefinitionID != nil { + roleDefinitionId = *item.RoleDefinitionID + } + + results = append(results, map[string]interface{}{ + "role_definition_id": roleDefinitionId, + "service_principal_id": servicePrincipalId, + }) + } + + return results +} diff --git a/azurerm/internal/services/managedapplication/tests/data_source_managed_application_definition_test.go b/azurerm/internal/services/managedapplication/tests/data_source_managed_application_definition_test.go new file mode 100644 index 000000000000..81b2826b5cbc --- /dev/null +++ b/azurerm/internal/services/managedapplication/tests/data_source_managed_application_definition_test.go @@ -0,0 +1,38 @@ +package tests + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccDataSourceAzureRMManagedApplicationDefinition_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_managed_application_definition", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceManagedApplicationDefinition_basic(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(data.ResourceName, "name"), + ), + }, + }, + }) +} + +func testAccDataSourceManagedApplicationDefinition_basic(data acceptance.TestData) string { + config := testAccAzureRMManagedApplicationDefinition_basic(data) + return fmt.Sprintf(` +%s + +data "azurerm_managed_application_definition" "test" { + name = azurerm_managed_application_definition.test.name + resource_group_name = azurerm_managed_application_definition.test.resource_group_name +} +`, config) +} diff --git a/azurerm/internal/services/managedapplication/tests/resource_arm_managed_application_definition_test.go b/azurerm/internal/services/managedapplication/tests/resource_arm_managed_application_definition_test.go new file mode 100644 index 000000000000..8100a249e9bc --- /dev/null +++ b/azurerm/internal/services/managedapplication/tests/resource_arm_managed_application_definition_test.go @@ -0,0 +1,328 @@ +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" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managedapplication/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMManagedApplicationDefinition_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_managed_application_definition", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMManagedApplicationDefinitionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMManagedApplicationDefinition_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMManagedApplicationDefinitionExists(data.ResourceName), + ), + }, + data.ImportStep("package_file_uri"), + }, + }) +} + +func TestAccAzureRMManagedApplicationDefinition_requiresImport(t *testing.T) { + if !features.ShouldResourcesBeImported() { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + data := acceptance.BuildTestData(t, "azurerm_managed_application_definition", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMManagedApplicationDefinitionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMManagedApplicationDefinition_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMManagedApplicationDefinitionExists(data.ResourceName), + ), + }, + { + Config: testAccAzureRMManagedApplicationDefinition_requiresImport(data), + ExpectError: acceptance.RequiresImportError("azurerm_managed_application_definition"), + }, + }, + }) +} + +func TestAccAzureRMManagedApplicationDefinition_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_managed_application_definition", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMManagedApplicationDefinitionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMManagedApplicationDefinition_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMManagedApplicationDefinitionExists(data.ResourceName), + ), + }, + data.ImportStep("create_ui_definition", "main_template"), + }, + }) +} + +func TestAccAzureRMManagedApplicationDefinition_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_managed_application_definition", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMManagedApplicationDefinitionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMManagedApplicationDefinition_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMManagedApplicationDefinitionExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "display_name", "TestManagedApplicationDefinition"), + resource.TestCheckResourceAttr(data.ResourceName, "description", "Test Managed Application Definition"), + resource.TestCheckResourceAttr(data.ResourceName, "enabled", "false"), + resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0"), + ), + }, + data.ImportStep("package_file_uri"), + { + Config: testAccAzureRMManagedApplicationDefinition_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMManagedApplicationDefinitionExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "display_name", "UpdatedTestManagedApplicationDefinition"), + resource.TestCheckResourceAttr(data.ResourceName, "description", "Updated Test Managed Application Definition"), + resource.TestCheckResourceAttr(data.ResourceName, "enabled", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(data.ResourceName, "tags.ENV", "Test"), + ), + }, + data.ImportStep("create_ui_definition", "main_template", "package_file_uri"), + }, + }) +} + +func testCheckAzureRMManagedApplicationDefinitionExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Managed Application Definition not found: %s", resourceName) + } + + id, err := parse.ManagedApplicationDefinitionID(rs.Primary.ID) + if err != nil { + return err + } + + client := acceptance.AzureProvider.Meta().(*clients.Client).ManagedApplication.ApplicationDefinitionClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + if resp, err := client.Get(ctx, id.ResourceGroup, id.Name); err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Managed Application Definition %q (Resource Group %q) does not exist", id.Name, id.ResourceGroup) + } + return fmt.Errorf("Bad: Get on ManagedApplication.ApplicationDefinitionClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMManagedApplicationDefinitionDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).ManagedApplication.ApplicationDefinitionClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_managed_application_definition" { + continue + } + + id, err := parse.ManagedApplicationDefinitionID(rs.Primary.ID) + if err != nil { + return err + } + + if resp, err := client.Get(ctx, id.ResourceGroup, id.Name); err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Get on ManagedApplication.ApplicationDefinitionClient: %+v", err) + } + } + + return nil + } + + return nil +} + +func testAccAzureRMManagedApplicationDefinition_basic(data acceptance.TestData) string { + template := testAccAzureRMManagedApplicationDefinition_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_managed_application_definition" "test" { + name = "acctestAppDef%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + lock_level = "ReadOnly" + package_file_uri = "https://github.com/Azure/azure-managedapp-samples/raw/master/Managed Application Sample Packages/201-managed-storage-account/managedstorage.zip" + display_name = "TestManagedApplicationDefinition" + description = "Test Managed Application Definition" + enabled = false + + authorization { + service_principal_id = "${data.azurerm_client_config.current.object_id}" + role_definition_id = "b24988ac-6180-42a0-ab88-20f7382dd24c" + } +} +`, template, data.RandomInteger) +} + +func testAccAzureRMManagedApplicationDefinition_requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_managed_application_definition" "import" { + name = "${azurerm_managed_application_definition.test.name}" + location = "${azurerm_managed_application_definition.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, testAccAzureRMManagedApplicationDefinition_basic(data)) +} + +func testAccAzureRMManagedApplicationDefinition_complete(data acceptance.TestData) string { + template := testAccAzureRMManagedApplicationDefinition_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_managed_application_definition" "test" { + name = "acctestAppDef%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + lock_level = "ReadOnly" + display_name = "UpdatedTestManagedApplicationDefinition" + description = "Updated Test Managed Application Definition" + enabled = true + create_ui_definition = <azurerm_logic_app_workflow +
  • + azurerm_managed_application_definition +
  • +
  • azurerm_managed_disk
  • @@ -973,6 +977,10 @@ azurerm_linux_virtual_machine_scale_set +
  • + azurerm_managed_application_definition +
  • +
  • azurerm_managed_disk
  • diff --git a/website/docs/d/managed_application_definition.html.markdown b/website/docs/d/managed_application_definition.html.markdown new file mode 100644 index 000000000000..2af99e2ae617 --- /dev/null +++ b/website/docs/d/managed_application_definition.html.markdown @@ -0,0 +1,76 @@ +--- +subcategory: "ManagedApplication" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_managed_application_definition" +description: |- + Gets information about an existing Managed Application Definition +--- + +# Data Source: azurerm_managed_application_definition + +Uses this data source to access information about an existing Managed Application Definition. + +## Managed Application Definition Usage + +```hcl +provider "azurerm" { + features {} +} + +data "azurerm_managed_application_definition" "example" { + name = "example-managedappdef" + resource_group_name = "example-resources" +} + +output "id" { + value = data.azurerm_managed_application_definition.existing.id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Managed Application Definition. + +* `resource_group_name` - (Required) Specifies the name of the Resource Group where this Managed Application Definition exists. + +## Attributes Reference + +The following attributes are exported: + +* `location` - The Azure location where the resource exists. + +* `authorization` - One or more `authorization` block defined below. + +* `create_ui_definition` - The createUiDefinition json for the backing template with Microsoft.Solutions/applications resource. + +* `description` - The managed application definition description. + +* `display_name` - The managed application definition display name. + +* `enabled` - The value indicating whether the package is enabled or not. + +* `lock_level` - The managed application lock level. + +* `main_template` - The inline main template json which has resources to be provisioned. + +* `package_file_uri` - The managed application definition package file Uri. + +* `tags` - A mapping of tags to assign to the resource. + +--- + +An `authorization` block supports the following: + +* `role_definition_id` - The provider's role definition identifier. + +* `service_principal_id` - The provider's principal identifier. + +--- + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the DataBox. diff --git a/website/docs/r/managed_application_definition.html.markdown b/website/docs/r/managed_application_definition.html.markdown new file mode 100644 index 000000000000..3fe284c514e4 --- /dev/null +++ b/website/docs/r/managed_application_definition.html.markdown @@ -0,0 +1,102 @@ +--- +subcategory: "ManagedApplication" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_managed_application_definition" +description: |- + Manages a Managed Application Definition. +--- + +# azurerm_managed_application_definition + +Manages a Managed Application Definition. + +## Managed Application Definition Usage + +```hcl +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_managed_application_definition" "example" { + name = "example-managedapplicationdefinition" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + lock_level = "ReadOnly" + package_file_uri = "https://github.com/Azure/azure-managedapp-samples/raw/master/Managed Application Sample Packages/201-managed-storage-account/managedstorage.zip" + display_name = "TestManagedApplicationDefinition" + description = "Test Managed Application Definition" + + authorization { + service_principal_id = data.azurerm_client_config.current.object_id + role_definition_id = "a094b430-dad3-424d-ae58-13f72fd72591" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Managed Application Definition. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the Resource Group where the Managed Application Definition should exist. Changing this forces a new resource to be created. + +* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. + +* `authorization` - (Required) One or more `authorization` block defined below. + +* `create_ui_definition` - (Optional) Specifies the createUiDefinition json for the backing template with Microsoft.Solutions/applications resource. + +* `display_name` - (Optional) Specifies the managed application definition display name. + +* `description` - (Optional) Specifies the managed application definition description. + +* `enabled` - (Optional) Specifies the value indicating whether the package is enabled or not. + +* `lock_level` - (Optional) Specifies the managed application lock level. Valid values include `CanNotDelete`, `None`, `ReadOnly`. Changing this forces a new resource to be created. + +* `main_template` - (Optional) Specifies the inline main template json which has resources to be provisioned. + +* `package_file_uri` - (Optional) Specifies the managed application definition package file Uri. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +--- + +An `authorization` block supports the following: + +* `role_definition_id` - (Required) Specifies the provider's role definition identifier. This role will define all the permissions that the provider must have on the managed application's container resource group. This role definition cannot have permission to delete the resource group. + +* `service_principal_id` - (Required) Specifies the provider's principal identifier. This is the identity that the provider will use to call ARM to manage the managed application resources. + +--- + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Managed Application Definition. + +## 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 Managed Application Definition. +* `update` - (Defaults to 30 minutes) Used when updating the Managed Application Definition. +* `read` - (Defaults to 5 minutes) Used when retrieving the Managed Application Definition. +* `delete` - (Defaults to 30 minutes) Used when deleting the Managed Application Definition. + +## Import + +Managed Application Definition can be imported using the `resource id`, e.g. + +```shell +$ terraform import azurerm_managed_application_definition.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Solutions/applicationDefinitions/appDefinition1 +``` From e71b245c2b8049f50054e93b4e0b5c9ae8105957 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 20 Mar 2020 17:58:28 +0800 Subject: [PATCH 2/5] Update code --- ...a_source_managed_application_definition.go | 4 +- .../managedapplication/registration.go | 4 +- ...urce_arm_managed_application_definition.go | 60 +++++++++---------- ...rce_managed_application_definition_test.go | 5 +- ...arm_managed_application_definition_test.go | 38 ++++++------ .../managed_application_definition.go | 6 +- website/allowed-subcategories | 2 +- ...naged_application_definition.html.markdown | 4 +- ...naged_application_definition.html.markdown | 8 +-- 9 files changed, 64 insertions(+), 67 deletions(-) diff --git a/azurerm/internal/services/managedapplication/data_source_managed_application_definition.go b/azurerm/internal/services/managedapplication/data_source_managed_application_definition.go index 3383815ec81d..9fdbcaf26c75 100644 --- a/azurerm/internal/services/managedapplication/data_source_managed_application_definition.go +++ b/azurerm/internal/services/managedapplication/data_source_managed_application_definition.go @@ -64,7 +64,7 @@ func dataSourceArmManagedApplicationDefinition() *schema.Resource { Computed: true, }, - "enabled": { + "package_enabled": { Type: schema.TypeBool, Computed: true, }, @@ -116,7 +116,7 @@ func dataSourceArmManagedApplicationDefinitionRead(d *schema.ResourceData, meta } d.Set("description", props.Description) d.Set("display_name", props.DisplayName) - d.Set("enabled", props.IsEnabled) + d.Set("package_enabled", props.IsEnabled) d.Set("lock_level", string(props.LockLevel)) } if v, ok := d.GetOk("create_ui_definition"); ok { diff --git a/azurerm/internal/services/managedapplication/registration.go b/azurerm/internal/services/managedapplication/registration.go index 73c8012166e6..ee96e077d6cf 100644 --- a/azurerm/internal/services/managedapplication/registration.go +++ b/azurerm/internal/services/managedapplication/registration.go @@ -8,13 +8,13 @@ type Registration struct{} // Name is the name of this Service func (r Registration) Name() string { - return "ManagedApplication" + return "Managed Application" } // WebsiteCategories returns a list of categories which can be used for the sidebar func (r Registration) WebsiteCategories() []string { return []string{ - "ManagedApplication", + "Managed Application", } } diff --git a/azurerm/internal/services/managedapplication/resource_arm_managed_application_definition.go b/azurerm/internal/services/managedapplication/resource_arm_managed_application_definition.go index 118b2ce2acf7..31f8802b191d 100644 --- a/azurerm/internal/services/managedapplication/resource_arm_managed_application_definition.go +++ b/azurerm/internal/services/managedapplication/resource_arm_managed_application_definition.go @@ -6,14 +6,11 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications" - "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/structure" "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/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managedapplication/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managedapplication/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" @@ -73,11 +70,10 @@ func resourceArmManagedApplicationDefinition() *schema.Resource { }, "create_ui_definition": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringIsJSON, - DiffSuppressFunc: structure.SuppressJsonDiff, - ConflictsWith: []string{"package_file_uri"}, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsJSON, + ConflictsWith: []string{"package_file_uri"}, }, "description": { @@ -92,9 +88,10 @@ func resourceArmManagedApplicationDefinition() *schema.Resource { ValidateFunc: validate.ManagedApplicationDefinitionDisplayName, }, - "enabled": { + "package_enabled": { Type: schema.TypeBool, Optional: true, + Default: true, }, "lock_level": { @@ -109,17 +106,16 @@ func resourceArmManagedApplicationDefinition() *schema.Resource { }, "main_template": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringIsJSON, - DiffSuppressFunc: structure.SuppressJsonDiff, - ConflictsWith: []string{"package_file_uri"}, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsJSON, + ConflictsWith: []string{"package_file_uri"}, }, "package_file_uri": { Type: schema.TypeString, Optional: true, - ValidateFunc: validation.IsURLWithHTTPS, + ValidateFunc: validation.IsURLWithHTTPorHTTPS, }, "tags": tags.Schema(), @@ -129,17 +125,17 @@ func resourceArmManagedApplicationDefinition() *schema.Resource { func resourceArmManagedApplicationDefinitionCreateUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).ManagedApplication.ApplicationDefinitionClient - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() name := d.Get("name").(string) resourceGroupName := d.Get("resource_group_name").(string) - if features.ShouldResourcesBeImported() && d.IsNewResource() { + if d.IsNewResource() { existing, err := client.Get(ctx, resourceGroupName, name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Failure checking for present of existing Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroupName, err) + return fmt.Errorf("failure checking for present of existing Managed Application Definition Name %q (Resource Group %q): %+v", name, resourceGroupName, err) } } if existing.ID != nil && *existing.ID != "" { @@ -151,7 +147,7 @@ func resourceArmManagedApplicationDefinitionCreateUpdate(d *schema.ResourceData, authorizations := d.Get("authorization").(*schema.Set).List() displayName := d.Get("display_name").(string) description := d.Get("description").(string) - enabled := d.Get("enabled").(bool) + packageEnabled := d.Get("package_enabled").(bool) lockLevel := d.Get("lock_level").(string) t := d.Get("tags").(map[string]interface{}) @@ -161,7 +157,7 @@ func resourceArmManagedApplicationDefinitionCreateUpdate(d *schema.ResourceData, Authorizations: expandArmManagedApplicationDefinitionAuthorization(authorizations), Description: utils.String(description), DisplayName: utils.String(displayName), - IsEnabled: utils.Bool(enabled), + IsEnabled: utils.Bool(packageEnabled), LockLevel: managedapplications.ApplicationLockLevel(lockLevel), }, Tags: tags.Expand(t), @@ -175,24 +171,28 @@ func resourceArmManagedApplicationDefinitionCreateUpdate(d *schema.ResourceData, parameters.MainTemplate = utils.String(v.(string)) } + if (parameters.CreateUIDefinition != nil && parameters.MainTemplate == nil) || (parameters.CreateUIDefinition == nil && parameters.MainTemplate != nil) { + return fmt.Errorf("`create_ui_definition` and `main_template` should be set or not set together") + } + if v, ok := d.GetOk("package_file_uri"); ok { parameters.PackageFileURI = utils.String(v.(string)) } future, err := client.CreateOrUpdate(ctx, resourceGroupName, name, parameters) if err != nil { - return fmt.Errorf("Failure creating Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroupName, err) + return fmt.Errorf("failure creating Managed Application Definition %q (Resource Group %q): %+v", name, resourceGroupName, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Failure waiting for creation of Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroupName, err) + return fmt.Errorf("failure waiting for creation of Managed Application Definition %q (Resource Group %q): %+v", name, resourceGroupName, err) } resp, err := client.Get(ctx, resourceGroupName, name) if err != nil { - return fmt.Errorf("Failure retrieving Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", name, resourceGroupName, err) + return fmt.Errorf("failure retrieving Managed Application Definition %q (Resource Group %q): %+v", name, resourceGroupName, err) } if resp.ID == nil || *resp.ID == "" { - return fmt.Errorf("Cannot read Managed Application Definition (Managed Application Definition Name %q / Resource Group %q) ID", name, resourceGroupName) + return fmt.Errorf("cannot read Managed Application Definition %q (Resource Group %q) ID", name, resourceGroupName) } d.SetId(*resp.ID) @@ -216,7 +216,7 @@ func resourceArmManagedApplicationDefinitionRead(d *schema.ResourceData, meta in d.SetId("") return nil } - return fmt.Errorf("Failure reading Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("failure reading Managed Application Definition %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } d.Set("name", id.Name) @@ -226,11 +226,11 @@ func resourceArmManagedApplicationDefinitionRead(d *schema.ResourceData, meta in } if props := resp.ApplicationDefinitionProperties; props != nil { if err := d.Set("authorization", flattenArmManagedApplicationDefinitionAuthorization(props.Authorizations)); err != nil { - return fmt.Errorf("Failure setting `authorization`: %+v", err) + return fmt.Errorf("failure setting `authorization`: %+v", err) } d.Set("description", props.Description) d.Set("display_name", props.DisplayName) - d.Set("enabled", props.IsEnabled) + d.Set("package_enabled", props.IsEnabled) d.Set("lock_level", string(props.LockLevel)) } if v, ok := d.GetOk("create_ui_definition"); ok { @@ -258,13 +258,11 @@ func resourceArmManagedApplicationDefinitionDelete(d *schema.ResourceData, meta future, err := client.Delete(ctx, id.ResourceGroup, id.Name) if err != nil { - return fmt.Errorf("Failure deleting Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("failure deleting Managed Application Definition %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - if !response.WasNotFound(future.Response()) { - return fmt.Errorf("Failure waiting for deleting Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", id.Name, id.ResourceGroup, err) - } + return fmt.Errorf("failure waiting for deleting Managed Application Definition (Managed Application Definition Name %q / Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } return nil diff --git a/azurerm/internal/services/managedapplication/tests/data_source_managed_application_definition_test.go b/azurerm/internal/services/managedapplication/tests/data_source_managed_application_definition_test.go index 81b2826b5cbc..22faf45daaf7 100644 --- a/azurerm/internal/services/managedapplication/tests/data_source_managed_application_definition_test.go +++ b/azurerm/internal/services/managedapplication/tests/data_source_managed_application_definition_test.go @@ -12,8 +12,9 @@ func TestAccDataSourceAzureRMManagedApplicationDefinition_basic(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_managed_application_definition", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMManagedApplicationDefinitionDestroy, Steps: []resource.TestStep{ { Config: testAccDataSourceManagedApplicationDefinition_basic(data), diff --git a/azurerm/internal/services/managedapplication/tests/resource_arm_managed_application_definition_test.go b/azurerm/internal/services/managedapplication/tests/resource_arm_managed_application_definition_test.go index 8100a249e9bc..a1fd57f8b3ae 100644 --- a/azurerm/internal/services/managedapplication/tests/resource_arm_managed_application_definition_test.go +++ b/azurerm/internal/services/managedapplication/tests/resource_arm_managed_application_definition_test.go @@ -51,10 +51,7 @@ func TestAccAzureRMManagedApplicationDefinition_requiresImport(t *testing.T) { testCheckAzureRMManagedApplicationDefinitionExists(data.ResourceName), ), }, - { - Config: testAccAzureRMManagedApplicationDefinition_requiresImport(data), - ExpectError: acceptance.RequiresImportError("azurerm_managed_application_definition"), - }, + data.RequiresImportErrorStep(testAccAzureRMManagedApplicationDefinition_requiresImport), }, }) } @@ -92,7 +89,7 @@ func TestAccAzureRMManagedApplicationDefinition_update(t *testing.T) { testCheckAzureRMManagedApplicationDefinitionExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "display_name", "TestManagedApplicationDefinition"), resource.TestCheckResourceAttr(data.ResourceName, "description", "Test Managed Application Definition"), - resource.TestCheckResourceAttr(data.ResourceName, "enabled", "false"), + resource.TestCheckResourceAttr(data.ResourceName, "package_enabled", "false"), resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0"), ), }, @@ -103,7 +100,7 @@ func TestAccAzureRMManagedApplicationDefinition_update(t *testing.T) { testCheckAzureRMManagedApplicationDefinitionExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "display_name", "UpdatedTestManagedApplicationDefinition"), resource.TestCheckResourceAttr(data.ResourceName, "description", "Updated Test Managed Application Definition"), - resource.TestCheckResourceAttr(data.ResourceName, "enabled", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "package_enabled", "true"), resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "1"), resource.TestCheckResourceAttr(data.ResourceName, "tags.ENV", "Test"), ), @@ -178,10 +175,10 @@ resource "azurerm_managed_application_definition" "test" { package_file_uri = "https://github.com/Azure/azure-managedapp-samples/raw/master/Managed Application Sample Packages/201-managed-storage-account/managedstorage.zip" display_name = "TestManagedApplicationDefinition" description = "Test Managed Application Definition" - enabled = false + package_enabled = false authorization { - service_principal_id = "${data.azurerm_client_config.current.object_id}" + service_principal_id = data.azurerm_client_config.current.object_id role_definition_id = "b24988ac-6180-42a0-ab88-20f7382dd24c" } } @@ -193,9 +190,9 @@ func testAccAzureRMManagedApplicationDefinition_requiresImport(data acceptance.T %s resource "azurerm_managed_application_definition" "import" { - name = "${azurerm_managed_application_definition.test.name}" - location = "${azurerm_managed_application_definition.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = azurerm_managed_application_definition.test.name + location = azurerm_managed_application_definition.test.location + resource_group_name = azurerm_resource_group.test.name } `, testAccAzureRMManagedApplicationDefinition_basic(data)) } @@ -206,13 +203,14 @@ func testAccAzureRMManagedApplicationDefinition_complete(data acceptance.TestDat %s resource "azurerm_managed_application_definition" "test" { - name = "acctestAppDef%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - lock_level = "ReadOnly" - display_name = "UpdatedTestManagedApplicationDefinition" - description = "Updated Test Managed Application Definition" - enabled = true + name = "acctestAppDef%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + lock_level = "ReadOnly" + display_name = "UpdatedTestManagedApplicationDefinition" + description = "Updated Test Managed Application Definition" + package_enabled = true + create_ui_definition = < 60 { errors = append(errors, fmt.Errorf("%q must be between 4 and 60 characters in length.", k)) } @@ -45,7 +45,7 @@ func ManagedApplicationDefinitionDisplayName(v interface{}, k string) (warnings func ManagedApplicationDefinitionDescription(v interface{}, k string) (warnings []string, errors []error) { value := v.(string) - if !regexp.MustCompile(`^[\s\S]{0,200}$`).MatchString(value) { + if len(value) > 200 { errors = append(errors, fmt.Errorf("%q should not exceed 200 characters in length.", k)) } diff --git a/website/allowed-subcategories b/website/allowed-subcategories index 93f29022e9d2..dc533a866421 100644 --- a/website/allowed-subcategories +++ b/website/allowed-subcategories @@ -31,7 +31,7 @@ Key Vault Load Balancer Log Analytics Logic App -ManagedApplication +Managed Application Management Maps Media diff --git a/website/docs/d/managed_application_definition.html.markdown b/website/docs/d/managed_application_definition.html.markdown index 2af99e2ae617..872f607428c7 100644 --- a/website/docs/d/managed_application_definition.html.markdown +++ b/website/docs/d/managed_application_definition.html.markdown @@ -10,7 +10,7 @@ description: |- Uses this data source to access information about an existing Managed Application Definition. -## Managed Application Definition Usage +## Example Usage ```hcl provider "azurerm" { @@ -49,7 +49,7 @@ The following attributes are exported: * `display_name` - The managed application definition display name. -* `enabled` - The value indicating whether the package is enabled or not. +* `package_enabled` - Is enabled on this package? * `lock_level` - The managed application lock level. diff --git a/website/docs/r/managed_application_definition.html.markdown b/website/docs/r/managed_application_definition.html.markdown index 3fe284c514e4..047e187bc820 100644 --- a/website/docs/r/managed_application_definition.html.markdown +++ b/website/docs/r/managed_application_definition.html.markdown @@ -10,7 +10,7 @@ description: |- Manages a Managed Application Definition. -## Managed Application Definition Usage +## Example Usage ```hcl provider "azurerm" { @@ -52,15 +52,15 @@ The following arguments are supported: * `authorization` - (Required) One or more `authorization` block defined below. +* `lock_level` - (Required) Specifies the managed application lock level. Valid values include `CanNotDelete`, `None`, `ReadOnly`. Changing this forces a new resource to be created. + * `create_ui_definition` - (Optional) Specifies the createUiDefinition json for the backing template with Microsoft.Solutions/applications resource. * `display_name` - (Optional) Specifies the managed application definition display name. * `description` - (Optional) Specifies the managed application definition description. -* `enabled` - (Optional) Specifies the value indicating whether the package is enabled or not. - -* `lock_level` - (Optional) Specifies the managed application lock level. Valid values include `CanNotDelete`, `None`, `ReadOnly`. Changing this forces a new resource to be created. +* `package_enabled` - (Optional) Is enabled for this package? Defaults to `true`. * `main_template` - (Optional) Specifies the inline main template json which has resources to be provisioned. From aaecd266d12eb6f8b8a6c9454a1910db0c7b32e6 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 20 Mar 2020 18:31:15 +0800 Subject: [PATCH 3/5] Update code --- website/allowed-subcategories | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/allowed-subcategories b/website/allowed-subcategories index dc533a866421..93f29022e9d2 100644 --- a/website/allowed-subcategories +++ b/website/allowed-subcategories @@ -31,7 +31,7 @@ Key Vault Load Balancer Log Analytics Logic App -Managed Application +ManagedApplication Management Maps Media From 6e820d7f55238318aec294035fda3b72a4b7ff11 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 20 Mar 2020 18:56:40 +0800 Subject: [PATCH 4/5] Update code --- .../validate/managed_application_definition.go | 2 +- .../validate/managed_application_definition_test.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/azurerm/internal/services/managedapplication/validate/managed_application_definition.go b/azurerm/internal/services/managedapplication/validate/managed_application_definition.go index bf9c2369bd8a..63ee9c9804b8 100644 --- a/azurerm/internal/services/managedapplication/validate/managed_application_definition.go +++ b/azurerm/internal/services/managedapplication/validate/managed_application_definition.go @@ -35,7 +35,7 @@ func ManagedApplicationDefinitionName(v interface{}, k string) (warnings []strin func ManagedApplicationDefinitionDisplayName(v interface{}, k string) (warnings []string, errors []error) { value := v.(string) - if len(value) < 4 && len(value) > 60 { + if len(value) < 4 || len(value) > 60 { errors = append(errors, fmt.Errorf("%q must be between 4 and 60 characters in length.", k)) } diff --git a/azurerm/internal/services/managedapplication/validate/managed_application_definition_test.go b/azurerm/internal/services/managedapplication/validate/managed_application_definition_test.go index 4a594bbe6660..0e066d750c49 100644 --- a/azurerm/internal/services/managedapplication/validate/managed_application_definition_test.go +++ b/azurerm/internal/services/managedapplication/validate/managed_application_definition_test.go @@ -113,18 +113,18 @@ func TestManagedApplicationDefinitionDisplayName(t *testing.T) { expected: true, }, { - // 63 chars + // 59 chars input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg", expected: true, }, { - // 64 chars - input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh", + // 60 chars + input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefga", expected: true, }, { - // 65 chars - input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi", + // 61 chars + input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgaa", expected: false, }, } From 286124e3d36ac31aa7a6a57383bdb8b7c946bbbf Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 20 Mar 2020 20:50:00 +0800 Subject: [PATCH 5/5] Update code --- azurerm/internal/services/managedapplication/registration.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/managedapplication/registration.go b/azurerm/internal/services/managedapplication/registration.go index ee96e077d6cf..73c8012166e6 100644 --- a/azurerm/internal/services/managedapplication/registration.go +++ b/azurerm/internal/services/managedapplication/registration.go @@ -8,13 +8,13 @@ type Registration struct{} // Name is the name of this Service func (r Registration) Name() string { - return "Managed Application" + return "ManagedApplication" } // WebsiteCategories returns a list of categories which can be used for the sidebar func (r Registration) WebsiteCategories() []string { return []string{ - "Managed Application", + "ManagedApplication", } }