export async function installCli()

in packages/core/src/shared/utilities/cliUtils.ts [181:321]


export async function installCli(
    cli: AwsClis,
    confirm: boolean,
    skipPostInstallValidation: boolean = false
): Promise<string | never> {
    const cliToInstall = awsClis[cli]
    if (!cliToInstall) {
        throw new InstallerError(`Invalid not found for CLI: ${cli}`)
    }
    let result: Result = 'Succeeded'
    let reason: string = ''

    let tempDir: string | undefined
    const manualInstall = localize('AWS.cli.manualInstall', 'Install manually...')

    try {
        // get install uri to see if auto-install is enabled.
        if (!getOsCliSource(awsClis[cli])) {
            // Installer not supported on this platform, direct custoemr to manual install
            const selection = await vscode.window.showInformationMessage(
                localize(
                    'AWS.cli.autoInstallNotSupported',
                    'Auto install of {0} CLI is not supported on your platform',
                    cliToInstall.name
                ),
                manualInstall
            )
            if (selection === manualInstall) {
                void openUrl(vscode.Uri.parse(cliToInstall.manualInstallLink))
            }
            throw new CancellationError('user')
        }

        const install = localize('AWS.generic.install', 'Install')
        const selection = !confirm
            ? install
            : await vscode.window.showInformationMessage(
                  localize(
                      'AWS.cli.installCliPrompt',
                      '{0} could not find {1} CLI. Install a local copy?',
                      localize('AWS.channel.aws.toolkit', '{0} Toolkit', getIdeProperties().company),
                      cliToInstall.name
                  ),
                  install,
                  manualInstall
              )

        if (selection !== install) {
            if (selection === manualInstall) {
                void openUrl(vscode.Uri.parse(cliToInstall.manualInstallLink))
            }
            throw new CancellationError('user')
        }
        const timeout = new Timeout(20 * 60 * 1000)
        const progress = await showMessageWithCancel(
            localize('AWS.cli.installProgress', 'Installing: {0} CLI', cliToInstall.name),
            timeout
        )

        tempDir = await makeTemporaryToolkitFolder()
        let cliPath: string | undefined
        try {
            switch (cli) {
                case 'session-manager-plugin':
                    cliPath = await installSsmCli(tempDir, progress, timeout)
                    break
                case 'aws-cli':
                case 'sam-cli':
                case 'docker':
                    cliPath = await installGui(cli, tempDir, progress, timeout)
                    break
                default:
                    throw new InstallerError(`Invalid not found for CLI: ${cli}`)
            }
        } finally {
            timeout.dispose()
        }

        if (skipPostInstallValidation) {
            return cliToInstall.name
        }
        // validate
        if (cli === 'session-manager-plugin') {
            if (!cliPath || !(await hasCliCommand(cliToInstall, false))) {
                throw new InstallerError('Could not verify installed CLIs')
            }
        } else {
            if (!cliPath) {
                // install success but wrong exit code
                const toolPath = await hasCliCommand(cliToInstall, true)
                if (!toolPath) {
                    throw new InstallerError('Could not verify installed CLIs')
                }
                return toolPath
            }
        }

        return cliPath
    } catch (err) {
        const error = err as Error
        if (CancellationError.isUserCancelled(err)) {
            result = 'Cancelled'
            getLogger().info(`Cancelled installation for: ${cli}`)
            throw err
        }

        result = 'Failed'

        void vscode.window
            .showErrorMessage(
                localize('AWS.cli.failedInstall', 'Installation of the {0} CLI failed.', cliToInstall.name),
                manualInstall
            )
            .then((button) => {
                if (button === manualInstall) {
                    void openUrl(vscode.Uri.parse(cliToInstall.manualInstallLink))
                }
            })
        reason = error.message
        throw err
    } finally {
        if (tempDir) {
            getLogger().info('Cleaning up installer...')
            // nonblocking: use `then`
            tryRemoveFolder(tempDir).then(
                (success) => {
                    if (success) {
                        getLogger().info('Removed installer.')
                    } else {
                        getLogger().warn(`installCli: failed to clean up temp directory: ${tempDir}`)
                    }
                },
                (e) => {
                    getLogger().error('installCli: tryRemoveFolder failed: %s', (e as Error).message)
                }
            )
        }
        getLogger().info(`${cli} installation: ${result}`)
        telemetry.aws_toolInstallation.emit({ result, reason, toolId: cli })
    }
}