Skip to content

Commit

Permalink
Redpanda Module: Add option for arbitrary bootstrap config (#2666)
Browse files Browse the repository at this point in the history
WithBootstrapConfig adds an arbitrary config kvp to the Redpanda container.
Per the name, this config will be interpolated into the generated bootstrap
config file, which is particularly useful for configs requiring a restart
when otherwise applied to a running Redpanda instance.

Includes a test that sets a couple of restart-requiring cluster configs and
checks a) that the values are reflected in the config state at run time AND
b) that the cluster does not need a restart. (b) demonstrates that the configs
were bootstrapped rather than applied to a live cluster.

Signed-off-by: Oren Leiman <[email protected]>
  • Loading branch information
oleiman authored Aug 8, 2024
1 parent db119f6 commit 81007d6
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 0 deletions.
2 changes: 2 additions & 0 deletions modules/redpanda/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ func ExampleRun() {
redpanda.WithEnableSASL(),
redpanda.WithEnableKafkaAuthorization(),
redpanda.WithEnableWasmTransform(),
redpanda.WithBootstrapConfig("data_transforms_per_core_memory_reservation", 33554432),
redpanda.WithBootstrapConfig("data_transforms_per_function_memory_limit", 16777216),
redpanda.WithNewServiceAccount("superuser-1", "test"),
redpanda.WithNewServiceAccount("superuser-2", "test"),
redpanda.WithNewServiceAccount("no-superuser", "test"),
Expand Down
5 changes: 5 additions & 0 deletions modules/redpanda/mounts/bootstrap.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ data_transforms_enabled: true
{{- if .AutoCreateTopics }}
auto_create_topics_enabled: true
{{- end }}

{{- range $key, $value := .ExtraBootstrapConfig }}
{{ $key }}: {{ $value }}
{{- end }}

15 changes: 15 additions & 0 deletions modules/redpanda/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ type options struct {
// Listeners is a list of custom listeners that can be provided to access the
// containers form within docker networks
Listeners []listener

// ExtraBootstrapConfig is a map of configs to be interpolated into the
// container's bootstrap.yml
ExtraBootstrapConfig map[string]any
}

func defaultOptions() options {
Expand All @@ -55,6 +59,7 @@ func defaultOptions() options {
AutoCreateTopics: false,
EnableTLS: false,
Listeners: make([]listener, 0),
ExtraBootstrapConfig: make(map[string]any, 0),
}
}

Expand Down Expand Up @@ -155,3 +160,13 @@ func WithListener(lis string) Option {
})
}
}

// WithBootstrapConfig adds an arbitrary config kvp to the Redpanda container.
// Per the name, this config will be interpolated into the generated bootstrap
// config file, which is particularly useful for configs requiring a restart
// when otherwise applied to a running Redpanda instance.
func WithBootstrapConfig(cfg string, val any) Option {
return func(o *options) {
o.ExtraBootstrapConfig[cfg] = val
}
}
2 changes: 2 additions & 0 deletions modules/redpanda/redpanda.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ func renderBootstrapConfig(settings options) ([]byte, error) {
KafkaAPIEnableAuthorization: settings.KafkaEnableAuthorization,
AutoCreateTopics: settings.AutoCreateTopics,
EnableWasmTransform: settings.EnableWasmTransform,
ExtraBootstrapConfig: settings.ExtraBootstrapConfig,
}

tpl, err := template.New("bootstrap.yaml").Parse(bootstrapConfigTpl)
Expand Down Expand Up @@ -355,6 +356,7 @@ type redpandaBootstrapConfigTplParams struct {
KafkaAPIEnableAuthorization bool
AutoCreateTopics bool
EnableWasmTransform bool
ExtraBootstrapConfig map[string]any
}

type redpandaConfigTplParams struct {
Expand Down
56 changes: 56 additions & 0 deletions modules/redpanda/redpanda_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package redpanda_test

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
Expand Down Expand Up @@ -573,3 +574,58 @@ func TestRedpandaListener_NoNetwork(t *testing.T) {

require.Contains(t, err.Error(), "container must be attached to at least one network")
}

func TestRedpandaBootstrapConfig(t *testing.T) {
ctx := context.Background()

container, err := redpanda.RunContainer(ctx,
redpanda.WithEnableWasmTransform(),
// These configs would require a restart if applied to a live Redpanda instance
redpanda.WithBootstrapConfig("data_transforms_per_core_memory_reservation", 33554432),
redpanda.WithBootstrapConfig("data_transforms_per_function_memory_limit", 16777216),
)
require.NoError(t, err)

httpCl := &http.Client{
Timeout: 5 * time.Second,
Transport: &http.Transport{
ForceAttemptHTTP2: true,
TLSHandshakeTimeout: 10 * time.Second,
},
}
adminAPIUrl, err := container.AdminAPIAddress(ctx)
require.NoError(t, err)

{
// Check that the configs reflect specified values
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster_config", adminAPIUrl), nil)
require.NoError(t, err)
resp, err := httpCl.Do(req)
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode)
var data map[string]any
err = json.NewDecoder(resp.Body).Decode(&data)
require.NoError(t, err)
reservation := int(data["data_transforms_per_core_memory_reservation"].(float64))
require.Equal(t, 33554432, reservation)
pf_limit := int(data["data_transforms_per_function_memory_limit"].(float64))
require.Equal(t, 16777216, pf_limit)
}

{
// Check that no restart is required. i.e. that the configs were applied via bootstrap config
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster_config/status", adminAPIUrl), nil)
require.NoError(t, err)
resp, err := httpCl.Do(req)
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode)
var data []map[string]any
err = json.NewDecoder(resp.Body).Decode(&data)
require.NoError(t, err)
require.Len(t, data, 1)
needs_restart := data[0]["restart"].(bool)
require.False(t, needs_restart)
}
}

0 comments on commit 81007d6

Please sign in to comment.