Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions core/src/main/scala/kafka/admin/TopicCommand.scala
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ object TopicCommand extends Logging {
if (topic.partitions.exists(partitions => partitions < 1))
throw new IllegalArgumentException(s"The partitions must be greater than 0")

if (!adminClient.listTopics().names().get().contains(topic.name)) {
try {
Comment thread
cmccabe marked this conversation as resolved.
val newTopic = if (topic.hasReplicaAssignment)
new NewTopic(topic.name, asJavaReplicaReassignment(topic.replicaAssignment.get))
else {
Expand All @@ -247,8 +247,12 @@ object TopicCommand extends Logging {
val createResult = adminClient.createTopics(Collections.singleton(newTopic))
createResult.all().get()
println(s"Created topic ${topic.name}.")
} else {
throw new IllegalArgumentException(s"Topic ${topic.name} already exists")
} catch {
case e : ExecutionException =>
if (e.getCause == null)
throw e
if (!e.getCause.isInstanceOf[TopicExistsException] || !topic.ifTopicDoesntExist())
Comment thread
cmccabe marked this conversation as resolved.
Outdated
throw e.getCause
}
}

Expand All @@ -259,7 +263,8 @@ object TopicCommand extends Logging {
override def alterTopic(opts: TopicCommandOptions): Unit = {
val topic = new CommandTopicPartition(opts)
val topics = getTopics(opts.topic, opts.excludeInternalTopics)
ensureTopicExists(topics, opts.topic)
ensureTopicExists(topics, opts.topic, !opts.ifExists)
Comment thread
cmccabe marked this conversation as resolved.

val topicsInfo = adminClient.describeTopics(topics.asJavaCollection).values()
adminClient.createPartitions(topics.map {topicName =>
if (topic.hasReplicaAssignment) {
Expand Down Expand Up @@ -290,6 +295,8 @@ object TopicCommand extends Logging {

override def describeTopic(opts: TopicCommandOptions): Unit = {
val topics = getTopics(opts.topic, opts.excludeInternalTopics)
ensureTopicExists(topics, opts.topic, !opts.ifExists)
Comment thread
vinothchandar marked this conversation as resolved.

val allConfigs = adminClient.describeConfigs(topics.map(new ConfigResource(Type.TOPIC, _)).asJavaCollection).values()
val liveBrokers = adminClient.describeCluster().nodes().get().asScala.map(_.id())
val reassignments = listAllReassignments()
Expand Down Expand Up @@ -324,7 +331,7 @@ object TopicCommand extends Logging {

override def deleteTopic(opts: TopicCommandOptions): Unit = {
val topics = getTopics(opts.topic, opts.excludeInternalTopics)
ensureTopicExists(topics, opts.topic)
ensureTopicExists(topics, opts.topic, !opts.ifExists)
Comment thread
vinothchandar marked this conversation as resolved.
adminClient.deleteTopics(topics.asJavaCollection).all().get()
}

Expand Down Expand Up @@ -501,7 +508,7 @@ object TopicCommand extends Logging {
* If set to true, the command will throw an exception if the topic with the
* requested name does not exist.
*/
private def ensureTopicExists(foundTopics: Seq[String], requestedTopic: Option[String], requireTopicExists: Boolean = true): Unit = {
private def ensureTopicExists(foundTopics: Seq[String], requestedTopic: Option[String], requireTopicExists: Boolean): Unit = {
// If no topic name was mentioned, do not need to throw exception.
if (requestedTopic.isDefined && requireTopicExists && foundTopics.isEmpty) {
// If given topic doesn't exist then throw exception
Expand Down Expand Up @@ -639,9 +646,9 @@ object TopicCommand extends Logging {
private val topicsWithOverridesOpt = parser.accepts("topics-with-overrides",
"if set when describing topics, only show topics that have overridden configs")
private val ifExistsOpt = parser.accepts("if-exists",
"if set when altering or deleting or describing topics, the action will only execute if the topic exists. Not supported with the --bootstrap-server option.")
"if set when altering or deleting or describing topics, the action will only execute if the topic exists.")
private val ifNotExistsOpt = parser.accepts("if-not-exists",
"if set when creating topics, the action will only execute if the topic does not already exist. Not supported with the --bootstrap-server option.")
"if set when creating topics, the action will only execute if the topic does not already exist.")

private val disableRackAware = parser.accepts("disable-rack-aware", "Disable rack aware replica assignment")

Expand Down Expand Up @@ -736,8 +743,8 @@ object TopicCommand extends Logging {
allTopicLevelOpts -- Set(describeOpt) ++ allReplicationReportOpts - reportUnavailablePartitionsOpt + topicsWithOverridesOpt)
CommandLineUtils.checkInvalidArgs(parser, options, topicsWithOverridesOpt,
allTopicLevelOpts -- Set(describeOpt) ++ allReplicationReportOpts)
CommandLineUtils.checkInvalidArgs(parser, options, ifExistsOpt, allTopicLevelOpts -- Set(alterOpt, deleteOpt, describeOpt) ++ Set(bootstrapServerOpt))
CommandLineUtils.checkInvalidArgs(parser, options, ifNotExistsOpt, allTopicLevelOpts -- Set(createOpt) ++ Set(bootstrapServerOpt))
Comment thread
vinothchandar marked this conversation as resolved.
CommandLineUtils.checkInvalidArgs(parser, options, ifExistsOpt, allTopicLevelOpts -- Set(alterOpt, deleteOpt, describeOpt))
CommandLineUtils.checkInvalidArgs(parser, options, ifNotExistsOpt, allTopicLevelOpts -- Set(createOpt))
CommandLineUtils.checkInvalidArgs(parser, options, excludeInternalTopicOpt, allTopicLevelOpts -- Set(listOpt, describeOpt))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import org.apache.kafka.clients.CommonClientConfigs
import org.apache.kafka.clients.admin._
import org.apache.kafka.common.TopicPartition
import org.apache.kafka.common.config.{ConfigException, ConfigResource, TopicConfig}
import org.apache.kafka.common.errors.TopicExistsException
import org.apache.kafka.common.internals.Topic
import org.apache.kafka.common.network.ListenerName
import org.apache.kafka.common.protocol.Errors
Expand Down Expand Up @@ -214,7 +215,7 @@ class TopicCommandWithAdminClientTest extends KafkaServerTestHarness with Loggin
}

@Test
def testCreateIfItAlreadyExists(): Unit = {
def testCreateWhenAlreadyExists(): Unit = {
val numPartitions = 1

// create the topic
Expand All @@ -223,8 +224,20 @@ class TopicCommandWithAdminClientTest extends KafkaServerTestHarness with Loggin
createAndWaitTopic(createOpts)

// try to re-create the topic
intercept[IllegalArgumentException] {
intercept[TopicExistsException] {
topicService.createTopic(createOpts)
}
}

@Test
def testCreateWhenAlreadyExistsWithIfNotExists(): Unit = {
val createOpts = new TopicCommandOptions(Array("--topic", testTopicName, "--if-not-exists"))
createAndWaitTopic(createOpts)

try {
topicService.createTopic(createOpts)
} catch {
Comment thread
vinothchandar marked this conversation as resolved.
Outdated
case _ : TopicExistsException => fail("Topic recreation should not throw exception")
}
}

Expand Down Expand Up @@ -431,10 +444,13 @@ class TopicCommandWithAdminClientTest extends KafkaServerTestHarness with Loggin
}

@Test
def testIfExistsAndIfNotExistsOptionsInvalidWithBootstrapServers(): Unit = {
// alter a topic that does not exist without --if-exists
assertCheckArgsExitCode(1, new TopicCommandOptions(Array("--bootstrap-server", "server1:9092", "--alter", "--if-exists", "--topic", testTopicName, "--partitions", "1")))
assertCheckArgsExitCode(1, new TopicCommandOptions(Array("--bootstrap-server", "server1:9092", "--create", "--if-not-exists", "--topic", testTopicName, "--partitions", "1", "--replication-factor", "1")))
def testAlterWhenTopicDoesntExistWithIfExists(): Unit = {
try {
topicService.alterTopic(new TopicCommandOptions(
Array("--topic", testTopicName, "--partitions", "1", "--if-exists")))
} catch {
case _ : IllegalArgumentException => fail("Alter topic should not throw exception")
}
}

@Test
Expand Down Expand Up @@ -530,14 +546,23 @@ class TopicCommandWithAdminClientTest extends KafkaServerTestHarness with Loggin
}

@Test
def testDeleteIfExists(): Unit = {
def testDeleteWhenTopicDoesntExist(): Unit = {
// delete a topic that does not exist
val deleteOpts = new TopicCommandOptions(Array("--topic", testTopicName))
intercept[IllegalArgumentException] {
topicService.deleteTopic(deleteOpts)
}
}

@Test
def testDeleteWhenTopicDoesntExistWithIfExists(): Unit = {
try {
topicService.deleteTopic(new TopicCommandOptions(Array("--topic", testTopicName, "--if-exists")))
} catch {
case _ : IllegalArgumentException => fail("Topic deletion should not throw an exception")
}
}

@Test
def testDescribe(): Unit = {
adminClient.createTopics(
Expand All @@ -551,6 +576,22 @@ class TopicCommandWithAdminClientTest extends KafkaServerTestHarness with Loggin
rows(0).startsWith(s"Topic:$testTopicName\tPartitionCount:2")
}

@Test
def testDescribeWhenTopicDoesntExist(): Unit = {
intercept[IllegalArgumentException] {
topicService.describeTopic(new TopicCommandOptions(Array("--topic", testTopicName)))
}
}

@Test
def testDescribeWhenTopicDoesntExistWithIfExists(): Unit = {
try {
topicService.describeTopic(new TopicCommandOptions(Array("--topic", testTopicName, "--if-exists")))
} catch {
case _ : IllegalArgumentException => fail("Describe topic should not throw an exception")
}
}

@Test
def testDescribeUnavailablePartitions(): Unit = {
adminClient.createTopics(
Expand Down