-
Notifications
You must be signed in to change notification settings - Fork 256
[WIP] Experimental krunkit support #5040
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,7 +59,7 @@ func getVersionGeneric(executablePath string, args ...string) (string, error) { | |
| logging.Debugf("failed to run executable %s: %v", executablePath, err) | ||
| return "", err | ||
| } | ||
| parsedOutput := strings.Split(stdOut, ":") | ||
| parsedOutput := strings.Split(stdOut, " ") | ||
| if len(parsedOutput) < 2 { | ||
| logging.Debugf("failed to parse version information for %s: %s", executablePath, stdOut) | ||
| return "", fmt.Errorf("Unable to parse the version information of %s", executablePath) | ||
|
|
@@ -144,7 +144,45 @@ func (c *Cache) cacheExecutable() error { | |
| if err != nil { | ||
| return err | ||
| } | ||
| if c.GetExecutableName() == constants.KrunkitCommand { | ||
| err = signKrunkit(finalExecutablePath) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func signKrunkit(executablePath string) error { | ||
| const krunkitEntitlements = `<?xml version="1.0" encoding="UTF-8"?> | ||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| <plist version="1.0"> | ||
| <dict> | ||
| <key>com.apple.security.cs.disable-library-validation</key> | ||
| <true/> | ||
| <key>com.apple.security.hypervisor</key> | ||
| <true/> | ||
| </dict> | ||
| </plist> | ||
| ` | ||
| tmpFile, err := os.CreateTemp("", "krunkit-entitlements-*.plist") | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create temp entitlements file: %w", err) | ||
| } | ||
| defer os.Remove(tmpFile.Name()) | ||
|
|
||
| if _, err := tmpFile.WriteString(krunkitEntitlements); err != nil { | ||
| tmpFile.Close() | ||
| return fmt.Errorf("failed to write entitlements: %w", err) | ||
| } | ||
| tmpFile.Close() | ||
|
|
||
| _, _, err = crcos.RunWithDefaultLocale("codesign", "-s", "-", "--entitlements", tmpFile.Name(), "--force", executablePath) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| logging.Debugf("Signed %s", executablePath) | ||
| return nil | ||
| } | ||
|
Comment on lines
+157
to
187
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Code signing implementation looks correct but needs platform isolation. The krunkit signing logic with entitlements for hypervisor access is appropriate for macOS. However, this function should be in a Darwin-specific file (e.g., 🤖 Prompt for AI Agents |
||
|
|
||
|
|
@@ -183,7 +221,7 @@ func (c *Cache) CheckVersion() error { | |
| } | ||
|
|
||
| func isTarball(filename string) bool { | ||
| tarballExtensions := []string{".tar", ".tar.gz", ".tar.xz", ".zip", ".tar.bz2", ".crcbundle"} | ||
| tarballExtensions := []string{".tar", ".tar.gz", ".tar.xz", ".zip", ".tar.bz2", ".crcbundle", ".tgz"} | ||
| for _, extension := range tarballExtensions { | ||
| if strings.HasSuffix(strings.ToLower(filename), extension) { | ||
| return true | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,10 @@ | ||
| //go:build darwin | ||
|
|
||
| package constants | ||
|
|
||
| import ( | ||
| "log" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the project's logging package instead of the standard library. The standard library 🔎 Proposed fix import (
- "log"
"os"
"path/filepath"
+
+ "github.com/crc-org/crc/v2/pkg/crc/logging"
)Then update line 32: default:
- log.Fatalf("Invalid provider: %s. Choose between %s or %s", provider, VfkitCommand, KrunkitCommand)
+ logging.Fatalf("Invalid provider: %s. Choose between %s or %s", provider, VfkitCommand, KrunkitCommand)
return ""
🤖 Prompt for AI Agents |
||
| "os" | ||
| "path/filepath" | ||
| ) | ||
|
|
||
|
|
@@ -9,8 +13,27 @@ const ( | |
| PodmanRemoteExecutableName = "podman" | ||
| DaemonAgentLabel = "com.redhat.crc.daemon" | ||
| QemuGuestAgentPort = 1234 | ||
|
|
||
| VfkitCommand = "vfkit" | ||
| KrunkitCommand = "krunkit" | ||
| ) | ||
|
|
||
| func Provider() string { | ||
| provider := os.Getenv("CRC_PROVIDER") | ||
| if provider == "" { | ||
| provider = VfkitCommand | ||
| } | ||
| switch provider { | ||
| case VfkitCommand: | ||
| return VfkitCommand | ||
| case KrunkitCommand: | ||
| return KrunkitCommand | ||
| default: | ||
| log.Fatalf("Invalid provider: %s. Choose between %s or %s", provider, VfkitCommand, KrunkitCommand) | ||
| return "" | ||
| } | ||
| } | ||
|
|
||
| var ( | ||
| TapSocketPath = filepath.Join(CrcBaseDir, "tap.sock") | ||
| DaemonHTTPSocketPath = filepath.Join(CrcBaseDir, "crc-http.sock") | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,20 +4,50 @@ package vfkit | |||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||
| "path/filepath" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| "github.com/crc-org/crc/v2/pkg/crc/constants" | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| const ( | ||||||||||||||||||||||||||||||||||||||||||
| VfkitVersion = "0.6.1" | ||||||||||||||||||||||||||||||||||||||||||
| vfkitCommand = "vfkit" | ||||||||||||||||||||||||||||||||||||||||||
| VfkitVersion = "0.6.1" | ||||||||||||||||||||||||||||||||||||||||||
| VfkitCommand = "vfkit" | ||||||||||||||||||||||||||||||||||||||||||
| KrunkitVersion = "1.1.1" | ||||||||||||||||||||||||||||||||||||||||||
| KrunkitCommand = "krunkit" | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| var ( | ||||||||||||||||||||||||||||||||||||||||||
| VfkitDownloadURL = fmt.Sprintf("https://github.com/crc-org/vfkit/releases/download/v%s/%s", VfkitVersion, vfkitCommand) | ||||||||||||||||||||||||||||||||||||||||||
| VfkitDownloadURL = fmt.Sprintf("https://github.com/crc-org/vfkit/releases/download/v%s/%s", VfkitVersion, VfkitCommand) | ||||||||||||||||||||||||||||||||||||||||||
| VfkitEntitlementsURL = fmt.Sprintf("https://raw.githubusercontent.com/crc-org/vfkit/v%s/vf.entitlements", VfkitVersion) | ||||||||||||||||||||||||||||||||||||||||||
| KrunkitDownloadURL = fmt.Sprintf("https://github.com/containers/krunkit/releases/download/v%s/krunkit-podman-unsigned-%s.tgz", KrunkitVersion, KrunkitVersion) | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+20
to
23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -name "constants.go" -path "*/vfkit/*" -type f 2>/dev/null | head -5Repository: crc-org/crc Length of output: 91 🏁 Script executed: cat -n ./pkg/crc/machine/vfkit/constants.goRepository: crc-org/crc Length of output: 1479 Krunkit download URL references non-existent GitHub release v1.1.1. The URL attempts to download from 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| func ExecutablePath() string { | ||||||||||||||||||||||||||||||||||||||||||
| return constants.ResolveHelperPath(vfkitCommand) | ||||||||||||||||||||||||||||||||||||||||||
| provider := constants.Provider() | ||||||||||||||||||||||||||||||||||||||||||
| if provider == KrunkitCommand { | ||||||||||||||||||||||||||||||||||||||||||
| return filepath.Join(constants.CrcBinDir, provider) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| return constants.ResolveHelperPath(provider) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| func DownloadURL() string { | ||||||||||||||||||||||||||||||||||||||||||
| switch constants.Provider() { | ||||||||||||||||||||||||||||||||||||||||||
| case VfkitCommand: | ||||||||||||||||||||||||||||||||||||||||||
| return VfkitDownloadURL | ||||||||||||||||||||||||||||||||||||||||||
| case KrunkitCommand: | ||||||||||||||||||||||||||||||||||||||||||
| return KrunkitDownloadURL | ||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||
| return "" | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+33
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Default case returns empty string silently. When Proposed fix func DownloadURL() string {
switch constants.Provider() {
case VfkitCommand:
return VfkitDownloadURL
case KrunkitCommand:
return KrunkitDownloadURL
default:
+ // This should not happen as Provider() validates the value
return ""
}
}📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: build-installer (windows-2022, 1.24)[failure] 29-29: 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| func Version() string { | ||||||||||||||||||||||||||||||||||||||||||
| switch constants.Provider() { | ||||||||||||||||||||||||||||||||||||||||||
| case VfkitCommand: | ||||||||||||||||||||||||||||||||||||||||||
| return VfkitVersion | ||||||||||||||||||||||||||||||||||||||||||
| case KrunkitCommand: | ||||||||||||||||||||||||||||||||||||||||||
| return KrunkitVersion | ||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||
| return "" | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -11,12 +11,10 @@ import ( | |||||
| ) | ||||||
|
|
||||||
| func CreateHost(machineConfig config.MachineConfig) *vfkit.Driver { | ||||||
| vfDriver := vfkit.NewDriver(machineConfig.Name, constants.MachineBaseDir) | ||||||
| vfDriver := vfkit.NewDriver(machineConfig.Name, constants.MachineBaseDir, VfkitCommand) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Consider using dynamic provider selection instead of hardcoded VfkitCommand. Line 14 passes 🔎 Proposed fix- vfDriver := vfkit.NewDriver(machineConfig.Name, constants.MachineBaseDir, VfkitCommand)
+ vfDriver := vfkit.NewDriver(machineConfig.Name, constants.MachineBaseDir, constants.Provider())📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
|
|
||||||
| config.InitVMDriverFromMachineConfig(machineConfig, vfDriver.VMDriver) | ||||||
|
|
||||||
| vfDriver.VfkitPath = ExecutablePath() | ||||||
|
|
||||||
| vfDriver.VirtioNet = machineConfig.NetworkMode == network.SystemNetworkingMode | ||||||
|
|
||||||
| vfDriver.VsockPath = constants.TapSocketPath | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,12 +3,13 @@ package libmachine | |
| import ( | ||
| "encoding/json" | ||
|
|
||
| "github.com/crc-org/crc/v2/pkg/drivers/vfkit" | ||
| "github.com/crc-org/crc/v2/pkg/crc/constants" | ||
| vfkitDriver "github.com/crc-org/crc/v2/pkg/drivers/vfkit" | ||
| "github.com/crc-org/crc/v2/pkg/libmachine/host" | ||
| ) | ||
|
|
||
| func (api *Client) NewHost(_ string, driverPath string, rawDriver []byte) (*host.Host, error) { | ||
| driver := vfkit.NewDriver("", "") | ||
| driver := vfkitDriver.NewDriver("", "", constants.Provider()) | ||
| if err := json.Unmarshal(rawDriver, &driver); err != nil { | ||
| return nil, err | ||
| } | ||
|
|
@@ -29,10 +30,11 @@ func (api *Client) Load(name string) (*host.Host, error) { | |
| return nil, err | ||
| } | ||
|
|
||
| driver := vfkit.NewDriver("", "") | ||
| driver := vfkitDriver.NewDriver("", "", constants.Provider()) | ||
| if err := json.Unmarshal(h.RawDriver, &driver); err != nil { | ||
| return nil, err | ||
| } | ||
| driver.VfkitPath = constants.ResolveHelperPath(constants.Provider()) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# First, let's find the relevant files and understand the structure
echo "=== Searching for Driver struct definition ==="
fd -e go -e json | head -20
# Find load_darwin.go and examine context around line 37
echo -e "\n=== Examining load_darwin.go ==="
find . -name "load_darwin.go" -type f
# Search for Driver struct definition
echo -e "\n=== Searching for Driver struct ==="
rg "type Driver struct" -A 20 --type go | head -50
# Search for VfkitPath usage
echo -e "\n=== Searching for VfkitPath usage ==="
rg "VfkitPath" --type goRepository: crc-org/crc Length of output: 5080 🏁 Script executed: #!/bin/bash
# Let's look at the actual load_darwin.go file
cat -n pkg/libmachine/load_darwin.goRepository: crc-org/crc Length of output: 1390 🏁 Script executed: #!/bin/bash
# Search for how driver configuration is saved/loaded
echo "=== Searching for JSON serialization of Driver ==="
rg "json:" --type go | rg -i "driver\|vfkit\|provider" | head -30
# Search for constants.Provider usage
echo -e "\n=== Searching for constants.Provider usage ==="
rg "constants.Provider" --type goRepository: crc-org/crc Length of output: 1096 🏁 Script executed: #!/bin/bash
# Let's find the Driver struct more carefully
echo "=== Finding Driver struct in the codebase ==="
fd -e go -type f | xargs rg "type Driver struct" -l
echo -e "\n=== Full Driver struct definition ==="
fd -e go -type f | xargs grep -l "type Driver struct" | xargs cat | rg "type Driver struct" -A 50Repository: crc-org/crc Length of output: 665 🏁 Script executed: #!/bin/bash
# Let's examine the vfkit driver struct with field tags
cat -n pkg/drivers/vfkit/driver_darwin.go | head -50Repository: crc-org/crc Length of output: 1642 🏁 Script executed: #!/bin/bash
# Search for json tags on VfkitPath and nearby fields
rg "VfkitPath|json:" pkg/drivers/vfkit/driver_darwin.go -B 2 -A 2Repository: crc-org/crc Length of output: 401 🏁 Script executed: #!/bin/bash
# Let's check the base driver struct to understand field persistence
rg "type.*VMDriver|type.*BaseDriver" vendor/github.com/crc-org/machine/drivers/ -A 30 | head -100Repository: crc-org/crc Length of output: 37 🏁 Script executed: #!/bin/bash
# Check what fields are actually stored in the JSON by looking at the base driver
find . -path ./vendor -prune -o -name "driver.go" -type f -print | xargs grep -l "VMDriver\|BaseDriver" | head -5Repository: crc-org/crc Length of output: 146 🏁 Script executed: #!/bin/bash
# Let's check if provider is stored anywhere in the configuration
rg "Provider\(\)" pkg/drivers/vfkit/driver_darwin.go -B 3 -A 3
# Also check if there's any provider field in the driver
rg "Provider" pkg/drivers/vfkit/driver_darwin.goRepository: crc-org/crc Length of output: 321 🏁 Script executed: #!/bin/bash
# Let's see the full Driver struct definition with all fields and potential json tags
cat -n pkg/drivers/vfkit/driver_darwin.go | sed -n '42,100p'Repository: crc-org/crc Length of output: 2188 🏁 Script executed: #!/bin/bash
# Check the VMDriver base class to see what fields it has and if they're serialized
cat -n vendor/github.com/crc-org/machine/drivers/base_driver.go | head -100Repository: crc-org/crc Length of output: 143 🏁 Script executed: #!/bin/bash
# Let's see if VfkitPath gets serialized by checking what happens when we marshal
# and if there are any struct tags
rg "type Driver struct" -A 50 pkg/drivers/vfkit/driver_darwin.go | head -60Repository: crc-org/crc Length of output: 1434 🏁 Script executed: #!/bin/bash
# Check what constants.Provider() returns and if it's configurable
cat -n pkg/crc/constants/constants.go | grep -A 20 "func Provider"Repository: crc-org/crc Length of output: 37 🏁 Script executed: #!/bin/bash
# Find the constants file with Provider function
find . -path ./vendor -prune -o -name "*.go" -type f -print | xargs grep -l "func Provider" | grep -v vendorRepository: crc-org/crc Length of output: 174 🏁 Script executed: #!/bin/bash
# Let's check the constants_darwin.go file for Provider function
cat -n pkg/crc/constants/constants_darwin.go | grep -A 10 "func Provider"Repository: crc-org/crc Length of output: 362 🏁 Script executed: #!/bin/bash
# Check if Provider is a global function or method
rg "Provider\(\)" pkg/crc/constants/ -B 2 -A 2Repository: crc-org/crc Length of output: 868 🏁 Script executed: #!/bin/bash
# Let's examine what files exist in the constants directory
ls -la pkg/crc/constants/Repository: crc-org/crc Length of output: 499 🏁 Script executed: #!/bin/bash
# Now check the actual load_darwin.go again in context - see if VfkitPath is expected to be in JSON
# and look at what happens during unmarshal
cat -n pkg/libmachine/load_darwin.goRepository: crc-org/crc Length of output: 1390 🏁 Script executed: #!/by
# Check what fields would be unmarshalled from JSON in the VMDriver base
find . -path ./vendor -prune -o -name "*.go" -type f -print | xargs grep -l "type VMDriver" | head -3Repository: crc-org/crc Length of output: 37 🏁 Script executed: #!/bin/bash
# Let's search for where Provider is defined and what it returns
rg "^func Provider|^var Provider" --type go | grep -v vendor | head -20Repository: crc-org/crc Length of output: 243 🏁 Script executed: #!/bin/bash
# Check all go files in constants package
ls -la pkg/crc/constants/*.goRepository: crc-org/crc Length of output: 470 🏁 Script executed: #!/bin/bash
# Check the full Provider() function to understand its behavior
cat -n pkg/crc/constants/constants_darwin.goRepository: crc-org/crc Length of output: 1209 🏁 Script executed: #!/bin/bash
# Let's verify if VfkitPath is actually used when starting the VM
# and what happens with different providers
rg "VfkitPath" pkg/drivers/vfkit/driver_darwin.go -B 5 -A 5Repository: crc-org/crc Length of output: 852 🏁 Script executed: #!/bin/bash
# Check if the VM configuration persists any provider information
# or if switching providers would actually cause issues
rg "krunkit|Provider" pkg/drivers/vfkit/driver_darwin.goRepository: crc-org/crc Length of output: 107 🏁 Script executed: #!/bin/bash
# Check the NewDriver function more carefully - see what executableName param does
cat -n pkg/drivers/vfkit/driver_darwin.go | sed -n '55,75p'Repository: crc-org/crc Length of output: 893 🏁 Script executed: #!/bin/bash
# Let's check if there are tests or documentation about provider switching
rg "CRC_PROVIDER" --type go -B 3 -A 3 | head -50Repository: crc-org/crc Length of output: 437 🏁 Script executed: #!/bin/bash
# Check what ResolveHelperPath does
rg "func ResolveHelperPath" -A 15 --type go pkg/crc/constants/Repository: crc-org/crc Length of output: 1021 Unconditionally overwriting VfkitPath with current provider breaks existing VMs. When loading an existing VM, line 37 overwrites VfkitPath with the currently configured provider via
The VM's original provider should be recorded and validated on load, not silently switched. Either:
🤖 Prompt for AI Agents |
||
| h.Driver = driver | ||
| return h, nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Platform-specific constant used in non-platform-specific file causes build failures.
The code references
constants.KrunkitCommandwhich is only defined inconstants_darwin.go. This causes build failures on Windows and Linux platforms as shown in the pipeline failures and static analysis hints.🔎 Proposed fix
Add build tags to this file or move the krunkit-specific logic to a Darwin-only file:
Option 1: Add build tags to this section
Option 2: Move signing to a platform-specific file
Create
cache_darwin.go:Then call it from the main cacheExecutable function (with a no-op implementation in
cache_other.gofor other platforms).🧰 Tools
🪛 GitHub Actions: Build Windows chocolatey
[error] 147-147: undefined: constants.KrunkitCommand
🪛 GitHub Actions: Test OKD bundle
[error] 147-147: undefined: constants.KrunkitCommand
🪛 GitHub Check: build (ubuntu-latest, 1.24)
[failure] 147-147:
undefined: constants.KrunkitCommand
🪛 GitHub Check: build (windows-2022, 1.24)
[failure] 147-147:
undefined: constants.KrunkitCommand
🪛 GitHub Check: Run OKD bundle with crc (1.24)
[failure] 147-147:
undefined: constants.KrunkitCommand
🤖 Prompt for AI Agents