Skip to content

Commit f030565

Browse files
authored
Update kernel install UX (apple#22)
This change updates the UX when we install required dependencies at first launch ### Fresh install - respond `y` to prompt ``` ➜ bin/container system start Verifying apiserver is running... Installing base container filesystem... No default kernel configured. Install the recommended default kernel from [https://github.com/kata-containers/kata-containers/releases/download/3.17.0/kata-static-3.17.0-arm64.tar.xz]? [Y/n]: y Installing kernel... ``` ### Fresh install - respond `n` to prompt and then run the provided command ``` ➜ bin/container system start Verifying apiserver is running... Installing base container filesystem... No default kernel configured. Install the recommended default kernel from [https://github.com/kata-containers/kata-containers/releases/download/3.17.0/kata-static-3.17.0-arm64.tar.xz]? [Y/n]: n Please use the `container system kernel set --recommended` command to configure the default kernel ➜ bin/container system kernel set --recommended Installing the recommended kernel from https://github.com/kata-containers/kata-containers/releases/download/3.17.0/kata-static-3.17.0-arm64.tar.xz... ``` ### Fresh install - respond `n` to prompt and then run a container ``` ➜ bin/container system start Verifying apiserver is running... Installing base container filesystem... No default kernel configured. Install the recommended default kernel from [https://github.com/kata-containers/kata-containers/releases/download/3.17.0/kata-static-3.17.0-arm64.tar.xz]? [Y/n]: n Please use the `container system kernel set --recommended` command to configure the default kernel ➜ bin/container run alpine uname Error: notFound: "Default kernel not configured for architecture arm64. Please use the `container system kernel set` command to configure it ``` --------- Signed-off-by: Aditya Ramani <a_ramani@apple.com>
1 parent 85c10da commit f030565

File tree

6 files changed

+48
-49
lines changed

6 files changed

+48
-49
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ _site:
178178

179179
.PHONY: cleancontent
180180
cleancontent:
181+
@bin/container system stop || true
181182
@echo Cleaning the content...
182183
@rm -rf ~/Library/Application\ Support/com.apple.container
183184

Sources/APIServer/Kernel/KernelService.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,13 @@ actor KernelService {
4242
let kFile = url.resolvingSymlinksInPath()
4343
let destPath = self.kernelDirectory.appendingPathComponent(kFile.lastPathComponent)
4444
try FileManager.default.copyItem(at: kFile, to: destPath)
45-
try self.setDefaultKernel(name: kFile.lastPathComponent, platform: platform)
45+
try Task.checkCancellation()
46+
do {
47+
try self.setDefaultKernel(name: kFile.lastPathComponent, platform: platform)
48+
} catch {
49+
try? FileManager.default.removeItem(at: destPath)
50+
throw error
51+
}
4652
}
4753

4854
/// Copies a kernel binary from inside of tar file into the managed kernels directory

Sources/CLI/System/Kernel/KernelSet.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@ extension Application {
3939
@Option(name: .customLong("arch"), help: "The architecture of the kernel binary. One of (amd64, arm64)")
4040
var architecture: String = ContainerizationOCI.Platform.current.architecture.description
4141

42-
@Flag(name: .customLong("install-recommended"), help: "Download and install the recommended kernel as the default. This flag ignores any other arguments")
43-
var installRecommended: Bool = false
42+
@Flag(name: .customLong("recommended"), help: "Download and install the recommended kernel as the default. This flag ignores any other arguments")
43+
var recommended: Bool = false
4444

4545
func run() async throws {
46-
if installRecommended {
46+
if recommended {
4747
let url = ClientDefaults.get(key: .defaultKernelURL)
4848
let path = ClientDefaults.get(key: .defaultKernelBinaryPath)
49+
print("Installing the recommended kernel from \(url)...")
4950
try await Self.downloadAndInstallWithProgressBar(tarRemoteURL: url, kernelFilePath: path)
5051
return
5152
}

Sources/CLI/System/SystemStart.swift

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -77,73 +77,57 @@ extension Application {
7777
do {
7878
print("Verifying apiserver is running...")
7979
try await ClientHealthCheck.ping(timeout: .seconds(10))
80-
print("Done")
8180
} catch {
8281
throw ContainerizationError(
8382
.internalError,
8483
message: "failed to get a response from apiserver: \(error)"
8584
)
8685
}
8786

88-
var kernelConfigured: Bool = true
89-
var missingDependencies: [Dependencies] = []
9087
if await !initImageExists() {
91-
missingDependencies.append(.initFs)
88+
try? await installInitialFilesystem()
9289
}
93-
if await !kernelExists() {
94-
kernelConfigured = false
95-
missingDependencies.append(.kernel)
96-
}
97-
guard missingDependencies.count > 0 else {
90+
91+
guard await !kernelExists() else {
9892
return
9993
}
94+
try await installDefaultKernel()
95+
}
10096

101-
print("Missing required runtime dependencies:")
102-
for (idx, dependency) in missingDependencies.enumerated() {
103-
print(" \(idx+1). \(dependency.rawValue)")
97+
private func installInitialFilesystem() async throws {
98+
let dep = Dependencies.initFs
99+
let pullCommand = ImagePull(reference: dep.source)
100+
print("Installing base container filesystem...")
101+
do {
102+
try await pullCommand.run()
103+
} catch {
104+
log.error("Failed to install base container filesystem: \(error)")
104105
}
106+
}
107+
108+
private func installDefaultKernel() async throws {
109+
let kernelDependency = Dependencies.kernel
110+
let defaultKernelURL = kernelDependency.source
111+
let defaultKernelBinaryPath = ClientDefaults.get(key: .defaultKernelBinaryPath)
105112

113+
print("No default kernel configured.")
114+
print("Install the recommended default kernel from [\(kernelDependency.source)]? [Y/n]: ", terminator: "")
106115
if !installDependencies {
107-
print("Would like to install them now? [Y/n]: ", terminator: "")
108116
guard let read = readLine(strippingNewline: true) else {
109117
throw ContainerizationError(.internalError, message: "Failed to read user input")
110118
}
111119
guard read.lowercased() == "y" || read.count == 0 else {
112-
if !kernelConfigured {
113-
print("Please use the `container system kernel set` command to configure the kernel")
114-
}
120+
print("Please use the `container system kernel set --recommended` command to configure the default kernel")
115121
return
116122
}
117123
}
118-
try await installDeps(deps: missingDependencies)
119-
}
120-
121-
private func installDeps(deps: [Dependencies]) async throws {
122-
if deps.contains(.kernel) {
123-
try await installDefaultKernel()
124-
}
125-
if deps.contains(.initFs) {
126-
try await installInitialFilesystem()
127-
}
128-
}
129-
130-
private func installInitialFilesystem() async throws {
131-
let reference = ClientDefaults.get(key: .defaultInitImage)
132-
let pullCommand = ImagePull(reference: reference)
133-
print("Installing initial filesystem from [\(reference)]...")
134-
try await pullCommand.run()
135-
}
136-
137-
private func installDefaultKernel() async throws {
138-
let defaultKernelURL = ClientDefaults.get(key: .defaultKernelURL)
139-
let defaultKernelBinaryPath = ClientDefaults.get(key: .defaultKernelBinaryPath)
140-
print("Installing default kernel from [\(defaultKernelURL)]...")
124+
print("Installing kernel...")
141125
try await KernelSet.downloadAndInstallWithProgressBar(tarRemoteURL: defaultKernelURL, kernelFilePath: defaultKernelBinaryPath)
142126
}
143127

144128
private func initImageExists() async -> Bool {
145129
do {
146-
let img = try await ClientImage.get(reference: ClientDefaults.get(key: .defaultInitImage))
130+
let img = try await ClientImage.get(reference: Dependencies.initFs.source)
147131
let _ = try await img.getSnapshot(platform: .current)
148132
return true
149133
} catch {
@@ -162,7 +146,16 @@ extension Application {
162146
}
163147

164148
private enum Dependencies: String {
165-
case kernel = "Kernel"
166-
case initFs = "Initial filesystem"
149+
case kernel
150+
case initFs
151+
152+
var source: String {
153+
switch self {
154+
case .initFs:
155+
return ClientDefaults.get(key: .defaultInitImage)
156+
case .kernel:
157+
return ClientDefaults.get(key: .defaultKernelURL)
158+
}
159+
}
167160
}
168161
}

Sources/ContainerClient/Core/ClientKernel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ extension ClientKernel {
8080
throw err
8181
}
8282
throw ContainerizationError(
83-
.notFound, message: "Default kernel not configured for architecture \(platform.architecture). Please use the `container system kernel` command to configure it")
83+
.notFound, message: "Default kernel not configured for architecture \(platform.architecture). Please use the `container system kernel set` command to configure it")
8484
}
8585
}
8686
}

Sources/ContainerClient/XPC+.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ public enum XPCKeys: String {
9393
case kernel
9494
case kernelTarURL
9595
case kernelFilePath
96-
case setDefault
9796
case systemPlatform
98-
case kernelName
9997
}
10098

10199
public enum XPCRoute: String {

0 commit comments

Comments
 (0)