forked from hashicorp/terraform-provider-azurerm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Resource][Data Source] ACR Scope Map and Tokens (hashicorp#11350)
Supersede hashicorp#9402 after email exchange with @Lucretius which didn't have time to complete it currently. I fixed the comments from last review. Data Source for azurerm_container_registry_token Data Source for azurerm_container_registry_scope_map Resource for azurerm_container_registry_token Resource for azurerm_container_registry_scope_map Documentation for each Tests for each, they all pass running against my own Azure environment. There are passwords for the token which I would like to expose but there is no way to delete them once generated so they didn't really fit into the lifecycle management of the token itself. Perhaps they might be better suited as a separate data source, similar to how we handle the SAS tokens? Also note that these are still both preview features. As such I've vendor-included the SDK preview code and only used it in these specific preview features (see client.go) This PR resolves hashicorp#6505
- Loading branch information
1 parent
3ac9477
commit 2ea8ce8
Showing
23 changed files
with
2,050 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
azurerm/internal/services/containers/container_registry_scope_map_data_source.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package containers | ||
|
||
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/containers/validate" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||
) | ||
|
||
func dataSourceContainerRegistryScopeMap() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceContainerRegistryScopeMapRead, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Read: schema.DefaultTimeout(5 * time.Minute), | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"container_registry_name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validate.ContainerRegistryName, | ||
}, | ||
"resource_group_name": azure.SchemaResourceGroupNameForDataSource(), | ||
"description": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"actions": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceContainerRegistryScopeMapRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Containers.ScopeMapsClient | ||
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
resourceGroup := d.Get("resource_group_name").(string) | ||
containerRegistryName := d.Get("container_registry_name").(string) | ||
name := d.Get("name").(string) | ||
|
||
resp, err := client.Get(ctx, resourceGroup, containerRegistryName, name) | ||
if err != nil { | ||
if utils.ResponseWasNotFound(resp.Response) { | ||
return fmt.Errorf("Container Registry Scope Map %q was not found in Resource Group %q", name, resourceGroup) | ||
} | ||
|
||
return fmt.Errorf("Error making Read request on Scope Map %q (Azure Container Registry %q, Resource Group %q): %+v", name, containerRegistryName, resourceGroup, err) | ||
} | ||
|
||
if resp.ID == nil || *resp.ID == "" { | ||
return fmt.Errorf("retrieving Container Registry Scope Map %q (Azure Container Registry %q, Resource Group %q): `id` was nil", name, containerRegistryName, resourceGroup) | ||
} | ||
|
||
d.SetId(*resp.ID) | ||
d.Set("name", resp.Name) | ||
d.Set("resource_group_name", resourceGroup) | ||
d.Set("container_registry_name", containerRegistryName) | ||
d.Set("description", resp.Description) | ||
d.Set("actions", utils.FlattenStringSlice(resp.Actions)) | ||
|
||
return nil | ||
} |
52 changes: 52 additions & 0 deletions
52
azurerm/internal/services/containers/container_registry_scope_map_data_source_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package containers_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check" | ||
) | ||
|
||
type ContainerRegistryScopeMapDataSource struct { | ||
} | ||
|
||
func TestAccDataSourceContainerRegistryScopeMap_complete(t *testing.T) { | ||
data := acceptance.BuildTestData(t, "data.azurerm_container_registry_scope_map", "test") | ||
r := ContainerRegistryScopeMapDataSource{} | ||
|
||
data.DataSourceTest(t, []resource.TestStep{ | ||
{ | ||
Config: r.complete(data), | ||
Check: resource.ComposeTestCheckFunc( | ||
check.That(data.ResourceName).Key("name").Exists(), | ||
check.That(data.ResourceName).Key("resource_group_name").Exists(), | ||
check.That(data.ResourceName).Key("container_registry_name").Exists(), | ||
check.That(data.ResourceName).Key("description").HasValue("A test scope map"), | ||
check.That(data.ResourceName).Key("actions.#").HasValue("1"), | ||
check.That(data.ResourceName).Key("actions.0").HasValue("repositories/testrepo/content/read"), | ||
), | ||
}, | ||
}) | ||
} | ||
|
||
func (ContainerRegistryScopeMapDataSource) complete(data acceptance.TestData) string { | ||
return fmt.Sprintf(` | ||
%s | ||
resource "azurerm_container_registry_scope_map" "test" { | ||
name = "testscopemap%d" | ||
description = "A test scope map" | ||
resource_group_name = azurerm_resource_group.test.name | ||
container_registry_name = azurerm_container_registry.test.name | ||
actions = ["repositories/testrepo/content/read"] | ||
} | ||
data "azurerm_container_registry_scope_map" "test" { | ||
name = azurerm_container_registry_scope_map.test.name | ||
container_registry_name = azurerm_container_registry.test.name | ||
resource_group_name = azurerm_container_registry.test.resource_group_name | ||
} | ||
`, ContainerRegistryResource{}.basicManaged(data, "Premium"), data.RandomInteger) | ||
} |
229 changes: 229 additions & 0 deletions
229
azurerm/internal/services/containers/container_registry_scope_map_resource.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
package containers | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/mgmt/2020-11-01-preview/containerregistry" | ||
"github.com/hashicorp/go-azure-helpers/response" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/validation" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/containers/parse" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/containers/validate" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||
) | ||
|
||
func resourceContainerRegistryScopeMap() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceContainerRegistryScopeMapCreate, | ||
Read: resourceContainerRegistryScopeMapRead, | ||
Update: resourceContainerRegistryScopeMapUpdate, | ||
Delete: resourceContainerRegistryScopeMapDelete, | ||
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{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validate.ContainerRegistryName, | ||
}, | ||
|
||
"description": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ValidateFunc: validation.StringLenBetween(1, 256), | ||
}, | ||
|
||
"resource_group_name": azure.SchemaResourceGroupName(), | ||
|
||
"container_registry_name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validate.ContainerRegistryName, | ||
}, | ||
|
||
"actions": { | ||
Type: schema.TypeList, | ||
Required: true, | ||
MinItems: 1, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
ValidateFunc: validation.StringIsNotEmpty, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceContainerRegistryScopeMapCreate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Containers.ScopeMapsClient | ||
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
log.Printf("[INFO] preparing arguments for AzureRM Container Registry scope map creation.") | ||
resourceGroup := d.Get("resource_group_name").(string) | ||
containerRegistryName := d.Get("container_registry_name").(string) | ||
name := d.Get("name").(string) | ||
|
||
if d.IsNewResource() { | ||
existing, err := client.Get(ctx, resourceGroup, containerRegistryName, name) | ||
if err != nil { | ||
if !utils.ResponseWasNotFound(existing.Response) { | ||
return fmt.Errorf("Error checking for presence of existing scope map %q in Container Registry %q (Resource Group %q): %s", name, containerRegistryName, resourceGroup, err) | ||
} | ||
} | ||
|
||
if existing.ID != nil && *existing.ID != "" { | ||
return tf.ImportAsExistsError("azurerm_container_registry_scope_map", *existing.ID) | ||
} | ||
} | ||
|
||
description := d.Get("description").(string) | ||
actions := d.Get("actions").([]interface{}) | ||
|
||
parameters := containerregistry.ScopeMap{ | ||
ScopeMapProperties: &containerregistry.ScopeMapProperties{ | ||
Description: utils.String(description), | ||
Actions: utils.ExpandStringSlice(actions), | ||
}, | ||
} | ||
|
||
future, err := client.Create(ctx, resourceGroup, containerRegistryName, name, parameters) | ||
if err != nil { | ||
return fmt.Errorf("Error creating scope map %q in Container Registry %q (Resource Group %q): %+v", name, containerRegistryName, resourceGroup, err) | ||
} | ||
|
||
if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { | ||
return fmt.Errorf("Error waiting for creation of scope map %q (Container Registry %q, Resource Group %q): %+v", name, containerRegistryName, resourceGroup, err) | ||
} | ||
|
||
read, err := client.Get(ctx, resourceGroup, containerRegistryName, name) | ||
if err != nil { | ||
return fmt.Errorf("Error retrieving scope map %q for Container Registry %q (Resource Group %q): %+v", name, containerRegistryName, resourceGroup, err) | ||
} | ||
|
||
if read.ID == nil { | ||
return fmt.Errorf("Cannot read scope map %q for Container Registry %q (resource group %q) ID", name, containerRegistryName, resourceGroup) | ||
} | ||
|
||
d.SetId(*read.ID) | ||
|
||
return resourceContainerRegistryScopeMapRead(d, meta) | ||
} | ||
|
||
func resourceContainerRegistryScopeMapUpdate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Containers.ScopeMapsClient | ||
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
log.Printf("[INFO] preparing arguments for AzureRM Container Registry scope map update.") | ||
resourceGroup := d.Get("resource_group_name").(string) | ||
containerRegistryName := d.Get("container_registry_name").(string) | ||
name := d.Get("name").(string) | ||
description := d.Get("description").(string) | ||
actions := d.Get("actions").([]interface{}) | ||
|
||
parameters := containerregistry.ScopeMapUpdateParameters{ | ||
ScopeMapPropertiesUpdateParameters: &containerregistry.ScopeMapPropertiesUpdateParameters{ | ||
Description: utils.String(description), | ||
Actions: utils.ExpandStringSlice(actions), | ||
}, | ||
} | ||
|
||
future, err := client.Update(ctx, resourceGroup, containerRegistryName, name, parameters) | ||
if err != nil { | ||
return fmt.Errorf("Error updating scope map %q for Container Registry %q (Resource Group %q): %+v", name, containerRegistryName, resourceGroup, err) | ||
} | ||
|
||
if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { | ||
return fmt.Errorf("Error waiting for update of scope map %q (Container Registry %q, Resource Group %q): %+v", name, containerRegistryName, resourceGroup, err) | ||
} | ||
|
||
read, err := client.Get(ctx, resourceGroup, containerRegistryName, name) | ||
if err != nil { | ||
return fmt.Errorf("Error retrieving scope map %q (Container Registry %q, Resource Group %q): %+v", name, containerRegistryName, resourceGroup, err) | ||
} | ||
|
||
if read.ID == nil { | ||
return fmt.Errorf("Cannot read scope map %q (Container Registry %q, resource group %q) ID", name, containerRegistryName, resourceGroup) | ||
} | ||
|
||
d.SetId(*read.ID) | ||
|
||
return resourceContainerRegistryScopeMapRead(d, meta) | ||
} | ||
|
||
func resourceContainerRegistryScopeMapRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Containers.ScopeMapsClient | ||
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
id, err := parse.ContainerRegistryScopeMapID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
resp, err := client.Get(ctx, id.ResourceGroup, id.RegistryName, id.ScopeMapName) | ||
|
||
if err != nil { | ||
if utils.ResponseWasNotFound(resp.Response) { | ||
log.Printf("[DEBUG] Scope Map %q was not found in Container Registry %q in Resource Group %q", id.ScopeMapName, id.RegistryName, id.ResourceGroup) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
return fmt.Errorf("Error making Read request on scope map %q in Azure Container Registry %q (Resource Group %q): %+v", id.ScopeMapName, id.RegistryName, id.ResourceGroup, err) | ||
} | ||
|
||
d.Set("name", resp.Name) | ||
d.Set("resource_group_name", id.ResourceGroup) | ||
d.Set("container_registry_name", id.RegistryName) | ||
d.Set("description", resp.Description) | ||
d.Set("actions", utils.FlattenStringSlice(resp.Actions)) | ||
|
||
return nil | ||
} | ||
|
||
func resourceContainerRegistryScopeMapDelete(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Containers.ScopeMapsClient | ||
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
id, err := parse.ContainerRegistryScopeMapID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
future, err := client.Delete(ctx, id.ResourceGroup, id.RegistryName, id.ScopeMapName) | ||
if err != nil { | ||
if response.WasNotFound(future.Response()) { | ||
return nil | ||
} | ||
return fmt.Errorf("Error issuing Azure ARM delete request of Container Registry scope map '%s': %+v", id.ScopeMapName, err) | ||
} | ||
|
||
if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { | ||
if response.WasNotFound(future.Response()) { | ||
return nil | ||
} | ||
return fmt.Errorf("Error issuing Azure ARM delete request of Container Registry scope map '%s': %+v", id.ScopeMapName, err) | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.