Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.prism.log
.stdy.log
codegen.log
Brewfile.lock.json
.idea/
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.16.0"
".": "0.17.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 47
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fhypeman-8251e13b6a8ec8965b5cb0b5ab33d4a16e274a4be7cd6d9fa36642878108797c.yml
openapi_spec_hash: 5c1c0d21d430074ffa76ae62ea137f0b
config_hash: 47cce606a7f8af4dac9c2a8dbc822484
configured_endpoints: 50
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fhypeman-c642f2375b218db533c8ae0ff0695b85c048c72fe19400788ecd2c9d992def46.yml
openapi_spec_hash: 505818e6d24972006fa869dd6ed90757
config_hash: 32c7f371b192b03881971de768ebb07d
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 0.17.0 (2026-03-24)

Full Changelog: [v0.16.0...v0.17.0](https://github.com/kernel/hypeman-go/compare/v0.16.0...v0.17.0)

### Features

* Add scheduled instance snapshots with retention cleanup ([f0d4d52](https://github.com/kernel/hypeman-go/commit/f0d4d52bf563ca828cba5f31f6a0c913d4dba4f8))


### Chores

* **internal:** update gitignore ([3dbe64e](https://github.com/kernel/hypeman-go/commit/3dbe64e2bdb18744c58d30a8a9df44107fed6a61))

## 0.16.0 (2026-03-23)

Full Changelog: [v0.15.0...v0.16.0](https://github.com/kernel/hypeman-go/compare/v0.15.0...v0.16.0)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

```sh
go get -u 'github.com/kernel/hypeman-go@v0.16.0'
go get -u 'github.com/kernel/hypeman-go@v0.17.0'
```

<!-- x-release-please-end -->
Expand Down
12 changes: 12 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ Methods:

Params Types:

- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#SetSnapshotScheduleRequestParam">SetSnapshotScheduleRequestParam</a>
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#SnapshotPolicyParam">SnapshotPolicyParam</a>
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#SnapshotScheduleRetentionParam">SnapshotScheduleRetentionParam</a>
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#VolumeMountParam">VolumeMountParam</a>

Response Types:
Expand All @@ -42,6 +44,8 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceStats">InstanceStats</a>
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#PathInfo">PathInfo</a>
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#SnapshotPolicy">SnapshotPolicy</a>
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#SnapshotSchedule">SnapshotSchedule</a>
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#SnapshotScheduleRetention">SnapshotScheduleRetention</a>
- <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#VolumeMount">VolumeMount</a>

Methods:
Expand Down Expand Up @@ -74,6 +78,14 @@ Methods:
- <code title="post /instances/{id}/snapshots">client.Instances.Snapshots.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceSnapshotService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceSnapshotNewParams">InstanceSnapshotNewParams</a>) (\*<a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#Snapshot">Snapshot</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /instances/{id}/snapshots/{snapshotId}/restore">client.Instances.Snapshots.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceSnapshotService.Restore">Restore</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, snapshotID <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceSnapshotRestoreParams">InstanceSnapshotRestoreParams</a>) (\*<a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#Instance">Instance</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

## SnapshotSchedule

Methods:

- <code title="put /instances/{id}/snapshot-schedule">client.Instances.SnapshotSchedule.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceSnapshotScheduleService.Update">Update</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceSnapshotScheduleUpdateParams">InstanceSnapshotScheduleUpdateParams</a>) (\*<a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#SnapshotSchedule">SnapshotSchedule</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="delete /instances/{id}/snapshot-schedule">client.Instances.SnapshotSchedule.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceSnapshotScheduleService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="get /instances/{id}/snapshot-schedule">client.Instances.SnapshotSchedule.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#InstanceSnapshotScheduleService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (\*<a href="https://pkg.go.dev/github.com/kernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/kernel/hypeman-go#SnapshotSchedule">SnapshotSchedule</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

# Snapshots

Params Types:
Expand Down
126 changes: 123 additions & 3 deletions instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ import (
// automatically. You should not instantiate this service directly, and instead use
// the [NewInstanceService] method instead.
type InstanceService struct {
Options []option.RequestOption
Volumes InstanceVolumeService
Snapshots InstanceSnapshotService
Options []option.RequestOption
Volumes InstanceVolumeService
Snapshots InstanceSnapshotService
SnapshotSchedule InstanceSnapshotScheduleService
}

// NewInstanceService generates a new service that applies the given options to
Expand All @@ -42,6 +43,7 @@ func NewInstanceService(opts ...option.RequestOption) (r InstanceService) {
r.Options = opts
r.Volumes = NewInstanceVolumeService(opts...)
r.Snapshots = NewInstanceSnapshotService(opts...)
r.SnapshotSchedule = NewInstanceSnapshotScheduleService(opts...)
return
}

Expand Down Expand Up @@ -481,6 +483,27 @@ func (r *PathInfo) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// The properties Interval, Retention are required.
type SetSnapshotScheduleRequestParam struct {
// Snapshot interval (Go duration format, minimum 1m).
Interval string `json:"interval" api:"required"`
// At least one of max_count or max_age must be provided.
Retention SnapshotScheduleRetentionParam `json:"retention,omitzero" api:"required"`
// Optional prefix for auto-generated scheduled snapshot names (max 47 chars).
NamePrefix param.Opt[string] `json:"name_prefix,omitzero"`
// User-defined key-value tags.
Metadata map[string]string `json:"metadata,omitzero"`
paramObj
}

func (r SetSnapshotScheduleRequestParam) MarshalJSON() (data []byte, err error) {
type shadow SetSnapshotScheduleRequestParam
return param.MarshalObject(r, (*shadow)(&r))
}
func (r *SetSnapshotScheduleRequestParam) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

type SnapshotPolicy struct {
Compression shared.SnapshotCompressionConfig `json:"compression"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
Expand Down Expand Up @@ -519,6 +542,103 @@ func (r *SnapshotPolicyParam) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

type SnapshotSchedule struct {
// Schedule creation timestamp.
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Source instance ID.
InstanceID string `json:"instance_id" api:"required"`
// Snapshot interval (Go duration format).
Interval string `json:"interval" api:"required"`
// Next scheduled run time.
NextRunAt time.Time `json:"next_run_at" api:"required" format:"date-time"`
// Automatic cleanup policy for scheduled snapshots.
Retention SnapshotScheduleRetention `json:"retention" api:"required"`
// Schedule update timestamp.
UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
// Last schedule run error, if any.
LastError string `json:"last_error" api:"nullable"`
// Last schedule execution time.
LastRunAt time.Time `json:"last_run_at" api:"nullable" format:"date-time"`
// Snapshot ID produced by the last successful run.
LastSnapshotID string `json:"last_snapshot_id" api:"nullable"`
// User-defined key-value tags.
Metadata map[string]string `json:"metadata"`
// Optional prefix used for generated scheduled snapshot names.
NamePrefix string `json:"name_prefix" api:"nullable"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CreatedAt respjson.Field
InstanceID respjson.Field
Interval respjson.Field
NextRunAt respjson.Field
Retention respjson.Field
UpdatedAt respjson.Field
LastError respjson.Field
LastRunAt respjson.Field
LastSnapshotID respjson.Field
Metadata respjson.Field
NamePrefix respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

// Returns the unmodified JSON received from the API
func (r SnapshotSchedule) RawJSON() string { return r.JSON.raw }
func (r *SnapshotSchedule) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// Automatic cleanup policy for scheduled snapshots.
type SnapshotScheduleRetention struct {
// Delete scheduled snapshots older than this duration (Go duration format).
MaxAge string `json:"max_age"`
// Keep at most this many scheduled snapshots for the instance (0 disables
// count-based cleanup).
MaxCount int64 `json:"max_count"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
MaxAge respjson.Field
MaxCount respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

// Returns the unmodified JSON received from the API
func (r SnapshotScheduleRetention) RawJSON() string { return r.JSON.raw }
func (r *SnapshotScheduleRetention) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// ToParam converts this SnapshotScheduleRetention to a
// SnapshotScheduleRetentionParam.
//
// Warning: the fields of the param type will not be present. ToParam should only
// be used at the last possible moment before sending a request. Test for this with
// SnapshotScheduleRetentionParam.Overrides()
func (r SnapshotScheduleRetention) ToParam() SnapshotScheduleRetentionParam {
return param.Override[SnapshotScheduleRetentionParam](json.RawMessage(r.RawJSON()))
}

// Automatic cleanup policy for scheduled snapshots.
type SnapshotScheduleRetentionParam struct {
// Delete scheduled snapshots older than this duration (Go duration format).
MaxAge param.Opt[string] `json:"max_age,omitzero"`
// Keep at most this many scheduled snapshots for the instance (0 disables
// count-based cleanup).
MaxCount param.Opt[int64] `json:"max_count,omitzero"`
paramObj
}

func (r SnapshotScheduleRetentionParam) MarshalJSON() (data []byte, err error) {
type shadow SnapshotScheduleRetentionParam
return param.MarshalObject(r, (*shadow)(&r))
}
func (r *SnapshotScheduleRetentionParam) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

type VolumeMount struct {
// Path where volume is mounted in the guest
MountPath string `json:"mount_path" api:"required"`
Expand Down
93 changes: 93 additions & 0 deletions instancesnapshotschedule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

package hypeman

import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"slices"

shimjson "github.com/kernel/hypeman-go/internal/encoding/json"
"github.com/kernel/hypeman-go/internal/requestconfig"
"github.com/kernel/hypeman-go/option"
)

// InstanceSnapshotScheduleService contains methods and other services that help
// with interacting with the hypeman API.
//
// Note, unlike clients, this service does not read variables from the environment
// automatically. You should not instantiate this service directly, and instead use
// the [NewInstanceSnapshotScheduleService] method instead.
type InstanceSnapshotScheduleService struct {
Options []option.RequestOption
}

// NewInstanceSnapshotScheduleService generates a new service that applies the
// given options to each request. These options are applied after the parent
// client's options (if there is one), and before any request-specific options.
func NewInstanceSnapshotScheduleService(opts ...option.RequestOption) (r InstanceSnapshotScheduleService) {
r = InstanceSnapshotScheduleService{}
r.Options = opts
return
}

// Scheduled runs automatically choose snapshot behavior from current instance
// state:
//
// - `Running` or `Standby` source: create a `Standby` snapshot.
// - `Stopped` source: create a `Stopped` snapshot. For running instances, this
// includes a brief pause/resume cycle during each capture. The minimum supported
// interval is `1m`, but larger intervals are recommended for heavier or
// latency-sensitive workloads. Updating only retention, metadata, or
// `name_prefix` preserves the next scheduled run; changing `interval`
// establishes a new cadence.
func (r *InstanceSnapshotScheduleService) Update(ctx context.Context, id string, body InstanceSnapshotScheduleUpdateParams, opts ...option.RequestOption) (res *SnapshotSchedule, err error) {
opts = slices.Concat(r.Options, opts)
if id == "" {
err = errors.New("missing required id parameter")
return nil, err
}
path := fmt.Sprintf("instances/%s/snapshot-schedule", id)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPut, path, body, &res, opts...)
return res, err
}

// Delete snapshot schedule for an instance
func (r *InstanceSnapshotScheduleService) Delete(ctx context.Context, id string, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
if id == "" {
err = errors.New("missing required id parameter")
return err
}
path := fmt.Sprintf("instances/%s/snapshot-schedule", id)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...)
return err
}

// Get snapshot schedule for an instance
func (r *InstanceSnapshotScheduleService) Get(ctx context.Context, id string, opts ...option.RequestOption) (res *SnapshotSchedule, err error) {
opts = slices.Concat(r.Options, opts)
if id == "" {
err = errors.New("missing required id parameter")
return nil, err
}
path := fmt.Sprintf("instances/%s/snapshot-schedule", id)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return res, err
}

type InstanceSnapshotScheduleUpdateParams struct {
SetSnapshotScheduleRequest SetSnapshotScheduleRequestParam
paramObj
}

func (r InstanceSnapshotScheduleUpdateParams) MarshalJSON() (data []byte, err error) {
return shimjson.Marshal(r.SetSnapshotScheduleRequest)
}
func (r *InstanceSnapshotScheduleUpdateParams) UnmarshalJSON(data []byte) error {
return json.Unmarshal(data, &r.SetSnapshotScheduleRequest)
}
Loading
Loading