Skip to content
This repository was archived by the owner on Jan 2, 2026. It is now read-only.

Commit 2f85eba

Browse files
committed
feat: add machine gateways
1 parent 4f0bd66 commit 2f85eba

File tree

27 files changed

+495
-192
lines changed

27 files changed

+495
-192
lines changed

agent/client/machines.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,21 @@ func (a *AgentClient) GetMachineLogsRaw(ctx context.Context, id string, follow b
105105
}
106106
return a.client.RawGet(ctx, path)
107107
}
108+
109+
func (a *AgentClient) DisableMachineGateway(ctx context.Context, id string) error {
110+
path := "/machines/" + id + "/gateway/disable"
111+
err := a.client.Post(ctx, path, nil)
112+
if err != nil {
113+
return err
114+
}
115+
return nil
116+
}
117+
118+
func (a *AgentClient) EnableMachineGateway(ctx context.Context, id string) error {
119+
path := "/machines/" + id + "/gateway/enable"
120+
err := a.client.Post(ctx, path, nil)
121+
if err != nil {
122+
return err
123+
}
124+
return nil
125+
}

agent/machine.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,11 @@ func (a *Agent) PutMachine(ctx context.Context, opt cluster.PutMachineOptions) (
6565
Machine: opt.Machine,
6666
Version: opt.Version,
6767
State: structs.MachineInstanceState{
68-
DesiredStatus: desiredStatus,
69-
Status: api.MachineStatusCreated,
70-
CreatedAt: time.Now(),
71-
UpdatedAt: time.Now(),
68+
DesiredStatus: desiredStatus,
69+
Status: api.MachineStatusCreated,
70+
CreatedAt: time.Now(),
71+
UpdatedAt: time.Now(),
72+
MachineGatewayEnabled: opt.EnableGateway,
7273
},
7374
}
7475

@@ -139,3 +140,21 @@ func (d *Agent) MachineExec(ctx context.Context, id string, cmd []string, timeou
139140

140141
return machine.Exec(ctx, cmd, timeout)
141142
}
143+
144+
func (d *Agent) EnableMachineGateway(ctx context.Context, id string) error {
145+
machine, err := d.machines.GetMachine(id)
146+
if err != nil {
147+
return err
148+
}
149+
150+
return machine.EnableGateway(ctx)
151+
}
152+
153+
func (d *Agent) DisableMachineGateway(ctx context.Context, id string) error {
154+
machine, err := d.machines.GetMachine(id)
155+
if err != nil {
156+
return err
157+
}
158+
159+
return machine.DisableGateway(ctx)
160+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package machinerunner
2+
3+
import "context"
4+
5+
func (m *MachineRunner) EnableGateway(ctx context.Context) error {
6+
m.mutex.Lock()
7+
defer m.mutex.Unlock()
8+
9+
if m.state.MachineInstance().State.MachineGatewayEnabled {
10+
return nil
11+
}
12+
13+
if err := m.state.PushGatewayEvent(true); err != nil {
14+
return err
15+
}
16+
17+
return nil
18+
}
19+
20+
func (m *MachineRunner) DisableGateway(ctx context.Context) error {
21+
m.mutex.Lock()
22+
defer m.mutex.Unlock()
23+
24+
if !m.state.MachineInstance().State.MachineGatewayEnabled {
25+
return nil
26+
}
27+
28+
if err := m.state.PushGatewayEvent(false); err != nil {
29+
return err
30+
}
31+
32+
return nil
33+
}

agent/machinerunner/state/events.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,27 @@ func (s *MachineInstanceState) PushDestroyedEvent(ctx context.Context) (err erro
323323

324324
return nil
325325
}
326+
327+
func (s *MachineInstanceState) PushGatewayEvent(enabled bool) (err error) {
328+
s.mutex.Lock()
329+
defer s.mutex.Unlock()
330+
331+
event := s.newEvent(
332+
api.MachineGateway,
333+
api.OriginUser,
334+
s.mi.State.Status,
335+
api.MachineEventPayload{
336+
Gateway: &api.MachineGatewayEventPayload{
337+
Enabled: enabled,
338+
},
339+
},
340+
)
341+
342+
s.mi.State.MachineGatewayEnabled = enabled
343+
344+
if err = s.persistStateAndEvent(event); err != nil {
345+
return
346+
}
347+
348+
return nil
349+
}

agent/server/machines.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,35 @@ func (s *AgentServer) getMachineLogs(ctx context.Context, req *GetMachineLogsReq
130130
}
131131
return &GetMachineLogsResponse{Body: logs}, nil
132132
}
133+
134+
type EnableMachineGatewayRequest struct {
135+
Id string `path:"id"`
136+
}
137+
138+
type EnableMachineGatewayResponse struct {
139+
}
140+
141+
func (s *AgentServer) enableMachineGateway(ctx context.Context, req *EnableMachineGatewayRequest) (*EnableMachineGatewayResponse, error) {
142+
err := s.agent.EnableMachineGateway(ctx, req.Id)
143+
if err != nil {
144+
s.log("Failed to enable machine gateway", err)
145+
return nil, err
146+
}
147+
return &EnableMachineGatewayResponse{}, nil
148+
}
149+
150+
type DisableMachineGatewayRequest struct {
151+
Id string `path:"id"`
152+
}
153+
154+
type DisableMachineGatewayResponse struct {
155+
}
156+
157+
func (s *AgentServer) disableMachineGateway(ctx context.Context, req *DisableMachineGatewayRequest) (*DisableMachineGatewayResponse, error) {
158+
err := s.agent.DisableMachineGateway(ctx, req.Id)
159+
if err != nil {
160+
s.log("Failed to disable machine gateway", err)
161+
return nil, err
162+
}
163+
return &DisableMachineGatewayResponse{}, nil
164+
}

agent/server/routes.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,16 @@ func (s AgentServer) registerEndpoints(mux humago.Mux) {
7373
Method: http.MethodDelete,
7474
}, s.destroyMachine)
7575

76+
huma.Register(api, huma.Operation{
77+
OperationID: "enableMachineGateway",
78+
Path: "/machines/{id}/gateway/enable",
79+
Method: http.MethodPost,
80+
}, s.enableMachineGateway)
81+
82+
huma.Register(api, huma.Operation{
83+
OperationID: "disableMachineGateway",
84+
Path: "/machines/{id}/gateway/disable",
85+
Method: http.MethodPost,
86+
}, s.disableMachineGateway)
87+
7688
}

agent/structs/machine_instance.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import (
99
)
1010

1111
type MachineInstanceState struct {
12-
DesiredStatus api.MachineStatus `json:"desired_status"`
13-
Status api.MachineStatus `json:"status"`
14-
Restarts int `json:"restarts"`
15-
CreatedAt time.Time `json:"created_at"`
16-
UpdatedAt time.Time `json:"updated_at"`
17-
LocalIPV4 string `json:"local_ipv4"`
18-
LastEvents []api.MachineEvent `json:"last_events"`
12+
DesiredStatus api.MachineStatus `json:"desired_status"`
13+
Status api.MachineStatus `json:"status"`
14+
Restarts int `json:"restarts"`
15+
CreatedAt time.Time `json:"created_at"`
16+
UpdatedAt time.Time `json:"updated_at"`
17+
LocalIPV4 string `json:"local_ipv4"`
18+
LastEvents []api.MachineEvent `json:"last_events"`
19+
MachineGatewayEnabled bool `json:"machine_gateway_enabled"`
1920
}
2021

2122
type MachineInstance struct {
@@ -47,15 +48,16 @@ func (mi *MachineInstance) InstanceOptions() instance.InstanceOptions {
4748

4849
func (mi *MachineInstance) ClusterInstance() cluster.MachineInstance {
4950
return cluster.MachineInstance{
50-
Id: mi.Machine.InstanceId,
51-
Node: mi.Machine.Node,
52-
Namespace: mi.Machine.Namespace,
53-
MachineId: mi.Machine.Id,
54-
MachineVersion: mi.Version.Id,
55-
Events: mi.State.LastEvents,
56-
Status: mi.State.Status,
57-
LocalIPV4: mi.State.LocalIPV4,
58-
CreatedAt: mi.State.CreatedAt,
59-
UpdatedAt: mi.State.UpdatedAt,
51+
Id: mi.Machine.InstanceId,
52+
Node: mi.Machine.Node,
53+
Namespace: mi.Machine.Namespace,
54+
MachineId: mi.Machine.Id,
55+
MachineVersion: mi.Version.Id,
56+
Events: mi.State.LastEvents,
57+
Status: mi.State.Status,
58+
LocalIPV4: mi.State.LocalIPV4,
59+
CreatedAt: mi.State.CreatedAt,
60+
UpdatedAt: mi.State.UpdatedAt,
61+
EnableMachineGateway: mi.State.MachineGatewayEnabled,
6062
}
6163
}

api/machines.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Machine struct {
2929
UpdatedAt time.Time `json:"updated_at"`
3030
Events []MachineEvent `json:"events"`
3131
Status MachineStatus `json:"state"`
32+
GatewayEnabled bool `json:"gateway_enabled"`
3233
}
3334

3435
type MachineStatus string
@@ -69,7 +70,7 @@ type (
6970
MachineConfig struct {
7071
Image string `json:"image"`
7172
Guest GuestConfig `json:"guest"`
72-
Workload Workload `json:"workload"`
73+
Workload Workload `json:"workload,omitempty"`
7374
StopConfig *StopConfig `json:"stop_config,omitempty"`
7475
AutoDestroy bool `json:"auto_destroy,omitempty"`
7576
}
@@ -120,12 +121,14 @@ const (
120121
MachineExited MachineEventType = "machine.exited"
121122
MachineDestroy MachineEventType = "machine.destroy"
122123
MachineDestroyed MachineEventType = "machine.destroyed"
124+
MachineGateway MachineEventType = "machine.gateway"
123125
)
124126

125127
type CreateMachinePayload struct {
126-
Region string `json:"region"`
127-
Config MachineConfig `json:"config"`
128-
SkipStart bool `json:"skip_start"`
128+
Region string `json:"region"`
129+
Config MachineConfig `json:"config"`
130+
SkipStart bool `json:"skip_start,omitempty"`
131+
EnableMachineGateway bool `json:"enable_machine_gateway,omitempty"`
129132
}
130133

131134
type MachineStartEventPayload struct {
@@ -159,6 +162,10 @@ type MachineDestroyEventPayload struct {
159162
Force bool `json:"force"`
160163
}
161164

165+
type MachineGatewayEventPayload struct {
166+
Enabled bool `json:"enabled"`
167+
}
168+
162169
type MachineEventPayload struct {
163170
PrepareFailed *MachinePrepareFailedEventPayload `json:"prepare_failed,omitempty"`
164171
Stop *MachineStopEventPayload `json:"stop,omitempty"`
@@ -167,6 +174,7 @@ type MachineEventPayload struct {
167174
Started *MachineStartedEventPayload `json:"started,omitempty"`
168175
Exited *MachineExitedEventPayload `json:"stopped,omitempty"`
169176
Destroy *MachineDestroyEventPayload `json:"destroy,omitempty"`
177+
Gateway *MachineGatewayEventPayload `json:"gateway,omitempty"`
170178
}
171179

172180
type Origin string

core/cluster/agent.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import (
88
)
99

1010
type PutMachineOptions struct {
11-
Machine Machine `json:"machine"`
12-
Version api.MachineVersion `json:"version"`
13-
AllocationId string `json:"allocation_id"`
14-
Start bool `json:"start"`
11+
Machine Machine `json:"machine"`
12+
Version api.MachineVersion `json:"version"`
13+
AllocationId string `json:"allocation_id"`
14+
Start bool `json:"start"`
15+
EnableGateway bool `json:"enable_gateway"`
1516
}
1617

1718
type Agent interface {
@@ -26,4 +27,7 @@ type Agent interface {
2627
DestroyMachine(ctx context.Context, machineId string, force bool) error
2728
SubscribeToMachineLogs(ctx context.Context, id string) ([]*api.LogEntry, <-chan *api.LogEntry, error)
2829
GetMachineLogs(ctx context.Context, id string) ([]*api.LogEntry, error)
30+
31+
EnableMachineGateway(ctx context.Context, id string) error
32+
DisableMachineGateway(ctx context.Context, id string) error
2933
}

core/cluster/cluster_state.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
)
99

1010
type Queries interface {
11+
12+
/* Used by the API server */
1113
CreateGateway(ctx context.Context, gateway api.Gateway) error
1214
DeleteGateway(ctx context.Context, id string) error
1315
DeleteFleetGateways(ctx context.Context, fleetId string) error
@@ -17,17 +19,17 @@ type Queries interface {
1719
UpdateMachine(ctx context.Context, m Machine) error
1820
DestroyMachine(ctx context.Context, id string) error
1921

20-
UpsertInstance(ctx context.Context, i MachineInstance) error
22+
ListAPIMachines(ctx context.Context, namespace string, fleetId string, includeDestroyed bool) ([]api.Machine, error)
23+
GetAPIMachine(ctx context.Context, namespace string, fleetId string, machineId string) (*api.Machine, error)
24+
DestroyNamespaceData(ctx context.Context, namespace string) error
2125

2226
GetNode(ctx context.Context, id string) (api.Node, error)
23-
UpsertNode(ctx context.Context, node api.Node) error
2427
ListNodesInRegion(ctx context.Context, region string) ([]api.Node, error)
2528
ListNodes(ctx context.Context) ([]api.Node, error)
2629

27-
ListAPIMachines(ctx context.Context, namespace string, fleetId string, includeDestroyed bool) ([]api.Machine, error)
28-
GetAPIMachine(ctx context.Context, namespace string, fleetId string, machineId string) (*api.Machine, error)
29-
30-
DestroyNamespaceData(ctx context.Context, namespace string) error
30+
/* Used by raveld */
31+
UpsertNode(ctx context.Context, node api.Node) error
32+
UpsertInstance(ctx context.Context, i MachineInstance) error
3133
}
3234

3335
type ClusterState interface {

0 commit comments

Comments
 (0)