Skip to content

Commit

Permalink
size image constraints types and validation (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
majst01 authored Jan 27, 2022
1 parent 4764ed4 commit 79372e4
Show file tree
Hide file tree
Showing 20 changed files with 1,426 additions and 182 deletions.
15 changes: 8 additions & 7 deletions .github/workflows/latest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v2

- name: Set up Go 1.16
uses: actions/setup-go@v2.1.3
- name: Set up Go 1.17
uses: actions/setup-go@v2
with:
go-version: '1.16.x'
go-version: '1.17.x'

- name: Docker Login
uses: docker/login-action@v1
Expand All @@ -27,6 +27,7 @@ jobs:
- name: Lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.43
args: --build-tags integration -p bugs -p unused --timeout=3m

- name: Build Docker image
Expand All @@ -47,11 +48,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v2

- name: Set up Go 1.16
uses: actions/setup-go@v2.1.3
- name: Set up Go 1.17
uses: actions/setup-go@v2
with:
go-version: '1.16.x'
go-version: '1.17.x'

- name: Run integration tests
run: |
go test -tags=integration -timeout 600s -p 1 ./...
go test -tags=integration -timeout 600s -p 1 ./...
15 changes: 8 additions & 7 deletions .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v2

- name: Set up Go 1.16
uses: actions/setup-go@v2.1.3
- name: Set up Go 1.17
uses: actions/setup-go@v2
with:
go-version: '1.16.x'
go-version: '1.17.x'

- name: Figure out if running fork PR
id: fork
Expand All @@ -32,6 +32,7 @@ jobs:
- name: Lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.43
args: --build-tags integration -p bugs -p unused --timeout=3m

- name: Build Docker image
Expand All @@ -50,11 +51,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v2

- name: Set up Go 1.16
uses: actions/setup-go@v2.1.3
- name: Set up Go 1.17
uses: actions/setup-go@v2
with:
go-version: '1.16.x'
go-version: '1.17.x'

- name: Run integration tests
run: |
go test -tags=integration -timeout 600s -p 1 ./...
go test -tags=integration -timeout 600s -p 1 ./...
7 changes: 4 additions & 3 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v2

- name: Set up Go 1.16
uses: actions/setup-go@v2.1.3
- name: Set up Go 1.17
uses: actions/setup-go@v2
with:
go-version: '1.16.x'
go-version: '1.17.x'

- name: Docker Login
uses: docker/login-action@v1
Expand All @@ -27,6 +27,7 @@ jobs:
- name: Lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.43
args: --build-tags integration -p bugs -p unused --timeout=3m

- name: Build and push Docker image
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM metalstack/builder:latest as builder

FROM alpine:3.13
FROM alpine:3.15
RUN apk -U add ca-certificates
COPY --from=builder /work/bin/metal-api /metal-api
CMD ["/metal-api"]
7 changes: 6 additions & 1 deletion cmd/metal-api/internal/datastore/rethinkdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (
)

var tables = []string{
"image", "size", "partition", "machine", "switch", "event", "network", "ip", "migration", "filesystemlayout",
"image", "size", "partition", "machine", "switch", "event", "network", "ip", "migration", "filesystemlayout", "sizeimageconstraint",
VRFIntegerPool.String(), VRFIntegerPool.String() + "info",
ASNIntegerPool.String(), ASNIntegerPool.String() + "info",
}
Expand Down Expand Up @@ -180,6 +180,11 @@ func (rs *RethinkStore) filesystemLayoutTable() *r.Term {
return &res
}

func (rs *RethinkStore) sizeImageConstraintTable() *r.Term {
res := r.DB(rs.dbname).Table("sizeimageconstraint")
return &res
}

func (rs *RethinkStore) asnTable() *r.Term {
res := r.DB(rs.dbname).Table(ASNIntegerPool.String())
return &res
Expand Down
35 changes: 35 additions & 0 deletions cmd/metal-api/internal/datastore/sizeimageconstraint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package datastore

import "github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"

// FindSizeImageConstraint return a SizeImageConstraint for a given size.
func (rs *RethinkStore) FindSizeImageConstraint(sizeID string) (*metal.SizeImageConstraint, error) {
var ic metal.SizeImageConstraint
err := rs.findEntityByID(rs.sizeImageConstraintTable(), &ic, sizeID)
if err != nil {
return nil, err
}
return &ic, nil
}

// ListSizeImageConstraints returns all SizeImageConstraints.
func (rs *RethinkStore) ListSizeImageConstraints() (metal.SizeImageConstraints, error) {
fls := make(metal.SizeImageConstraints, 0)
err := rs.listEntities(rs.sizeImageConstraintTable(), &fls)
return fls, err
}

// CreateSizeImageConstraint creates a new SizeImageConstraint.
func (rs *RethinkStore) CreateSizeImageConstraint(ic *metal.SizeImageConstraint) error {
return rs.createEntity(rs.sizeImageConstraintTable(), ic)
}

// DeleteSizeImageConstraint deletes a SizeImageConstraint.
func (rs *RethinkStore) DeleteSizeImageConstraint(ic *metal.SizeImageConstraint) error {
return rs.deleteEntity(rs.sizeImageConstraintTable(), ic)
}

// UpdateSizeImageConstraint updates a SizeImageConstraint.
func (rs *RethinkStore) UpdateSizeImageConstraint(oldSizeImageConstraint *metal.SizeImageConstraint, newSizeImageConstraint *metal.SizeImageConstraint) error {
return rs.updateEntity(rs.sizeImageConstraintTable(), newSizeImageConstraint, oldSizeImageConstraint)
}
3 changes: 2 additions & 1 deletion cmd/metal-api/internal/grpc/wait-service_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
)

Expand Down Expand Up @@ -218,7 +219,7 @@ func (t *test) startMachineInstances() {
}
opts := []grpc.DialOption{
grpc.WithKeepaliveParams(kacp),
grpc.WithInsecure(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
}
for i := 0; i < t.numberMachineInstances; i++ {
Expand Down
2 changes: 1 addition & 1 deletion cmd/metal-api/internal/metal/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ func (c *FilesystemLayoutConstraints) validate() error {
if err != nil {
return err
}

}

sizeSet := make(map[string]bool)
// no wildcard in size
for _, s := range c.Sizes {
Expand Down
93 changes: 93 additions & 0 deletions cmd/metal-api/internal/metal/sizeimageconstraint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package metal

import (
"fmt"
"strings"

"github.com/Masterminds/semver/v3"
)

// SizeImageConstraint expresses optional restrictions for specific size to image combinations
// this might be required if the support for a specific hardware in a given size is only supported
// with a newer version of the image.
//
// If the size in question is not found, no restrictions apply.
// If the image in question is not found, no restrictions apply as well.
// If the image in question is found, but does not match the given expression, machine creation must be forbidden.
type SizeImageConstraint struct {
Base
// Images a map from imageID to semver compatible matcher string
// example:
// images:
// ubuntu: ">= 20.04.20211011"
// debian: ">= 10.0.20210101"
Images map[string]string `rethinkdb:"images" json:"images"`
}

// SizeImageConstraints is a slice of ImageConstraint
type SizeImageConstraints []SizeImageConstraint

func (scs *SizeImageConstraints) Validate() error {
for _, c := range *scs {
err := c.Validate()
if err != nil {
return err
}
}
return nil
}

func (sc *SizeImageConstraint) Validate() error {
for os, vc := range sc.Images {
// no pure wildcard in images
if os == "*" {
return fmt.Errorf("just '*' is not allowed as image os constraint")
}
// a single "*" is possible
if strings.TrimSpace(vc) == "*" {
continue
}
_, _, err := convertToOpAndVersion(vc)
if err != nil {
return err
}
}
return nil
}

func (scs *SizeImageConstraints) Matches(size Size, image Image) error {
for _, sc := range *scs {
if sc.ID == size.ID {
return sc.Matches(size, image)
}
}
return nil
}

func (sc *SizeImageConstraint) Matches(size Size, image Image) error {
if sc.ID != size.ID {
return nil
}
for os, versionconstraint := range sc.Images {
if os != image.OS {
continue
}
version, err := semver.NewVersion(image.Version)
if err != nil {
return fmt.Errorf("version of image is invalid %w", err)
}

// FIXME is this a valid assumption
if version.Patch() == 0 {
return fmt.Errorf("no patch version given")
}
c, err := semver.NewConstraint(versionconstraint)
if err != nil {
return fmt.Errorf("versionconstraint %s is invalid %w", versionconstraint, err)
}
if !c.Check(version) {
return fmt.Errorf("given size:%s with image:%s does violate image constraint:%s %s", size.ID, image.OS+"-"+image.Version, os, c.String())
}
}
return nil
}
Loading

0 comments on commit 79372e4

Please sign in to comment.