switch-profile 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/cli.js +92 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npx switch-profile
|
|
|
21
21
|
│ ○ globex-dev ReadOnly 333333333333 us-east-1
|
|
22
22
|
│ ○ initech-dev Admin 444444444444 eu-west-1
|
|
23
23
|
│
|
|
24
|
-
│ [Log in] [Add] [Remove] [Log out] [Settings]
|
|
24
|
+
│ [Log in] [Add] [Rename] [Remove] [Log out] [Settings]
|
|
25
25
|
└ ↑↓ choose · enter switch · tab actions · esc quit
|
|
26
26
|
```
|
|
27
27
|
|
|
@@ -100,7 +100,7 @@ No profiles yet? `switch-profile` starts the **Add profiles** flow. To import ev
|
|
|
100
100
|
Running `sp` (or `npx switch-profile`) with no arguments opens the home screen:
|
|
101
101
|
|
|
102
102
|
- **Type and press Enter** to switch. That's the whole path for everyday use.
|
|
103
|
-
- **Tab** moves to the action bar below the list, which is always visible however many profiles you have: **Log in**, **Add**, **Remove**, **Log out**, **Settings**. Use ←→ to choose and Enter to open.
|
|
103
|
+
- **Tab** moves to the action bar below the list, which is always visible however many profiles you have: **Log in**, **Add**, **Rename**, **Remove**, **Log out**, **Settings**. Use ←→ to choose and Enter to open.
|
|
104
104
|
- **Every action opens as a page and comes back** to the home screen when it's done. **Esc** goes back from a page, and quits from the home screen.
|
|
105
105
|
- A switch ends the session, which is what lets `sp` set `AWS_PROFILE` in your terminal.
|
|
106
106
|
|
|
@@ -115,6 +115,7 @@ Running `sp` (or `npx switch-profile`) with no arguments opens the home screen:
|
|
|
115
115
|
| `logout [--yes]` | Ends every SSO session on this machine (`aws sso logout`, plus `aws logout --all` on AWS CLI 2.32+). |
|
|
116
116
|
| `add` | Adds profiles: import accounts from an SSO portal (recommended), a single SSO profile, a console sign-in profile, or access keys. |
|
|
117
117
|
| `add --from-sso [session]` | Imports or re-syncs every account and role of an `[sso-session]`. Options: `--region`, `--prefix`, `--prune`, `--yes`. |
|
|
118
|
+
| `rename [profile] [new-name]` | Renames a profile (alias `mv`), for example an imported `acme-prod-workloads-administratoraccess` to `acme-prod`. Also updates `source_profile` references, the default profile and the home screen order. SSO logins are kept. Scripts, terminals and tools that use the old name need the new one. |
|
|
118
119
|
| `remove [profiles...] [--yes]` | Removes profiles (alias `rm`). The current default cannot be removed. |
|
|
119
120
|
| `settings` | Per-terminal switching, SSO login mode, legacy SSO upgrade. |
|
|
120
121
|
|
|
@@ -155,7 +156,7 @@ sp add # then choose "Accounts from an SSO portal"
|
|
|
155
156
|
|
|
156
157
|
1. Pick an existing `[sso-session]` or create one: start URL (e.g. `https://acme.awsapps.com/start`), SSO region (where Identity Center lives, not where you deploy), and a short name, usually the client.
|
|
157
158
|
2. Log in if needed.
|
|
158
|
-
3. `switch-profile` lists every account and role you can access, then asks for a default region and a name prefix. Profiles are named `<prefix>-<account-name>-<role>`, for example `acme-prod-workloads-admin`.
|
|
159
|
+
3. `switch-profile` lists every account and role you can access, then asks for a default region and a name prefix. Profiles are named `<prefix>-<account-name>-<role>`, for example `acme-prod-workloads-admin`. Rename any of them later with `sp rename` (re-imports still recognize them).
|
|
159
160
|
4. A preview shows the new profiles, the ones already set up, and the ones that no longer exist. Then pick the new profiles to add: all are selected, so press Enter to add everything, or untick the ones you don't want (type to search by name, account or role).
|
|
160
161
|
|
|
161
162
|
Run it again later to pick up new accounts. Account/role pairs that already have a profile are never duplicated, whatever its name. Generated profiles that no longer exist can be pruned (after a backup); profiles you wrote by hand are never pruned.
|
|
@@ -251,7 +252,7 @@ The SSO login is missing or expired. Run `sp login` (or just switch to the profi
|
|
|
251
252
|
|
|
252
253
|
### SSO login hangs on a remote machine
|
|
253
254
|
|
|
254
|
-
The AWS CLI is waiting for a browser on the remote machine. Run `sp login --device`, or set **Settings > SSO login** to always use a device code.
|
|
255
|
+
The AWS CLI is waiting for a browser on the remote machine. Run `sp login --device`, or set **Settings > SSO login** to always use a device code. Since 2.3.1, `sp add` > A single SSO profile also uses a device code automatically over SSH; with an older version, press Ctrl+C and update (`sp` always runs the latest).
|
|
255
256
|
|
|
256
257
|
### The code is not in my clipboard over SSH
|
|
257
258
|
|
package/dist/cli.js
CHANGED
|
@@ -5419,7 +5419,7 @@ var require_package = __commonJS({
|
|
|
5419
5419
|
"package.json"(exports2, module2) {
|
|
5420
5420
|
module2.exports = {
|
|
5421
5421
|
name: "switch-profile",
|
|
5422
|
-
version: "2.
|
|
5422
|
+
version: "2.4.0",
|
|
5423
5423
|
main: "index.js",
|
|
5424
5424
|
bin: {
|
|
5425
5425
|
"switch-profile": "index.js"
|
|
@@ -5602,6 +5602,9 @@ var require_ini = __commonJS({
|
|
|
5602
5602
|
return str;
|
|
5603
5603
|
let newline = detectNewline(str);
|
|
5604
5604
|
return tidy(stringify(blocks.filter((b3) => b3.name !== name), newline), newline);
|
|
5605
|
+
}, renameSection = (str, name, newName) => {
|
|
5606
|
+
let blocks = parse(str), block2 = findBlock(blocks, name);
|
|
5607
|
+
return block2 ? (block2.lines[0] = `[${newName}]`, stringify(blocks, detectNewline(str))) : str;
|
|
5605
5608
|
}, setKeys = (str, name, changes) => {
|
|
5606
5609
|
let blocks = parse(str), block2 = findBlock(blocks, name);
|
|
5607
5610
|
if (!block2)
|
|
@@ -5636,6 +5639,7 @@ var require_ini = __commonJS({
|
|
|
5636
5639
|
getSection,
|
|
5637
5640
|
setSection,
|
|
5638
5641
|
removeSection,
|
|
5642
|
+
renameSection,
|
|
5639
5643
|
setKeys
|
|
5640
5644
|
};
|
|
5641
5645
|
}
|
|
@@ -5755,6 +5759,19 @@ var require_transforms = __commonJS({
|
|
|
5755
5759
|
for (let name of stale)
|
|
5756
5760
|
config = ini.removeSection(config, configSectionName(config, name)), removed.push(name);
|
|
5757
5761
|
return { config, added, addedEntries, existing, stale, removed };
|
|
5762
|
+
}, escapeRegex = (text2) => text2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), renameProfile = (configStr, credsStr, from, to) => {
|
|
5763
|
+
let section = from == "default" ? null : configSectionName(configStr, from);
|
|
5764
|
+
if (!section)
|
|
5765
|
+
throw new Error(`Profile ${from} not found in ~/.aws/config.`);
|
|
5766
|
+
if (to == "default" || configSectionName(configStr, to) || ini.getSection(credsStr, to))
|
|
5767
|
+
throw new Error(`Profile ${to} already exists.`);
|
|
5768
|
+
let config = ini.renameSection(configStr, section, `profile ${to}`), creds = ini.renameSection(credsStr, from, to), sources = [], processes = [], mentions = new RegExp(`--profile[\\s=]+["']?${escapeRegex(from)}(?=["'\\s]|$)`);
|
|
5769
|
+
for (let s of ini.listSections(config).filter((s2) => s2 != "default" && !s2.startsWith("sso-session "))) {
|
|
5770
|
+
let params = ini.getSection(config, s), name = s.replace(/^profile\s+/, "");
|
|
5771
|
+
params.source_profile == from && (config = ini.setKeys(config, s, { source_profile: to }), sources.push(name)), params.credential_process && mentions.test(params.credential_process) && processes.push(name);
|
|
5772
|
+
}
|
|
5773
|
+
let defaults = ini.getSection(config, "default") || {}, wasDefault = defaults[NAME_KEY] == from;
|
|
5774
|
+
return wasDefault && (config = ini.setKeys(config, "default", { [NAME_KEY]: to, ...defaults.source_profile == from ? { source_profile: to } : {} })), { config, creds, sources, wasDefault, processes };
|
|
5758
5775
|
}, listSsoSessions = (configStr) => ini.listSections(configStr).filter((s) => s.startsWith("sso-session ")).map((s) => ({ name: s.replace(/^sso-session\s+/, ""), ...ini.getSection(configStr, s) })), addSsoSession = (configStr, { name, startUrl, region, version }) => ini.getSection(configStr, `sso-session ${name}`) ? configStr : ini.setSection(configStr, `sso-session ${name}`, [
|
|
5759
5776
|
["sso_start_url", startUrl],
|
|
5760
5777
|
["sso_region", region],
|
|
@@ -5781,7 +5798,8 @@ var require_transforms = __commonJS({
|
|
|
5781
5798
|
sessionNameFromUrl,
|
|
5782
5799
|
upgradeLegacySsoProfiles,
|
|
5783
5800
|
stampProfile,
|
|
5784
|
-
listProfiles
|
|
5801
|
+
listProfiles,
|
|
5802
|
+
renameProfile
|
|
5785
5803
|
};
|
|
5786
5804
|
}
|
|
5787
5805
|
});
|
|
@@ -6078,6 +6096,16 @@ var require_aws = __commonJS({
|
|
|
6078
6096
|
configStr = deleteProfileFromConfig(profile, configStr), credsStr = deleteProfileFromCreds(profile, credsStr);
|
|
6079
6097
|
}
|
|
6080
6098
|
updateConfig && await writeAwsFile(AWS_CONFIG_FILE, configStr), updateCreds && await writeAwsFile(AWS_CREDS_FILE, credsStr);
|
|
6099
|
+
})()), renameProfile = (from, to) => catchErrors((async () => {
|
|
6100
|
+
let errMsg = `Fail to rename profile ${from} to ${to}`, [configStrErrors, configStr] = await getConfigFile(), [credsStrErrors, credsStr] = await getCredsFile();
|
|
6101
|
+
if (configStrErrors || credsStrErrors)
|
|
6102
|
+
throw wrapErrors(errMsg, configStrErrors || credsStrErrors);
|
|
6103
|
+
try {
|
|
6104
|
+
let { config, creds, sources, wasDefault, processes } = transforms.renameProfile(configStr, credsStr, from, to);
|
|
6105
|
+
return await writeAwsFiles({ config, creds }), { sources, wasDefault, processes };
|
|
6106
|
+
} catch (err) {
|
|
6107
|
+
throw wrapErrors(errMsg, [err]);
|
|
6108
|
+
}
|
|
6081
6109
|
})()), createProfile = ({ name, aws_access_key_id, aws_secret_access_key, region }) => catchErrors((async () => {
|
|
6082
6110
|
await awsCliV2Exists();
|
|
6083
6111
|
let errMsg = "Fail to create AWS profile";
|
|
@@ -6104,10 +6132,11 @@ var require_aws = __commonJS({
|
|
|
6104
6132
|
`${transforms.VERSION_KEY} = ${CLI_VERSION2}`
|
|
6105
6133
|
].join(NL) + NL, append = (str, section) => (str || "").trim() ? str.replace(/\s+$/, "") + NL + NL + section : section;
|
|
6106
6134
|
await writeAwsFile(AWS_CONFIG_FILE, append(configStr, newConfig)), await writeAwsFile(AWS_CREDS_FILE, append(credsStr, newCreds));
|
|
6107
|
-
})()), createSsoProfile = (name) => catchErrors((async () => {
|
|
6135
|
+
})()), createSsoProfile = (name, { loginMode } = {}) => catchErrors((async () => {
|
|
6108
6136
|
await awsCliV2Exists();
|
|
6137
|
+
let flags = loginFlags(loginMode || "auto", { env: process.env, platform: process.platform, cliVersion: await getAwsCliVersion() });
|
|
6109
6138
|
try {
|
|
6110
|
-
await run2("aws", ["configure", "sso", "--profile", name], { tee: !0 });
|
|
6139
|
+
await run2("aws", ["configure", "sso", "--profile", name, ...flags], { tee: !0 });
|
|
6111
6140
|
} catch (err) {
|
|
6112
6141
|
throw Object.assign(new Error(`'aws configure sso' failed: ${err.message}`, { cause: err }), { output: err.output || "" });
|
|
6113
6142
|
}
|
|
@@ -6134,6 +6163,7 @@ var require_aws = __commonJS({
|
|
|
6134
6163
|
getDefaultProfile,
|
|
6135
6164
|
setDefaultProfile,
|
|
6136
6165
|
deleteProfiles,
|
|
6166
|
+
renameProfile,
|
|
6137
6167
|
createProfile,
|
|
6138
6168
|
createSsoProfile,
|
|
6139
6169
|
backupAwsFiles,
|
|
@@ -6150,7 +6180,7 @@ var require_aws = __commonJS({
|
|
|
6150
6180
|
// src/shell.js
|
|
6151
6181
|
var require_shell = __commonJS({
|
|
6152
6182
|
"src/shell.js"(exports2, module2) {
|
|
6153
|
-
var fs = require("fs"), { homedir } = require("os"), { join: join2, dirname: dirname2, basename } = require("path"), { run: run2 } = require_core(), log3 = require_log(), IS_WINDOWS = process.platform === "win32", IS_MAC = process.platform === "darwin", FUNCTION_NAME = "sp", BLOCK_START_PREFIX = "# >>> switch-profile", BLOCK_END = "# <<< switch-profile <<<", BLOCK_REGEX = /(^|\r?\n)# >>> switch-profile[^\n]*\r?\n[\s\S]*?# <<< switch-profile <<<[^\n]*(\r?\n)?/, blockStart = (version) => `${BLOCK_START_PREFIX} v${version} (managed by switch-profile, do not edit) >>>`, CLEARED_VARS = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN", "AWS_DEFAULT_PROFILE"], SUBCOMMANDS = ["status", "login", "logout", "add", "remove", "settings", "use"], PROFILES_SED = "sed -n 's/^\\[profile \\(.*\\)\\]$/\\1/p'", POSIX_FUNCTION = (shell) => `${FUNCTION_NAME}() {
|
|
6183
|
+
var fs = require("fs"), { homedir } = require("os"), { join: join2, dirname: dirname2, basename } = require("path"), { run: run2 } = require_core(), log3 = require_log(), IS_WINDOWS = process.platform === "win32", IS_MAC = process.platform === "darwin", FUNCTION_NAME = "sp", BLOCK_START_PREFIX = "# >>> switch-profile", BLOCK_END = "# <<< switch-profile <<<", BLOCK_REGEX = /(^|\r?\n)# >>> switch-profile[^\n]*\r?\n[\s\S]*?# <<< switch-profile <<<[^\n]*(\r?\n)?/, blockStart = (version) => `${BLOCK_START_PREFIX} v${version} (managed by switch-profile, do not edit) >>>`, CLEARED_VARS = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN", "AWS_DEFAULT_PROFILE"], SUBCOMMANDS = ["status", "login", "logout", "add", "remove", "settings", "use", "rename"], PROFILES_SED = "sed -n 's/^\\[profile \\(.*\\)\\]$/\\1/p'", POSIX_FUNCTION = (shell) => `${FUNCTION_NAME}() {
|
|
6154
6184
|
local __sp_file __sp_status
|
|
6155
6185
|
__sp_file="$(mktemp "\${TMPDIR:-/tmp}/switch-profile.XXXXXX")" || return 1
|
|
6156
6186
|
if [ -n "\${SWITCH_PROFILE_DEV_BIN:-}" ]; then
|
|
@@ -6170,7 +6200,7 @@ var require_shell = __commonJS({
|
|
|
6170
6200
|
items=(\${(f)"$(${PROFILES_SED} "\${AWS_CONFIG_FILE:-$HOME/.aws/config}" 2>/dev/null)"})
|
|
6171
6201
|
if (( CURRENT == 2 )); then
|
|
6172
6202
|
compadd -- $items ${SUBCOMMANDS.join(" ")}
|
|
6173
|
-
elif [[ $words[2] == (remove|rm) ]] || { (( CURRENT == 3 )) && [[ $words[2] == (use|login) ]] }; then
|
|
6203
|
+
elif [[ $words[2] == (remove|rm) ]] || { (( CURRENT == 3 )) && [[ $words[2] == (use|login|rename|mv) ]] }; then
|
|
6174
6204
|
compadd -- $items
|
|
6175
6205
|
fi
|
|
6176
6206
|
}
|
|
@@ -6181,7 +6211,7 @@ fi`, BASH_COMPLETION = `_switch_profile_complete() {
|
|
|
6181
6211
|
items="$(${PROFILES_SED} "\${AWS_CONFIG_FILE:-$HOME/.aws/config}" 2>/dev/null)"
|
|
6182
6212
|
if [ "$COMP_CWORD" -eq 1 ]; then
|
|
6183
6213
|
items="$items ${SUBCOMMANDS.join(" ")}"
|
|
6184
|
-
elif [ "$COMP_CWORD" -lt 2 ] || ! case "\${COMP_WORDS[1]}" in use|login|remove|rm) true ;; *) false ;; esac; then
|
|
6214
|
+
elif [ "$COMP_CWORD" -lt 2 ] || ! case "\${COMP_WORDS[1]}" in use|login|rename|mv|remove|rm) true ;; *) false ;; esac; then
|
|
6185
6215
|
return 0
|
|
6186
6216
|
elif [ "$COMP_CWORD" -gt 2 ] && [ "\${COMP_WORDS[1]}" != remove ] && [ "\${COMP_WORDS[1]}" != rm ]; then
|
|
6187
6217
|
return 0
|
|
@@ -6210,7 +6240,7 @@ function __switch_profile_profiles
|
|
|
6210
6240
|
end
|
|
6211
6241
|
for __sp_cmd in ${FUNCTION_NAME} switch-profile
|
|
6212
6242
|
complete -c $__sp_cmd -f -n 'test (count (commandline -opc)) -eq 1' -a '(__switch_profile_profiles) ${SUBCOMMANDS.join(" ")}'
|
|
6213
|
-
complete -c $__sp_cmd -f -n 'test (count (commandline -opc)) -eq 2; and __fish_seen_subcommand_from use login' -a '(__switch_profile_profiles)'
|
|
6243
|
+
complete -c $__sp_cmd -f -n 'test (count (commandline -opc)) -eq 2; and __fish_seen_subcommand_from use login rename mv' -a '(__switch_profile_profiles)'
|
|
6214
6244
|
complete -c $__sp_cmd -f -n '__fish_seen_subcommand_from remove rm' -a '(__switch_profile_profiles)'
|
|
6215
6245
|
end`, POWERSHELL_FUNCTION = `function ${FUNCTION_NAME} {
|
|
6216
6246
|
param([Parameter(ValueFromRemainingArguments = $true)] [string[]] $Rest)
|
|
@@ -7660,6 +7690,7 @@ ${ui2.dim(viaShortcut ? "Switching clears them from this terminal." : `Unset ${s
|
|
|
7660
7690
|
}, ACTIONS = [
|
|
7661
7691
|
{ key: "login", label: "Log in" },
|
|
7662
7692
|
{ key: "add", label: "Add" },
|
|
7693
|
+
{ key: "rename", label: "Rename" },
|
|
7663
7694
|
{ key: "remove", label: "Remove" },
|
|
7664
7695
|
{ key: "logout", label: "Log out" },
|
|
7665
7696
|
{ key: "settings", label: "Settings" }
|
|
@@ -7756,7 +7787,7 @@ ${ui2.dim("Tip: enable per-terminal switching in Settings.")}` : ""}`);
|
|
|
7756
7787
|
${ui2.dim(`Open a new terminal or run: ${installed.reload}`)}`), installed.name == "powershell" && p4.log.message(ui2.dim("If PowerShell refuses to load your profile: Set-ExecutionPolicy -Scope CurrentUser RemoteSigned"));
|
|
7757
7788
|
}, runAction = async (key, state, opts) => {
|
|
7758
7789
|
let commands2 = require_commands();
|
|
7759
|
-
return key == "login" ? commands2.login(state.defaultName, { ...opts, fromPicker: !0 }) : commands2[key](opts.args || [], { ...opts, fromPicker: !0 });
|
|
7790
|
+
return key == "login" ? commands2.login(state.defaultName, { ...opts, fromPicker: !0 }) : key == "rename" ? commands2.rename(null, null, { ...opts, fromPicker: !0 }) : commands2[key](opts.args || [], { ...opts, fromPicker: !0 });
|
|
7760
7791
|
}, routeChoice = (choice) => {
|
|
7761
7792
|
if (p4.isCancel(choice))
|
|
7762
7793
|
return { type: "quit" };
|
|
@@ -7823,7 +7854,7 @@ ${ui2.dim(`Open a new terminal or run: ${installed.reload}`)}`), installed.name
|
|
|
7823
7854
|
// src/commands/index.js
|
|
7824
7855
|
var require_commands = __commonJS({
|
|
7825
7856
|
"src/commands/index.js"(exports2, module2) {
|
|
7826
|
-
var p4 = (init_dist4(), __toCommonJS(dist_exports2)), log3 = require_log(), aws = require_aws(), transforms = require_transforms(), settings2 = require_settings(), shell = require_shell(), migrate = require_migrate(), rank = require_rank(), { resolveLoginMode, isRemoteSession, configureSsoFailure } = require_login(), ui2 = require_ui(), { ask, preflight, loadState, loginKey, describe, loginState, upgradeLegacySso } = require_common(), { ssoLogin, rememberLogin } = require_login_flow(), { switchCommand, switchTo, connect, enableShortcut } = require_switch(), intro2 = (opts) => {
|
|
7857
|
+
var p4 = (init_dist4(), __toCommonJS(dist_exports2)), log3 = require_log(), aws = require_aws(), transforms = require_transforms(), settings2 = require_settings(), shell = require_shell(), migrate = require_migrate(), rank = require_rank(), { resolveLoginMode, isRemoteSession, configureSsoFailure } = require_login(), ui2 = require_ui(), { ask, preflight, loadState, loginKey, describe, loginState, upgradeLegacySso } = require_common(), { ssoLogin, rememberLogin } = require_login_flow(), { switchCommand, switchTo, connect, enableShortcut, exportHint } = require_switch(), intro2 = (opts) => {
|
|
7827
7858
|
!opts.fromPicker && !opts.json && p4.intro(`${ui2.badge("switch-profile")} ${ui2.dim(settings2.CLI_VERSION)}`);
|
|
7828
7859
|
}, begin = async (opts, { needsInput } = {}) => {
|
|
7829
7860
|
let interactive = ui2.isInteractive(opts);
|
|
@@ -7919,7 +7950,7 @@ var require_commands = __commonJS({
|
|
|
7919
7950
|
...sessions.length ? [ui2.dim(`Portals already set up: ${sessions.map((x2) => `${x2.name} (${x2.sso_region || "?"})`).join(", ")}. Type one of these names to reuse it.`)] : []
|
|
7920
7951
|
].join(`
|
|
7921
7952
|
`));
|
|
7922
|
-
let [errors, upgraded] = await aws.createSsoProfile(name);
|
|
7953
|
+
let [errors, upgraded] = await aws.createSsoProfile(name, { loginMode: settings2.getLoginMode(state.settings) });
|
|
7923
7954
|
if (errors) {
|
|
7924
7955
|
let failed = errors.find((e) => e.output != null);
|
|
7925
7956
|
if (!failed)
|
|
@@ -8059,6 +8090,53 @@ AWS recommends SSO or console sign-in instead.`), !await ask(p4.confirm({ messag
|
|
|
8059
8090
|
if (errors)
|
|
8060
8091
|
throw ui2.cliErrorFrom(errors);
|
|
8061
8092
|
p4.outro(`${ui2.ok(ui2.sym.ok)} Removed ${names.join(", ")}`);
|
|
8093
|
+
}, moveKey = (obj, from, to) => {
|
|
8094
|
+
if (!obj || !(from in obj))
|
|
8095
|
+
return obj;
|
|
8096
|
+
let { [from]: value, ...rest } = obj;
|
|
8097
|
+
return { ...rest, [to]: value };
|
|
8098
|
+
}, rename = async (from, to, opts) => {
|
|
8099
|
+
let interactive = await begin(opts), state = await loadState();
|
|
8100
|
+
if (!from) {
|
|
8101
|
+
if (!interactive)
|
|
8102
|
+
throw new ui2.CliError("Which profile?", { code: 3, hint: "Run: switch-profile rename <profile> <new-name>" });
|
|
8103
|
+
from = await ask(p4.autocomplete({
|
|
8104
|
+
message: "Rename which profile?",
|
|
8105
|
+
maxItems: 12,
|
|
8106
|
+
options: state.profiles.map((x2) => ({ value: x2.name, label: x2.name, hint: describe(x2) }))
|
|
8107
|
+
}));
|
|
8108
|
+
}
|
|
8109
|
+
let profile = findProfile(state, from), taken = [...state.profiles.map((x2) => x2.name).filter((n3) => n3 != from), "default"], validate = (v) => v == from ? "That is already its name." : validateProfileName(taken)(v);
|
|
8110
|
+
if (!to) {
|
|
8111
|
+
if (!interactive)
|
|
8112
|
+
throw new ui2.CliError("What is the new name?", { code: 3, hint: `Run: switch-profile rename ${from} <new-name>` });
|
|
8113
|
+
to = await ask(p4.text({ message: `New name for ${from}`, initialValue: from, validate }));
|
|
8114
|
+
}
|
|
8115
|
+
let invalid = validate(to);
|
|
8116
|
+
if (invalid)
|
|
8117
|
+
throw new ui2.CliError(invalid, { code: 3 });
|
|
8118
|
+
let [errors, result] = await aws.renameProfile(from, to);
|
|
8119
|
+
if (errors)
|
|
8120
|
+
throw ui2.cliErrorFrom(errors);
|
|
8121
|
+
let current = await settings2.read();
|
|
8122
|
+
await settings2.update({
|
|
8123
|
+
usage: moveKey(current.usage, from, to),
|
|
8124
|
+
...loginKey(profile) == from ? { logins: moveKey(current.logins, from, to) } : {}
|
|
8125
|
+
});
|
|
8126
|
+
let inTerminal = process.env.AWS_PROFILE == from, terminal = inTerminal ? await shell.exportProfile(to).catch(log3.tolerated("handing the profile to sp", !1)) : !1;
|
|
8127
|
+
if (opts.json) {
|
|
8128
|
+
process.stdout.write(JSON.stringify({ from, to, default: result.wasDefault, sources: result.sources, processes: result.processes, terminal }) + `
|
|
8129
|
+
`);
|
|
8130
|
+
return;
|
|
8131
|
+
}
|
|
8132
|
+
let lines = [
|
|
8133
|
+
result.wasDefault ? ui2.dim("still the default profile") : null,
|
|
8134
|
+
result.sources.length ? ui2.dim(`source_profile updated in ${result.sources.join(", ")}`) : null,
|
|
8135
|
+
terminal ? ui2.dim("this terminal now uses the new name") : null
|
|
8136
|
+
].filter(Boolean);
|
|
8137
|
+
p4.log.success([`Renamed ${ui2.accent(from)} to ${ui2.accent(to)}`, ...lines].join(`
|
|
8138
|
+
`)), result.processes.length && p4.log.warn(`The credential_process of ${result.processes.join(", ")} still uses --profile ${from}. Update ${result.processes.length == 1 ? "it" : "them"} in ~/.aws/config.`), inTerminal && !terminal && p4.log.warn(`This terminal still uses ${from}. Run:
|
|
8139
|
+
${ui2.accent(exportHint(to))}`), p4.outro(ui2.dim(`Other terminals, scripts and tools that use ${from} (AWS_PROFILE or --profile) need the new name.`));
|
|
8062
8140
|
}, LOGIN_MODE_LABELS = {
|
|
8063
8141
|
auto: "Auto: device code over SSH, browser otherwise",
|
|
8064
8142
|
device: "Always device code (approve from any device)",
|
|
@@ -8110,6 +8188,7 @@ AWS recommends SSO or console sign-in instead.`), !await ask(p4.confirm({ messag
|
|
|
8110
8188
|
logout,
|
|
8111
8189
|
add,
|
|
8112
8190
|
remove,
|
|
8191
|
+
rename,
|
|
8113
8192
|
settings: settingsCommand
|
|
8114
8193
|
};
|
|
8115
8194
|
}
|
|
@@ -8125,6 +8204,7 @@ Examples:
|
|
|
8125
8204
|
$ sp acme prod fuzzy match: switches if only one profile matches
|
|
8126
8205
|
$ sp login log in again now (device code over SSH)
|
|
8127
8206
|
$ sp add import every account of an SSO portal
|
|
8207
|
+
$ sp rename <profile> <new> give a profile a friendlier name
|
|
8128
8208
|
$ switch-profile status --json
|
|
8129
8209
|
|
|
8130
8210
|
'sp' is the shortcut switch-profile installs on first use (or from Settings). It also
|
|
@@ -8154,6 +8234,6 @@ Exit codes: 0 ok \xB7 1 error \xB7 2 login required \xB7 3 bad input \xB7 130 ca
|
|
|
8154
8234
|
}, main = (argv) => {
|
|
8155
8235
|
log2.start({ version: CLI_VERSION, argv }), process.on("uncaughtException", crashed), process.on("unhandledRejection", crashed), process.on("exit", (code) => log2.info(`exit ${code}`));
|
|
8156
8236
|
let program = new Command();
|
|
8157
|
-
return program.name("switch-profile").description("Switch between AWS profiles, log in with SSO, and keep every terminal on the right account.").version(CLI_VERSION, "-v, --version").argument("[profile...]", "profile name or search text").option("--json", "machine-readable output").option("--no-input", "never prompt (fails with a hint instead)").option("--debug", "show error details").addHelpText("after", EXAMPLES).showSuggestionAfterError().action(run((words, opts) => commands.switch((words || []).join(" "), opts))), program.command("use").argument("<profile>").description("switch to a profile by its exact name").action(run(commands.use)), program.command("status").description("show the current profile and login state").action(run((opts) => commands.status([], opts))), program.command("login").argument("[profile]", "defaults to this terminal's profile, then the default profile").description("log in again now, even if the session is still valid").option("--device", "use a device code (approve from any device)").option("--browser", "use the browser on this machine").action(run(commands.login)), program.command("logout").description("end every SSO session on this machine").option("-y, --yes", "do not ask for confirmation").action(run((opts) => commands.logout([], opts))), program.command("add").description("add profiles: import an SSO portal, or create one").option("--from-sso [session]", "import (or re-sync) every account and role of an [sso-session]").option("--region <region>", "default region of imported profiles").option("--prefix <prefix>", "name prefix of imported profiles").option("--prune", "remove imported profiles that no longer exist").option("-y, --yes", "do not ask for confirmation").action(run((opts) => commands.add([], opts))), program.command("remove").alias("rm").argument("[profiles...]").description("remove profiles").option("-y, --yes", "do not ask for confirmation").action(run(commands.remove)), program.command("settings").description("per-terminal switching, login mode and more").action(run((opts) => commands.settings([], opts))), program.command("switch", { hidden: !0 }).action(run((opts) => commands.switch("", opts))), program.parseAsync(argv);
|
|
8237
|
+
return program.name("switch-profile").description("Switch between AWS profiles, log in with SSO, and keep every terminal on the right account.").version(CLI_VERSION, "-v, --version").argument("[profile...]", "profile name or search text").option("--json", "machine-readable output").option("--no-input", "never prompt (fails with a hint instead)").option("--debug", "show error details").addHelpText("after", EXAMPLES).showSuggestionAfterError().action(run((words, opts) => commands.switch((words || []).join(" "), opts))), program.command("use").argument("<profile>").description("switch to a profile by its exact name").action(run(commands.use)), program.command("status").description("show the current profile and login state").action(run((opts) => commands.status([], opts))), program.command("login").argument("[profile]", "defaults to this terminal's profile, then the default profile").description("log in again now, even if the session is still valid").option("--device", "use a device code (approve from any device)").option("--browser", "use the browser on this machine").action(run(commands.login)), program.command("logout").description("end every SSO session on this machine").option("-y, --yes", "do not ask for confirmation").action(run((opts) => commands.logout([], opts))), program.command("add").description("add profiles: import an SSO portal, or create one").option("--from-sso [session]", "import (or re-sync) every account and role of an [sso-session]").option("--region <region>", "default region of imported profiles").option("--prefix <prefix>", "name prefix of imported profiles").option("--prune", "remove imported profiles that no longer exist").option("-y, --yes", "do not ask for confirmation").action(run((opts) => commands.add([], opts))), program.command("remove").alias("rm").argument("[profiles...]").description("remove profiles").option("-y, --yes", "do not ask for confirmation").action(run(commands.remove)), program.command("rename").alias("mv").argument("[profile]").argument("[new-name]").description("rename a profile").action(run(commands.rename)), program.command("settings").description("per-terminal switching, login mode and more").action(run((opts) => commands.settings([], opts))), program.command("switch", { hidden: !0 }).action(run((opts) => commands.switch("", opts))), program.parseAsync(argv);
|
|
8158
8238
|
};
|
|
8159
8239
|
module.exports = { main };
|