@sap/cds-mtxs
Advanced tools
Comparing version 1.12.0 to 1.12.1
@@ -73,2 +73,3 @@ #!/usr/bin/env node | ||
return _handleError(message + ` | ||
USAGE | ||
@@ -75,0 +76,0 @@ |
@@ -9,2 +9,9 @@ # Change Log | ||
## Version 1.12.1 - 2023-10-17 | ||
### Fixed | ||
- More stable upgrade with extensibility enabled. | ||
- Downloaded migrated extension projects now contain correct base model references. | ||
## Version 1.12.0 - 2023-10-05 | ||
@@ -31,3 +38,3 @@ | ||
- Extensions containing new entities with associations to base entities do no longer cause a compilation error. | ||
- For HANA deployment, no recompilation is done any more for applications not using extensibility. | ||
- For SAP HANA deployment, no recompilation is done any more for applications not using extensibility. | ||
@@ -34,0 +41,0 @@ ## Version 1.11.0 - 2023-09-01 |
@@ -360,3 +360,3 @@ const path = require('path') | ||
module.exports.getMigratedProjects = async (req, tagRule, tenant) => { | ||
module.exports.getMigratedProjects = async (req, tagRule, defaultTag, tenant) => { | ||
const temp = await mtxAdapter.mkdirTemp() | ||
@@ -366,3 +366,3 @@ | ||
// { directory, dry, force, tagRule: tagRegex, tag: defaultTag, "skip-verification": skipVerification, "ignore-migrations": ignoreMigrations } | ||
await module.exports.migrate([tenant], { directory: temp, dry: true, skipVerification: true, tagRule, force: true}) | ||
await module.exports.migrate([tenant], { directory: temp, dry: true, skipVerification: true, tagRule, tag: defaultTag, force: true}) | ||
@@ -398,3 +398,3 @@ const projectsLocation = path.join(temp, tenant) | ||
const content = await read(file, 'utf-8') | ||
const fixedContent = content.replace(/\'_base\/.*\'/, '\'_base\'/g') | ||
const fixedContent = content.replace(/\'_base\/.*\'/g, '\'_base\'') | ||
await write(file, fixedContent, 'utf-8') | ||
@@ -401,0 +401,0 @@ } |
module.exports = axError => { | ||
const { inspect } = require('util'); | ||
const { url, method } = axError.config ?? {}; | ||
const { code, response } = axError; | ||
const { status, data } = response ?? {}; | ||
const { code, response = {} } = axError; | ||
const { status } = response; | ||
let { data } = response; | ||
if (Buffer.isBuffer(data)) { | ||
data = data.toString(); | ||
} | ||
const reason = data?.error /* RFC 6749 */ ? inspect(data.error) : axError.message; | ||
@@ -7,0 +11,0 @@ const prefix = (url && method |
{ | ||
"name": "@sap/cds-mtxs", | ||
"version": "1.12.0", | ||
"version": "1.12.1", | ||
"description": "SAP Cloud Application Programming Model - Multitenancy library", | ||
@@ -5,0 +5,0 @@ "homepage": "https://cap.cloud.sap/", |
@@ -31,3 +31,3 @@ const cds = require('@sap/cds/lib') | ||
this.on('getMigratedProjects', (req) => { | ||
const { tagRule } = req.data | ||
const { tagRule, defaultTag } = req.data | ||
@@ -38,3 +38,3 @@ // REVIEW check if access for arbitrary tenants needed | ||
return getMigratedProjects(req, tagRule, tenant) | ||
return getMigratedProjects(req, tagRule, defaultTag, tenant) | ||
}) | ||
@@ -41,0 +41,0 @@ |
@@ -0,1 +1,2 @@ | ||
const { inspect } = require('util') | ||
const cds = require('@sap/cds/lib'), { uuid } = cds.utils | ||
@@ -18,3 +19,3 @@ const { retry } = require('../lib/utils') | ||
async enqueue(clusters, op, args = [], onJobDone) { | ||
const _args = args.length > 0 ? ['with args', args.filter(Boolean)] : [] | ||
const _args = args.length > 0 ? ['with args', inspect(args.filter(Boolean), { depth: 5, colors: true })] : [] | ||
LOG.info(`enqueuing '${op}' job for`, clusters, ..._args) | ||
@@ -21,0 +22,0 @@ |
@@ -267,25 +267,24 @@ const crypto = require('crypto') | ||
async function _getExtResources(tx) { | ||
if (tenant) cds.context = { tenant } | ||
let extSources | ||
try { | ||
const cqn = SELECT('sources').from('cds.xt.Extensions').where('sources !=', null).orderBy('timestamp') | ||
const extSources = await tx.run(cqn) | ||
if (extSources && extSources.length) { | ||
const root = await fs.mkdtemp(`${TEMP_DIR}${path.sep}extension-`) | ||
try { | ||
await Promise.all(extSources.map(({sources}) => readData(sources, root))) | ||
return await tar.cz (root) // REVISIT: pipe to res instead of materializing buffer | ||
} finally { | ||
rimraf (root) | ||
extSources = await cds.db.run(cqn) | ||
} catch (e) { | ||
DEBUG?.(`cds.xt.Extensions not yet deployed for tenant ${tenant}`, e) | ||
return null | ||
} | ||
if (extSources && extSources.length) { | ||
const root = await fs.mkdtemp(`${TEMP_DIR}${path.sep}extension-`) | ||
try { | ||
// important to keep the sequence of extensions | ||
// readData (tar) fails to run in parallel | ||
for (const extSource of extSources) { | ||
await readData(extSource.sources, root) | ||
} | ||
return await tar.cz (root) // REVISIT: pipe to res instead of materializing buffer | ||
} finally { | ||
rimraf (root) | ||
} | ||
} | ||
try { | ||
if (tenant) cds.context = { tenant } | ||
return await _getExtResources(cds.db) | ||
// if (cds.context.tenant === tenant) return await _getExtResources(cds.db) | ||
// else return await cds.db.tx({ tenant: tenant}, _getExtResources) | ||
} catch (e) { | ||
DEBUG?.(`cds.xt.Extensions not yet deployed for tenant ${tenant}`, e) // REVISIT: Questionable usage of try-catch pattern | ||
return null | ||
} | ||
} | ||
@@ -292,0 +291,0 @@ } |
@@ -30,5 +30,11 @@ const cds = require('@sap/cds/lib'), {db} = cds.env.requires | ||
ds.on ('subscribe', req => { | ||
ds.on ('subscribe', async req => { | ||
const { tenant:t, options: { _: params } = {}, metadata } = req.data | ||
return _deploy(req, hana.acquire(t, _imCreateParams(t, params, metadata))) | ||
let existingContainer | ||
try { existingContainer = await hana.get(t, { disableCache: true }) } catch (e) { | ||
if (e.status === 404) return _deploy(req, hana.create(t, _imCreateParams(t, params, metadata)), true) | ||
else throw e | ||
} | ||
// run upgrade | ||
return _deploy(req, existingContainer) | ||
}) | ||
@@ -42,3 +48,3 @@ ds.on (['upgrade', 'extend'], req => { | ||
await hana.deploy (container, t, out, _hdiDeployParams(t, params)) | ||
LOG.info(`finished HANA deployment for tenant ${t}`) | ||
LOG.info(`successfully deployed to tenant ${t}`) | ||
}) | ||
@@ -68,4 +74,4 @@ ds.on ('unsubscribe', req => { | ||
await migration.checkMigration(req) | ||
}) | ||
}) | ||
}) | ||
@@ -210,3 +216,3 @@ } | ||
async function _deploy (req, _container) { | ||
async function _deploy (req, _container, skipExt = false) { | ||
const { tenant, options: { _: params = {}, csn: csnFromParameter } = {} } = req.data | ||
@@ -231,3 +237,3 @@ | ||
// Can already start getting the csn if later required | ||
const _csn = isExtensible && !csnFromParameter ? csn4(tenant) : csnFromParameter | ||
const _csn = isExtensible && !csnFromParameter && !skipExt ? csn4(tenant) : csnFromParameter | ||
@@ -238,3 +244,3 @@ // 1. Unpack what comes from getResources() | ||
// 2. Get csvs from extensions | ||
const updateCsvs = !csnFromParameter && !!await csvs4(tenant) | ||
const updateCsvs = !csnFromParameter && !skipExt && !!await csvs4(tenant) | ||
@@ -241,0 +247,0 @@ if (_csn) { |
@@ -43,10 +43,18 @@ const https = require('https') | ||
if (e.status === 404) return create(tenant, parameters) | ||
cds.error(_errorMessage(e, 'acquiring', tenant), { status: e.response?.status ?? 500 }) | ||
throw e | ||
} | ||
} | ||
// TODO revisit control flow | ||
async function get(tenant, options) { | ||
const [{ credentials } = {}] = await _bindings4([tenant], options) | ||
let credentials | ||
let result | ||
try { | ||
[{ credentials } = {}] = await _bindings4([tenant], options) | ||
result = { name: await _instanceName4(tenant), tenant_id: tenant, credentials, tags: ['hana'] } | ||
} catch (e) { | ||
cds.error(_errorMessage(e, 'getting', tenant), { status: e.status ?? 500 }) | ||
} | ||
if (!credentials) cds.error(`Tenant '${tenant}' does not exist`, { status: 404 }) | ||
return { name: await _instanceName4(tenant), tenant_id: tenant, credentials, tags: ['hana'] } | ||
return result | ||
} | ||
@@ -87,3 +95,3 @@ | ||
async function _instanceName4(tenant) { | ||
if (cds.requires.multitenancy.humanReadableInstanceName) return tenant | ||
if (cds.requires.multitenancy?.humanReadableInstanceName) return tenant | ||
// Compatible with @sap/instance-manager-created instances | ||
@@ -94,4 +102,4 @@ return require('crypto').createHash('sha256').update(`${await _planId()}_${tenant}`).digest('base64') | ||
_bindings4.cached = {} | ||
async function _bindings4(tenants, options = {}) { | ||
const useCache = cacheBindings && !options.disableCache && tenants !== '*' | ||
async function _bindings4(tenants, { disableCache = false } = {}) { | ||
const useCache = cacheBindings && !disableCache && tenants !== '*' | ||
const uncached = useCache ? tenants.filter(t => !(t in _bindings4.cached)) : tenants | ||
@@ -98,0 +106,0 @@ DEBUG?.('retrieving', { tenants }, { uncached }) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
228791
4419