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

New Resource: azurerm_security_center_subscription_pricing #2043

Merged
merged 6 commits into from
Oct 13, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/Azure/azure-sdk-for-go/services/preview/operationalinsights/mgmt/2015-11-01-preview/operationalinsights"
"github.com/Azure/azure-sdk-for-go/services/preview/operationsmanagement/mgmt/2015-11-01-preview/operationsmanagement"
"github.com/Azure/azure-sdk-for-go/services/preview/resources/mgmt/2018-03-01-preview/management"
"github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/2017-08-01-preview/security"
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql"
"github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2016-06-01/recoveryservices"
"github.com/Azure/azure-sdk-for-go/services/redis/mgmt/2018-03-01/redis"
Expand Down Expand Up @@ -252,6 +253,9 @@ type ArmClient struct {
// Search
searchServicesClient search.ServicesClient

// Security Centre
securityCenterPricingClient security.PricingsClient

// ServiceBus
serviceBusQueuesClient servicebus.QueuesClient
serviceBusNamespacesClient servicebus.NamespacesClient
Expand Down Expand Up @@ -492,6 +496,7 @@ func getArmClient(c *authentication.Config) (*ArmClient, error) {
client.registerRelayClients(endpoint, c.SubscriptionID, auth, sender)
client.registerResourcesClients(endpoint, c.SubscriptionID, auth)
client.registerSearchClients(endpoint, c.SubscriptionID, auth)
client.registerSecurityCenterClients(endpoint, c.SubscriptionID, "Global", auth)
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
client.registerServiceBusClients(endpoint, c.SubscriptionID, auth)
client.registerServiceFabricClients(endpoint, c.SubscriptionID, auth)
client.registerSchedulerClients(endpoint, c.SubscriptionID, auth)
Expand Down Expand Up @@ -1016,6 +1021,12 @@ func (c *ArmClient) registerSearchClients(endpoint, subscriptionId string, auth
c.searchServicesClient = searchClient
}

func (c *ArmClient) registerSecurityCenterClients(endpoint, subscriptionId, ascLocation string, auth autorest.Authorizer) {
securityCenterPricingClient := security.NewPricingsClientWithBaseURI(endpoint, subscriptionId, ascLocation)
c.configureClient(&securityCenterPricingClient.Client, auth)
c.securityCenterPricingClient = securityCenterPricingClient
}

func (c *ArmClient) registerServiceBusClients(endpoint, subscriptionId string, auth autorest.Authorizer) {
queuesClient := servicebus.NewQueuesClientWithBaseURI(endpoint, subscriptionId)
c.configureClient(&queuesClient.Client, auth)
Expand Down
1 change: 1 addition & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_route": resourceArmRoute(),
"azurerm_route_table": resourceArmRouteTable(),
"azurerm_search_service": resourceArmSearchService(),
"azurerm_securitycenter_subscription_pricing": resourceArmSecurityCenterSubscriptionPricing(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

securitycenter -> security_center

"azurerm_servicebus_namespace": resourceArmServiceBusNamespace(),
"azurerm_servicebus_namespace_authorization_rule": resourceArmServiceBusNamespaceAuthorizationRule(),
"azurerm_servicebus_queue": resourceArmServiceBusQueue(),
Expand Down
2 changes: 0 additions & 2 deletions azurerm/resource_arm_search_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ func testCheckAzureRMSearchServiceExists(name string) resource.TestCheckFunc {
ctx := testAccProvider.Meta().(*ArmClient).StopContext

resp, err := client.Get(ctx, resourceGroup, searchName, nil)

if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Search Service %q (resource group %q) was not found: %+v", searchName, resourceGroup, err)
Expand All @@ -94,7 +93,6 @@ func testCheckAzureRMSearchServiceDestroy(s *terraform.State) error {
ctx := testAccProvider.Meta().(*ArmClient).StopContext

resp, err := client.Get(ctx, resourceGroup, searchName, nil)

if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return nil
Expand Down
94 changes: 94 additions & 0 deletions azurerm/resource_arm_securitycenter_subscription_pricing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package azurerm

import (
"fmt"
"log"

"github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/2017-08-01-preview/security"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress"

"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmSecurityCenterSubscriptionPricing() *schema.Resource {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thinking about this longer term - I think this'd make more sense as a nested element on the azurerm_subscription resource (but this is fine as an independent resource for the moment) 🤔

return &schema.Resource{
Create: resourceArmSecurityCenterSubscriptionPricingCreateUpdate,
Read: resourceArmSecurityCenterSubscriptionPricingRead,
Update: resourceArmSecurityCenterSubscriptionPricingCreateUpdate,
Delete: resourceArmSecurityCenterSubscriptionPricingDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"tier": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the API support in-place update ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

Type: schema.TypeString,
Required: true,
DiffSuppressFunc: suppress.CaseDifference,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can remove this since we're requiring the case matches below

ValidateFunc: validation.StringInSlice([]string{
string(security.Free),
string(security.Standard),
}, false),
},
},
}
}

//NOTE: seems default is the only valid pricing name:
//Code="InvalidInputJson" Message="Pricing name '360k Sponsored' is not allowed. Expected 'default' for this scope."
func resourceArmSecurityCenterSubscriptionPricingCreateUpdate(d *schema.ResourceData, meta interface{}) error {
katbyte marked this conversation as resolved.
Show resolved Hide resolved
client := meta.(*ArmClient).securityCenterPricingClient
ctx := meta.(*ArmClient).StopContext

pricing := security.Pricing{
PricingProperties: &security.PricingProperties{
PricingTier: security.PricingTier(d.Get("tier").(string)),
},
}

_, err := client.UpdateSubscriptionPricing(ctx, "default", pricing)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to constant variable?

if err != nil {
return fmt.Errorf("Error creating/updating Security Center Subscription pricing: %+v", err)
}

resp, err := client.GetSubscriptionPricing(ctx, "default")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the GetSubscriptionPricing duplicated with resourceArmSecurityCenterSubscriptionPricingRead ?

if err != nil {
return fmt.Errorf("Error reading Security Center Subscription pricing: %+v", err)
}
if resp.ID == nil {
return fmt.Errorf("Security Center Subscription pricing ID is nil")
}

d.SetId(*resp.ID)

return resourceArmSecurityCenterSubscriptionPricingRead(d, meta)
}

func resourceArmSecurityCenterSubscriptionPricingRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).securityCenterPricingClient
ctx := meta.(*ArmClient).StopContext

resp, err := client.GetSubscriptionPricing(ctx, "default")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge to single line?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It cannot be done as resp is used below

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we move "default" to a constant variable?

if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it because of terraform import ?

log.Printf("[DEBUG] Security Center Subscription was not found: %v", err)
d.SetId("")
return nil
}

return fmt.Errorf("Error reading Security Center Subscription pricing: %+v", err)
}

if properties := resp.PricingProperties; properties != nil {
d.Set("tier", properties.PricingTier)
}

return nil
}

func resourceArmSecurityCenterSubscriptionPricingDelete(_ *schema.ResourceData, _ interface{}) error {
return nil //cannot be deleted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we revert to whatever the default value is? we do this for the Postgresql/MySql configuration value resources

}
78 changes: 78 additions & 0 deletions azurerm/resource_arm_securitycenter_subscription_pricing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package azurerm

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func TestAccAzureRMSecurityCenterSubscriptionPricing_update(t *testing.T) {
resourceName := "azurerm_securitycenter_subscription_pricing.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAzureRMSecurityCenterSubscriptionPricing_tier("Standard"),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSecurityCenterSubscriptionPricingExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tier", "Standard"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAzureRMSecurityCenterSubscriptionPricing_tier("Free"),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSecurityCenterSubscriptionPricingExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tier", "Free"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testCheckAzureRMSecurityCenterSubscriptionPricingExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := testAccProvider.Meta().(*ArmClient).securityCenterPricingClient
ctx := testAccProvider.Meta().(*ArmClient).StopContext

rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}

pricingName := rs.Primary.Attributes["pricings"]

resp, err := client.GetSubscriptionPricing(ctx, pricingName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Security Center Subscription Pricing %q was not found: %+v", pricingName, err)
}

return fmt.Errorf("Bad: GetSubscriptionPricing: %+v", err)
}

return nil
}
}

func testAccAzureRMSecurityCenterSubscriptionPricing_tier(tier string) string {
return fmt.Sprintf(`
resource "azurerm_securitycenter_subscription_pricing" "test" {
tier = "%s"
}
`, tier)
}
Loading