Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- etcd connections failing with `Unexpected HTTP 400 from v3/maintenance/status` once authentication is enabled. (#2994)
- etcd connections carrying a username refusing a server that has authentication disabled.
- Raw JSON shown instead of etcd's own message when a username or password is wrong.
- etcd connections reported as unreachable every 30 seconds for a user without the root role.
- An etcd `watch` returning no events instead of an error when the session is not authenticated.
- `The request timed out` from an etcd `watch --timeout` above 60 seconds.
- Stop in an etcd tab cancelling an unrelated request and leaving the running one alone.
- Crash from an etcd `watch --timeout` with a negative or out-of-range value.
- Colored highlight on the AI chat input painting over a window that is not key.
- Colored highlight on the AI chat input ignoring Reduce Transparency and Increase Contrast.
- AI chat input focus crossfade playing against Reduce Motion.
Expand Down
12 changes: 10 additions & 2 deletions Plugins/EtcdDriverPlugin/EtcdCommandParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ extension EtcdParseError: PluginDriverError {
struct EtcdCommandParser {
private static let logger = Logger(subsystem: "com.TablePro", category: "EtcdCommandParser")

static let defaultWatchTimeout: TimeInterval = 30
static let maximumWatchTimeout: TimeInterval = 3_000

// MARK: - Public API

static func parse(_ input: String) throws -> EtcdOperation {
Expand Down Expand Up @@ -198,11 +201,16 @@ struct EtcdCommandParser {

let prefix = flags.has("prefix")

var timeout: TimeInterval = 30
var timeout = Self.defaultWatchTimeout
if let timeoutStr = flags.value(for: "timeout") {
guard let parsed = TimeInterval(timeoutStr) else {
guard let parsed = TimeInterval(timeoutStr), parsed.isFinite else {
throw EtcdParseError.invalidArgument("--timeout must be a number")
}
guard parsed >= 0, parsed <= Self.maximumWatchTimeout else {
throw EtcdParseError.invalidArgument(
"--timeout must be between 0 and \(Int(Self.maximumWatchTimeout)) seconds"
)
}
timeout = parsed
}

Expand Down
34 changes: 34 additions & 0 deletions Plugins/EtcdDriverPlugin/EtcdGatewayRoute.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// EtcdGatewayRoute.swift
// EtcdDriverPlugin
//
// Decides whether an etcd v3 gateway prefix is routed, from the answer alone.
//

import Foundation

internal enum EtcdGatewayRoute: Equatable, Sendable {
case routed
case notRouted
case notEtcd
}

internal extension EtcdGatewayRoute {
static let candidatePrefixes = ["v3", "v3beta", "v3alpha"]

static func classify(httpStatus: Int, body: Data) -> EtcdGatewayRoute {
guard httpStatus != notFoundStatus else { return .notRouted }
guard isJsonObject(body) else { return .notEtcd }
return .routed
}
}

private extension EtcdGatewayRoute {
static let notFoundStatus = 404

static func isJsonObject(_ body: Data) -> Bool {
guard !body.isEmpty else { return false }
guard let object = try? JSONSerialization.jsonObject(with: body) else { return false }
return object is [String: Any]
}
}
Loading
Loading