UNPKG

samtsc

Version:

This project was put together to make working with the AWS SAM framework easier for developers. It simplifies working with the SAM framework, using real-time updates to lambda functions, layers and resources. This is done by **samtsc** connecting to the

214 lines (182 loc) 8.38 kB
console.log('samtsc: Loading SAM Framework Tools'); const { execSync } = require('child_process'); const { execOnlyShowErrors } = require('./tsc-tools'); const { mkdir, watch, existsSync, symlinkSync, readFileSync, copyFileSync } = require('./file-system'); const { logger } = require('./logger'); const { samconfig } = require('./sam/samconfig'); const { SAMTemplate } = require('./sam/template'); const { copyFolder } = require('./file-system'); const { resolve, relative } = require('path'); const { PluginFramework } = require('./plugin-framework'); const tempDir = "./.build/tmp"; mkdir(tempDir); logger.loadConfig(samconfig); console.debug = (...params) => { if(samconfig.debug) { console.log('samtsc:', ...params); } } let buildRoot; module.exports.setBuildRoot = (rootPath) => { buildRoot = rootPath; } class SAMFramework { constructor(path, buildRootDir, flags) { console.log('samtsc: Loading Framework'); const self = this; this.loadPromise = samconfig.load(flags, buildRootDir); this.pluginFramework = new PluginFramework(samconfig); this.loadPromise.then(() => { samconfig.save(); }); buildRoot = buildRootDir; this.buildRoot = buildRoot; this.path = path; } async load() { await this.loadPromise; this.pluginFramework.preTemplateLoad(); this.template = new SAMTemplate(this.path, buildRoot, samconfig, samconfig.stack_name); await this.template.reload(); this.pluginFramework.postTemplateLoad(); if(samconfig.include_in_builddir) { if(!existsSync('.build/root')) { mkdir('.build/root'); } this.pluginFramework.preCopyIncludes(); samconfig.include_in_builddir = samconfig.include_in_builddir.split(','); samconfig.include_in_builddir.forEach((x, i) => { if(!x) { return; } const source = resolve(x); const dest = resolve('.build/root', x); if(!existsSync(source)) { return; } const relativePath = relative(resolve('.'), source); samconfig.include_in_builddir[i] = relativePath; copyFolder(source, dest); }); this.pluginFramework.postCopyIncludes(); } if(samconfig.skip_init_deploy != 'true') { this.templateUpdated(); } if(!samconfig.build_only && !samconfig.package && !samconfig.deploy_only) { const self = this; this.template.events.on('layer-change', (source) => { logger.debug('Layer Updated', source); self.templateUpdated(source); }); this.template.events.on('template-update', (source) => { logger.debug('Template Updated', source); self.templateUpdated(); } ) this.watcher = watch('.', { recursive: true }, (event, filename) => { logger.debug('Watcher file event', filename); const ignore = this.template.fileEvent(filename); if(samconfig.include_in_builddir) { logger.debug('Evaluating include files'); let modified = false; samconfig.include_in_builddir.forEach(x => { if(!filename.startsWith(x)) { return; } const source = resolve(x); const dest = resolve('.build/root', x); if(!existsSync(source)) { return; } this.pluginFramework.preCopyIncludes(); copyFolder(source, dest); this.pluginFramework.postCopyIncludes(); modified = true; }); logger.debug('Evaluating template reload', modified, ignore); if(modified && !ignore) { self.templateUpdated(); } } }); } if(samconfig.package) { const outputDir = 'dist/cloudformation'; mkdir(outputDir); const environments = samconfig.package && samconfig.environments? samconfig.environments.split(',') : [samconfig.environment]; environments.forEach(env => { copyFileSync(resolve(this.buildRoot, `template-${env}.config`), `dist/cloudformation/template-${env}.config`); }); let postfix = ''; if(samconfig.region_postfix) { postfix = '-' + samconfig.region; } let parameters = `--s3-bucket ${samconfig.s3_bucket} --s3-prefix ${samconfig.s3_prefix} --output-template-file ../../${outputDir}/template${postfix}.yaml`; if(samconfig.region) { parameters += ` --region ${samconfig.region}`; } logger.info('packaging'); const execCommand = `sam package ${parameters}`; logger.debug(execCommand); execSync(execCommand, { cwd: buildRoot, stdio: 'inherit' }); } } templateUpdated() { try { logger.info('Validating SAM template'); execSync('sam validate', { cwd: buildRoot, stdio: 'inherit' }); logger.info('Building SAM deployment'); execSync(`sam build`, { cwd: buildRoot, stdio: 'inherit' }); if(!samconfig.minimal_deploy) { const source = resolve(buildRoot, '.aws-sam'); const dest = resolve('.aws-sam'); logger.info('Copying sam files for use at root', source, dest); copyFolder(source, dest); } console.log('samtsc: Completed building SAM deployment, deploying with SAM'); if (samconfig.build_only != 'true' && samconfig.build_only != true && !samconfig.package ) { let parameters = `--no-fail-on-empty-changeset --s3-bucket ${samconfig.s3_bucket}`; let paramOverrides = []; const envConf = this.template.templateConfigurations.find(x => x.Tags.environment == samconfig.environment); logger.debug('Env Config', samconfig.environment, JSON.stringify(envConf)); const params = envConf? envConf.Parameters || {} : {}; if(samconfig.base_stack) { if(params.StackName) { paramOverrides.push(`StackName=${samconfig.base_stack}`); } if(params.StackTagName) { paramOverrides.push(`StackTagName=${samconfig.base_stack}`); } if(params.EnvironmentName) { paramOverrides.push(`EnvironmentName=${samconfig.environment}`); } if(params.EnvironmentTagName) { paramOverrides.push(`EnvironmentTagName=${samconfig.environment}`); } } Object.keys(params).forEach(k => { if(k == 'StackName' || k =='EnvironmentTagName') { return; } const defaultVal = params[k]; if(defaultVal) { paramOverrides.push(`"${k}=${defaultVal}"`); } }); if(paramOverrides && paramOverrides.length > 0) { parameters = `${parameters} --parameter-overrides ${paramOverrides.join(' ')}`; } logger.info('deploying'); execSync(`sam deploy ${parameters}`, { cwd: buildRoot, stdio: 'inherit' }); console.log('samtsc: deploy complete, waiting for file change'); } } catch (err) { if(samconfig.deploy_only || samconfig.build_only || samconfig.package) { throw err; } else { console.log(err); } } } } module.exports.SAMFramework = SAMFramework;