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_mssql_managed_instance_start_stop_schedule #26702

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
75225d8
feat: new resource mssql managed instance start and stop schedule
hqhqhqhqhqhqhqhqhqhqhq Jul 15, 2024
026412b
Update mssql_managed_instance_start_stop_schedule_resource_test.go
hqhqhqhqhqhqhqhqhqhqhq Jul 19, 2024
277d7a2
Update mssql_managed_instance_start_stop_schedule_resource.go
hqhqhqhqhqhqhqhqhqhqhq Jul 20, 2024
8541832
Update mssql_managed_instance_start_stop_schedule_resource.go
hqhqhqhqhqhqhqhqhqhqhq Jul 23, 2024
72f2f41
Update mssql_managed_instance_sql_start_stop_schedule.html.markdown
hqhqhqhqhqhqhqhqhqhqhq Jul 26, 2024
e5507d7
Update modules.txt
hqhqhqhqhqhqhqhqhqhqhq Sep 3, 2024
7448c8f
fix issues in review
hqhqhqhqhqhqhqhqhqhqhq Sep 3, 2024
1ce24db
fix: fix comments from review
hqhqhqhqhqhqhqhqhqhqhq Sep 3, 2024
29c8e98
Update client.go
hqhqhqhqhqhqhqhqhqhqhq Sep 3, 2024
54072a9
Update mssql_managed_instance_start_stop_schedule_resource.go
hqhqhqhqhqhqhqhqhqhqhq Sep 3, 2024
ff4e40b
fix lint
hqhqhqhqhqhqhqhqhqhqhq Sep 3, 2024
9e1dcba
Update mssql_managed_instance_start_stop_schedule_resource.go
hqhqhqhqhqhqhqhqhqhqhq Sep 3, 2024
a1e9705
Merge remote-tracking branch 'upstream/main' into feat/sql-StartStopM…
hqhqhqhqhqhqhqhqhqhqhq Feb 24, 2025
30520a6
Update mssql_managed_instance_start_stop_schedule_resource_test.go
hqhqhqhqhqhqhqhqhqhqhq Feb 24, 2025
25f476f
Update mssql_managed_instance_start_stop_schedule_resource.go
hqhqhqhqhqhqhqhqhqhqhq Feb 24, 2025
966a6fc
Update mssql_managed_instance_start_stop_schedule_resource.go
hqhqhqhqhqhqhqhqhqhqhq Feb 24, 2025
12ab7a0
update
hqhqhqhqhqhqhqhqhqhqhq Feb 25, 2025
a92ab30
update vendor dependency
hqhqhqhqhqhqhqhqhqhqhq Feb 25, 2025
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
9 changes: 9 additions & 0 deletions internal/services/mssqlmanagedinstance/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-08-01-preview/managedinstances"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-08-01-preview/managedinstancevulnerabilityassessments"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-08-01-preview/managedserversecurityalertpolicies"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-08-01-preview/startstopmanagedinstanceschedules"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
)

Expand All @@ -33,6 +34,7 @@ type Client struct {
ManagedInstanceEncryptionProtectorClient *managedinstanceencryptionprotectors.ManagedInstanceEncryptionProtectorsClient
ManagedInstanceFailoverGroupsClient *instancefailovergroups.InstanceFailoverGroupsClient
ManagedInstanceKeysClient *managedinstancekeys.ManagedInstanceKeysClient
ManagedInstanceStartStopSchedulesClient *startstopmanagedinstanceschedules.StartStopManagedInstanceSchedulesClient

options *common.ClientOptions
}
Expand Down Expand Up @@ -104,6 +106,12 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
}
o.Configure(managedInstanceServerSecurityAlertPoliciesClient.Client, o.Authorizers.ResourceManager)

managedInstanceStartStopSchedulesClient, err := startstopmanagedinstanceschedules.NewStartStopManagedInstanceSchedulesClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building Managed Instance Start Stop Schedules Client: %+v", err)
}
o.Configure(managedInstanceStartStopSchedulesClient.Client, o.Authorizers.ResourceManager)

return &Client{
ManagedDatabasesClient: managedDatabasesClient,
ManagedInstanceAdministratorsClient: managedInstancesAdministratorsClient,
Expand All @@ -116,6 +124,7 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
ManagedInstancesShortTermRetentionPoliciesClient: managedInstancesShortTermRetentionPoliciesClient,
ManagedInstanceVulnerabilityAssessmentsClient: managedInstanceVulnerabilityAssessmentsClient,
ManagedInstancesClient: managedInstancesClient,
ManagedInstanceStartStopSchedulesClient: managedInstanceStartStopSchedulesClient,

options: o,
}, nil
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
package mssqlmanagedinstance

import (
"context"
"fmt"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
schedule "github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-08-01-preview/startstopmanagedinstanceschedules"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mssqlmanagedinstance/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mssqlmanagedinstance/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

type SqlManagedInstanceStartStopScheduleModel struct {
SqlManagedInstanceId string `tfschema:"managed_instance_id"`
Description string `tfschema:"description"`
Schedule []ScheduleItemModel `tfschema:"schedule"`
TimeZoneId string `tfschema:"timezone_id"`
NextExecutionTime string `tfschema:"next_execution_time"`
NextRunAction string `tfschema:"next_run_action"`
}

type ScheduleItemModel struct {
StartDay schedule.DayOfWeek `tfschema:"start_day"`
StartTime string `tfschema:"start_time"`
StopDay schedule.DayOfWeek `tfschema:"stop_day"`
StopTime string `tfschema:"stop_time"`
}

type MsSqlManagedInstanceStartStopScheduleResource struct{}

var _ sdk.ResourceWithUpdate = MsSqlManagedInstanceStartStopScheduleResource{}

func (r MsSqlManagedInstanceStartStopScheduleResource) ResourceType() string {
return "azurerm_mssql_managed_instance_start_stop_schedule"
}

func (r MsSqlManagedInstanceStartStopScheduleResource) ModelObject() interface{} {
return &SqlManagedInstanceStartStopScheduleModel{}
}

func (r MsSqlManagedInstanceStartStopScheduleResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return validate.ManagedInstanceStartStopScheduleID
}

func (r MsSqlManagedInstanceStartStopScheduleResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a name argument with a validation func which only allows "default".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have confirmed with the service team that this resource will have 1to1 relationship with the managedinstance and hence the name will always be "default", I think leaving this out so that user doesn't need to declare it is cleaner.

"managed_instance_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: commonids.ValidateSqlManagedInstanceID,
},

"description": {
Type: pluginsdk.TypeString,
Optional: true,
},

"schedule": {
Type: pluginsdk.TypeList,
Required: true,
MinItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"start_day": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(schedule.PossibleValuesForDayOfWeek(), false),
},

"start_time": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"stop_day": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(schedule.PossibleValuesForDayOfWeek(), false),
},

"stop_time": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},
},
},
},

"timezone_id": {
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be shortened to

Suggested change
"timezone_id": {
"timezone": {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for this, the parent resource azurerm_mssql_managed_instance uses timezone_id, I think it would nice to have similar terminologies.

Type: pluginsdk.TypeString,
Optional: true,
Default: "UTC",
ValidateFunc: validation.StringIsNotEmpty,
},
}
}

func (r MsSqlManagedInstanceStartStopScheduleResource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"next_execution_time": {
Type: pluginsdk.TypeString,
Computed: true,
},

"next_run_action": {
Type: pluginsdk.TypeString,
Computed: true,
},
}
}

func (r MsSqlManagedInstanceStartStopScheduleResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
var model SqlManagedInstanceStartStopScheduleModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

client := metadata.Client.MSSQLManagedInstance.ManagedInstanceStartStopSchedulesClient

managedInstanceId, err := commonids.ParseSqlManagedInstanceID(model.SqlManagedInstanceId)
if err != nil {
return err
}

id := *managedInstanceId

existing, err := client.Get(ctx, id)
if err != nil && !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for existing %s: %+v", id, err)
}

if !response.WasNotFound(existing.HttpResponse) {
return metadata.ResourceRequiresImport(r.ResourceType(), id)
}

properties := &schedule.StartStopManagedInstanceSchedule{
Properties: &schedule.StartStopManagedInstanceScheduleProperties{},
}

if model.Description != "" {
properties.Properties.Description = &model.Description
}

properties.Properties.ScheduleList = expandScheduleItemModelArray(model.Schedule)

if model.TimeZoneId != "" {
properties.Properties.TimeZoneId = &model.TimeZoneId
}

if _, err := client.CreateOrUpdate(ctx, id, *properties); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}

scheduleID := parse.NewManagedInstanceStartStopScheduleID(id.SubscriptionId, id.ResourceGroupName, id.ManagedInstanceName, "default")
metadata.SetID(scheduleID)

return nil
},
}
}

func (r MsSqlManagedInstanceStartStopScheduleResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MSSQLManagedInstance.ManagedInstanceStartStopSchedulesClient

id, err := parse.ManagedInstanceStartStopScheduleID(metadata.ResourceData.Id())
if err != nil {
return err
}

managedInstanceID := commonids.NewSqlManagedInstanceID(id.SubscriptionId, id.ResourceGroup, id.ManagedInstanceName)

var model SqlManagedInstanceStartStopScheduleModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

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

if resp.Model == nil {
return fmt.Errorf("retrieving %s:`model` was nil", managedInstanceID)
}
if resp.Model.Properties == nil {
return fmt.Errorf("retrieving %s:`properties` was nil", managedInstanceID)
}

properties := resp.Model

if metadata.ResourceData.HasChange("description") {
properties.Properties.Description = pointer.To(model.Description)
}

if metadata.ResourceData.HasChange("schedule") {
properties.Properties.ScheduleList = expandScheduleItemModelArray(model.Schedule)
}

if metadata.ResourceData.HasChange("timezone_id") {
properties.Properties.TimeZoneId = pointer.To(model.TimeZoneId)
}

if _, err := client.CreateOrUpdate(ctx, managedInstanceID, *properties); err != nil {
return fmt.Errorf("updating %s: %+v", managedInstanceID, err)
}

return nil
},
}
}

func (r MsSqlManagedInstanceStartStopScheduleResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MSSQLManagedInstance.ManagedInstanceStartStopSchedulesClient

id, err := parse.ManagedInstanceStartStopScheduleID(metadata.ResourceData.Id())
if err != nil {
return err
}

managedInstanceID := commonids.NewSqlManagedInstanceID(id.SubscriptionId, id.ResourceGroup, id.ManagedInstanceName)

resp, err := client.Get(ctx, managedInstanceID)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return metadata.MarkAsGone(managedInstanceID)
}

return fmt.Errorf("retrieving %s: %+v", managedInstanceID, err)
}

state := SqlManagedInstanceStartStopScheduleModel{
SqlManagedInstanceId: managedInstanceID.ID(),
}

if model := resp.Model; model != nil {
if properties := model.Properties; properties != nil {
state.Description = pointer.From(properties.Description)

state.NextExecutionTime = pointer.From(properties.NextExecutionTime)

state.NextRunAction = pointer.From(properties.NextRunAction)

if properties.ScheduleList != nil {
state.Schedule = flattenScheduleItemModelArray(properties.ScheduleList)
}

state.TimeZoneId = pointer.From(properties.TimeZoneId)
}
}

return metadata.Encode(&state)
},
}
}

func (r MsSqlManagedInstanceStartStopScheduleResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MSSQLManagedInstance.ManagedInstanceStartStopSchedulesClient

id, err := parse.ManagedInstanceStartStopScheduleID(metadata.ResourceData.Id())
if err != nil {
return err
}

managedInstanceID := commonids.NewSqlManagedInstanceID(id.SubscriptionId, id.ResourceGroup, id.ManagedInstanceName)

if _, err := client.Delete(ctx, managedInstanceID); err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}

return nil
},
}
}

func expandScheduleItemModelArray(inputList []ScheduleItemModel) []schedule.ScheduleItem {
outputList := make([]schedule.ScheduleItem, 0, len(inputList))

for _, v := range inputList {
input := v
output := schedule.ScheduleItem{
StartDay: input.StartDay,
StartTime: input.StartTime,
StopDay: input.StopDay,
StopTime: input.StopTime,
}

outputList = append(outputList, output)
}
return outputList
}

func flattenScheduleItemModelArray(inputList []schedule.ScheduleItem) []ScheduleItemModel {
outputList := make([]ScheduleItemModel, 0, len(inputList))

if inputList == nil {
return outputList
}
for _, input := range inputList {
output := ScheduleItemModel{
StartDay: input.StartDay,
StartTime: input.StartTime,
StopDay: input.StopDay,
StopTime: input.StopTime,
}

outputList = append(outputList, output)
}
return outputList
}
Loading
Loading