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