Support external plugins in NewTestDockerCluster (#11023) (#11035)

This commit is contained in:
Vault Automation 2025-11-28 16:37:26 -05:00 committed by GitHub
parent 91a9b23651
commit 4e2f3ba489
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 72 additions and 1 deletions

3
changelog/_11023.txt Normal file
View file

@ -0,0 +1,3 @@
```release-note:improvement
sdk: Add NewTestDockerCluster support for running external plugins within the same container as the server. Also add support for those plugins to expose their own listeners, as KMIP does.
```

View file

@ -498,6 +498,7 @@ type DockerClusterNode struct {
DataVolumeName string
cleanupVolume func()
AllClients []*api.Client
ExtraAddrs []string
}
func (n *DockerClusterNode) TLSConfig() *tls.Config {
@ -699,6 +700,11 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption
ports = append(ports, portStr)
}
}
if opts.VaultNodeConfig != nil {
for _, portNo := range opts.VaultNodeConfig.AdditionalTCPPorts {
ports = append(ports, fmt.Sprintf("%d/tcp", portNo))
}
}
vaultCfg["listener"] = listenerConfig
vaultCfg["telemetry"] = map[string]interface{}{
"disable_hostname": true,
@ -934,7 +940,11 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption
n.AllClients = append(n.AllClients, client)
for _, addr := range svc.StartResult.Addrs[2:] {
end := len(svc.StartResult.Addrs)
if opts.VaultNodeConfig != nil {
end = 2 + len(opts.VaultNodeConfig.AdditionalListeners)
}
for _, addr := range svc.StartResult.Addrs[2:end] {
// The second element of this list of addresses is the cluster address
// We do not want to create a client for the cluster address mapping
client, err := n.newAPIClientForAddress(addr)
@ -944,6 +954,9 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption
client.SetToken(n.Cluster.rootToken)
n.AllClients = append(n.AllClients, client)
}
if len(svc.StartResult.Addrs) > end {
n.ExtraAddrs = svc.StartResult.Addrs[end:]
}
return nil
}
@ -1254,12 +1267,65 @@ func (dc *DockerCluster) addNode(ctx context.Context, opts *DockerClusterOptions
if err := os.MkdirAll(node.WorkDir, 0o755); err != nil {
return err
}
if err := copyDirContents(node.WorkDir, dc.tmpDir); err != nil {
return err
}
if err := node.Start(ctx, opts); err != nil {
return err
}
return nil
}
func copyFile(to string, from string) error {
in, err := os.Open(from)
if err != nil {
return fmt.Errorf("failed to open source file %s: %w", from, err)
}
defer in.Close()
out, err := os.Create(to)
if err != nil {
return fmt.Errorf("failed to create destination file %s: %w", to, err)
}
defer out.Close()
_, err = io.Copy(out, in)
if err != nil {
return fmt.Errorf("failed to copy file content from %s to %s: %w", from, to, err)
}
// Copy file permissions
info, err := os.Stat(from)
if err != nil {
return fmt.Errorf("failed to get source file info %s: %w", from, err)
}
err = os.Chmod(to, info.Mode())
if err != nil {
return fmt.Errorf("failed to set destination file permissions %s: %w", to, err)
}
return nil
}
func copyDirContents(to string, from string) error {
entries, err := os.ReadDir(from)
if err != nil {
return fmt.Errorf("failed to read source directory %s: %w", from, err)
}
for _, entry := range entries {
fromPath := filepath.Join(from, entry.Name())
toPath := filepath.Join(to, entry.Name())
if !entry.IsDir() {
if err = copyFile(toPath, fromPath); err != nil {
return err
}
}
}
return nil
}
func (dc *DockerCluster) joinNode(ctx context.Context, nodeIdx int, leaderIdx int) error {
if dc.storage != nil && dc.storage.Type() != "raft" {
// Storage is not raft so nothing to do but unseal.

View file

@ -56,6 +56,7 @@ type VaultNodeConfig struct {
StorageOptions map[string]string `json:"-"`
AdditionalListeners []VaultNodeListenerConfig `json:"-"`
AdditionalTCPPorts []int `json:"-"`
DefaultMaxRequestDuration time.Duration `json:"default_max_request_duration"`
LogFormat string `json:"log_format"`
@ -67,6 +68,7 @@ type VaultNodeConfig struct {
MaxLeaseTTL time.Duration `json:"max_lease_ttl"`
DefaultLeaseTTL time.Duration `json:"default_lease_ttl"`
ClusterCipherSuites string `json:"cluster_cipher_suites"`
PluginDirectory string `json:"plugin_directory"`
PluginFileUid int `json:"plugin_file_uid"`
PluginFilePermissions int `json:"plugin_file_permissions"`
EnableRawEndpoint bool `json:"raw_storage_endpoint"`