Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

azurerm_kusto_cluster - Support for identity #7367

Merged
merged 3 commits into from Jun 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
91 changes: 91 additions & 0 deletions azurerm/helpers/azure/kusto.go
@@ -0,0 +1,91 @@
package azure

import (
"github.com/Azure/azure-sdk-for-go/services/kusto/mgmt/2020-02-15/kusto"
"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/suppress"
)

func SchemaKustoIdentity() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(kusto.IdentityTypeNone),
string(kusto.IdentityTypeSystemAssigned),
}, true),
DiffSuppressFunc: suppress.CaseDifference,
},
"principal_id": {
Type: schema.TypeString,
Computed: true,
},
"tenant_id": {
Type: schema.TypeString,
Computed: true,
},
"identity_ids": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
}
}

func ExpandKustoIdentity(input []interface{}) *kusto.Identity {
if len(input) == 0 || input[0] == nil {
return nil
}
identity := input[0].(map[string]interface{})
identityType := kusto.IdentityType(identity["type"].(string))

kustoIdentity := kusto.Identity{
Type: identityType,
}

return &kustoIdentity
}

func FlattenKustoIdentity(input *kusto.Identity) []interface{} {
if input == nil || input.Type == kusto.IdentityTypeNone {
return []interface{}{}
}

identityIds := make([]string, 0)
if input.UserAssignedIdentities != nil {
for k := range input.UserAssignedIdentities {
identityIds = append(identityIds, k)
}
}

principalID := ""
if input.PrincipalID != nil {
principalID = *input.PrincipalID
}

tenantID := ""
if input.TenantID != nil {
tenantID = *input.TenantID
}

return []interface{}{
map[string]interface{}{
"type": string(input.Type),
"identity_ids": identityIds,
"principal_id": principalID,
"tenant_id": tenantID,
},
}
}
12 changes: 12 additions & 0 deletions azurerm/internal/services/kusto/kusto_cluster_resource.go
Expand Up @@ -50,6 +50,8 @@ func resourceArmKustoCluster() *schema.Resource {

"location": azure.SchemaLocation(),

"identity": azure.SchemaKustoIdentity(),

"sku": {
Type: schema.TypeList,
Required: true,
Expand Down Expand Up @@ -169,6 +171,12 @@ func resourceArmKustoClusterCreateUpdate(d *schema.ResourceData, meta interface{
Tags: tags.Expand(t),
}

if _, ok := d.GetOk("identity"); ok {
kustoIdentityRaw := d.Get("identity").([]interface{})
kustoIdentity := azure.ExpandKustoIdentity(kustoIdentityRaw)
kustoCluster.Identity = kustoIdentity
}

future, err := client.CreateOrUpdate(ctx, resourceGroup, name, kustoCluster)
if err != nil {
return fmt.Errorf("Error creating or updating Kusto Cluster %q (Resource Group %q): %+v", name, resourceGroup, err)
Expand Down Expand Up @@ -219,6 +227,10 @@ func resourceArmKustoClusterRead(d *schema.ResourceData, meta interface{}) error
d.Set("location", azure.NormalizeLocation(*location))
}

if err := d.Set("identity", azure.FlattenKustoIdentity(clusterResponse.Identity)); err != nil {
return fmt.Errorf("Error setting `identity`: %s", err)
}

if err := d.Set("sku", flattenKustoClusterSku(clusterResponse.Sku)); err != nil {
return fmt.Errorf("Error setting `sku`: %+v", err)
}
Expand Down
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
Expand Down Expand Up @@ -129,6 +130,28 @@ func TestAccAzureRMKustoCluster_sku(t *testing.T) {
})
}

func TestAccAzureRMKustoCluster_identitySystemAssigned(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kusto_cluster", "test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
Providers: acceptance.SupportedProviders,
CheckDestroy: testCheckAzureRMKustoClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMKustoCluster_identitySystemAssigned(data),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMKustoClusterExists(data.ResourceName),
resource.TestCheckResourceAttr(data.ResourceName, "identity.0.type", "SystemAssigned"),
resource.TestCheckResourceAttr(data.ResourceName, "identity.0.identity_ids.#", "0"),
resource.TestMatchResourceAttr(data.ResourceName, "identity.0.principal_id", validate.UUIDRegExp),
),
},
jrauschenbusch marked this conversation as resolved.
Show resolved Hide resolved
data.ImportStep(),
},
})
}

func testAccAzureRMKustoCluster_basic(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down Expand Up @@ -261,6 +284,34 @@ resource "azurerm_kusto_cluster" "test" {
`, data.RandomInteger, data.Locations.Primary, data.RandomString)
}

func testAccAzureRMKustoCluster_identitySystemAssigned(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_kusto_cluster" "test" {
name = "acctestkc%s"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name

sku {
name = "Dev(No SLA)_Standard_D11_v2"
capacity = 1
}

identity {
type = "SystemAssigned"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomString)
}

func testCheckAzureRMKustoClusterDestroy(s *terraform.State) error {
client := acceptance.AzureProvider.Meta().(*clients.Client).Kusto.ClustersClient
ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext
Expand Down
15 changes: 15 additions & 0 deletions website/docs/r/kusto_cluster.html.markdown
Expand Up @@ -46,6 +46,8 @@ The following arguments are supported:

* `sku` - (Required) A `sku` block as defined below.

* `identity` - (Optional) A identity block.

* `enable_disk_encryption` - (Optional) Specifies if the cluster's disks are encrypted.

* `enable_streaming_ingest` - (Optional) Specifies if the streaming ingest is enabled.
Expand All @@ -62,6 +64,19 @@ A `sku` block supports the following:

* `capacity` - (Required) Specifies the node count for the cluster. Boundaries depend on the sku name.

---

An `identity` block supports the following:

* `type` - (Required) Specifies the type of Managed Service Identity that is configured on this Kusto Cluster. Possible values are: `SystemAssigned` (where Azure will generate a Service Principal for you).

* `principal_id` - (Computed) Specifies the Principal ID of the System Assigned Managed Service Identity that is configured on this Kusto Cluster.

* `tenant_id` - (Computed) Specifies the Tenant ID of the System Assigned Managed Service Identity that is configured on this Kusto Cluster.

* `identity_ids` - (Computed) The list of user identities associated with the Kusto cluster.

~> **NOTE:** When `type` is set to `SystemAssigned`, the Principal ID can be retrieved after the cluster has been created. More details are available below. See [documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/overview) for additional information.

## Attributes Reference

Expand Down