Merge pull request #2160 from hashicorp/llb-scale-testing
perf(session): Improve list response time Notable changes include: - Change to not include terminated sessions by default. Use the new `include_terminated=true` query parameter to return terminated sessions. - Remove connections from list response. Connection information is still returned for a read of an individual session. - Creates a periodic job that will delete terminated sessions.
This commit is contained in:
28 files changed
+879
-156
No files matched your search
@@ -4,8 +4,21 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
|
||||
|
||||
## Next
|
||||
|
||||
### New and Improved
|
||||
|
||||
* controller: Improve response time for listing sessions.
|
||||
This also creates a new periodic job that will delete terminated
|
||||
sessions after 1 hour.
|
||||
See Deprecations/Changes for some additional details.
|
||||
[PR](https://github.com/hashicorp/boundary/pull/2160).
|
||||
|
||||
### Deprecations/Changes
|
||||
|
||||
* controller: Change the default behavior of the session list endpoint
|
||||
to no longer include sessions in a terminated state and introduces
|
||||
a new query parameter/cli flag to include the terminated sessions.
|
||||
This also removes the connection information from the list response.
|
||||
[PR](https://github.com/hashicorp/boundary/pull/2160).
|
||||
* Anonymous user permissions: In order to reduce the risk of accidental and
|
||||
unintended granting of permissions to anonymous users, the permissions system
|
||||
now only allows certain actions on certain resources to be assigned to the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package sessions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -86,3 +87,15 @@ func WithRecursive(recurse bool) Option {
|
||||
o.withRecursive = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithIncludeTerminated(inIncludeTerminated bool) Option {
|
||||
return func(o *options) {
|
||||
o.queryMap["include_terminated"] = fmt.Sprintf("%v", inIncludeTerminated)
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultIncludeTerminated() Option {
|
||||
return func(o *options) {
|
||||
o.postMap["include_terminated"] = nil
|
||||
}
|
||||
}
|
||||
@@ -701,6 +701,14 @@ var inputStructs = []*structInfo{
|
||||
readTemplate,
|
||||
listTemplate,
|
||||
},
|
||||
extraFields: []fieldInfo{
|
||||
{
|
||||
Name: "IncludeTerminated",
|
||||
ProtoName: "include_terminated",
|
||||
FieldType: "bool",
|
||||
Query: true,
|
||||
},
|
||||
},
|
||||
pluralResourceName: "sessions",
|
||||
createResponseTypes: true,
|
||||
fieldFilter: []string{"private_key"},
|
||||
|
||||
@@ -10,17 +10,48 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
)
|
||||
|
||||
const (
|
||||
flagIncludeTerminated = "include-terminated"
|
||||
)
|
||||
|
||||
func init() {
|
||||
extraActionsFlagsMapFunc = extraActionsFlagsMapFuncImpl
|
||||
extraFlagsFunc = extraFlagsFuncImpl
|
||||
extraFlagsHandlingFunc = extraFlagsHandlingFuncImpl
|
||||
executeExtraActions = executeExtraActionsImpl
|
||||
}
|
||||
|
||||
func extraActionsFlagsMapFuncImpl() map[string][]string {
|
||||
return map[string][]string{
|
||||
"cancel": {"id"},
|
||||
"list": {flagIncludeTerminated},
|
||||
}
|
||||
}
|
||||
|
||||
type extraCmdVars struct {
|
||||
flagIncludeTerminated bool
|
||||
}
|
||||
|
||||
func extraFlagsFuncImpl(c *Command, set *base.FlagSets, f *base.FlagSet) {
|
||||
for _, name := range flagsMap[c.Func] {
|
||||
switch name {
|
||||
case flagIncludeTerminated:
|
||||
f.BoolVar(&base.BoolVar{
|
||||
Name: flagIncludeTerminated,
|
||||
Target: &c.flagIncludeTerminated,
|
||||
Usage: "If set, terminated sessions will be included in the results.",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]sessions.Option) bool {
|
||||
if c.flagIncludeTerminated {
|
||||
*opts = append(*opts, sessions.WithIncludeTerminated(c.flagIncludeTerminated))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
|
||||
@@ -35,6 +35,8 @@ type Command struct {
|
||||
Func string
|
||||
|
||||
plural string
|
||||
|
||||
extraCmdVars
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteArgs() complete.Predictor {
|
||||
|
||||
@@ -408,13 +408,14 @@ var inputStructs = map[string][]*cmdInfo{
|
||||
},
|
||||
"sessions": {
|
||||
{
|
||||
ResourceType: resource.Session.String(),
|
||||
Pkg: "sessions",
|
||||
StdActions: []string{"read", "list"},
|
||||
Container: "Scope",
|
||||
HasExtraHelpFunc: true,
|
||||
HasId: true,
|
||||
VersionedActions: []string{"cancel"},
|
||||
ResourceType: resource.Session.String(),
|
||||
Pkg: "sessions",
|
||||
StdActions: []string{"read", "list"},
|
||||
Container: "Scope",
|
||||
HasExtraCommandVars: true,
|
||||
HasExtraHelpFunc: true,
|
||||
HasId: true,
|
||||
VersionedActions: []string{"cancel"},
|
||||
},
|
||||
},
|
||||
"targets": {
|
||||
|
||||
@@ -353,7 +353,7 @@ func (c *Controller) registerJobs() error {
|
||||
if err := pluginhost.RegisterJobs(c.baseContext, c.scheduler, rw, rw, c.kms, c.conf.HostPlugins); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := session.RegisterJobs(c.baseContext, c.scheduler, rw, c.conf.StatusGracePeriodDuration); err != nil {
|
||||
if err := session.RegisterJobs(c.baseContext, c.scheduler, rw, rw, c.kms, c.conf.StatusGracePeriodDuration); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ func (s Service) ListSessions(ctx context.Context, req *pbs.ListSessionsRequest)
|
||||
RootScopeId: req.GetScopeId(),
|
||||
Type: resource.Session,
|
||||
Recursive: req.GetRecursive(),
|
||||
AuthzProtectedEntityProvider: repo,
|
||||
AuthzProtectedEntityProvider: session.ListForAuthzCheck(repo, session.WithTerminated(req.IncludeTerminated)),
|
||||
ActionSet: IdActions,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -232,6 +232,7 @@ func TestList(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrap := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrap)
|
||||
ctx := context.Background()
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrap)
|
||||
|
||||
@@ -260,16 +261,17 @@ func TestList(t *testing.T) {
|
||||
hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
|
||||
h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0]
|
||||
static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h})
|
||||
tar := tcp.TestTarget(context.Background(), t, conn, pWithSessions.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()}))
|
||||
tar := tcp.TestTarget(ctx, t, conn, pWithSessions.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()}))
|
||||
|
||||
hcOther := static.TestCatalogs(t, conn, pWithOtherSessions.GetPublicId(), 1)[0]
|
||||
hsOther := static.TestSets(t, conn, hcOther.GetPublicId(), 1)[0]
|
||||
hOther := static.TestHosts(t, conn, hcOther.GetPublicId(), 1)[0]
|
||||
static.TestSetMembers(t, conn, hsOther.GetPublicId(), []*static.Host{hOther})
|
||||
tarOther := tcp.TestTarget(context.Background(), t, conn, pWithOtherSessions.GetPublicId(), "test", target.WithHostSources([]string{hsOther.GetPublicId()}))
|
||||
tarOther := tcp.TestTarget(ctx, t, conn, pWithOtherSessions.GetPublicId(), "test", target.WithHostSources([]string{hsOther.GetPublicId()}))
|
||||
|
||||
var wantSession []*pb.Session
|
||||
var totalSession []*pb.Session
|
||||
var wantIncludeTerminatedSessions []*pb.Session
|
||||
for i := 0; i < 10; i++ {
|
||||
sess := session.TestSession(t, conn, wrap, session.ComposedOf{
|
||||
UserId: uId,
|
||||
@@ -281,7 +283,7 @@ func TestList(t *testing.T) {
|
||||
Endpoint: "tcp://127.0.0.1:22",
|
||||
})
|
||||
|
||||
c := session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, "127.0.0.2", 23, "127.0.0.1")
|
||||
session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, "127.0.0.2", 23, "127.0.0.1")
|
||||
|
||||
status, states := convertStates(sess.States)
|
||||
|
||||
@@ -304,17 +306,11 @@ func TestList(t *testing.T) {
|
||||
Certificate: sess.Certificate,
|
||||
Type: tcp.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Connections: []*pb.Connection{
|
||||
{
|
||||
ClientTcpAddress: c.ClientTcpAddress,
|
||||
ClientTcpPort: c.ClientTcpPort,
|
||||
EndpointTcpAddress: c.EndpointTcpAddress,
|
||||
EndpointTcpPort: c.EndpointTcpPort,
|
||||
},
|
||||
},
|
||||
Connections: []*pb.Connection{}, // connections should not be returned for list
|
||||
})
|
||||
|
||||
totalSession = append(totalSession, wantSession[i])
|
||||
wantIncludeTerminatedSessions = append(wantIncludeTerminatedSessions, wantSession[i])
|
||||
|
||||
sess = session.TestSession(t, conn, wrap, session.ComposedOf{
|
||||
UserId: uIdOther,
|
||||
@@ -326,7 +322,7 @@ func TestList(t *testing.T) {
|
||||
Endpoint: "tcp://127.0.0.1:22",
|
||||
})
|
||||
|
||||
c = session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, "127.0.0.2", 23, "127.0.0.1")
|
||||
session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, "127.0.0.2", 23, "127.0.0.1")
|
||||
|
||||
status, states = convertStates(sess.States)
|
||||
|
||||
@@ -349,17 +345,57 @@ func TestList(t *testing.T) {
|
||||
Certificate: sess.Certificate,
|
||||
Type: tcp.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Connections: []*pb.Connection{
|
||||
{
|
||||
ClientTcpAddress: c.ClientTcpAddress,
|
||||
ClientTcpPort: c.ClientTcpPort,
|
||||
EndpointTcpAddress: c.EndpointTcpAddress,
|
||||
EndpointTcpPort: c.EndpointTcpPort,
|
||||
},
|
||||
},
|
||||
Connections: []*pb.Connection{}, // connections should not be returned for list
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
sess := session.TestSession(t, conn, wrap, session.ComposedOf{
|
||||
UserId: uId,
|
||||
HostId: h.GetPublicId(),
|
||||
TargetId: tar.GetPublicId(),
|
||||
HostSetId: hs.GetPublicId(),
|
||||
AuthTokenId: at.GetPublicId(),
|
||||
ScopeId: pWithSessions.GetPublicId(),
|
||||
Endpoint: "tcp://127.0.0.1:22",
|
||||
})
|
||||
|
||||
sess, err := sessRepo.CancelSession(ctx, sess.PublicId, sess.Version)
|
||||
require.NoError(t, err)
|
||||
terminated, err := sessRepo.TerminateCompletedSessions(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, terminated)
|
||||
|
||||
sess, _, err = sessRepo.LookupSession(ctx, sess.PublicId)
|
||||
require.NoError(t, err)
|
||||
status, states := convertStates(sess.States)
|
||||
|
||||
expected := &pb.Session{
|
||||
Id: sess.GetPublicId(),
|
||||
ScopeId: pWithSessions.GetPublicId(),
|
||||
AuthTokenId: at.GetPublicId(),
|
||||
UserId: at.GetIamUserId(),
|
||||
TargetId: sess.TargetId,
|
||||
Endpoint: sess.Endpoint,
|
||||
HostSetId: sess.HostSetId,
|
||||
HostId: sess.HostId,
|
||||
Version: sess.Version,
|
||||
UpdatedTime: sess.UpdateTime.GetTimestamp(),
|
||||
CreatedTime: sess.CreateTime.GetTimestamp(),
|
||||
ExpirationTime: sess.ExpirationTime.GetTimestamp(),
|
||||
Scope: &scopes.ScopeInfo{Id: pWithSessions.GetPublicId(), Type: scope.Project.String(), ParentScopeId: o.GetPublicId()},
|
||||
Status: status,
|
||||
States: states,
|
||||
Certificate: sess.Certificate,
|
||||
TerminationReason: sess.TerminationReason,
|
||||
Type: tcp.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Connections: []*pb.Connection{}, // connections should not be returned for list
|
||||
}
|
||||
|
||||
wantIncludeTerminatedSessions = append(wantIncludeTerminatedSessions, expected)
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pbs.ListSessionsRequest
|
||||
@@ -371,6 +407,11 @@ func TestList(t *testing.T) {
|
||||
req: &pbs.ListSessionsRequest{ScopeId: pWithSessions.GetPublicId()},
|
||||
res: &pbs.ListSessionsResponse{Items: wantSession},
|
||||
},
|
||||
{
|
||||
name: "List Many Include Terminated",
|
||||
req: &pbs.ListSessionsRequest{ScopeId: pWithSessions.GetPublicId(), IncludeTerminated: true},
|
||||
res: &pbs.ListSessionsResponse{Items: wantIncludeTerminatedSessions},
|
||||
},
|
||||
{
|
||||
name: "List No Sessions",
|
||||
req: &pbs.ListSessionsRequest{ScopeId: pNoSessions.GetPublicId()},
|
||||
@@ -423,14 +464,8 @@ func TestList(t *testing.T) {
|
||||
require.Equal(len(tc.res.GetItems()), len(got.GetItems()), "Didn't get expected number of sessions: %v", got.GetItems())
|
||||
for i, wantSess := range tc.res.GetItems() {
|
||||
assert.True(got.GetItems()[i].GetExpirationTime().AsTime().Sub(wantSess.GetExpirationTime().AsTime()) < 10*time.Millisecond)
|
||||
assert.Equal(1, len(wantSess.GetConnections()))
|
||||
assert.Equal(0, len(wantSess.GetConnections())) // no connections on list
|
||||
wantSess.ExpirationTime = got.GetItems()[i].GetExpirationTime()
|
||||
for _, c := range got.GetItems()[i].GetConnections() {
|
||||
assert.Equal("127.0.0.1", c.ClientTcpAddress)
|
||||
assert.Equal(uint32(22), c.ClientTcpPort)
|
||||
assert.Equal("127.0.0.2", c.EndpointTcpAddress)
|
||||
assert.Equal(uint32(23), c.EndpointTcpPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListSessions(%q) got response %q, wanted %q", tc.req, got, tc.res)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
begin;
|
||||
|
||||
-- Replaces the view created in 1/01 to include connections
|
||||
-- Replaced in 31/0_session_list_no_connections
|
||||
drop view session_with_state;
|
||||
create view session_list as
|
||||
select
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
begin;
|
||||
delete from session
|
||||
using session_state
|
||||
where
|
||||
session.public_id = session_state.session_id
|
||||
and
|
||||
session_state.state = 'terminated'
|
||||
and
|
||||
session_state.start_time < wt_sub_seconds_from_now(3600);
|
||||
|
||||
analyze;
|
||||
commit;
|
||||
@@ -0,0 +1,38 @@
|
||||
begin;
|
||||
|
||||
-- Replaces the view created in 2/09_session_list_view
|
||||
drop view session_list;
|
||||
create view session_list as
|
||||
select
|
||||
s.public_id,
|
||||
s.user_id,
|
||||
s.host_id,
|
||||
s.server_id,
|
||||
s.server_type,
|
||||
s.target_id,
|
||||
s.host_set_id,
|
||||
s.auth_token_id,
|
||||
s.scope_id,
|
||||
s.certificate,
|
||||
s.expiration_time,
|
||||
s.connection_limit,
|
||||
s.tofu_token,
|
||||
s.key_id,
|
||||
s.termination_reason,
|
||||
s.version,
|
||||
s.create_time,
|
||||
s.update_time,
|
||||
s.endpoint,
|
||||
s.worker_filter,
|
||||
ss.state,
|
||||
ss.previous_end_time,
|
||||
ss.start_time,
|
||||
ss.end_time
|
||||
from
|
||||
session s
|
||||
join
|
||||
session_state ss
|
||||
on
|
||||
s.public_id = ss.session_id;
|
||||
|
||||
commit;
|
||||
@@ -2523,6 +2523,13 @@
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "include_terminated",
|
||||
"description": "Experimental. By default only non-terminated (i.e. pending, active, canceling) are returned.\nSet this option to include terminated sessions as well.",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
||||
@@ -125,6 +125,9 @@ type ListSessionsRequest struct {
|
||||
ScopeId string `protobuf:"bytes,1,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
Recursive bool `protobuf:"varint,20,opt,name=recursive,proto3" json:"recursive,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
Filter string `protobuf:"bytes,30,opt,name=filter,proto3" json:"filter,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
// Experimental. By default only non-terminated (i.e. pending, active, canceling) are returned.
|
||||
// Set this option to include terminated sessions as well.
|
||||
IncludeTerminated bool `protobuf:"varint,40,opt,name=include_terminated,proto3" json:"include_terminated,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
}
|
||||
|
||||
func (x *ListSessionsRequest) Reset() {
|
||||
@@ -180,6 +183,13 @@ func (x *ListSessionsRequest) GetFilter() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ListSessionsRequest) GetIncludeTerminated() bool {
|
||||
if x != nil {
|
||||
return x.IncludeTerminated
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ListSessionsResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -352,68 +362,72 @@ var file_controller_api_services_v1_session_service_proto_rawDesc = []byte{
|
||||
0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75,
|
||||
0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x66,
|
||||
0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x64,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x14, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
||||
0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x5b, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65,
|
||||
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43,
|
||||
0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
|
||||
0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x96,
|
||||
0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49,
|
||||
0x64, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x14,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12,
|
||||
0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75,
|
||||
0x64, 0x65, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, 0x28, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x65, 0x72,
|
||||
0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x22, 0x5b, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x43, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||
0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x73, 0x22, 0x40, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65,
|
||||
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x5a, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c,
|
||||
0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x41, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x73, 0x22, 0x40, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x5a, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41,
|
||||
0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65,
|
||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x32, 0x95, 0x04, 0x0a, 0x0e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x12, 0xa7, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x3a, 0x92, 0x41, 0x18, 0x12, 0x16, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20,
|
||||
0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x82,
|
||||
0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x9f,
|
||||
0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12,
|
||||
0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
|
||||
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x2c, 0x92, 0x41, 0x15, 0x12, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61,
|
||||
0x6c, 0x6c, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93,
|
||||
0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x12, 0xb6, 0x01, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x32, 0x95, 0x04, 0x0a, 0x0e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa7, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x92, 0x41, 0x14, 0x12, 0x12, 0x43, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x6c, 0x73, 0x20, 0x61, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c,
|
||||
0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
|
||||
0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x3a, 0x92, 0x41, 0x18, 0x12, 0x16, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61,
|
||||
0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12,
|
||||
0x9f, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
|
||||
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
|
||||
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x2c, 0x92, 0x41, 0x15, 0x12, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20,
|
||||
0x61, 0x6c, 0x6c, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x82, 0xd3, 0xe4,
|
||||
0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x12, 0xb6, 0x01, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x92, 0x41, 0x14, 0x12, 0x12, 0x43,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x6c, 0x73, 0x20, 0x61, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x63, 0x61, 0x6e, 0x63, 0x65,
|
||||
0x6c, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
||||
0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -63,6 +63,9 @@ message ListSessionsRequest {
|
||||
string scope_id = 1; // @gotags: `class:"public"`
|
||||
bool recursive = 20 [json_name = "recursive"]; // @gotags: `class:"public"`
|
||||
string filter = 30 [json_name = "filter"]; // @gotags: `class:"public"`
|
||||
// Experimental. By default only non-terminated (i.e. pending, active, canceling) are returned.
|
||||
// Set this option to include terminated sessions as well.
|
||||
bool include_terminated = 40 [json_name = "include_terminated"]; // @gotags: `class:"public"`
|
||||
}
|
||||
|
||||
message ListSessionsResponse {
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/scheduler"
|
||||
)
|
||||
|
||||
type deleteTerminatedJob struct {
|
||||
repo *Repository
|
||||
|
||||
// the amount of time that a session must be in the terminated
|
||||
// state for it to be deleted.
|
||||
threshold time.Duration
|
||||
|
||||
// the number of sessions deleted in the most recent run
|
||||
deletedInRun int
|
||||
}
|
||||
|
||||
func newDeleteTerminatedJob(ctx context.Context, repo *Repository, threshold time.Duration) (*deleteTerminatedJob, error) {
|
||||
const op = "session.newDeleteTerminatedJob"
|
||||
switch {
|
||||
case repo == nil:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing repository")
|
||||
}
|
||||
|
||||
return &deleteTerminatedJob{
|
||||
repo: repo,
|
||||
threshold: threshold,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Status reports the job’s current status. The status is periodically persisted by
|
||||
// the scheduler when a job is running, and will be used to verify a job is making progress.
|
||||
func (d *deleteTerminatedJob) Status() scheduler.JobStatus {
|
||||
return scheduler.JobStatus{
|
||||
Completed: d.deletedInRun,
|
||||
Total: d.deletedInRun,
|
||||
}
|
||||
}
|
||||
|
||||
// Run performs the required work depending on the implementation.
|
||||
// The context is used to notify the job that it should exit early.
|
||||
func (d *deleteTerminatedJob) Run(ctx context.Context) error {
|
||||
const op = "session.(deleteTerminatedJob).Run"
|
||||
d.deletedInRun = 0
|
||||
var err error
|
||||
|
||||
d.deletedInRun, err = d.repo.deleteSessionsTerminatedBefore(ctx, d.threshold)
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NextRunIn returns the duration until the next job run should be scheduled. This
|
||||
// method is invoked after a run has successfully completed and the next run time
|
||||
// is being persisted by the scheduler. If an error is returned, the error will be logged
|
||||
// but the duration returned will still be used in scheduling. If a zero duration is returned
|
||||
// the job will be scheduled to run again immediately.
|
||||
func (d *deleteTerminatedJob) NextRunIn(_ context.Context) (time.Duration, error) {
|
||||
return time.Minute * 30, nil
|
||||
}
|
||||
|
||||
// Name is the unique name of the job.
|
||||
func (d *deleteTerminatedJob) Name() string {
|
||||
return "delete_terminated_sessions"
|
||||
}
|
||||
|
||||
// Description is the human readable description of the job.
|
||||
func (d *deleteTerminatedJob) Description() string {
|
||||
return "Delete terminated sessions that were terminated "
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDeleteTermiantedSessionsJob(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(rw, rw, kms)
|
||||
require.NoError(t, err)
|
||||
composedOf := TestSessionParams(t, conn, wrapper, iamRepo)
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := []struct {
|
||||
sessionCount int
|
||||
terminateCount int
|
||||
threshold time.Duration
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
0,
|
||||
0,
|
||||
time.Nanosecond,
|
||||
0,
|
||||
},
|
||||
{
|
||||
1,
|
||||
1,
|
||||
time.Nanosecond,
|
||||
1,
|
||||
},
|
||||
{
|
||||
1,
|
||||
1,
|
||||
time.Hour,
|
||||
0,
|
||||
},
|
||||
{
|
||||
10,
|
||||
10,
|
||||
time.Nanosecond,
|
||||
10,
|
||||
},
|
||||
{
|
||||
10,
|
||||
4,
|
||||
time.Nanosecond,
|
||||
4,
|
||||
},
|
||||
{
|
||||
10,
|
||||
0,
|
||||
time.Nanosecond,
|
||||
0,
|
||||
},
|
||||
{
|
||||
10,
|
||||
10,
|
||||
time.Hour,
|
||||
0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(fmt.Sprintf("%d_%d_%s", tc.sessionCount, tc.terminateCount, tc.threshold), func(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
sdb, err := conn.SqlDB(ctx)
|
||||
require.NoError(t, err)
|
||||
_, err = sdb.Exec(`delete from session;`)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
for i := 0; i < tc.sessionCount; i++ {
|
||||
s := TestSession(t, conn, wrapper, composedOf)
|
||||
if i < tc.terminateCount {
|
||||
_, err = repo.CancelSession(ctx, s.PublicId, s.Version)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
}
|
||||
c, err := repo.TerminateCompletedSessions(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.terminateCount, c)
|
||||
|
||||
job, err := newDeleteTerminatedJob(ctx, repo, tc.threshold)
|
||||
require.NoError(t, err)
|
||||
err = job.Run(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, job.deletedInRun)
|
||||
})
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -6,12 +6,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/scheduler"
|
||||
)
|
||||
|
||||
// RegisterJobs registers plugin host related jobs with the provided scheduler.
|
||||
func RegisterJobs(ctx context.Context, scheduler *scheduler.Scheduler, w db.Writer, gracePeriod time.Duration) error {
|
||||
const deleteTerminatedThreshold = time.Hour
|
||||
|
||||
// RegisterJobs registers session related jobs with the provided scheduler.
|
||||
func RegisterJobs(ctx context.Context, scheduler *scheduler.Scheduler, w db.Writer, r db.Reader, k *kms.Kms, gracePeriod time.Duration) error {
|
||||
const op = "session.RegisterJobs"
|
||||
|
||||
sessionConnectionCleanupJob, err := newSessionConnectionCleanupJob(w, gracePeriod)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating session cleanup job: %w", err)
|
||||
@@ -20,5 +24,17 @@ func RegisterJobs(ctx context.Context, scheduler *scheduler.Scheduler, w db.Writ
|
||||
return fmt.Errorf("error registering session cleanup job: %w", err)
|
||||
}
|
||||
|
||||
repo, err := NewRepository(r, w, k)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating repository: %w", err)
|
||||
}
|
||||
deleteTerminatedJob, err := newDeleteTerminatedJob(ctx, repo, deleteTerminatedThreshold)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating delete terminated session job: %w", err)
|
||||
}
|
||||
if err = scheduler.RegisterJob(ctx, deleteTerminatedJob); err != nil {
|
||||
return fmt.Errorf("error registering delete terminated session job: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -32,6 +32,7 @@ type options struct {
|
||||
withServerId string
|
||||
withDbOpts []db.Option
|
||||
withWorkerStateDelay time.Duration
|
||||
withTerminated bool
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
@@ -121,3 +122,10 @@ func WithWorkerStateDelay(d time.Duration) Option {
|
||||
o.withWorkerStateDelay = d
|
||||
}
|
||||
}
|
||||
|
||||
// WithTerminated is used to include terminated sessions in a list request.
|
||||
func WithTerminated(withTerminated bool) Option {
|
||||
return func(o *options) {
|
||||
o.withTerminated = withTerminated
|
||||
}
|
||||
}
|
||||
@@ -117,11 +117,20 @@ session_connection_limit(expiration_time, connection_limit) as (
|
||||
select expiration_time, connection_limit, current_connection_count
|
||||
from
|
||||
session_connection_limit, session_connection_count;
|
||||
`
|
||||
nonTerminatedSessionPublicIdList = `
|
||||
select public_id, scope_id, user_id from session
|
||||
where
|
||||
session.termination_reason is null
|
||||
and
|
||||
scope_id = any(@scope_ids)
|
||||
;
|
||||
`
|
||||
|
||||
sessionPublicIdList = `
|
||||
select public_id, scope_id, user_id from session
|
||||
%s
|
||||
where
|
||||
scope_id = any(@scope_ids)
|
||||
;
|
||||
`
|
||||
|
||||
@@ -388,6 +397,17 @@ where
|
||||
and ss.end_time is null
|
||||
%s
|
||||
;
|
||||
`
|
||||
deleteTerminated = `
|
||||
delete from session
|
||||
using session_state
|
||||
where
|
||||
session.public_id = session_state.session_id
|
||||
and
|
||||
session_state.state = 'terminated'
|
||||
and
|
||||
session_state.start_time < wt_sub_seconds_from_now(@threshold_seconds)
|
||||
;
|
||||
`
|
||||
)
|
||||
|
||||
|
||||
@@ -83,8 +83,6 @@ func (r *Repository) convertToSessions(ctx context.Context, sessionList []*sessi
|
||||
return nil, nil
|
||||
}
|
||||
sessions := []*Session{}
|
||||
// deduplication map of connections by connection_id
|
||||
connections := map[string]*Connection{}
|
||||
// deduplication map of states by end_time
|
||||
states := map[*timestamp.Timestamp]*State{}
|
||||
var prevSessionId string
|
||||
@@ -92,10 +90,6 @@ func (r *Repository) convertToSessions(ctx context.Context, sessionList []*sessi
|
||||
for _, sv := range sessionList {
|
||||
if sv.PublicId != prevSessionId {
|
||||
if prevSessionId != "" {
|
||||
for _, c := range connections {
|
||||
workingSession.Connections = append(workingSession.Connections, c)
|
||||
}
|
||||
connections = map[string]*Connection{}
|
||||
for _, s := range states {
|
||||
workingSession.States = append(workingSession.States, s)
|
||||
}
|
||||
@@ -157,22 +151,6 @@ func (r *Repository) convertToSessions(ctx context.Context, sessionList []*sessi
|
||||
}
|
||||
}
|
||||
|
||||
if sv.ConnectionId != "" {
|
||||
if _, ok := connections[sv.ConnectionId]; !ok {
|
||||
connections[sv.ConnectionId] = &Connection{
|
||||
PublicId: sv.ConnectionId,
|
||||
SessionId: sv.PublicId,
|
||||
ClientTcpAddress: sv.ClientTcpAddress,
|
||||
ClientTcpPort: sv.ClientTcpPort,
|
||||
EndpointTcpAddress: sv.EndpointTcpAddress,
|
||||
EndpointTcpPort: sv.EndpointTcpPort,
|
||||
BytesUp: sv.BytesUp,
|
||||
BytesDown: sv.BytesDown,
|
||||
ClosedReason: sv.ClosedReason,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
for _, s := range states {
|
||||
workingSession.States = append(workingSession.States, s)
|
||||
@@ -180,9 +158,6 @@ func (r *Repository) convertToSessions(ctx context.Context, sessionList []*sessi
|
||||
sort.Slice(workingSession.States, func(i, j int) bool {
|
||||
return workingSession.States[i].StartTime.GetTimestamp().AsTime().After(workingSession.States[j].StartTime.GetTimestamp().AsTime())
|
||||
})
|
||||
for _, c := range connections {
|
||||
workingSession.Connections = append(workingSession.Connections, c)
|
||||
}
|
||||
sessions = append(sessions, workingSession)
|
||||
return sessions, nil
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/boundary"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
@@ -206,32 +207,31 @@ func (r *Repository) LookupSession(ctx context.Context, sessionId string, _ ...O
|
||||
return &session, authzSummary, nil
|
||||
}
|
||||
|
||||
// FetchAuthzProtectedEntitiesByScope implements boundary.AuthzProtectedEntityProvider
|
||||
func (r *Repository) FetchAuthzProtectedEntitiesByScope(ctx context.Context, scopeIds []string) (map[string][]boundary.AuthzProtectedEntity, error) {
|
||||
const op = "session.(Repository).FetchAuthzProtectedEntityInfo"
|
||||
// fetchAuthzProtectedSessionsByScope fetches sessions for the given scopes.
|
||||
// Note that the sessions are not fully populated, and only contain the
|
||||
// necessary information to implement the boundary.AuthzProtectedEntity
|
||||
// interface. Supports the WithTerminated option.
|
||||
func (r *Repository) fetchAuthzProtectedSessionsByScope(
|
||||
ctx context.Context, scopeIds []string, opt ...Option,
|
||||
) (map[string][]boundary.AuthzProtectedEntity, error) {
|
||||
const op = "session.(Repository).fetchAuthzProtectedSessionsByScope"
|
||||
|
||||
var where string
|
||||
var args []interface{}
|
||||
opts := getOpts(opt...)
|
||||
|
||||
inClauseCnt := 0
|
||||
|
||||
switch len(scopeIds) {
|
||||
case 0:
|
||||
if len(scopeIds) == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no scopes given")
|
||||
case 1:
|
||||
inClauseCnt += 1
|
||||
where, args = fmt.Sprintf("where scope_id = @%d", inClauseCnt), append(args, sql.Named(fmt.Sprintf("%d", inClauseCnt), scopeIds[0]))
|
||||
default:
|
||||
idsInClause := make([]string, 0, len(scopeIds))
|
||||
for _, id := range scopeIds {
|
||||
inClauseCnt += 1
|
||||
idsInClause, args = append(idsInClause, fmt.Sprintf("@%d", inClauseCnt)), append(args, sql.Named(fmt.Sprintf("%d", inClauseCnt), id))
|
||||
}
|
||||
where = fmt.Sprintf("where scope_id in (%s)", strings.Join(idsInClause, ","))
|
||||
}
|
||||
|
||||
q := sessionPublicIdList
|
||||
query := fmt.Sprintf(q, where)
|
||||
args := []interface{}{
|
||||
sql.Named("scope_ids", "{"+strings.Join(scopeIds, ",")+"}"),
|
||||
}
|
||||
|
||||
var query string
|
||||
if opts.withTerminated {
|
||||
query = sessionPublicIdList
|
||||
} else {
|
||||
query = nonTerminatedSessionPublicIdList
|
||||
}
|
||||
|
||||
rows, err := r.reader.Query(ctx, query, args)
|
||||
if err != nil {
|
||||
@@ -700,6 +700,20 @@ func (r *Repository) checkIfNoLongerActive(ctx context.Context, reportedSessions
|
||||
return notActive, nil
|
||||
}
|
||||
|
||||
func (r *Repository) deleteSessionsTerminatedBefore(ctx context.Context, threshold time.Duration) (int, error) {
|
||||
const op = "session.(Repository).deleteTerminated"
|
||||
|
||||
args := []any{
|
||||
sql.Named("threshold_seconds", threshold.Seconds()),
|
||||
}
|
||||
|
||||
c, err := r.writer.Exec(ctx, deleteTerminated, args)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(ctx, err, op, errors.WithMsg("error deleting terminated sessions"))
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func fetchStates(ctx context.Context, r db.Reader, sessionId string, opt ...db.Option) ([]*State, error) {
|
||||
const op = "session.fetchStates"
|
||||
var states []*State
|
||||
|
||||
@@ -126,7 +126,8 @@ func TestRepository_ListSession(t *testing.T) {
|
||||
require.NoError(err)
|
||||
assert.Equal(tt.wantCnt, len(got))
|
||||
for i := 0; i < len(got); i++ {
|
||||
assert.Equal(tt.withConnections, len(got[i].Connections))
|
||||
// connections should not be returned for list requests
|
||||
assert.Equal(0, len(got[i].Connections))
|
||||
for _, c := range got[i].Connections {
|
||||
assert.Equal("127.0.0.1", c.ClientTcpAddress)
|
||||
assert.Equal(uint32(22), c.ClientTcpPort)
|
||||
@@ -1503,3 +1504,320 @@ func TestRepository_deleteTargetFKey(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_deleteTerminated(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(rw, rw, kms)
|
||||
composedOf := TestSessionParams(t, conn, wrapper, iamRepo)
|
||||
|
||||
cases := []struct {
|
||||
sessionCount int
|
||||
terminateCount int
|
||||
threshold time.Duration
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
0,
|
||||
0,
|
||||
time.Nanosecond,
|
||||
0,
|
||||
},
|
||||
{
|
||||
1,
|
||||
1,
|
||||
time.Nanosecond,
|
||||
1,
|
||||
},
|
||||
{
|
||||
1,
|
||||
1,
|
||||
time.Hour,
|
||||
0,
|
||||
},
|
||||
{
|
||||
10,
|
||||
10,
|
||||
time.Nanosecond,
|
||||
10,
|
||||
},
|
||||
{
|
||||
10,
|
||||
4,
|
||||
time.Nanosecond,
|
||||
4,
|
||||
},
|
||||
{
|
||||
10,
|
||||
0,
|
||||
time.Nanosecond,
|
||||
0,
|
||||
},
|
||||
{
|
||||
10,
|
||||
10,
|
||||
time.Hour,
|
||||
0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(fmt.Sprintf("%d_%d_%s", tc.sessionCount, tc.terminateCount, tc.threshold), func(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
sdb, err := conn.SqlDB(ctx)
|
||||
require.NoError(t, err)
|
||||
_, err = sdb.Exec(`delete from session;`)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
for i := 0; i < tc.sessionCount; i++ {
|
||||
s := TestSession(t, conn, wrapper, composedOf)
|
||||
if i < tc.terminateCount {
|
||||
_, err = repo.CancelSession(ctx, s.PublicId, s.Version)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
}
|
||||
c, err := repo.TerminateCompletedSessions(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.terminateCount, c)
|
||||
|
||||
c, err = repo.deleteSessionsTerminatedBefore(ctx, tc.threshold)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, c)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchAuthzProtectedSessionsByScopes(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
ctx := context.Background()
|
||||
wrapper := db.TestWrapper(t)
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(rw, rw, kms)
|
||||
require.NoError(t, err)
|
||||
composedOf := TestSessionParams(t, conn, wrapper, iamRepo)
|
||||
|
||||
_, pWithOtherSessions := iam.TestScopes(t, iamRepo)
|
||||
|
||||
hcOther := static.TestCatalogs(t, conn, pWithOtherSessions.GetPublicId(), 1)[0]
|
||||
hsOther := static.TestSets(t, conn, hcOther.GetPublicId(), 1)[0]
|
||||
hOther := static.TestHosts(t, conn, hcOther.GetPublicId(), 1)[0]
|
||||
static.TestSetMembers(t, conn, hsOther.GetPublicId(), []*static.Host{hOther})
|
||||
tarOther := tcp.TestTarget(ctx, t, conn, pWithOtherSessions.GetPublicId(), "test", target.WithHostSources([]string{hsOther.GetPublicId()}))
|
||||
|
||||
composedOfOther := ComposedOf{
|
||||
UserId: composedOf.UserId,
|
||||
HostId: hOther.GetPublicId(),
|
||||
TargetId: tarOther.GetPublicId(),
|
||||
HostSetId: hsOther.GetPublicId(),
|
||||
AuthTokenId: composedOf.AuthTokenId,
|
||||
ScopeId: pWithOtherSessions.GetPublicId(),
|
||||
Endpoint: "tcp://127.0.0.1:22",
|
||||
}
|
||||
|
||||
type testCase struct {
|
||||
name string
|
||||
createCnt int
|
||||
terminateCnt int
|
||||
otherCnt int
|
||||
otherTerminateCnt int
|
||||
opts []Option
|
||||
reqScopes []string
|
||||
wantCnt int
|
||||
wantOtherCnt int
|
||||
wantErr bool
|
||||
}
|
||||
|
||||
cases := []testCase{
|
||||
{
|
||||
name: "NonTerminated/none",
|
||||
createCnt: 0,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 0,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "NonTerminated/one",
|
||||
createCnt: 1,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 1,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "NonTerminated/many",
|
||||
createCnt: 5,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 5,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "NonTerminated/many one terminated",
|
||||
createCnt: 5,
|
||||
terminateCnt: 1,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 4,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "NonTerminated/many terminated",
|
||||
createCnt: 5,
|
||||
terminateCnt: 3,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 2,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "NonTerminated/many multiple scopes",
|
||||
createCnt: 5,
|
||||
terminateCnt: 3,
|
||||
reqScopes: []string{composedOf.ScopeId, composedOfOther.ScopeId},
|
||||
wantCnt: 2,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "NonTerminated/many multiple scopes",
|
||||
createCnt: 5,
|
||||
terminateCnt: 3,
|
||||
otherCnt: 3,
|
||||
otherTerminateCnt: 1,
|
||||
reqScopes: []string{composedOf.ScopeId, composedOfOther.ScopeId},
|
||||
wantCnt: 2,
|
||||
wantOtherCnt: 2,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "NonTerminated/no scopes",
|
||||
createCnt: 2,
|
||||
terminateCnt: 1,
|
||||
otherCnt: 2,
|
||||
otherTerminateCnt: 1,
|
||||
reqScopes: []string{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "none",
|
||||
opts: []Option{WithTerminated(true)},
|
||||
createCnt: 0,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 0,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "one",
|
||||
opts: []Option{WithTerminated(true)},
|
||||
createCnt: 1,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 1,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "many",
|
||||
opts: []Option{WithTerminated(true)},
|
||||
createCnt: 5,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 5,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "many one terminated",
|
||||
opts: []Option{WithTerminated(true)},
|
||||
createCnt: 5,
|
||||
terminateCnt: 1,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 5,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "many terminated",
|
||||
opts: []Option{WithTerminated(true)},
|
||||
createCnt: 5,
|
||||
terminateCnt: 3,
|
||||
reqScopes: []string{composedOf.ScopeId},
|
||||
wantCnt: 5,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "many multiple scopes",
|
||||
opts: []Option{WithTerminated(true)},
|
||||
createCnt: 5,
|
||||
terminateCnt: 3,
|
||||
reqScopes: []string{composedOf.ScopeId, composedOfOther.ScopeId},
|
||||
wantCnt: 5,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "many multiple scopes",
|
||||
opts: []Option{WithTerminated(true)},
|
||||
createCnt: 5,
|
||||
terminateCnt: 3,
|
||||
otherCnt: 3,
|
||||
otherTerminateCnt: 1,
|
||||
reqScopes: []string{composedOf.ScopeId, composedOfOther.ScopeId},
|
||||
wantCnt: 5,
|
||||
wantOtherCnt: 3,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "no scopes",
|
||||
opts: []Option{WithTerminated(true)},
|
||||
createCnt: 2,
|
||||
terminateCnt: 1,
|
||||
otherCnt: 2,
|
||||
otherTerminateCnt: 1,
|
||||
reqScopes: []string{},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1")
|
||||
|
||||
testSessions := []*Session{}
|
||||
for i := 0; i < tt.createCnt; i++ {
|
||||
s := TestSession(t, conn, wrapper, composedOf)
|
||||
_ = TestState(t, conn, s.PublicId, StatusActive)
|
||||
testSessions = append(testSessions, s)
|
||||
}
|
||||
for i := 0; i < tt.terminateCnt; i++ {
|
||||
_, err := repo.CancelSession(ctx, testSessions[i].PublicId, testSessions[i].Version)
|
||||
require.NoError(err)
|
||||
}
|
||||
terminated, err := repo.TerminateCompletedSessions(ctx)
|
||||
require.NoError(err)
|
||||
require.Equal(tt.terminateCnt, terminated)
|
||||
|
||||
otherTestSessions := []*Session{}
|
||||
for i := 0; i < tt.otherCnt; i++ {
|
||||
s := TestSession(t, conn, wrapper, composedOfOther)
|
||||
_ = TestState(t, conn, s.PublicId, StatusActive)
|
||||
otherTestSessions = append(otherTestSessions, s)
|
||||
}
|
||||
for i := 0; i < tt.otherTerminateCnt; i++ {
|
||||
_, err := repo.CancelSession(ctx, otherTestSessions[i].PublicId, otherTestSessions[i].Version)
|
||||
require.NoError(err)
|
||||
}
|
||||
terminated, err = repo.TerminateCompletedSessions(ctx)
|
||||
require.NoError(err)
|
||||
require.Equal(tt.otherTerminateCnt, terminated)
|
||||
|
||||
assert.Equal(tt.otherCnt, len(otherTestSessions))
|
||||
|
||||
got, err := repo.fetchAuthzProtectedSessionsByScope(ctx, tt.reqScopes, tt.opts...)
|
||||
if tt.wantErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Equal(tt.wantCnt, len(got[composedOf.ScopeId]))
|
||||
assert.Equal(tt.wantOtherCnt, len(got[composedOfOther.ScopeId]))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/boundary"
|
||||
)
|
||||
|
||||
type listForAuthzCheckFunc func(ctx context.Context, scopeIds []string) (map[string][]boundary.AuthzProtectedEntity, error)
|
||||
|
||||
func (a listForAuthzCheckFunc) FetchAuthzProtectedEntitiesByScope(ctx context.Context, scopeIds []string) (map[string][]boundary.AuthzProtectedEntity, error) {
|
||||
return a(ctx, scopeIds)
|
||||
}
|
||||
|
||||
// ListForAuthzCheck returns a functions that fetches sessions for the given
|
||||
// scopes. Note that the sessions are not fully populated, and only contain the
|
||||
// necessary information to implement the boundary.AuthzProtectedEntity
|
||||
// interface. Supports the WithTerminated option.
|
||||
func ListForAuthzCheck(repo *Repository, opt ...Option) listForAuthzCheckFunc {
|
||||
return func(ctx context.Context, scopeIds []string) (map[string][]boundary.AuthzProtectedEntity, error) {
|
||||
return repo.fetchAuthzProtectedSessionsByScope(ctx, scopeIds, opt...)
|
||||
}
|
||||
}
|
||||
@@ -472,16 +472,6 @@ type sessionListView struct {
|
||||
PreviousEndTime *timestamp.Timestamp `json:"previous_end_time,omitempty" gorm:"default:current_timestamp"`
|
||||
StartTime *timestamp.Timestamp `json:"start_time,omitempty" gorm:"default:current_timestamp;primary_key"`
|
||||
EndTime *timestamp.Timestamp `json:"end_time,omitempty" gorm:"default:current_timestamp"`
|
||||
|
||||
// Connection fields
|
||||
ConnectionId string `json:"connection_id,omitempty" gorm:"default:null"`
|
||||
ClientTcpAddress string `json:"client_tcp_address,omitempty" gorm:"default:null"`
|
||||
ClientTcpPort uint32 `json:"client_tcp_port,omitempty" gorm:"default:null"`
|
||||
EndpointTcpAddress string `json:"endpoint_tcp_address,omitempty" gorm:"default:null"`
|
||||
EndpointTcpPort uint32 `json:"endpoint_tcp_port,omitempty" gorm:"default:null"`
|
||||
BytesUp uint64 `json:"bytes_up,omitempty" gorm:"default:null"`
|
||||
BytesDown uint64 `json:"bytes_down,omitempty" gorm:"default:null"`
|
||||
ClosedReason string `json:"closed_reason,omitempty" gorm:"default:null"`
|
||||
}
|
||||
|
||||
// TableName returns the tablename to override the default gorm table name
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
698160d423e8fee640d3286c3a3f17434f56a12b
|
||||
dc78fe90286d8b24e70dca36b19ce77a5a032dcb
|
||||
# This file determines the version of the UI to embed in the boundary binary.
|
||||
# Update this file by running 'make update-ui-version' from the root of this repo.
|
||||
# Set UI_COMMITISH when running the above target to update to a specific version.
|
||||
Reference in new issue
Block a user