Skip to content
Merged
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
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.0.3"
".": "0.1.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 18
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fhypeman-7c27e323412e72166bce2de104f1bf82b57197e05b686e94cd81d07e288bd558.yml
openapi_spec_hash: 4656d2b318d04a9fec0210897d76b505
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fhypeman-5e2239ba23ac3dbbc95b8993a491e99e9fd23fed2e6ea9cecb81b83bf34a00ff.yml
openapi_spec_hash: 4708504f9119289926b3341d083a1814
config_hash: 35db4c99791f175865381f13a8ad6075
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.1.0 (2025-11-26)

Full Changelog: [v0.0.3...v0.1.0](https://github.com/onkernel/hypeman-go/compare/v0.0.3...v0.1.0)

### Features

* Network manager ([7864aba](https://github.com/onkernel/hypeman-go/commit/7864abadad29bcfbb61d2c35a7135ef2407d6c47))

## 0.0.3 (2025-11-19)

Full Changelog: [v0.0.2...v0.0.3](https://github.com/onkernel/hypeman-go/compare/v0.0.2...v0.0.3)
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/onkernel/hypeman-go@v0.0.3'
go get -u 'github.com/onkernel/hypeman-go@v0.1.0'
```

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

# Instances

Params Types:

- <a href="https://pkg.go.dev/github.com/onkernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/onkernel/hypeman-go#PortMappingParam">PortMappingParam</a>
- <a href="https://pkg.go.dev/github.com/onkernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/onkernel/hypeman-go#VolumeAttachmentParam">VolumeAttachmentParam</a>

Response Types:

- <a href="https://pkg.go.dev/github.com/onkernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/onkernel/hypeman-go#Instance">Instance</a>
- <a href="https://pkg.go.dev/github.com/onkernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/onkernel/hypeman-go#PortMapping">PortMapping</a>
- <a href="https://pkg.go.dev/github.com/onkernel/hypeman-go">hypeman</a>.<a href="https://pkg.go.dev/github.com/onkernel/hypeman-go#VolumeAttachment">VolumeAttachment</a>

Methods:

Expand Down
216 changes: 68 additions & 148 deletions instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package hypeman

import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
Expand Down Expand Up @@ -125,11 +124,11 @@ func (r *InstanceService) StreamLogsStreaming(ctx context.Context, id string, qu
}

type Instance struct {
// Unique identifier
// Auto-generated unique identifier (CUID2 format)
ID string `json:"id,required"`
// Creation timestamp (RFC3339)
CreatedAt time.Time `json:"created_at,required" format:"date-time"`
// Image identifier
// OCI image reference
Image string `json:"image,required"`
// Human-readable name
Name string `json:"name,required"`
Expand All @@ -146,49 +145,40 @@ type Instance struct {
State InstanceState `json:"state,required"`
// Environment variables
Env map[string]string `json:"env"`
// Fully qualified domain name
Fqdn string `json:"fqdn,nullable"`
// Whether a snapshot exists for this instance
HasSnapshot bool `json:"has_snapshot"`
// Configured maximum memory in MB
MemoryMaxMB int64 `json:"memory_max_mb"`
// Configured base memory in MB
MemoryMB int64 `json:"memory_mb"`
// Port mappings
PortMappings []PortMapping `json:"port_mappings"`
// Private IP address
PrivateIP string `json:"private_ip,nullable"`
// Hotplug memory size (human-readable)
HotplugSize string `json:"hotplug_size"`
// Network configuration of the instance
Network InstanceNetwork `json:"network"`
// Writable overlay disk size (human-readable)
OverlaySize string `json:"overlay_size"`
// Base memory size (human-readable)
Size string `json:"size"`
// Start timestamp (RFC3339)
StartedAt time.Time `json:"started_at,nullable" format:"date-time"`
// Stop timestamp (RFC3339)
StoppedAt time.Time `json:"stopped_at,nullable" format:"date-time"`
// Timeout configuration
TimeoutSeconds int64 `json:"timeout_seconds"`
// Number of virtual CPUs
Vcpus int64 `json:"vcpus"`
// Attached volumes
Volumes []VolumeAttachment `json:"volumes"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
ID respjson.Field
CreatedAt respjson.Field
Image respjson.Field
Name respjson.Field
State respjson.Field
Env respjson.Field
Fqdn respjson.Field
HasSnapshot respjson.Field
MemoryMaxMB respjson.Field
MemoryMB respjson.Field
PortMappings respjson.Field
PrivateIP respjson.Field
StartedAt respjson.Field
StoppedAt respjson.Field
TimeoutSeconds respjson.Field
Vcpus respjson.Field
Volumes respjson.Field
ExtraFields map[string]respjson.Field
raw string
ID respjson.Field
CreatedAt respjson.Field
Image respjson.Field
Name respjson.Field
State respjson.Field
Env respjson.Field
HasSnapshot respjson.Field
HotplugSize respjson.Field
Network respjson.Field
OverlaySize respjson.Field
Size respjson.Field
StartedAt respjson.Field
StoppedAt respjson.Field
Vcpus respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

Expand Down Expand Up @@ -217,136 +207,51 @@ const (
InstanceStateStandby InstanceState = "Standby"
)

type PortMapping struct {
// Port in the guest VM
GuestPort int64 `json:"guest_port,required"`
// Port on the host
HostPort int64 `json:"host_port,required"`
// Any of "tcp", "udp".
Protocol PortMappingProtocol `json:"protocol"`
// Network configuration of the instance
type InstanceNetwork struct {
// Whether instance is attached to the default network
Enabled bool `json:"enabled"`
// Assigned IP address (null if no network)
IP string `json:"ip,nullable"`
// Assigned MAC address (null if no network)
Mac string `json:"mac,nullable"`
// Network name (always "default" when enabled)
Name string `json:"name"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
GuestPort respjson.Field
HostPort respjson.Field
Protocol respjson.Field
Enabled respjson.Field
IP respjson.Field
Mac respjson.Field
Name respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

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

// ToParam converts this PortMapping to a PortMappingParam.
//
// 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
// PortMappingParam.Overrides()
func (r PortMapping) ToParam() PortMappingParam {
return param.Override[PortMappingParam](json.RawMessage(r.RawJSON()))
}

type PortMappingProtocol string

const (
PortMappingProtocolTcp PortMappingProtocol = "tcp"
PortMappingProtocolUdp PortMappingProtocol = "udp"
)

// The properties GuestPort, HostPort are required.
type PortMappingParam struct {
// Port in the guest VM
GuestPort int64 `json:"guest_port,required"`
// Port on the host
HostPort int64 `json:"host_port,required"`
// Any of "tcp", "udp".
Protocol PortMappingProtocol `json:"protocol,omitzero"`
paramObj
}

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

type VolumeAttachment struct {
// Path where volume is mounted in the guest
MountPath string `json:"mount_path,required"`
// Volume identifier
VolumeID string `json:"volume_id,required"`
// Whether volume is mounted read-only
Readonly bool `json:"readonly"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
MountPath respjson.Field
VolumeID respjson.Field
Readonly respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

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

// ToParam converts this VolumeAttachment to a VolumeAttachmentParam.
//
// 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
// VolumeAttachmentParam.Overrides()
func (r VolumeAttachment) ToParam() VolumeAttachmentParam {
return param.Override[VolumeAttachmentParam](json.RawMessage(r.RawJSON()))
}

// The properties MountPath, VolumeID are required.
type VolumeAttachmentParam struct {
// Path where volume is mounted in the guest
MountPath string `json:"mount_path,required"`
// Volume identifier
VolumeID string `json:"volume_id,required"`
// Whether volume is mounted read-only
Readonly param.Opt[bool] `json:"readonly,omitzero"`
paramObj
}

func (r VolumeAttachmentParam) MarshalJSON() (data []byte, err error) {
type shadow VolumeAttachmentParam
return param.MarshalObject(r, (*shadow)(&r))
}
func (r *VolumeAttachmentParam) UnmarshalJSON(data []byte) error {
func (r InstanceNetwork) RawJSON() string { return r.JSON.raw }
func (r *InstanceNetwork) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

type InstanceNewParams struct {
// Unique identifier for the instance (provided by caller)
ID string `json:"id,required"`
// Image identifier
// OCI image reference
Image string `json:"image,required"`
// Human-readable name
// Human-readable name (lowercase letters, digits, and dashes only; cannot start or
// end with a dash)
Name string `json:"name,required"`
// Maximum memory with hotplug in MB
MemoryMaxMB param.Opt[int64] `json:"memory_max_mb,omitzero"`
// Base memory in MB
MemoryMB param.Opt[int64] `json:"memory_mb,omitzero"`
// Timeout for scale-to-zero semantics
TimeoutSeconds param.Opt[int64] `json:"timeout_seconds,omitzero"`
// Additional memory for hotplug (human-readable format like "3GB", "1G")
HotplugSize param.Opt[string] `json:"hotplug_size,omitzero"`
// Writable overlay disk size (human-readable format like "10GB", "50G")
OverlaySize param.Opt[string] `json:"overlay_size,omitzero"`
// Base memory size (human-readable format like "1GB", "512MB", "2G")
Size param.Opt[string] `json:"size,omitzero"`
// Number of virtual CPUs
Vcpus param.Opt[int64] `json:"vcpus,omitzero"`
// Environment variables
Env map[string]string `json:"env,omitzero"`
// Port mappings from host to guest
PortMappings []PortMappingParam `json:"port_mappings,omitzero"`
// Volumes to attach
Volumes []VolumeAttachmentParam `json:"volumes,omitzero"`
// Network configuration for the instance
Network InstanceNewParamsNetwork `json:"network,omitzero"`
paramObj
}

Expand All @@ -358,6 +263,21 @@ func (r *InstanceNewParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// Network configuration for the instance
type InstanceNewParamsNetwork struct {
// Whether to attach instance to the default network
Enabled param.Opt[bool] `json:"enabled,omitzero"`
paramObj
}

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

type InstanceStreamLogsParams struct {
// Follow logs (stream with SSE)
Follow param.Opt[bool] `query:"follow,omitzero" json:"-"`
Expand Down
24 changes: 8 additions & 16 deletions instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,19 @@ func TestInstanceNewWithOptionalParams(t *testing.T) {
option.WithAPIKey("My API Key"),
)
_, err := client.Instances.New(context.TODO(), hypeman.InstanceNewParams{
ID: "inst-abc123",
Image: "img-chrome-v1",
Image: "docker.io/library/alpine:latest",
Name: "my-workload-1",
Env: map[string]string{
"PORT": "3000",
"NODE_ENV": "production",
},
MemoryMaxMB: hypeman.Int(4096),
MemoryMB: hypeman.Int(2048),
PortMappings: []hypeman.PortMappingParam{{
GuestPort: 80,
HostPort: 8080,
Protocol: hypeman.PortMappingProtocolTcp,
}},
TimeoutSeconds: hypeman.Int(7200),
Vcpus: hypeman.Int(2),
Volumes: []hypeman.VolumeAttachmentParam{{
MountPath: "/mnt/data",
VolumeID: "vol-abc123",
Readonly: hypeman.Bool(true),
}},
HotplugSize: hypeman.String("2GB"),
Network: hypeman.InstanceNewParamsNetwork{
Enabled: hypeman.Bool(true),
},
OverlaySize: hypeman.String("20GB"),
Size: hypeman.String("2GB"),
Vcpus: hypeman.Int(2),
})
if err != nil {
var apierr *hypeman.Error
Expand Down
2 changes: 1 addition & 1 deletion internal/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

package internal

const PackageVersion = "0.0.3" // x-release-please-version
const PackageVersion = "0.1.0" // x-release-please-version