Skip to content

Commit

Permalink
Merge pull request #45 from derekhiggins/cir-list
Browse files Browse the repository at this point in the history
Add support for a CIR type list
  • Loading branch information
openshift-merge-bot[bot] authored Apr 30, 2024
2 parents 2e2ccab + ae84854 commit 660e454
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 26 deletions.
40 changes: 29 additions & 11 deletions pkg/server/commands/acquire.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"math/rand"
"net/http"
"sort"
"strings"

"github.com/gin-gonic/gin"
ofcirv1 "github.com/openshift/ofcir/api/v1"
Expand All @@ -15,19 +16,35 @@ import (
)

type acquireCmd struct {
context *gin.Context
clientset *ofcirclientv1.OfcirV1Client
namespace string
resourceType ofcirv1.CIResourceType
context *gin.Context
clientset *ofcirclientv1.OfcirV1Client
namespace string
resourceTypes []ofcirv1.CIResourceType
}

func NewAcquireCmd(c *gin.Context, clientset *ofcirclientv1.OfcirV1Client, ns string, resourceType string) command {
func NewAcquireCmd(c *gin.Context, clientset *ofcirclientv1.OfcirV1Client, ns string, resourceType_str string) command {
// type can be a comma seperated list
resourceTypes_split := strings.Split(resourceType_str, ",")
resourceTypes := make([]ofcirv1.CIResourceType, len(resourceTypes_split))
for i, v := range resourceTypes_split {
resourceTypes[i] = ofcirv1.CIResourceType(v)
}

return &acquireCmd{
context: c,
clientset: clientset,
namespace: ns,
resourceType: ofcirv1.CIResourceType(resourceType),
context: c,
clientset: clientset,
namespace: ns,
resourceTypes: resourceTypes,
}
}

func contains(rtypes []ofcirv1.CIResourceType, rtype ofcirv1.CIResourceType) bool {
for _, t := range rtypes {
if t == rtype {
return true
}
}
return false
}

func (c *acquireCmd) Run() error {
Expand All @@ -38,14 +55,15 @@ func (c *acquireCmd) Run() error {
}

poolsByName := make(map[string]ofcirv1.CIPool)
// c.resourceTypes is a list of cir types, no preference is given to the order
for _, p := range pools.Items {
if (p.Spec.Type == c.resourceType) && utils.CanUsePool(c.context, p.Name) {
if (contains(c.resourceTypes, p.Spec.Type)) && utils.CanUsePool(c.context, p.Name) {
poolsByName[p.Name] = p
}
}

if len(poolsByName) == 0 {
c.context.String(http.StatusNotFound, fmt.Sprintf("No available pool found of type %v", c.resourceType))
c.context.String(http.StatusNotFound, fmt.Sprintf("No available pool found of type %v", c.resourceTypes))
return nil
}

Expand Down
48 changes: 38 additions & 10 deletions tests/e2e/acquire_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestAcquire(t *testing.T) {

waitForPoolReady(t, r, "pool-with-2-cirs")

cir := c.TryAcquireCIR()
cir := c.TryAcquireCIR("host")
waitForCIRState(t, r, cir, ofcirv1.StateInUse)

return ctx
Expand All @@ -46,11 +46,11 @@ func TestAcquireAllResources(t *testing.T) {

// Try to acquire all the resources offered by the pool
for range cirs.Items {
c.TryAcquireCIR()
c.TryAcquireCIR("host")
}

// Next acquire must fail
_, err := c.Acquire()
_, err := c.Acquire("host")
assert.ErrorContains(t, err, "No available resource found")

return ctx
Expand All @@ -71,13 +71,13 @@ func TestPoolsPriority(t *testing.T) {

waitForsPoolReady(t, r)

cirInfo := c.TryAcquireCIR()
cirInfo := c.TryAcquireCIR("host")
assert.Equal(t, "pool-0", cirInfo.Spec.PoolRef.Name)

cirInfo = c.TryAcquireCIR()
cirInfo = c.TryAcquireCIR("host")
assert.Equal(t, "pool-1", cirInfo.Spec.PoolRef.Name)

cirInfo = c.TryAcquireCIR()
cirInfo = c.TryAcquireCIR("host")
assert.Equal(t, "pool-2", cirInfo.Spec.PoolRef.Name)

// Fallback resources quickly go through several stages before settling down on "in use"
Expand All @@ -100,7 +100,7 @@ func TestPoolsToken(t *testing.T) {
Setup(ofcirSetup("three-pools", "pool-0")).
Assess("blocks when empty token", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
c := NewOfcirClient(t, cfg, "")
_, e := c.Acquire()
_, e := c.Acquire("host")
if assert.Error(t, e) {
assert.Equal(t, fmt.Errorf("%q", "401 Unauthorized"), e)
}
Expand All @@ -113,10 +113,10 @@ func TestPoolsToken(t *testing.T) {

waitForsPoolReady(t, r)

cirInfo := c.TryAcquireCIR()
cirInfo := c.TryAcquireCIR("host")
assert.Equal(t, "pool-0", cirInfo.Spec.PoolRef.Name)

_, e := c.Acquire()
_, e := c.Acquire("host")
if assert.Error(t, e) {
assert.Equal(t, fmt.Errorf("%q", "No available resource found"), e)
}
Expand All @@ -127,6 +127,34 @@ func TestPoolsToken(t *testing.T) {
)
}

func TestPoolsTypes(t *testing.T) {
testenv.Test(t, features.New("resource acquisition by type list").
Setup(ofcirSetup("pools-different-types", "pool-0,pool-1")).
Assess("allows when \"host\" available", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
c := NewOfcirClient(t, cfg, ctx.Value("token").(string))
cirInfo := c.TryAcquireCIR("host")
assert.Equal(t, "pool-0", cirInfo.Spec.PoolRef.Name)
return ctx
}).
Assess("blocks when \"host2\" not specified and \"host\" not available", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
c := NewOfcirClient(t, cfg, ctx.Value("token").(string))
_, e := c.Acquire("host")
if assert.Error(t, e) {
assert.Equal(t, fmt.Errorf("%q", "No available resource found"), e)
}
return ctx
}).
Assess("allows when \"host2\" specified and available", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
c := NewOfcirClient(t, cfg, ctx.Value("token").(string))
cirInfo := c.TryAcquireCIR("host,host2")
assert.Equal(t, "pool-1", cirInfo.Spec.PoolRef.Name)
return ctx
}).
Teardown(ofcirTeardown()).
Feature(),
)
}

func TestAcquireDurationResources(t *testing.T) {
testenv.Test(t, features.New("resource acquisition").
Setup(ofcirSetup("pool-duration", "pool-duration")).
Expand All @@ -136,7 +164,7 @@ func TestAcquireDurationResources(t *testing.T) {

waitForPoolReady(t, r, "pool-duration")

cir := c.TryAcquireCIR()
cir := c.TryAcquireCIR("host")

waitForCIRState(t, r, cir, ofcirv1.StateInUse)
// CIR should be released after 10 seconds (actually a minute due to reconcile loop timing)
Expand Down
10 changes: 5 additions & 5 deletions tests/e2e/client_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ type OfcirAcquire struct {
Type string
}

func (c *OfcirClient) Acquire() (*OfcirAcquire, error) {
destUrl := fmt.Sprintf("%s/v1/ofcir?type=host", c.baseUrl)
func (c *OfcirClient) Acquire(cirtype string) (*OfcirAcquire, error) {
destUrl := fmt.Sprintf("%s/v1/ofcir?type="+cirtype, c.baseUrl)

req, err := http.NewRequest("POST", destUrl, nil)
req.Header.Add("X-Ofcirtoken", c.token)
Expand Down Expand Up @@ -94,13 +94,13 @@ func (c *OfcirClient) Acquire() (*OfcirAcquire, error) {
}

func (c *OfcirClient) TryAcquire() *OfcirAcquire {
acquire, err := c.Acquire()
acquire, err := c.Acquire("host")
assert.NoError(c.t, err)
return acquire
}

func (c *OfcirClient) TryAcquireCIR() *ofcirv1.CIResource {
acquire, err := c.Acquire()
func (c *OfcirClient) TryAcquireCIR(cirtype string) *ofcirv1.CIResource {
acquire, err := c.Acquire(cirtype)
assert.NoError(c.t, err)

var cir ofcirv1.CIResource
Expand Down
25 changes: 25 additions & 0 deletions tests/e2e/testdata/pools-different-types.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: ofcir.openshift/v1
kind: CIPool
metadata:
name: pool-0
namespace: ofcir-system
spec:
provider: fake-provider
priority: 0
size: 1
timeout: '4h'
state: available
type: host
---
apiVersion: ofcir.openshift/v1
kind: CIPool
metadata:
name: pool-1
namespace: ofcir-system
spec:
provider: fake-provider
priority: 1
size: 1
timeout: '4h'
state: available
type: host2

0 comments on commit 660e454

Please sign in to comment.