( inventory coreansible.InventoryResult, limit string, dryRun bool, timeout time.Duration, )
| 1179 | } |
| 1180 | |
| 1181 | func (p *Plugin) runBootstrapDirect( |
| 1182 | inventory coreansible.InventoryResult, |
| 1183 | limit string, |
| 1184 | dryRun bool, |
| 1185 | timeout time.Duration, |
| 1186 | ) { |
| 1187 | bootstrap := p.ansiblePluginConfig().Bootstrap |
| 1188 | targets := selectDirectBootstrapTargets(inventory.Hosts, limit) |
| 1189 | if len(targets) == 0 { |
| 1190 | p.app.ShowMessageSafe("No matching bootstrap targets for the selected scope/limit.") |
| 1191 | return |
| 1192 | } |
| 1193 | |
| 1194 | var keyContent string |
| 1195 | if bootstrap.InstallAuthorizedKey { |
| 1196 | keyPath := strings.TrimSpace(bootstrap.SSHPublicKeyFile) |
| 1197 | if keyPath == "" { |
| 1198 | p.app.ShowMessageSafe("Bootstrap ssh_public_key_file is required when install_authorized_key is enabled.") |
| 1199 | return |
| 1200 | } |
| 1201 | // #nosec G304 -- path is a local, user-configured key file for bootstrap. |
| 1202 | data, err := os.ReadFile(keyPath) |
| 1203 | if err != nil { |
| 1204 | p.app.ShowMessageSafe(fmt.Sprintf("Failed to read SSH public key file: %v", err)) |
| 1205 | return |
| 1206 | } |
| 1207 | keyContent = strings.TrimSpace(string(data)) |
| 1208 | if keyContent == "" { |
| 1209 | p.app.ShowMessageSafe("SSH public key file is empty.") |
| 1210 | return |
| 1211 | } |
| 1212 | } |
| 1213 | |
| 1214 | appendLiveLine, closeLive := p.showLiveOutputModal("Running direct bootstrap workflow...") |
| 1215 | ctx, cancel := context.WithTimeout(context.Background(), timeout) |
| 1216 | p.setRunningCancel(cancel) |
| 1217 | |
| 1218 | go func() { |
| 1219 | defer cancel() |
| 1220 | defer p.clearRunningCancel() |
| 1221 | |
| 1222 | results := make([]directBootstrapResult, len(targets)) |
| 1223 | parallelism := bootstrap.Parallelism |
| 1224 | if parallelism <= 0 { |
| 1225 | parallelism = 1 |
| 1226 | } |
| 1227 | sem := make(chan struct{}, parallelism) |
| 1228 | var wg sync.WaitGroup |
| 1229 | |
| 1230 | nodeByName := map[string]coreansible.InventoryHost{} |
| 1231 | for _, host := range inventory.Hosts { |
| 1232 | if host.Vars["pvetui_kind"] == hostKindNode { |
| 1233 | nodeByName[host.Vars["pvetui_node"]] = host |
| 1234 | } |
| 1235 | } |
| 1236 | guestByNodeID := map[string]*api.VM{} |
| 1237 | for _, vm := range p.app.VMList().GetVMs() { |
| 1238 | if vm == nil { |
no test coverage detected