Skip to content

Commit f8ec45a

Browse files
committed
Use FilePath for PublishSocket.
Closes CHAOS-1459. Unblocks CHAOS-1463 (Parser).
1 parent caff1e9 commit f8ec45a

3 files changed

Lines changed: 53 additions & 8 deletions

File tree

Sources/ContainerResource/Container/PublishSocket.swift

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,64 @@ import SystemPackage
2020
/// Represents a socket that should be published from container to host.
2121
public struct PublishSocket: Sendable, Codable {
2222
/// The path to the socket in the container.
23-
public var containerPath: URL
23+
public var containerPath: FilePath
2424

2525
/// The path where the socket should appear on the host.
26-
public var hostPath: URL
26+
public var hostPath: FilePath
2727

2828
/// File permissions for the socket on the host.
2929
public var permissions: FilePermissions?
3030

3131
public init(
32-
containerPath: URL,
33-
hostPath: URL,
32+
containerPath: FilePath,
33+
hostPath: FilePath,
3434
permissions: FilePermissions? = nil
3535
) {
3636
self.containerPath = containerPath
3737
self.hostPath = hostPath
3838
self.permissions = permissions
3939
}
40+
41+
private enum CodingKeys: String, CodingKey {
42+
case containerPath
43+
case hostPath
44+
case permissions
45+
}
46+
47+
/// Encode paths as plain JSON strings.
48+
///
49+
/// Previously these fields were `URL`s; `JSONEncoder` special-cases `URL`
50+
/// to encode as `absoluteString` (e.g. `"file:///var/run/docker.sock"`).
51+
/// `FilePath`'s synthesized Codable conformance uses a keyed container
52+
/// (`{"_storage": "..."}`), which would change the on-disk and XPC wire
53+
/// format. We override that here to keep the value a flat JSON string;
54+
/// the decoder accepts both the new clean form (`"/var/run/docker.sock"`)
55+
/// and the legacy `URL`-encoded form (`"file:///..."`).
56+
public func encode(to encoder: any Encoder) throws {
57+
var container = encoder.container(keyedBy: CodingKeys.self)
58+
try container.encode(containerPath.string, forKey: .containerPath)
59+
try container.encode(hostPath.string, forKey: .hostPath)
60+
try container.encodeIfPresent(permissions, forKey: .permissions)
61+
}
62+
63+
public init(from decoder: any Decoder) throws {
64+
let container = try decoder.container(keyedBy: CodingKeys.self)
65+
self.containerPath = try Self.decodePath(from: container, forKey: .containerPath)
66+
self.hostPath = try Self.decodePath(from: container, forKey: .hostPath)
67+
self.permissions = try container.decodeIfPresent(FilePermissions.self, forKey: .permissions)
68+
}
69+
70+
/// Decode a `FilePath` from either a plain path string or a legacy
71+
/// `URL.absoluteString` (e.g. `"file:///foo"`) for backward compatibility
72+
/// with container bundles persisted before the migration to `FilePath`.
73+
private static func decodePath(
74+
from container: KeyedDecodingContainer<CodingKeys>,
75+
forKey key: CodingKeys
76+
) throws -> FilePath {
77+
let raw = try container.decode(String.self, forKey: key)
78+
if raw.hasPrefix("file://"), let url = URL(string: raw), url.isFileURL {
79+
return FilePath(url.path)
80+
}
81+
return FilePath(raw)
82+
}
4083
}

Sources/Services/ContainerAPIService/Client/Parser.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import ContainerizationExtras
2222
import ContainerizationOCI
2323
import ContainerizationOS
2424
import Foundation
25+
import SystemPackage
2526

2627
/// A parsed volume specification from user input
2728
public struct ParsedVolume {
@@ -787,8 +788,8 @@ public struct Parser {
787788

788789
// Create and return PublishSocket object with validated paths
789790
return PublishSocket(
790-
containerPath: URL(fileURLWithPath: containerPath),
791-
hostPath: URL(fileURLWithPath: absoluteHostPath),
791+
containerPath: FilePath(containerPath),
792+
hostPath: FilePath(absoluteHostPath),
792793
permissions: nil
793794
)
794795

Sources/Services/RuntimeLinux/Server/RuntimeService.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -999,9 +999,10 @@ public actor RuntimeService {
999999
}
10001000

10011001
for publishedSocket in config.publishedSockets {
1002+
// UnixSocketConfiguration (Containerization) takes URL; convert from FilePath at the boundary.
10021003
let socketConfig = UnixSocketConfiguration(
1003-
source: publishedSocket.containerPath,
1004-
destination: publishedSocket.hostPath,
1004+
source: URL(filePath: publishedSocket.containerPath.string),
1005+
destination: URL(filePath: publishedSocket.hostPath.string),
10051006
permissions: publishedSocket.permissions,
10061007
direction: .outOf
10071008
)

0 commit comments

Comments
 (0)