mirror of
https://github.com/apple/container.git
synced 2026-07-13 13:07:06 +00:00
b1f3c0d35b
- Part of #1404. - Evolves API to use NetworkResource that conforms to ManagedResource. - BREAKING CHANGE - compile time impact due to changes to Swift client API signatures. No change to persistent data or API server XPC protocols.
129 lines
4.9 KiB
Swift
129 lines
4.9 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
// Copyright © 2025-2026 Apple Inc. and the container project authors.
|
|
//
|
|
// Licensed 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
|
|
//
|
|
// https://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.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import ArgumentParser
|
|
import ContainerAPIClient
|
|
import ContainerResource
|
|
import ContainerizationError
|
|
import Foundation
|
|
|
|
extension Application {
|
|
public struct NetworkDelete: AsyncLoggableCommand {
|
|
public static let configuration = CommandConfiguration(
|
|
commandName: "delete",
|
|
abstract: "Delete one or more networks",
|
|
aliases: ["rm"])
|
|
|
|
@Flag(name: .shortAndLong, help: "Delete all networks")
|
|
var all = false
|
|
|
|
@OptionGroup
|
|
public var logOptions: Flags.Logging
|
|
|
|
@Argument(help: "Network names")
|
|
var networkNames: [String] = []
|
|
|
|
public init() {}
|
|
|
|
public func validate() throws {
|
|
if networkNames.count == 0 && !all {
|
|
throw ContainerizationError(.invalidArgument, message: "no networks specified and --all not supplied")
|
|
}
|
|
if networkNames.count > 0 && all {
|
|
throw ContainerizationError(
|
|
.invalidArgument,
|
|
message: "explicitly supplied network name(s) conflict with the --all flag"
|
|
)
|
|
}
|
|
}
|
|
|
|
public mutating func run() async throws {
|
|
let networkClient = NetworkClient()
|
|
let uniqueNetworkNames = Set<String>(networkNames)
|
|
let networks: [NetworkResource]
|
|
|
|
if all {
|
|
networks = try await networkClient.list()
|
|
.filter { !$0.isBuiltin }
|
|
} else {
|
|
networks = try await networkClient.list()
|
|
.filter { c in
|
|
guard uniqueNetworkNames.contains(c.id) else {
|
|
return false
|
|
}
|
|
guard !c.isBuiltin else {
|
|
throw ContainerizationError(
|
|
.invalidArgument,
|
|
message: "cannot delete a builtin network: \(c.id)"
|
|
)
|
|
}
|
|
return true
|
|
}
|
|
|
|
// If one of the networks requested isn't present lets throw. We don't need to do
|
|
// this for --all as --all should be perfectly usable with no networks to remove,
|
|
// otherwise it'd be quite clunky.
|
|
if networks.count != uniqueNetworkNames.count {
|
|
let missing = uniqueNetworkNames.filter { id in
|
|
!networks.contains { n in
|
|
n.id == id
|
|
}
|
|
}
|
|
throw ContainerizationError(
|
|
.notFound,
|
|
message: "failed to delete one or more networks: \(missing)"
|
|
)
|
|
}
|
|
}
|
|
|
|
var failed = [String]()
|
|
let _log = log
|
|
try await withThrowingTaskGroup(of: NetworkResource?.self) { group in
|
|
for network in networks {
|
|
group.addTask {
|
|
do {
|
|
// Delete atomically disables the IP allocator, then deletes
|
|
// the allocator. The disable fails if any IPs are still in use.
|
|
try await networkClient.delete(id: network.id)
|
|
print(network.id)
|
|
return nil
|
|
} catch {
|
|
_log.error(
|
|
"failed to delete network",
|
|
metadata: [
|
|
"id": "\(network.id)",
|
|
"error": "\(error)",
|
|
])
|
|
return network
|
|
}
|
|
}
|
|
}
|
|
|
|
for try await network in group {
|
|
guard let network else {
|
|
continue
|
|
}
|
|
failed.append(network.id)
|
|
}
|
|
}
|
|
|
|
if failed.count > 0 {
|
|
throw ContainerizationError(.internalError, message: "delete failed for one or more networks: \(failed)")
|
|
}
|
|
}
|
|
}
|
|
}
|