* Remove the server_id from session table, change it to worker_id on session_connection This is step 1 in updating the worker table. The worker is becoming a public resource so it must have a public id. We drop the server_id column on the session_connection table and add the worker_id column so we can use the wt_public_key type. Since db migrations are applied while the controller is offline, it should be safe to assume all session connections are not in a running state, thus allowing us to null out all the worker ids in the session_connection table. For now we don't have very good enforcement of the wt_public_id constraints, since the id is currently defined in the worker config, but this will soon change and the worker's id will be generated by the controller.
396 lines
9.4 KiB
Go
396 lines
9.4 KiB
Go
package servers
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/hashicorp/boundary/internal/db"
|
|
"github.com/hashicorp/boundary/internal/iam"
|
|
"github.com/hashicorp/boundary/internal/servers/store"
|
|
"github.com/hashicorp/boundary/internal/types/scope"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/protobuf/testing/protocmp"
|
|
)
|
|
|
|
func TestWorkerCanonicalAddress(t *testing.T) {
|
|
worker := NewWorker(scope.Global.String())
|
|
worker.ReportedStatus = NewWorkerStatus("foo", WithAddress("status"))
|
|
assert.Equal(t, "status", worker.CanonicalAddress())
|
|
worker.Address = "worker"
|
|
assert.Equal(t, "worker", worker.CanonicalAddress())
|
|
}
|
|
|
|
func TestWorkerCanonicalTags(t *testing.T) {
|
|
w := NewWorker(scope.Global.String(),
|
|
WithWorkerTags(
|
|
&Tag{Key: "key", Value: "apis unique"},
|
|
&Tag{Key: "key", Value: "shared"},
|
|
&Tag{Key: "key2", Value: "apis key2 unique"},
|
|
))
|
|
w.ReportedStatus = NewWorkerStatus("",
|
|
WithWorkerTags(
|
|
&Tag{Key: "key", Value: "configs unique"},
|
|
&Tag{Key: "key", Value: "shared"},
|
|
&Tag{Key: "key3", Value: "configs key3 unique"},
|
|
))
|
|
|
|
got := w.CanonicalTags()
|
|
assert.Len(t, got, 3, "2 keys expected, 'key' and 'key2'")
|
|
assert.ElementsMatch(t, got["key"], []string{"shared", "apis unique", "configs unique"})
|
|
assert.ElementsMatch(t, got["key2"], []string{"apis key2 unique"})
|
|
assert.ElementsMatch(t, got["key3"], []string{"configs key3 unique"})
|
|
}
|
|
|
|
func TestWorkerAggregate(t *testing.T) {
|
|
t.Parallel()
|
|
conn, _ := db.TestSetup(t, "postgres")
|
|
rw := db.New(conn)
|
|
ctx := context.Background()
|
|
|
|
getAggWorker := func(id string) *Worker {
|
|
agg := &workerAggregate{PublicId: id}
|
|
require.NoError(t, rw.LookupById(ctx, agg))
|
|
got, err := agg.toWorker(ctx)
|
|
assert.NoError(t, err)
|
|
return got
|
|
}
|
|
|
|
// Worker without a status
|
|
{
|
|
id, err := newWorkerId(ctx)
|
|
require.NoError(t, err)
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorker(scope.Global.String(),
|
|
WithPublicId(id),
|
|
WithName(id),
|
|
WithAddress("address"))))
|
|
|
|
got := getAggWorker(id)
|
|
assert.Equal(t, id, got.GetPublicId())
|
|
assert.Equal(t, scope.Global.String(), got.GetScopeId())
|
|
assert.Equal(t, id, got.GetName())
|
|
assert.Equal(t, "address", got.GetAddress())
|
|
assert.Equal(t, uint32(1), got.GetVersion())
|
|
assert.Nil(t, got.ReportedStatus)
|
|
assert.Empty(t, got.CanonicalTags())
|
|
}
|
|
|
|
// Worker with status
|
|
{
|
|
id, err := newWorkerId(ctx)
|
|
require.NoError(t, err)
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorker(scope.Global.String(), WithPublicId(id))))
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorkerStatus(id,
|
|
WithAddress("address"),
|
|
WithName(id))))
|
|
|
|
got := getAggWorker(id)
|
|
assert.Equal(t, id, got.GetPublicId())
|
|
assert.Equal(t, uint32(1), got.GetVersion())
|
|
assert.NotNil(t, got.ReportedStatus)
|
|
assert.Equal(t, id, got.ReportedStatus.GetWorkerId())
|
|
assert.Equal(t, id, got.ReportedStatus.GetName())
|
|
assert.NotNil(t, got.ReportedStatus.CreateTime)
|
|
assert.NotNil(t, got.ReportedStatus.UpdateTime)
|
|
assert.Equal(t, "address", got.ReportedStatus.GetAddress())
|
|
}
|
|
|
|
// Worker with a config tag
|
|
{
|
|
id, err := newWorkerId(ctx)
|
|
require.NoError(t, err)
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorker(scope.Global.String(), WithPublicId(id))))
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorkerStatus(id, WithAddress("address"))))
|
|
require.NoError(t, rw.Create(ctx,
|
|
&store.WorkerTag{
|
|
WorkerId: id,
|
|
Key: "key",
|
|
Value: "val",
|
|
Source: ConfigurationTagSource.String(),
|
|
}))
|
|
|
|
got := getAggWorker(id)
|
|
assert.Equal(t, id, got.GetPublicId())
|
|
assert.Equal(t, uint32(1), got.GetVersion())
|
|
assert.NotNil(t, got.ReportedStatus)
|
|
assert.Empty(t, got.Tags)
|
|
assert.Equal(t, got.ReportedStatus.Tags, []*Tag{{Key: "key", Value: "val"}})
|
|
}
|
|
|
|
// Worker with many config tag
|
|
{
|
|
id, err := newWorkerId(ctx)
|
|
require.NoError(t, err)
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorker(scope.Global.String(), WithPublicId(id))))
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorkerStatus(id, WithAddress("address"))))
|
|
require.NoError(t, rw.Create(ctx, &store.WorkerTag{
|
|
WorkerId: id,
|
|
Key: "key",
|
|
Value: "val",
|
|
Source: ConfigurationTagSource.String(),
|
|
}))
|
|
require.NoError(t, rw.Create(ctx, &store.WorkerTag{
|
|
WorkerId: id,
|
|
Key: "key",
|
|
Value: "val2",
|
|
Source: ConfigurationTagSource.String(),
|
|
}))
|
|
require.NoError(t, rw.Create(ctx, &store.WorkerTag{
|
|
WorkerId: id,
|
|
Key: "key2",
|
|
Value: "val2",
|
|
Source: ConfigurationTagSource.String(),
|
|
}))
|
|
|
|
got := getAggWorker(id)
|
|
require.NotNil(t, got.ReportedStatus)
|
|
assert.Empty(t, got.Tags)
|
|
assert.ElementsMatch(t, got.ReportedStatus.Tags, []*Tag{
|
|
{Key: "key", Value: "val"},
|
|
{Key: "key", Value: "val2"},
|
|
{Key: "key2", Value: "val2"},
|
|
})
|
|
}
|
|
|
|
// Worker with an api tag
|
|
{
|
|
id, err := newWorkerId(ctx)
|
|
require.NoError(t, err)
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorker(scope.Global.String(), WithPublicId(id))))
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorkerStatus(id, WithAddress("address"))))
|
|
require.NoError(t, rw.Create(ctx,
|
|
&store.WorkerTag{
|
|
WorkerId: id,
|
|
Key: "key",
|
|
Value: "val",
|
|
Source: ApiTagSource.String(),
|
|
}))
|
|
|
|
got := getAggWorker(id)
|
|
assert.Equal(t, id, got.GetPublicId())
|
|
assert.Equal(t, uint32(1), got.GetVersion())
|
|
assert.NotNil(t, got.ReportedStatus)
|
|
assert.Empty(t, got.ReportedStatus.Tags)
|
|
assert.Equal(t, got.Tags, []*Tag{{Key: "key", Value: "val"}})
|
|
}
|
|
|
|
// Worker with mix of tag sources
|
|
{
|
|
id, err := newWorkerId(ctx)
|
|
require.NoError(t, err)
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorker(scope.Global.String(), WithPublicId(id))))
|
|
require.NoError(t, rw.Create(ctx,
|
|
NewWorkerStatus(id, WithAddress("address"))))
|
|
require.NoError(t, rw.Create(ctx, &store.WorkerTag{
|
|
WorkerId: id,
|
|
Key: "key",
|
|
Value: "val",
|
|
Source: ConfigurationTagSource.String(),
|
|
}))
|
|
require.NoError(t, rw.Create(ctx, &store.WorkerTag{
|
|
WorkerId: id,
|
|
Key: "key",
|
|
Value: "val2",
|
|
Source: ApiTagSource.String(),
|
|
}))
|
|
require.NoError(t, rw.Create(ctx, &store.WorkerTag{
|
|
WorkerId: id,
|
|
Key: "key2",
|
|
Value: "val2",
|
|
Source: ApiTagSource.String(),
|
|
}))
|
|
|
|
got := getAggWorker(id)
|
|
require.NotNil(t, got.ReportedStatus)
|
|
assert.ElementsMatch(t, got.Tags, []*Tag{
|
|
{Key: "key", Value: "val2"},
|
|
{Key: "key2", Value: "val2"},
|
|
})
|
|
assert.ElementsMatch(t, got.ReportedStatus.Tags, []*Tag{
|
|
{Key: "key", Value: "val"},
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWorker_New(t *testing.T) {
|
|
t.Parallel()
|
|
conn, _ := db.TestSetup(t, "postgres")
|
|
wrapper := db.TestWrapper(t)
|
|
rw := db.New(conn)
|
|
|
|
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
|
|
|
type args struct {
|
|
scopeId string
|
|
opts []Option
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want *Worker
|
|
wantCreateErr bool
|
|
}{
|
|
{
|
|
name: "missing-scope-id",
|
|
args: args{},
|
|
want: &Worker{
|
|
Worker: &store.Worker{},
|
|
},
|
|
wantCreateErr: true,
|
|
},
|
|
{
|
|
name: "global-scope-id",
|
|
args: args{
|
|
scopeId: scope.Global.String(),
|
|
},
|
|
want: &Worker{
|
|
Worker: &store.Worker{
|
|
ScopeId: scope.Global.String(),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "org-scope-id",
|
|
args: args{
|
|
scopeId: org.GetPublicId(),
|
|
},
|
|
want: &Worker{
|
|
Worker: &store.Worker{
|
|
ScopeId: org.GetPublicId(),
|
|
},
|
|
},
|
|
wantCreateErr: true,
|
|
},
|
|
{
|
|
name: "project-scope-id",
|
|
args: args{
|
|
scopeId: prj.GetPublicId(),
|
|
},
|
|
want: &Worker{
|
|
Worker: &store.Worker{
|
|
ScopeId: prj.GetPublicId(),
|
|
},
|
|
},
|
|
wantCreateErr: true,
|
|
},
|
|
{
|
|
name: "with public id",
|
|
args: args{
|
|
scopeId: scope.Global.String(),
|
|
opts: []Option{
|
|
WithPublicId("w_test_public_id"),
|
|
},
|
|
},
|
|
want: &Worker{
|
|
Worker: &store.Worker{
|
|
PublicId: "w_test_public_id",
|
|
ScopeId: scope.Global.String(),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "with name",
|
|
args: args{
|
|
scopeId: scope.Global.String(),
|
|
opts: []Option{
|
|
WithName("foo"),
|
|
},
|
|
},
|
|
want: &Worker{
|
|
Worker: &store.Worker{
|
|
ScopeId: scope.Global.String(),
|
|
Name: "foo",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "with description",
|
|
args: args{
|
|
scopeId: scope.Global.String(),
|
|
opts: []Option{
|
|
WithDescription("foo"),
|
|
},
|
|
},
|
|
want: &Worker{
|
|
Worker: &store.Worker{
|
|
ScopeId: scope.Global.String(),
|
|
Description: "foo",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "with address",
|
|
args: args{
|
|
scopeId: scope.Global.String(),
|
|
opts: []Option{
|
|
WithAddress("foo"),
|
|
},
|
|
},
|
|
want: &Worker{
|
|
Worker: &store.Worker{
|
|
ScopeId: scope.Global.String(),
|
|
Address: "foo",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "with Tags",
|
|
args: args{
|
|
scopeId: scope.Global.String(),
|
|
opts: []Option{
|
|
WithWorkerTags(&Tag{
|
|
Key: "key",
|
|
Value: "val",
|
|
}),
|
|
},
|
|
},
|
|
want: &Worker{
|
|
Worker: &store.Worker{
|
|
ScopeId: scope.Global.String(),
|
|
},
|
|
Tags: []*Tag{
|
|
{
|
|
Key: "key",
|
|
Value: "val",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert := assert.New(t)
|
|
got := NewWorker(tt.args.scopeId, tt.args.opts...)
|
|
assert.Empty(cmp.Diff(tt.want, got.clone(), protocmp.Transform()))
|
|
|
|
id, err := newWorkerId(context.Background())
|
|
assert.NoError(err)
|
|
|
|
tt.want.PublicId = id
|
|
got.PublicId = id
|
|
|
|
err2 := rw.Create(context.Background(), got)
|
|
if tt.wantCreateErr {
|
|
assert.Error(err2)
|
|
} else {
|
|
assert.NoError(err2)
|
|
assert.Equal(uint32(1), got.Version)
|
|
}
|
|
})
|
|
}
|
|
}
|