-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(CLI Onboarding): Move
dashboard-login
step from plugin
- Loading branch information
Showing
7 changed files
with
271 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
'use strict'; | ||
|
||
const _ = require('lodash'); | ||
const { ServerlessSDK } = require('@serverless/platform-client'); | ||
const login = require('@serverless/dashboard-plugin/lib/login'); | ||
const configUtils = require('@serverless/utils/config'); | ||
const { StepHistory } = require('@serverless/utils/telemetry'); | ||
|
||
const loginOrRegisterQuestion = async (inquirer) => | ||
( | ||
await inquirer.prompt({ | ||
message: 'Do you want to login/register to Serverless Dashboard?', | ||
type: 'confirm', | ||
name: 'shouldLoginOrRegister', | ||
}) | ||
).shouldLoginOrRegister; | ||
|
||
const steps = { | ||
loginOrRegister: async (context) => { | ||
const result = await loginOrRegisterQuestion(context.inquirer); | ||
context.stepHistory.set('shouldLoginOrRegister', result); | ||
if (result) { | ||
await login({ isInteractive: true }); | ||
} | ||
}, | ||
}; | ||
|
||
module.exports = { | ||
async isApplicable(context) { | ||
const { configuration, options, serviceDir } = context; | ||
|
||
if (!serviceDir) { | ||
context.inapplicabilityReasonCode = 'NOT_IN_SERVICE_DIRECTORY'; | ||
return false; | ||
} | ||
|
||
if ( | ||
_.get(configuration, 'provider') !== 'aws' && | ||
_.get(configuration, 'provider.name') !== 'aws' | ||
) { | ||
context.inapplicabilityReasonCode = 'NON_AWS_PROVIDER'; | ||
return false; | ||
} | ||
|
||
if (process.env.SERVERLESS_ACCESS_KEY) { | ||
context.inapplicabilityReasonCode = 'SERVERLESS_ACCESS_KEY_PROVIDED'; | ||
return false; | ||
} | ||
|
||
const sdk = new ServerlessSDK(); | ||
const { supportedRegions, supportedRuntimes } = await sdk.metadata.get(); | ||
if (!supportedRuntimes.includes(_.get(configuration.provider, 'runtime') || 'nodejs12.x')) { | ||
context.inapplicabilityReasonCode = 'UNSUPPORTED_RUNTIME'; | ||
return false; | ||
} | ||
if ( | ||
!supportedRegions.includes(options.region || configuration.provider.region || 'us-east-1') | ||
) { | ||
context.inapplicabilityReasonCode = 'UNSUPPORTED_REGION'; | ||
return false; | ||
} | ||
const isLoggedIn = Boolean(configUtils.getLoggedInUser()); | ||
if (isLoggedIn) { | ||
context.inapplicabilityReasonCode = 'ALREADY_LOGGED_IN'; | ||
} | ||
return !isLoggedIn; | ||
}, | ||
async run(context) { | ||
// TODO: Remove check for `StepHistory` after releasing new major version | ||
if (!_.get(context.stepHistory, 'set')) context.stepHistory = new StepHistory(); | ||
process.stdout.write('You are not logged in or you do not have a Serverless account.\n\n'); | ||
return steps.loginOrRegister(context); | ||
}, | ||
steps, | ||
configuredQuestions: ['shouldLoginOrRegister'], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
test/fixtures/programmatic/aws-loggedin-service/.serverlessrc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"frameworkId": "00000000-0000-0000-0000-000000000000", | ||
"meta": { | ||
"created_at": 1560000000, | ||
"updated_at": 1560000000 | ||
}, | ||
"userId": "testinteractivecli", | ||
"users": { | ||
"testinteractivecli": { | ||
"userId": "testinteractivecli", | ||
"name": "Testing Interactive Cli", | ||
"email": "test-interactive-cli@interactive.cli", | ||
"username": "testinteractivecli", | ||
"dashboard": { | ||
"refreshToken": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", | ||
"accessToken": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", | ||
"idToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik56azVNREl5TVRnNFJqWTBORGswT0VJM1JrRXpORGN4UmtVMU1FWXdNemczT1VKQlFqRTBNZyJ9.eyJuaWNrbmFtZSI6InRlc3QtaW50ZXJhY3RpdmUtY2xpIiwibmFtZSI6IlRlc3RpbmcgSW50ZXJhY3RpdmUgQ2xpIiwicGljdHVyZSI6Imh0dHBzOi8vaW50ZXJhdGNpdmUuY2xpL3Rlc3RpbmcucG5nIiwidXBkYXRlZF9hdCI6IjIwMTktMDktMTZUMTU6MTg6NDMuOTk5WiIsImVtYWlsIjoidGVzdGluZ0BpbnRlcmFjdGl2ZS5jbGkiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaXNzIjoiaHR0cHM6Ly9zZXJ2ZXJsZXNzaW5jLmF1dGgwLmNvbS8iLCJzdWIiOiJ0ZXN0LWludGVyYWN0aXZlLWNsaSIsImF1ZCI6IlhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYIiwiaWF0IjoxNTYwMDAwMDAwLCJleHAiOjMwMDAwMDAwMDB9.GcNQtWSxv9CHTABw-HIjYSvRxTEapDUDqIIWRGmz01XmShQxRGOHRuUg1NKU4w9MpOlB6txHKs8UWd2eZkzw_Z4QmIuLyAVhVklpWP2-xeysPLUyqVTgqAg8kgIUAwdKjmrdpQqHhGd-Q1BIX62-E-qKKx8prmADSw_hgmuvlMuSCa1ajCnfyUXycQxDmbFrvjd24lJER0FSpB2nWWW3KxZ_UBX-TuVmiEtRXg9GYeSv6oIU78PrIhYgJ0QjERRF1yAYamIXNRs-KZ7Z4YiFNC4uKzFH1524pZkS4Q0-pweIvBrrsjekz-vEYcbaVG1zAxDu_yNrYPk5phCy8MHTrQ", | ||
"expiresAt": 3000000000000, | ||
"username": "testinteractivecli", | ||
"accessKeys": { | ||
"testinteractivecli": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" | ||
} | ||
}, | ||
"enterprise": { | ||
"versionSDK": "2.1.1", | ||
"timeLastLogin": 1560000000, | ||
"timeLastLogout": 1560000000 | ||
} | ||
} | ||
} | ||
} |
Empty file.
10 changes: 10 additions & 0 deletions
10
test/fixtures/programmatic/aws-loggedin-service/serverless.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
service: 'some-aws-service' | ||
provider: 'aws' | ||
|
||
functions: | ||
app: | ||
handler: index.handler | ||
foo: bar | ||
org: | ||
handler: index.handler | ||
foo: bar |
152 changes: 152 additions & 0 deletions
152
test/unit/lib/cli/interactive-setup/dashboard-login.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
'use strict'; | ||
|
||
const chai = require('chai'); | ||
const sinon = require('sinon'); | ||
const proxyquire = require('proxyquire'); | ||
const overrideCwd = require('process-utils/override-cwd'); | ||
const configureInquirerStub = require('@serverless/test/configure-inquirer-stub'); | ||
const { StepHistory } = require('@serverless/utils/telemetry'); | ||
const inquirer = require('@serverless/utils/inquirer'); | ||
|
||
const { expect } = chai; | ||
|
||
chai.use(require('chai-as-promised')); | ||
|
||
const fixtures = require('../../../../fixtures/programmatic'); | ||
|
||
const ServerlessSDKMock = class ServerlessSDK { | ||
constructor() { | ||
this.metadata = { | ||
get: async () => { | ||
return { | ||
awsAccountId: '377024778620', | ||
supportedRuntimes: ['nodejs10.x', 'nodejs12.x', 'python2.7', 'python3.6', 'python3.7'], | ||
supportedRegions: [ | ||
'us-east-1', | ||
'us-east-2', | ||
'us-west-2', | ||
'eu-central-1', | ||
'eu-west-1', | ||
'eu-west-2', | ||
'ap-northeast-1', | ||
'ap-southeast-1', | ||
'ap-southeast-2', | ||
], | ||
}; | ||
}, | ||
}; | ||
} | ||
}; | ||
|
||
const step = proxyquire('../../../../../lib/cli/interactive-setup/dashboard-login', { | ||
'@serverless/platform-client': { | ||
ServerlessSDK: ServerlessSDKMock, | ||
}, | ||
}); | ||
|
||
describe('test/unit/lib/cli/interactive-setup/dashboard-login.test.js', function () { | ||
this.timeout(1000 * 60 * 3); | ||
|
||
const loginStub = sinon.stub().resolves(); | ||
|
||
afterEach(() => { | ||
loginStub.resetHistory(); | ||
}); | ||
|
||
it('Should be ineffective, when not at service path', async () => { | ||
const context = {}; | ||
expect(await step.isApplicable(context)).to.be.false; | ||
expect(context.inapplicabilityReasonCode).to.equal('NOT_IN_SERVICE_DIRECTORY'); | ||
}); | ||
|
||
it('Should be ineffective, when not at AWS service path', async () => { | ||
const context = { | ||
serviceDir: process.cwd(), | ||
configuration: {}, | ||
configurationFilename: 'serverless.yml', | ||
options: {}, | ||
inquirer, | ||
}; | ||
expect(await step.isApplicable(context)).to.equal(false); | ||
expect(context.inapplicabilityReasonCode).to.equal('NON_AWS_PROVIDER'); | ||
}); | ||
|
||
it('Should be ineffective, when not at supported runtime service path', async () => { | ||
const context = { | ||
serviceDir: process.cwd(), | ||
configuration: { provider: { name: 'aws', runtime: 'java8' } }, | ||
configurationFilename: 'serverless.yml', | ||
options: {}, | ||
inquirer, | ||
}; | ||
expect(await step.isApplicable(context)).to.equal(false); | ||
expect(context.inapplicabilityReasonCode).to.equal('UNSUPPORTED_RUNTIME'); | ||
}); | ||
|
||
it('Should be ineffective, when logged in', async () => { | ||
const { servicePath: serviceDir, serviceConfig: configuration } = await fixtures.setup( | ||
'aws-loggedin-service' | ||
); | ||
const context = { | ||
serviceDir, | ||
configuration, | ||
configurationFilename: 'serverless.yml', | ||
options: {}, | ||
inquirer, | ||
}; | ||
expect(await overrideCwd(serviceDir, async () => await step.isApplicable(context))).to.equal( | ||
false | ||
); | ||
expect(context.inapplicabilityReasonCode).to.equal('ALREADY_LOGGED_IN'); | ||
}); | ||
|
||
it('Should login when user decides to login/register', async () => { | ||
configureInquirerStub(inquirer, { | ||
confirm: { shouldLoginOrRegister: true }, | ||
}); | ||
const loginStep = proxyquire('../../../../../lib/cli/interactive-setup/dashboard-login', { | ||
'@serverless/dashboard-plugin/lib/login': loginStub, | ||
'@serverless/platform-client': { | ||
ServerlessSDK: ServerlessSDKMock, | ||
}, | ||
}); | ||
const context = { | ||
serviceDir: process.cwd(), | ||
configuration: { provider: { name: 'aws', runtime: 'nodejs12.x' } }, | ||
configurationFilename: 'serverless.yml', | ||
options: {}, | ||
inquirer, | ||
stepHistory: new StepHistory(), | ||
}; | ||
await loginStep.run(context); | ||
expect(loginStub.calledOnce).to.be.true; | ||
expect(context.stepHistory.valuesMap()).to.deep.equal( | ||
new Map([['shouldLoginOrRegister', true]]) | ||
); | ||
}); | ||
|
||
it('Should not login when user decides not to login/register', async () => { | ||
configureInquirerStub(inquirer, { | ||
confirm: { shouldLoginOrRegister: false }, | ||
}); | ||
const loginStep = proxyquire('../../../../../lib/cli/interactive-setup/dashboard-login', { | ||
'@serverless/dashboard-plugin/lib/login': loginStub, | ||
'@serverless/platform-client': { | ||
ServerlessSDK: ServerlessSDKMock, | ||
}, | ||
}); | ||
const context = { | ||
serviceDir: process.cwd(), | ||
configuration: { provider: { name: 'aws', runtime: 'nodejs12.x' } }, | ||
configurationFilename: 'serverless.yml', | ||
options: {}, | ||
inquirer, | ||
stepHistory: new StepHistory(), | ||
}; | ||
await loginStep.run(context); | ||
expect(loginStub.called).to.be.false; | ||
expect(context.stepHistory.valuesMap()).to.deep.equal( | ||
new Map([['shouldLoginOrRegister', false]]) | ||
); | ||
}); | ||
}); |