Skip to content

Commit e68a49d

Browse files
committed
API layer depends on domain
cmd/api/api (handlers) ↓ depends on lib/images, lib/instances, lib/volumes (domain) ↓ independent of lib/oapi (API types)
1 parent 675e090 commit e68a49d

File tree

12 files changed

+233
-165
lines changed

12 files changed

+233
-165
lines changed

cmd/api/api/images.go

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,34 @@ import (
99
"github.com/onkernel/hypeman/lib/oapi"
1010
)
1111

12-
// ListImages lists all images
1312
func (s *ApiService) ListImages(ctx context.Context, request oapi.ListImagesRequestObject) (oapi.ListImagesResponseObject, error) {
1413
log := logger.FromContext(ctx)
1514

16-
imgs, err := s.ImageManager.ListImages(ctx)
15+
domainImages, err := s.ImageManager.ListImages(ctx)
1716
if err != nil {
1817
log.Error("failed to list images", "error", err)
1918
return oapi.ListImages500JSONResponse{
2019
Code: "internal_error",
2120
Message: "failed to list images",
2221
}, nil
2322
}
24-
return oapi.ListImages200JSONResponse(imgs), nil
23+
24+
oapiImages := make([]oapi.Image, len(domainImages))
25+
for i, img := range domainImages {
26+
oapiImages[i] = imageToOAPI(img)
27+
}
28+
29+
return oapi.ListImages200JSONResponse(oapiImages), nil
2530
}
2631

27-
// CreateImage creates a new image from an OCI reference
2832
func (s *ApiService) CreateImage(ctx context.Context, request oapi.CreateImageRequestObject) (oapi.CreateImageResponseObject, error) {
2933
log := logger.FromContext(ctx)
3034

31-
img, err := s.ImageManager.CreateImage(ctx, *request.Body)
35+
domainReq := images.CreateImageRequest{
36+
Name: request.Body.Name,
37+
}
38+
39+
img, err := s.ImageManager.CreateImage(ctx, domainReq)
3240
if err != nil {
3341
switch {
3442
case errors.Is(err, images.ErrInvalidName):
@@ -49,7 +57,7 @@ func (s *ApiService) CreateImage(ctx context.Context, request oapi.CreateImageRe
4957
}, nil
5058
}
5159
}
52-
return oapi.CreateImage202JSONResponse(*img), nil
60+
return oapi.CreateImage202JSONResponse(imageToOAPI(*img)), nil
5361
}
5462

5563
func (s *ApiService) GetImage(ctx context.Context, request oapi.GetImageRequestObject) (oapi.GetImageResponseObject, error) {
@@ -71,7 +79,7 @@ func (s *ApiService) GetImage(ctx context.Context, request oapi.GetImageRequestO
7179
}, nil
7280
}
7381
}
74-
return oapi.GetImage200JSONResponse(*img), nil
82+
return oapi.GetImage200JSONResponse(imageToOAPI(*img)), nil
7583
}
7684

7785
func (s *ApiService) DeleteImage(ctx context.Context, request oapi.DeleteImageRequestObject) (oapi.DeleteImageResponseObject, error) {
@@ -96,3 +104,28 @@ func (s *ApiService) DeleteImage(ctx context.Context, request oapi.DeleteImageRe
96104
return oapi.DeleteImage204Response{}, nil
97105
}
98106

107+
func imageToOAPI(img images.Image) oapi.Image {
108+
oapiImg := oapi.Image{
109+
Name: img.Name,
110+
Status: oapi.ImageStatus(img.Status),
111+
QueuePosition: img.QueuePosition,
112+
Error: img.Error,
113+
SizeBytes: img.SizeBytes,
114+
CreatedAt: img.CreatedAt,
115+
}
116+
117+
if len(img.Entrypoint) > 0 {
118+
oapiImg.Entrypoint = &img.Entrypoint
119+
}
120+
if len(img.Cmd) > 0 {
121+
oapiImg.Cmd = &img.Cmd
122+
}
123+
if len(img.Env) > 0 {
124+
oapiImg.Env = &img.Env
125+
}
126+
if img.WorkingDir != "" {
127+
oapiImg.WorkingDir = &img.WorkingDir
128+
}
129+
130+
return oapiImg
131+
}

cmd/api/api/instances.go

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,42 @@ import (
1414
func (s *ApiService) ListInstances(ctx context.Context, request oapi.ListInstancesRequestObject) (oapi.ListInstancesResponseObject, error) {
1515
log := logger.FromContext(ctx)
1616

17-
insts, err := s.InstanceManager.ListInstances(ctx)
17+
domainInsts, err := s.InstanceManager.ListInstances(ctx)
1818
if err != nil {
1919
log.Error("failed to list instances", "error", err)
2020
return oapi.ListInstances500JSONResponse{
2121
Code: "internal_error",
2222
Message: "failed to list instances",
2323
}, nil
2424
}
25-
return oapi.ListInstances200JSONResponse(insts), nil
25+
26+
oapiInsts := make([]oapi.Instance, len(domainInsts))
27+
for i, inst := range domainInsts {
28+
oapiInsts[i] = instanceToOAPI(inst)
29+
}
30+
31+
return oapi.ListInstances200JSONResponse(oapiInsts), nil
2632
}
2733

2834
// CreateInstance creates and starts a new instance
2935
func (s *ApiService) CreateInstance(ctx context.Context, request oapi.CreateInstanceRequestObject) (oapi.CreateInstanceResponseObject, error) {
3036
log := logger.FromContext(ctx)
3137

32-
inst, err := s.InstanceManager.CreateInstance(ctx, *request.Body)
38+
domainReq := instances.CreateInstanceRequest{
39+
Id: request.Body.Id,
40+
Name: request.Body.Name,
41+
Image: request.Body.Image,
42+
}
43+
44+
inst, err := s.InstanceManager.CreateInstance(ctx, domainReq)
3345
if err != nil {
34-
log.Error("failed to create instance", "error", err, "name", request.Body.Name)
46+
log.Error("failed to create instance", "error", err, "image", request.Body.Image)
3547
return oapi.CreateInstance500JSONResponse{
3648
Code: "internal_error",
3749
Message: "failed to create instance",
3850
}, nil
3951
}
40-
return oapi.CreateInstance201JSONResponse(*inst), nil
52+
return oapi.CreateInstance201JSONResponse(instanceToOAPI(*inst)), nil
4153
}
4254

4355
// GetInstance gets instance details
@@ -60,9 +72,11 @@ func (s *ApiService) GetInstance(ctx context.Context, request oapi.GetInstanceRe
6072
}, nil
6173
}
6274
}
63-
return oapi.GetInstance200JSONResponse(*inst), nil
75+
return oapi.GetInstance200JSONResponse(instanceToOAPI(*inst)), nil
6476
}
6577

78+
79+
6680
// DeleteInstance stops and deletes an instance
6781
func (s *ApiService) DeleteInstance(ctx context.Context, request oapi.DeleteInstanceRequestObject) (oapi.DeleteInstanceResponseObject, error) {
6882
log := logger.FromContext(ctx)
@@ -111,7 +125,7 @@ func (s *ApiService) StandbyInstance(ctx context.Context, request oapi.StandbyIn
111125
}, nil
112126
}
113127
}
114-
return oapi.StandbyInstance200JSONResponse(*inst), nil
128+
return oapi.StandbyInstance200JSONResponse(instanceToOAPI(*inst)), nil
115129
}
116130

117131
// RestoreInstance restores an instance from standby
@@ -139,7 +153,7 @@ func (s *ApiService) RestoreInstance(ctx context.Context, request oapi.RestoreIn
139153
}, nil
140154
}
141155
}
142-
return oapi.RestoreInstance200JSONResponse(*inst), nil
156+
return oapi.RestoreInstance200JSONResponse(instanceToOAPI(*inst)), nil
143157
}
144158

145159
// GetInstanceLogs streams instance logs
@@ -182,7 +196,11 @@ func (s *ApiService) GetInstanceLogs(ctx context.Context, request oapi.GetInstan
182196
func (s *ApiService) AttachVolume(ctx context.Context, request oapi.AttachVolumeRequestObject) (oapi.AttachVolumeResponseObject, error) {
183197
log := logger.FromContext(ctx)
184198

185-
inst, err := s.InstanceManager.AttachVolume(ctx, request.Id, request.VolumeId, *request.Body)
199+
domainReq := instances.AttachVolumeRequest{
200+
MountPath: request.Body.MountPath,
201+
}
202+
203+
inst, err := s.InstanceManager.AttachVolume(ctx, request.Id, request.VolumeId, domainReq)
186204
if err != nil {
187205
switch {
188206
case errors.Is(err, instances.ErrNotFound):
@@ -198,7 +216,7 @@ func (s *ApiService) AttachVolume(ctx context.Context, request oapi.AttachVolume
198216
}, nil
199217
}
200218
}
201-
return oapi.AttachVolume200JSONResponse(*inst), nil
219+
return oapi.AttachVolume200JSONResponse(instanceToOAPI(*inst)), nil
202220
}
203221

204222
// DetachVolume detaches a volume from an instance
@@ -221,6 +239,14 @@ func (s *ApiService) DetachVolume(ctx context.Context, request oapi.DetachVolume
221239
}, nil
222240
}
223241
}
224-
return oapi.DetachVolume200JSONResponse(*inst), nil
242+
return oapi.DetachVolume200JSONResponse(instanceToOAPI(*inst)), nil
225243
}
226244

245+
func instanceToOAPI(inst instances.Instance) oapi.Instance {
246+
return oapi.Instance{
247+
Id: inst.Id,
248+
Name: inst.Name,
249+
Image: inst.Image,
250+
CreatedAt: inst.CreatedAt,
251+
}
252+
}

cmd/api/api/volumes.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,42 @@ import (
1313
func (s *ApiService) ListVolumes(ctx context.Context, request oapi.ListVolumesRequestObject) (oapi.ListVolumesResponseObject, error) {
1414
log := logger.FromContext(ctx)
1515

16-
vols, err := s.VolumeManager.ListVolumes(ctx)
16+
domainVols, err := s.VolumeManager.ListVolumes(ctx)
1717
if err != nil {
1818
log.Error("failed to list volumes", "error", err)
1919
return oapi.ListVolumes500JSONResponse{
2020
Code: "internal_error",
2121
Message: "failed to list volumes",
2222
}, nil
2323
}
24-
return oapi.ListVolumes200JSONResponse(vols), nil
24+
25+
oapiVols := make([]oapi.Volume, len(domainVols))
26+
for i, vol := range domainVols {
27+
oapiVols[i] = volumeToOAPI(vol)
28+
}
29+
30+
return oapi.ListVolumes200JSONResponse(oapiVols), nil
2531
}
2632

2733
// CreateVolume creates a new volume
2834
func (s *ApiService) CreateVolume(ctx context.Context, request oapi.CreateVolumeRequestObject) (oapi.CreateVolumeResponseObject, error) {
2935
log := logger.FromContext(ctx)
3036

31-
vol, err := s.VolumeManager.CreateVolume(ctx, *request.Body)
37+
domainReq := volumes.CreateVolumeRequest{
38+
Name: request.Body.Name,
39+
SizeGb: request.Body.SizeGb,
40+
Id: request.Body.Id,
41+
}
42+
43+
vol, err := s.VolumeManager.CreateVolume(ctx, domainReq)
3244
if err != nil {
3345
log.Error("failed to create volume", "error", err, "name", request.Body.Name)
3446
return oapi.CreateVolume500JSONResponse{
3547
Code: "internal_error",
3648
Message: "failed to create volume",
3749
}, nil
3850
}
39-
return oapi.CreateVolume201JSONResponse(*vol), nil
51+
return oapi.CreateVolume201JSONResponse(volumeToOAPI(*vol)), nil
4052
}
4153

4254
// GetVolume gets volume details
@@ -59,7 +71,7 @@ func (s *ApiService) GetVolume(ctx context.Context, request oapi.GetVolumeReques
5971
}, nil
6072
}
6173
}
62-
return oapi.GetVolume200JSONResponse(*vol), nil
74+
return oapi.GetVolume200JSONResponse(volumeToOAPI(*vol)), nil
6375
}
6476

6577
// DeleteVolume deletes a volume
@@ -90,3 +102,12 @@ func (s *ApiService) DeleteVolume(ctx context.Context, request oapi.DeleteVolume
90102
return oapi.DeleteVolume204Response{}, nil
91103
}
92104

105+
func volumeToOAPI(vol volumes.Volume) oapi.Volume {
106+
return oapi.Volume{
107+
Id: vol.Id,
108+
Name: vol.Name,
109+
SizeGb: vol.SizeGb,
110+
CreatedAt: vol.CreatedAt,
111+
}
112+
}
113+

lib/images/manager.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"time"
1010

1111
"github.com/distribution/reference"
12-
"github.com/onkernel/hypeman/lib/oapi"
1312
)
1413

1514
const (
@@ -20,12 +19,11 @@ const (
2019
StatusFailed = "failed"
2120
)
2221

23-
// Manager handles image lifecycle operations
2422
type Manager interface {
25-
ListImages(ctx context.Context) ([]oapi.Image, error)
26-
CreateImage(ctx context.Context, req oapi.CreateImageRequest) (*oapi.Image, error)
27-
GetImage(ctx context.Context, id string) (*oapi.Image, error)
28-
DeleteImage(ctx context.Context, id string) error
23+
ListImages(ctx context.Context) ([]Image, error)
24+
CreateImage(ctx context.Context, req CreateImageRequest) (*Image, error)
25+
GetImage(ctx context.Context, name string) (*Image, error)
26+
DeleteImage(ctx context.Context, name string) error
2927
RecoverInterruptedBuilds()
3028
}
3129

@@ -46,21 +44,21 @@ func NewManager(dataDir string, ociClient *OCIClient, maxConcurrentBuilds int) M
4644
return m
4745
}
4846

49-
func (m *manager) ListImages(ctx context.Context) ([]oapi.Image, error) {
47+
func (m *manager) ListImages(ctx context.Context) ([]Image, error) {
5048
metas, err := listMetadata(m.dataDir)
5149
if err != nil {
5250
return nil, fmt.Errorf("list metadata: %w", err)
5351
}
5452

55-
images := make([]oapi.Image, 0, len(metas))
53+
images := make([]Image, 0, len(metas))
5654
for _, meta := range metas {
57-
images = append(images, *meta.toOAPI())
55+
images = append(images, *meta.toImage())
5856
}
5957

6058
return images, nil
6159
}
6260

63-
func (m *manager) CreateImage(ctx context.Context, req oapi.CreateImageRequest) (*oapi.Image, error) {
61+
func (m *manager) CreateImage(ctx context.Context, req CreateImageRequest) (*Image, error) {
6462
normalizedName, err := normalizeImageName(req.Name)
6563
if err != nil {
6664
return nil, fmt.Errorf("%w: %s", ErrInvalidName, err.Error())
@@ -85,14 +83,14 @@ func (m *manager) CreateImage(ctx context.Context, req oapi.CreateImageRequest)
8583
m.buildImage(context.Background(), normalizedName, req)
8684
})
8785

88-
img := meta.toOAPI()
86+
img := meta.toImage()
8987
if queuePos > 0 {
9088
img.QueuePosition = &queuePos
9189
}
9290
return img, nil
9391
}
9492

95-
func (m *manager) buildImage(ctx context.Context, imageName string, req oapi.CreateImageRequest) {
93+
func (m *manager) buildImage(ctx context.Context, imageName string, req CreateImageRequest) {
9694
defer m.queue.MarkComplete(imageName)
9795

9896
buildDir := filepath.Join(imageDir(m.dataDir, imageName), ".build")
@@ -184,7 +182,7 @@ func (m *manager) RecoverInterruptedBuilds() {
184182
}
185183
}
186184

187-
func (m *manager) GetImage(ctx context.Context, name string) (*oapi.Image, error) {
185+
func (m *manager) GetImage(ctx context.Context, name string) (*Image, error) {
188186
normalizedName, err := normalizeImageName(name)
189187
if err != nil {
190188
return nil, fmt.Errorf("%w: %s", ErrInvalidName, err.Error())
@@ -195,7 +193,7 @@ func (m *manager) GetImage(ctx context.Context, name string) (*oapi.Image, error
195193
return nil, err
196194
}
197195

198-
img := meta.toOAPI()
196+
img := meta.toImage()
199197

200198
if meta.Status == StatusPending {
201199
img.QueuePosition = m.queue.GetPosition(normalizedName)

0 commit comments

Comments
 (0)