diff --git a/i18n/en.yml b/i18n/en.yml index 1fd0df0..66f9b63 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -1,41 +1,24 @@ --- en: - __version: - desc: Prints the version - add: - desc: Adds an ACCOUNT to the keyring - add_role: - desc: Adds a ROLE to the keyring - awskeyring: - desc: Autocompletion for bourne shells - console: - desc: Open the AWS Console for the ACCOUNT - env: - desc: Outputs bourne shell environment exports for an ACCOUNT - exec: - desc: Execute a COMMAND with the environment set for an ACCOUNT - import: - desc: Import an ACCOUNT to the keyring from ~/.aws/credentials - initialise: - desc: Initialises a new KEYCHAIN - json: - desc: Outputs AWS CLI compatible JSON for an ACCOUNT - list: - desc: Prints a list of accounts in the keyring - list_role: - desc: Prints a list of roles in the keyring - remove: - desc: Removes an ACCOUNT from the keyring - remove_role: - desc: Removes a ROLE from the keyring - remove_token: - desc: Removes a token for ACCOUNT from the keyring - rotate: - desc: Rotate access keys for an ACCOUNT - token: - desc: Create an STS Token from a ROLE or an MFA code - update: - desc: Updates an ACCOUNT in the keyring + __version_desc: Prints the version + add_desc: Adds an ACCOUNT to the keyring + add_role_desc: Adds a ROLE to the keyring + awskeyring_desc: Autocompletion for bourne shells + console_desc: Open the AWS Console for the ACCOUNT + default_desc: Run default help or initialise if needed. + env_desc: Outputs bourne shell environment exports for an ACCOUNT + exec_desc: Execute a COMMAND with the environment set for an ACCOUNT + import_desc: Import an ACCOUNT to the keyring from ~/.aws/credentials + initialise_desc: Initialises a new KEYCHAIN + json_desc: Outputs AWS CLI compatible JSON for an ACCOUNT + list_desc: Prints a list of accounts in the keyring + list_role_desc: Prints a list of roles in the keyring + remove_desc: Removes an ACCOUNT from the keyring + remove_role_desc: Removes a ROLE from the keyring + remove_token_desc: Removes a token for ACCOUNT from the keyring + rotate_desc: Rotate access keys for an ACCOUNT + token_desc: Create an STS Token from a ROLE or an MFA code + update_desc: Updates an ACCOUNT in the keyring method_option: arn: 'AWS role arn.' code: 'Virtual mfa CODE.' diff --git a/lib/awskeyring_command.rb b/lib/awskeyring_command.rb index b9746e5..5c5c2e4 100644 --- a/lib/awskeyring_command.rb +++ b/lib/awskeyring_command.rb @@ -28,13 +28,24 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength map 'rot' => :rotate map 'tok' => :token map 'up' => :update + default_command :default # default to returning an error on failure. def self.exit_on_failure? true end - desc '--version, -v', I18n.t('__version.desc') + desc 'default', I18n.t('default_desc'), hide: true + # default command to run + def default + if Awskeyring.prefs.empty? + invoke :initialise + else + invoke :help + end + end + + desc '--version, -v', I18n.t('__version_desc') method_option 'no-remote', type: :boolean, aliases: '-r', desc: I18n.t('method_option.noremote'), default: false # print the version number def __version @@ -45,7 +56,7 @@ def __version puts "Homepage #{Awskeyring::HOMEPAGE}" end - desc 'initialise', I18n.t('initialise.desc') + desc 'initialise', I18n.t('initialise_desc') method_option :keychain, type: :string, aliases: '-n', desc: I18n.t('method_option.keychain') # initialise the keychain def initialise @@ -70,7 +81,7 @@ def initialise puts I18n.t('message.addkeychain', keychain: keychain, exec_name: exec_name) end - desc 'list', I18n.t('list.desc') + desc 'list', I18n.t('list_desc') # list the accounts def list if Awskeyring.list_account_names.empty? @@ -81,7 +92,7 @@ def list end map 'list-role' => :list_role - desc 'list-role', I18n.t('list_role.desc') + desc 'list-role', I18n.t('list_role_desc') method_option 'detail', type: :boolean, aliases: '-d', desc: I18n.t('method_option.detail'), default: false # List roles def list_role @@ -96,7 +107,7 @@ def list_role end end - desc 'env ACCOUNT', I18n.t('env.desc') + desc 'env ACCOUNT', I18n.t('env_desc') method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false method_option 'unset', type: :boolean, aliases: '-u', desc: I18n.t('method_option.unset'), default: false # Print Env vars @@ -114,7 +125,7 @@ def env(account = nil) end end - desc 'json ACCOUNT', I18n.t('json.desc') + desc 'json ACCOUNT', I18n.t('json_desc') method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false # Print JSON for use with credential_process def json(account) @@ -131,7 +142,7 @@ def json(account) ) end - desc 'import ACCOUNT', I18n.t('import.desc') + desc 'import ACCOUNT', I18n.t('import_desc') method_option 'no-remote', type: :boolean, aliases: '-r', desc: I18n.t('method_option.noremote'), default: false # Import an Account def import(account = nil) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize @@ -167,7 +178,7 @@ def import(account = nil) # rubocop:disable Metrics/MethodLength, Metrics/AbcSiz end end - desc 'exec ACCOUNT command...', I18n.t('exec.desc') + desc 'exec ACCOUNT command...', I18n.t('exec_desc') method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false method_option 'no-bundle', type: :boolean, aliases: '-b', desc: I18n.t('method_option.nobundle'), default: false # execute an external command with env set @@ -189,7 +200,7 @@ def exec(account, *command) end end - desc 'add ACCOUNT', I18n.t('add.desc') + desc 'add ACCOUNT', I18n.t('add_desc') method_option :key, type: :string, aliases: '-k', desc: I18n.t('method_option.key') method_option :secret, type: :string, aliases: '-s', desc: I18n.t('method_option.secret') method_option :mfa, type: :string, aliases: '-m', desc: I18n.t('method_option.mfa') @@ -220,7 +231,7 @@ def add(account = nil) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize puts I18n.t('message.addaccount', account: account) end - desc 'update ACCOUNT', I18n.t('update.desc') + desc 'update ACCOUNT', I18n.t('update_desc') method_option :key, type: :string, aliases: '-k', desc: I18n.t('method_option.key') method_option :secret, type: :string, aliases: '-s', desc: I18n.t('method_option.secret') method_option 'no-remote', type: :boolean, aliases: '-r', desc: I18n.t('method_option.noremote'), default: false @@ -248,7 +259,7 @@ def update(account = nil) # rubocop:disable Metrics/MethodLength, Metrics/AbcSiz end map 'add-role' => :add_role - desc 'add-role ROLE', I18n.t('add_role.desc') + desc 'add-role ROLE', I18n.t('add_role_desc') method_option :arn, type: :string, aliases: '-a', desc: I18n.t('method_option.arn') # Add a role def add_role(role = nil) @@ -268,7 +279,7 @@ def add_role(role = nil) puts I18n.t('message.addrole', role: role) end - desc 'remove ACCOUNT', I18n.t('remove.desc') + desc 'remove ACCOUNT', I18n.t('remove_desc') # Remove an account def remove(account = nil) account = ask_check( @@ -278,7 +289,7 @@ def remove(account = nil) Awskeyring.delete_account(account: account, message: I18n.t('message.delaccount', account: account)) end - desc 'remove-token ACCOUNT', I18n.t('remove_token.desc') + desc 'remove-token ACCOUNT', I18n.t('remove_token_desc') # remove a session token def remove_token(account = nil) account = ask_check( @@ -289,7 +300,7 @@ def remove_token(account = nil) end map 'remove-role' => :remove_role - desc 'remove-role ROLE', I18n.t('remove_role.desc') + desc 'remove-role ROLE', I18n.t('remove_role_desc') # remove a role def remove_role(role = nil) role = ask_check( @@ -299,7 +310,7 @@ def remove_role(role = nil) Awskeyring.delete_role(role_name: role, message: I18n.t('message.delrole', role: role)) end - desc 'rotate ACCOUNT', I18n.t('rotate.desc') + desc 'rotate ACCOUNT', I18n.t('rotate_desc') # rotate Account keys def rotate(account = nil) # rubocop:disable Metrics/MethodLength account = ask_check( @@ -331,7 +342,7 @@ def rotate(account = nil) # rubocop:disable Metrics/MethodLength puts I18n.t('message.upaccount', account: account) end - desc 'token ACCOUNT [ROLE] [MFA]', I18n.t('token.desc') + desc 'token ACCOUNT [ROLE] [MFA]', I18n.t('token_desc') method_option :role, type: :string, aliases: '-r', desc: I18n.t('method_option.role') method_option :code, type: :string, aliases: '-c', desc: I18n.t('method_option.code') method_option :duration, type: :string, aliases: '-d', desc: I18n.t('method_option.duration') @@ -386,7 +397,7 @@ def token(account = nil, role = nil, code = nil) # rubocop:disable Metrics/AbcSi puts I18n.t('message.addtoken', account: account, time: Time.at(new_creds[:expiry].to_i)) end - desc 'console ACCOUNT', I18n.t('console.desc') + desc 'console ACCOUNT', I18n.t('console_desc') method_option :path, type: :string, aliases: '-p', desc: I18n.t('method_option.path') method_option :browser, type: :string, aliases: '-b', desc: I18n.t('method_option.browser') method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false @@ -425,7 +436,7 @@ def console(account = nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLeng end end - desc 'awskeyring CURR PREV', I18n.t('awskeyring.desc'), hide: true + desc "#{File.basename($PROGRAM_NAME)} CURR PREV", I18n.t('awskeyring_desc'), hide: true map File.basename($PROGRAM_NAME) => :autocomplete # autocomplete def autocomplete(curr, prev) @@ -508,7 +519,8 @@ def print_auto_resp(curr, len, sub_cmd) # rubocop:disable Metrics/MethodLength, end def list_commands - self.class.all_commands.keys.map { |elem| elem.tr('_', '-') }.reject! { |elem| elem == 'autocomplete' } + commands = self.class.all_commands.keys.map { |elem| elem.tr('_', '-') } + commands.reject! { |elem| %w[autocomplete default].include?(elem) } end def list_arguments(command:) diff --git a/spec/lib/awskeyring_command_spec.rb b/spec/lib/awskeyring_command_spec.rb index f2c67b9..c35fa22 100644 --- a/spec/lib/awskeyring_command_spec.rb +++ b/spec/lib/awskeyring_command_spec.rb @@ -21,8 +21,6 @@ end it 'outputs help text' do - expect { described_class.start([]) } - .to output(/^ \w+ --version, -v\s+# Prints the version/).to_stdout expect { described_class.start(%w[help]) } .to output(/Awskeyring commands:/).to_stdout end @@ -57,6 +55,11 @@ expect { described_class.start(%w[initialise]) } .to output(/Add accounts to your test keychain with:/).to_stdout end + + it 'initialises the keychain by default' do + expect { described_class.start([]) } + .to output(/Add accounts to your test keychain with:/).to_stdout + end end context 'when no accounts or roles are set' do @@ -66,6 +69,11 @@ allow(Awskeyring).to receive(:prefs).and_return('{"awskeyring": "awskeyringtest"}') end + it 'outputs help text by default' do + expect { described_class.start([]) } + .to output(/^ \w+ --version, -v\s+# Prints the version/).to_stdout + end + it 'tells you that you must add accounts' do expect { described_class.start(%w[list]) }.to raise_error .and output(/No accounts added, run `\w+ add` to add./).to_stderr