Skip to content

Commit

Permalink
refactor(sdl): tidy up errors handling and formatting
Browse files Browse the repository at this point in the history
Signed-off-by: Artur Troian <troian.ap@gmail.com>
  • Loading branch information
troian committed Aug 21, 2023
1 parent 47b9d34 commit 5d2af9c
Showing 1 changed file with 112 additions and 24 deletions.
136 changes: 112 additions & 24 deletions sdl/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
"sort"
"strconv"

"gopkg.in/yaml.v3"

manifest "github.com/akash-network/akash-api/go/manifest/v2beta2"
dtypes "github.com/akash-network/akash-api/go/node/deployment/v1beta3"
types "github.com/akash-network/akash-api/go/node/types/v1beta3"
"gopkg.in/yaml.v3"
)

const (
Expand Down Expand Up @@ -41,10 +42,10 @@ var (
errUnknownNextCase = errors.New("next case is unknown")
errHTTPOptionNotAllowed = errors.New("http option not allowed")
errSDLInvalid = errors.New("SDL invalid")

endpointNameValidationRegex = regexp.MustCompile(`^[[:lower:]]+[[:lower:]-_\d]+$`)
)

var endpointNameValidationRegex = regexp.MustCompile(`^[[:lower:]]+[[:lower:]-_\d]+$`)

var _ SDL = (*v2)(nil)

type v2 struct {
Expand Down Expand Up @@ -84,28 +85,29 @@ type v2HTTPOptions struct {

func (ho v2HTTPOptions) asManifest() (manifest.ServiceExposeHTTPOptions, error) {
maxBodySize := ho.MaxBodySize
if 0 == maxBodySize {

if maxBodySize == 0 {
maxBodySize = defaultMaxBodySize
} else if maxBodySize > upperLimitBodySize {
return manifest.ServiceExposeHTTPOptions{}, fmt.Errorf("%w: body size cannot be greater than %d bytes", errHTTPOptionNotAllowed, upperLimitBodySize)
}

readTimeout := ho.ReadTimeout
if 0 == readTimeout {
if readTimeout == 0 {
readTimeout = defaultReadTimeout
} else if readTimeout > upperLimitReadTimeout {
return manifest.ServiceExposeHTTPOptions{}, fmt.Errorf("%w: read timeout cannot be greater than %d ms", errHTTPOptionNotAllowed, upperLimitReadTimeout)
}

sendTimeout := ho.SendTimeout
if 0 == sendTimeout {
if sendTimeout == 0 {
sendTimeout = defaultSendTimeout
} else if sendTimeout > upperLimitSendTimeout {
return manifest.ServiceExposeHTTPOptions{}, fmt.Errorf("%w: send timeout cannot be greater than %d ms", errHTTPOptionNotAllowed, upperLimitSendTimeout)
}

nextTries := ho.NextTries
if 0 == nextTries {
if nextTries == 0 {
nextTries = defaultNextTries
}

Expand Down Expand Up @@ -394,7 +396,11 @@ func (sdl *v2) buildGroups() error {
func (sdl *v2) validate() error {
for endpointName, endpoint := range sdl.Endpoints {
if !endpointNameValidationRegex.MatchString(endpointName) {
return fmt.Errorf("%w: endpoint named %q is not a valid name", errSDLInvalid, endpointName)
return fmt.Errorf(
"%w: endpoint named %q is not a valid name",
errSDLInvalid,
endpointName,
)
}

if len(endpoint.Kind) == 0 {
Expand All @@ -403,7 +409,12 @@ func (sdl *v2) validate() error {

// Validate endpoint kind, there is only one allowed value for now
if endpoint.Kind != endpointKindIP {
return fmt.Errorf("%w: endpoint named %q, unknown kind %q", errSDLInvalid, endpointName, endpoint.Kind)
return fmt.Errorf(
"%w: endpoint named %q, unknown kind %q",
errSDLInvalid,
endpointName,
endpoint.Kind,
)

Check warning on line 417 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L412-L417

Added lines #L412 - L417 were not covered by tests
}
}

Expand All @@ -417,50 +428,102 @@ func (sdl *v2) validate() error {

compute, ok := sdl.Profiles.Compute[svcdepl.Profile]
if !ok {
return fmt.Errorf("%w: %v.%v: no compute profile named %v", errSDLInvalid, svcName, placementName, svcdepl.Profile)
return fmt.Errorf(
"%w: %v.%v: no compute profile named %v",
errSDLInvalid,
svcName,
placementName,
svcdepl.Profile,
)

Check warning on line 437 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L431-L437

Added lines #L431 - L437 were not covered by tests
}

infra, ok := sdl.Profiles.Placement[placementName]
if !ok {
return fmt.Errorf("%w: %v.%v: no placement profile named %v", errSDLInvalid, svcName, placementName, placementName)
return fmt.Errorf(
"%w: %v.%v: no placement profile named %v",
errSDLInvalid,
svcName,
placementName,
placementName,
)

Check warning on line 448 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L442-L448

Added lines #L442 - L448 were not covered by tests
}

if _, ok := infra.Pricing[svcdepl.Profile]; !ok {
return fmt.Errorf("%w: %v.%v: no pricing for profile %v", errSDLInvalid, svcName, placementName, svcdepl.Profile)
return fmt.Errorf(
"%w: %v.%v: no pricing for profile %v",
errSDLInvalid,
svcName,
placementName,
svcdepl.Profile,
)

Check warning on line 458 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L452-L458

Added lines #L452 - L458 were not covered by tests
}

svc, ok := sdl.Services[svcName]
if !ok {
return fmt.Errorf("%w: %v.%v: no service profile named %v", errSDLInvalid, svcName, placementName, svcName)
return fmt.Errorf(
"%w: %v.%v: no service profile named %v",
errSDLInvalid,
svcName,
placementName,
svcName,
)
}

for _, serviceExpose := range svc.Expose {
for _, to := range serviceExpose.To {
// Check to see if an IP endpoint is also specified
if len(to.IP) != 0 {
if !to.Global {
return fmt.Errorf("%w: error on %q if an IP is declared the directive must be declared as global", errSDLInvalid, svcName)
return fmt.Errorf(
"%w: error on %q if an IP is declared the directive must be declared as global",
errSDLInvalid,
svcName,
)

Check warning on line 481 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L477-L481

Added lines #L477 - L481 were not covered by tests
}
endpoint, endpointExists := sdl.Endpoints[to.IP]
if !endpointExists {
return fmt.Errorf("%w: error on service %q no endpoint named %q exists", errSDLInvalid, svcName, to.IP)
return fmt.Errorf(
"%w: error on service %q no endpoint named %q exists",
errSDLInvalid,
svcName,
to.IP,
)

Check warning on line 490 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L485-L490

Added lines #L485 - L490 were not covered by tests
}

if endpoint.Kind != endpointKindIP {
return fmt.Errorf("%w: error on service %q endpoint %q has type %q, should be %q", errSDLInvalid, svcName, to.IP, endpoint.Kind, endpointKindIP)
return fmt.Errorf(
"%w: error on service %q endpoint %q has type %q, should be %q",
errSDLInvalid,
svcName,
to.IP,
endpoint.Kind,
endpointKindIP,
)

Check warning on line 501 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L494-L501

Added lines #L494 - L501 were not covered by tests
}

endpointsUsed[to.IP] = struct{}{}

// Endpoint exists. Now check for port collisions across a single endpoint, port, & protocol
portKey := fmt.Sprintf("%s-%d-%s", to.IP, serviceExpose.As, serviceExpose.Proto)
portKey := fmt.Sprintf(
"%s-%d-%s",
to.IP,
serviceExpose.As,
serviceExpose.Proto,
)
otherServiceName, inUse := portsUsed[portKey]
if inUse {
return fmt.Errorf("%w: IP endpoint %q port: %d protocol: %s specified by service %q already in use by %q", errSDLInvalid, to.IP, serviceExpose.Port, serviceExpose.Proto, svcName, otherServiceName)
return fmt.Errorf(
"%w: IP endpoint %q port: %d protocol: %s specified by service %q already in use by %q",
errSDLInvalid,
to.IP,
serviceExpose.Port,
serviceExpose.Proto,
svcName,
otherServiceName,
)

Check warning on line 523 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L515-L523

Added lines #L515 - L523 were not covered by tests
}
portsUsed[portKey] = svcName
}

}
}

Expand All @@ -485,11 +548,21 @@ func (sdl *v2) validate() error {
if svc.Params != nil {
for name, params := range svc.Params.Storage {
if _, exists := volumes[name]; !exists {
return fmt.Errorf("%w: service \"%s\" references to no-existing compute volume named \"%s\"", errSDLInvalid, svcName, name)
return fmt.Errorf(
"%w: service \"%s\" references to no-existing compute volume named \"%s\"",
errSDLInvalid,
svcName,
name,
)
}

if !path.IsAbs(params.Mount) {
return fmt.Errorf("%w: invalid value for \"service.%s.params.%s.mount\" parameter. expected absolute path", errSDLInvalid, svcName, name)
return fmt.Errorf(
"%w: invalid value for \"service.%s.params.%s.mount\" parameter. expected absolute path",
errSDLInvalid,
svcName,
name,
)
}

attr[StorageAttributeMount] = params.Mount
Expand All @@ -501,7 +574,12 @@ func (sdl *v2) validate() error {
return errStorageMultipleRootEphemeral
}

return fmt.Errorf("%w: mount %q already in use by volume %q", errStorageDupMountPoint, mount, vlname)
return fmt.Errorf(
"%w: mount %q already in use by volume %q",
errStorageDupMountPoint,
mount,
vlname,
)
}

mounts[mount] = name
Expand All @@ -516,7 +594,13 @@ func (sdl *v2) validate() error {
persistent, _ := strconv.ParseBool(attr[StorageAttributePersistent])

if persistent && attr[StorageAttributeMount] == "" {
return fmt.Errorf("%w: compute.storage.%s has persistent=true which requires service.%s.params.storage.%s to have mount", errSDLInvalid, name, svcName, name)
return fmt.Errorf(
"%w: compute.storage.%s has persistent=true which requires service.%s.params.storage.%s to have mount",
errSDLInvalid,
name,
svcName,
name,
)
}
}
}
Expand All @@ -525,7 +609,11 @@ func (sdl *v2) validate() error {
for endpointName := range sdl.Endpoints {
_, inUse := endpointsUsed[endpointName]
if !inUse {
return fmt.Errorf("%w: endpoint %q declared but never used", errSDLInvalid, endpointName)
return fmt.Errorf(
"%w: endpoint %q declared but never used",
errSDLInvalid,
endpointName,
)

Check warning on line 616 in sdl/v2.go

View check run for this annotation

Codecov / codecov/patch

sdl/v2.go#L612-L616

Added lines #L612 - L616 were not covered by tests
}
}

Expand Down

0 comments on commit 5d2af9c

Please sign in to comment.