From 69daa2debd483d1f4107f262a402ca8e93811bea Mon Sep 17 00:00:00 2001 From: David Teutli Date: Tue, 6 Jan 2026 16:49:08 -0700 Subject: [PATCH 1/3] feat: add option to override placementStrategy for bootstrap command --- cmd/topicctl/subcmd/bootstrap.go | 11 ++++++++++- pkg/cli/cli.go | 7 +++++++ pkg/config/topic.go | 3 ++- pkg/config/topic_test.go | 1 + pkg/version/version.go | 2 +- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/cmd/topicctl/subcmd/bootstrap.go b/cmd/topicctl/subcmd/bootstrap.go index 8b090bdd..4a25c368 100644 --- a/cmd/topicctl/subcmd/bootstrap.go +++ b/cmd/topicctl/subcmd/bootstrap.go @@ -21,6 +21,7 @@ type bootstrapCmdConfig struct { excludeRegexp string outputDir string overwrite bool + placementStrategyOverwrite config.PlacementStrategy allowInternalTopics bool @@ -59,7 +60,14 @@ func init() { &bootstrapConfig.allowInternalTopics, "allow-internal-topics", false, - "Include topics that start with __ (typically these are internal topics)") + "Include topics that start with __ (typically these are internal topics)", + ) + bootstrapCmd.Flags().StringVar( + (*string)(&bootstrapConfig.placementStrategyOverwrite), + "placement-strategy-overwrite", + "cross-rack", + "Provide a placementStrategy to overwrite the default value of cross-rack", + ) addSharedConfigOnlyFlags(bootstrapCmd, &bootstrapConfig.shared) bootstrapCmd.MarkFlagRequired("cluster-config") @@ -101,5 +109,6 @@ func bootstrapRun(cmd *cobra.Command, args []string) error { bootstrapConfig.outputDir, bootstrapConfig.overwrite, bootstrapConfig.allowInternalTopics, + bootstrapConfig.placementStrategyOverwrite, ) } diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index a60a1208..2af77d8e 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -210,6 +210,7 @@ func (c *CLIRunner) BootstrapTopics( outputDir string, overwrite bool, allowInternalTopics bool, + placementStrategyOverwrite ...config.PlacementStrategy, ) error { topicInfoObjs, err := c.adminClient.GetTopics(ctx, topics, false) if err != nil { @@ -225,6 +226,11 @@ func (c *CLIRunner) BootstrapTopics( return err } + placementStrategy := config.PlacementStrategyCrossRack + if len(placementStrategyOverwrite) > 0 { + placementStrategy = placementStrategyOverwrite[0] + } + topicConfigs := []config.TopicConfig{} for _, topicInfo := range topicInfoObjs { @@ -240,6 +246,7 @@ func (c *CLIRunner) BootstrapTopics( topicConfig := config.TopicConfigFromTopicInfo( clusterConfig, topicInfo, + placementStrategy, ) topicConfigs = append(topicConfigs, topicConfig) } diff --git a/pkg/config/topic.go b/pkg/config/topic.go index 370b877e..2fdf955d 100644 --- a/pkg/config/topic.go +++ b/pkg/config/topic.go @@ -313,6 +313,7 @@ func (t TopicConfig) ToYAML() (string, error) { func TopicConfigFromTopicInfo( clusterConfig ClusterConfig, topicInfo admin.TopicInfo, + placementStrategy PlacementStrategy, ) TopicConfig { topicConfig := TopicConfig{ Meta: ResourceMeta{ @@ -326,7 +327,7 @@ func TopicConfigFromTopicInfo( Partitions: len(topicInfo.Partitions), ReplicationFactor: len(topicInfo.Partitions[0].Replicas), PlacementConfig: TopicPlacementConfig{ - Strategy: PlacementStrategyAny, + Strategy: placementStrategy, }, }, } diff --git a/pkg/config/topic_test.go b/pkg/config/topic_test.go index 764010d8..f4135ab2 100644 --- a/pkg/config/topic_test.go +++ b/pkg/config/topic_test.go @@ -481,6 +481,7 @@ func TestTopicConfigFromTopicInfo(t *testing.T) { topicConfig := TopicConfigFromTopicInfo( testCase.clusterConfig, testCase.topicInfo, + "any", ) assert.Equal(t, testCase.expTopicConfig, topicConfig) } diff --git a/pkg/version/version.go b/pkg/version/version.go index f2857ccb..81f0f7a1 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,4 +1,4 @@ package version // Version is the current topicctl version. -const Version = "1.23.1" +const Version = "1.24.0" From dc351da22020de95291cdfc0f3d8470a6bdd22b8 Mon Sep 17 00:00:00 2001 From: David Teutli Date: Wed, 7 Jan 2026 08:13:33 -0700 Subject: [PATCH 2/3] chore: update README and bump version --- README.md | 4 ++++ pkg/version/version.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0dcd7731..ac9ddede 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,10 @@ The `bootstrap` subcommand creates apply topic configs from the existing topics cluster. This can be used to "import" topics not created or previously managed by topicctl. The output can be sent to either a directory (if the `--output` flag is set) or `stdout`. +The placement strategy for the bootstrapped topic configs will default to `cross-rack`. +This can be overwritten by setting the `--placement-strategy-overwrite` flag to any of the +values mentioned in the Placement strategies section. + By default, this does not include internal topics such as `__consumer_offsets`. If you would like to have these topics included, pass the `--allow-internal-topics` flag. diff --git a/pkg/version/version.go b/pkg/version/version.go index 81f0f7a1..8d061ec6 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,4 +1,4 @@ package version // Version is the current topicctl version. -const Version = "1.24.0" +const Version = "2.0.0" From 3054a440a711243ec523b5175aedd4457be9be00 Mon Sep 17 00:00:00 2001 From: David Teutli Date: Wed, 7 Jan 2026 10:08:39 -0700 Subject: [PATCH 3/3] chore: change placement-straegy-overwrite flag to placement-stragy --- README.md | 5 ++--- cmd/topicctl/subcmd/bootstrap.go | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ac9ddede..8f5d651b 100644 --- a/README.md +++ b/README.md @@ -145,9 +145,8 @@ The `bootstrap` subcommand creates apply topic configs from the existing topics cluster. This can be used to "import" topics not created or previously managed by topicctl. The output can be sent to either a directory (if the `--output` flag is set) or `stdout`. -The placement strategy for the bootstrapped topic configs will default to `cross-rack`. -This can be overwritten by setting the `--placement-strategy-overwrite` flag to any of the -values mentioned in the Placement strategies section. +The placement strategy for the bootstrapped topic configs will default to `cross-rack` +unless a different one is set via the `--placement-strategy` flag. By default, this does not include internal topics such as `__consumer_offsets`. If you would like to have these topics included, diff --git a/cmd/topicctl/subcmd/bootstrap.go b/cmd/topicctl/subcmd/bootstrap.go index 4a25c368..e7d4ed3a 100644 --- a/cmd/topicctl/subcmd/bootstrap.go +++ b/cmd/topicctl/subcmd/bootstrap.go @@ -21,7 +21,7 @@ type bootstrapCmdConfig struct { excludeRegexp string outputDir string overwrite bool - placementStrategyOverwrite config.PlacementStrategy + placementStrategy config.PlacementStrategy allowInternalTopics bool @@ -63,8 +63,8 @@ func init() { "Include topics that start with __ (typically these are internal topics)", ) bootstrapCmd.Flags().StringVar( - (*string)(&bootstrapConfig.placementStrategyOverwrite), - "placement-strategy-overwrite", + (*string)(&bootstrapConfig.placementStrategy), + "placement-strategy", "cross-rack", "Provide a placementStrategy to overwrite the default value of cross-rack", ) @@ -109,6 +109,6 @@ func bootstrapRun(cmd *cobra.Command, args []string) error { bootstrapConfig.outputDir, bootstrapConfig.overwrite, bootstrapConfig.allowInternalTopics, - bootstrapConfig.placementStrategyOverwrite, + bootstrapConfig.placementStrategy, ) }