* chore(deps): bump the go group across 13 directories with 59 updates Bumps the go group with 36 updates in the / directory: | Package | From | To | | --- | --- | --- | | [github.com/cenkalti/backoff/v4](https://github.com/cenkalti/backoff) | `4.2.1` | `4.3.0` | | [github.com/creack/pty](https://github.com/creack/pty) | `1.1.21` | `1.1.24` | | [github.com/docker/docker](https://github.com/docker/docker) | `27.1.1+incompatible` | `28.1.1+incompatible` | | [github.com/fatih/color](https://github.com/fatih/color) | `1.17.0` | `1.18.0` | | [github.com/glebarez/sqlite](https://github.com/glebarez/sqlite) | `1.10.0` | `1.11.0` | | [github.com/golang-migrate/migrate/v4](https://github.com/golang-migrate/migrate) | `4.17.0` | `4.18.3` | | [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) | `2.19.1` | `2.26.3` | | [github.com/hashicorp/cap](https://github.com/hashicorp/cap) | `0.5.1-0.20240315182732-faa330bfb8df` | `0.9.0` | | [github.com/hashicorp/eventlogger](https://github.com/hashicorp/eventlogger) | `0.2.9` | `0.2.11` | | [github.com/hashicorp/go-bexpr](https://github.com/hashicorp/go-bexpr) | `0.1.13` | `0.1.14` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.17-0.20240313190905-91d44aa8e360` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/configutil/v2](https://github.com/hashicorp/go-secure-stdlib) | `2.0.11` | `2.0.12` | | [github.com/hashicorp/go-secure-stdlib/listenerutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.1.10` | | [github.com/hashicorp/go-secure-stdlib/password](https://github.com/hashicorp/go-secure-stdlib) | `0.1.3` | `0.1.4` | | [github.com/hashicorp/go-secure-stdlib/pluginutil/v2](https://github.com/hashicorp/go-secure-stdlib) | `2.0.6` | `2.0.8` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/hashicorp/go-version](https://github.com/hashicorp/go-version) | `1.6.0` | `1.7.0` | | [github.com/hashicorp/hcl](https://github.com/hashicorp/hcl) | `1.0.1-vault-5` | `1.0.1-vault-7` | | [github.com/hashicorp/mql](https://github.com/hashicorp/mql) | `0.1.3` | `0.1.5` | | [github.com/hashicorp/vault/api](https://github.com/hashicorp/vault) | `1.12.0` | `1.16.0` | | [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) | `5.6.0` | `5.7.5` | | [github.com/jimlambrt/gldap](https://github.com/jimlambrt/gldap) | `0.1.10` | `0.1.14` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/miekg/dns](https://github.com/miekg/dns) | `1.1.58` | `1.1.66` | | [github.com/oligot/go-mod-upgrade](https://github.com/oligot/go-mod-upgrade) | `0.9.1` | `0.11.0` | | [github.com/ory/dockertest/v3](https://github.com/ory/dockertest) | `3.10.0` | `3.12.0` | | [github.com/pires/go-proxyproto](https://github.com/pires/go-proxyproto) | `0.7.0` | `0.8.1` | | [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) | `1.18.0` | `1.22.0` | | [github.com/zalando/go-keyring](https://github.com/zalando/go-keyring) | `0.2.3` | `0.2.6` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc/cmd/protoc-gen-go-grpc](https://github.com/grpc/grpc-go) | `1.3.0` | `1.5.1` | | [gorm.io/driver/postgres](https://github.com/go-gorm/postgres) | `1.5.9` | `1.5.11` | | [nhooyr.io/websocket](https://github.com/nhooyr/websocket-old) | `1.8.10` | `1.8.17` | | [golang.org/x/time](https://github.com/golang/time) | `0.5.0` | `0.11.0` | | [github.com/hashicorp/go-kms-wrapping/plugin/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.7` | `2.0.8` | Bumps the go group with 10 updates in the /api directory: | Package | From | To | | --- | --- | --- | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/google/go-cmp](https://github.com/google/go-cmp) | `0.6.0` | `0.7.0` | | [github.com/hashicorp/eventlogger](https://github.com/hashicorp/eventlogger) | `0.2.6-0.20231025104552-802587e608f0` | `0.2.11` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.61.0` | `1.72.1` | | [nhooyr.io/websocket](https://github.com/nhooyr/websocket-old) | `1.8.10` | `1.8.17` | | [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary) | `0.0.48` | `0.0.52` | | [golang.org/x/time](https://github.com/golang/time) | `0.3.0` | `0.11.0` | Bumps the go group with 9 updates in the /plugins/boundary/mains/aws directory: | Package | From | To | | --- | --- | --- | | [github.com/hashicorp/eventlogger](https://github.com/hashicorp/eventlogger) | `0.2.10` | `0.2.11` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/pluginutil/v2](https://github.com/hashicorp/go-secure-stdlib) | `2.0.7` | `2.0.8` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.68.0` | `1.72.1` | | [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary) | `0.0.51` | `0.0.52` | Bumps the go group with 13 updates in the /plugins/boundary/mains/azure directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.16.0` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/hashicorp/eventlogger](https://github.com/hashicorp/eventlogger) | `0.2.6-0.20231025104552-802587e608f0` | `0.2.11` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/parseutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.2.0` | | [github.com/hashicorp/go-secure-stdlib/pluginutil/v2](https://github.com/hashicorp/go-secure-stdlib) | `2.0.6` | `2.0.8` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/hashicorp/go-version](https://github.com/hashicorp/go-version) | `1.3.0` | `1.7.0` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.59.0` | `1.72.1` | | [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary) | `0.0.39` | `0.0.52` | Bumps the go group with 14 updates in the /plugins/boundary/mains/gcp directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.15.0` | `1.18.0` | | [github.com/hashicorp/eventlogger](https://github.com/hashicorp/eventlogger) | `0.2.9` | `0.2.11` | | [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) | `1.5.0` | `1.6.3` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/parseutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.2.0` | | [github.com/hashicorp/go-secure-stdlib/pluginutil/v2](https://github.com/hashicorp/go-secure-stdlib) | `2.0.6` | `2.0.8` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.9.0` | `1.10.0` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.66.0` | `1.72.1` | | [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary) | `0.0.47` | `0.0.52` | | [golang.org/x/time](https://github.com/golang/time) | `0.6.0` | `0.11.0` | Bumps the go group with 13 updates in the /plugins/boundary/mains/minio directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.15.0` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/hashicorp/eventlogger](https://github.com/hashicorp/eventlogger) | `0.2.6-0.20231025104552-802587e608f0` | `0.2.11` | | [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) | `1.5.0` | `1.6.3` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/pluginutil/v2](https://github.com/hashicorp/go-secure-stdlib) | `2.0.6` | `2.0.8` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.9.0` | `1.10.0` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.61.0` | `1.72.1` | | [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary) | `0.0.51` | `0.0.52` | Bumps the go group with 12 updates in the /plugins/kms/mains/alicloudkms directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.14.1` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) | `1.5.0` | `1.6.3` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/parseutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.2.0` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.8.4` | `1.10.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.59.0` | `1.72.1` | | [github.com/hashicorp/go-kms-wrapping/plugin/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.7` | `2.0.8` | | [github.com/hashicorp/go-kms-wrapping/wrappers/alicloudkms/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.3` | `2.0.4` | Bumps the go group with 12 updates in the /plugins/kms/mains/awskms directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.14.1` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) | `1.5.0` | `1.6.3` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/parseutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.2.0` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.8.4` | `1.10.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.59.0` | `1.72.1` | | [github.com/hashicorp/go-kms-wrapping/plugin/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.7` | `2.0.8` | | [github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.10` | `2.0.11` | Bumps the go group with 13 updates in the /plugins/kms/mains/azurekeyvault directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.15.0` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) | `1.5.0` | `1.6.3` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/parseutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.2.0` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.9.0` | `1.10.0` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.59.0` | `1.72.1` | | [github.com/hashicorp/go-kms-wrapping/plugin/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.7` | `2.0.8` | | [github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.11` | `2.0.14` | Bumps the go group with 13 updates in the /plugins/kms/mains/gcpckms directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.14.1` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) | `1.5.0` | `1.6.3` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/parseutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.2.0` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.8.4` | `1.10.0` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.59.0` | `1.72.1` | | [github.com/hashicorp/go-kms-wrapping/plugin/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.7` | `2.0.8` | | [github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.12` | `2.0.13` | Bumps the go group with 12 updates in the /plugins/kms/mains/ocikms directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.14.1` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) | `1.5.0` | `1.6.3` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/parseutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.2.0` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.8.4` | `1.10.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.59.0` | `1.72.1` | | [github.com/hashicorp/go-kms-wrapping/plugin/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.7` | `2.0.8` | | [github.com/hashicorp/go-kms-wrapping/wrappers/ocikms/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.8` | `2.0.9` | Bumps the go group with 13 updates in the /plugins/kms/mains/transit directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.16.0` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-sockaddr](https://github.com/hashicorp/go-sockaddr) | `1.0.6` | `1.0.7` | | [github.com/hashicorp/vault/api](https://github.com/hashicorp/vault) | `1.10.0` | `1.16.0` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.8.4` | `1.10.0` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.59.0` | `1.72.1` | | [golang.org/x/time](https://github.com/golang/time) | `0.3.0` | `0.11.0` | | [github.com/hashicorp/go-kms-wrapping/plugin/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.7` | `2.0.8` | | [github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.12` | `2.0.13` | Bumps the go group with 14 updates in the /sdk directory: | Package | From | To | | --- | --- | --- | | [github.com/fatih/color](https://github.com/fatih/color) | `1.15.0` | `1.18.0` | | [github.com/golang/protobuf](https://github.com/golang/protobuf) | `1.5.3` | `1.5.4` | | [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) | `2.19.1` | `2.26.3` | | [github.com/hashicorp/eventlogger](https://github.com/hashicorp/eventlogger) | `0.2.6-0.20231025104552-802587e608f0` | `0.2.11` | | [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) | `1.5.0` | `1.6.3` | | [github.com/hashicorp/go-kms-wrapping/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.16` | `2.0.18` | | [github.com/hashicorp/go-secure-stdlib/configutil/v2](https://github.com/hashicorp/go-secure-stdlib) | `2.0.11` | `2.0.12` | | [github.com/hashicorp/go-secure-stdlib/listenerutil](https://github.com/hashicorp/go-secure-stdlib) | `0.1.9` | `0.1.10` | | [github.com/hashicorp/go-secure-stdlib/pluginutil/v2](https://github.com/hashicorp/go-secure-stdlib) | `2.0.6` | `2.0.8` | | [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable) | `0.1.13` | `0.1.14` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.37.0` | `0.38.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.39.0` | `0.40.0` | | [nhooyr.io/websocket](https://github.com/nhooyr/websocket-old) | `1.8.10` | `1.8.17` | | [github.com/hashicorp/go-kms-wrapping/plugin/v2](https://github.com/hashicorp/go-kms-wrapping) | `2.0.7` | `2.0.8` | Updates `github.com/cenkalti/backoff/v4` from 4.2.1 to 4.3.0 - [Changelog](https://github.com/cenkalti/backoff/blob/v5/CHANGELOG.md) - [Commits](https://github.com/cenkalti/backoff/compare/v4.2.1...v4.3.0) Updates `github.com/creack/pty` from 1.1.21 to 1.1.24 - [Release notes](https://github.com/creack/pty/releases) - [Commits](https://github.com/creack/pty/compare/v1.1.21...v1.1.24) Updates `github.com/docker/docker` from 27.1.1+incompatible to 28.1.1+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.1.1...v28.1.1) Updates `github.com/fatih/color` from 1.17.0 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/glebarez/sqlite` from 1.10.0 to 1.11.0 - [Release notes](https://github.com/glebarez/sqlite/releases) - [Commits](https://github.com/glebarez/sqlite/compare/v1.10.0...v1.11.0) Updates `github.com/golang-migrate/migrate/v4` from 4.17.0 to 4.18.3 - [Release notes](https://github.com/golang-migrate/migrate/releases) - [Changelog](https://github.com/golang-migrate/migrate/blob/master/.goreleaser.yml) - [Commits](https://github.com/golang-migrate/migrate/compare/v4.17.0...v4.18.3) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/google/go-cmp` from 0.6.0 to 0.7.0 - [Release notes](https://github.com/google/go-cmp/releases) - [Commits](https://github.com/google/go-cmp/compare/v0.6.0...v0.7.0) Updates `github.com/grpc-ecosystem/grpc-gateway/v2` from 2.19.1 to 2.26.3 - [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases) - [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml) - [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.19.1...v2.26.3) Updates `github.com/hashicorp/cap` from 0.5.1-0.20240315182732-faa330bfb8df to 0.9.0 - [Release notes](https://github.com/hashicorp/cap/releases) - [Changelog](https://github.com/hashicorp/cap/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/cap/commits/v0.9.0) Updates `github.com/hashicorp/eventlogger` from 0.2.9 to 0.2.11 - [Commits](https://github.com/hashicorp/eventlogger/compare/v0.2.9...v0.2.11) Updates `github.com/hashicorp/go-bexpr` from 0.1.13 to 0.1.14 - [Release notes](https://github.com/hashicorp/go-bexpr/releases) - [Commits](https://github.com/hashicorp/go-bexpr/compare/v0.1.13...v0.1.14) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.17-0.20240313190905-91d44aa8e360 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/configutil/v2` from 2.0.11 to 2.0.12 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/configutil/v2.0.11...configutil/v2.0.12) Updates `github.com/hashicorp/go-secure-stdlib/listenerutil` from 0.1.9 to 0.1.10 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...listenerutil/v0.1.10) Updates `github.com/hashicorp/go-secure-stdlib/password` from 0.1.3 to 0.1.4 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/mlock/v0.1.3...awsutil/v0.1.4) Updates `github.com/hashicorp/go-secure-stdlib/pluginutil/v2` from 2.0.6 to 2.0.8 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/configutil/v2.0.6...configutil/v2.0.8) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/hashicorp/go-version` from 1.6.0 to 1.7.0 - [Release notes](https://github.com/hashicorp/go-version/releases) - [Changelog](https://github.com/hashicorp/go-version/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/go-version/compare/v1.6.0...v1.7.0) Updates `github.com/hashicorp/hcl` from 1.0.1-vault-5 to 1.0.1-vault-7 - [Release notes](https://github.com/hashicorp/hcl/releases) - [Changelog](https://github.com/hashicorp/hcl/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/hcl/compare/v1.0.1-vault-5...v1.0.1-vault-7) Updates `github.com/hashicorp/mql` from 0.1.3 to 0.1.5 - [Release notes](https://github.com/hashicorp/mql/releases) - [Changelog](https://github.com/hashicorp/mql/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/mql/compare/v0.1.3...v0.1.5) Updates `github.com/hashicorp/vault/api` from 1.12.0 to 1.16.0 - [Release notes](https://github.com/hashicorp/vault/releases) - [Changelog](https://github.com/hashicorp/vault/blob/main/CHANGELOG-v1.10-v1.15.md) - [Commits](https://github.com/hashicorp/vault/compare/v1.12.0...v1.16.0) Updates `github.com/jackc/pgx/v5` from 5.6.0 to 5.7.5 - [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md) - [Commits](https://github.com/jackc/pgx/compare/v5.6.0...v5.7.5) Updates `github.com/jimlambrt/gldap` from 0.1.10 to 0.1.14 - [Release notes](https://github.com/jimlambrt/gldap/releases) - [Commits](https://github.com/jimlambrt/gldap/compare/v0.1.10...v0.1.14) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/miekg/dns` from 1.1.58 to 1.1.66 - [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release) - [Commits](https://github.com/miekg/dns/compare/v1.1.58...v1.1.66) Updates `github.com/oligot/go-mod-upgrade` from 0.9.1 to 0.11.0 - [Release notes](https://github.com/oligot/go-mod-upgrade/releases) - [Changelog](https://github.com/oligot/go-mod-upgrade/blob/main/.goreleaser.yml) - [Commits](https://github.com/oligot/go-mod-upgrade/compare/v0.9.1...v0.11.0) Updates `github.com/ory/dockertest/v3` from 3.10.0 to 3.12.0 - [Release notes](https://github.com/ory/dockertest/releases) - [Commits](https://github.com/ory/dockertest/compare/v3.10.0...v3.12.0) Updates `github.com/pires/go-proxyproto` from 0.7.0 to 0.8.1 - [Release notes](https://github.com/pires/go-proxyproto/releases) - [Commits](https://github.com/pires/go-proxyproto/compare/v0.7.0...v0.8.1) Updates `github.com/prometheus/client_golang` from 1.18.0 to 1.22.0 - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.18.0...v1.22.0) Updates `github.com/zalando/go-keyring` from 0.2.3 to 0.2.6 - [Release notes](https://github.com/zalando/go-keyring/releases) - [Commits](https://github.com/zalando/go-keyring/compare/v0.2.3...v0.2.6) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/exp` from 0.0.0-20240205201215-2c58cdc269a3 to 0.0.0-20250408133849-7e4ce0ab07d0 - [Commits](https://github.com/golang/exp/commits) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sync` from 0.13.0 to 0.14.0 - [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/term` from 0.31.0 to 0.32.0 - [Commits](https://github.com/golang/term/compare/v0.31.0...v0.32.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `golang.org/x/tools` from 0.21.1-0.20240508182429-e35e4ccd0d2d to 0.32.0 - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/commits/v0.32.0) Updates `google.golang.org/genproto` from 0.0.0-20240205150955-31a09d347014 to 0.0.0-20240213162025-012b6fc9bca9 - [Commits](https://github.com/googleapis/go-genproto/commits) Updates `google.golang.org/genproto/googleapis/api` from 0.0.0-20240205150955-31a09d347014 to 0.0.0-20250303144028-a0af3efb3deb - [Commits](https://github.com/googleapis/go-genproto/commits) Updates `google.golang.org/grpc` from 1.61.1 to 1.70.0 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/grpc/cmd/protoc-gen-go-grpc` from 1.3.0 to 1.5.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.3.0...v1.5.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `gorm.io/driver/postgres` from 1.5.9 to 1.5.11 - [Commits](https://github.com/go-gorm/postgres/compare/v1.5.9...v1.5.11) Updates `mvdan.cc/gofumpt` from 0.5.0 to 0.8.0 - [Release notes](https://github.com/mvdan/gofumpt/releases) - [Changelog](https://github.com/mvdan/gofumpt/blob/master/CHANGELOG.md) - [Commits](https://github.com/mvdan/gofumpt/compare/v0.5.0...v0.8.0) Updates `nhooyr.io/websocket` from 1.8.10 to 1.8.17 - [Release notes](https://github.com/nhooyr/websocket-old/releases) - [Commits](https://github.com/nhooyr/websocket-old/commits/v1.8.17) Updates `golang.org/x/time` from 0.5.0 to 0.11.0 - [Commits](https://github.com/golang/time/compare/v0.5.0...v0.11.0) Updates `github.com/hashicorp/go-kms-wrapping/plugin/v2` from 2.0.7 to 2.0.8 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.7...v2.0.8) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/google/go-cmp` from 0.6.0 to 0.7.0 - [Release notes](https://github.com/google/go-cmp/releases) - [Commits](https://github.com/google/go-cmp/compare/v0.6.0...v0.7.0) Updates `github.com/hashicorp/eventlogger` from 0.2.6-0.20231025104552-802587e608f0 to 0.2.11 - [Commits](https://github.com/hashicorp/eventlogger/compare/v0.2.9...v0.2.11) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.8 to 0.1.9 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-sockaddr` from 1.0.5 to 1.0.6 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/stretchr/testify` from 1.8.4 to 1.9.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `google.golang.org/grpc` from 1.61.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `nhooyr.io/websocket` from 1.8.10 to 1.8.17 - [Release notes](https://github.com/nhooyr/websocket-old/releases) - [Commits](https://github.com/nhooyr/websocket-old/commits/v1.8.17) Updates `github.com/hashicorp/boundary/sdk` from 0.0.48 to 0.0.52 - [Release notes](https://github.com/hashicorp/boundary/releases) - [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.48...api/v0.0.52) Updates `golang.org/x/time` from 0.3.0 to 0.11.0 - [Commits](https://github.com/golang/time/compare/v0.5.0...v0.11.0) Updates `github.com/hashicorp/eventlogger` from 0.2.10 to 0.2.11 - [Commits](https://github.com/hashicorp/eventlogger/compare/v0.2.9...v0.2.11) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/pluginutil/v2` from 2.0.7 to 2.0.8 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/configutil/v2.0.6...configutil/v2.0.8) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.68.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/boundary/sdk` from 0.0.51 to 0.0.52 - [Release notes](https://github.com/hashicorp/boundary/releases) - [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.48...api/v0.0.52) Updates `github.com/fatih/color` from 1.16.0 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/hashicorp/eventlogger` from 0.2.6-0.20231025104552-802587e608f0 to 0.2.11 - [Commits](https://github.com/hashicorp/eventlogger/compare/v0.2.9...v0.2.11) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.9 to 0.2.0 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-secure-stdlib/pluginutil/v2` from 2.0.6 to 2.0.8 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/configutil/v2.0.6...configutil/v2.0.8) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/hashicorp/go-version` from 1.3.0 to 1.7.0 - [Release notes](https://github.com/hashicorp/go-version/releases) - [Changelog](https://github.com/hashicorp/go-version/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/go-version/compare/v1.6.0...v1.7.0) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.8.4 to 1.9.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sync` from 0.13.0 to 0.14.0 - [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.59.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/boundary/sdk` from 0.0.39 to 0.0.52 - [Release notes](https://github.com/hashicorp/boundary/releases) - [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.48...api/v0.0.52) Updates `github.com/fatih/color` from 1.15.0 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/hashicorp/eventlogger` from 0.2.9 to 0.2.11 - [Commits](https://github.com/hashicorp/eventlogger/compare/v0.2.9...v0.2.11) Updates `github.com/hashicorp/go-hclog` from 1.5.0 to 1.6.3 - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.5.0...v1.6.3) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.9 to 0.2.0 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-secure-stdlib/pluginutil/v2` from 2.0.6 to 2.0.8 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/configutil/v2.0.6...configutil/v2.0.8) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.9.0 to 1.10.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sync` from 0.13.0 to 0.14.0 - [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.66.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/boundary/sdk` from 0.0.47 to 0.0.52 - [Release notes](https://github.com/hashicorp/boundary/releases) - [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.48...api/v0.0.52) Updates `golang.org/x/time` from 0.6.0 to 0.11.0 - [Commits](https://github.com/golang/time/compare/v0.5.0...v0.11.0) Updates `github.com/fatih/color` from 1.15.0 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/hashicorp/eventlogger` from 0.2.6-0.20231025104552-802587e608f0 to 0.2.11 - [Commits](https://github.com/hashicorp/eventlogger/compare/v0.2.9...v0.2.11) Updates `github.com/hashicorp/go-hclog` from 1.5.0 to 1.6.3 - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.5.0...v1.6.3) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/pluginutil/v2` from 2.0.6 to 2.0.8 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/configutil/v2.0.6...configutil/v2.0.8) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.9.0 to 1.10.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.61.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/boundary/sdk` from 0.0.51 to 0.0.52 - [Release notes](https://github.com/hashicorp/boundary/releases) - [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.48...api/v0.0.52) Updates `github.com/fatih/color` from 1.14.1 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/hashicorp/go-hclog` from 1.5.0 to 1.6.3 - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.5.0...v1.6.3) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.9 to 0.2.0 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.8.4 to 1.10.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.59.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/go-kms-wrapping/plugin/v2` from 2.0.7 to 2.0.8 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.7...v2.0.8) Updates `github.com/hashicorp/go-kms-wrapping/wrappers/alicloudkms/v2` from 2.0.3 to 2.0.4 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.3...v2.0.4) Updates `github.com/fatih/color` from 1.14.1 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/hashicorp/go-hclog` from 1.5.0 to 1.6.3 - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.5.0...v1.6.3) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.9 to 0.2.0 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.8.4 to 1.10.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.59.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/go-kms-wrapping/plugin/v2` from 2.0.7 to 2.0.8 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.7...v2.0.8) Updates `github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2` from 2.0.10 to 2.0.11 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.10...v2.0.11) Updates `github.com/fatih/color` from 1.15.0 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/hashicorp/go-hclog` from 1.5.0 to 1.6.3 - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.5.0...v1.6.3) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.9 to 0.2.0 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.9.0 to 1.10.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.59.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/go-kms-wrapping/plugin/v2` from 2.0.7 to 2.0.8 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.7...v2.0.8) Updates `github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2` from 2.0.11 to 2.0.14 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.11...v2.0.14) Updates `github.com/fatih/color` from 1.14.1 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/hashicorp/go-hclog` from 1.5.0 to 1.6.3 - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.5.0...v1.6.3) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.9 to 0.2.0 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.8.4 to 1.10.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sync` from 0.13.0 to 0.14.0 - [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.59.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/go-kms-wrapping/plugin/v2` from 2.0.7 to 2.0.8 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.7...v2.0.8) Updates `github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2` from 2.0.12 to 2.0.13 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.12...v2.0.13) Updates `github.com/fatih/color` from 1.14.1 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/hashicorp/go-hclog` from 1.5.0 to 1.6.3 - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.5.0...v1.6.3) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.9 to 0.2.0 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.8.4 to 1.10.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.59.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `github.com/hashicorp/go-kms-wrapping/plugin/v2` from 2.0.7 to 2.0.8 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.7...v2.0.8) Updates `github.com/hashicorp/go-kms-wrapping/wrappers/ocikms/v2` from 2.0.8 to 2.0.9 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.8...v2.0.9) Updates `github.com/fatih/color` from 1.16.0 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.7 to 0.1.9 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-sockaddr` from 1.0.6 to 1.0.7 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/hashicorp/vault/api` from 1.10.0 to 1.16.0 - [Release notes](https://github.com/hashicorp/vault/releases) - [Changelog](https://github.com/hashicorp/vault/blob/main/CHANGELOG-v1.10-v1.15.md) - [Commits](https://github.com/hashicorp/vault/compare/v1.12.0...v1.16.0) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.8.4 to 1.10.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/grpc` from 1.59.0 to 1.72.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `golang.org/x/time` from 0.3.0 to 0.11.0 - [Commits](https://github.com/golang/time/compare/v0.5.0...v0.11.0) Updates `github.com/hashicorp/go-kms-wrapping/plugin/v2` from 2.0.7 to 2.0.8 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.7...v2.0.8) Updates `github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2` from 2.0.12 to 2.0.13 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.12...v2.0.13) Updates `github.com/fatih/color` from 1.15.0 to 1.18.0 - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) Updates `github.com/golang/protobuf` from 1.5.3 to 1.5.4 - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.5.3...v1.5.4) Updates `github.com/grpc-ecosystem/grpc-gateway/v2` from 2.19.1 to 2.26.3 - [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases) - [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml) - [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.19.1...v2.26.3) Updates `github.com/hashicorp/eventlogger` from 0.2.6-0.20231025104552-802587e608f0 to 0.2.11 - [Commits](https://github.com/hashicorp/eventlogger/compare/v0.2.9...v0.2.11) Updates `github.com/hashicorp/go-hclog` from 1.5.0 to 1.6.3 - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.5.0...v1.6.3) Updates `github.com/hashicorp/go-kms-wrapping/v2` from 2.0.16 to 2.0.18 - [Commits](https://github.com/hashicorp/go-kms-wrapping/commits/v2.0.18) Updates `github.com/hashicorp/go-secure-stdlib/configutil/v2` from 2.0.11 to 2.0.12 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/configutil/v2.0.11...configutil/v2.0.12) Updates `github.com/hashicorp/go-secure-stdlib/listenerutil` from 0.1.9 to 0.1.10 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...listenerutil/v0.1.10) Updates `github.com/hashicorp/go-secure-stdlib/parseutil` from 0.1.8 to 0.1.9 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/parseutil/v0.1.9...awsutil/v0.2.0) Updates `github.com/hashicorp/go-secure-stdlib/pluginutil/v2` from 2.0.6 to 2.0.8 - [Release notes](https://github.com/hashicorp/go-secure-stdlib/releases) - [Commits](https://github.com/hashicorp/go-secure-stdlib/compare/configutil/v2.0.6...configutil/v2.0.8) Updates `github.com/hashicorp/go-sockaddr` from 1.0.5 to 1.0.6 - [Release notes](https://github.com/hashicorp/go-sockaddr/releases) - [Commits](https://github.com/hashicorp/go-sockaddr/compare/v1.0.6...v1.0.7) Updates `github.com/mattn/go-colorable` from 0.1.13 to 0.1.14 - [Commits](https://github.com/mattn/go-colorable/compare/v0.1.13...v0.1.14) Updates `github.com/stretchr/testify` from 1.8.4 to 1.9.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) Updates `golang.org/x/crypto` from 0.37.0 to 0.38.0 - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) Updates `golang.org/x/net` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0) Updates `golang.org/x/sys` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0) Updates `golang.org/x/text` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0) Updates `google.golang.org/genproto/googleapis/api` from 0.0.0-20240125205218-1f4bbc51befe to 0.0.0-20250303144028-a0af3efb3deb - [Commits](https://github.com/googleapis/go-genproto/commits) Updates `google.golang.org/grpc` from 1.61.0 to 1.70.0 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.72.1) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.5 Updates `nhooyr.io/websocket` from 1.8.10 to 1.8.17 - [Release notes](https://github.com/nhooyr/websocket-old/releases) - [Commits](https://github.com/nhooyr/websocket-old/commits/v1.8.17) Updates `github.com/hashicorp/go-kms-wrapping/plugin/v2` from 2.0.7 to 2.0.8 - [Commits](https://github.com/hashicorp/go-kms-wrapping/compare/v2.0.7...v2.0.8) --- updated-dependencies: - dependency-name: github.com/cenkalti/backoff/v4 dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/creack/pty dependency-version: 1.1.24 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/docker/docker dependency-version: 28.1.1+incompatible dependency-type: direct:production update-type: version-update:semver-major dependency-group: go - dependency-name: github.com/fatih/color dependency-version: 1.18.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/glebarez/sqlite dependency-version: 1.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/golang-migrate/migrate/v4 dependency-version: 4.18.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/golang/protobuf dependency-version: 1.5.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/google/go-cmp dependency-version: 0.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2 dependency-version: 2.26.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/hashicorp/cap dependency-version: 0.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/hashicorp/eventlogger dependency-version: 0.2.11 dependency-type: direct:production update-type: version-... Signed-off-by: dependabot[bot] <support@github.com> * mod: downgrade/upgrade some dependencies to fix build * all: regenerate protobuf files * internal: rerun gofumpt * internal/cmd/config: fix test after change of behavior * internal/daemon/controlller: explicitly disable gRPC Client DNS resolution It seems that the gRPC client update caused it to dislike our empty connection string. Explicitly pass through DNS resolution using the "passthrough" resolver. * testing/e2e: update test type reference Docker changed the type here apparently --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
3564 lines
88 KiB
Go
3564 lines
88 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package config
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/boundary/internal/event"
|
|
"github.com/hashicorp/boundary/internal/ratelimit"
|
|
"github.com/hashicorp/boundary/internal/util"
|
|
configutil "github.com/hashicorp/go-secure-stdlib/configutil/v2"
|
|
"github.com/hashicorp/go-secure-stdlib/listenerutil"
|
|
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDevController(t *testing.T) {
|
|
actual, err := DevController()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
truePointer := new(bool)
|
|
*truePointer = true
|
|
|
|
apiHeaders := map[int]http.Header{
|
|
0: {
|
|
"Content-Security-Policy": {"default-src 'none'"},
|
|
"X-Content-Type-Options": {"nosniff"},
|
|
"Strict-Transport-Security": {"max-age=31536000; includeSubDomains"},
|
|
"Cache-Control": {"no-store"},
|
|
},
|
|
}
|
|
uiHeaders := map[int]http.Header{
|
|
0: {
|
|
"Content-Security-Policy": {defaultCsp},
|
|
"X-Content-Type-Options": {"nosniff"},
|
|
"Strict-Transport-Security": {"max-age=31536000; includeSubDomains"},
|
|
"Cache-Control": {"no-store"},
|
|
},
|
|
}
|
|
|
|
exp := &Config{
|
|
Eventing: event.DefaultEventerConfig(),
|
|
SharedConfig: &configutil.SharedConfig{
|
|
DisableMlock: true,
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"api"},
|
|
TLSDisable: true,
|
|
CorsEnabled: truePointer,
|
|
CorsAllowedOrigins: []string{"*"},
|
|
CustomApiResponseHeaders: apiHeaders,
|
|
CustomUiResponseHeaders: uiHeaders,
|
|
},
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"cluster"},
|
|
CustomApiResponseHeaders: apiHeaders,
|
|
CustomUiResponseHeaders: uiHeaders,
|
|
},
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"ops"},
|
|
TLSDisable: true,
|
|
CustomApiResponseHeaders: apiHeaders,
|
|
CustomUiResponseHeaders: uiHeaders,
|
|
},
|
|
},
|
|
Seals: []*configutil.KMS{
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"root"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_root",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"worker-auth"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_worker-auth",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"bsr"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_bsr",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"recovery"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_recovery",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{
|
|
Name: "dev-controller",
|
|
Description: "A default controller created in dev mode",
|
|
ApiRateLimits: make(ratelimit.Configs, 0),
|
|
ApiRateLimiterMaxQuotas: ratelimit.DefaultLimiterMaxQuotas(),
|
|
},
|
|
DevController: true,
|
|
}
|
|
exp.Eventing.ErrorEventsDisabled = true
|
|
exp.Eventing.SysEventsEnabled = false
|
|
exp.Eventing.ObservationsEnabled = false
|
|
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Listeners[1].RawConfig = actual.Listeners[1].RawConfig
|
|
exp.Listeners[2].RawConfig = actual.Listeners[2].RawConfig
|
|
exp.Seals[0].Config["key"] = actual.Seals[0].Config["key"]
|
|
exp.Seals[1].Config["key"] = actual.Seals[1].Config["key"]
|
|
exp.Seals[2].Config["key"] = actual.Seals[2].Config["key"]
|
|
exp.Seals[3].Config["key"] = actual.Seals[3].Config["key"]
|
|
exp.DevControllerKey = actual.Seals[0].Config["key"]
|
|
exp.DevWorkerAuthKey = actual.Seals[1].Config["key"]
|
|
exp.DevBsrKey = actual.Seals[2].Config["key"]
|
|
exp.DevRecoveryKey = actual.Seals[3].Config["key"]
|
|
|
|
assert.Equal(t, exp, actual)
|
|
|
|
// Do some CORS-specific testing
|
|
{
|
|
// CORS disabled
|
|
conf := `
|
|
listener "tcp" {
|
|
purpose = "api"
|
|
cors_enabled = false
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
l0 := actual.Listeners[0]
|
|
assert.False(t, *l0.CorsEnabled)
|
|
assert.Empty(t, l0.CorsAllowedHeaders)
|
|
|
|
// Enabled with a wildcard
|
|
conf = `
|
|
listener "tcp" {
|
|
purpose = "api"
|
|
cors_enabled = true
|
|
cors_allowed_origins = ["*"]
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
l0 = actual.Listeners[0]
|
|
assert.True(t, *l0.CorsEnabled)
|
|
assert.Equal(t, []string{"*"}, l0.CorsAllowedOrigins)
|
|
assert.Nil(t, l0.CorsDisableDefaultAllowedOriginValues)
|
|
|
|
// Disabled, default behavior
|
|
conf = `
|
|
listener "tcp" {
|
|
purpose = "api"
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
l0 = actual.Listeners[0]
|
|
assert.True(t, *l0.CorsEnabled)
|
|
assert.Equal(t, []string{"*"}, l0.CorsAllowedOrigins)
|
|
assert.Nil(t, l0.CorsDisableDefaultAllowedOriginValues)
|
|
|
|
// Disabled, default behavior
|
|
conf = `
|
|
listener "tcp" {
|
|
purpose = "api"
|
|
cors_disable_default_allowed_origin_values = true
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
l0 = actual.Listeners[0]
|
|
assert.Nil(t, l0.CorsEnabled)
|
|
assert.Empty(t, l0.CorsAllowedOrigins)
|
|
assert.True(t, *l0.CorsDisableDefaultAllowedOriginValues)
|
|
}
|
|
|
|
// Test plugins block
|
|
{
|
|
// CORS disabled
|
|
conf := `
|
|
plugins {
|
|
execution_dir = "/tmp/foobar"
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, actual.Plugins.ExecutionDir, "/tmp/foobar")
|
|
}
|
|
}
|
|
|
|
func TestDevWorker(t *testing.T) {
|
|
actual, err := DevWorker(WithSysEventsEnabled(true), WithObservationsEnabled(true), TestWithErrorEventsEnabled(t, true))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
exp := &Config{
|
|
Eventing: event.DefaultEventerConfig(),
|
|
SharedConfig: &configutil.SharedConfig{
|
|
DisableMlock: true,
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"proxy"},
|
|
CustomApiResponseHeaders: map[int]http.Header{
|
|
0: {
|
|
"Content-Security-Policy": {"default-src 'none'"},
|
|
"X-Content-Type-Options": {"nosniff"},
|
|
"Strict-Transport-Security": {"max-age=31536000; includeSubDomains"},
|
|
"Cache-Control": {"no-store"},
|
|
},
|
|
},
|
|
CustomUiResponseHeaders: map[int]http.Header{
|
|
0: {
|
|
"Content-Security-Policy": {defaultCsp},
|
|
"X-Content-Type-Options": {"nosniff"},
|
|
"Strict-Transport-Security": {"max-age=31536000; includeSubDomains"},
|
|
"Cache-Control": {"no-store"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Seals: []*configutil.KMS{
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"worker-auth-storage"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "worker-auth-storage",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Worker: &Worker{
|
|
Name: "w_1234567890",
|
|
Description: "A default worker created in dev mode",
|
|
InitialUpstreams: []string{"127.0.0.1"},
|
|
InitialUpstreamsRaw: []any{"127.0.0.1"},
|
|
Tags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
},
|
|
},
|
|
}
|
|
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Seals[0].Config["key"] = actual.Seals[0].Config["key"]
|
|
exp.Worker.TagsRaw = actual.Worker.TagsRaw
|
|
assert.Equal(t, exp, actual)
|
|
|
|
// Redo it with key=value syntax for tags
|
|
devWorkerKeyValueConfig := `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags = ["type=dev", "type=local"]
|
|
}
|
|
`
|
|
|
|
actual, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.NoError(t, err)
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Seals = nil
|
|
exp.Worker.TagsRaw = actual.Worker.TagsRaw
|
|
assert.Equal(t, exp, actual)
|
|
|
|
// Handle when there is a singular value not indicated as a slice
|
|
devWorkerKeyValueConfig = `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = "local"
|
|
}
|
|
}
|
|
`
|
|
|
|
actual, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.NoError(t, err)
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Worker.TagsRaw = actual.Worker.TagsRaw
|
|
prevTags := exp.Worker.Tags
|
|
exp.Worker.Tags = map[string][]string{"type": {"local"}}
|
|
assert.Equal(t, exp, actual)
|
|
exp.Worker.Tags = prevTags
|
|
|
|
// Redo it with non-lower-cased keys
|
|
devWorkerKeyValueConfig = `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags = ["tyPe=dev", "type=local"]
|
|
}
|
|
`
|
|
|
|
_, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.Error(t, err)
|
|
|
|
// Redo it with non-lower-cased values
|
|
devWorkerKeyValueConfig = `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags = ["type=dev", "type=loCal"]
|
|
}
|
|
`
|
|
|
|
_, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.Error(t, err)
|
|
|
|
// Redo with non-printable characters to validate the strutil function
|
|
devWorkerKeyValueConfig = `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "dev-work\u0000er"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags = ["type=dev", "type=local"]
|
|
}
|
|
`
|
|
|
|
_, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.Error(t, err)
|
|
|
|
// Check activation token parsing
|
|
devWorkerActivationTokenConfig := `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "dev-worker"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
controller_generated_activation_token = "foobar"
|
|
}
|
|
`
|
|
|
|
actual, err = Parse(devConfig + devWorkerActivationTokenConfig)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "foobar", actual.Worker.ControllerGeneratedActivationToken)
|
|
}
|
|
|
|
func TestDevCombined(t *testing.T) {
|
|
actual, err := DevCombined()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
truePointer := new(bool)
|
|
*truePointer = true
|
|
|
|
apiHeaders := map[int]http.Header{
|
|
0: {
|
|
"Content-Security-Policy": {"default-src 'none'"},
|
|
"X-Content-Type-Options": {"nosniff"},
|
|
"Strict-Transport-Security": {"max-age=31536000; includeSubDomains"},
|
|
"Cache-Control": {"no-store"},
|
|
},
|
|
}
|
|
uiHeaders := map[int]http.Header{
|
|
0: {
|
|
"Content-Security-Policy": {defaultCsp},
|
|
"X-Content-Type-Options": {"nosniff"},
|
|
"Strict-Transport-Security": {"max-age=31536000; includeSubDomains"},
|
|
"Cache-Control": {"no-store"},
|
|
},
|
|
}
|
|
|
|
exp := &Config{
|
|
Eventing: event.DefaultEventerConfig(),
|
|
SharedConfig: &configutil.SharedConfig{
|
|
DisableMlock: true,
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"api"},
|
|
TLSDisable: true,
|
|
CorsEnabled: truePointer,
|
|
CorsAllowedOrigins: []string{"*"},
|
|
CustomApiResponseHeaders: apiHeaders,
|
|
CustomUiResponseHeaders: uiHeaders,
|
|
},
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"cluster"},
|
|
CustomApiResponseHeaders: apiHeaders,
|
|
CustomUiResponseHeaders: uiHeaders,
|
|
},
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"ops"},
|
|
TLSDisable: true,
|
|
CustomApiResponseHeaders: apiHeaders,
|
|
CustomUiResponseHeaders: uiHeaders,
|
|
},
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"proxy"},
|
|
CustomApiResponseHeaders: apiHeaders,
|
|
CustomUiResponseHeaders: uiHeaders,
|
|
},
|
|
},
|
|
Seals: []*configutil.KMS{
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"root"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_root",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"worker-auth"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_worker-auth",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"bsr"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_bsr",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"recovery"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_recovery",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"worker-auth-storage"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "worker-auth-storage",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{
|
|
Name: "dev-controller",
|
|
Description: "A default controller created in dev mode",
|
|
ApiRateLimits: make(ratelimit.Configs, 0),
|
|
ApiRateLimiterMaxQuotas: ratelimit.DefaultLimiterMaxQuotas(),
|
|
},
|
|
DevController: true,
|
|
Worker: &Worker{
|
|
Name: "w_1234567890",
|
|
Description: "A default worker created in dev mode",
|
|
InitialUpstreams: []string{"127.0.0.1"},
|
|
InitialUpstreamsRaw: []any{"127.0.0.1"},
|
|
Tags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
},
|
|
},
|
|
}
|
|
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Listeners[1].RawConfig = actual.Listeners[1].RawConfig
|
|
exp.Listeners[2].RawConfig = actual.Listeners[2].RawConfig
|
|
exp.Listeners[3].RawConfig = actual.Listeners[3].RawConfig
|
|
exp.Seals[0].Config["key"] = actual.Seals[0].Config["key"]
|
|
exp.Seals[1].Config["key"] = actual.Seals[1].Config["key"]
|
|
exp.Seals[2].Config["key"] = actual.Seals[2].Config["key"]
|
|
exp.Seals[3].Config["key"] = actual.Seals[3].Config["key"]
|
|
exp.Seals[4].Config["key"] = actual.Seals[4].Config["key"]
|
|
exp.DevControllerKey = actual.Seals[0].Config["key"]
|
|
exp.DevWorkerAuthKey = actual.Seals[1].Config["key"]
|
|
exp.DevBsrKey = actual.Seals[2].Config["key"]
|
|
exp.DevRecoveryKey = actual.Seals[3].Config["key"]
|
|
exp.DevWorkerAuthStorageKey = actual.Seals[4].Config["key"]
|
|
exp.Worker.TagsRaw = actual.Worker.TagsRaw
|
|
assert.Equal(t, exp, actual)
|
|
}
|
|
|
|
func TestDevWorkerCredentialStoragePath(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
name string
|
|
devWorkerProvidedConfiguration string
|
|
storagePath string
|
|
}{
|
|
{
|
|
name: "Relative Storage Directory",
|
|
devWorkerProvidedConfiguration: `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
auth_storage_path = ".."
|
|
}
|
|
`,
|
|
storagePath: "..",
|
|
},
|
|
{
|
|
name: "Nonexistent Storage Directory",
|
|
devWorkerProvidedConfiguration: `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
auth_storage_path = "nonexistent_dir/here"
|
|
}
|
|
`,
|
|
storagePath: "nonexistent_dir/here",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parsed, err := Parse(devConfig + tt.devWorkerProvidedConfiguration)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.storagePath, parsed.Worker.AuthStoragePath)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDevWorkerRecordingStorageMinimumAvailableCapacity(t *testing.T) {
|
|
t.Parallel()
|
|
td := t.TempDir()
|
|
tests := []struct {
|
|
name string
|
|
devWorkerProvidedConfiguration string
|
|
storagePath string
|
|
storageCapacity string
|
|
expectedDiskSpace uint64
|
|
expectedErrMsg string
|
|
}{
|
|
{
|
|
name: "empty storage with empty capacity",
|
|
devWorkerProvidedConfiguration: `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
}
|
|
`,
|
|
expectedDiskSpace: 0,
|
|
storagePath: "",
|
|
},
|
|
{
|
|
name: "empty storage path with set capacity",
|
|
devWorkerProvidedConfiguration: `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
recording_storage_minimum_available_capacity = "4kib"
|
|
}
|
|
`,
|
|
expectedErrMsg: "recording_storage_path cannot be empty when providing recording_storage_minimum_available_capacity",
|
|
},
|
|
{
|
|
name: "storage path with empty capacity defaults to 500mib",
|
|
devWorkerProvidedConfiguration: fmt.Sprintf(`
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
recording_storage_path = "%v"
|
|
}
|
|
`, td),
|
|
storagePath: td,
|
|
expectedDiskSpace: 524288000,
|
|
},
|
|
{
|
|
name: "storage path with capacity string",
|
|
devWorkerProvidedConfiguration: fmt.Sprintf(`
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
recording_storage_path = "%v"
|
|
recording_storage_minimum_available_capacity = "4kib"
|
|
}
|
|
`, td),
|
|
storagePath: td,
|
|
expectedDiskSpace: 4096,
|
|
},
|
|
{
|
|
name: "storage path with raw byte value",
|
|
devWorkerProvidedConfiguration: fmt.Sprintf(`
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
recording_storage_path = "%v"
|
|
recording_storage_minimum_available_capacity = "4096"
|
|
}
|
|
`, td),
|
|
storagePath: td,
|
|
expectedDiskSpace: 4096,
|
|
},
|
|
{
|
|
name: "storage path with invalid capacity input",
|
|
devWorkerProvidedConfiguration: fmt.Sprintf(`
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
recording_storage_path = "%v"
|
|
recording_storage_minimum_available_capacity = "gib"
|
|
}
|
|
`, td),
|
|
storagePath: td,
|
|
expectedErrMsg: "could not parse capacity from input",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parsed, err := Parse(devConfig + tt.devWorkerProvidedConfiguration)
|
|
if tt.expectedErrMsg != "" {
|
|
require.Error(t, err)
|
|
assert.ErrorContains(t, err, tt.expectedErrMsg)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.storagePath, parsed.Worker.RecordingStoragePath)
|
|
assert.Equal(t, tt.expectedDiskSpace, parsed.Worker.RecordingStorageMinimumAvailableDiskSpace)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDevWorkerRecordingStoragePath(t *testing.T) {
|
|
t.Parallel()
|
|
td := t.TempDir()
|
|
tests := []struct {
|
|
name string
|
|
devWorkerProvidedConfiguration string
|
|
storagePath string
|
|
}{
|
|
{
|
|
name: "Relative Storage Directory",
|
|
devWorkerProvidedConfiguration: `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
recording_storage_path = ".."
|
|
}
|
|
`,
|
|
storagePath: "..",
|
|
},
|
|
{
|
|
name: "temp dir",
|
|
devWorkerProvidedConfiguration: fmt.Sprintf(`
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "w_1234567890"
|
|
description = "A default worker created in dev mode"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
tags {
|
|
type = ["dev", "local"]
|
|
}
|
|
recording_storage_path = "%v"
|
|
}
|
|
`, td),
|
|
storagePath: td,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parsed, err := Parse(devConfig + tt.devWorkerProvidedConfiguration)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.storagePath, parsed.Worker.RecordingStoragePath)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestDevControllerIpv6 validates that all listeners use an IPv6 address when
|
|
// the WithIPv6Enabled(true) option is passed into DevController. Other dev
|
|
// controller configurations are validated in TestDevController.
|
|
func TestDevControllerIpv6(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
actual, err := DevController(WithIPv6Enabled(true))
|
|
require.NoError(err)
|
|
|
|
// Expected an error here because PublicClusterAddr is not set.
|
|
_, _, err = net.SplitHostPort(actual.Controller.PublicClusterAddr)
|
|
require.Error(err)
|
|
|
|
// Same here.
|
|
publicAddr, port, err := util.SplitHostPort(actual.Controller.PublicClusterAddr)
|
|
require.ErrorIs(err, util.ErrMissingPort)
|
|
require.Empty(port)
|
|
require.Empty(publicAddr)
|
|
|
|
require.NotEmpty(actual.Listeners)
|
|
for _, l := range actual.Listeners {
|
|
addr, _, err := util.SplitHostPort(l.Address)
|
|
require.ErrorIs(err, util.ErrMissingPort)
|
|
require.NotEmpty(t, addr)
|
|
|
|
ip := net.ParseIP(addr)
|
|
require.NotNil(ip, "failed to parse listener address for %v", l.Purpose)
|
|
require.NotNil(ip.To16(), "failed to convert address to IPv6 for %v, found %v", l.Purpose, addr)
|
|
}
|
|
}
|
|
|
|
// TestDevWorkerIpv6 validates that all listeners use an IPv6 address when the
|
|
// WithIPv6Enabled(true) option is passed into DevWorker. Other dev worker
|
|
// configurations are validated in TestDevWorker.
|
|
func TestDevWorkerIpv6(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
actual, err := DevWorker(WithIPv6Enabled(true))
|
|
require.NoError(err)
|
|
|
|
// Expected an error here because PublicAddr does not have a port.
|
|
_, _, err = net.SplitHostPort(actual.Worker.PublicAddr)
|
|
require.Error(err)
|
|
|
|
// util.SplitHostPort, however, can handle it when ports are missing.
|
|
publicAddr, port, err := util.SplitHostPort(actual.Worker.PublicAddr)
|
|
require.ErrorIs(err, util.ErrMissingPort)
|
|
require.Empty(port)
|
|
require.NotEmpty(t, publicAddr)
|
|
|
|
ip := net.ParseIP(publicAddr)
|
|
require.NotNil(ip, "failed to parse worker public address")
|
|
require.NotNil(ip.To16(), "worker public address is not IPv6 %s", actual.Worker.PublicAddr)
|
|
|
|
require.NotEmpty(actual.Listeners)
|
|
for _, l := range actual.Listeners {
|
|
addr, _, err := util.SplitHostPort(l.Address)
|
|
require.ErrorIs(err, util.ErrMissingPort)
|
|
require.NotEmpty(addr)
|
|
|
|
ip := net.ParseIP(addr)
|
|
require.NotNil(ip, "failed to parse listener address for %v", l.Purpose)
|
|
require.NotNil(ip.To16(), "failed to convert address to IPv6 for %v, found %v", l.Purpose, addr)
|
|
}
|
|
}
|
|
|
|
// TestDevCombinedIpv6 validates that all listeners use an IPv6 address when the
|
|
// WithIPv6Enabled(true) option is passed into DevCombined.
|
|
func TestDevCombinedIpv6(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
actual, err := DevCombined(WithIPv6Enabled(true))
|
|
require.NoError(err)
|
|
|
|
// Expected to fail because PublicAddr does not have a port.
|
|
_, _, err = net.SplitHostPort(actual.Worker.PublicAddr)
|
|
require.Error(err)
|
|
// Expected to fail because PublicClusterAddr is not set.
|
|
_, _, err = net.SplitHostPort(actual.Controller.PublicClusterAddr)
|
|
require.Error(err)
|
|
|
|
// util.SplitHostPort, however, can handle it when ports are missing.
|
|
publicAddr, port, err := util.SplitHostPort(actual.Worker.PublicAddr)
|
|
require.ErrorIs(err, util.ErrMissingPort)
|
|
require.Empty(port)
|
|
require.NotEmpty(publicAddr)
|
|
|
|
ip := net.ParseIP(publicAddr)
|
|
require.NotNil(ip, "failed to parse worker public address")
|
|
require.NotNil(ip.To16(), "worker public address is not IPv6 %s", actual.Worker.PublicAddr)
|
|
|
|
// Expected to fail because PublicClusterAddr is not set.
|
|
publicAddr, port, err = util.SplitHostPort(actual.Controller.PublicClusterAddr)
|
|
require.ErrorIs(err, util.ErrMissingPort)
|
|
require.Empty(port)
|
|
require.Empty(publicAddr)
|
|
|
|
require.NotEmpty(actual.Listeners)
|
|
for _, l := range actual.Listeners {
|
|
addr, _, err := util.SplitHostPort(l.Address)
|
|
require.ErrorIs(err, util.ErrMissingPort)
|
|
require.NotEmpty(addr)
|
|
|
|
ip := net.ParseIP(addr)
|
|
require.NotNil(ip, "failed to parse listener address for %v", l.Purpose)
|
|
require.NotNil(ip.To16(), "failed to convert address to IPv6 for %v, found %v", l.Purpose, addr)
|
|
}
|
|
}
|
|
|
|
func TestDevKeyGeneration(t *testing.T) {
|
|
t.Parallel()
|
|
dk := DevKeyGeneration()
|
|
buf, err := base64.StdEncoding.DecodeString(dk)
|
|
require.NoError(t, err)
|
|
require.Len(t, buf, 32)
|
|
require.NotEqual(t, dk, DevKeyGeneration())
|
|
}
|
|
|
|
func TestParsingName(t *testing.T) {
|
|
t.Parallel()
|
|
config := `
|
|
controller {
|
|
name = "%s"
|
|
}
|
|
worker {
|
|
name = "%s"
|
|
}
|
|
`
|
|
controllerEnv := "FOOENV"
|
|
workerEnv := "BARENV"
|
|
cases := []struct {
|
|
name string
|
|
templateController string
|
|
templateWorker string
|
|
envController string
|
|
envWorker string
|
|
expectedController string
|
|
expectedWorker string
|
|
}{
|
|
{
|
|
name: "no env",
|
|
templateController: "foobar",
|
|
templateWorker: "test_worker_barfoo",
|
|
expectedController: "foobar",
|
|
expectedWorker: "test_worker_barfoo",
|
|
},
|
|
{
|
|
name: "env",
|
|
templateController: fmt.Sprintf("env://%s", controllerEnv),
|
|
templateWorker: fmt.Sprintf("env://%s", workerEnv),
|
|
envController: "foobar2",
|
|
envWorker: "env_name_barfoo2",
|
|
expectedController: "foobar2",
|
|
expectedWorker: "env_name_barfoo2",
|
|
},
|
|
}
|
|
for _, tt := range cases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.envController != "" {
|
|
os.Setenv(controllerEnv, tt.envController)
|
|
}
|
|
if tt.envWorker != "" {
|
|
os.Setenv(workerEnv, tt.envWorker)
|
|
}
|
|
out, err := Parse(fmt.Sprintf(config, tt.templateController, tt.templateWorker))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.expectedController, out.Controller.Name)
|
|
assert.Equal(t, tt.expectedWorker, out.Worker.Name)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParsingSchedulerIntervals(t *testing.T) {
|
|
t.Parallel()
|
|
cases := []struct {
|
|
name string
|
|
config string
|
|
wantErr bool
|
|
wantMonitorInterval time.Duration
|
|
wantRunJobInterval time.Duration
|
|
}{
|
|
{
|
|
name: "invalid-run-interval",
|
|
config: `
|
|
controller {
|
|
scheduler {
|
|
job_run_interval = "hello"
|
|
}
|
|
}
|
|
`,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "invalid-monitor-interval",
|
|
config: `
|
|
controller {
|
|
scheduler {
|
|
monitor_interval = "hello"
|
|
}
|
|
}
|
|
`,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "valid-undefined",
|
|
config: `controller { scheduler {} }`,
|
|
wantMonitorInterval: 0,
|
|
wantRunJobInterval: 0,
|
|
},
|
|
{
|
|
name: "run-job-interval",
|
|
config: `
|
|
controller {
|
|
scheduler {
|
|
job_run_interval = "10m"
|
|
}
|
|
}
|
|
`,
|
|
wantMonitorInterval: 0,
|
|
wantRunJobInterval: 10 * time.Minute,
|
|
},
|
|
{
|
|
name: "monitor-interval",
|
|
config: `
|
|
controller {
|
|
scheduler {
|
|
monitor_interval = "6h"
|
|
}
|
|
}
|
|
`,
|
|
wantMonitorInterval: 6 * time.Hour,
|
|
wantRunJobInterval: 0,
|
|
},
|
|
{
|
|
name: "both",
|
|
config: `
|
|
controller {
|
|
scheduler {
|
|
monitor_interval = "7d"
|
|
job_run_interval = "20s"
|
|
}
|
|
}
|
|
`,
|
|
wantMonitorInterval: 7 * 24 * time.Hour,
|
|
wantRunJobInterval: 20 * time.Second,
|
|
},
|
|
}
|
|
for _, tt := range cases {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
out, err := Parse(tt.config)
|
|
if tt.wantErr {
|
|
require.Error(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.wantMonitorInterval, out.Controller.Scheduler.MonitorIntervalDuration)
|
|
assert.Equal(t, tt.wantRunJobInterval, out.Controller.Scheduler.JobRunIntervalDuration)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWorkerTags(t *testing.T) {
|
|
defaultStateFn := func(t *testing.T, tags string) {
|
|
t.Setenv("BOUNDARY_WORKER_TAGS", tags)
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
stateFn func(t *testing.T, tags string)
|
|
actualTags string
|
|
expWorkerTags map[string][]string
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "tags in HCL",
|
|
in: `
|
|
worker {
|
|
tags {
|
|
type = ["dev", "local"]
|
|
typetwo = "devtwo"
|
|
}
|
|
}`,
|
|
expWorkerTags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
"typetwo": {"devtwo"},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "tags in HCL key=value",
|
|
in: `
|
|
worker {
|
|
tags = ["type=dev", "type=local", "typetwo=devtwo"]
|
|
}
|
|
`,
|
|
expWorkerTags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
"typetwo": {"devtwo"},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "no tags",
|
|
in: `
|
|
worker {
|
|
name = "w_1234567890"
|
|
}
|
|
`,
|
|
expWorkerTags: nil,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "empty tags",
|
|
in: `
|
|
worker {
|
|
name = "w_1234567890"
|
|
tags = {}
|
|
}
|
|
`,
|
|
expWorkerTags: map[string][]string{},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "empty tags 2",
|
|
in: `
|
|
worker {
|
|
name = "w_1234567890"
|
|
tags = []
|
|
}
|
|
`,
|
|
expWorkerTags: map[string][]string{},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "empty str",
|
|
in: `
|
|
worker {
|
|
tags = ""
|
|
}`,
|
|
expWorkerTags: map[string][]string{},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "empty env var",
|
|
in: `
|
|
worker {
|
|
tags = "env://BOUNDARY_WORKER_TAGS"
|
|
}`,
|
|
expWorkerTags: map[string][]string{},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "not a url - entire tags block",
|
|
in: `
|
|
worker {
|
|
tags = "\x00"
|
|
}`,
|
|
expWorkerTags: map[string][]string{},
|
|
expErr: true,
|
|
expErrStr: `Error parsing worker tags: error parsing url ("parse \"\\x00\": net/url: invalid control character in URL"): not a url`,
|
|
},
|
|
{
|
|
name: "not a url - key's value set to string",
|
|
in: `
|
|
worker {
|
|
tags {
|
|
type = "\x00"
|
|
}
|
|
}
|
|
`,
|
|
expWorkerTags: map[string][]string{
|
|
"type": {"\x00"},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "one tag key",
|
|
in: `
|
|
worker {
|
|
tags = "env://BOUNDARY_WORKER_TAGS"
|
|
}`,
|
|
stateFn: defaultStateFn,
|
|
actualTags: `type = ["dev", "local"]`,
|
|
expWorkerTags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "multiple tag keys",
|
|
in: `
|
|
worker {
|
|
tags = "env://BOUNDARY_WORKER_TAGS"
|
|
}`,
|
|
stateFn: defaultStateFn,
|
|
actualTags: `
|
|
type = ["dev", "local"]
|
|
typetwo = ["devtwo", "localtwo"]
|
|
`,
|
|
expWorkerTags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
"typetwo": {"devtwo", "localtwo"},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "comma in tag key string",
|
|
in: `
|
|
worker {
|
|
tags {
|
|
"key,"= ["value"],
|
|
}
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: `Tag key "key," cannot contain commas`,
|
|
},
|
|
{
|
|
name: "comma in tag value string",
|
|
in: `
|
|
worker {
|
|
tags {
|
|
"key"= ["va,lue","value2"],
|
|
}
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: `Tag value "va,lue" for tag key "key" cannot contain commas`,
|
|
},
|
|
{
|
|
name: "json tags - entire tags block",
|
|
in: `
|
|
worker {
|
|
tags = "env://BOUNDARY_WORKER_TAGS"
|
|
}`,
|
|
stateFn: defaultStateFn,
|
|
actualTags: `
|
|
{
|
|
"type": ["dev", "local"],
|
|
"typetwo": ["devtwo", "localtwo"]
|
|
}
|
|
`,
|
|
expWorkerTags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
"typetwo": {"devtwo", "localtwo"},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "json tags - keys specified in the HCL file, values point to env/file",
|
|
in: `
|
|
worker {
|
|
tags = {
|
|
type = "env://BOUNDARY_WORKER_TAGS"
|
|
typetwo = "env://BOUNDARY_WORKER_TAGS_TWO"
|
|
}
|
|
}`,
|
|
stateFn: func(t *testing.T, tags string) {
|
|
defaultStateFn(t, tags)
|
|
t.Setenv("BOUNDARY_WORKER_TAGS_TWO", `["devtwo", "localtwo"]`)
|
|
},
|
|
actualTags: `["dev","local"]`,
|
|
expWorkerTags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
"typetwo": {"devtwo", "localtwo"},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "json tags - mix n' match",
|
|
in: `
|
|
worker {
|
|
name = "web-prod-us-east-1"
|
|
tags {
|
|
type = "env://BOUNDARY_WORKER_TYPE_TAGS"
|
|
typetwo = "file://type_two_tags.json"
|
|
typethree = ["devthree", "localthree"]
|
|
}
|
|
}
|
|
`,
|
|
stateFn: func(t *testing.T, tags string) {
|
|
workerTypeTags := `["dev", "local"]`
|
|
t.Setenv("BOUNDARY_WORKER_TYPE_TAGS", workerTypeTags)
|
|
|
|
filepath := "./type_two_tags.json"
|
|
err := os.WriteFile(filepath, []byte(`["devtwo", "localtwo"]`), 0o666)
|
|
require.NoError(t, err)
|
|
|
|
t.Cleanup(func() {
|
|
err := os.Remove(filepath)
|
|
require.NoError(t, err)
|
|
})
|
|
},
|
|
expWorkerTags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
"typetwo": {"devtwo", "localtwo"},
|
|
"typethree": {"devthree", "localthree"},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "bad json tags",
|
|
in: `
|
|
worker {
|
|
tags = {
|
|
type = "env://BOUNDARY_WORKER_TAGS"
|
|
typetwo = "env://BOUNDARY_WORKER_TAGS"
|
|
}
|
|
}`,
|
|
stateFn: defaultStateFn,
|
|
actualTags: `
|
|
{
|
|
"type": ["dev", "local"],
|
|
"typetwo": ["devtwo", "localtwo"]
|
|
}
|
|
`,
|
|
expWorkerTags: nil,
|
|
expErr: true,
|
|
expErrStr: "Error unmarshaling env var/file contents: json: cannot unmarshal object into Go value of type []string",
|
|
},
|
|
{
|
|
name: "no clean mapping to internal structures",
|
|
in: `
|
|
worker {
|
|
tags = "env://BOUNDARY_WORKER_TAGS"
|
|
}`,
|
|
stateFn: defaultStateFn,
|
|
actualTags: `
|
|
worker {
|
|
tags {
|
|
type = "indeed"
|
|
}
|
|
}
|
|
`,
|
|
expErr: true,
|
|
expErrStr: "Error decoding the worker's tags: 1 error(s) decoding:\n\n* '[0][worker][0]' expected type 'string', got unconvertible type 'map[string]interface {}', value: 'map[tags:[map[type:indeed]]]'",
|
|
},
|
|
{
|
|
name: "not HCL",
|
|
in: `worker {
|
|
tags = "env://BOUNDARY_WORKER_TAGS"
|
|
}`,
|
|
stateFn: defaultStateFn,
|
|
actualTags: `not_hcl`,
|
|
expErr: true,
|
|
expErrStr: "Error decoding raw worker tags: At 1:9: key 'not_hcl' expected start of object ('{') or assignment ('=')",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.stateFn != nil {
|
|
tt.stateFn(t, tt.actualTags)
|
|
}
|
|
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Worker)
|
|
require.Equal(t, tt.expWorkerTags, c.Worker.Tags)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestController_EventingConfig(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
config []string
|
|
wantEventerConfig *event.EventerConfig
|
|
wantErr string
|
|
}{
|
|
{
|
|
name: "default",
|
|
wantEventerConfig: event.DefaultEventerConfig(),
|
|
},
|
|
{
|
|
name: "audit-enabled",
|
|
config: []string{`
|
|
events {
|
|
audit_enabled = true
|
|
}
|
|
`},
|
|
wantEventerConfig: &event.EventerConfig{
|
|
AuditEnabled: true,
|
|
ObservationsEnabled: false,
|
|
Sinks: []*event.SinkConfig{
|
|
event.DefaultSink(),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "observations-enabled",
|
|
config: []string{`
|
|
events {
|
|
observations_enabled = true
|
|
}
|
|
`},
|
|
wantEventerConfig: &event.EventerConfig{
|
|
AuditEnabled: false,
|
|
ObservationsEnabled: true,
|
|
Sinks: []*event.SinkConfig{
|
|
event.DefaultSink(),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "no-sink-type-determined",
|
|
config: []string{
|
|
`events {
|
|
audit_enabled = false
|
|
observations_enabled = true
|
|
sink {
|
|
format = "cloudevents-json"
|
|
name = "configured-sink"
|
|
event_types = [ "audit", "observation" ]
|
|
}
|
|
}`,
|
|
},
|
|
wantErr: `error parsing "events": sink type could not be determined`,
|
|
},
|
|
{
|
|
name: "sinks-configured",
|
|
config: []string{
|
|
`events {
|
|
audit_enabled = false
|
|
observations_enabled = true
|
|
sink {
|
|
type = "file"
|
|
format = "cloudevents-json"
|
|
name = "configured-sink"
|
|
event_types = [ "audit", "observation" ]
|
|
file {
|
|
file_name = "file-name"
|
|
rotate_duration = "2m"
|
|
}
|
|
}
|
|
sink {
|
|
type = "stderr"
|
|
format = "hclog-text"
|
|
name = "stderr-sink"
|
|
event_types = [ "error" ]
|
|
}
|
|
}`,
|
|
`events {
|
|
audit_enabled = false
|
|
observations_enabled = true
|
|
sink "file" {
|
|
format = "cloudevents-json"
|
|
name = "configured-sink"
|
|
event_types = [ "audit", "observation" ]
|
|
file {
|
|
file_name = "file-name"
|
|
rotate_duration = "2m"
|
|
}
|
|
}
|
|
sink "stderr" {
|
|
format = "hclog-text"
|
|
name = "stderr-sink"
|
|
event_types = [ "error" ]
|
|
}
|
|
}`,
|
|
`events {
|
|
audit_enabled = false
|
|
observations_enabled = true
|
|
sink {
|
|
format = "cloudevents-json"
|
|
name = "configured-sink"
|
|
event_types = [ "audit", "observation" ]
|
|
file {
|
|
file_name = "file-name"
|
|
rotate_duration = "2m"
|
|
}
|
|
}
|
|
sink {
|
|
format = "hclog-text"
|
|
name = "stderr-sink"
|
|
event_types = [ "error" ]
|
|
stderr = {}
|
|
}
|
|
}`,
|
|
`{
|
|
"events": {
|
|
"audit_enabled": false,
|
|
"observations_enabled": true,
|
|
"sink": [
|
|
{
|
|
"type": "file",
|
|
"format": "cloudevents-json",
|
|
"name": "configured-sink",
|
|
"event_types": ["audit", "observation"],
|
|
"file": {
|
|
"file_name": "file-name",
|
|
"rotate_duration": "2m"
|
|
}
|
|
},
|
|
{
|
|
"format": "hclog-text",
|
|
"name": "stderr-sink",
|
|
"event_types": ["error"],
|
|
"stderr": {}
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
},
|
|
wantEventerConfig: &event.EventerConfig{
|
|
AuditEnabled: false,
|
|
ObservationsEnabled: true,
|
|
Sinks: []*event.SinkConfig{
|
|
{
|
|
Type: "file",
|
|
Name: "configured-sink",
|
|
Format: "cloudevents-json",
|
|
EventTypes: []event.Type{"audit", "observation"},
|
|
FileConfig: &event.FileSinkTypeConfig{
|
|
FileName: "file-name",
|
|
RotateDurationHCL: "2m",
|
|
RotateDuration: 2 * time.Minute,
|
|
},
|
|
},
|
|
{
|
|
Type: "stderr",
|
|
Name: "stderr-sink",
|
|
Format: "hclog-text",
|
|
EventTypes: []event.Type{"error"},
|
|
StderrConfig: &event.StderrSinkTypeConfig{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "audit_config",
|
|
config: []string{
|
|
`events {
|
|
audit_enabled = true
|
|
sink {
|
|
name = "audit-sink"
|
|
format = "cloudevents-json"
|
|
event_types = ["audit"]
|
|
file {
|
|
file_name = "audit.log"
|
|
}
|
|
audit_config {
|
|
audit_filter_overrides {
|
|
sensitive = ""
|
|
secret = "hmac-sha256"
|
|
}
|
|
}
|
|
}
|
|
}`,
|
|
},
|
|
wantEventerConfig: &event.EventerConfig{
|
|
AuditEnabled: true,
|
|
Sinks: []*event.SinkConfig{
|
|
{
|
|
Type: "file",
|
|
Name: "audit-sink",
|
|
Format: "cloudevents-json",
|
|
EventTypes: []event.Type{"audit"},
|
|
FileConfig: &event.FileSinkTypeConfig{
|
|
FileName: "audit.log",
|
|
},
|
|
AuditConfig: &event.AuditConfig{
|
|
FilterOverridesHCL: map[string]string{
|
|
"sensitive": "",
|
|
"secret": "hmac-sha256",
|
|
},
|
|
FilterOverrides: event.AuditFilterOperations{
|
|
event.SensitiveClassification: event.NoOperation,
|
|
event.SecretClassification: event.HmacSha256Operation,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
for i, conf := range tt.config {
|
|
c, err := Parse(conf)
|
|
if tt.wantErr != "" {
|
|
require.Error(err)
|
|
assert.Empty(c)
|
|
assert.Equal(tt.wantErr, err.Error(), "config %d want %q and got %q", i, tt.wantErr, err.Error())
|
|
return
|
|
}
|
|
require.NoError(err)
|
|
assert.NotEmpty(c)
|
|
assert.Equal(tt.wantEventerConfig, c.Eventing)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWorkerUpstreams(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
stateFn func(t *testing.T)
|
|
expWorkerUpstreams []string
|
|
expErr bool
|
|
expErrIs error
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "No Upstreams",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
}
|
|
`,
|
|
expWorkerUpstreams: nil,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "ipv4 Upstream",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = ["127.0.0.1"]
|
|
}
|
|
`,
|
|
expWorkerUpstreams: []string{"127.0.0.1"},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "ipv6 Upstream",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = ["2001:4860:4860:0:0:0:0:8888"]
|
|
}
|
|
`,
|
|
expWorkerUpstreams: []string{"2001:4860:4860::8888"},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "abbreviated ipv6 Upstream",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = ["2001:4860:4860::8888"]
|
|
}
|
|
`,
|
|
expWorkerUpstreams: []string{"2001:4860:4860::8888"},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Multiple Upstreams",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = ["127.0.0.1", "127.0.0.2", "127.0.0.3"]
|
|
}
|
|
`,
|
|
expWorkerUpstreams: []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Using env var",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = "env://BOUNDARY_WORKER_UPSTREAMS"
|
|
}
|
|
`,
|
|
stateFn: func(t *testing.T) { t.Setenv("BOUNDARY_WORKER_UPSTREAMS", `["127.0.0.1", "127.0.0.2", "127.0.0.3"]`) },
|
|
expWorkerUpstreams: []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Using env var - invalid input 1",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = "env://BOUNDARY_WORKER_UPSTREAMS"
|
|
}
|
|
`,
|
|
stateFn: func(t *testing.T) {
|
|
upstreams := `
|
|
worker {
|
|
initial_upstreams = ["127.0.0.1"]
|
|
}
|
|
`
|
|
t.Setenv("BOUNDARY_WORKER_UPSTREAMS", upstreams)
|
|
},
|
|
expWorkerUpstreams: nil,
|
|
expErr: true,
|
|
expErrStr: "Failed to parse worker upstreams: failed to unmarshal env/file contents: invalid character 'w' looking for beginning of value",
|
|
},
|
|
{
|
|
name: "Using env var - invalid input 2",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = "env://BOUNDARY_WORKER_UPSTREAMS"
|
|
}
|
|
`,
|
|
stateFn: func(t *testing.T) { t.Setenv("BOUNDARY_WORKER_UPSTREAMS", `initial_upstreams = ["127.0.0.1"]`) },
|
|
expWorkerUpstreams: nil,
|
|
expErr: true,
|
|
expErrStr: "Failed to parse worker upstreams: failed to unmarshal env/file contents: invalid character 'i' looking for beginning of value",
|
|
},
|
|
{
|
|
name: "Duplicate field",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = {
|
|
ip = "127.0.0.1"
|
|
ip = "127.0.0.2"
|
|
}
|
|
}
|
|
`,
|
|
expWorkerUpstreams: nil,
|
|
expErr: true,
|
|
expErrStr: "The argument \"ip\" at 6:6 was already set. Each argument can only be defined once",
|
|
},
|
|
{
|
|
name: "Worker initial_upstreams set to invalid url",
|
|
in: `
|
|
worker {
|
|
name = "test"
|
|
initial_upstreams = "env://\x00"
|
|
}`,
|
|
expWorkerUpstreams: nil,
|
|
expErr: true,
|
|
expErrIs: parseutil.ErrNotAUrl,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.stateFn != nil {
|
|
tt.stateFn(t)
|
|
}
|
|
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
if tt.expErrIs != nil {
|
|
require.ErrorIs(t, err, tt.expErrIs)
|
|
} else {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
}
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Worker)
|
|
require.EqualValues(t, tt.expWorkerUpstreams, c.Worker.InitialUpstreams)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestControllerDescription(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
envDescription string
|
|
expDescription string
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Valid controller description from env var",
|
|
in: `
|
|
controller {
|
|
description = "env://CONTROLLER_DESCRIPTION"
|
|
}`,
|
|
envDescription: "Test controller description",
|
|
expDescription: "Test controller description",
|
|
expErr: false,
|
|
}, {
|
|
name: "Invalid controller description from env var",
|
|
in: `
|
|
controller {
|
|
description = "\uTest controller description"
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "At 3:22: illegal char escape",
|
|
}, {
|
|
name: "Not a URL, non-printable description",
|
|
in: `
|
|
controller {
|
|
description = "\x00"
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Controller description contains non-printable characters",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv("CONTROLLER_DESCRIPTION", tt.envDescription)
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.Equal(t, tt.expDescription, c.Controller.Description)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestControllerApiRateLimits(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
expLimits ratelimit.Configs
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Single Rate limit",
|
|
in: `
|
|
controller {
|
|
api_rate_limit {
|
|
resources = ["*"]
|
|
actions = ["*"]
|
|
per = "total"
|
|
limit = 50
|
|
period = "1m"
|
|
}
|
|
}`,
|
|
expLimits: ratelimit.Configs{
|
|
{
|
|
Resources: []string{"*"},
|
|
Actions: []string{"*"},
|
|
Per: "total",
|
|
Limit: 50,
|
|
PeriodHCL: "1m",
|
|
Period: time.Minute,
|
|
Unlimited: false,
|
|
},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Single Rate with name",
|
|
in: `
|
|
controller {
|
|
api_rate_limit "default" {
|
|
resources = ["*"]
|
|
actions = ["*"]
|
|
per = "total"
|
|
limit = 50
|
|
period = "1m"
|
|
}
|
|
}`,
|
|
expLimits: ratelimit.Configs{
|
|
{
|
|
Resources: []string{"*"},
|
|
Actions: []string{"*"},
|
|
Per: "total",
|
|
Limit: 50,
|
|
PeriodHCL: "1m",
|
|
Period: time.Minute,
|
|
Unlimited: false,
|
|
},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Multiple Rate limit",
|
|
in: `
|
|
controller {
|
|
api_rate_limit {
|
|
resources = ["*"]
|
|
actions = ["*"]
|
|
per = "total"
|
|
limit = 50
|
|
period = "1m"
|
|
}
|
|
|
|
api_rate_limit {
|
|
resources = ["*"]
|
|
actions = ["list"]
|
|
per = "total"
|
|
limit = 20
|
|
period = "1m"
|
|
}
|
|
}`,
|
|
expLimits: ratelimit.Configs{
|
|
{
|
|
Resources: []string{"*"},
|
|
Actions: []string{"*"},
|
|
Per: "total",
|
|
Limit: 50,
|
|
PeriodHCL: "1m",
|
|
Period: time.Minute,
|
|
Unlimited: false,
|
|
},
|
|
{
|
|
Resources: []string{"*"},
|
|
Actions: []string{"list"},
|
|
Per: "total",
|
|
Limit: 20,
|
|
PeriodHCL: "1m",
|
|
Period: time.Minute,
|
|
Unlimited: false,
|
|
},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Multiple Rate limit with names",
|
|
in: `
|
|
controller {
|
|
api_rate_limit "default" {
|
|
resources = ["*"]
|
|
actions = ["*"]
|
|
per = "total"
|
|
limit = 50
|
|
period = "1m"
|
|
}
|
|
|
|
api_rate_limit "default-list" {
|
|
resources = ["*"]
|
|
actions = ["list"]
|
|
per = "total"
|
|
limit = 20
|
|
period = "1m"
|
|
}
|
|
}`,
|
|
expLimits: ratelimit.Configs{
|
|
{
|
|
Resources: []string{"*"},
|
|
Actions: []string{"*"},
|
|
Per: "total",
|
|
Limit: 50,
|
|
PeriodHCL: "1m",
|
|
Period: time.Minute,
|
|
Unlimited: false,
|
|
},
|
|
{
|
|
Resources: []string{"*"},
|
|
Actions: []string{"list"},
|
|
Per: "total",
|
|
Limit: 20,
|
|
PeriodHCL: "1m",
|
|
Period: time.Minute,
|
|
Unlimited: false,
|
|
},
|
|
},
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Multiple Rate limit with name and no name",
|
|
in: `
|
|
controller {
|
|
api_rate_limit {
|
|
resources = ["*"]
|
|
actions = ["*"]
|
|
per = "total"
|
|
limit = 50
|
|
period = "1m"
|
|
}
|
|
|
|
api_rate_limit "list" {
|
|
resources = ["*"]
|
|
actions = ["list"]
|
|
per = "total"
|
|
limit = 20
|
|
period = "1m"
|
|
}
|
|
}`,
|
|
expLimits: ratelimit.Configs{
|
|
{
|
|
Resources: []string{"*"},
|
|
Actions: []string{"*"},
|
|
Per: "total",
|
|
Limit: 50,
|
|
PeriodHCL: "1m",
|
|
Period: time.Minute,
|
|
Unlimited: false,
|
|
},
|
|
{
|
|
Resources: []string{"*"},
|
|
Actions: []string{"list"},
|
|
Per: "total",
|
|
Limit: 20,
|
|
PeriodHCL: "1m",
|
|
Period: time.Minute,
|
|
Unlimited: false,
|
|
},
|
|
},
|
|
expErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.Equal(t, tt.expLimits, c.Controller.ApiRateLimits)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWorkerDescription(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
envDescription string
|
|
expDescription string
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Valid worker description from env var",
|
|
in: `
|
|
worker {
|
|
description = "env://WORKER_DESCRIPTION"
|
|
}`,
|
|
envDescription: "Test worker description",
|
|
expDescription: "Test worker description",
|
|
expErr: false,
|
|
}, {
|
|
name: "Invalid worker description",
|
|
in: `
|
|
worker {
|
|
description = "\uTest worker description"
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "At 3:22: illegal char escape",
|
|
}, {
|
|
name: "Not a URL, non-printable description",
|
|
in: `
|
|
worker {
|
|
description = "\x00"
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Worker description contains non-printable characters",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv("WORKER_DESCRIPTION", tt.envDescription)
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Worker)
|
|
require.Equal(t, tt.expDescription, c.Worker.Description)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPluginExecutionDir(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
envPluginExecutionDir string
|
|
expPluginExecutionDir string
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Valid plugin execution dir from env var",
|
|
in: `
|
|
plugins {
|
|
execution_dir = "env://PLUGIN_EXEC_DIR"
|
|
}`,
|
|
envPluginExecutionDir: `/var/run/boundary/plugin-exec`,
|
|
expPluginExecutionDir: `/var/run/boundary/plugin-exec`,
|
|
expErr: false,
|
|
}, {
|
|
name: "Invalid plugin execution dir from env var",
|
|
in: `
|
|
plugins {
|
|
execution_dir ="\ubad plugin directory"
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "At 3:28: illegal char escape",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv("PLUGIN_EXEC_DIR", tt.envPluginExecutionDir)
|
|
p, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, p)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, p)
|
|
require.NotNil(t, p.Plugins)
|
|
require.Equal(t, tt.expPluginExecutionDir, p.Plugins.ExecutionDir)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDatabaseMaxConnections(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
envMaxOpenConnections string
|
|
expMaxOpenConnections int
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Valid integer value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_open_connections = 5
|
|
}
|
|
}`,
|
|
expMaxOpenConnections: 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Valid string value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_open_connections = "5"
|
|
}
|
|
}`,
|
|
expMaxOpenConnections: 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid value string",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_open_connections = "string bad"
|
|
}
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Database max open connections value is not an int: " +
|
|
"strconv.Atoi: parsing \"string bad\": invalid syntax",
|
|
},
|
|
{
|
|
name: "Invalid value type",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_open_connections = false
|
|
}
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Database max open connections: unsupported type \"bool\"",
|
|
},
|
|
{
|
|
name: "Valid env var",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_open_connections = "env://ENV_MAX_CONN"
|
|
}
|
|
}`,
|
|
expMaxOpenConnections: 8,
|
|
envMaxOpenConnections: "8",
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid env var",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_open_connections = "env://ENV_MAX_CONN"
|
|
}
|
|
}`,
|
|
envMaxOpenConnections: "bogus value",
|
|
expErr: true,
|
|
expErrStr: "Database max open connections value is not an int: " +
|
|
"strconv.Atoi: parsing \"bogus value\": invalid syntax",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv("ENV_MAX_CONN", tt.envMaxOpenConnections)
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.NotNil(t, c.Controller.Database)
|
|
require.Equal(t, tt.expMaxOpenConnections, c.Controller.Database.MaxOpenConnections)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDatabaseMaxIdleConnections(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
envMaxIdleConnections string
|
|
expMaxIdleConnections int
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Valid integer value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_connections = 5
|
|
}
|
|
}`,
|
|
expMaxIdleConnections: 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Valid integer string",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_connections = "5"
|
|
}
|
|
}`,
|
|
expMaxIdleConnections: 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid value string",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_connections = "string bad"
|
|
}
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Database max idle connections value is not a uint: " +
|
|
"strconv.Atoi: parsing \"string bad\": invalid syntax",
|
|
},
|
|
{
|
|
name: "Invalid value type",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_connections = false
|
|
}
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Database max idle connections: unsupported type \"bool\"",
|
|
},
|
|
{
|
|
name: "Valid env var",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_connections = "env://ENV_MAX_IDLE_CONN"
|
|
}
|
|
}`,
|
|
expMaxIdleConnections: 8,
|
|
envMaxIdleConnections: "8",
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid env var",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_connections = "env://ENV_MAX_IDLE_CONN"
|
|
}
|
|
}`,
|
|
envMaxIdleConnections: "bogus value",
|
|
expErr: true,
|
|
expErrStr: "Database max idle connections value is not a uint: " +
|
|
"strconv.Atoi: parsing \"bogus value\": invalid syntax",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv("ENV_MAX_IDLE_CONN", tt.envMaxIdleConnections)
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.NotNil(t, c.Controller.Database)
|
|
require.Equal(t, tt.expMaxIdleConnections, *c.Controller.Database.MaxIdleConnections)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDatabaseConnMaxIdleTimeDuration(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
envConnMaxIdleTimeDuration string
|
|
expConnMaxIdleTimeDuration time.Duration
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Valid duration value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_time = "5m"
|
|
}
|
|
}`,
|
|
expConnMaxIdleTimeDuration: time.Minute * 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Valid env var value",
|
|
envConnMaxIdleTimeDuration: "5m",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_time = "env://ENV_CONN_MAX_IDLE_TIME"
|
|
}
|
|
}`,
|
|
expConnMaxIdleTimeDuration: time.Minute * 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid value string",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
max_idle_time = "string bad"
|
|
}
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Connection max idle time is not a duration: " +
|
|
"strconv.ParseInt: parsing \"string ba\": invalid syntax",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv("ENV_CONN_MAX_IDLE_TIME", tt.envConnMaxIdleTimeDuration)
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.NotNil(t, c.Controller.Database)
|
|
require.Equal(t, tt.expConnMaxIdleTimeDuration, *c.Controller.Database.ConnMaxIdleTimeDuration)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDatabaseSkipSharedLockAcquisition(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
expSkipSharedLockAcquisition bool
|
|
}{
|
|
{
|
|
name: "not set",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
}
|
|
}`,
|
|
expSkipSharedLockAcquisition: false,
|
|
},
|
|
{
|
|
name: "set",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
database {
|
|
skip_shared_lock_acquisition = true
|
|
}
|
|
}`,
|
|
expSkipSharedLockAcquisition: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c, err := Parse(tt.in)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.NotNil(t, c.Controller.Database)
|
|
require.Equal(t, tt.expSkipSharedLockAcquisition, c.Controller.Database.SkipSharedLockAcquisition)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetupControllerPublicClusterAddress(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
inputConfig *Config
|
|
inputFlagValue string
|
|
stateFn func(t *testing.T)
|
|
expErr bool
|
|
expErrStr string
|
|
expPublicClusterAddress string
|
|
}{
|
|
{
|
|
name: "nil controller",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: nil,
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: ":9201",
|
|
},
|
|
{
|
|
name: "setting public cluster address directly with ipv4",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "127.0.0.1",
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "setting public cluster address directly with ipv4:port",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "127.0.0.1:8080",
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:8080",
|
|
},
|
|
{
|
|
name: "setting public cluster address directly with ipv6",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "2001:4860:4860:0:0:0:0:8888",
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "[2001:4860:4860::8888]:9201",
|
|
},
|
|
{
|
|
name: "setting public cluster address directly with ipv6:port",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "[2001:4860:4860:0:0:0:0:8888]:8080",
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "[2001:4860:4860::8888]:8080",
|
|
},
|
|
{
|
|
name: "setting public cluster address directly with abbreviated ipv6",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "2001:4860:4860::8888",
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "[2001:4860:4860::8888]:9201",
|
|
},
|
|
{
|
|
name: "setting public cluster address directly with abbreviated ipv6:port",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "[2001:4860:4860::8888]:8080",
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "[2001:4860:4860::8888]:8080",
|
|
},
|
|
{
|
|
name: "setting public cluster address to env var",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "env://TEST_ENV_VAR_FOR_CONTROLLER_ADDR",
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
stateFn: func(t *testing.T) {
|
|
t.Setenv("TEST_ENV_VAR_FOR_CONTROLLER_ADDR", "127.0.0.1:8080")
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:8080",
|
|
},
|
|
{
|
|
name: "setting public cluster address to env var that points to template",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "env://TEST_ENV_VAR_FOR_CONTROLLER_ADDR",
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
stateFn: func(t *testing.T) {
|
|
t.Setenv("TEST_ENV_VAR_FOR_CONTROLLER_ADDR", `{{ GetAllInterfaces | include "flags" "loopback" | include "type" "IPV4" | join "address" " " }}`)
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "setting public cluster address to ip template",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: `{{ GetAllInterfaces | include "flags" "loopback" | include "type" "IPV4" | join "address" " " }}`,
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "setting public cluster address to multiline ip template",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: `{{ with $local := GetAllInterfaces | include "flags" "loopback" | include "type" "IPV4" -}}
|
|
{{- $local | join "address" " " -}}
|
|
{{- end }}`,
|
|
},
|
|
},
|
|
inputFlagValue: "",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "using flag value with ip only",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: "127.0.0.1",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "using flag value with ip:port",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: "127.0.0.1:8080",
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:8080",
|
|
},
|
|
{
|
|
name: "using flag value with ip template",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: `{{ GetAllInterfaces | include "flags" "loopback" | include "type" "IPV4" | join "address" " " }}`,
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "using flag value with multiline ip template",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: `{{ with $local := GetAllInterfaces | include "flags" "loopback" | include "type" "IPV4" -}}
|
|
{{- $local | join "address" " " -}}
|
|
{{- end }}`,
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "using flag value to point to env var with ip only",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: "env://TEST_ENV_VAR_FOR_CONTROLLER_ADDR",
|
|
stateFn: func(t *testing.T) {
|
|
t.Setenv("TEST_ENV_VAR_FOR_CONTROLLER_ADDR", "127.0.0.1")
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "using flag value to point to env var with ip:port",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: "env://TEST_ENV_VAR_FOR_CONTROLLER_ADDR",
|
|
stateFn: func(t *testing.T) {
|
|
t.Setenv("TEST_ENV_VAR_FOR_CONTROLLER_ADDR", "127.0.0.1:8080")
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:8080",
|
|
},
|
|
{
|
|
name: "read address from listeners ipv4 only",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{Purpose: []string{"cluster"}, Address: "127.0.0.1"},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:9201",
|
|
},
|
|
{
|
|
name: "read address from listeners ipv4:port",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{Purpose: []string{"cluster"}, Address: "127.0.0.1:8080"},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "127.0.0.1:8080",
|
|
},
|
|
{
|
|
name: "read address from listeners ipv6 only",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{Purpose: []string{"cluster"}, Address: "2001:4860:4860:0:0:0:0:8888"},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "[2001:4860:4860::8888]:9201",
|
|
},
|
|
{
|
|
name: "read address from listeners ipv6:port",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{Purpose: []string{"cluster"}, Address: "[2001:4860:4860::8888]:8080"},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "[2001:4860:4860::8888]:8080",
|
|
},
|
|
{
|
|
name: "read address from listeners abbreviated ipv6 only",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{Purpose: []string{"cluster"}, Address: "2001:4860:4860::8888"},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "[2001:4860:4860::8888]:9201",
|
|
},
|
|
{
|
|
name: "read address from listeners abbreviated ipv6:port",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{Purpose: []string{"cluster"}, Address: "[2001:4860:4860::8888]:8080"},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: "[2001:4860:4860::8888]:8080",
|
|
},
|
|
{
|
|
name: "read address from listeners is ignored on different purpose",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{Purpose: []string{"somethingelse"}, Address: "127.0.0.1:8080"},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expPublicClusterAddress: ":9201",
|
|
},
|
|
{
|
|
name: "using flag value to point to nonexistent file",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: "file://this_doesnt_exist_for_sure",
|
|
expErr: true,
|
|
expErrStr: "Error parsing public cluster addr: error reading file at file://this_doesnt_exist_for_sure: open this_doesnt_exist_for_sure: no such file or directory",
|
|
expPublicClusterAddress: "",
|
|
},
|
|
{
|
|
name: "using flag value to provoke error in SplitHostPort",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: "abc::123:::",
|
|
expErr: true,
|
|
expErrStr: "Error splitting public cluster adddress host/port: too many colons in address",
|
|
expPublicClusterAddress: "",
|
|
},
|
|
{
|
|
name: "bad ip template",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
inputFlagValue: "{{ somethingthatdoesntexist }}",
|
|
expErr: true,
|
|
expErrStr: "Error parsing IP template on controller public cluster addr: unable to parse address template \"{{ somethingthatdoesntexist }}\": unable to parse template \"{{ somethingthatdoesntexist }}\": template: sockaddr.Parse:1: function \"somethingthatdoesntexist\" not defined",
|
|
expPublicClusterAddress: "",
|
|
},
|
|
{
|
|
name: "unix listener",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{Address: "someaddr", Type: "unix", Purpose: []string{"cluster"}},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
},
|
|
expPublicClusterAddress: "someaddr:9201",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.stateFn != nil {
|
|
tt.stateFn(t)
|
|
}
|
|
err := tt.inputConfig.SetupControllerPublicClusterAddress(tt.inputFlagValue)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, tt.inputConfig.Controller)
|
|
require.Equal(t, tt.expPublicClusterAddress, tt.inputConfig.Controller.PublicClusterAddr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetupWorkerInitialUpstreams(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
name string
|
|
inputConfig *Config
|
|
stateFn func(t *testing.T)
|
|
expErr bool
|
|
expErrStr string
|
|
expInitialUpstreams []string
|
|
}{
|
|
{
|
|
name: "NilController",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: nil,
|
|
Worker: &Worker{
|
|
InitialUpstreams: []string{"192.168.0.2:9201"},
|
|
},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"192.168.0.2:9201"},
|
|
},
|
|
{
|
|
name: "NilWorker",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "192.168.0.3:9201",
|
|
},
|
|
Worker: nil,
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: nil,
|
|
},
|
|
{
|
|
name: "ipv4 PublicClusterAddr",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "192.168.0.4:9201",
|
|
},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"192.168.0.4:9201"},
|
|
},
|
|
{
|
|
name: "ipv6 PublicClusterAddr",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "[2001:4860:4860:0:0:0:0:8888]:9201",
|
|
},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"[2001:4860:4860:0:0:0:0:8888]:9201"},
|
|
},
|
|
{
|
|
name: "abbreviated ipv6 PublicClusterAddr",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "[2001:4860:4860::8888]:9201",
|
|
},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"[2001:4860:4860::8888]:9201"},
|
|
},
|
|
{
|
|
name: "ListenerNoAddr",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Purpose: []string{"cluster"},
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"127.0.0.1:9201"},
|
|
},
|
|
{
|
|
name: "ipv4 ListenerAddr",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Purpose: []string{"cluster"},
|
|
Address: "192.168.0.5:9201",
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"192.168.0.5:9201"},
|
|
},
|
|
{
|
|
name: "ipv6 ListenerAddr",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Purpose: []string{"cluster"},
|
|
Address: "[2001:4860:4860:0:0:0:0:8888]:9201",
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"[2001:4860:4860:0:0:0:0:8888]:9201"},
|
|
},
|
|
{
|
|
name: "abbreviated ipv6 ListenerAddr",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Purpose: []string{"cluster"},
|
|
Address: "[2001:4860:4860::8888]:9201",
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"[2001:4860:4860::8888]:9201"},
|
|
},
|
|
{
|
|
name: "ListenerAddrDomain",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Purpose: []string{"cluster"},
|
|
Address: "foo.test",
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: false,
|
|
expErrStr: "",
|
|
expInitialUpstreams: []string{"foo.test"},
|
|
},
|
|
{
|
|
name: "ListenerAddrMultiplePurpose",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Purpose: []string{"cluster", "api"},
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: true,
|
|
expErrStr: "Specifying a listener with more than one purpose is not supported",
|
|
expInitialUpstreams: nil,
|
|
},
|
|
{
|
|
name: "ListenerAddrNoPurposes",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Purpose: []string{},
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
Worker: &Worker{},
|
|
},
|
|
expErr: true,
|
|
expErrStr: "Listener specified without a purpose",
|
|
expInitialUpstreams: nil,
|
|
},
|
|
{
|
|
name: "ListenerAddrMismatchAddress",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Purpose: []string{"cluster"},
|
|
Address: "192.168.0.5:9201",
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{},
|
|
Worker: &Worker{
|
|
InitialUpstreams: []string{"192.168.0.2:9201"},
|
|
},
|
|
},
|
|
expErr: true,
|
|
expErrStr: `When running a combined controller and worker, it's invalid to specify a "initial_upstreams" or "controllers" key in the worker block with any values other than the controller cluster or upstream worker address/port when using IPs rather than DNS names`,
|
|
expInitialUpstreams: nil,
|
|
},
|
|
{
|
|
name: "ClusterAddrMismatchAddress",
|
|
inputConfig: &Config{
|
|
SharedConfig: &configutil.SharedConfig{
|
|
Listeners: []*listenerutil.ListenerConfig{},
|
|
},
|
|
Controller: &Controller{
|
|
PublicClusterAddr: "192.168.0.3:9201",
|
|
},
|
|
Worker: &Worker{
|
|
InitialUpstreams: []string{"192.168.0.2:9201"},
|
|
},
|
|
},
|
|
expErr: true,
|
|
expErrStr: `When running a combined controller and worker, it's invalid to specify a "initial_upstreams" or "controllers" key in the worker block with any values other than the controller cluster or upstream worker address/port when using IPs rather than DNS names`,
|
|
expInitialUpstreams: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.stateFn != nil {
|
|
tt.stateFn(t)
|
|
}
|
|
err := tt.inputConfig.SetupWorkerInitialUpstreams()
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
if tt.inputConfig.Worker == nil {
|
|
require.Empty(t, tt.expInitialUpstreams)
|
|
} else {
|
|
require.ElementsMatch(t, tt.expInitialUpstreams, tt.inputConfig.Worker.InitialUpstreams)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetDownstreamWorkersTimeout(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
wantController bool
|
|
wantWorker bool
|
|
wantControllerTimeout time.Duration
|
|
wantWorkerTimeout time.Duration
|
|
assertErr func(*testing.T, error)
|
|
}{
|
|
{
|
|
name: "controller_valid_time_value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
get_downstream_workers_timeout = "10s"
|
|
}`,
|
|
wantControllerTimeout: 10 * time.Second,
|
|
wantWorkerTimeout: 0,
|
|
wantController: true,
|
|
wantWorker: false,
|
|
assertErr: nil,
|
|
},
|
|
{
|
|
name: "worker_valid_time_value",
|
|
in: `
|
|
worker {
|
|
name = "example-worker"
|
|
get_downstream_workers_timeout = "5s"
|
|
}`,
|
|
wantControllerTimeout: 0,
|
|
wantWorkerTimeout: 5 * time.Second,
|
|
wantController: false,
|
|
wantWorker: true,
|
|
assertErr: nil,
|
|
},
|
|
{
|
|
name: "both_valid_time_value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
get_downstream_workers_timeout = "5s"
|
|
}
|
|
worker {
|
|
name = "example-worker"
|
|
get_downstream_workers_timeout = "500ms"
|
|
}`,
|
|
wantControllerTimeout: 5 * time.Second,
|
|
wantWorkerTimeout: 500 * time.Millisecond,
|
|
wantController: true,
|
|
wantWorker: true,
|
|
assertErr: nil,
|
|
},
|
|
{
|
|
name: "both_unspecified_defaults_to_zero",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
}
|
|
worker {
|
|
name = "example-worker"
|
|
}`,
|
|
wantController: true,
|
|
wantWorker: true,
|
|
wantControllerTimeout: 0,
|
|
wantWorkerTimeout: 0,
|
|
assertErr: nil,
|
|
},
|
|
{
|
|
name: "controller_int_value_no_unit_assumes_seconds",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
get_downstream_workers_timeout = 100
|
|
}`,
|
|
wantController: true,
|
|
wantWorker: false,
|
|
wantControllerTimeout: 100 * time.Second,
|
|
wantWorkerTimeout: 0,
|
|
},
|
|
{
|
|
name: "worker_int_value_no_unit_assumes_seconds",
|
|
in: `
|
|
worker {
|
|
name = "example-worker"
|
|
get_downstream_workers_timeout = 30
|
|
}`,
|
|
wantController: false,
|
|
wantWorker: true,
|
|
wantWorkerTimeout: 30 * time.Second,
|
|
},
|
|
{
|
|
name: "controller_invalid_bool_value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
get_downstream_workers_timeout = true
|
|
}`,
|
|
wantController: true,
|
|
wantWorker: false,
|
|
assertErr: func(t *testing.T, err error) {
|
|
require.Error(t, err)
|
|
require.ErrorContains(t, err, `error trying to parse controller get_downstream_workers_timeout`)
|
|
},
|
|
},
|
|
{
|
|
name: "worker_invalid_bool_value",
|
|
in: `
|
|
worker {
|
|
name = "example-worker"
|
|
get_downstream_workers_timeout = false
|
|
}`,
|
|
wantController: false,
|
|
wantWorker: true,
|
|
assertErr: func(t *testing.T, err error) {
|
|
require.Error(t, err)
|
|
require.ErrorContains(t, err, `error trying to parse worker get_downstream_workers_timeout`)
|
|
},
|
|
},
|
|
{
|
|
name: "controller_invalid_empty_value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
get_downstream_workers_timeout = ""
|
|
}`,
|
|
wantController: true,
|
|
wantWorker: false,
|
|
wantControllerTimeout: 0,
|
|
},
|
|
{
|
|
name: "worker_invalid_empty_value",
|
|
in: `
|
|
worker {
|
|
name = "example-worker"
|
|
get_downstream_workers_timeout = ""
|
|
}`,
|
|
wantController: false,
|
|
wantWorker: true,
|
|
wantWorkerTimeout: 0,
|
|
},
|
|
{
|
|
name: "controller_invalid_zero_value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
get_downstream_workers_timeout = "0s"
|
|
}`,
|
|
wantController: true,
|
|
wantWorker: false,
|
|
wantControllerTimeout: 0,
|
|
},
|
|
{
|
|
name: "worker_invalid_zero_value",
|
|
in: `
|
|
worker {
|
|
name = "example-worker"
|
|
get_downstream_workers_timeout = "0s"
|
|
}`,
|
|
wantController: false,
|
|
wantWorker: true,
|
|
wantWorkerTimeout: 0,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c, err := Parse(tt.in)
|
|
if tt.assertErr != nil {
|
|
tt.assertErr(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
if tt.wantController {
|
|
require.NotNil(t, c.Controller)
|
|
require.Equal(t, tt.wantControllerTimeout, c.Controller.GetDownstreamWorkersTimeoutDuration)
|
|
}
|
|
if tt.wantWorker {
|
|
require.NotNil(t, c.Worker)
|
|
require.Equal(t, tt.wantWorkerTimeout, c.Worker.GetDownstreamWorkersTimeoutDuration)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMaxPageSize(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
envMaxPageSize string
|
|
expMaxPageSize uint
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Valid integer value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
max_page_size = 5
|
|
}`,
|
|
expMaxPageSize: 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Valid string value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
max_page_size = "5"
|
|
}`,
|
|
expMaxPageSize: 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid value integer",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
max_page_size = 0
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Max page size value must be at least 1, was 0",
|
|
},
|
|
{
|
|
name: "Invalid value string",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
max_page_size = "string bad"
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Max page size value is not an int: " +
|
|
"strconv.Atoi: parsing \"string bad\": invalid syntax",
|
|
},
|
|
{
|
|
name: "Invalid value type",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
max_page_size = false
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Max page size: unsupported type \"bool\"",
|
|
},
|
|
{
|
|
name: "Valid env var",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
max_page_size = "env://ENV_MAX_PAGE_SIZE"
|
|
}`,
|
|
expMaxPageSize: 8,
|
|
envMaxPageSize: "8",
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid env var",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
max_page_size = "env://ENV_MAX_PAGE_SIZE"
|
|
}`,
|
|
envMaxPageSize: "bogus value",
|
|
expErr: true,
|
|
expErrStr: "Max page size value is not an int: " +
|
|
"strconv.Atoi: parsing \"bogus value\": invalid syntax",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv("ENV_MAX_PAGE_SIZE", tt.envMaxPageSize)
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.Equal(t, tt.expMaxPageSize, c.Controller.MaxPageSize)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConcurrentPasswordHashWorkers(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
envConcurrentPasswordHashWorkers string
|
|
expConcurrentPasswordHashWorkers uint
|
|
expErr bool
|
|
expErrStr string
|
|
}{
|
|
{
|
|
name: "Valid integer value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = 5
|
|
}`,
|
|
expConcurrentPasswordHashWorkers: 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Valid string value",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = "5"
|
|
}`,
|
|
expConcurrentPasswordHashWorkers: 5,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid value integer",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = 0
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Concurrent password hash workers value must be at least 1, was 0",
|
|
},
|
|
{
|
|
name: "Invalid value string",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = "string bad"
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Concurrent password hash workers value is not an int: " +
|
|
"strconv.Atoi: parsing \"string bad\": invalid syntax",
|
|
},
|
|
{
|
|
name: "Invalid value string integer",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = "-1"
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Concurrent password hash workers value must be at least 1, was -1",
|
|
},
|
|
{
|
|
name: "Invalid value type",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = false
|
|
}`,
|
|
expErr: true,
|
|
expErrStr: "Concurrent password hash workers: unsupported type \"bool\"",
|
|
},
|
|
{
|
|
name: "Valid env var",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = "env://ENV_MAX_PW_WORKERS"
|
|
}`,
|
|
expConcurrentPasswordHashWorkers: 8,
|
|
envConcurrentPasswordHashWorkers: "8",
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Invalid env var",
|
|
in: `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = "env://ENV_MAX_PW_WORKERS"
|
|
}`,
|
|
envConcurrentPasswordHashWorkers: "bogus value",
|
|
expErr: true,
|
|
expErrStr: "Concurrent password hash workers value is not an int: " +
|
|
"strconv.Atoi: parsing \"bogus value\": invalid syntax",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv("ENV_MAX_PW_WORKERS", tt.envConcurrentPasswordHashWorkers)
|
|
c, err := Parse(tt.in)
|
|
if tt.expErr {
|
|
require.EqualError(t, err, tt.expErrStr)
|
|
require.Nil(t, c)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.Equal(t, tt.expConcurrentPasswordHashWorkers, c.Controller.ConcurrentPasswordHashWorkers)
|
|
})
|
|
}
|
|
|
|
t.Run("using environment variable", func(t *testing.T) {
|
|
t.Setenv("BOUNDARY_CONTROLLER_CONCURRENT_PASSWORD_HASH_WORKERS", "2")
|
|
in := `
|
|
controller {
|
|
name = "example-controller"
|
|
}`
|
|
c, err := Parse(in)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.EqualValues(t, 2, c.Controller.ConcurrentPasswordHashWorkers)
|
|
})
|
|
|
|
t.Run("using environment variable with invalid value", func(t *testing.T) {
|
|
t.Setenv("BOUNDARY_CONTROLLER_CONCURRENT_PASSWORD_HASH_WORKERS", "invalid")
|
|
in := `
|
|
controller {
|
|
name = "example-controller"
|
|
}`
|
|
c, err := Parse(in)
|
|
require.Error(t, err)
|
|
require.Nil(t, c)
|
|
require.Contains(t, err.Error(), "BOUNDARY_CONTROLLER_CONCURRENT_PASSWORD_HASH_WORKERS value is not an int")
|
|
})
|
|
|
|
t.Run("using environment variable and config value uses config value", func(t *testing.T) {
|
|
t.Setenv("BOUNDARY_CONTROLLER_CONCURRENT_PASSWORD_HASH_WORKERS", "2")
|
|
in := `
|
|
controller {
|
|
name = "example-controller"
|
|
concurrent_password_hash_workers = 3
|
|
}`
|
|
c, err := Parse(in)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, c)
|
|
require.NotNil(t, c.Controller)
|
|
require.EqualValues(t, 3, c.Controller.ConcurrentPasswordHashWorkers)
|
|
})
|
|
}
|