chore: zsh prompt alignment

This commit is contained in:
Harivansh Rathi 2026-04-10 00:57:59 +00:00
parent 3eb610b703
commit 39f8882c30
8 changed files with 56 additions and 11 deletions

View file

@ -17,7 +17,7 @@ type Machine struct {
} }
type GuestConfig struct { type GuestConfig struct {
Hostname string `json:"hostname,omitempty"` Hostname string `json:"hostname,omitempty"`
AuthorizedKeys []string `json:"authorized_keys,omitempty"` AuthorizedKeys []string `json:"authorized_keys,omitempty"`
TrustedUserCAKeys []string `json:"trusted_user_ca_keys,omitempty"` TrustedUserCAKeys []string `json:"trusted_user_ca_keys,omitempty"`
LoginWebhook *GuestLoginWebhook `json:"login_webhook,omitempty"` LoginWebhook *GuestLoginWebhook `json:"login_webhook,omitempty"`

View file

@ -41,7 +41,7 @@ type Daemon struct {
store store.Store store store.Store
runtime Runtime runtime Runtime
reconfigureGuestIdentity func(context.Context, string, contracthost.MachineID) error reconfigureGuestIdentity func(context.Context, string, contracthost.MachineID, *contracthost.GuestConfig) error
readGuestSSHPublicKey func(context.Context, string) (string, error) readGuestSSHPublicKey func(context.Context, string) (string, error)
syncGuestFilesystem func(context.Context, string) error syncGuestFilesystem func(context.Context, string) error

View file

@ -128,6 +128,7 @@ func TestCreateMachineStagesArtifactsAndPersistsState(t *testing.T) {
RootFSURL: server.URL + "/rootfs", RootFSURL: server.URL + "/rootfs",
}, },
GuestConfig: &contracthost.GuestConfig{ GuestConfig: &contracthost.GuestConfig{
Hostname: "workbox",
AuthorizedKeys: []string{ AuthorizedKeys: []string{
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestOverrideKey daemon-test", "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestOverrideKey daemon-test",
}, },
@ -179,7 +180,7 @@ func TestCreateMachineStagesArtifactsAndPersistsState(t *testing.T) {
if !ok { if !ok {
t.Fatalf("mmds payload type mismatch: got %T", runtime.lastSpec.MMDS.Data) t.Fatalf("mmds payload type mismatch: got %T", runtime.lastSpec.MMDS.Data)
} }
if payload.Latest.MetaData.Hostname != "vm-1" { if payload.Latest.MetaData.Hostname != "workbox" {
t.Fatalf("mmds hostname mismatch: got %q", payload.Latest.MetaData.Hostname) t.Fatalf("mmds hostname mismatch: got %q", payload.Latest.MetaData.Hostname)
} }
authorizedKeys := strings.Join(payload.Latest.MetaData.AuthorizedKeys, "\n") authorizedKeys := strings.Join(payload.Latest.MetaData.AuthorizedKeys, "\n")
@ -340,7 +341,7 @@ func TestRestoreSnapshotFallsBackToLocalSnapshotNetwork(t *testing.T) {
t.Fatalf("create daemon: %v", err) t.Fatalf("create daemon: %v", err)
} }
stubGuestSSHPublicKeyReader(hostDaemon) stubGuestSSHPublicKeyReader(hostDaemon)
hostDaemon.reconfigureGuestIdentity = func(context.Context, string, contracthost.MachineID) error { return nil } hostDaemon.reconfigureGuestIdentity = func(context.Context, string, contracthost.MachineID, *contracthost.GuestConfig) error { return nil }
artifactRef := contracthost.ArtifactRef{KernelImageURL: "kernel", RootFSURL: "rootfs"} artifactRef := contracthost.ArtifactRef{KernelImageURL: "kernel", RootFSURL: "rootfs"}
kernelPath := filepath.Join(root, "artifact-kernel") kernelPath := filepath.Join(root, "artifact-kernel")
@ -397,6 +398,7 @@ func TestRestoreSnapshotFallsBackToLocalSnapshotNetwork(t *testing.T) {
{ID: "disk-system", Kind: contracthost.SnapshotArtifactKindDisk, Name: "system.img", DownloadURL: server.URL + "/system"}, {ID: "disk-system", Kind: contracthost.SnapshotArtifactKindDisk, Name: "system.img", DownloadURL: server.URL + "/system"},
}, },
}, },
GuestConfig: &contracthost.GuestConfig{Hostname: "restored-shell"},
}) })
if err != nil { if err != nil {
t.Fatalf("restore snapshot: %v", err) t.Fatalf("restore snapshot: %v", err)
@ -462,9 +464,11 @@ func TestRestoreSnapshotUsesDurableSnapshotSpec(t *testing.T) {
stubGuestSSHPublicKeyReader(hostDaemon) stubGuestSSHPublicKeyReader(hostDaemon)
var reconfiguredHost string var reconfiguredHost string
var reconfiguredMachine contracthost.MachineID var reconfiguredMachine contracthost.MachineID
hostDaemon.reconfigureGuestIdentity = func(_ context.Context, host string, machineID contracthost.MachineID) error { var reconfiguredConfig *contracthost.GuestConfig
hostDaemon.reconfigureGuestIdentity = func(_ context.Context, host string, machineID contracthost.MachineID, guestConfig *contracthost.GuestConfig) error {
reconfiguredHost = host reconfiguredHost = host
reconfiguredMachine = machineID reconfiguredMachine = machineID
reconfiguredConfig = cloneGuestConfig(guestConfig)
return nil return nil
} }
@ -497,6 +501,7 @@ func TestRestoreSnapshotUsesDurableSnapshotSpec(t *testing.T) {
{ID: "disk-user-0", Kind: contracthost.SnapshotArtifactKindDisk, Name: "user-0.img", DownloadURL: server.URL + "/user-0"}, {ID: "disk-user-0", Kind: contracthost.SnapshotArtifactKindDisk, Name: "user-0.img", DownloadURL: server.URL + "/user-0"},
}, },
}, },
GuestConfig: &contracthost.GuestConfig{Hostname: "restored-shell"},
}) })
if err != nil { if err != nil {
t.Fatalf("restore snapshot: %v", err) t.Fatalf("restore snapshot: %v", err)
@ -525,6 +530,9 @@ func TestRestoreSnapshotUsesDurableSnapshotSpec(t *testing.T) {
if reconfiguredHost != "127.0.0.1" || reconfiguredMachine != "restored" { if reconfiguredHost != "127.0.0.1" || reconfiguredMachine != "restored" {
t.Fatalf("guest identity reconfigure mismatch: host=%q machine=%q", reconfiguredHost, reconfiguredMachine) t.Fatalf("guest identity reconfigure mismatch: host=%q machine=%q", reconfiguredHost, reconfiguredMachine)
} }
if reconfiguredConfig == nil || reconfiguredConfig.Hostname != "restored-shell" {
t.Fatalf("guest identity hostname mismatch: %#v", reconfiguredConfig)
}
machine, err := fileStore.GetMachine(context.Background(), "restored") machine, err := fileStore.GetMachine(context.Background(), "restored")
if err != nil { if err != nil {

View file

@ -251,9 +251,13 @@ func (d *Daemon) mergedGuestConfig(config *contracthost.GuestConfig) (*contracth
} }
merged := &contracthost.GuestConfig{ merged := &contracthost.GuestConfig{
Hostname: "",
AuthorizedKeys: authorizedKeys, AuthorizedKeys: authorizedKeys,
TrustedUserCAKeys: nil, TrustedUserCAKeys: nil,
} }
if config != nil {
merged.Hostname = strings.TrimSpace(config.Hostname)
}
if strings.TrimSpace(d.config.GuestLoginCAPublicKey) != "" { if strings.TrimSpace(d.config.GuestLoginCAPublicKey) != "" {
merged.TrustedUserCAKeys = append(merged.TrustedUserCAKeys, d.config.GuestLoginCAPublicKey) merged.TrustedUserCAKeys = append(merged.TrustedUserCAKeys, d.config.GuestLoginCAPublicKey)
} }
@ -447,6 +451,21 @@ func validateGuestConfig(config *contracthost.GuestConfig) error {
if config == nil { if config == nil {
return nil return nil
} }
if config.Hostname != "" {
hostname := strings.TrimSpace(config.Hostname)
if hostname == "" {
return fmt.Errorf("guest_config.hostname is required")
}
if len(hostname) > 63 {
return fmt.Errorf("guest_config.hostname must be 63 characters or fewer")
}
if strings.ContainsAny(hostname, "/\\") {
return fmt.Errorf("guest_config.hostname must not contain path separators")
}
if strings.ContainsAny(hostname, " \t\r\n") {
return fmt.Errorf("guest_config.hostname must not contain whitespace")
}
}
for i, key := range config.AuthorizedKeys { for i, key := range config.AuthorizedKeys {
if strings.TrimSpace(key) == "" { if strings.TrimSpace(key) == "" {
return fmt.Errorf("guest_config.authorized_keys[%d] is required", i) return fmt.Errorf("guest_config.authorized_keys[%d] is required", i)

View file

@ -10,9 +10,9 @@ import (
contracthost "github.com/getcompanion-ai/computer-host/contract" contracthost "github.com/getcompanion-ai/computer-host/contract"
) )
func (d *Daemon) reconfigureGuestIdentityOverSSH(ctx context.Context, runtimeHost string, machineID contracthost.MachineID) error { func (d *Daemon) reconfigureGuestIdentityOverSSH(ctx context.Context, runtimeHost string, machineID contracthost.MachineID, guestConfig *contracthost.GuestConfig) error {
runtimeHost = strings.TrimSpace(runtimeHost) runtimeHost = strings.TrimSpace(runtimeHost)
machineName := strings.TrimSpace(string(machineID)) machineName := guestHostname(machineID, guestConfig)
if runtimeHost == "" { if runtimeHost == "" {
return fmt.Errorf("guest runtime host is required") return fmt.Errorf("guest runtime host is required")
} }

View file

@ -35,6 +35,7 @@ func cloneGuestConfig(config *contracthost.GuestConfig) *contracthost.GuestConfi
return nil return nil
} }
cloned := &contracthost.GuestConfig{ cloned := &contracthost.GuestConfig{
Hostname: config.Hostname,
AuthorizedKeys: append([]string(nil), config.AuthorizedKeys...), AuthorizedKeys: append([]string(nil), config.AuthorizedKeys...),
TrustedUserCAKeys: append([]string(nil), config.TrustedUserCAKeys...), TrustedUserCAKeys: append([]string(nil), config.TrustedUserCAKeys...),
} }
@ -45,8 +46,17 @@ func cloneGuestConfig(config *contracthost.GuestConfig) *contracthost.GuestConfi
return cloned return cloned
} }
func guestHostname(machineID contracthost.MachineID, guestConfig *contracthost.GuestConfig) string {
if guestConfig != nil {
if hostname := strings.TrimSpace(guestConfig.Hostname); hostname != "" {
return hostname
}
}
return strings.TrimSpace(string(machineID))
}
func (d *Daemon) guestMetadataSpec(machineID contracthost.MachineID, guestConfig *contracthost.GuestConfig) (*firecracker.MMDSSpec, error) { func (d *Daemon) guestMetadataSpec(machineID contracthost.MachineID, guestConfig *contracthost.GuestConfig) (*firecracker.MMDSSpec, error) {
name := strings.TrimSpace(string(machineID)) name := guestHostname(machineID, guestConfig)
if name == "" { if name == "" {
return nil, fmt.Errorf("machine id is required") return nil, fmt.Errorf("machine id is required")
} }

View file

@ -448,7 +448,7 @@ func TestRestoreSnapshotDeletesSystemVolumeRecordWhenRelayAllocationFails(t *tes
t.Fatalf("create daemon: %v", err) t.Fatalf("create daemon: %v", err)
} }
stubGuestSSHPublicKeyReader(hostDaemon) stubGuestSSHPublicKeyReader(hostDaemon)
hostDaemon.reconfigureGuestIdentity = func(context.Context, string, contracthost.MachineID) error { return nil } hostDaemon.reconfigureGuestIdentity = func(context.Context, string, contracthost.MachineID, *contracthost.GuestConfig) error { return nil }
artifactRef := contracthost.ArtifactRef{KernelImageURL: "kernel", RootFSURL: "rootfs"} artifactRef := contracthost.ArtifactRef{KernelImageURL: "kernel", RootFSURL: "rootfs"}
kernelPath := filepath.Join(root, "artifact-kernel") kernelPath := filepath.Join(root, "artifact-kernel")
@ -695,7 +695,7 @@ func TestRestoreSnapshotCleansStagingArtifactsAfterSuccess(t *testing.T) {
t.Fatalf("create daemon: %v", err) t.Fatalf("create daemon: %v", err)
} }
stubGuestSSHPublicKeyReader(hostDaemon) stubGuestSSHPublicKeyReader(hostDaemon)
hostDaemon.reconfigureGuestIdentity = func(context.Context, string, contracthost.MachineID) error { return nil } hostDaemon.reconfigureGuestIdentity = func(context.Context, string, contracthost.MachineID, *contracthost.GuestConfig) error { return nil }
server := newRestoreArtifactServer(t, map[string][]byte{ server := newRestoreArtifactServer(t, map[string][]byte{
"/kernel": []byte("kernel"), "/kernel": []byte("kernel"),

View file

@ -222,6 +222,13 @@ func (d *Daemon) RestoreSnapshot(ctx context.Context, snapshotID contracthost.Sn
if err := validateArtifactRef(req.Artifact); err != nil { if err := validateArtifactRef(req.Artifact); err != nil {
return nil, err return nil, err
} }
if err := validateGuestConfig(req.GuestConfig); err != nil {
return nil, err
}
guestConfig, err := d.mergedGuestConfig(req.GuestConfig)
if err != nil {
return nil, err
}
unlock := d.lockMachine(req.MachineID) unlock := d.lockMachine(req.MachineID)
defer unlock() defer unlock()
@ -349,7 +356,7 @@ func (d *Daemon) RestoreSnapshot(ctx context.Context, snapshotID contracthost.Sn
clearOperation = true clearOperation = true
return nil, fmt.Errorf("wait for restored guest ready: %w", err) return nil, fmt.Errorf("wait for restored guest ready: %w", err)
} }
if err := d.reconfigureGuestIdentity(ctx, machineState.RuntimeHost, req.MachineID); err != nil { if err := d.reconfigureGuestIdentity(ctx, machineState.RuntimeHost, req.MachineID, guestConfig); err != nil {
_ = d.runtime.Delete(ctx, *machineState) _ = d.runtime.Delete(ctx, *machineState)
_ = os.RemoveAll(filepath.Dir(newSystemDiskPath)) _ = os.RemoveAll(filepath.Dir(newSystemDiskPath))
clearOperation = true clearOperation = true
@ -406,6 +413,7 @@ func (d *Daemon) RestoreSnapshot(ctx context.Context, snapshotID contracthost.Sn
machineRecord := model.MachineRecord{ machineRecord := model.MachineRecord{
ID: req.MachineID, ID: req.MachineID,
Artifact: req.Artifact, Artifact: req.Artifact,
GuestConfig: cloneGuestConfig(guestConfig),
SystemVolumeID: systemVolumeID, SystemVolumeID: systemVolumeID,
UserVolumeIDs: restoredUserVolumeIDs, UserVolumeIDs: restoredUserVolumeIDs,
RuntimeHost: machineState.RuntimeHost, RuntimeHost: machineState.RuntimeHost,