mirror of
https://github.com/serverless/serverless.git
synced 2026-02-01 16:07:28 +00:00
refactor: Revert bluebird from lib/plugins/interactiveCli
This reverts commit 7c0ceb5c4a1171666e381ef9a00c6f133569732b.
This commit is contained in:
parent
399d91b7e4
commit
217b9751ea
@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BbPromise = require('bluebird');
|
||||
const chalk = require('chalk');
|
||||
const inquirer = require('@serverless/utils/inquirer');
|
||||
const awsCredentials = require('../aws/utils/credentials');
|
||||
@ -9,66 +10,61 @@ const openBrowser = require('../../utils/openBrowser');
|
||||
const isValidAwsAccessKeyId = RegExp.prototype.test.bind(/^[A-Z0-9]{10,}$/);
|
||||
const isValidAwsSecretAccessKey = RegExp.prototype.test.bind(/^[a-zA-Z0-9/+]{10,}$/);
|
||||
|
||||
async function awsAccessKeyIdInput() {
|
||||
const { accessKeyId } = await inquirer.prompt({
|
||||
message: 'AWS Access Key Id:',
|
||||
type: 'input',
|
||||
name: 'accessKeyId',
|
||||
validate(input) {
|
||||
if (isValidAwsAccessKeyId(input.trim())) return true;
|
||||
return 'AWS Access Key Id seems not valid.\n Expected something like AKIAIOSFODNN7EXAMPLE';
|
||||
},
|
||||
});
|
||||
const awsAccessKeyIdInput = () =>
|
||||
inquirer
|
||||
.prompt({
|
||||
message: 'AWS Access Key Id:',
|
||||
type: 'input',
|
||||
name: 'accessKeyId',
|
||||
validate: (input) => {
|
||||
if (isValidAwsAccessKeyId(input.trim())) return true;
|
||||
return 'AWS Access Key Id seems not valid.\n Expected something like AKIAIOSFODNN7EXAMPLE';
|
||||
},
|
||||
})
|
||||
.then(({ accessKeyId }) => accessKeyId.trim());
|
||||
|
||||
return accessKeyId.trim();
|
||||
}
|
||||
|
||||
async function awsSecretAccessKeyInput() {
|
||||
const { secretAccessKey } = await inquirer.prompt({
|
||||
message: 'AWS Secret Access Key:',
|
||||
type: 'input',
|
||||
name: 'secretAccessKey',
|
||||
validate(input) {
|
||||
if (isValidAwsSecretAccessKey(input.trim())) return true;
|
||||
return (
|
||||
'AWS Secret Access Key seems not valid.\n' +
|
||||
' Expected something like wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return secretAccessKey.trim();
|
||||
}
|
||||
const awsSecretAccessKeyInput = () =>
|
||||
inquirer
|
||||
.prompt({
|
||||
message: 'AWS Secret Access Key:',
|
||||
type: 'input',
|
||||
name: 'secretAccessKey',
|
||||
validate: (input) => {
|
||||
if (isValidAwsSecretAccessKey(input.trim())) return true;
|
||||
return (
|
||||
'AWS Secret Access Key seems not valid.\n' +
|
||||
' Expected something like wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
|
||||
);
|
||||
},
|
||||
})
|
||||
.then(({ secretAccessKey }) => secretAccessKey.trim());
|
||||
|
||||
const steps = {
|
||||
writeOnSetupSkip() {
|
||||
writeOnSetupSkip: () =>
|
||||
process.stdout.write(`\nYou can setup your AWS account later. More details available here:
|
||||
|
||||
http://slss.io/aws-creds-setup\n`);
|
||||
},
|
||||
async shouldSetupAwsCredentials() {
|
||||
const isConfirmed = await confirm('Do you want to set them up now?', {
|
||||
name: 'shouldSetupAwsCredentials',
|
||||
});
|
||||
|
||||
if (!isConfirmed) steps.writeOnSetupSkip();
|
||||
return isConfirmed;
|
||||
},
|
||||
async ensureAwsAccount() {
|
||||
const hasAccount = await confirm('Do you have an AWS account?', { name: 'hasAwsAccount' });
|
||||
|
||||
if (!hasAccount) {
|
||||
await openBrowser('https://portal.aws.amazon.com/billing/signup');
|
||||
return inquirer.prompt({
|
||||
message: 'Press Enter to continue after creating an AWS account',
|
||||
name: 'createAwsAccountPrompt',
|
||||
});
|
||||
}
|
||||
return null;
|
||||
},
|
||||
async ensureAwsCredentials(serverless) {
|
||||
http://slss.io/aws-creds-setup\n`),
|
||||
shouldSetupAwsCredentials: () =>
|
||||
confirm('Do you want to set them up now?', { name: 'shouldSetupAwsCredentials' }).then(
|
||||
(isConfirmed) => {
|
||||
if (!isConfirmed) steps.writeOnSetupSkip();
|
||||
return isConfirmed;
|
||||
}
|
||||
),
|
||||
ensureAwsAccount: () =>
|
||||
confirm('Do you have an AWS account?', { name: 'hasAwsAccount' }).then((hasAccount) => {
|
||||
if (!hasAccount) {
|
||||
openBrowser('https://portal.aws.amazon.com/billing/signup');
|
||||
return inquirer.prompt({
|
||||
message: 'Press Enter to continue after creating an AWS account',
|
||||
name: 'createAwsAccountPrompt',
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
ensureAwsCredentials: (serverless) => {
|
||||
const region = serverless.getProvider('aws').getRegion();
|
||||
await openBrowser(
|
||||
openBrowser(
|
||||
`https://console.aws.amazon.com/iam/home?region=${region}#/users$new?step=final&accessKey&userNames=serverless&permissionType=policies&policies=arn:aws:iam::aws:policy%2FAdministratorAccess`
|
||||
);
|
||||
return inquirer.prompt({
|
||||
@ -76,46 +72,52 @@ const steps = {
|
||||
name: 'generateAwsCredsPrompt',
|
||||
});
|
||||
},
|
||||
async inputAwsCredentials() {
|
||||
const accessKeyId = await awsAccessKeyIdInput();
|
||||
const secretAccessKey = await awsSecretAccessKeyInput();
|
||||
|
||||
await awsCredentials.saveFileProfiles(new Map([['default', { accessKeyId, secretAccessKey }]]));
|
||||
|
||||
process.stdout.write(
|
||||
`\n${chalk.green(
|
||||
`AWS credentials saved on your machine at ${chalk.bold(
|
||||
process.platform === 'win32' ? '%userprofile%\\.aws\\credentials' : '~/.aws/credentials'
|
||||
)}. Go there to change them at any time.`
|
||||
)}\n`
|
||||
inputAwsCredentials: () => {
|
||||
return awsAccessKeyIdInput().then((accessKeyId) =>
|
||||
awsSecretAccessKeyInput().then((secretAccessKey) =>
|
||||
awsCredentials
|
||||
.saveFileProfiles(new Map([['default', { accessKeyId, secretAccessKey }]]))
|
||||
.then(() =>
|
||||
process.stdout.write(
|
||||
`\n${chalk.green(
|
||||
`AWS credentials saved on your machine at ${chalk.bold(
|
||||
process.platform === 'win32'
|
||||
? '%userprofile%\\.aws\\credentials'
|
||||
: '~/.aws/credentials'
|
||||
)}. Go there to change them at any time.`
|
||||
)}\n`
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
async check(serverless) {
|
||||
if (serverless.service.provider.name !== 'aws') return false;
|
||||
if (serverless.getProvider('aws').cachedCredentials) return false;
|
||||
const [fileProfiles, envCredentials] = await Promise.all([
|
||||
awsCredentials.resolveFileProfiles(),
|
||||
awsCredentials.resolveEnvCredentials(),
|
||||
]);
|
||||
return !fileProfiles.size && !envCredentials;
|
||||
check(serverless) {
|
||||
return BbPromise.try(() => {
|
||||
if (serverless.service.provider.name !== 'aws') return false;
|
||||
if (serverless.getProvider('aws').cachedCredentials) return false;
|
||||
return BbPromise.all([
|
||||
awsCredentials.resolveFileProfiles(),
|
||||
awsCredentials.resolveEnvCredentials(),
|
||||
]).then(([fileProfiles, envCredentials]) => !fileProfiles.size && !envCredentials);
|
||||
});
|
||||
},
|
||||
async run(serverless) {
|
||||
run(serverless) {
|
||||
process.stdout.write(
|
||||
'No AWS credentials were found on your computer, ' +
|
||||
'you need these to host your application.\n\n'
|
||||
);
|
||||
await module.exports.runSteps(serverless);
|
||||
return module.exports.runSteps(serverless);
|
||||
},
|
||||
steps,
|
||||
async runSteps(serverless) {
|
||||
const isConfirmed = await steps.shouldSetupAwsCredentials();
|
||||
|
||||
if (!isConfirmed) return;
|
||||
await steps.ensureAwsAccount();
|
||||
await steps.ensureAwsCredentials(serverless);
|
||||
await steps.inputAwsCredentials();
|
||||
},
|
||||
runSteps: (serverless) =>
|
||||
steps.shouldSetupAwsCredentials().then((isConfirmed) => {
|
||||
if (!isConfirmed) return null;
|
||||
return steps
|
||||
.ensureAwsAccount()
|
||||
.then(() => steps.ensureAwsCredentials(serverless))
|
||||
.then(steps.inputAwsCredentials);
|
||||
}),
|
||||
};
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const fs = require('fs').promises;
|
||||
const fs = require('fs');
|
||||
const chalk = require('chalk');
|
||||
const BbPromise = require('bluebird');
|
||||
const requireUncached = require('ncjsm/require-uncached');
|
||||
const resolve = require('ncjsm/resolve/sync');
|
||||
const configUtils = require('@serverless/utils/config');
|
||||
@ -14,52 +15,64 @@ const promptDisabledConfigPropertyName = require('../../utils/tabCompletion/prom
|
||||
const inquirer = require('@serverless/utils/inquirer');
|
||||
const { confirm } = require('./utils');
|
||||
|
||||
BbPromise.promisifyAll(fs);
|
||||
|
||||
module.exports = {
|
||||
async check() {
|
||||
if (!isTabTabCompletionSupported) return false;
|
||||
check() {
|
||||
return BbPromise.try(() => {
|
||||
if (!isTabTabCompletionSupported) return false;
|
||||
|
||||
const shellExtension = require('tabtab/lib/utils/systemShell')();
|
||||
try {
|
||||
await fs.stat(path.resolve(os.homedir(), `.config/tabtab/serverless.${shellExtension}`));
|
||||
return false;
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') throw error;
|
||||
return !configUtils.get(promptDisabledConfigPropertyName);
|
||||
}
|
||||
const shellExtension = require('tabtab/lib/utils/systemShell')();
|
||||
return fs
|
||||
.statAsync(path.resolve(os.homedir(), `.config/tabtab/serverless.${shellExtension}`))
|
||||
.then(
|
||||
() => false,
|
||||
(error) => {
|
||||
if (error.code !== 'ENOENT') throw error;
|
||||
return !configUtils.get(promptDisabledConfigPropertyName);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
async run() {
|
||||
const isConfirmed = await confirm('Would you like to setup a command line <tab> completion?', {
|
||||
name: 'shouldSetupTabCompletion',
|
||||
run() {
|
||||
return BbPromise.try(() => {
|
||||
return confirm('Would you like to setup a command line <tab> completion?', {
|
||||
name: 'shouldSetupTabCompletion',
|
||||
}).then((isConfirmed) => {
|
||||
if (!isConfirmed) {
|
||||
configUtils.set(promptDisabledConfigPropertyName, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
const promptPath = require.resolve('tabtab/lib/prompt');
|
||||
const tabtabsInquirerPath = resolve(path.dirname(promptPath), 'inquirer').realPath;
|
||||
|
||||
// Hack tabtabs prompt to use our inquirer customization
|
||||
const prompt = requireUncached([promptPath, tabtabsInquirerPath], () => {
|
||||
require(tabtabsInquirerPath);
|
||||
require.cache[tabtabsInquirerPath].exports = inquirer;
|
||||
return require(promptPath);
|
||||
});
|
||||
const { install } = require('tabtab/lib/installer');
|
||||
return prompt().then(({ location }) =>
|
||||
muteConsoleLog(() =>
|
||||
tabtabOptions.reduce(
|
||||
(previousOperation, options) =>
|
||||
previousOperation.then(() => install(Object.assign({ location }, options))),
|
||||
BbPromise.resolve()
|
||||
)
|
||||
).then(() =>
|
||||
process.stdout.write(
|
||||
`\n${chalk.green(
|
||||
`Command line <tab> completion was successfully setup. ${chalk.bold(
|
||||
'Make sure to reload your SHELL'
|
||||
)}.\n` +
|
||||
'You may uninstall it by running: serverless config tabcompletion uninstall'
|
||||
)}\n`
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
configUtils.set(promptDisabledConfigPropertyName, true);
|
||||
return;
|
||||
}
|
||||
|
||||
const promptPath = require.resolve('tabtab/lib/prompt');
|
||||
const tabtabsInquirerPath = resolve(path.dirname(promptPath), 'inquirer').realPath;
|
||||
|
||||
// Hack tabtabs prompt to use our inquirer customization
|
||||
const prompt = requireUncached([promptPath, tabtabsInquirerPath], () => {
|
||||
require(tabtabsInquirerPath);
|
||||
require.cache[tabtabsInquirerPath].exports = inquirer;
|
||||
return require(promptPath);
|
||||
});
|
||||
const { install } = require('tabtab/lib/installer');
|
||||
const { location } = await prompt();
|
||||
await muteConsoleLog(async () => {
|
||||
for (const options of tabtabOptions) {
|
||||
await install({ location, ...options });
|
||||
}
|
||||
});
|
||||
|
||||
process.stdout.write(
|
||||
`\n${chalk.green(
|
||||
`Command line <tab> completion was successfully setup. ${chalk.bold(
|
||||
'Make sure to reload your SHELL'
|
||||
)}.\nYou may uninstall it by running: serverless config tabcompletion uninstall`
|
||||
)}\n`
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@ -5,6 +5,8 @@ const sinon = require('sinon');
|
||||
const runServerless = require('../../../../utils/run-serverless');
|
||||
const configureInquirerStub = require('@serverless/test/configure-inquirer-stub');
|
||||
|
||||
const fs = require('fs');
|
||||
const BbPromise = require('bluebird');
|
||||
const configUtils = require('@serverless/utils/config');
|
||||
const inquirer = require('@serverless/utils/inquirer');
|
||||
|
||||
@ -15,6 +17,8 @@ const lifecycleHookNamesBlacklist = [
|
||||
'interactiveCli:tabCompletion',
|
||||
];
|
||||
|
||||
BbPromise.promisifyAll(fs);
|
||||
|
||||
const modulesCacheStub = {
|
||||
'./lib/utils/npmPackage/isGlobal.js': async () => true,
|
||||
'./lib/utils/npmPackage/isWritable.js': async () => true,
|
||||
|
||||
@ -4,6 +4,7 @@ const { join } = require('path');
|
||||
const { homedir: getHomedir } = require('os');
|
||||
const { expect } = require('chai');
|
||||
const sinon = require('sinon');
|
||||
const BbPromise = require('bluebird');
|
||||
const { remove: rmDir, lstat, outputFile: writeFile } = require('fs-extra');
|
||||
const { resolveFileProfiles } = require('../../../../../lib/plugins/aws/utils/credentials');
|
||||
const inquirer = require('@serverless/utils/inquirer');
|
||||
@ -20,7 +21,10 @@ const lifecycleHookNamesBlacklist = [
|
||||
|
||||
const openBrowserUrls = [];
|
||||
const modulesCacheStub = {
|
||||
'./lib/utils/openBrowser': async (url) => openBrowserUrls.push(url),
|
||||
'./lib/utils/openBrowser': (url) =>
|
||||
BbPromise.try(() => {
|
||||
openBrowserUrls.push(url);
|
||||
}),
|
||||
// Ensure to rely on same inquirer module that we mock in tests
|
||||
'@serverless/utils/inquirer': inquirer,
|
||||
};
|
||||
|
||||
@ -6,8 +6,9 @@ const runServerless = require('../../../../utils/run-serverless');
|
||||
const configureInquirerStub = require('@serverless/test/configure-inquirer-stub');
|
||||
|
||||
const os = require('os');
|
||||
const fs = require('fs').promises;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const BbPromise = require('bluebird');
|
||||
const configUtils = require('@serverless/utils/config');
|
||||
const promptDisabledConfigPropertyName = require('../../../../../lib/utils/tabCompletion/promptDisabledConfigPropertyName');
|
||||
const isTabCompletionSupported = require('../../../../../lib/utils/tabCompletion/isSupported');
|
||||
@ -20,6 +21,8 @@ const lifecycleHookNamesBlacklist = [
|
||||
'interactiveCli:autoUpdate',
|
||||
];
|
||||
|
||||
BbPromise.promisifyAll(fs);
|
||||
|
||||
describe('interactiveCli: tabCompletion', () => {
|
||||
let backupIsTTY;
|
||||
|
||||
@ -84,12 +87,12 @@ describe('interactiveCli: tabCompletion', () => {
|
||||
}).then(() =>
|
||||
Promise.all([
|
||||
fs
|
||||
.readFile(path.resolve(os.homedir(), '.bashrc'), 'utf8')
|
||||
.readFileAsync(path.resolve(os.homedir(), '.bashrc'), 'utf8')
|
||||
.then((bashRcContent) =>
|
||||
expect(bashRcContent).to.include(' ~/.config/tabtab/__tabtab.bash')
|
||||
),
|
||||
fs.readFile(path.resolve(os.homedir(), '.config/tabtab/serverless.bash'), 'utf8'),
|
||||
fs.readFile(path.resolve(os.homedir(), '.config/tabtab/sls.bash'), 'utf8'),
|
||||
fs.readFileAsync(path.resolve(os.homedir(), '.config/tabtab/serverless.bash'), 'utf8'),
|
||||
fs.readFileAsync(path.resolve(os.homedir(), '.config/tabtab/sls.bash'), 'utf8'),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user