18
18
package kafka .admin
19
19
20
20
import java .nio .charset .StandardCharsets
21
- import java .util .concurrent .TimeUnit
21
+ import java .util .concurrent .{ ExecutionException , TimeUnit }
22
22
import java .util .{Collections , Properties }
23
23
import joptsimple ._
24
24
import kafka .server .DynamicConfig
25
25
import kafka .utils .Implicits ._
26
26
import kafka .utils .Logging
27
- import org .apache .kafka .clients .admin .{Admin , AlterClientQuotasOptions , AlterConfigOp , AlterConfigsOptions , ConfigEntry , DescribeClusterOptions , DescribeConfigsOptions , ListTopicsOptions , ScramCredentialInfo , UserScramCredentialDeletion , UserScramCredentialUpsertion , Config => JConfig , ScramMechanism => PublicScramMechanism }
27
+ import org .apache .kafka .clients .admin .{Admin , AlterClientQuotasOptions , AlterConfigOp , AlterConfigsOptions , ConfigEntry , DescribeClusterOptions , DescribeConfigsOptions , ListTopicsOptions , ScramCredentialInfo , UserScramCredentialDeletion , UserScramCredentialUpsertion , ScramMechanism => PublicScramMechanism }
28
28
import org .apache .kafka .common .config .{ConfigResource , TopicConfig }
29
- import org .apache .kafka .common .errors .InvalidConfigurationException
29
+ import org .apache .kafka .common .errors .{ InvalidConfigurationException , UnsupportedVersionException }
30
30
import org .apache .kafka .common .internals .Topic
31
+ import org .apache .kafka .common .protocol .ApiKeys
31
32
import org .apache .kafka .common .quota .{ClientQuotaAlteration , ClientQuotaEntity , ClientQuotaFilter , ClientQuotaFilterComponent }
32
33
import org .apache .kafka .common .security .scram .internals .ScramMechanism
33
34
import org .apache .kafka .common .utils .{Exit , Utils }
34
35
import org .apache .kafka .server .config .{ConfigType , QuotaConfig }
35
36
import org .apache .kafka .server .util .{CommandDefaultOptions , CommandLineUtils }
36
37
import org .apache .kafka .storage .internals .log .LogConfig
38
+
37
39
import scala .annotation .nowarn
38
40
import scala .jdk .CollectionConverters ._
39
41
import scala .collection ._
@@ -80,6 +82,11 @@ object ConfigCommand extends Logging {
80
82
System .err.println(e.getMessage)
81
83
Exit .exit(1 )
82
84
85
+ case e : UnsupportedVersionException =>
86
+ logger.debug(s " Unsupported API encountered in server when executing config command with args ' ${args.mkString(" " )}' " )
87
+ System .err.println(e.getMessage)
88
+ Exit .exit(1 )
89
+
83
90
case t : Throwable =>
84
91
logger.debug(s " Error while executing config command with args ' ${args.mkString(" " )}' " , t)
85
92
System .err.println(s " Error while executing config command with args ' ${args.mkString(" " )}' " )
@@ -161,7 +168,6 @@ object ConfigCommand extends Logging {
161
168
}
162
169
}
163
170
164
- @ nowarn(" cat=deprecation" )
165
171
def alterConfig (adminClient : Admin , opts : ConfigCommandOptions ): Unit = {
166
172
val entityTypes = opts.entityTypes
167
173
val entityNames = opts.entityNames
@@ -172,27 +178,25 @@ object ConfigCommand extends Logging {
172
178
val configsToBeDeleted = parseConfigsToBeDeleted(opts)
173
179
174
180
entityTypeHead match {
175
- case ConfigType .TOPIC =>
176
- alterResourceConfig(adminClient, entityTypeHead, entityNameHead, configsToBeDeleted, configsToBeAdded, ConfigResource .Type .TOPIC )
177
-
178
- case ConfigType .BROKER =>
179
- val oldConfig = getResourceConfig(adminClient, entityTypeHead, entityNameHead, includeSynonyms = false , describeAll = false )
180
- .map { entry => (entry.name, entry) }.toMap
181
-
182
- // fail the command if any of the configs to be deleted does not exist
183
- val invalidConfigs = configsToBeDeleted.filterNot(oldConfig.contains)
184
- if (invalidConfigs.nonEmpty)
185
- throw new InvalidConfigurationException (s " Invalid config(s): ${invalidConfigs.mkString(" ," )}" )
186
-
187
- val newEntries = oldConfig ++ configsToBeAdded -- configsToBeDeleted
188
- val sensitiveEntries = newEntries.filter(_._2.value == null )
189
- if (sensitiveEntries.nonEmpty)
190
- throw new InvalidConfigurationException (s " All sensitive broker config entries must be specified for --alter, missing entries: ${sensitiveEntries.keySet}" )
191
- val newConfig = new JConfig (newEntries.asJava.values)
192
-
193
- val configResource = new ConfigResource (ConfigResource .Type .BROKER , entityNameHead)
194
- val alterOptions = new AlterConfigsOptions ().timeoutMs(30000 ).validateOnly(false )
195
- adminClient.alterConfigs(Map (configResource -> newConfig).asJava, alterOptions).all().get(60 , TimeUnit .SECONDS )
181
+ case ConfigType .TOPIC | ConfigType .CLIENT_METRICS | ConfigType .BROKER | ConfigType .GROUP =>
182
+ val configResourceType = entityTypeHead match {
183
+ case ConfigType .TOPIC => ConfigResource .Type .TOPIC
184
+ case ConfigType .CLIENT_METRICS => ConfigResource .Type .CLIENT_METRICS
185
+ case ConfigType .BROKER => ConfigResource .Type .BROKER
186
+ case ConfigType .GROUP => ConfigResource .Type .GROUP
187
+ }
188
+ try {
189
+ alterResourceConfig(adminClient, entityTypeHead, entityNameHead, configsToBeDeleted, configsToBeAdded, configResourceType)
190
+ } catch {
191
+ case e : ExecutionException =>
192
+ e.getCause match {
193
+ case _ : UnsupportedVersionException =>
194
+ throw new UnsupportedVersionException (s " The ${ApiKeys .INCREMENTAL_ALTER_CONFIGS } API is not supported by the cluster. The API is supported starting from version 2.3.0. "
195
+ + " You may want to use an older version of this tool to interact with your cluster, or upgrade your brokers to version 2.3.0 or newer to avoid this error." )
196
+ case _ => throw e
197
+ }
198
+ case e : Throwable => throw e
199
+ }
196
200
197
201
case BrokerLoggerConfigType =>
198
202
val validLoggers = getResourceConfig(adminClient, entityTypeHead, entityNameHead, includeSynonyms = true , describeAll = false ).map(_.name)
@@ -203,10 +207,10 @@ object ConfigCommand extends Logging {
203
207
204
208
val configResource = new ConfigResource (ConfigResource .Type .BROKER_LOGGER , entityNameHead)
205
209
val alterOptions = new AlterConfigsOptions ().timeoutMs(30000 ).validateOnly(false )
206
- val alterLogLevelEntries = ( configsToBeAdded.values.map(new AlterConfigOp (_ , AlterConfigOp .OpType .SET ))
207
- ++ configsToBeDeleted.map { k => new AlterConfigOp (new ConfigEntry (k, " " ), AlterConfigOp .OpType .DELETE ) }
208
- ).asJavaCollection
209
- adminClient.incrementalAlterConfigs(Map (configResource -> alterLogLevelEntries ).asJava, alterOptions).all().get(60 , TimeUnit .SECONDS )
210
+ val addEntries = configsToBeAdded.values.map(k => new AlterConfigOp (k , AlterConfigOp .OpType .SET ))
211
+ val deleteEntries = configsToBeDeleted.map( k => new AlterConfigOp (new ConfigEntry (k, " " ), AlterConfigOp .OpType .DELETE ))
212
+ val alterEntries = (deleteEntries ++ addEntries ).asJavaCollection
213
+ adminClient.incrementalAlterConfigs(Map (configResource -> alterEntries ).asJava, alterOptions).all().get(60 , TimeUnit .SECONDS )
210
214
211
215
case ConfigType .USER | ConfigType .CLIENT =>
212
216
val hasQuotaConfigsToAdd = configsToBeAdded.keys.exists(QuotaConfig .isClientOrUserQuotaConfig)
@@ -250,13 +254,8 @@ object ConfigCommand extends Logging {
250
254
throw new IllegalArgumentException (s " Only connection quota configs can be added for ' ${ConfigType .IP }' using --bootstrap-server. Unexpected config names: ${unknownConfigs.mkString(" ," )}" )
251
255
alterQuotaConfigs(adminClient, entityTypes, entityNames, configsToBeAddedMap, configsToBeDeleted)
252
256
253
- case ConfigType .CLIENT_METRICS =>
254
- alterResourceConfig(adminClient, entityTypeHead, entityNameHead, configsToBeDeleted, configsToBeAdded, ConfigResource .Type .CLIENT_METRICS )
255
-
256
- case ConfigType .GROUP =>
257
- alterResourceConfig(adminClient, entityTypeHead, entityNameHead, configsToBeDeleted, configsToBeAdded, ConfigResource .Type .GROUP )
258
-
259
- case _ => throw new IllegalArgumentException (s " Unsupported entity type: $entityTypeHead" )
257
+ case _ =>
258
+ throw new IllegalArgumentException (s " Unsupported entity type: $entityTypeHead" )
260
259
}
261
260
262
261
if (entityNameHead.nonEmpty)
@@ -380,9 +379,9 @@ object ConfigCommand extends Logging {
380
379
381
380
val configResource = new ConfigResource (resourceType, entityNameHead)
382
381
val alterOptions = new AlterConfigsOptions ().timeoutMs(30000 ).validateOnly(false )
383
- val alterEntries = ( configsToBeAdded.values.map(new AlterConfigOp (_ , AlterConfigOp .OpType .SET ))
384
- ++ configsToBeDeleted.map { k => new AlterConfigOp (new ConfigEntry (k, " " ), AlterConfigOp .OpType .DELETE ) }
385
- ).asJavaCollection
382
+ val addEntries = configsToBeAdded.values.map(k => new AlterConfigOp (k , AlterConfigOp .OpType .SET ))
383
+ val deleteEntries = configsToBeDeleted.map( k => new AlterConfigOp (new ConfigEntry (k, " " ), AlterConfigOp .OpType .DELETE ))
384
+ val alterEntries = (deleteEntries ++ addEntries ).asJavaCollection
386
385
adminClient.incrementalAlterConfigs(Map (configResource -> alterEntries).asJava, alterOptions).all().get(60 , TimeUnit .SECONDS )
387
386
}
388
387
0 commit comments