Skip to content

Commit

Permalink
split create/update and make customer_managed_key.identity_id optional
Browse files Browse the repository at this point in the history
  • Loading branch information
catriona-m committed Jan 17, 2025
1 parent 5bce84c commit 1b3f2c1
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 34 deletions.
172 changes: 139 additions & 33 deletions internal/services/servicebus/servicebus_namespace_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/suppress"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

// Default Authorization Rule/Policy created by Azure, used to populate the
Expand All @@ -44,9 +43,9 @@ var (

func resourceServiceBusNamespace() *pluginsdk.Resource {
resource := &pluginsdk.Resource{
Create: resourceServiceBusNamespaceCreateUpdate,
Create: resourceServiceBusNamespaceCreate,
Read: resourceServiceBusNamespaceRead,
Update: resourceServiceBusNamespaceCreateUpdate,
Update: resourceServiceBusNamespaceUpdate,
Delete: resourceServiceBusNamespaceDelete,

Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
Expand Down Expand Up @@ -119,7 +118,7 @@ func resourceServiceBusNamespace() *pluginsdk.Resource {

"identity_id": {
Type: pluginsdk.TypeString,
Required: true,
Optional: true,
ValidateFunc: commonids.ValidateUserAssignedIdentityID,
},

Expand Down Expand Up @@ -272,13 +271,13 @@ func resourceServiceBusNamespace() *pluginsdk.Resource {
return resource
}

func resourceServiceBusNamespaceCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
func resourceServiceBusNamespaceCreate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).ServiceBus.NamespacesClient
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

log.Printf("[INFO] preparing arguments for ServiceBus Namespace create/update.")
log.Printf("[INFO] preparing arguments for ServiceBus Namespace create")

location := azure.NormalizeLocation(d.Get("location").(string))
sku := d.Get("sku").(string)
Expand Down Expand Up @@ -318,7 +317,7 @@ func resourceServiceBusNamespaceCreateUpdate(d *pluginsdk.ResourceData, meta int
},
Properties: &namespaces.SBNamespaceProperties{
Encryption: expandServiceBusNamespaceEncryption(d.Get("customer_managed_key").([]interface{})),
DisableLocalAuth: utils.Bool(!d.Get("local_auth_enabled").(bool)),
DisableLocalAuth: pointer.To(!d.Get("local_auth_enabled").(bool)),
PublicNetworkAccess: &publicNetworkEnabled,
},
Tags: expandTags(t),
Expand All @@ -336,7 +335,7 @@ func resourceServiceBusNamespaceCreateUpdate(d *pluginsdk.ResourceData, meta int
if strings.EqualFold(sku, string(namespaces.SkuNamePremium)) && capacity.(int) == 0 {
return fmt.Errorf("service bus SKU %q only supports `capacity` of 1, 2, 4, 8 or 16", sku)
}
parameters.Sku.Capacity = utils.Int64(int64(capacity.(int)))
parameters.Sku.Capacity = pointer.To(int64(capacity.(int)))
}

if premiumMessagingUnit := d.Get("premium_messaging_partitions"); premiumMessagingUnit != nil {
Expand All @@ -346,11 +345,115 @@ func resourceServiceBusNamespaceCreateUpdate(d *pluginsdk.ResourceData, meta int
if strings.EqualFold(sku, string(namespaces.SkuNamePremium)) && premiumMessagingUnit.(int) == 0 {
return fmt.Errorf("service bus SKU %q only supports `premium_messaging_partitions` of 1, 2, 4", sku)
}
parameters.Properties.PremiumMessagingPartitions = utils.Int64(int64(premiumMessagingUnit.(int)))
parameters.Properties.PremiumMessagingPartitions = pointer.To(int64(premiumMessagingUnit.(int)))
}

if err := client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil {
return fmt.Errorf("creating/updating %s: %+v", id, err)
return fmt.Errorf("creating %s: %+v", id, err)
}

d.SetId(id.ID())

if d.HasChange("network_rule_set") {
networkRuleSet := d.Get("network_rule_set").([]interface{})

log.Printf("[DEBUG] Creating the Network Rule Set associated with %s..", id)
if err = createNetworkRuleSetForNamespace(ctx, client, id, networkRuleSet); err != nil {
return err
}
log.Printf("[DEBUG] Created the Network Rule Set associated with %s", id)

}

return resourceServiceBusNamespaceRead(d, meta)
}

func resourceServiceBusNamespaceUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).ServiceBus.NamespacesClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

log.Printf("[INFO] preparing arguments for ServiceBus Namespace update")

t := d.Get("tags").(map[string]interface{})

Check failure on line 378 in internal/services/servicebus/servicebus_namespace_resource.go

View workflow job for this annotation

GitHub Actions / golint

unnecessary trailing newline (whitespace)

id, err := namespaces.ParseNamespaceID(d.Id())
if err != nil {
return err
}

existing, err := client.Get(ctx, *id)
if err != nil {
return fmt.Errorf("retrieving %s: %+v", *id, err)
}

if existing.Model == nil {
return fmt.Errorf("retrieving existing %s: `model` was nil", *id)
}
if existing.Model.Properties == nil {
return fmt.Errorf("retrieving existing %s: `model.Properties` was nil", *id)
}

payload := existing.Model

if d.HasChange("identity") {
identity, err := expandSystemAndUserAssignedMap(d.Get("identity").([]interface{}))
if err != nil {
return fmt.Errorf("expanding `identity`: %+v", err)
}
payload.Identity = identity

}

if d.HasChange("public_network_access_enabled") {
publicNetworkEnabled := namespaces.PublicNetworkAccessEnabled
if !d.Get("public_network_access_enabled").(bool) {
publicNetworkEnabled = namespaces.PublicNetworkAccessDisabled
}
payload.Properties.PublicNetworkAccess = &publicNetworkEnabled
}

if d.HasChange("sku") {
sku := d.Get("sku").(string)
s := namespaces.SkuTier(sku)

Check failure on line 418 in internal/services/servicebus/servicebus_namespace_resource.go

View workflow job for this annotation

GitHub Actions / golint

unnecessary trailing newline (whitespace)
payload.Sku = &namespaces.SBSku{
Name: namespaces.SkuName(sku),
Tier: &s,
}
}

if d.HasChange("customer_managed_key") {
payload.Properties.Encryption = expandServiceBusNamespaceEncryption(d.Get("customer_managed_key").([]interface{}))
}

if d.HasChange("local_auth_enabled") {
payload.Properties.DisableLocalAuth = pointer.To(!d.Get("local_auth_enabled").(bool))
}

if d.HasChange("tags") {
payload.Tags = expandTags(t)
}

if d.HasChange("minimum_tls_version") {
if tlsValue := d.Get("minimum_tls_version").(string); tlsValue != "" {
minimumTls := namespaces.TlsVersion(tlsValue)
payload.Properties.MinimumTlsVersion = &minimumTls
}
}
if d.HasChange("capacity") {
sku := d.Get("sku").(string)
if capacity := d.Get("capacity"); capacity != nil {
if !strings.EqualFold(sku, string(namespaces.SkuNamePremium)) && capacity.(int) > 0 {
return fmt.Errorf("service bus SKU %q only supports `capacity` of 0", sku)
}
if strings.EqualFold(sku, string(namespaces.SkuNamePremium)) && capacity.(int) == 0 {
return fmt.Errorf("service bus SKU %q only supports `capacity` of 1, 2, 4, 8 or 16", sku)
}
payload.Sku.Capacity = pointer.To(int64(capacity.(int)))
}
}
if err := client.CreateOrUpdateThenPoll(ctx, *id, *payload); err != nil {
return fmt.Errorf("updating %s: %+v", id, err)
}

d.SetId(id.ID())
Expand All @@ -360,13 +463,13 @@ func resourceServiceBusNamespaceCreateUpdate(d *pluginsdk.ResourceData, meta int
// if the network rule set has been removed from config, reset it instead as there is no way to remove a rule set
if len(oldNetworkRuleSet.([]interface{})) == 1 && len(newNetworkRuleSet.([]interface{})) == 0 {
log.Printf("[DEBUG] Resetting Network Rule Set associated with %s..", id)
if err = resetNetworkRuleSetForNamespace(ctx, client, id); err != nil {
if err = resetNetworkRuleSetForNamespace(ctx, client, *id); err != nil {
return err
}
log.Printf("[DEBUG] Reset the Existing Network Rule Set associated with %s", id)
} else {
log.Printf("[DEBUG] Creating the Network Rule Set associated with %s..", id)
if err = createNetworkRuleSetForNamespace(ctx, client, id, newNetworkRuleSet.([]interface{})); err != nil {
if err = createNetworkRuleSetForNamespace(ctx, client, *id, newNetworkRuleSet.([]interface{})); err != nil {
return err
}
log.Printf("[DEBUG] Created the Network Rule Set associated with %s", id)
Expand Down Expand Up @@ -507,20 +610,34 @@ func expandServiceBusNamespaceEncryption(input []interface{}) *namespaces.Encryp
v := input[0].(map[string]interface{})
keyId, _ := keyVaultParse.ParseOptionallyVersionedNestedItemID(v["key_vault_key_id"].(string))
keySource := namespaces.KeySourceMicrosoftPointKeyVault
return &namespaces.Encryption{
KeyVaultProperties: &[]namespaces.KeyVaultProperties{

encryption := namespaces.Encryption{
KeySource: &keySource,
RequireInfrastructureEncryption: pointer.To(v["infrastructure_encryption_enabled"].(bool)),
}

if v["identity_id"].(string) == "" {
encryption.KeyVaultProperties = &[]namespaces.KeyVaultProperties{
{
KeyName: utils.String(keyId.Name),
KeyVersion: utils.String(keyId.Version),
KeyVaultUri: utils.String(keyId.KeyVaultBaseUrl),
KeyName: pointer.To(keyId.Name),
KeyVersion: pointer.To(keyId.Version),
KeyVaultUri: pointer.To(keyId.KeyVaultBaseUrl),
},
}
} else {
encryption.KeyVaultProperties = &[]namespaces.KeyVaultProperties{
{
KeyName: pointer.To(keyId.Name),
KeyVersion: pointer.To(keyId.Version),
KeyVaultUri: pointer.To(keyId.KeyVaultBaseUrl),
Identity: &namespaces.UserAssignedIdentityProperties{
UserAssignedIdentity: utils.String(v["identity_id"].(string)),
UserAssignedIdentity: pointer.To(v["identity_id"].(string)),
},
},
},
KeySource: &keySource,
RequireInfrastructureEncryption: utils.Bool(v["infrastructure_encryption_enabled"].(bool)),
}
}

return &encryption
}

func flattenServiceBusNamespaceEncryption(encryption *namespaces.Encryption) ([]interface{}, error) {
Expand Down Expand Up @@ -631,7 +748,7 @@ func createNetworkRuleSetForNamespace(ctx context.Context, client *namespaces.Na
VirtualNetworkRules: vnetRule,
IPRules: ipRule,
PublicNetworkAccess: &publicNetworkAccess,
TrustedServiceAccessEnabled: utils.Bool(item["trusted_services_allowed"].(bool)),
TrustedServiceAccessEnabled: pointer.To(item["trusted_services_allowed"].(bool)),
},
}

Expand Down Expand Up @@ -675,17 +792,6 @@ func flattenServiceBusNamespaceNetworkRuleSet(networkRuleSet namespaces.NetworkR
networkRules := flattenServiceBusNamespaceVirtualNetworkRules(networkRuleSet.VirtualNetworkRules)
ipRules := flattenServiceBusNamespaceIPRules(networkRuleSet.IPRules)

// only set network rule set if the values are different than what they are defaulted to during namespace creation
// this has to wait until 4.0 due to `azurerm_servicebus_namespace_network_rule_set` which forces `network_rule_set` to be Optional/Computed

if defaultAction == string(namespaces.DefaultActionAllow) &&
publicNetworkAccess == namespaces.PublicNetworkAccessFlagEnabled &&
!trustedServiceEnabled &&
len(networkRules) == 0 &&
len(ipRules) == 0 {
return []interface{}{}
}

return []interface{}{map[string]interface{}{
"default_action": defaultAction,
"trusted_services_allowed": trustedServiceEnabled,
Expand Down
2 changes: 1 addition & 1 deletion website/docs/r/servicebus_namespace.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ A `customer_managed_key` block supports the following:

* `key_vault_key_id` - (Required) The ID of the Key Vault Key which should be used to Encrypt the data in this ServiceBus Namespace.

* `identity_id` - (Required) The ID of the User Assigned Identity that has access to the key.
* `identity_id` - (Optional) The ID of the User Assigned Identity that has access to the key.

* `infrastructure_encryption_enabled` - (Optional) Used to specify whether enable Infrastructure Encryption (Double Encryption). Changing this forces a new resource to be created.

Expand Down

0 comments on commit 1b3f2c1

Please sign in to comment.