@sap/cds-mtxs
Advanced tools
Comparing version 1.8.2 to 1.8.3
@@ -122,3 +122,3 @@ const path = require('path') | ||
const { directory, dry, force, tagRule: tagRegex, tag: defaultTag, "skip-verification": skipVerification } = options | ||
const { directory, dry, force, tagRule: tagRegex, tag: defaultTag, "skip-verification": skipVerification, "ignore-migrations": ignoreMigrations } = options | ||
@@ -206,3 +206,9 @@ const migrationResult = new MigrationResult() | ||
try { | ||
await _verifyExtension(tenantProjectFolder, tenant, tags) | ||
// check diff and abort if necessary | ||
const existingCsn = await mtxAdapter.getCsn(tenant) | ||
await fs.mkdir(path.join(tenantProjectFolder, 'mtx_original_csn'), { recursive: true }) | ||
await fs.writeFile(path.join(tenantProjectFolder, 'mtx_original_csn', 'csn.json'), JSON.stringify(existingCsn, null, 2)) | ||
await _verifyExtension(migrationResult, tenantProjectFolder, tenant, tags, existingCsn, options) | ||
migrationResult.log(tenant, `Extension verification successful for tenant ${tenant} [${tenantProjectFolder}]`) | ||
@@ -268,9 +274,14 @@ } catch (error) { | ||
async function _verifyExtension(tenantProjectFolder, tenant, tags) { | ||
async function _verifyExtension(migrationResult, tenantProjectFolder, tenant, tags, existingCsn, options) { | ||
const projectFolders = tags//await fs.readdir(tenantProjectFolder) | ||
const { "ignore-migrations": ignoreMigrations } = options | ||
const projectFolders = tags | ||
const mp = await cds.connect.to('cds.xt.ModelProviderService') | ||
const isExtended = await (async () => { try { return await mp.isExtended(tenant) } catch(error) { return false } })() | ||
const mainCsn = await mp.getCsn({ tenant, flavor: 'inferred', activated: true }) | ||
if (!mainCsn) throw new Error(`Verification error for tenant ${tenant}: Empty base model`) | ||
let previewCsn = mainCsn | ||
@@ -287,5 +298,2 @@ | ||
// check diff and abort if necessary | ||
const existingCsn = await mtxAdapter.getCsn(tenant) | ||
// ensure flavor | ||
@@ -302,4 +310,10 @@ const inferredExistingCsn = cds.compile({inferred: existingCsn}, {flavor: 'inferred'}) | ||
} | ||
if (hanaDiffNewToOld.migrations.length) { | ||
throw new Error(`Verification error for tenant ${tenant}: migrations found`) | ||
if (hanaDiffNewToOld.migrations.length) { | ||
const ignore = ignoreMigrations ?? '^sap.common' | ||
const relevantMigrations = hanaDiffNewToOld.migrations.filter( m => !new RegExp(ignore).test(m.name)) | ||
migrationResult.log(tenant, `Table migrations found but ignored for /${ignore}/`) | ||
if (relevantMigrations.length) throw new Error(`Verification error for tenant ${tenant}: table migrations found\n` + | ||
`${relevantMigrations.map( ({ name, suffix, changeset }) => `${name}${suffix}: ${changeset.map(({sql}) => sql)}\n`)}`) | ||
} | ||
@@ -306,0 +320,0 @@ |
{ | ||
"name": "@sap/cds-mtxs", | ||
"version": "1.8.2", | ||
"version": "1.8.3", | ||
"description": "SAP Cloud Application Programming Model - Multitenancy library", | ||
@@ -5,0 +5,0 @@ "homepage": "https://cap.cloud.sap/", |
@@ -82,3 +82,3 @@ const cds = require('@sap/cds/lib') | ||
if (lazyT0) { | ||
await require('../plugins/common/metadata').resubscribeT0IfNeeded(options._) | ||
await require('../plugins/common/metadata').resubscribeT0IfNeeded(options?._) | ||
} | ||
@@ -85,0 +85,0 @@ const js = await cds.connect.to(JobsService) |
@@ -0,4 +1,6 @@ | ||
const { join } = require('path') | ||
const HdiDeployUtil = require('@sap/cds/bin/deploy/to-hana/hdiDeployUtil') | ||
const { clean_env } = require('@sap/hdi-deploy/library') | ||
const cds = require ('@sap/cds/lib') | ||
const { fs, mkdirp } = cds.utils | ||
@@ -9,8 +11,14 @@ exports.deploy = async (hana, tenant, cwd, options) => { | ||
DEBUG?.(`deployment directory: ${cwd}`) | ||
DEBUG?.(`HDI options: ${env.HDI_DEPLOY_OPTIONS}`) | ||
DEBUG?.(`effective HDI options: ${env.HDI_DEPLOY_OPTIONS}`) | ||
const logPath = join(cds.root, 'logs', `${cds.context.tenant}.log`) | ||
const writeStream = fs.createWriteStream(logPath) | ||
await mkdirp('logs') | ||
LOG.info('------------[BEGIN HDI-DEPLOY-OUTPUT]---------------') | ||
try { | ||
LOG.info('------------[BEGIN HDI-DEPLOY-OUTPUT]---------------') | ||
await HdiDeployUtil.deployTenant (cwd, env, LOG) | ||
} finally { | ||
LOG.info('-------------[END HDI-DEPLOY-OUTPUT]----------------') | ||
writeStream.end() | ||
LOG.info(`written deployment logs to ${logPath}`) | ||
} | ||
@@ -17,0 +25,0 @@ } |
@@ -17,3 +17,3 @@ const https = require('https') | ||
async function create(tenant, parameters = {}) { | ||
LOG.info('creating HDI container for', { tenant }, 'with', { parameters }) | ||
LOG.info('creating HDI container for', { tenant }, 'with', { ...parameters }) | ||
const name = await _instanceName4(tenant), service_plan_id = await _planId() | ||
@@ -136,3 +136,3 @@ const { binding_parameters, provisioning_parameters } = parameters | ||
const config = { method: 'POST', timeout: 5000, data, ...auth } | ||
const { access_token, expires_in } = (await axios(authUrl, config)).data | ||
const { access_token, expires_in } = await fetchTokenResiliently(authUrl, config) | ||
_token.cached = { access_token, expiry: Date.now() + expires_in * 1000 } | ||
@@ -160,1 +160,25 @@ } | ||
} | ||
const maxRetries = 3 | ||
const fetchTokenResiliently = module.exports.fetchTokenResiliently = async function (url, config, retriesLeft = maxRetries) { | ||
try { | ||
return (await axios(url, config)).data | ||
} catch (error) { | ||
const { status, headers } = error.response | ||
if (status in { 401: 1, 403: 1 } || retriesLeft === 0) throw error | ||
const attempt = maxRetries - retriesLeft + 1 | ||
DEBUG?.(`fetching token attempt ${attempt} failed with`, { error }) | ||
let delay = 0 | ||
if (status === 429) { | ||
const retryAfter = headers['retry-after'] | ||
if (retryAfter) delay = parseInt(retryAfter, 10) * 1000 | ||
else throw error | ||
} else if (status in { 408: 1, 502: 1, 504: 1 }) { | ||
delay = 300 * 2 ** (attempt - 1) | ||
} else if (status in { 500: 1, 503: 1 }) { | ||
delay = 1000 * 3 ** (attempt - 1) | ||
} | ||
await new Promise((resolve) => setTimeout(resolve, delay)) | ||
return fetchTokenResiliently(url, config, retriesLeft - 1) | ||
} | ||
} |
194571
4112