You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jira@kafka.apache.org by GitBox <gi...@apache.org> on 2022/06/20 13:53:14 UTC
[GitHub] [kafka] cmccabe opened a new pull request, #12315: MINOR: the Kafka metadata shell should support connecting to a controller quorum
cmccabe opened a new pull request, #12315:
URL: https://github.com/apache/kafka/pull/12315
This PR allows us to support connecting the metadata shell to a live KRaft quorum via --controller,
as specified in the original KIPs. In order to do this, the PR factors out a "MetadataShellSource"
interface which is implemented by both a snapshot file and a live quorum.
Previously, the "shell" gradle submodule dependend on "core." This extended the gradle build time
because "core" takes a long time to build. It also tended to reduce the encapsulation of the
shell. This PR makes "core" depend on "shell" instead. In order to support this, the new entry
point for the tool is kafka.tools.MetadataShellTool rather than
org.apache.kafka.shell.MetadataShell.
RaftManager.scala: make close() idempotent, as it is for nearly everything else. This makes cleanup
logic easier.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: jira-unsubscribe@kafka.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] MINOR: the Kafka metadata shell should support connecting to a controller quorum [kafka]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #12315:
URL: https://github.com/apache/kafka/pull/12315#issuecomment-2563279493
This PR is being marked as stale since it has not had any activity in 90 days. If you
would like to keep this PR alive, please leave a comment asking for a review. If the PR has
merge conflicts, update it with the latest from the base branch.
<p>
If you are having difficulty finding a reviewer, please reach out on the
[mailing list](https://kafka.apache.org/contact).
<p>
If this PR is no longer valid or desired, please feel free to close it. If no activity
occurs in the next 30 days, it will be automatically closed.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: jira-unsubscribe@kafka.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] MINOR: the Kafka metadata shell should support connecting to a controller quorum [kafka]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] closed pull request #12315: MINOR: the Kafka metadata shell should support connecting to a controller quorum
URL: https://github.com/apache/kafka/pull/12315
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: jira-unsubscribe@kafka.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [kafka] dengziming commented on a diff in pull request #12315: MINOR: the Kafka metadata shell should support connecting to a controller quorum
Posted by GitBox <gi...@apache.org>.
dengziming commented on code in PR #12315:
URL: https://github.com/apache/kafka/pull/12315#discussion_r905758022
##########
core/src/main/scala/kafka/tools/MetadataShellTool.scala:
##########
@@ -0,0 +1,199 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package kafka.tools
+
+import java.nio.file.{Files, Path}
+import java.util.Collections
+import java.util.concurrent.CompletableFuture
+import kafka.raft.KafkaRaftManager
+import kafka.server.{KafkaConfig, KafkaRaftServer, MetaProperties}
+import kafka.utils.Logging
+import net.sourceforge.argparse4j.ArgumentParsers
+import org.apache.kafka.common.metrics.Metrics
+import org.apache.kafka.common.utils.{Exit, Time, Utils}
+import org.apache.kafka.metadata.MetadataRecordSerde
+import org.apache.kafka.metadata.util.{ClusterMetadataSource, SnapshotFileReader}
+import org.apache.kafka.raft.{BatchReader, KafkaRaftClient, LeaderAndEpoch, RaftClient, RaftConfig}
+import org.apache.kafka.server.common.ApiMessageAndVersion
+import org.apache.kafka.shell.{InteractiveShell, NonInteractiveShell}
+import org.apache.kafka.snapshot.SnapshotReader
+
+
+object MetadataShellTool {
+ def main(args: Array[String]): Unit = {
+ val parser = ArgumentParsers.newArgumentParser("metadata-tool").
+ defaultHelp(true).
+ description("The Apache Kafka metadata tool")
+ parser.addArgument("--cluster-id", "-t").
+ `type`(classOf[String]).
+ help("The cluster id. Required when using --controllers")
+ val accessGroup = parser.addMutuallyExclusiveGroup().
+ required(true)
+ accessGroup.addArgument("--snapshot", "-s").
+ `type`(classOf[String]).
+ help("The snapshot file to read.")
+ accessGroup.addArgument("--controllers", "-q").
+ `type`(classOf[String]).
+ help(s"The ${RaftConfig.QUORUM_VOTERS_CONFIG}.")
+ parser.addArgument("command").
+ nargs("*").
+ help("The command to run.")
+ val res = parser.parseArgsOrFail(args)
+ val source = if (res.getString("snapshot") != null) {
+ new SnapshotFileReader(res.getString("snapshot"))
+ } else if (res.getString("controllers") != null) {
+ val clusterId = res.getString("cluster_id")
+ if (clusterId == null || clusterId.isEmpty) {
+ throw new RuntimeException("You must provide --cluster-id when connecting " +
+ "directly to the controllers.")
+ }
+ val observer = new MetadataShellObserver()
+ observer.setup(res.getString("controllers"), clusterId)
+ observer
+ } else {
+ throw new RuntimeException("You must set either --snapshot or --controllers")
+ }
+ try {
+ val args = Option(res.getList[String]("command")).getOrElse(Collections.emptyList[String])
+ if (args.isEmpty) {
+ val shell = new InteractiveShell(source)
+ try {
+ shell.run()
+ } finally {
+ shell.close()
+ }
+ } else {
+ val shell = new NonInteractiveShell(source)
+ try {
+ shell.run(System.out, args)
+ } finally {
+ shell.close()
+ }
+ }
+ Exit.exit(0)
+ } catch {
+ case e: Throwable =>
+ System.err.println("Unexpected error: " + (if (e.getMessage == null) ""
+ else e.getMessage))
+ e.printStackTrace(System.err)
+ Exit.exit(1)
+ }
+ }
+}
+
+class HighWaterMarkTrackingRaftClientListener(
+ val caughtUpFuture: CompletableFuture[Void],
+ val raftClient: KafkaRaftClient[ApiMessageAndVersion],
+ val underlying: RaftClient.Listener[ApiMessageAndVersion],
+) extends RaftClient.Listener[ApiMessageAndVersion] {
+ override def handleCommit(reader: BatchReader[ApiMessageAndVersion]): Unit = {
+ reader.lastOffset().ifPresent(checkIfCaughtUp(_))
+ underlying.handleCommit(reader)
+ }
+
+ override def handleSnapshot(reader: SnapshotReader[ApiMessageAndVersion]): Unit = {
+ checkIfCaughtUp(reader.lastContainedLogOffset())
+ underlying.handleSnapshot(reader)
+ }
+
+ override def handleLeaderChange(leader: LeaderAndEpoch): Unit = {
+ underlying.handleLeaderChange(leader)
+ }
+
+ override def beginShutdown(): Unit = {
+ underlying.beginShutdown()
+ }
+
+ private def checkIfCaughtUp(offset: Long): Unit = {
+ if (!caughtUpFuture.isDone) {
+ raftClient.highWatermark().ifPresent(highWatermark =>
+ if (offset >= highWatermark) {
+ caughtUpFuture.complete(null)
+ })
+ }
+ }
+}
+
+class MetadataShellObserver extends ClusterMetadataSource with Logging {
+ val _caughtUpFuture = new CompletableFuture[Void]()
+ var tempDir: Path = null
+ var raftManager: KafkaRaftManager[ApiMessageAndVersion] = null
+ var _listener: HighWaterMarkTrackingRaftClientListener = null
+
+ def setup(
+ quorumVoters: String,
+ clusterId: String
+ ): Unit = {
+ try {
+ tempDir = Files.createTempDirectory("MetadataShell")
+ val metaProperties = new MetaProperties(clusterId, -1)
+ val configMap = new java.util.HashMap[String, Object]
+ configMap.put(RaftConfig.QUORUM_VOTERS_CONFIG, quorumVoters)
+ configMap.put(KafkaConfig.MetadataLogDirProp, tempDir.toAbsolutePath.toString)
+ val config = new KafkaConfig(configMap)
Review Comment:
We should set `process.roles` here to avoid exception
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: jira-unsubscribe@kafka.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] MINOR: the Kafka metadata shell should support connecting to a controller quorum [kafka]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #12315:
URL: https://github.com/apache/kafka/pull/12315#issuecomment-2614789905
This PR has been closed since it has not had any activity in 120 days. If you feel like this
was a mistake, or you would like to continue working on it, please feel free to re-open the
PR and ask for a review.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: jira-unsubscribe@kafka.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org