Inspect returns err only when the instance does not exist (os.ErrNotExist). Other errors are returned as *Instance.Errors.
(ctx context.Context, instName string)
| 34 | // Inspect returns err only when the instance does not exist (os.ErrNotExist). |
| 35 | // Other errors are returned as *Instance.Errors. |
| 36 | func Inspect(ctx context.Context, instName string) (*limatype.Instance, error) { |
| 37 | inst := &limatype.Instance{ |
| 38 | Name: instName, |
| 39 | // TODO: support customizing hostname |
| 40 | Hostname: hostname.FromInstName(instName), |
| 41 | Status: limatype.StatusUnknown, |
| 42 | } |
| 43 | // InstanceDir validates the instName but does not check whether the instance exists |
| 44 | instDir, err := dirnames.InstanceDir(instName) |
| 45 | if err != nil { |
| 46 | return nil, err |
| 47 | } |
| 48 | // Make sure inst.Dir is set, even when YAML validation fails |
| 49 | inst.Dir = instDir |
| 50 | yamlPath := filepath.Join(instDir, filenames.LimaYAML) |
| 51 | y, err := LoadYAMLByFilePath(ctx, yamlPath) |
| 52 | if err != nil { |
| 53 | if errors.Is(err, os.ErrNotExist) { |
| 54 | return nil, err |
| 55 | } |
| 56 | inst.Errors = append(inst.Errors, err) |
| 57 | return inst, nil |
| 58 | } |
| 59 | inst.Config = y |
| 60 | inst.Arch = *y.Arch |
| 61 | inst.VMType = *y.VMType |
| 62 | inst.SSHAddress = "127.0.0.1" |
| 63 | inst.SSHLocalPort = *y.SSH.LocalPort // maybe 0 |
| 64 | inst.SSHConfigFile = filepath.Join(instDir, filenames.SSHConfig) |
| 65 | inst.HostAgentPID, err = ReadPIDFile(filepath.Join(instDir, filenames.HostAgentPID)) |
| 66 | if err != nil { |
| 67 | inst.Status = limatype.StatusBroken |
| 68 | inst.Errors = append(inst.Errors, err) |
| 69 | } |
| 70 | |
| 71 | if inst.HostAgentPID != 0 { |
| 72 | haSock := filepath.Join(instDir, filenames.HostAgentSock) |
| 73 | haClient, err := hostagentclient.NewHostAgentClient(haSock) |
| 74 | if err != nil { |
| 75 | inst.Status = limatype.StatusBroken |
| 76 | inst.Errors = append(inst.Errors, fmt.Errorf("failed to connect to %q: %w", haSock, err)) |
| 77 | } else { |
| 78 | ctx, cancel := context.WithTimeout(ctx, 3*time.Second) |
| 79 | defer cancel() |
| 80 | info, err := haClient.Info(ctx) |
| 81 | if err != nil { |
| 82 | inst.Status = limatype.StatusBroken |
| 83 | inst.Errors = append(inst.Errors, fmt.Errorf("failed to get Info from %q: %w", haSock, err)) |
| 84 | } else { |
| 85 | inst.SSHLocalPort = info.SSHLocalPort |
| 86 | inst.AutoStartedIdentifier = info.AutoStartedIdentifier |
| 87 | } |
| 88 | } |
| 89 | } |
| 90 | if inst.SSHLocalPort == 0 { |
| 91 | sshConfigPath := filepath.Join(instDir, filenames.SSHConfig) |
| 92 | if port, err := sshPortFromConfig(sshConfigPath); err == nil { |
| 93 | inst.SSHLocalPort = port |