Skip to content

Commit

Permalink
Merge pull request #10144 from magodo/sentinel_resourceid
Browse files Browse the repository at this point in the history
sentinel: generating & switching to use the resource id parsers
  • Loading branch information
tombuildsstuff authored Jan 14, 2021
2 parents 54d8c49 + 160c3b4 commit 09bd111
Show file tree
Hide file tree
Showing 15 changed files with 390 additions and 211 deletions.
75 changes: 75 additions & 0 deletions azurerm/internal/services/sentinel/parse/alert_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"fmt"
"strings"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type AlertRuleId struct {
SubscriptionId string
ResourceGroup string
WorkspaceName string
Name string
}

func NewAlertRuleID(subscriptionId, resourceGroup, workspaceName, name string) AlertRuleId {
return AlertRuleId{
SubscriptionId: subscriptionId,
ResourceGroup: resourceGroup,
WorkspaceName: workspaceName,
Name: name,
}
}

func (id AlertRuleId) String() string {
segments := []string{
fmt.Sprintf("Name %q", id.Name),
fmt.Sprintf("Workspace Name %q", id.WorkspaceName),
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Alert Rule", segmentsStr)
}

func (id AlertRuleId) ID() string {
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.OperationalInsights/workspaces/%s/providers/Microsoft.SecurityInsights/alertRules/%s"
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.WorkspaceName, id.Name)
}

// AlertRuleID parses a AlertRule ID into an AlertRuleId struct
func AlertRuleID(input string) (*AlertRuleId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := AlertRuleId{
SubscriptionId: id.SubscriptionID,
ResourceGroup: id.ResourceGroup,
}

if resourceId.SubscriptionId == "" {
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
}

if resourceId.ResourceGroup == "" {
return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
}

if resourceId.WorkspaceName, err = id.PopSegment("workspaces"); err != nil {
return nil, err
}
if resourceId.Name, err = id.PopSegment("alertRules"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
128 changes: 128 additions & 0 deletions azurerm/internal/services/sentinel/parse/alert_rule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"testing"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid"
)

var _ resourceid.Formatter = AlertRuleId{}

func TestAlertRuleIDFormatter(t *testing.T) {
actual := NewAlertRuleID("12345678-1234-9876-4563-123456789012", "resGroup1", "workspace1", "rule1").ID()
expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1/providers/Microsoft.SecurityInsights/alertRules/rule1"
if actual != expected {
t.Fatalf("Expected %q but got %q", expected, actual)
}
}

func TestAlertRuleID(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *AlertRuleId
}{

{
// empty
Input: "",
Error: true,
},

{
// missing SubscriptionId
Input: "/",
Error: true,
},

{
// missing value for SubscriptionId
Input: "/subscriptions/",
Error: true,
},

{
// missing ResourceGroup
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
Error: true,
},

{
// missing value for ResourceGroup
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
Error: true,
},

{
// missing WorkspaceName
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/",
Error: true,
},

{
// missing value for WorkspaceName
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/",
Error: true,
},

{
// missing Name
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1/providers/Microsoft.SecurityInsights/",
Error: true,
},

{
// missing value for Name
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1/providers/Microsoft.SecurityInsights/alertRules/",
Error: true,
},

{
// valid
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1/providers/Microsoft.SecurityInsights/alertRules/rule1",
Expected: &AlertRuleId{
SubscriptionId: "12345678-1234-9876-4563-123456789012",
ResourceGroup: "resGroup1",
WorkspaceName: "workspace1",
Name: "rule1",
},
},

{
// upper-cased
Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.OPERATIONALINSIGHTS/WORKSPACES/WORKSPACE1/PROVIDERS/MICROSOFT.SECURITYINSIGHTS/ALERTRULES/RULE1",
Error: true,
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

actual, err := AlertRuleID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expect a value but got an error: %s", err)
}
if v.Error {
t.Fatal("Expect an error but didn't get one")
}

if actual.SubscriptionId != v.Expected.SubscriptionId {
t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
}
if actual.ResourceGroup != v.Expected.ResourceGroup {
t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
}
if actual.WorkspaceName != v.Expected.WorkspaceName {
t.Fatalf("Expected %q but got %q for WorkspaceName", v.Expected.WorkspaceName, actual.WorkspaceName)
}
if actual.Name != v.Expected.Name {
t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
}
}
}
36 changes: 0 additions & 36 deletions azurerm/internal/services/sentinel/parse/sentinel_alert_rules.go

This file was deleted.

This file was deleted.

1 change: 1 addition & 0 deletions azurerm/internal/services/sentinel/resourceids.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
package sentinel

//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=AlertRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1/providers/Microsoft.SecurityInsights/alertRules/rule1
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SentinelAlertRuleTemplate -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1/providers/Microsoft.SecurityInsights/AlertRuleTemplates/template1
6 changes: 3 additions & 3 deletions azurerm/internal/services/sentinel/sentinel_alert_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func alertRuleID(rule securityinsight.BasicAlertRule) *string {

func importSentinelAlertRule(expectKind securityinsight.AlertRuleKind) func(d *schema.ResourceData, meta interface{}) (data []*schema.ResourceData, err error) {
return func(d *schema.ResourceData, meta interface{}) (data []*schema.ResourceData, err error) {
id, err := parse.SentinelAlertRuleID(d.Id())
id, err := parse.AlertRuleID(d.Id())
if err != nil {
return nil, err
}
Expand All @@ -37,9 +37,9 @@ func importSentinelAlertRule(expectKind securityinsight.AlertRuleKind) func(d *s
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

resp, err := client.Get(ctx, id.ResourceGroup, "Microsoft.OperationalInsights", id.Workspace, id.Name)
resp, err := client.Get(ctx, id.ResourceGroup, "Microsoft.OperationalInsights", id.WorkspaceName, id.Name)
if err != nil {
return nil, fmt.Errorf("retrieving Sentinel Alert Rule %q (Resource Group %q / Workspace: %q): %+v", id.Name, id.ResourceGroup, id.Workspace, err)
return nil, fmt.Errorf("retrieving Sentinel Alert Rule %q: %+v", id, err)
}

if err := assertAlertRuleKind(resp.Value, expectKind); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"time"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/sentinel/parse"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
Expand Down Expand Up @@ -47,21 +49,18 @@ func dataSourceSentinelAlertRuleRead(d *schema.ResourceData, meta interface{}) e
if err != nil {
return err
}
id := parse.NewAlertRuleID(workspaceID.SubscriptionId, workspaceID.ResourceGroup, workspaceID.WorkspaceName, name)

resp, err := client.Get(ctx, workspaceID.ResourceGroup, "Microsoft.OperationalInsights", workspaceID.WorkspaceName, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Sentinel Alert Rule %q (Resource Group %q / Workspace: %q) was not found", name, workspaceID.ResourceGroup, workspaceID.WorkspaceName)
return fmt.Errorf("Sentinel Alert Rule %q was not found", id)
}

return fmt.Errorf("retrieving Sentinel Alert Rule %q (Resource Group %q / Workspace: %q): %+v", name, workspaceID.ResourceGroup, workspaceID.WorkspaceName, err)
return fmt.Errorf("retrieving Sentinel Alert Rule %q: %+v", id, err)
}

id := alertRuleID(resp.Value)
if id == nil || *id == "" {
return fmt.Errorf("nil or empty ID of Sentinel Alert Rule %q (Resource Group %q / Workspace: %q)", name, workspaceID.ResourceGroup, workspaceID.WorkspaceName)
}
d.SetId(*id)
d.SetId(id.ID())

return nil
}
Loading

0 comments on commit 09bd111

Please sign in to comment.