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
36 changes: 33 additions & 3 deletions cmd/api/api/builds.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (s *ApiService) CreateBuild(ctx context.Context, request oapi.CreateBuildRe
// Parse multipart form fields
var sourceData []byte
var baseImageDigest, cacheScope, dockerfile, globalCacheKey, imageName string
var timeoutSeconds int
var timeoutSeconds, memoryMB, cpus int
var isAdminBuild bool
var secrets []builds.SecretRef

Expand Down Expand Up @@ -106,6 +106,28 @@ func (s *ApiService) CreateBuild(ctx context.Context, request oapi.CreateBuildRe
if v, err := strconv.Atoi(string(data)); err == nil {
timeoutSeconds = v
}
case "memory_mb":
data, err := io.ReadAll(part)
if err != nil {
return oapi.CreateBuild400JSONResponse{
Code: "invalid_request",
Message: "failed to read memory_mb field",
}, nil
}
if v, err := strconv.Atoi(string(data)); err == nil {
memoryMB = v
}
case "cpus":
data, err := io.ReadAll(part)
if err != nil {
return oapi.CreateBuild400JSONResponse{
Code: "invalid_request",
Message: "failed to read cpus field",
}, nil
}
if v, err := strconv.Atoi(string(data)); err == nil {
cpus = v
}
case "secrets":
data, err := io.ReadAll(part)
if err != nil {
Expand Down Expand Up @@ -183,10 +205,18 @@ func (s *ApiService) CreateBuild(ctx context.Context, request oapi.CreateBuildRe
ImageName: imageName,
}

// Apply timeout if provided
if timeoutSeconds > 0 {
// Apply build policy if any field was provided
if timeoutSeconds > 0 || memoryMB > 0 || cpus > 0 {
domainReq.BuildPolicy = &builds.BuildPolicy{
TimeoutSeconds: timeoutSeconds,
MemoryMB: memoryMB,
CPUs: cpus,
}
if err := domainReq.BuildPolicy.Validate(); err != nil {
return oapi.CreateBuild400JSONResponse{
Code: "invalid_request",
Message: err.Error(),
}, nil
}
}

Expand Down
30 changes: 26 additions & 4 deletions lib/builds/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// inside ephemeral Cloud Hypervisor microVMs for multi-tenant isolation.
package builds

import "time"
import (
"fmt"
"time"
)

// Build status constants
const (
Expand Down Expand Up @@ -211,6 +214,13 @@ type BuildResult struct {
DurationMS int64 `json:"duration_ms"`
}

const (
// MaxBuildCPUs is the maximum number of vCPUs for a builder VM
MaxBuildCPUs = 8
// MaxBuildMemoryMB is the maximum memory in MB for a builder VM (16GB)
MaxBuildMemoryMB = 16384
)

// DefaultBuildPolicy returns the default build policy
func DefaultBuildPolicy() BuildPolicy {
return BuildPolicy{
Expand All @@ -224,16 +234,28 @@ func DefaultBuildPolicy() BuildPolicy {
// ApplyDefaults fills in default values for a build policy
func (p *BuildPolicy) ApplyDefaults() {
defaults := DefaultBuildPolicy()
if p.TimeoutSeconds == 0 {
if p.TimeoutSeconds <= 0 {
p.TimeoutSeconds = defaults.TimeoutSeconds
}
if p.MemoryMB == 0 {
if p.MemoryMB <= 0 {
p.MemoryMB = defaults.MemoryMB
}
if p.CPUs == 0 {
if p.CPUs <= 0 {
p.CPUs = defaults.CPUs
}
if p.NetworkMode == "" {
p.NetworkMode = defaults.NetworkMode
}
}

// Validate checks that the build policy values are within allowed limits.
// Returns an error if any value exceeds the maximum.
func (p *BuildPolicy) Validate() error {
if p.CPUs > MaxBuildCPUs {
return fmt.Errorf("cpus exceeds maximum of %d", MaxBuildCPUs)
}
if p.MemoryMB > MaxBuildMemoryMB {
return fmt.Errorf("memory_mb exceeds maximum of %d MB", MaxBuildMemoryMB)
}
return nil
}
Loading