Skip to content

Commit

Permalink
[Feat.][ACNA-1056] Support workspace creation in aio app use -w and a…
Browse files Browse the repository at this point in the history
…io app init -w (#498)

Allow workspace creation during 'aio app use'
support for workspace switching via id.
support for workspace creation with given name via flag.
  • Loading branch information
florind-ens authored Nov 2, 2021
1 parent d959682 commit ebaae1e
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 60 deletions.
23 changes: 19 additions & 4 deletions src/commands/app/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class InitCommand extends AddCommand {
// 3. select or create project
const project = await this.selectOrCreateConsoleProject(consoleCLI, org)
// 4. retrieve workspace details, defaults to Stage
const workspace = await this.retrieveWorkspaceFromName(consoleCLI, org, project, flags.workspace)
const workspace = await this.retrieveWorkspaceFromName(consoleCLI, org, project, flags)
// 5. ask for exensionPoints, only allow selection for extensions that have services enabled in Org
const extensionPoints = await this.selectExtensionPoints(flags, orgSupportedServices)
// 6. add any required services to Workspace
Expand Down Expand Up @@ -186,12 +186,23 @@ class InitCommand extends AddCommand {
return project
}

async retrieveWorkspaceFromName (consoleCLI, org, project, workspaceName) {
async retrieveWorkspaceFromName (consoleCLI, org, project, flags) {
const workspaceName = flags.workspace
// get workspace details
const workspaces = await consoleCLI.getWorkspaces(org.id, project.id)
const workspace = workspaces.find(w => w.name.toLowerCase() === workspaceName.toLowerCase())
let workspace = workspaces.find(w => w.name.toLowerCase() === workspaceName.toLowerCase())
if (!workspace) {
throw new Error(`'--workspace=${workspaceName}' in Project '${project.name}' not found.`)
if (!flags['confirm-new-workspace']) {
const shouldNewWorkspace = await consoleCLI.prompt.promptConfirm(`Workspace '${workspaceName}' does not exist \n > Do you wish to create a new workspace?`)
if (!shouldNewWorkspace) {
this.error(`Workspace '${workspaceName}' does not exist and creation aborted`)
}
}
this.log(`'--workspace=${workspaceName}' in Project '${project.name}' not found. \n Creating one...`)
workspace = await consoleCLI.createWorkspace(org.id, project.id, {
name: workspaceName,
title: ''
})
}
return workspace
}
Expand Down Expand Up @@ -329,6 +340,10 @@ InitCommand.flags = {
default: DEFAULT_WORKSPACE,
char: 'w',
exclusive: ['import'] // also no-login
}),
'confirm-new-workspace': flags.boolean({
description: 'Skip and confirm prompt for creating a new workspace',
default: false
})
}

Expand Down
62 changes: 29 additions & 33 deletions src/commands/app/use.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,6 @@ class Use extends BaseCommand {
this.error(message)
}
newConfig = globalConfig
if (
currentConfigIsComplete &&
newConfig.org.id === currentConfig.org.id &&
newConfig.project.id === currentConfig.project.id &&
newConfig.workspace.id === currentConfig.workspace.id
) {
this.error('The selected configuration is the same as the current configuration.')
}
} else {
// useOperation = 'workspace'
if (!currentConfigIsComplete) {
Expand Down Expand Up @@ -190,37 +182,37 @@ class Use extends BaseCommand {
* @returns {Buffer} the Adobe Developer Console configuration file for the workspace
*/
async selectTargetWorkspaceInProject (consoleCLI, config, flags) {
const project = { name: config.project.name, id: config.project.id }
const currentWorkspace = { name: config.workspace.name, id: config.workspace.id }

// make sure user is not trying to switch to current workspace
const workspaceFlag = flags.workspace
if (workspaceFlag === currentWorkspace.name) {
this.cleanConsoleCLIOutput()
this.error(`--workspace=${workspaceFlag} is the same as the currently selected workspace, nothing to be done.`)
}
const { project, org } = config
const workspaceNameOrId = flags.workspace

// retrieve all workspaces
const workspaces = await consoleCLI.getWorkspaces(
config.org.id,
config.project.id
org.id,
project.id
)
const workspacesButCurrent = workspaces.filter(w => w.id !== currentWorkspace.id)

let workspace

if (workspaceFlag) {
// workspace name is given, make sure the workspace is in there
workspace = workspacesButCurrent.find(w => w.name === workspaceFlag)
if (!workspace) {
this.cleanConsoleCLIOutput()
this.error(`--workspace=${workspaceFlag} does not exist in current Project ${project.name}.`)
let workspaceData = { name: workspaceNameOrId }
// does not prompt if workspaceNameOrId is defined via the flag
workspace = await consoleCLI.promptForSelectWorkspace(workspaces, { workspaceId: workspaceNameOrId, workspaceName: workspaceNameOrId }, { allowCreate: true })
if (!workspace) {
aioLogger.debug(`--workspace=${workspaceNameOrId} was not found in the current Project ${project.name}`)
if (workspaceNameOrId) {
if (!flags['confirm-new-workspace']) {
const shouldNewWorkspace = await consoleCLI.prompt.promptConfirm(`Workspace '${workspaceNameOrId}' does not exist \n > Do you wish to create a new workspace?`)
if (!shouldNewWorkspace) {
this.error('Workspace creation aborted')
}
}
} else {
workspaceData = await consoleCLI.promptForCreateWorkspaceDetails()
}
} else {
// workspace name is not given, let the user choose the
workspace = await consoleCLI.promptForSelectWorkspace(workspacesButCurrent)
aioLogger.debug(`Creating workspace: ${workspaceData.name}`)
workspace = await consoleCLI.createWorkspace(org.id, project.id, workspaceData)
}
return {
name: workspace.name,
id: workspace.id
}
return { name: workspace.name, id: workspace.id }
}

/**
Expand Down Expand Up @@ -395,11 +387,15 @@ Use.flags = {
exclusive: ['workspace']
}),
workspace: flags.string({
description: 'Specify the Adobe Developer Console Workspace name to import the configuration from',
description: 'Specify the Adobe Developer Console Workspace name or Workspace id to import the configuration from',
default: '',
char: 'w',
exclusive: ['global', 'workspace-name']
}),
'confirm-new-workspace': flags.boolean({
description: 'Skip and confirm prompt for creating a new workspace',
default: false
}),
'workspace-name': flags.string({
description: '[DEPRECATED]: please use --workspace instead',
default: '',
Expand Down
53 changes: 47 additions & 6 deletions test/commands/app/init.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,25 @@ const mockConsoleCLIInstance = {
promptForSelectWorkspace: jest.fn(),
getServicePropertiesFromWorkspace: jest.fn(),
subscribeToServices: jest.fn(),
getWorkspaceConfig: jest.fn()
getWorkspaceConfig: jest.fn(),
createWorkspace: jest.fn(),
prompt: {
promptConfirm: jest.fn()
}
// promptForServiceSubscriptionsOperation: jest.fn(),
// confirmNewServiceSubscriptions: jest.fn(),
// promptForSelectServiceProperties: jest.fn()
}
LibConsoleCLI.init.mockResolvedValue(mockConsoleCLIInstance)
/** @private */
function resetMockConsoleCLI () {
Object.keys(mockConsoleCLIInstance).forEach(
k => mockConsoleCLIInstance[k].mockReset()
)
Object.keys(mockConsoleCLIInstance).forEach(k => {
if ('mockReset' in mockConsoleCLIInstance[k]) {
mockConsoleCLIInstance[k].mockReset()
}
})
LibConsoleCLI.init.mockClear()
mockConsoleCLIInstance.prompt.promptConfirm.mockReset()
}

jest.mock('@adobe/generator-aio-app', () => ({
Expand Down Expand Up @@ -669,15 +676,49 @@ describe('run', () => {
expect(mockConsoleCLIInstance.createProject).not.toHaveBeenCalled()
})

test('with login, select excshell, -w notexists', async () => {
test('with login, select excshell, -w notexists, promptConfirm true', async () => {
mockConsoleCLIInstance.prompt.promptConfirm.mockResolvedValue(true)
mockConsoleCLIInstance.promptForSelectOrganization.mockResolvedValue(fakeOrg)
mockConsoleCLIInstance.promptForSelectProject.mockResolvedValue(fakeProject)
mockConsoleCLIInstance.getWorkspaces.mockResolvedValue(fakeWorkspaces)
mockConsoleCLIInstance.getServicePropertiesFromWorkspace.mockResolvedValue(fakeServicePropertiesNoAssetCompute)
mockConsoleCLIInstance.getEnabledServicesForOrg.mockResolvedValue(fakeSupportedOrgServices)
mockConsoleCLIInstance.getWorkspaceConfig.mockResolvedValue(fakeConfig)
mockExtensionPrompt.mockReturnValue({ res: excshellSelection })
mockConsoleCLIInstance.createWorkspace.mockResolvedValue(fakeWorkspaces[0])

await TheCommand.run(['-w', 'notexists'])
expect(mockConsoleCLIInstance.createWorkspace).toHaveBeenCalledWith(expect.anything(), expect.anything(), expect.objectContaining({ name: 'notexists', title: '' }))
})

test('with login, select excshell, -w notexists, promptConfirm false, should throw', async () => {
const workspaceName = 'notexists'
mockConsoleCLIInstance.prompt.promptConfirm.mockResolvedValue(false)
mockConsoleCLIInstance.promptForSelectOrganization.mockResolvedValue(fakeOrg)
mockConsoleCLIInstance.promptForSelectProject.mockResolvedValue(fakeProject)
mockConsoleCLIInstance.getWorkspaces.mockResolvedValue(fakeWorkspaces)
mockConsoleCLIInstance.getServicePropertiesFromWorkspace.mockResolvedValue(fakeServicePropertiesNoAssetCompute)
mockConsoleCLIInstance.getEnabledServicesForOrg.mockResolvedValue(fakeSupportedOrgServices)
mockConsoleCLIInstance.getWorkspaceConfig.mockResolvedValue(fakeConfig)
mockExtensionPrompt.mockReturnValue({ res: excshellSelection })
mockConsoleCLIInstance.createWorkspace.mockResolvedValue(fakeWorkspaces[0])

await expect(TheCommand.run(['-w', workspaceName])).rejects.toThrow(`Workspace '${workspaceName}' does not exist and creation aborted`)
})
test('with login, select excshell, -w notexists, --confirm-new-workspace', async () => {
const notexistsWorkspace = 'notexists'
mockConsoleCLIInstance.prompt.promptConfirm.mockResolvedValue(true)
mockConsoleCLIInstance.promptForSelectOrganization.mockResolvedValue(fakeOrg)
mockConsoleCLIInstance.promptForSelectProject.mockResolvedValue(fakeProject)
mockConsoleCLIInstance.getWorkspaces.mockResolvedValue(fakeWorkspaces)
mockConsoleCLIInstance.getServicePropertiesFromWorkspace.mockResolvedValue(fakeServicePropertiesNoAssetCompute)
mockConsoleCLIInstance.getEnabledServicesForOrg.mockResolvedValue(fakeSupportedOrgServices)
mockConsoleCLIInstance.getWorkspaceConfig.mockResolvedValue(fakeConfig)
mockExtensionPrompt.mockReturnValue({ res: excshellSelection })
mockConsoleCLIInstance.createWorkspace.mockResolvedValue(fakeWorkspaces[0])

await expect(TheCommand.run(['-w', 'notexists'])).rejects.toThrow('\'--workspace=notexists\' in Project \'bestproject\' not found.')
await TheCommand.run(['-w', notexistsWorkspace, '--confirm-new-workspace'])
expect(mockConsoleCLIInstance.prompt.promptConfirm).not.toHaveBeenCalled()
expect(mockConsoleCLIInstance.createWorkspace).toHaveBeenCalledWith(expect.anything(), expect.anything(), expect.objectContaining({ name: 'notexists', title: '' }))
})
})
Loading

0 comments on commit ebaae1e

Please sign in to comment.