Skip to content

Commit 6cea778

Browse files
Project: Host Maintenance Policy (#798)
* Added support for Host/VM Maintenance (#720) * Added support for Host/VM Maintenance * Fix lint * Deprecate fields instead of removing them * Made updates to address API spec changes * Addressed additional API Spec changes (#771) * Updated maintenance_policy_id to maintenance_policy * Fix lint * Modified maintenance/policies endpoint to reflect paginated response * Add integration test for VM Maintenance Policy changes (#781) * int_test * lint-issue * address_PR_comment * fix * address_comment * fix * clean up the fixtures * clean up the fixtures * Added `v4beta` notices for new fields and methods (#795) * Added v4beta notices * Fix tests * Fix lint --------- Co-authored-by: Vinay <[email protected]>
1 parent dca68fa commit 6cea778

34 files changed

+1832
-921
lines changed

account_events.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,25 @@ type Event struct {
5252

5353
// The total duration in seconds that it takes for the Event to complete.
5454
Duration float64 `json:"duration"`
55+
56+
// The maintenance policy configured by the user for the event.
57+
// NOTE: MaintenancePolicySet can only be used with v4beta.
58+
MaintenancePolicySet string `json:"maintenance_policy_set"`
59+
60+
// Describes the nature of the event (e.g., whether it is scheduled or emergency).
61+
Description string `json:"description"`
62+
63+
// The origin of the event (e.g., platform, user).
64+
Source string `json:"source"`
65+
66+
// Scheduled start time for the event.
67+
NotBefore *time.Time `json:"-"`
68+
69+
// The actual start time of the event.
70+
StartTime *time.Time `json:"-"`
71+
72+
// The actual completion time of the event.
73+
CompleteTime *time.Time `json:"-"`
5574
}
5675

5776
// EventAction constants start with Action and include all known Linode API Event Actions.
@@ -121,6 +140,7 @@ const (
121140
ActionLinodeMigrateDatacenterCreate EventAction = "linode_migrate_datacenter_create"
122141
ActionLinodeMutate EventAction = "linode_mutate"
123142
ActionLinodeMutateCreate EventAction = "linode_mutate_create"
143+
ActionLinodePowerOffOn EventAction = "linode_poweroff_on"
124144
ActionLinodeReboot EventAction = "linode_reboot"
125145
ActionLinodeRebuild EventAction = "linode_rebuild"
126146
ActionLinodeResize EventAction = "linode_resize"
@@ -261,6 +281,7 @@ const (
261281
EventNotification EventStatus = "notification"
262282
EventScheduled EventStatus = "scheduled"
263283
EventStarted EventStatus = "started"
284+
EventCanceled EventStatus = "canceled"
264285
)
265286

266287
// EventEntity provides detailed information about the Event's
@@ -284,6 +305,9 @@ func (i *Event) UnmarshalJSON(b []byte) error {
284305

285306
Created *parseabletime.ParseableTime `json:"created"`
286307
TimeRemaining json.RawMessage `json:"time_remaining"`
308+
NotBefore *parseabletime.ParseableTime `json:"not_before"`
309+
StartTime *parseabletime.ParseableTime `json:"start_time"`
310+
CompleteTime *parseabletime.ParseableTime `json:"complete_time"`
287311
}{
288312
Mask: (*Mask)(i),
289313
}
@@ -294,6 +318,9 @@ func (i *Event) UnmarshalJSON(b []byte) error {
294318

295319
i.Created = (*time.Time)(p.Created)
296320
i.TimeRemaining = duration.UnmarshalTimeRemaining(p.TimeRemaining)
321+
i.NotBefore = (*time.Time)(p.NotBefore)
322+
i.StartTime = (*time.Time)(p.StartTime)
323+
i.CompleteTime = (*time.Time)(p.CompleteTime)
297324

298325
return nil
299326
}

account_maintenance.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,22 @@ import (
1010

1111
// AccountMaintenance represents a Maintenance object for any entity a user has permissions to view
1212
type AccountMaintenance struct {
13-
Entity *Entity `json:"entity"`
14-
Reason string `json:"reason"`
15-
Status string `json:"status"`
16-
Type string `json:"type"`
17-
When *time.Time `json:"when"`
13+
Entity *Entity `json:"entity"`
14+
Reason string `json:"reason"`
15+
Status string `json:"status"`
16+
Type string `json:"type"`
17+
18+
// NOTE: MaintenancePolicySet can only be used with v4beta.
19+
MaintenancePolicySet string `json:"maintenance_policy_set"`
20+
21+
Description string `json:"description"`
22+
Source string `json:"source"`
23+
NotBefore *time.Time `json:"-"`
24+
StartTime *time.Time `json:"-"`
25+
CompleteTime *time.Time `json:"-"`
26+
27+
// Deprecated: When is a deprecated property
28+
When *time.Time `json:"when"`
1829
}
1930

2031
// The entity being affected by maintenance
@@ -32,7 +43,10 @@ func (accountMaintenance *AccountMaintenance) UnmarshalJSON(b []byte) error {
3243
p := struct {
3344
*Mask
3445

35-
When *parseabletime.ParseableTime `json:"when"`
46+
NotBefore *parseabletime.ParseableTime `json:"not_before"`
47+
StartTime *parseabletime.ParseableTime `json:"start_time"`
48+
CompleteTime *parseabletime.ParseableTime `json:"complete_time"`
49+
When *parseabletime.ParseableTime `json:"when"`
3650
}{
3751
Mask: (*Mask)(accountMaintenance),
3852
}
@@ -41,6 +55,9 @@ func (accountMaintenance *AccountMaintenance) UnmarshalJSON(b []byte) error {
4155
return err
4256
}
4357

58+
accountMaintenance.NotBefore = (*time.Time)(p.NotBefore)
59+
accountMaintenance.StartTime = (*time.Time)(p.StartTime)
60+
accountMaintenance.CompleteTime = (*time.Time)(p.CompleteTime)
4461
accountMaintenance.When = (*time.Time)(p.When)
4562

4663
return nil

account_notifications.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,17 @@ type NotificationType string
4444

4545
// NotificationType constants represent the actions that cause a Notification. New types may be added in the future.
4646
const (
47-
NotificationMigrationScheduled NotificationType = "migration_scheduled"
48-
NotificationMigrationImminent NotificationType = "migration_imminent"
49-
NotificationMigrationPending NotificationType = "migration_pending"
50-
NotificationRebootScheduled NotificationType = "reboot_scheduled"
51-
NotificationOutage NotificationType = "outage"
52-
NotificationPaymentDue NotificationType = "payment_due"
53-
NotificationTicketImportant NotificationType = "ticket_important"
54-
NotificationTicketAbuse NotificationType = "ticket_abuse"
55-
NotificationNotice NotificationType = "notice"
56-
NotificationMaintenance NotificationType = "maintenance"
47+
NotificationMigrationScheduled NotificationType = "migration_scheduled"
48+
NotificationMigrationImminent NotificationType = "migration_imminent"
49+
NotificationMigrationPending NotificationType = "migration_pending"
50+
NotificationRebootScheduled NotificationType = "reboot_scheduled"
51+
NotificationOutage NotificationType = "outage"
52+
NotificationPaymentDue NotificationType = "payment_due"
53+
NotificationTicketImportant NotificationType = "ticket_important"
54+
NotificationTicketAbuse NotificationType = "ticket_abuse"
55+
NotificationNotice NotificationType = "notice"
56+
NotificationMaintenance NotificationType = "maintenance"
57+
NotificationMaintenanceScheduled NotificationType = "maintenance_scheduled"
5758
)
5859

5960
// ListNotifications gets a collection of Notification objects representing important,

account_settings.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,21 @@ type AccountSettings struct {
99
// The default backups enrollment status for all new Linodes for all users on the account. When enabled, backups are mandatory per instance.
1010
BackupsEnabled bool `json:"backups_enabled"`
1111

12-
// Wether or not Linode Managed service is enabled for the account.
12+
// Whether or not Linode Managed service is enabled for the account.
1313
Managed bool `json:"managed"`
1414

15-
// Wether or not the Network Helper is enabled for all new Linode Instance Configs on the account.
15+
// Whether or not the Network Helper is enabled for all new Linode Instance Configs on the account.
1616
NetworkHelper bool `json:"network_helper"`
1717

1818
// A plan name like "longview-3"..."longview-100", or a nil value for to cancel any existing subscription plan.
1919
LongviewSubscription *string `json:"longview_subscription"`
2020

2121
// A string like "disabled", "suspended", or "active" describing the status of this account’s Object Storage service enrollment.
2222
ObjectStorage *string `json:"object_storage"`
23+
24+
// The slug of the maintenance policy associated with the account.
25+
// NOTE: MaintenancePolicy can only be used with v4beta.
26+
MaintenancePolicy string `json:"maintenance_policy"`
2327
}
2428

2529
// AccountSettingsUpdateOptions are the updateable account wide flags or plans that effect new resources.
@@ -29,6 +33,10 @@ type AccountSettingsUpdateOptions struct {
2933

3034
// The default network helper setting for all new Linodes and Linode Configs for all users on the account.
3135
NetworkHelper *bool `json:"network_helper,omitempty"`
36+
37+
// The slug of the maintenance policy to set the account to.
38+
// NOTE: MaintenancePolicy can only be used with v4beta.
39+
MaintenancePolicy *string `json:"maintenance_policy,omitempty"`
3240
}
3341

3442
// GetAccountSettings gets the account wide flags or plans that effect new resources

go.work.sum

Whitespace-only changes.

instances.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ type Instance struct {
7777

7878
// Note: Linode interfaces may not currently be available to all users.
7979
InterfaceGeneration InterfaceGeneration `json:"interface_generation"`
80+
81+
// NOTE: MaintenancePolicy can only be used with v4beta.
82+
MaintenancePolicy string `json:"maintenance_policy"`
8083
}
8184

8285
// InstanceSpec represents a linode spec
@@ -208,6 +211,9 @@ type InstanceCreateOptions struct {
208211
Group string `json:"group,omitempty"`
209212

210213
IPv4 []string `json:"ipv4,omitempty"`
214+
215+
// NOTE: MaintenancePolicy can only be used with v4beta.
216+
MaintenancePolicy *string `json:"maintenance_policy,omitempty"`
211217
}
212218

213219
// InstanceCreatePlacementGroupOptions represents the placement group
@@ -227,6 +233,9 @@ type InstanceUpdateOptions struct {
227233

228234
// Deprecated: group is a deprecated property denoting a group label for the Linode.
229235
Group *string `json:"group,omitempty"`
236+
237+
// NOTE: MaintenancePolicy can only be used with v4beta.
238+
MaintenancePolicy *string `json:"maintenance_policy,omitempty"`
230239
}
231240

232241
// UnmarshalJSON implements the json.Unmarshaler interface
@@ -276,12 +285,13 @@ func (backup *InstanceBackup) UnmarshalJSON(b []byte) error {
276285
// GetUpdateOptions converts an Instance to InstanceUpdateOptions for use in UpdateInstance
277286
func (i *Instance) GetUpdateOptions() InstanceUpdateOptions {
278287
return InstanceUpdateOptions{
279-
Label: i.Label,
280-
Group: &i.Group,
281-
Backups: i.Backups,
282-
Alerts: i.Alerts,
283-
WatchdogEnabled: &i.WatchdogEnabled,
284-
Tags: &i.Tags,
288+
Label: i.Label,
289+
Group: &i.Group,
290+
Backups: i.Backups,
291+
Alerts: i.Alerts,
292+
WatchdogEnabled: &i.WatchdogEnabled,
293+
Tags: &i.Tags,
294+
MaintenancePolicy: &i.MaintenancePolicy,
285295
}
286296
}
287297

maintenance_policy.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package linodego
2+
3+
import (
4+
"context"
5+
)
6+
7+
type MaintenancePolicy struct {
8+
Slug string `json:"slug"`
9+
Label string `json:"label"`
10+
Description string `json:"description"`
11+
Type string `json:"type"`
12+
NotificationPeriodSec int `json:"notification_period_sec"`
13+
IsDefault bool `json:"is_default"`
14+
}
15+
16+
// ListMaintenancePolicies can only be used with v4beta.
17+
func (c *Client) ListMaintenancePolicies(ctx context.Context, opts *ListOptions) ([]MaintenancePolicy, error) {
18+
return getPaginatedResults[MaintenancePolicy](ctx, c, "maintenance/policies", opts)
19+
}

regions.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const (
2828
CapabilityLinodes string = "Linodes"
2929
CapabilityLkeHaControlPlanes string = "LKE HA Control Planes"
3030
CapabilityMachineImages string = "Machine Images"
31+
CapabilityMaintenancePolicy string = "Maintenance Policy"
3132
CapabilityMetadata string = "Metadata"
3233
CapabilityNodeBalancers string = "NodeBalancers"
3334
CapabilityObjectStorage string = "Object Storage"

test/integration/account_settings_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,15 @@ func TestAccountSettings_Update(t *testing.T) {
5151
defer httpmock.DeactivateAndReset()
5252

5353
opts := linodego.AccountSettingsUpdateOptions{
54-
BackupsEnabled: Bool(false),
55-
NetworkHelper: Bool(false),
54+
BackupsEnabled: Bool(false),
55+
NetworkHelper: Bool(false),
56+
MaintenancePolicy: String("linode/migrate"),
5657
}
5758

5859
mockSettings := linodego.AccountSettings{
5960
BackupsEnabled: false,
6061
NetworkHelper: false,
62+
MaintenancePolicy: "linode/migrate",
6163
LongviewSubscription: String("longview-100"),
6264
}
6365
mockResponse, _ := json.Marshal(mockSettings)
@@ -72,6 +74,7 @@ func TestAccountSettings_Update(t *testing.T) {
7274
require.False(t, settings.NetworkHelper, "Expected NetworkHelper to be false")
7375
require.NotNil(t, settings.LongviewSubscription, "Expected LongviewSubscription to be non-nil")
7476
require.Equal(t, "longview-100", *settings.LongviewSubscription, "Expected LongviewSubscription to be 'longview-100'")
77+
require.Equal(t, "linode/migrate", settings.MaintenancePolicy, "Expected MaintenancePolicy to be 'linode/migrate'")
7578
}
7679

7780
func Bool(v bool) *bool { return &v }

test/integration/fixtures/TestAccountMaintenances_List.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ interactions:
3939
Content-Type:
4040
- application/json
4141
Expires:
42-
- Wed, 30 Oct 2024 14:06:55 GMT
42+
- Wed, 13 Aug 2025 16:42:52 GMT
4343
Pragma:
4444
- no-cache
4545
Strict-Transport-Security:
@@ -57,7 +57,7 @@ interactions:
5757
X-Oauth-Scopes:
5858
- unknown
5959
X-Ratelimit-Limit:
60-
- "800"
60+
- "1840"
6161
X-Xss-Protection:
6262
- 1; mode=block
6363
status: 200 OK

0 commit comments

Comments
 (0)