diff --git a/lib/utils/fonts/fonts.conf b/lib/utils/fonts/fonts.conf new file mode 100644 index 000000000..53aad4e2a --- /dev/null +++ b/lib/utils/fonts/fonts.conf @@ -0,0 +1,158 @@ + + + + + + + + + + /usr/share/fonts + /usr/X11R6/lib/X11/fonts + /usr/local/share/fonts + /code/fonts + + fonts + + ~/.fonts + + + + + mono + + + monospace + + + + + + + sans serif + + + sans-serif + + + + + + + sans + + + sans-serif + + + + + conf.d + + + + /var/cache/fontconfig + fontconfig + + ~/.fontconfig + + + + + 0x0020 + 0x00A0 + 0x00AD + 0x034F + 0x0600 + 0x0601 + 0x0602 + 0x0603 + 0x06DD + 0x070F + 0x115F + 0x1160 + 0x1680 + 0x17B4 + 0x17B5 + 0x180E + 0x2000 + 0x2001 + 0x2002 + 0x2003 + 0x2004 + 0x2005 + 0x2006 + 0x2007 + 0x2008 + 0x2009 + 0x200A + 0x200B + 0x200C + 0x200D + 0x200E + 0x200F + 0x2028 + 0x2029 + 0x202A + 0x202B + 0x202C + 0x202D + 0x202E + 0x202F + 0x205F + 0x2060 + 0x2061 + 0x2062 + 0x2063 + 0x206A + 0x206B + 0x206C + 0x206D + 0x206E + 0x206F + 0x2800 + 0x3000 + 0x3164 + 0xFEFF + 0xFFA0 + 0xFFF9 + 0xFFFA + 0xFFFB + + + + 30 + + + + \ No newline at end of file diff --git a/src/bin/fun-install.js b/src/bin/fun-install.js index 687ca593c..894e8b0ef 100755 --- a/src/bin/fun-install.js +++ b/src/bin/fun-install.js @@ -37,6 +37,8 @@ program .description('install dependencies which are described in fun.yml file.') .action(async (packageNames, program) => { + if (_.isEmpty(packageNames)) { return; } + const options = convertOptions(program); // merge options default values. @@ -181,7 +183,6 @@ program.parse(process.argv); notifier.notify(); - if (!program.args.length) { if (program.packageType) { diff --git a/src/lib/deploy/deploy-by-tpl.js b/src/lib/deploy/deploy-by-tpl.js index f209ff7bf..99283dc5a 100644 --- a/src/lib/deploy/deploy-by-tpl.js +++ b/src/lib/deploy/deploy-by-tpl.js @@ -703,7 +703,7 @@ async function partialDeployment(sourceName, tpl) { } if (nameArray.length === 2) { - + const funcRes = definition.findServiceByCertainServiceAndFunctionName(tpl.Resources, _.first(nameArray), _.last(nameArray)); return { @@ -819,16 +819,9 @@ async function deployByApi(baseDir, tpl, tplPath, context) { const { Type: resourceType = '' } = resourceRes; if (resourceType === definition.SERVICE_RESOURCE) { - await showResourcesChanges({ - Resources: { - [resourceName]: resourceRes - } - }, remoteYml); + await showResourcesChanges({ Resources: { [resourceName]: resourceRes } }, remoteYml); - if (!context.assumeYes - && !await promptForConfirmContinue('Please confirm to continue.')) { - return; - } + if (!context.assumeYes && !await promptForConfirmContinue('Please confirm to continue.')) { return; } await deployTplService({ baseDir, tplPath, serviceName: resourceName, @@ -846,10 +839,7 @@ async function deployByApi(baseDir, tpl, tplPath, context) { await showResourcesChanges(tpl, remoteYml); - if (!context.assumeYes - && !await promptForConfirmContinue('Please confirm to continue.')) { - return; - } + if (!context.assumeYes && !await promptForConfirmContinue('Please confirm to continue.')) { return; } await deployLogs(tpl.Resources); diff --git a/src/lib/fc.js b/src/lib/fc.js index d28e2c0f9..83e198366 100644 --- a/src/lib/fc.js +++ b/src/lib/fc.js @@ -23,6 +23,7 @@ const getUuid = require('uuid-by-string'); const { sleep } = require('./time'); const { makeTrigger } = require('./trigger'); const { makeSlsAuto } = require('./deploy/deploy-support'); +const { isNotEmptyDir } = require('./nas/cp/file'); const { updateTimestamps } = require('./utils/file'); const { green, red, yellow } = require('colors'); const { getFcClient, getEcsPopClient, getNasPopClient } = require('./client'); @@ -171,14 +172,19 @@ const CUSTOM_RUNTIME_JAVA_MAPPING = { 'pathSuffix': '*' }; +const FONTS_MAPPING = { + 'localDir': 'fonts', + 'remoteDir': 'fonts' +}; + const runtimeDependencyMappings = { - 'nodejs6': [NODE_RUNTIME_MAPPING], - 'nodejs8': [NODE_RUNTIME_MAPPING], - 'nodejs10': [NODE_RUNTIME_MAPPING], - 'python2.7': [PYTHON_RUNTIME_MAPPING], - 'python3': [PYTHON_RUNTIME_MAPPING], - 'java8': [JAVA_RUNTIME_MAPPING], - 'custom': [NODE_RUNTIME_MAPPING, PYTHON_RUNTIME_MAPPING, CUSTOM_RUNTIME_JAVA_MAPPING] + 'nodejs6': [NODE_RUNTIME_MAPPING, FONTS_MAPPING], + 'nodejs8': [NODE_RUNTIME_MAPPING, FONTS_MAPPING], + 'nodejs10': [NODE_RUNTIME_MAPPING, FONTS_MAPPING], + 'python2.7': [PYTHON_RUNTIME_MAPPING, FONTS_MAPPING], + 'python3': [PYTHON_RUNTIME_MAPPING, FONTS_MAPPING], + 'java8': [JAVA_RUNTIME_MAPPING, FONTS_MAPPING], + 'custom': [NODE_RUNTIME_MAPPING, PYTHON_RUNTIME_MAPPING, CUSTOM_RUNTIME_JAVA_MAPPING, FONTS_MAPPING] }; async function saveNasMappings(nasYmlPath, nasMappings) { @@ -195,9 +201,10 @@ async function saveNasMappings(nasYmlPath, nasMappings) { return mergedNasMappings; } -async function updateEnvironmentsInTpl({ tplPath, tpl, envs, +function updateEnvironmentsInTpl({ tplPath, tpl, envs, serviceName, - functionName + functionName, + displayLog = true }) { const updatedTplContent = _.cloneDeep(tpl); @@ -215,7 +222,9 @@ async function updateEnvironmentsInTpl({ tplPath, tpl, envs, util.outputTemplateFile(tplPath, updatedTplContent); - console.log(green(`Fun add environment variables to '${serviceName}/${functionName}' in ${tplPath}`)); + if (displayLog) { + console.log(green(`Fun add environment variables to '${serviceName}/${functionName}' in ${tplPath}`)); + } return updatedTplContent; } @@ -347,9 +356,8 @@ async function generateNasMappingsAndEnvs({ remoteNasDir: remoteDir }); - Object.assign(envs, { - [mapping.env]: generateNasEnv(mapping.defaultEnv, mapping.pathSuffix ? remoteDir + '/' + mapping.pathSuffix : remoteDir) - }); + const resolveNasDir = mapping.pathSuffix ? remoteDir + '/' + mapping.pathSuffix : remoteDir; + Object.assign(envs, generateNasEnv(mapping.defaultEnv, resolveNasDir, mapping.env)); outputNasMappingLog(baseDir, nasMappingPath, localDir); } @@ -364,15 +372,16 @@ async function generateNasMappingsAndEnvs({ }; } -function generateNasEnv(defaultEnv, remoteNasDir) { - let nasEnv; +function generateNasEnv(defaultEnvValue, remoteNasDir, envKey) { + const env = {}; - if (defaultEnv) { - nasEnv = `${remoteNasDir}:${defaultEnv}`; - } else { - nasEnv = remoteNasDir; + if (!envKey) { + return env; } - return nasEnv; + + env[envKey] = defaultEnvValue ? `${remoteNasDir}:${defaultEnvValue}` : remoteNasDir; + + return env; } function resolveLocalNasDir(runtime, baseDir, codeUri, localDirInNasMappings, serviceName, functionName) { @@ -450,7 +459,7 @@ async function processOtherFunctionsUnderServiceIfNecessary({ for (const pendingFuntion of pendingFuntions) { - tpl = await updateEnvironmentsInTpl({ + tpl = updateEnvironmentsInTpl({ tplPath, tpl, envs, serviceName: originServiceName, functionName: pendingFuntion.functionName @@ -472,14 +481,15 @@ async function processNasMappingsAndEnvs({ tpl, tplPath, runtime, codeUri, baseD const { serviceRes } = definition.findFunctionByServiceAndFunctionName(tpl.Resources, serviceName, functionName); const { envs, nasMappings, remoteNasDirPrefix } = await generateNasMappingsAndEnvs({ - baseDir, + baseDir, runtime, codeUri, serviceName: serviceName, functionName: functionName, - runtime, - codeUri, nasConfig: convertedNasConfig || (serviceRes.Properties || {}).NasConfig }); + const appendContet = ` ${remoteNasDirPrefix}${FONTS_MAPPING.remoteDir}`; + await generateFontsConfAndEnv(baseDir, codeUri, appendContet); + const localDirs = _.map(runtimeDependencyMappings[runtime], mapping => path.join(codeUri, mapping.localDir)); if (_.isEmpty(nasMappings[serviceName])) { @@ -665,7 +675,6 @@ async function processNasAutoConfiguration({ tpl, tplPath, runtime, codeUri, con console.log(yellow(`\nFun has automatically uploaded your code dependency to NAS, then fun will use 'fun deploy ${serviceName}/${functionName}' to redeploy.`)); console.log(`Waiting for service ${serviceName} to be deployed...`); - const partialDeploy = await require('./deploy/deploy-by-tpl').partialDeployment(`${serviceName}/${functionName}`, updatedTplContent); if (partialDeploy.resourceName) { @@ -686,7 +695,7 @@ async function updateEnvironments({ serviceName, functionName }) { - const updatedTplContent = await updateEnvironmentsInTpl({ envs, tpl, tplPath, serviceName, functionName }); + const updatedTplContent = updateEnvironmentsInTpl({ envs, tpl, tplPath, serviceName, functionName }); return await processOtherFunctionsUnderServiceIfNecessary({ tpl: updatedTplContent, tplPath, @@ -983,6 +992,38 @@ function generateNasAndVpcConfig(mountTarget, securityGroupId, serviceName) { }; } +function writeFileToLine(filePath, content, lineNum) { + let data = fs.readFileSync(filePath, 'utf8').split(/\r?\n/gm); + data.splice(lineNum, 0, content); + fs.writeFileSync(filePath, data.join('\n'), { + encoding: 'utf8' + }); +} + +const DEFAULT_FONTS_CONFIG_ENV = { + 'FONTCONFIG_FILE': '/code/.fonts.conf' +}; + +async function generateFontsConfAndEnv(baseDir, codeUri, appendContet) { + const absCodeUri = path.resolve(baseDir, codeUri); + const fontsDir = path.join(absCodeUri, 'fonts'); + + if (!await fs.pathExists(fontsDir) || !await isNotEmptyDir(fontsDir)) { return {}; } + + const fontsConfPath = path.join(absCodeUri, '.fonts.conf'); + + if (!await fs.pathExists(fontsConfPath)) { + const sourcePath = path.resolve(__dirname, './utils/fonts/fonts.conf'); + await fs.copyFile(sourcePath, fontsConfPath); + } + + if (appendContet) { + writeFileToLine(fontsConfPath, appendContet, 29); + } + + return DEFAULT_FONTS_CONFIG_ENV; +} + async function makeFunction(baseDir, { serviceName, functionName, @@ -1021,6 +1062,17 @@ async function makeFunction(baseDir, { if (codeUri && codeUri.startsWith('oss://')) { // oss://my-bucket/function.zip code = extractOssCodeUri(codeUri); } else { + + const fontsConfEnv = await generateFontsConfAndEnv(baseDir, codeUri); + if (!_.isEmpty(fontsConfEnv)) { + + updateEnvironmentsInTpl({ serviceName, functionName, tplPath, + displayLog: false, + tpl: await getTpl(tplPath), + envs: DEFAULT_FONTS_CONFIG_ENV + }); + } + console.log(`\t\tWaiting for packaging function ${functionName} code...`); const { base64, count, compressedSize } = await zipCode(baseDir, codeUri, runtime, functionName); diff --git a/src/lib/nas/cp/file.js b/src/lib/nas/cp/file.js index 56ff9086a..9dc0dc26f 100644 --- a/src/lib/nas/cp/file.js +++ b/src/lib/nas/cp/file.js @@ -54,6 +54,18 @@ async function isEmptyDir(path) { return false; } +// only if the path is directory and there are files in the directory, will true be returned +async function isNotEmptyDir(path) { + const lstat = await fs.lstat(path); + if (lstat.isDirectory()) { + const dirs = await fs.readdir(path); + if (!_.isEmpty(dirs)) { + return true; + } + } + return false; +} + async function getFileSize(filePath) { const stat = await fs.lstat(filePath); return stat.size; @@ -91,7 +103,7 @@ function writeBufToFile(dstPath, buf) { } module.exports = { - isDir, isFile, isEmptyDir, + isDir, isFile, isEmptyDir, isNotEmptyDir, getFileHash, getFileSize, getFilePermission, zipWithArchiver, readFileChunk, writeBufToFile }; \ No newline at end of file