feature (workers): add repository CreateWorker(...) (#2105)

This commit is contained in:
Jim authored and GitHub committed 2022-05-26 13:32:21 -04:00
1 parent a281d10206
commit 70c5da1048
20 files changed
+343 -54

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
**
!bin/**
!dist/**
!.release/docker/**
+23 -3
View File
@@ -60,10 +60,28 @@ jobs:
project="$(go list -m)"
sha="$(git rev-parse HEAD)"
echo "::set-output name=ldflags::"-s -w -X \'$project/version.GitCommit=$sha\'""
get-product-edition:
runs-on: ubuntu-latest
outputs:
product-edition: ${{ steps.get-product-edition.outputs.product-edition}}
steps:
- uses: actions/checkout@v3
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: "1.18.1"
- name: Get product edition
id: get-product-edition
run: |
make edition
echo "::set-output name=product-edition::$(make edition)"
build-other:
needs:
- get-product-version
- get-product-edition
- set-ld-flags
runs-on: ubuntu-latest
strategy:
@@ -102,7 +120,7 @@ jobs:
workflow: build-admin-ui.yaml
commit: ${{ steps.set-sha.outputs.sha }}
repo: "hashicorp/boundary-ui"
name: admin-ui
name: admin-ui-${{ needs.get-product-edition.outputs.product-edition }}
path: internal/ui/.tmp/boundary-ui/ui/admin/dist
- name: Go Build
env:
@@ -124,6 +142,7 @@ jobs:
build-linux:
needs:
- get-product-version
- get-product-edition
- set-ld-flags
runs-on: ubuntu-latest
strategy:
@@ -157,7 +176,7 @@ jobs:
workflow: build-admin-ui.yaml
commit: ${{ steps.set-sha.outputs.sha }}
repo: "hashicorp/boundary-ui"
name: admin-ui
name: admin-ui-${{ needs.get-product-edition.outputs.product-edition }}
path: internal/ui/.tmp/boundary-ui/ui/admin/dist
- name: Go Build
env:
@@ -209,6 +228,7 @@ jobs:
build-darwin:
needs:
- get-product-version
- get-product-edition
- set-ld-flags
runs-on: macos-latest
strategy:
@@ -239,7 +259,7 @@ jobs:
workflow: build-admin-ui.yaml
commit: ${{ steps.set-sha.outputs.sha }}
repo: "hashicorp/boundary-ui"
name: admin-ui
name: admin-ui-${{ needs.get-product-edition.outputs.product-edition }}
path: internal/ui/.tmp/boundary-ui/ui/admin/dist
- name: Go Build
env:
+4
View File
@@ -6,6 +6,10 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
### Bug Fixes
## 0.8.1 (2022/05/13)
### Bug Fixes
* controller: Do not shut down cluster listener when it receives an invalid
packet ([Issue](https://github.com/hashicorp/boundary/issues/2072),
[PR](https://github.com/hashicorp/boundary/pull/2073))
+10
View File
@@ -327,3 +327,13 @@ ci-verify:
# This is used for release builds by .github/workflows/build.yml
version:
@go run ./cmd/boundary version | awk '/Version Number:/ { print $$3 }'
EDITION?=
.PHONY: edition
# This is used for release builds by .github/workflows/build.yml
edition:
@if [ -z "$(EDITION)" ]; then \
go run ./cmd/boundary version -format=json | jq -r '.version_metadata // "oss"'; \
else \
echo $(EDITION); \
fi; \
+2 -12
View File
@@ -90,7 +90,8 @@ require (
require github.com/hashicorp/go-dbw v0.0.0-20220412153211-c470aec9369f // this is a branch and should be updated before merging
require (
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220512190651-85bdcdd684e6
github.com/DATA-DOG/go-sqlmock v1.5.0
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220515130442-cac0b5ac133b
github.com/hashicorp/nodeenrollment v0.0.0-20220520141833-ad7323153acc
)
@@ -98,7 +99,6 @@ require (
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/AlecAivazis/survey/v2 v2.2.9 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/DATA-DOG/go-sqlmock v1.5.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
@@ -172,7 +172,6 @@ require (
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/sethvargo/go-diceware v0.3.0 // indirect
@@ -195,14 +194,5 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gorm.io/driver/sqlite v1.2.4 // indirect
modernc.org/cc/v3 v3.32.4 // indirect
modernc.org/ccgo/v3 v3.9.2 // indirect
modernc.org/libc v1.9.5 // indirect
modernc.org/mathutil v1.2.2 // indirect
modernc.org/memory v1.0.4 // indirect
modernc.org/opt v0.1.1 // indirect
modernc.org/sqlite v1.10.6 // indirect
modernc.org/strutil v1.1.0 // indirect
modernc.org/token v1.0.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
+2 -16
View File
@@ -377,7 +377,6 @@ github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNE
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM=
github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU=
@@ -678,8 +677,8 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220512190651-85bdcdd684e6 h1:3BknAN8P8326GPQac8e3iM132lwtwkO/3OilBU67S1I=
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220512190651-85bdcdd684e6/go.mod h1:TzFKcCsMKyMwFiMfH2MfO8SXqsFQLxzR7Z8JZiGzpK4=
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220515130442-cac0b5ac133b h1:NmqGrxmUGR1XRhmYA3wsD2BktB9PfbCDIhXd4FM0hbk=
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220515130442-cac0b5ac133b/go.mod h1:puo5dXNWmXx4xoKCzbKSevcFQ4w+z72k3ZF3EVo6zI4=
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2 h1:it114Kjpk79JVh6AfxFMP5oi1gb+RPzcSLiG3zF/J0w=
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2/go.mod h1:b9mq0bG5xJ10ZcTEQJLZ22O9y71hIt2MGTLqROA/SAM=
github.com/hashicorp/go-kms-wrapping/v2 v2.0.6-0.20220512190651-85bdcdd684e6 h1:isD0/0pGWppbxkakRvnX4M4k65+ZSRW0yELW+twLPDk=
@@ -1159,7 +1158,6 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@@ -1967,41 +1965,29 @@ k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAG
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=
modernc.org/cc/v3 v3.32.4 h1:1ScT6MCQRWwvwVdERhGPsPq0f55J1/pFEOCiqM7zc78=
modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
modernc.org/ccgo/v3 v3.9.2 h1:mOLFgduk60HFuPmxSix3AluTEh7zhozkby+e1VDo/ro=
modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo=
modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8=
modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw=
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM=
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.5 h1:zv111ldxmP7DJ5mOIqzRbza7ZDl3kh4ncKfASB2jIYY=
modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY=
modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k=
modernc.org/sqlite v1.10.6 h1:iNDTQbULcm0IJAqrzCm2JcCqxaKRS94rJ5/clBMRmc8=
modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs=
modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc=
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/tcl v1.5.2 h1:sYNjGr4zK6cDH74USl8wVJRrvDX6UOLpG0j4lFvR0W0=
modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48=
+2 -1
View File
@@ -16,7 +16,7 @@ import (
// We expect the database already to be initialized iff initialized is set to true.
// Returns a cleanup function which must be called even if an error is returned and
// an error code where a non-zero value indicates an error happened.
func migrateDatabase(ctx context.Context, ui cli.Ui, dialect, u string, initialized bool) (func(), int) {
func migrateDatabase(ctx context.Context, ui cli.Ui, dialect, u string, initialized bool, maxOpenConns int) (func(), int) {
noop := func() {}
// This database is used to keep an exclusive lock on the database for the
// remainder of the command
@@ -25,6 +25,7 @@ func migrateDatabase(ctx context.Context, ui cli.Ui, dialect, u string, initiali
ui.Error(fmt.Errorf("Error establishing db connection: %w", err).Error())
return noop, 2
}
dBase.SetMaxOpenConns(maxOpenConns)
if err := dBase.PingContext(ctx); err != nil {
ui.Error(fmt.Sprintf("Unable to connect to the database at %q", u))
return noop, 2
+1 -1
View File
@@ -193,7 +193,7 @@ func TestMigrateDatabase(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
u := tc.urlProvider()
ui := cli.NewMockUi()
clean, errCode := migrateDatabase(ctx, ui, dialect, u, tc.initialized)
clean, errCode := migrateDatabase(ctx, ui, dialect, u, tc.initialized, 10)
clean()
assert.EqualValues(t, tc.expectedCode, errCode)
assert.Equal(t, tc.expectedOutput, ui.OutputWriter.String())
+3 -1
View File
@@ -239,6 +239,8 @@ func (c *InitCommand) Run(args []string) (retCode int) {
return base.CommandUserError
}
c.DatabaseMaxOpenConnections = c.Config.Controller.Database.MaxOpenConnections
var migrationUrlToParse string
if c.Config.Controller.Database.MigrationUrl != "" {
migrationUrlToParse = c.Config.Controller.Database.MigrationUrl
@@ -262,7 +264,7 @@ func (c *InitCommand) Run(args []string) (retCode int) {
return base.CommandUserError
}
clean, errCode := migrateDatabase(c.Context, c.UI, dialect, migrationUrl, false)
clean, errCode := migrateDatabase(c.Context, c.UI, dialect, migrationUrl, false, c.DatabaseMaxOpenConnections)
defer clean()
switch errCode {
case 0:
+1 -1
View File
@@ -259,7 +259,7 @@ plugins {
return base.CommandUserError
}
clean, errCode := migrateDatabase(c.Context, c.UI, dialect, migrationUrl, true)
clean, errCode := migrateDatabase(c.Context, c.UI, dialect, migrationUrl, true, c.Config.Controller.Database.MaxOpenConnections)
defer clean()
if errCode != 0 {
return errCode
@@ -75,7 +75,7 @@ func (c *ClientCertificate) SetTableName(n string) {
func (c *ClientCertificate) encrypt(ctx context.Context, cipher wrapping.Wrapper) error {
const op = "vault.(ClientCertificate).encrypt"
if len(c.CertificateKey) == 0 {
errors.New(ctx, errors.InvalidParameter, op, "no certificate key defined")
return errors.New(ctx, errors.InvalidParameter, op, "no certificate key defined")
}
if err := structwrapping.WrapStruct(ctx, cipher, c.ClientCertificate, nil); err != nil {
return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt))
@@ -86,7 +86,7 @@ func (c *ClientCertificate) encrypt(ctx context.Context, cipher wrapping.Wrapper
}
c.KeyId = keyId
if err := c.hmacCertificateKey(ctx, cipher); err != nil {
errors.Wrap(ctx, err, op)
return errors.Wrap(ctx, err, op)
}
return nil
}
@@ -6,6 +6,7 @@ import (
"github.com/hashicorp/boundary/internal/credential/vault/store"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/stretchr/testify/assert"
@@ -49,11 +50,12 @@ func TestClientCertificate_New(t *testing.T) {
}
tests := []struct {
name string
args args
want *ClientCertificate
wantErr bool
wantEncryptErr bool
name string
args args
want *ClientCertificate
wantErr bool
wantEncryptErr bool
wantEncryptErrCode errors.Code
}{
{
name: "missing-certificate",
@@ -64,7 +66,7 @@ func TestClientCertificate_New(t *testing.T) {
wantErr: true,
},
{
name: "valid-missing-key",
name: "missing-key",
args: args{
certificate: []byte(certPem),
},
@@ -73,7 +75,8 @@ func TestClientCertificate_New(t *testing.T) {
Certificate: []byte(certPem),
},
},
wantEncryptErr: true,
wantEncryptErr: true,
wantEncryptErrCode: errors.InvalidParameter,
},
{
name: "valid",
@@ -116,10 +119,12 @@ func TestClientCertificate_New(t *testing.T) {
err = got.encrypt(ctx, databaseWrapper)
if tt.wantEncryptErr {
require.Error(err)
} else {
require.NoError(err)
require.NoError(got.decrypt(ctx, databaseWrapper))
assert.Truef(errors.Match(errors.T(tt.wantEncryptErrCode), err), "%v", err)
return
}
require.NoError(err)
assert.NoError(got.decrypt(ctx, databaseWrapper))
})
}
}
+1 -1
View File
@@ -122,7 +122,7 @@ func (t *Token) encrypt(ctx context.Context, cipher wrapping.Wrapper) error {
}
keyId, err := cipher.KeyId(ctx)
if err != nil {
errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt), errors.WithMsg("error fetching wrapper key id"))
return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt), errors.WithMsg("error fetching wrapper key id"))
}
t.KeyId = keyId
return nil
+19
View File
@@ -9,6 +9,7 @@ import (
"testing"
"time"
"github.com/DATA-DOG/go-sqlmock"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
"github.com/hashicorp/boundary/internal/db/schema"
@@ -20,6 +21,7 @@ import (
aead "github.com/hashicorp/go-kms-wrapping/v2/aead"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
pgDriver "gorm.io/driver/postgres"
)
// setup the tests (initialize the database one-time and intialized
@@ -73,6 +75,23 @@ func TestSetup(t testing.TB, dialect string, opt ...TestOption) (*DB, string) {
return db, url
}
// TestSetupWithMock will return a test DB and an associated Sqlmock which can
// be used to mock out the db responses.
func TestSetupWithMock(t *testing.T) (*DB, sqlmock.Sqlmock) {
t.Helper()
require := require.New(t)
db, mock, err := sqlmock.New()
require.NoError(err)
require.NoError(err)
dbw, err := dbw.OpenWith(pgDriver.New(pgDriver.Config{
Conn: db,
}))
require.NoError(err)
return &DB{
wrapped: dbw,
}, mock
}
// TestWrapper initializes an AEAD wrapping.Wrapper for testing the oplog
func TestWrapper(t testing.TB) wrapping.Wrapper {
t.Helper()
+13 -1
View File
@@ -1,6 +1,7 @@
package servers
import (
"context"
"time"
)
@@ -31,10 +32,13 @@ type options struct {
withControllerEncryptionPrivateKey []byte
withKeyId string
withNonce []byte
withNewIdFunc func(context.Context) (string, error)
}
func getDefaultOptions() options {
return options{}
return options{
withNewIdFunc: newWorkerId,
}
}
// WithDescription provides an optional description.
@@ -128,3 +132,11 @@ func WithNonce(nonce []byte) Option {
o.withNonce = nonce
}
}
// WithNewIdFunc allows an optional factory function for new worker IDs to be
// specified (this option is likely only useful for tests).
func WithNewIdFunc(fn func(context.Context) (string, error)) Option {
return func(o *options) {
o.withNewIdFunc = fn
}
}
+38 -3
View File
@@ -1,6 +1,9 @@
package servers
import (
"context"
"reflect"
"runtime"
"testing"
"time"
@@ -10,49 +13,60 @@ import (
// Test_GetOpts provides unit tests for GetOpts and all the options
func Test_GetOpts(t *testing.T) {
t.Parallel()
opts := getOpts()
assert.Equal(t, options{}, opts)
t.Run("WithName", func(t *testing.T) {
opts := getOpts(WithName("test"))
testOpts := getDefaultOptions()
testOpts.withName = "test"
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(t, opts, testOpts)
})
t.Run("WithDescription", func(t *testing.T) {
opts := getOpts(WithDescription("test desc"))
testOpts := getDefaultOptions()
testOpts.withDescription = "test desc"
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(t, opts, testOpts)
})
t.Run("WithLimit", func(t *testing.T) {
opts := getOpts(WithLimit(5))
testOpts := getDefaultOptions()
testOpts.withLimit = 5
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(t, opts, testOpts)
})
t.Run("WithAddress", func(t *testing.T) {
opts := getOpts(WithAddress("test"))
testOpts := getDefaultOptions()
testOpts.withAddress = "test"
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(t, opts, testOpts)
})
t.Run("WithPublicId", func(t *testing.T) {
opts := getOpts(WithPublicId("test"))
testOpts := getDefaultOptions()
testOpts.withPublicId = "test"
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(t, opts, testOpts)
})
t.Run("WithLiveness", func(t *testing.T) {
opts := getOpts(WithLiveness(time.Hour))
testOpts := getDefaultOptions()
testOpts.withLiveness = time.Hour
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(t, opts, testOpts)
})
t.Run("WithUpdateTags", func(t *testing.T) {
opts := getOpts(WithUpdateTags(true))
testOpts := getDefaultOptions()
testOpts.withUpdateTags = true
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(t, opts, testOpts)
})
t.Run("WithWorkerTags", func(t *testing.T) {
@@ -63,6 +77,8 @@ func Test_GetOpts(t *testing.T) {
opts := getOpts(WithWorkerTags(tags...))
testOpts := getDefaultOptions()
testOpts.withWorkerTags = tags
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(t, opts, testOpts)
})
t.Run("WithWorkerKeys", func(t *testing.T) {
@@ -77,6 +93,8 @@ func Test_GetOpts(t *testing.T) {
opts := getOpts(WithWorkerKeys(keys))
testOpts = getDefaultOptions()
testOpts.withWorkerKeys = keys
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(opts, testOpts)
})
t.Run("WithControllerEncryptionPrivateKey", func(t *testing.T) {
@@ -88,6 +106,8 @@ func Test_GetOpts(t *testing.T) {
opts := getOpts(WithControllerEncryptionPrivateKey(key))
testOpts = getDefaultOptions()
testOpts.withControllerEncryptionPrivateKey = key
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(opts, testOpts)
})
t.Run("WithKeyId", func(t *testing.T) {
@@ -97,6 +117,8 @@ func Test_GetOpts(t *testing.T) {
opts := getOpts(WithKeyId("hi i'm another key id"))
testOpts = getDefaultOptions()
testOpts.withKeyId = "hi i'm another key id"
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(opts, testOpts)
})
t.Run("WithNonce", func(t *testing.T) {
@@ -108,6 +130,19 @@ func Test_GetOpts(t *testing.T) {
opts := getOpts(WithNonce(nonce))
testOpts = getDefaultOptions()
testOpts.withNonce = nonce
opts.withNewIdFunc = nil
testOpts.withNewIdFunc = nil
assert.Equal(opts, testOpts)
})
t.Run("WithNewIdFunc", func(t *testing.T) {
assert := assert.New(t)
testFn := func(context.Context) (string, error) { return "", nil }
opts := getOpts(WithNewIdFunc(testFn))
testOpts := getDefaultOptions()
testOpts.withNewIdFunc = testFn
assert.Equal(
runtime.FuncForPC(reflect.ValueOf(opts.withNewIdFunc).Pointer()).Name(),
runtime.FuncForPC(reflect.ValueOf(testOpts.withNewIdFunc).Pointer()).Name(),
)
})
}
+48
View File
@@ -191,3 +191,51 @@ func setWorkerTags(ctx context.Context, w db.Writer, id string, ts TagSource, ta
return nil
}
// CreateWorker will create a worker in the repository and return the written
// worker. Creating a worker is not intentionally oplogged. A worker's
// ReportedStatus and Tags are intentionally ignored when creating a worker (not
// included). Currently, a worker can only be created in the global scope
//
// Options supported: WithNewIdFunc (this option is likely only useful for tests)
func (r *Repository) CreateWorker(ctx context.Context, worker *Worker, opt ...Option) (*Worker, error) {
const op = "servers.CreateWorker"
switch {
case worker == nil:
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing worker")
case worker.PublicId != "":
return nil, errors.New(ctx, errors.InvalidParameter, op, "public id is not empty")
case worker.ScopeId == "":
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing scope id")
case worker.ScopeId != scope.Global.String():
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("scope id must be %q", scope.Global.String()))
}
opts := getOpts(opt...)
var err error
if worker.PublicId, err = opts.withNewIdFunc(ctx); err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to generate worker id"))
}
var returnedWorker *Worker
_, err = r.writer.DoTx(
ctx,
db.StdRetryCnt,
db.ExpBackoff{},
func(_ db.Reader, w db.Writer) error {
returnedWorker = worker.clone()
err := w.Create(
ctx,
returnedWorker,
)
if err != nil {
return errors.Wrap(ctx, err, op)
}
return nil
},
)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create worker"))
}
return returnedWorker, nil
}
+153
View File
@@ -8,8 +8,11 @@ import (
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/servers"
"github.com/hashicorp/boundary/internal/servers/store"
"github.com/hashicorp/boundary/internal/types/scope"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -315,3 +318,153 @@ func TestListWorkersWithLiveness(t *testing.T) {
require.Len(result, 3)
requireIds([]string{workConf1.WorkerId, workConf2.WorkerId, workConf3.WorkerId}, result)
}
func TestRepository_CreateWorker(t *testing.T) {
t.Parallel()
testCtx := context.Background()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
testRepo, err := servers.NewRepository(rw, rw, kms)
require.NoError(t, err)
iamRepo := iam.TestRepo(t, conn, wrapper)
org, _ := iam.TestScopes(t, iamRepo)
testNewIdFn := func(context.Context) (string, error) {
return "", errors.New(testCtx, errors.Internal, "test", "testNewIdFn-error")
}
tests := []struct {
name string
setup func() *servers.Worker
repo *servers.Repository
opt []servers.Option
wantErr bool
wantErrIs errors.Code
wantErrContains string
}{
{
name: "missing-worker",
setup: func() *servers.Worker {
return nil
},
repo: testRepo,
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErrContains: "missing worker",
},
{
name: "public-id-not-empty",
setup: func() *servers.Worker {
w := servers.NewWorker(scope.Global.String())
var err error
w.PublicId, err = db.NewPublicId(servers.WorkerPrefix)
require.NoError(t, err)
return w
},
repo: testRepo,
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErrContains: "public id is not empty",
},
{
name: "empty-scope-id",
setup: func() *servers.Worker {
w := servers.NewWorker(scope.Global.String())
w.ScopeId = ""
return w
},
repo: testRepo,
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErrContains: "missing scope id",
},
{
name: "org-scope-id",
setup: func() *servers.Worker {
w := servers.NewWorker(org.PublicId)
return w
},
repo: testRepo,
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErrContains: "scope id must be \"global\"",
},
{
name: "new-id-error",
setup: func() *servers.Worker {
w := servers.NewWorker(scope.Global.String())
return w
},
repo: testRepo,
opt: []servers.Option{servers.WithNewIdFunc(testNewIdFn)},
wantErr: true,
wantErrIs: errors.Internal,
wantErrContains: "testNewIdFn-error",
},
{
name: "create-error",
setup: func() *servers.Worker {
w := servers.NewWorker(scope.Global.String())
return w
},
repo: func() *servers.Repository {
conn, mock := db.TestSetupWithMock(t)
writer := db.New(conn)
mock.ExpectBegin()
mock.ExpectQuery(`INSERT`).WillReturnError(errors.New(testCtx, errors.Internal, "test", "create-error"))
mock.ExpectRollback()
r, err := servers.NewRepository(rw, writer, kms)
require.NoError(t, err)
return r
}(),
wantErr: true,
wantErrContains: "unable to create worker",
},
{
name: "success",
setup: func() *servers.Worker {
w := servers.NewWorker(scope.Global.String())
return w
},
repo: testRepo,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
testWorker := tc.setup()
got, err := tc.repo.CreateWorker(testCtx, testWorker, tc.opt...)
if tc.wantErr {
require.Error(err)
assert.Nil(got)
if tc.wantErrIs != errors.Unknown {
assert.True(errors.Match(errors.T(tc.wantErrIs), err))
}
if tc.wantErrContains != "" {
assert.Contains(err.Error(), tc.wantErrContains)
}
return
}
require.NoError(err)
assert.NotNil(got)
assert.NotEmpty(got.PublicId)
assert.NotEmpty(got.UpdateTime)
assert.NotEmpty(got.CreateTime)
found := &servers.Worker{
Worker: &store.Worker{
PublicId: got.PublicId,
},
}
err = rw.LookupByPublicId(testCtx, found)
require.NoError(err)
if found.Tags == nil {
found.Tags = []*servers.Tag{}
}
assert.Equal(got, found)
})
}
}
+1 -1
View File
@@ -179,11 +179,11 @@ func TestList(t *testing.T) {
require.NoError(err)
expected[i] = tcr.Item
}
filterItem := expected[3]
ul, err = tarClient.List(tc.Context(), proj.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(ul.Items))
filterItem := ul.Items[3]
ul, err = tarClient.List(tc.Context(), proj.GetPublicId(),
targets.WithFilter(fmt.Sprintf(`"/item/id"==%q`, filterItem.Id)))
require.NoError(err)
+1 -1
View File
@@ -1,4 +1,4 @@
8545697b430a432bd50c1bde6a080759f803f157 Add toolbar regions to align refresh button to the right (#1098)
698160d423e8fee640d3286c3a3f17434f56a12b
# 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.