Skip to content

Commit

Permalink
Add devtestlab global schedule parse and validate funcs
Browse files Browse the repository at this point in the history
  • Loading branch information
Sean Nixon committed Mar 27, 2020
1 parent 4d12fe9 commit ca9c6fc
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 17 deletions.
33 changes: 33 additions & 0 deletions azurerm/internal/services/devtestlabs/parse/global_schedule.go
@@ -0,0 +1,33 @@
package parse

import (
"fmt"

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

type GlobalScheduleId struct {
ResourceGroup string
Name string
}

func GlobalScheduleID(input string) (*GlobalScheduleId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("[ERROR] Unable to parse Global Schedule ID %q: %+v", input, err)
}

service := GlobalScheduleId{
ResourceGroup: id.ResourceGroup,
}

if service.Name, err = id.PopSegment("schedules"); err != nil {
return nil, err
}

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

return &service, nil
}
@@ -0,0 +1,61 @@
package parse

import "testing"

func TestGlobalSchedule(t *testing.T) {
testData := []struct {
Name string
Input string
Expected *GlobalScheduleId
}{
{
Name: "Empty",
Input: "",
Expected: nil,
},
{
Name: "No DevTest Lab segment",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/",
Expected: nil,
},
{
Name: "No schedule name",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/Microsoft.DevTestLab/schedules/",
Expected: nil,
},
{
Name: "Case incorrect in path element",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/Microsoft.DevTestLab/Schedules/schedule1",
Expected: nil,
},
{
Name: "Valid",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/Microsoft.DevTestLab/schedules/schedule1",
Expected: &GlobalScheduleId{
ResourceGroup: "myGroup1",
Name: "schedule1",
},
},
}

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

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

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

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

if actual.ResourceGroup != v.Expected.ResourceGroup {
t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
}
}
}
@@ -0,0 +1,33 @@
package parse

import (
"fmt"

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

type GlobalScheduleVirtualMachineId struct {
ResourceGroup string
Name string
}

func GlobalScheduleVirtualMachineID(input string) (*GlobalScheduleVirtualMachineId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("[ERROR] Unable to parse Virtual Machine ID %q: %+v", input, err)
}

service := GlobalScheduleVirtualMachineId{
ResourceGroup: id.ResourceGroup,
}

if service.Name, err = id.PopSegment("virtualMachines"); err != nil {
return nil, err
}

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

return &service, nil
}
@@ -0,0 +1,61 @@
package parse

import "testing"

func TestGlobalScheduleVirtualMachine(t *testing.T) {
testData := []struct {
Name string
Input string
Expected *GlobalScheduleVirtualMachineId
}{
{
Name: "Empty",
Input: "",
Expected: nil,
},
{
Name: "No virtual machine segment",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/",
Expected: nil,
},
{
Name: "No virtual machine name",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/microsoft.compute/virtualMachines/",
Expected: nil,
},
{
Name: "Case incorrect in path element",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/microsoft.compute/VirtualMachines/machine1",
Expected: nil,
},
{
Name: "Valid",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/microsoft.compute/virtualMachines/machine1",
Expected: &GlobalScheduleVirtualMachineId{
ResourceGroup: "myGroup1",
Name: "machine1",
},
},
}

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

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

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

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

if actual.ResourceGroup != v.Expected.ResourceGroup {
t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
}
}
}
Expand Up @@ -13,7 +13,10 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/devtestlabs/parse"
devtestValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/devtestlabs/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)
Expand All @@ -24,9 +27,10 @@ func resourceArmDevTestLabGlobalShutdownSchedule() *schema.Resource {
Read: resourceArmDevTestLabGlobalShutdownScheduleRead,
Update: resourceArmDevTestLabGlobalShutdownScheduleCreateUpdate,
Delete: resourceArmDevTestLabGlobalShutdownScheduleDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
_, err := devtestValidate.GlobalScheduleID(id)
return err
}),

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Expand All @@ -42,7 +46,7 @@ func resourceArmDevTestLabGlobalShutdownSchedule() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: azure.ValidateResourceID,
ValidateFunc: devtestValidate.GlobalScheduleVirtualMachineID,
},

"status": {
Expand Down Expand Up @@ -121,13 +125,13 @@ func resourceArmDevTestLabGlobalShutdownScheduleCreateUpdate(d *schema.ResourceD
defer cancel()

targetResourceID := d.Get("target_resource_id").(string)
rid, err := azure.ParseAzureResourceID(targetResourceID)
vm, err := parse.GlobalScheduleVirtualMachineID(vmID)
if err != nil {
return err
}

vmName := rid.Path["virtualMachines"]
resGroup := rid.ResourceGroup
vmName := vm.Name
resGroup := vm.ResourceGroup

// Can't find any official documentation on this, but the API returns a 400 for any other name.
// The best example I could find is here: https://social.msdn.microsoft.com/Forums/en-US/25a02403-dba9-4bcb-bdcc-1f4afcba5b65/powershell-script-to-autoshutdown-azure-virtual-machine?forum=WAVirtualMachinesforWindows
Expand Down Expand Up @@ -204,12 +208,12 @@ func resourceArmDevTestLabGlobalShutdownScheduleRead(d *schema.ResourceData, met
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := azure.ParseAzureResourceID(d.Id())
schedule, err := parse.GlobalScheduleID(d.Id())
if err != nil {
return err
}
resGroup := id.ResourceGroup
name := id.Path["schedules"]
resGroup := schedule.ResourceGroup
name := schedule.Name

resp, err := client.Get(ctx, resGroup, name, "")

Expand Down Expand Up @@ -248,12 +252,12 @@ func resourceArmDevTestLabGlobalShutdownScheduleDelete(d *schema.ResourceData, m
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := azure.ParseAzureResourceID(d.Id())
schedule, err := parse.GlobalScheduleID(d.Id())
if err != nil {
return err
}
resGroup := id.ResourceGroup
name := id.Path["schedules"]
resGroup := schedule.ResourceGroup
name := schedule.Name

if _, err := client.Delete(ctx, resGroup, name); err != nil {
return err
Expand Down
Expand Up @@ -6,9 +6,9 @@ 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/azure"
"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/internal/services/devtestlabs/parse"
)

func TestAccAzureRMDevTestLabGlobalShutdownSchedule_autoShutdownBasic(t *testing.T) {
Expand Down Expand Up @@ -99,14 +99,14 @@ func testCheckAzureRMDevTestLabGlobalShutdownScheduleExistsInternal(vmID string)
client := acceptance.AzureProvider.Meta().(*clients.Client).DevTestLabs.GlobalLabSchedulesClient
ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext

rid, err := azure.ParseAzureResourceID(vmID)
vm, err := parse.GlobalScheduleVirtualMachineID(vmID)
if err != nil {
return false, fmt.Errorf("Bad: Failed to parse ID (id: %s): %+v", vmID, err)
}

vmName := rid.Path["virtualMachines"]
vmName := vm.Name
name := "shutdown-computevm-" + vmName // Auto-shutdown schedule must use this naming format for Compute VMs
resourceGroup := rid.ResourceGroup
resourceGroup := vm.ResourceGroup

resp, err := client.Get(ctx, resourceGroup, name, "")
if err != nil {
Expand Down
22 changes: 22 additions & 0 deletions azurerm/internal/services/devtestlabs/validate/global_schedule.go
@@ -0,0 +1,22 @@
package validate

import (
"fmt"

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

func GlobalScheduleID(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
return
}

if _, err := parse.GlobalScheduleID(v); err != nil {
errors = append(errors, fmt.Errorf("Can not parse %q as a resource id: %v", k, err))
return
}

return warnings, errors
}
@@ -0,0 +1,40 @@
package validate

import "testing"

func TestGlobalScheduleID(t *testing.T) {
cases := []struct {
ID string
Valid bool
}{
{
ID: "",
Valid: false,
},
{
ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/",
Valid: false,
},
{
ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.DevTestLab/schedules/",
Valid: false,
},
{
ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/Microsoft.DevTestLab/Schedules/schedule1",
Valid: false,
},
{
ID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myGroup1/providers/Microsoft.DevTestLab/schedules/schedule1",
Valid: true,
},
}
for _, tc := range cases {
t.Logf("[DEBUG] Testing Value %s", tc.ID)
_, errors := GlobalScheduleID(tc.ID, "test")
valid := len(errors) == 0

if tc.Valid != valid {
t.Fatalf("Expected %t but got %t", tc.Valid, valid)
}
}
}
@@ -0,0 +1,22 @@
package validate

import (
"fmt"

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

func GlobalScheduleVirtualMachineID(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
return
}

if _, err := parse.GlobalScheduleVirtualMachineID(v); err != nil {
errors = append(errors, fmt.Errorf("Can not parse %q as a resource id: %v", k, err))
return
}

return warnings, errors
}

0 comments on commit ca9c6fc

Please sign in to comment.