Skip to content
9 changes: 7 additions & 2 deletions Sources/ContainerCommands/BuildCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ extension Application {
@OptionGroup
public var logOptions: Flags.Logging

@OptionGroup
public var dns: Flags.DNS

@Argument(help: "Build directory")
var contextDir: String = "."

Expand All @@ -143,12 +146,13 @@ extension Application {

progress.set(description: "Dialing builder")

let builder: Builder? = try await withThrowingTaskGroup(of: Builder.self) { [vsockPort, cpus, memory] group in
let dnsNameservers = self.dns.nameservers
let builder: Builder? = try await withThrowingTaskGroup(of: Builder.self) { [vsockPort, cpus, memory, dnsNameservers] group in
defer {
group.cancelAll()
}

group.addTask { [vsockPort, cpus, memory, log] in
group.addTask { [vsockPort, cpus, memory, log, dnsNameservers] in
while true {
do {
let container = try await ClientContainer.get(id: "buildkit")
Expand All @@ -170,6 +174,7 @@ extension Application {
cpus: cpus,
memory: memory,
log: log,
dnsNameservers: dnsNameservers,
progressUpdate: progress.handler
)

Expand Down
56 changes: 49 additions & 7 deletions Sources/ContainerCommands/Builder/BuilderStart.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ extension Application {
)
var memory: String = "2048MB"

@OptionGroup
public var dns: Flags.DNS

@OptionGroup
public var logOptions: Flags.Logging

Expand All @@ -61,11 +64,29 @@ extension Application {
progress.finish()
}
progress.start()
try await Self.start(cpus: self.cpus, memory: self.memory, log: log, progressUpdate: progress.handler)
try await Self.start(
cpus: self.cpus,
memory: self.memory,
log: log,
dnsNameservers: self.dns.nameservers,
dnsDomain: self.dns.domain,
dnsSearchDomains: self.dns.searchDomains,
dnsOptions: self.dns.options,
progressUpdate: progress.handler
)
progress.finish()
}

static func start(cpus: Int64?, memory: String?, log: Logger, progressUpdate: @escaping ProgressUpdateHandler) async throws {
static func start(
cpus: Int64?,
memory: String?,
log: Logger,
dnsNameservers: [String] = [],
dnsDomain: String? = nil,
dnsSearchDomains: [String] = [],
dnsOptions: [String] = [],
progressUpdate: @escaping ProgressUpdateHandler
) async throws {
await progressUpdate([
.setDescription("Fetching BuildKit image"),
.setItemsName("blobs"),
Expand Down Expand Up @@ -103,6 +124,7 @@ extension Application {
let existingImage = existingContainer.configuration.image.reference
let existingResources = existingContainer.configuration.resources
let existingEnv = existingContainer.configuration.initProcess.environment
let existingDNS = existingContainer.configuration.dns

let existingManagedEnv = existingEnv.filter { envVar in
envVar.hasPrefix("BUILDKIT_COLORS=") || envVar.hasPrefix("NO_COLOR=")
Expand All @@ -129,11 +151,26 @@ extension Application {
}
return false
}()
let dnsChanged = {
if !dnsNameservers.isEmpty {
return existingDNS?.nameservers != dnsNameservers
}
if dnsDomain != nil {
return existingDNS?.domain != dnsDomain
}
if !dnsSearchDomains.isEmpty {
return existingDNS?.searchDomains != dnsSearchDomains
}
if !dnsOptions.isEmpty {
return existingDNS?.options != dnsOptions
}
return false
}()

switch existingContainer.status {
case .running:
guard imageChanged || cpuChanged || memChanged || envChanged else {
// If image, mem and cpu are the same, continue using the existing builder
guard imageChanged || cpuChanged || memChanged || envChanged || dnsChanged else {
// If image, mem, cpu, env, and DNS are the same, continue using the existing builder
return
}
// If they changed, stop and delete the existing builder
Expand All @@ -142,7 +179,7 @@ extension Application {
case .stopped:
// If the builder is stopped and matches our requirements, start it
// Otherwise, delete it and create a new one
guard imageChanged || cpuChanged || memChanged || envChanged else {
guard imageChanged || cpuChanged || memChanged || envChanged || dnsChanged else {
try await existingContainer.startBuildKit(progressUpdate, nil)
return
}
Expand Down Expand Up @@ -233,8 +270,13 @@ extension Application {
config.networks = [AttachmentConfiguration(network: network.id, options: AttachmentOptions(hostname: id))]
let subnet = networkStatus.ipv4Subnet
let nameserver = IPv4Address(subnet.lower.value + 1).description
let nameservers = [nameserver]
config.dns = ContainerConfiguration.DNSConfiguration(nameservers: nameservers)
let nameservers = dnsNameservers.isEmpty ? [nameserver] : dnsNameservers
config.dns = ContainerConfiguration.DNSConfiguration(
nameservers: nameservers,
domain: dnsDomain,
searchDomains: dnsSearchDomains,
options: dnsOptions
)

let kernel = try await {
await progressUpdate([
Expand Down
53 changes: 30 additions & 23 deletions Sources/Services/ContainerAPIService/Client/Flags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,34 @@ public struct Flags {
public var memory: String?
}

public struct DNS: ParsableArguments {
public init() {}

@Option(
name: .customLong("dns"),
help: .init("DNS nameserver IP address", valueName: "ip")
)
public var nameservers: [String] = []

@Option(
name: .customLong("dns-domain"),
help: .init("Default DNS domain", valueName: "domain")
)
public var domain: String? = nil

@Option(
name: .customLong("dns-option"),
help: .init("DNS options", valueName: "option")
)
public var options: [String] = []

@Option(
name: .customLong("dns-search"),
help: .init("DNS search domains", valueName: "domain")
)
public var searchDomains: [String] = []
}

public struct Registry: ParsableArguments {
public init() {}

Expand All @@ -99,29 +127,8 @@ public struct Flags {
@Flag(name: .shortAndLong, help: "Run the container and detach from the process")
public var detach = false

@Option(
name: .customLong("dns"),
help: .init("DNS nameserver IP address", valueName: "ip")
)
public var dnsNameservers: [String] = []

@Option(
name: .long,
help: .init("Default DNS domain", valueName: "domain")
)
public var dnsDomain: String? = nil

@Option(
name: .customLong("dns-option"),
help: .init("DNS options", valueName: "option")
)
public var dnsOptions: [String] = []

@Option(
name: .customLong("dns-search"),
help: .init("DNS search domains", valueName: "domain")
)
public var dnsSearchDomains: [String] = []
@OptionGroup
public var dns: Flags.DNS

@Option(
name: .long,
Expand Down
8 changes: 4 additions & 4 deletions Sources/Services/ContainerAPIService/Client/Utility.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,12 @@ public struct Utility {
if management.dnsDisabled {
config.dns = nil
} else {
let domain = management.dnsDomain ?? DefaultsStore.getOptional(key: .defaultDNSDomain)
let domain = management.dns.domain ?? DefaultsStore.getOptional(key: .defaultDNSDomain)
config.dns = .init(
nameservers: management.dnsNameservers,
nameservers: management.dns.nameservers,
domain: domain,
searchDomains: management.dnsSearchDomains,
options: management.dnsOptions
searchDomains: management.dns.searchDomains,
options: management.dns.options
)
}

Expand Down