Filter WorkerList by feature and go from version string to version.Info (#2807)

This commit is contained in:
Todd authored and GitHub committed 2023-01-19 14:39:49 -08:00
1 parent 0bee55aa19
commit b359561e51
7 files changed
+190 -5

No files matched your search

@@ -276,6 +276,9 @@ func TestAuthorizeConnection(t *testing.T) {
require.NoError(t, kmsCache.CreateKeys(context.Background(), scope.Global.String(), kms.WithRandomReader(rand.Reader)))
currentConnFn := connectionRouteFn
t.Cleanup(func() {
connectionRouteFn = currentConnFn
})
connectionRouteFn = singleHopConnectionRoute
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
@@ -422,7 +425,6 @@ func TestAuthorizeConnection(t *testing.T) {
assert.Empty(t, cmp.Diff(resp, tc.want, protocmp.Transform()))
})
}
connectionRouteFn = currentConnFn
}
func TestCancelSession(t *testing.T) {
+14
View File
@@ -7,6 +7,7 @@ import (
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
"github.com/hashicorp/boundary/internal/server"
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets"
"github.com/hashicorp/boundary/version"
"github.com/hashicorp/go-bexpr"
"github.com/mitchellh/pointerstructure"
"google.golang.org/grpc/codes"
@@ -43,6 +44,19 @@ func (w WorkerList) WorkerInfos() []*pb.WorkerInfo {
return ret
}
// SupportsFeature returns a new WorkerList composed of all workers in this
// WorkerList which supports the provided feature.
func (w WorkerList) SupportsFeature(f version.Feature) WorkerList {
var ret []*server.Worker
for _, worker := range w {
sv := version.FromVersionString(worker.GetReleaseVersion()).Semver()
if version.SupportsFeature(sv, f) {
ret = append(ret, worker)
}
}
return ret
}
// filtered returns a new workerList where all elements contained in it are the
// ones which from the original workerList that pass the evaluator's evaluation.
func (w WorkerList) Filtered(eval *bexpr.Evaluator) (WorkerList, error) {
@@ -625,7 +625,7 @@ func (s Service) RemoveTargetCredentialSources(ctx context.Context, req *pbs.Rem
// If set, use the worker_filter or egress_worker_filter to filtere the selected workers
// and ensure we have workers available to service this request.
func AuthorizeSessionWithWorkerFilter(_ context.Context, t target.Target, selectedWorkers []*server.Worker, _ common.Downstreamers) ([]*server.Worker, error) {
func AuthorizeSessionWithWorkerFilter(_ context.Context, t target.Target, selectedWorkers wl.WorkerList, _ common.Downstreamers) (wl.WorkerList, error) {
if len(selectedWorkers) > 0 {
var eval *bexpr.Evaluator
var err error
@@ -641,7 +641,7 @@ func AuthorizeSessionWithWorkerFilter(_ context.Context, t target.Target, select
return nil, err
}
selectedWorkers, err = wl.WorkerList(selectedWorkers).Filtered(eval)
selectedWorkers, err = selectedWorkers.Filtered(eval)
if err != nil {
return nil, err
}
+3 -2
View File
@@ -109,13 +109,14 @@ session_connection_limit(expiration_time, connection_limit) as (
select
s.expiration_time,
s.connection_limit,
s.egress_worker_filter
s.egress_worker_filter,
s.ingress_worker_filter
from
session s
where
s.public_id = @session_id
)
select expiration_time, connection_limit, egress_worker_filter, current_connection_count
select expiration_time, connection_limit, egress_worker_filter, ingress_worker_filter, current_connection_count
from
session_connection_limit, session_connection_count;
`
+1
View File
@@ -446,6 +446,7 @@ type AuthzSummary struct {
ConnectionLimit int32
CurrentConnectionCount uint32
EgressWorkerFilter string
IngressWorkerFilter string
}
func (r *Repository) sessionAuthzSummary(ctx context.Context, sessionId string) (*AuthzSummary, error) {
+49
View File
@@ -3,6 +3,9 @@ package version
import (
"bytes"
"fmt"
"strings"
gvers "github.com/hashicorp/go-version"
)
const BoundaryPrefix = "Boundary v"
@@ -54,6 +57,52 @@ func (c *Info) VersionNumber() string {
return version
}
// Semver returns a *gvers.Version if the Info is parseable as
// a semantic version. Otherwise it returns nil.
func (c *Info) Semver() *gvers.Version {
if c == nil {
return nil
}
v, err := gvers.NewSemver(c.VersionNumber())
if err != nil {
return nil
}
return v
}
// FromVersionString returns an *Info containing the version, or nil if the
// string was unable to be parsed.
func FromVersionString(s string) *Info {
s = strings.TrimSpace(s)
s = strings.TrimPrefix(s, BoundaryPrefix)
i := Info{}
// Get the revision
startOfRevIdx := strings.LastIndex(s, "(")
endOfRevIdx := strings.LastIndex(s, ")")
if startOfRevIdx > 0 && endOfRevIdx > 0 {
if endOfRevIdx < startOfRevIdx {
return nil
}
i.Revision, s = s[startOfRevIdx+1:endOfRevIdx], strings.TrimSpace(s[:startOfRevIdx])
}
v, err := gvers.NewSemver(s)
if err != nil {
return nil
}
if md := v.Metadata(); len(md) > 0 {
i.VersionMetadata = md
}
if pr := v.Prerelease(); len(pr) > 0 {
i.VersionPrerelease = pr
}
i.Version = v.Core().String()
return &i
}
func (c *Info) FullVersionNumber(rev bool) string {
var versionString bytes.Buffer
+118
View File
@@ -0,0 +1,118 @@
package version
import (
"testing"
gvers "github.com/hashicorp/go-version"
"github.com/stretchr/testify/assert"
)
func TestFromVersionString(t *testing.T) {
cases := []struct {
input string
want *Info
}{
{
input: "Boundary v0.12.0-beta+hcp.int (revision)",
want: &Info{
Revision: "revision",
Version: "0.12.0",
VersionPrerelease: "beta",
VersionMetadata: "hcp.int",
},
},
{
input: "Boundary v0.12.0+hcp.int",
want: &Info{
Version: "0.12.0",
VersionMetadata: "hcp.int",
},
},
{
input: "Boundary v0.12.0",
want: &Info{
Version: "0.12.0",
},
},
{
input: "0.12.0-alpha+hcp.int (revision)",
want: &Info{
Revision: "revision",
Version: "0.12.0",
VersionPrerelease: "alpha",
VersionMetadata: "hcp.int",
},
},
{
input: " 0.12.0-hcp+int ",
want: &Info{
Version: "0.12.0",
VersionPrerelease: "hcp",
VersionMetadata: "int",
},
},
{
input: "0.12.0- spaces in the prerelease are invalid",
want: nil,
},
{
input: "Boundary (version unknown)",
want: nil,
},
{
input: "(version unknown)",
want: nil,
},
}
for _, tc := range cases {
t.Run(tc.input, func(t *testing.T) {
got := FromVersionString(tc.input)
assert.Equal(t, tc.want, got)
})
}
}
func TestSemver(t *testing.T) {
cases := []struct {
name string
toTest *Info
want *gvers.Version
}{
{
name: "0.12.0+hcp.int",
toTest: &Info{
Version: "0.12.0",
VersionMetadata: "hcp.int",
},
want: gvers.Must(gvers.NewSemver("0.12.0+hcp.int")),
},
{
name: "0.12.0+hcp.int (revision)",
toTest: &Info{
Version: "0.12.0",
VersionMetadata: "hcp.int",
Revision: "revision",
},
want: gvers.Must(gvers.NewSemver("0.12.0+hcp.int")),
},
{
name: "unparsable",
toTest: &Info{
Version: "some unparsable string",
VersionMetadata: "hcp.int",
},
want: nil,
},
{
name: "nil info",
toTest: nil,
want: nil,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := tc.toTest.Semver()
assert.Equal(t, tc.want, got)
})
}
}