├── .gitignore ├── README.md ├── demo.gif ├── index.js ├── package-lock.json ├── package.json ├── postinstall.sh ├── run.sh └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWSP - AWS Profile Switcher 2 | 3 | Easily switch between AWS Profiles 4 | 5 | 6 | 7 | ## Prereqs 8 | Setup your profiles using the aws cli 9 | 10 | ```sh 11 | aws configure --profile PROFILE_NAME 12 | ``` 13 | 14 | You can also leave out the `--profile PROFILE_NAME` param to set your `default` credentials 15 | 16 | Refer to this doc for more information 17 | https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html 18 | 19 | ## Setup 20 | 21 | ```sh 22 | npm install -g awsp 23 | ``` 24 | 25 | Add the following to your `.bashrc` or `.zshrc` config 26 | ```sh 27 | alias awsp="source _awsp" 28 | ``` 29 | 30 | ## Usage 31 | ```sh 32 | awsp 33 | ``` 34 | 35 | ## Show your AWS Profile in your shell prompt 36 | For better visibility into what your shell is set to it's helpful to configure your prompt to show the value of the env variable `AWS_PROFILE`. 37 | 38 | 39 | 40 | Here's a sample of my zsh prompt config using oh-my-zsh themes 41 | 42 | ```sh 43 | function aws_prof { 44 | local profile="${AWS_PROFILE:=default}" 45 | 46 | echo "%{$fg_bold[blue]%}aws:(%{$fg[yellow]%}${profile}%{$fg_bold[blue]%})%{$reset_color%} " 47 | } 48 | ``` 49 | 50 | ```sh 51 | PROMPT='OTHER_PROMPT_STUFF $(aws_prof)' 52 | ``` -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnnyopao/awsp/0656893f9521887d3af3d869cc757a64cdfcd179/demo.gif -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs'); 4 | const inquirer = require('inquirer'); 5 | 6 | console.log('AWS Profile Switcher'); 7 | 8 | const homeDir = process.env['HOME'] 9 | const profileRegex = /\[profile .*]/g; 10 | const bracketsRemovalRegx = /(\[profile )|(\])/g; 11 | const defaultProfileChoice = 'default'; 12 | 13 | const promptProfileChoice = (data) => { 14 | const matches = data.match(profileRegex); 15 | 16 | if (!matches) { 17 | console.log('No profiles found.'); 18 | console.log('Refer to this guide for help on setting up a new AWS profile:'); 19 | console.log('https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html'); 20 | 21 | return; 22 | } 23 | 24 | const profiles = matches.map((match) => { 25 | return match.replace(bracketsRemovalRegx, ''); 26 | }); 27 | 28 | profiles.push(defaultProfileChoice); 29 | 30 | const profileChoice = [ 31 | { 32 | type: 'list', 33 | name: 'profile', 34 | message: 'Choose a profile', 35 | choices: profiles, 36 | default: process.env.AWS_PROFILE || defaultProfileChoice 37 | } 38 | ]; 39 | 40 | return inquirer.prompt(profileChoice); 41 | } 42 | 43 | const readAwsProfiles = () => { 44 | return new Promise((resolve, reject) => { 45 | fs.readFile(`${homeDir}/.aws/config`, 'utf8', (err, data) => { 46 | if (err) { 47 | reject(err); 48 | } else { 49 | resolve(data); 50 | } 51 | }); 52 | }); 53 | }; 54 | 55 | const writeToConfig = (answers) => { 56 | const profileChoice = 57 | answers.profile === defaultProfileChoice ? '' : answers.profile; 58 | 59 | return new Promise((resolve, reject) => { 60 | fs.writeFile(`${homeDir}/.awsp`, profileChoice, { flag: 'w' }, function (err) { 61 | if (err) { 62 | reject(err); 63 | } else { 64 | resolve(); 65 | } 66 | }); 67 | }); 68 | }; 69 | 70 | readAwsProfiles() 71 | .then(promptProfileChoice) 72 | .then(writeToConfig) 73 | .catch(error => { 74 | console.log('Error:', error); 75 | process.exit(1); 76 | }); 77 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "awsp", 3 | "version": "0.2.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ansi-escapes": { 8 | "version": "3.1.0", 9 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", 10 | "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" 11 | }, 12 | "ansi-regex": { 13 | "version": "3.0.0", 14 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 15 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 16 | }, 17 | "ansi-styles": { 18 | "version": "3.2.1", 19 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 20 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 21 | "requires": { 22 | "color-convert": "^1.9.0" 23 | } 24 | }, 25 | "chalk": { 26 | "version": "2.4.1", 27 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 28 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 29 | "requires": { 30 | "ansi-styles": "^3.2.1", 31 | "escape-string-regexp": "^1.0.5", 32 | "supports-color": "^5.3.0" 33 | } 34 | }, 35 | "chardet": { 36 | "version": "0.4.2", 37 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", 38 | "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" 39 | }, 40 | "cli-cursor": { 41 | "version": "2.1.0", 42 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 43 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 44 | "requires": { 45 | "restore-cursor": "^2.0.0" 46 | } 47 | }, 48 | "cli-width": { 49 | "version": "2.2.0", 50 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 51 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" 52 | }, 53 | "color-convert": { 54 | "version": "1.9.3", 55 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 56 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 57 | "requires": { 58 | "color-name": "1.1.3" 59 | } 60 | }, 61 | "color-name": { 62 | "version": "1.1.3", 63 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 64 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 65 | }, 66 | "escape-string-regexp": { 67 | "version": "1.0.5", 68 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 69 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 70 | }, 71 | "external-editor": { 72 | "version": "2.2.0", 73 | "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", 74 | "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", 75 | "requires": { 76 | "chardet": "^0.4.0", 77 | "iconv-lite": "^0.4.17", 78 | "tmp": "^0.0.33" 79 | } 80 | }, 81 | "figures": { 82 | "version": "2.0.0", 83 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 84 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 85 | "requires": { 86 | "escape-string-regexp": "^1.0.5" 87 | } 88 | }, 89 | "has-flag": { 90 | "version": "3.0.0", 91 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 92 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 93 | }, 94 | "iconv-lite": { 95 | "version": "0.4.24", 96 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 97 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 98 | "requires": { 99 | "safer-buffer": ">= 2.1.2 < 3" 100 | } 101 | }, 102 | "inquirer": { 103 | "version": "5.2.0", 104 | "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", 105 | "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", 106 | "requires": { 107 | "ansi-escapes": "^3.0.0", 108 | "chalk": "^2.0.0", 109 | "cli-cursor": "^2.1.0", 110 | "cli-width": "^2.0.0", 111 | "external-editor": "^2.1.0", 112 | "figures": "^2.0.0", 113 | "lodash": "^4.3.0", 114 | "mute-stream": "0.0.7", 115 | "run-async": "^2.2.0", 116 | "rxjs": "^5.5.2", 117 | "string-width": "^2.1.0", 118 | "strip-ansi": "^4.0.0", 119 | "through": "^2.3.6" 120 | } 121 | }, 122 | "is-fullwidth-code-point": { 123 | "version": "2.0.0", 124 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 125 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 126 | }, 127 | "is-promise": { 128 | "version": "2.1.0", 129 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 130 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 131 | }, 132 | "lodash": { 133 | "version": "4.17.11", 134 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", 135 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" 136 | }, 137 | "mimic-fn": { 138 | "version": "1.2.0", 139 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 140 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" 141 | }, 142 | "mute-stream": { 143 | "version": "0.0.7", 144 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 145 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" 146 | }, 147 | "onetime": { 148 | "version": "2.0.1", 149 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 150 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 151 | "requires": { 152 | "mimic-fn": "^1.0.0" 153 | } 154 | }, 155 | "os-tmpdir": { 156 | "version": "1.0.2", 157 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 158 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 159 | }, 160 | "restore-cursor": { 161 | "version": "2.0.0", 162 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 163 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 164 | "requires": { 165 | "onetime": "^2.0.0", 166 | "signal-exit": "^3.0.2" 167 | } 168 | }, 169 | "run-async": { 170 | "version": "2.3.0", 171 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 172 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 173 | "requires": { 174 | "is-promise": "^2.1.0" 175 | } 176 | }, 177 | "rxjs": { 178 | "version": "5.5.12", 179 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", 180 | "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", 181 | "requires": { 182 | "symbol-observable": "1.0.1" 183 | } 184 | }, 185 | "safer-buffer": { 186 | "version": "2.1.2", 187 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 188 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 189 | }, 190 | "signal-exit": { 191 | "version": "3.0.2", 192 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 193 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 194 | }, 195 | "string-width": { 196 | "version": "2.1.1", 197 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 198 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 199 | "requires": { 200 | "is-fullwidth-code-point": "^2.0.0", 201 | "strip-ansi": "^4.0.0" 202 | } 203 | }, 204 | "strip-ansi": { 205 | "version": "4.0.0", 206 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 207 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 208 | "requires": { 209 | "ansi-regex": "^3.0.0" 210 | } 211 | }, 212 | "supports-color": { 213 | "version": "5.5.0", 214 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 215 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 216 | "requires": { 217 | "has-flag": "^3.0.0" 218 | } 219 | }, 220 | "symbol-observable": { 221 | "version": "1.0.1", 222 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", 223 | "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" 224 | }, 225 | "through": { 226 | "version": "2.3.8", 227 | "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", 228 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 229 | }, 230 | "tmp": { 231 | "version": "0.0.33", 232 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 233 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 234 | "requires": { 235 | "os-tmpdir": "~1.0.2" 236 | } 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "awsp", 3 | "version": "0.2.0", 4 | "description": "Switch AWS Profiles easily", 5 | "main": "index.js", 6 | "homepage": "https://github.com/johnnyopao/awsp", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "postinstall": "./postinstall.sh" 10 | }, 11 | "author": "Johnny Opao", 12 | "license": "ISC", 13 | "bin": { 14 | "_awsp_prompt": "./index.js", 15 | "_awsp": "./run.sh" 16 | }, 17 | "dependencies": { 18 | "inquirer": "^5.0.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /postinstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Add the following to your .bashrc or .zshrc config" 4 | echo ' alias awsp="source _awsp"' 5 | echo "" -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | AWS_PROFILE="$AWS_PROFILE" _awsp_prompt 4 | 5 | selected_profile="$(cat ~/.awsp)" 6 | 7 | if [ -z "$selected_profile" ] 8 | then 9 | unset AWS_PROFILE 10 | else 11 | export AWS_PROFILE="$selected_profile" 12 | fi 13 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnnyopao/awsp/0656893f9521887d3af3d869cc757a64cdfcd179/screenshot.png --------------------------------------------------------------------------------