Skip to content

Commit

Permalink
Support wildcards in credHelpers (#592)
Browse files Browse the repository at this point in the history
* Support wildcards in `credHelpers`

With #591 `tart pull` fails when for example you have `ecr-login` set as the default `credsStore` but you try to pull our images from `ghcr.io`.

This change reverts #591 and instead supports regex in `credHelpers`. This is not supported by Docker itself but highly demanded in docker/cli#2928

I think it's fine to support it for Tart.

Additionally this change bumps the minimum host macOS version to Ventura in order to bring `Regex`. Yes, `Regex` only supported in Swift for macOS 13+ 🤦‍♂️I think it's fine in the light of Sonoma release and Tart 2.0.0.

* Removed Monterey mentions from docs
  • Loading branch information
fkorotkov authored Aug 28, 2023
1 parent f45551c commit 4bb248e
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 54 deletions.
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ brews:
libexec.install Dir["*"]
bin.write_exec_script "#{libexec}/tart.app/Contents/MacOS/tart"
custom_block: |
depends_on :macos => :monterey
depends_on :macos => :ventura
on_macos do
unless Hardware::CPU.arm?
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PackageDescription
let package = Package(
name: "Tart",
platforms: [
.macOS(.v12)
.macOS(.v13)
],
products: [
.executable(name: "tart", targets: ["tart"])
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Many more companies are using Tart in their internal setups. Here are a few of t

## Usage

Try running a Tart VM on your Apple Silicon device running macOS 12.0 (Monterey) or later (will download a 25 GB image):
Try running a Tart VM on your Apple Silicon device running macOS 13.0 (Ventura) or later (will download a 25 GB image):

```bash
brew install cirruslabs/cli/tart
Expand Down
6 changes: 1 addition & 5 deletions Sources/tart/Commands/Create.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ struct Create: AsyncParsableCommand {
}

if linux {
if #available(macOS 13, *) {
_ = try await VM.linux(vmDir: tmpVMDir, diskSizeGB: diskSize)
} else {
throw UnsupportedOSError("Linux VMs", "are")
}
_ = try await VM.linux(vmDir: tmpVMDir, diskSizeGB: diskSize)
}

try VMStorageLocal().move(name, from: tmpVMDir)
Expand Down
27 changes: 21 additions & 6 deletions Sources/tart/Credentials/DockerConfigCredentialsProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@ class DockerConfigCredentialsProvider: CredentialsProvider {
if let credentialsFromAuth = config.auths?[host]?.decodeCredentials() {
return credentialsFromAuth
}
if let helperProgram = config.credHelpers?[host] {
if let helperProgram = try config.findCredHelper(host: host) {
return try executeHelper(binaryName: "docker-credential-\(helperProgram)", host: host)
}

if let defaultCredsStore = config.credsStore {
return try executeHelper(binaryName: "docker-credential-\(defaultCredsStore)", host: host)
}

return nil
}

Expand Down Expand Up @@ -63,7 +59,26 @@ class DockerConfigCredentialsProvider: CredentialsProvider {
struct DockerConfig: Codable {
var auths: Dictionary<String, DockerAuthConfig>? = Dictionary()
var credHelpers: Dictionary<String, String>? = Dictionary()
var credsStore: String? = nil

func findCredHelper(host: String) throws -> String? {
// Tart supports wildcards in credHelpers
// Similar to what is requested from Docker: https://github.com/docker/cli/issues/2928

guard let credHelpers else {
return nil
}

for (hostPattern, helperProgram) in credHelpers {
if (hostPattern == host) {
return helperProgram
}
let compiledPattern = try? Regex(hostPattern)
if (try compiledPattern?.wholeMatch(in: host) != nil) {
return helperProgram
}
}
return nil
}
}

struct DockerAuthConfig: Codable {
Expand Down
14 changes: 3 additions & 11 deletions Sources/tart/Platform/Darwin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,19 +116,11 @@ struct Darwin: PlatformSuspendable {
}

func pointingDevices() -> [VZPointingDeviceConfiguration] {
if #available(macOS 13, *) {
// Trackpad is only supported by guests starting with macOS Ventura
return [VZMacTrackpadConfiguration(), VZUSBScreenCoordinatePointingDeviceConfiguration()]
} else {
return [VZUSBScreenCoordinatePointingDeviceConfiguration()]
}
// Trackpad is only supported by guests starting with macOS Ventura
[VZMacTrackpadConfiguration(), VZUSBScreenCoordinatePointingDeviceConfiguration()]
}

func pointingDevicesSuspendable() -> [VZPointingDeviceConfiguration] {
if #available(macOS 13, *) {
return [VZMacTrackpadConfiguration()]
} else {
return []
}
[VZMacTrackpadConfiguration()]
}
}
30 changes: 12 additions & 18 deletions Sources/tart/VM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,15 +253,9 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {

@MainActor
private func start(_ recovery: Bool) async throws {
if #available(macOS 13, *) {
// new API introduced in Ventura
let startOptions = VZMacOSVirtualMachineStartOptions()
startOptions.startUpFromMacOSRecovery = recovery
try await virtualMachine.start(options: startOptions)
} else {
// use method that also available on Monterey
try await virtualMachine.start(recovery)
}
let startOptions = VZMacOSVirtualMachineStartOptions()
startOptions.startUpFromMacOSRecovery = recovery
try await virtualMachine.start(options: startOptions)
}

@MainActor
Expand Down Expand Up @@ -324,13 +318,15 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
let vio = VZVirtioNetworkDeviceConfiguration()
vio.attachment = $0
vio.macAddress = vmConfig.macAddress
return vio
return vio
}

// Storage
var attachments = [try VZDiskImageStorageDeviceAttachment(url: diskURL, readOnly: false)]
attachments.append(contentsOf: additionalDiskAttachments)
configuration.storageDevices = attachments.map { VZVirtioBlockDeviceConfiguration(attachment: $0) }
configuration.storageDevices = attachments.map {
VZVirtioBlockDeviceConfiguration(attachment: $0)
}

// Entropy
if !suspendable {
Expand All @@ -347,15 +343,13 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
//
// A dummy console device useful for implementing
// host feature checks in the guest agent software.
if #available(macOS 13, *) {
let consolePort = VZVirtioConsolePortConfiguration()
consolePort.name = "tart-version-\(CI.version)"
let consolePort = VZVirtioConsolePortConfiguration()
consolePort.name = "tart-version-\(CI.version)"

let consoleDevice = VZVirtioConsoleDeviceConfiguration()
consoleDevice.ports[0] = consolePort
let consoleDevice = VZVirtioConsoleDeviceConfiguration()
consoleDevice.ports[0] = consolePort

configuration.consoleDevices.append(consoleDevice)
}
configuration.consoleDevices.append(consoleDevice)

try configuration.validate()

Expand Down
6 changes: 1 addition & 5 deletions Sources/tart/VMConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,7 @@ struct VMConfig: Codable {
case .darwin:
platform = try Darwin(from: decoder)
case .linux:
if #available(macOS 13, *) {
platform = try Linux(from: decoder)
} else {
throw UnsupportedOSError("Linux VMs", "are")
}
platform = try Linux(from: decoder)
}
cpuCountMin = try container.decode(Int.self, forKey: .cpuCountMin)
cpuCount = try container.decode(Int.self, forKey: .cpuCount)
Expand Down
16 changes: 16 additions & 0 deletions Tests/TartTests/DockerConfigTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import XCTest
@testable import tart

final class DockerConfigTests: XCTestCase {
func testHelpers() throws {
let config = DockerConfig(credHelpers: [
"(.*).dkr.ecr.(.*).amazonaws.com": "ecr-login",
"gcr.io": "gcloud"
])

XCTAssertEqual(try config.findCredHelper(host: "gcr.io"), "gcloud")
XCTAssertEqual(try config.findCredHelper(host: "123.dkr.ecr.eu-west-1.amazonaws.com"), "ecr-login")
XCTAssertEqual(try config.findCredHelper(host: "456.dkr.ecr.us-east-1.amazonaws.com"), "ecr-login")
XCTAssertNil(try config.findCredHelper(host: "ghcr.io"))
}
}
4 changes: 2 additions & 2 deletions docs/integrations/cirrus-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ task:
name: hello
macos_instance:
# can be a remote or a local virtual machine
image: ghcr.io/cirruslabs/macos-monterey-base:latest
image: ghcr.io/cirruslabs/macos-ventura-base:latest
hello_script:
- echo "Hello from within a Tart VM!"
- echo "Here is my CPU info:"
Expand Down Expand Up @@ -45,7 +45,7 @@ exposes it via [`artifacts` instruction](https://cirrus-ci.org/guide/writing-tas
task:
name: Build
macos_instance:
image: ghcr.io/cirruslabs/macos-monterey-xcode:latest
image: ghcr.io/cirruslabs/macos-ventura-xcode:latest
build_script: swift build --product tart
binary_artifacts:
path: .build/debug/tart
Expand Down
6 changes: 3 additions & 3 deletions docs/integrations/vm-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Tart can create VMs from `*.ipsw` files. You can download a specific `*.ipsw` fi
use `latest` instead of a path to `*.ipsw` to download the latest available version:

```bash
tart create --from-ipsw=latest monterey-vanilla
tart run monterey-vanilla
tart create --from-ipsw=latest ventura-vanilla
tart run ventura-vanilla
```

After the initial booting of the VM you'll need to manually go through the macOS installation process. As a convention we recommend creating an `admin` user with an `admin` password. After the regular installation please do some additional modifications in the VM:
Expand Down Expand Up @@ -54,7 +54,7 @@ Please refer to `tart set --help` for additional details.
## Building with Packer

Please refer to [Tart Packer Plugin repository](https://github.com/cirruslabs/packer-plugin-tart) for setup instructions.
Here is an example of a template to build `monterey-base` local image based of a remote image:
Here is an example of a template to build a local image based of a remote image:

```hcl
packer {
Expand Down
2 changes: 1 addition & 1 deletion docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ hide:
- navigation
---

Try running a Tart VM on your Apple Silicon device running macOS 12.0 (Monterey) or later (will download a 25 GB image):
Try running a Tart VM on your Apple Silicon device running macOS 13.0 (Ventura) or later (will download a 25 GB image):

```bash
brew install cirruslabs/cli/tart
Expand Down

0 comments on commit 4bb248e

Please sign in to comment.