AddMachine provisions a remote machine and adds it to the cluster. It returns a cluster client and a machine client. The cluster client is connected to the existing machine in the cluster. It was used to add the new machine to the cluster. The machine client is connected to the new machine and can b
(ctx context.Context, opts AddMachineOptions)
| 332 | // cluster. The machine client is connected to the new machine and can be used to interact with it. |
| 333 | // Both client should be closed after use by the caller. |
| 334 | func (cli *CLI) AddMachine(ctx context.Context, opts AddMachineOptions) (_ *client.Client, _ *client.Client, err error) { |
| 335 | contextName := cli.ContextOverrideOrCurrent() |
| 336 | c, err := cli.ConnectCluster(ctx) |
| 337 | if err != nil { |
| 338 | return nil, nil, fmt.Errorf("connect to cluster (context '%s'): %w", contextName, err) |
| 339 | } |
| 340 | defer func() { |
| 341 | if err != nil { |
| 342 | c.Close() |
| 343 | } |
| 344 | }() |
| 345 | |
| 346 | machineClient, err := provisionOrConnectRemoteMachine(ctx, opts.RemoteMachine, opts.SkipInstall, opts.Version) |
| 347 | if err != nil { |
| 348 | return nil, nil, err |
| 349 | } |
| 350 | defer func() { |
| 351 | if err != nil { |
| 352 | machineClient.Close() |
| 353 | } |
| 354 | }() |
| 355 | // IMPORTANT: 'err' is a named return value so the deferred cleanups above observe it on every error return. |
| 356 | // Do not shadow it with ':=' in a nested scope, or the deferred client cleanup would be skipped on error. |
| 357 | |
| 358 | // Check if the machine is already initialised as a cluster member and prompt the user to reset it first. |
| 359 | inspectResp, err := machineClient.MachineClient.InspectMachine(ctx, nil) |
| 360 | if err != nil { |
| 361 | return nil, nil, fmt.Errorf("inspect machine: %w", err) |
| 362 | } |
| 363 | minfo := inspectResp.Machines[0].Machine |
| 364 | if minfo.Id != "" { |
| 365 | // Check if the machine is already a member of this cluster. |
| 366 | var machines api.MachineMembersList |
| 367 | machines, err = c.ListMachines(ctx, nil) |
| 368 | if err != nil { |
| 369 | return nil, nil, fmt.Errorf("list cluster machines: %w", err) |
| 370 | } |
| 371 | if slices.ContainsFunc(machines, func(m *pb.MachineMember) bool { |
| 372 | return m.Machine.Id == minfo.Id |
| 373 | }) { |
| 374 | return nil, nil, fmt.Errorf("machine is already a member of this cluster (%s)", minfo.Name) |
| 375 | } |
| 376 | |
| 377 | if !opts.AutoConfirm { |
| 378 | if err = promptResetMachine(); err != nil { |
| 379 | return nil, nil, err |
| 380 | } |
| 381 | } |
| 382 | if err = resetAndWaitMachine(ctx, machineClient.MachineClient); err != nil { |
| 383 | return nil, nil, err |
| 384 | } |
| 385 | } |
| 386 | |
| 387 | // Check machine meets all necessary system requirements before proceeding. |
| 388 | checkResp, err := machineClient.CheckPrerequisites(ctx, &emptypb.Empty{}) |
| 389 | // TODO(lhf): remove Unimplemented check when v0.9.0 is released. |
| 390 | if err != nil { |
| 391 | if status.Convert(err).Code() != codes.Unimplemented { |
nothing calls this directly
no test coverage detected