Skip to content

Commit 2447b0c

Browse files
purplecabbageAjazSumaiyapdohogne-magento
authored
Epic/abdb implementation (#896)
* feat: update deploy command to provision db * chore: revert package.json README.md * address review comment: remove default region * fix: region level * fix: test * CEXT-5618: Use @adobe/aio-lib-db for database provisioning * Updating lib-db version to 1.0.0 * Reverting lib-db version to 0.2.0-beta.1 * feat: update libint to accept Ims accessToken * Updating aio-lib-db dependency in anticipation of 1.0.0 release --------- Co-authored-by: ajaz <ajaz@adobe.com> Co-authored-by: Sumaiya <108254100+AjazSumaiya@users.noreply.github.com> Co-authored-by: Peter Dohogne <pdohogne@magento.com> Co-authored-by: Peter Dohogne <pdohogne@adobe.com>
1 parent a69d5ec commit 2447b0c

4 files changed

Lines changed: 464 additions & 4 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"@adobe/aio-lib-core-config": "^5",
1111
"@adobe/aio-lib-core-logging": "^3",
1212
"@adobe/aio-lib-core-networking": "^5",
13+
"@adobe/aio-lib-db": "^1.0.0",
1314
"@adobe/aio-lib-env": "^3",
1415
"@adobe/aio-lib-ims": "^7",
1516
"@adobe/aio-lib-runtime": "^7.1.3",

src/commands/app/deploy.js

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const {
2424
getFilesCountWithExtension
2525
} = require('../../lib/app-helper')
2626
const rtLib = require('@adobe/aio-lib-runtime')
27+
const dbLib = require('@adobe/aio-lib-db')
28+
const { DB_STATUS } = require('../../lib/defaults')
2729
const LogForwarding = require('../../lib/log-forwarding')
2830
const { sendAppAssetsDeployedAuditLog, sendAppDeployAuditLog } = require('../../lib/audit-logger')
2931
const { setRuntimeApiHostAndAuthHandler, getAccessToken } = require('../../lib/auth-helper')
@@ -133,7 +135,7 @@ class Deploy extends BuildCommand {
133135
const v = {
134136
...setRuntimeApiHostAndAuthHandler(values[i])
135137
}
136-
await this.deploySingleConfig({ name: k, config: v, originalConfig: values[i], flags, spinner })
138+
await this.deploySingleConfig({ name: k, config: v, originalConfig: values[i], flags, spinner, accessToken: cliDetails?.accessToken })
137139
if (cliDetails?.accessToken && v.app.hasFrontend && flags['web-assets']) {
138140
const opItems = getFilesCountWithExtension(v.web.distProd)
139141
try {
@@ -172,7 +174,7 @@ class Deploy extends BuildCommand {
172174
this.log(chalk.green(chalk.bold('Successful deployment 🏄')))
173175
}
174176

175-
async deploySingleConfig ({ name, config, originalConfig, flags, spinner }) {
177+
async deploySingleConfig ({ name, config, originalConfig, flags, spinner, accessToken }) {
176178
const onProgress = !flags.verbose
177179
? info => {
178180
spinner.text = info
@@ -204,6 +206,11 @@ class Deploy extends BuildCommand {
204206
this.error(err)
205207
}
206208

209+
// provision database if configured
210+
if (config.manifest?.full?.database?.['auto-provision'] === true) {
211+
await this.provisionDatabase(config, spinner, flags, accessToken)
212+
}
213+
207214
if (flags.actions) {
208215
if (config.app.hasBackend) {
209216
let filterEntities
@@ -300,6 +307,79 @@ class Deploy extends BuildCommand {
300307
}
301308
}
302309

310+
async provisionDatabase (config, spinner, flags, accessToken) {
311+
const { namespace } = config.ow || {}
312+
if (!(namespace)) {
313+
throw new Error('Database deployment requires OW namespace configuration.')
314+
}
315+
if (!accessToken) {
316+
throw new Error('Database deployment requires an IMS access token.')
317+
}
318+
319+
const region = config.manifest?.full?.database?.region
320+
const regionMess = region ? `'${region}'` : 'default'
321+
322+
const progress = ({ next = undefined, status = undefined, verboseOnly = false }, statusMethod = spinner.info) => {
323+
if (flags.verbose) {
324+
const method = statusMethod.bind(spinner)
325+
method(status)
326+
spinner.start(next)
327+
} else if (next && !verboseOnly) {
328+
spinner.text = next
329+
}
330+
}
331+
332+
let provRes
333+
try {
334+
spinner.start(`Deploying database in the ${regionMess} region...`)
335+
336+
const db = await dbLib.init({ ow: { namespace }, region, token: accessToken })
337+
338+
progress({ next: 'Checking existing database deployment status...', verboseOnly: true })
339+
340+
let prevStatus
341+
let statusRegion
342+
const next = `Submitting database provisioning request in the ${regionMess} region...`
343+
try {
344+
const statusRes = await db.provisionStatus()
345+
prevStatus = statusRes.status.toUpperCase()
346+
statusRegion = statusRes.region
347+
const regionMessage = statusRegion ? ` in region '${statusRegion}'` : ''
348+
progress({ status: chalk.dim(`Existing database provisioning status: ${prevStatus}${regionMessage}`), next })
349+
} catch (err) {
350+
progress({ status: chalk.red(`Database status check failed: ${err.message}`), next }, spinner.warn)
351+
prevStatus = null
352+
}
353+
354+
if (prevStatus === DB_STATUS.PROVISIONED) {
355+
spinner.succeed(chalk.green(`Database is deployed and ready for use in the '${statusRegion}' region`))
356+
return
357+
} else if (prevStatus === DB_STATUS.REQUESTED || prevStatus === DB_STATUS.PROCESSING) {
358+
spinner.succeed(chalk.green(`Database provisioning request has already been submitted in the '${statusRegion}' region and is pending`))
359+
return
360+
}
361+
362+
provRes = await db.provisionRequest()
363+
progress({ status: chalk.dim(`Database provisioning result:\n${JSON.stringify(provRes, null, 2)}`) })
364+
} catch (error) {
365+
spinner.fail(chalk.red('Database deployment failed'))
366+
throw error
367+
}
368+
369+
const resultStatus = provRes?.status?.toUpperCase() || DB_STATUS.UNKNOWN
370+
if (resultStatus === DB_STATUS.PROVISIONED) {
371+
spinner.succeed(chalk.green(`Database is deployed and ready for use in the '${provRes.region}' region`))
372+
} else if (resultStatus === DB_STATUS.REQUESTED || resultStatus === DB_STATUS.PROCESSING) {
373+
spinner.succeed(chalk.green(`Database provisioning request submitted in the '${provRes.region}' region, database deployment is now pending`))
374+
} else if (resultStatus === DB_STATUS.FAILED || resultStatus === DB_STATUS.REJECTED) {
375+
const message = `Database provisioning request failed with status '${resultStatus}'`
376+
spinner.fail(chalk.red(message))
377+
throw new Error(`${message}: ${provRes.message || 'Unknown error'}`)
378+
} else {
379+
spinner.warn(chalk.yellow(`Database provisioning request returned unexpected status '${resultStatus}', an update to the aio cli tool may be necessary.`))
380+
}
381+
}
382+
303383
async publishExtensionPoints (deployConfigs, aioConfig, force) {
304384
const libConsoleCLI = await this.getLibConsoleCLI()
305385

src/lib/defaults.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,16 @@ module.exports = {
4141
EXTENSIONS_CONFIG_KEY: 'extensions',
4242
// Adding tracking file constants
4343
LAST_BUILT_ACTIONS_FILENAME: 'last-built-actions.json',
44-
LAST_DEPLOYED_ACTIONS_FILENAME: 'last-deployed-actions.json'
44+
LAST_DEPLOYED_ACTIONS_FILENAME: 'last-deployed-actions.json',
45+
// Database constants
46+
DB_STATUS: {
47+
PROVISIONED: 'PROVISIONED',
48+
REQUESTED: 'REQUESTED',
49+
PROCESSING: 'PROCESSING',
50+
FAILED: 'FAILED',
51+
REJECTED: 'REJECTED',
52+
NOT_PROVISIONED: 'NOT_PROVISIONED',
53+
DELETED: 'DELETED',
54+
UNKNOWN: 'UNKNOWN'
55+
}
4556
}

0 commit comments

Comments
 (0)