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

Add new RP blueprint and resource azurerm_blueprint_assignment #6034

Closed
Closed
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
3 changes: 3 additions & 0 deletions azurerm/internal/clients/client.go
Expand Up @@ -12,6 +12,7 @@ import (
authorization "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/authorization/client"
automation "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/automation/client"
batch "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/batch/client"
blueprint "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/blueprint/client"
bot "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/bot/client"
cdn "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cdn/client"
cognitiveServices "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cognitive/client"
Expand Down Expand Up @@ -83,6 +84,7 @@ type Client struct {
Authorization *authorization.Client
Automation *automation.Client
Batch *batch.Client
Blueprint *blueprint.Client
Bot *bot.Client
Cdn *cdn.Client
Cognitive *cognitiveServices.Client
Expand Down Expand Up @@ -153,6 +155,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
client.Authorization = authorization.NewClient(o)
client.Automation = automation.NewClient(o)
client.Batch = batch.NewClient(o)
client.Blueprint = blueprint.NewClient(o)
client.Bot = bot.NewClient(o)
client.Cdn = cdn.NewClient(o)
client.Cognitive = cognitiveServices.NewClient(o)
Expand Down
2 changes: 2 additions & 0 deletions azurerm/internal/provider/services.go
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/authorization"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/automation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/batch"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/blueprint"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/bot"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cdn"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cognitive"
Expand Down Expand Up @@ -77,6 +78,7 @@ func SupportedServices() []common.ServiceRegistration {
authorization.Registration{},
automation.Registration{},
batch.Registration{},
blueprint.Registration{},
bot.Registration{},
cdn.Registration{},
cognitive.Registration{},
Expand Down
29 changes: 29 additions & 0 deletions azurerm/internal/services/blueprint/client/client.go
@@ -0,0 +1,29 @@
package client

import (
"github.com/Azure/azure-sdk-for-go/services/preview/blueprint/mgmt/2018-11-01-preview/blueprint"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common"
)

type Client struct {
BlueprintClient *blueprint.BlueprintsClient
AssignmentClient *blueprint.AssignmentsClient
PublishClient *blueprint.PublishedBlueprintsClient
}

func NewClient(o *common.ClientOptions) *Client {
blueprintsClient := blueprint.NewBlueprintsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&blueprintsClient.Client, o.ResourceManagerAuthorizer)

assignmentsClient := blueprint.NewAssignmentsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&assignmentsClient.Client, o.ResourceManagerAuthorizer)

publishClient := blueprint.NewPublishedBlueprintsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&publishClient.Client, o.ResourceManagerAuthorizer)

return &Client{
BlueprintClient: &blueprintsClient,
AssignmentClient: &assignmentsClient,
PublishClient: &publishClient,
}
}
68 changes: 68 additions & 0 deletions azurerm/internal/services/blueprint/parse/assignment.go
@@ -0,0 +1,68 @@
package parse

import (
"fmt"
"regexp"

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

type BlueprintAssignmentId struct {
Name string
BlueprintAssignmentScopeId
}

func BlueprintAssignmentID(input string) (*BlueprintAssignmentId, error) {
regex := regexp.MustCompile(`/providers/Microsoft\.Blueprint/blueprintAssignments/`)
if !regex.MatchString(input) {
return nil, fmt.Errorf("unable to parse Blueprint Assignment ID %q", input)
}

segments := regex.Split(input, -1)

if len(segments) != 2 {
return nil, fmt.Errorf("unable to parse Blueprint Assignment ID %q: expeceted 2 segmetns", input)
}

scope := segments[0]
scopeId, err := BlueprintAssignmentScopeID(scope)
if err != nil {
return nil, fmt.Errorf("unable to parse Blueprint Assignment ID %q: %+v", input, err)
}

name := segments[1]
if name == "" {
return nil, fmt.Errorf("unable to parse Blueprint Assignment ID %q: asssignment name is empty", input)
}

id := BlueprintAssignmentId{
Name: name,
BlueprintAssignmentScopeId: *scopeId,
}

return &id, nil
}

type BlueprintAssignmentScopeId struct {
ScopeId string
SubscriptionId string
}

func BlueprintAssignmentScopeID(input string) (*BlueprintAssignmentScopeId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("unable to parse Blueprint Assignment Scope ID %q: %+v", input, err)
}
if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, fmt.Errorf("unable to parse Blueprint Assignment Scope ID %q: %+v", input, err)
}
if id.ResourceGroup != "" {
return nil, fmt.Errorf("unable to parse Blueprint Assignment Scope ID %q: scope cannot have resource groups", input)
}
scopeId := BlueprintAssignmentScopeId{
ScopeId: input,
SubscriptionId: id.SubscriptionID,
}

return &scopeId, nil
}
140 changes: 140 additions & 0 deletions azurerm/internal/services/blueprint/parse/assignment_test.go
@@ -0,0 +1,140 @@
package parse

import "testing"

func TestBlueprintAssignmentID(t *testing.T) {
testData := []struct {
Name string
Input string
Error bool
Expected *BlueprintAssignmentId
}{
{
Name: "Empty",
Input: "",
Error: true,
},
{
Name: "Missing management group ID",
Input: "/providers/Microsoft.Management/managementGroups/providers/Microsoft.Blueprint/blueprintAssignments/assignment1",
Error: true,
},
{
Name: "Missing assignment name",
Input: "/providers/Microsoft.Management/managementGroups/00000000-0000-0000-0000-000000000000/providers/Microsoft.Blueprint/blueprintAssignments/",
Error: true,
},
{
Name: "Blueprint Assignment ID in subscription",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Blueprint/blueprintAssignments/assignment1",
Expected: &BlueprintAssignmentId{
Name: "assignment1",
BlueprintAssignmentScopeId: BlueprintAssignmentScopeId{
ScopeId: "/subscriptions/00000000-0000-0000-0000-000000000000",
SubscriptionId: "00000000-0000-0000-0000-000000000000",
},
},
},
{
Name: "Missing assignment name in subscription",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Blueprint/blueprintAssignments/",
Error: true,
},
{
Name: "Assignment ID in resource group",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Blueprint/blueprintAssignments/assignment1",
Error: true,
},
{
Name: "missing resource group name",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/providers/Microsoft.Blueprint/blueprintAssignments/assignment1",
Error: true,
},
}

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

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

t.Fatalf("Expected a value but got an error: %+v", err)
}

if actual.Name != v.Expected.Name {
t.Fatalf("Expected %q but got %q", v.Expected.Name, actual.Name)
}

if actual.ScopeId != v.Expected.ScopeId {
t.Fatalf("Expected %q but got %q", v.Expected.ScopeId, actual.ScopeId)
}

if actual.SubscriptionId != v.Expected.SubscriptionId {
t.Fatalf("Expected %q but got %q", v.Expected.SubscriptionId, actual.SubscriptionId)
}
}
}

func TestBlueprintAssignmentScopeID(t *testing.T) {
testData := []struct {
Name string
Input string
Error bool
Expected *BlueprintAssignmentScopeId
}{
{
Name: "Empty",
Input: "",
Error: true,
},
{
Name: "Management group ID but missing components",
Input: "/providers/Microsoft.Management/managementGroups/",
Error: true,
},
{
Name: "Resource Group ID",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1",
Error: true,
},
{
Name: "Incomplete resource group ID",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/",
Error: true,
},
{
Name: "Resource ID",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Compute/virtualMachines/vm1",
Error: true,
},
{
Name: "Incomplete resource ID",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Compute/virtualMachines/",
Error: true,
},
}

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

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

t.Fatalf("Expected a value but got an error: %+v", err)
}

if actual.ScopeId != v.Expected.ScopeId {
t.Fatalf("Expected %q but got %q", v.Expected.ScopeId, actual.ScopeId)
}

if actual.SubscriptionId != v.Expected.SubscriptionId {
t.Fatalf("Expected %q but got %q", v.Expected.SubscriptionId, actual.SubscriptionId)
}
}
}