NodeJS Lambda问题与操作顺序(NodeJS Lambda issue with order of operations)
主要问题是代码执行CodePipeline时,它会下载一个输入工件,将下载的工件和grep template.yml解压缩为一个名为Function name的字符串。 它大部分时间都有效,但会失败,说偶尔找不到template.yml文件。 如果我再次运行它,它将毫无错误地工作。 任何帮助表示感谢。 谢谢!
'严格使用'
// dependencies const child_process = require('child_process') const fs = require('fs') const path = require('path') const stripDirs = require('strip-dirs') const AWS = require('aws-sdk') const unzip = require('unzip') const shell = require('shelljs') // global process variable is still accessible process.env['PATH'] = process.env['PATH'] + ':' + process.env['/tmp'] // get reference to S3 client const s3 = new AWS.S3({maxRetries: 1, "signatureVersion":"v4"}) exports.handler = function(event, context) { const codepipeline = new AWS.CodePipeline() let jobId // Notify AWS CodePipeline of a successful job function putJobSuccess(message) { console.log(message) codepipeline.putJobSuccessResult({ jobId }, (err, data) => { if (err) context.fail(err) else context.succeed(message) }) } // Notify AWS CodePipeline of a failed job function putJobFailure(message) { console.error('job failure: ', message) codepipeline.putJobFailureResult({ jobId, failureDetails: { message: JSON.stringify(message), type: 'JobFailed', externalExecutionId: context.invokeid } }, (err, data) => context.fail(message)) } try { const jobEvent = event['CodePipeline.job'] jobId = jobEvent.id const jobData = jobEvent.data console.log(jobData) // Retrieve the value of UserParameters from the Lambda action configuration in AWS CodePipeline, in this case a URL which will be // health checked by this function. const userParams = jobData.actionConfiguration.configuration.UserParameters const userParamsSplit = userParams && userParams.split(' ') if (!userParams || !userParamsSplit || userParamsSplit.length !== 1) throw new Error('The User Parameters field must contain three items separated by spaces: the input artifact name, the location of the lambda function code within the input artifact, and the destination lambda function name') const artifactName = userParamsSplit[0] const artifact = jobData.inputArtifacts.find(a => a.name === artifactName && a.location.type === 'S3') if (!artifact) throw new Error('artifact not found: ', artifactName) console.log('Artifact:', artifact) const tmpDir = '/tmp' const artifactZipFilePath = path.join(tmpDir, stripDirs(artifact.location.s3Location.objectKey, 2)) console.log('ZipFilePath:', artifactZipFilePath) s3.getObject({ Bucket: artifact.location.s3Location.bucketName, Key: artifact.location.s3Location.objectKey }, (err, data) => { if (err) return putJobFailure(`could not download artifact from S3: ${err.stack || err}`) console.log() fs.writeFileSync(artifactZipFilePath, data.Body) const zipFileContents = fs.readFileSync(artifactZipFilePath) const zipFileDir = stripDirs(artifact.location.s3Location.objectKey, 2).slice(0, -4) console.log('zipFileDir:', zipFileDir) const newZipArtifact = path.join('/tmp', stripDirs(artifact.location.s3Location.objectKey, 2)) fs.createReadStream(newZipArtifact).pipe(unzip.Extract({ path: '/tmp' })) const prependFunctionName = shell.grep('FunctionName', '/tmp/template.yml') const destLambdaFunctionName = prependFunctionName.replace(/^.+:/,'').replace(/\s/g,'') const command = require('child_process').exec command(`echo ${destLambdaFunctionName}`, (error, stdout, stderr) => { if (error) { console.log("Error occurs"); console.error(error); return; } console.log(stdout); console.log(stderr); }) lambda.updateFunctionCode({ FunctionName: destLambdaFunctionName, Publish: true, ZipFile: zipFileContents }, function(err, data) { if (err) console.log(err, err.stack) // an error occurred else console.log(data) // successful response const sqsMsg = (data) putJobSuccess('lambda code updated') }) }) } catch (err) { putJobFailure(err.stack) } }
The main issue is when the code executes using CodePipeline it will download an input artifact, unzip the downloaded artifact and grep template.yml for a string called Function name. It works most of the time but will fail saying template.yml file not found occasionally. If I rerun it again it will work without errors. Any help is appreciate. Thanks!
'use strict'
// dependencies const child_process = require('child_process') const fs = require('fs') const path = require('path') const stripDirs = require('strip-dirs') const AWS = require('aws-sdk') const unzip = require('unzip') const shell = require('shelljs') // global process variable is still accessible process.env['PATH'] = process.env['PATH'] + ':' + process.env['/tmp'] // get reference to S3 client const s3 = new AWS.S3({maxRetries: 1, "signatureVersion":"v4"}) exports.handler = function(event, context) { const codepipeline = new AWS.CodePipeline() let jobId // Notify AWS CodePipeline of a successful job function putJobSuccess(message) { console.log(message) codepipeline.putJobSuccessResult({ jobId }, (err, data) => { if (err) context.fail(err) else context.succeed(message) }) } // Notify AWS CodePipeline of a failed job function putJobFailure(message) { console.error('job failure: ', message) codepipeline.putJobFailureResult({ jobId, failureDetails: { message: JSON.stringify(message), type: 'JobFailed', externalExecutionId: context.invokeid } }, (err, data) => context.fail(message)) } try { const jobEvent = event['CodePipeline.job'] jobId = jobEvent.id const jobData = jobEvent.data console.log(jobData) // Retrieve the value of UserParameters from the Lambda action configuration in AWS CodePipeline, in this case a URL which will be // health checked by this function. const userParams = jobData.actionConfiguration.configuration.UserParameters const userParamsSplit = userParams && userParams.split(' ') if (!userParams || !userParamsSplit || userParamsSplit.length !== 1) throw new Error('The User Parameters field must contain three items separated by spaces: the input artifact name, the location of the lambda function code within the input artifact, and the destination lambda function name') const artifactName = userParamsSplit[0] const artifact = jobData.inputArtifacts.find(a => a.name === artifactName && a.location.type === 'S3') if (!artifact) throw new Error('artifact not found: ', artifactName) console.log('Artifact:', artifact) const tmpDir = '/tmp' const artifactZipFilePath = path.join(tmpDir, stripDirs(artifact.location.s3Location.objectKey, 2)) console.log('ZipFilePath:', artifactZipFilePath) s3.getObject({ Bucket: artifact.location.s3Location.bucketName, Key: artifact.location.s3Location.objectKey }, (err, data) => { if (err) return putJobFailure(`could not download artifact from S3: ${err.stack || err}`) console.log() fs.writeFileSync(artifactZipFilePath, data.Body) const zipFileContents = fs.readFileSync(artifactZipFilePath) const zipFileDir = stripDirs(artifact.location.s3Location.objectKey, 2).slice(0, -4) console.log('zipFileDir:', zipFileDir) const newZipArtifact = path.join('/tmp', stripDirs(artifact.location.s3Location.objectKey, 2)) fs.createReadStream(newZipArtifact).pipe(unzip.Extract({ path: '/tmp' })) const prependFunctionName = shell.grep('FunctionName', '/tmp/template.yml') const destLambdaFunctionName = prependFunctionName.replace(/^.+:/,'').replace(/\s/g,'') const command = require('child_process').exec command(`echo ${destLambdaFunctionName}`, (error, stdout, stderr) => { if (error) { console.log("Error occurs"); console.error(error); return; } console.log(stdout); console.log(stderr); }) lambda.updateFunctionCode({ FunctionName: destLambdaFunctionName, Publish: true, ZipFile: zipFileContents }, function(err, data) { if (err) console.log(err, err.stack) // an error occurred else console.log(data) // successful response const sqsMsg = (data) putJobSuccess('lambda code updated') }) }) } catch (err) { putJobFailure(err.stack) } }
原文:https://stackoverflow.com/questions/43546191
最满意答案
这将返回一个带有类名称的数组(即字符串):
ActiveRecord::Base.descendants.map(&:to_s).select {|x| x.match('::')}
而这将返回实际的类对象:
ActiveRecord::Base.descendants.select {|x| x.name.match('::')}
This will return an array with the class names (ie. strings):
ActiveRecord::Base.descendants.map(&:to_s).select {|x| x.match('::')}
while this will return the actual class objects:
ActiveRecord::Base.descendants.select {|x| x.name.match('::')}
相关问答
更多-
在名称空间模型上使用带Rspec的factory_girl_rails(Using factory_girl_rails with Rspec on namespaced models)[2022-05-24]
我在这里有一个最小的工作示例,也许你可以用它来查明你的问题在哪里。 你在dmarkow的回答中留下的评论暗示了你在其他地方有一个错误。 应用程序/模型/酒吧/ foo.rb class Bar::Foo < ActiveRecord::Base end * DB /迁移/ 20110614204536_foo.rb * class Foo < ActiveRecord::Migration def self.up create_table :foos do |t| t.string ... -
如何单元测试命名空间模型(How to Unit Test namespaced models)[2021-10-11]
事实证明它很简单,即使在正常的ActiveSupport / Test::Unit 。 只需复制/test下的模型目录结构: test | +- base_game | | | +- foo_test.rb (defines class BaseGame::FooTest) | +- expansion | +- bar_test.rb (defines class Expansion::BarTest) Turns out it is straight-forward, even un ... -
我们在IRC中解决了这个问题,但核心问题是有一个config.autoload_paths glob集,其中包含models/**作为加载路径。 Rails的自动加载器迭代加载路径,并固定常量名称。 一旦找到存在的文件,它就会尝试加载它,如果该常量不可用则抛出异常。 所以,发生的事情是Rails有一个加载路径列表,如: /models/bar/ /models/ 它正在迭代路径,并在/models/bar/foo.rb找到匹配,然后加载(这使得Bar::Foo可用,但不是Foo ),然后抛出异常,因为Fo ...
-
是的 ,可以使用带有FactoryMuff命名空间模型。 除了在模型中的$factory变量和 FactoryMuff::create()参数中声明完全命名空间的类之外,还必须在关系声明中使用模型的完整命名空间。 例如: public function author() { return $this->hasMany('Project\\Model\\Post'); } 并在相关模型中: public function post() { return $this->belongsTo('P ...
-
rails获取所有命名空间模型(rails get all namespaced models)[2022-08-21]
这将返回一个带有类名称的数组(即字符串): ActiveRecord::Base.descendants.map(&:to_s).select {|x| x.match('::')} 而这将返回实际的类对象: ActiveRecord::Base.descendants.select {|x| x.name.match('::')} This will return an array with the class names (ie. strings): ActiveRecord::Base.desce ... -
Rails 5:查询has_many / belongs_to命名空间模型(Rails 5: query has_many / belongs_to namespaced models)[2023-06-12]
尝试颠倒连接可能 - Media :: Media.joins(:position) Try reversing the join maybe - Media::Media.joins(:positions) -
你有没有问过自己为什么要将模型嵌套? 在我看来,你正试图将名称空间命名为执行逻辑,最好留给关联。 如果您查看ActiveRecord关联文档 ,您会注意到在第一个示例中, Book和Author是顶级模型 - 没有提及Book::Author或类似的东西。 这是你的惯例。 随着您的应用程序变得越来越大,越来越复杂,可能会出现模型命名空间适当的情况(例如,特定于不同用户类型的资源),但我不认为它在这里。 Have you asked yourself why you're nesting your model ...
-
当您查看params哈希时 ,它有knowledgebase_category而不是category 。 因此,请尝试将category_params更改为以下内容 def category_params params.require(:knowledgebase_category).permit(:title) end 一个建议: 始终查看日志中 生成的参数 。 找到大多数错误的解决方案确实很有帮助。 As you look into the params hash, it has knowledg ...
-
要使多态关联起作用,您需要在“belongs_to”另一个模型上添加一个类型列和一个id列。 type列将存储类名,因此不需要在泛型关联中指定。 例如, Comment可以属于Question或Answer 。 让我们称问题和答案“可评论”。 注释应包含以下列:commentable_id和:commentable_type 。 class Comment < ActiveRecord::Base # has columns :commentable_id and :commentable_type ...
-
虽然我无法在Rails 3.2.2中重现这个问题,但我之前遇到过类似的问题。 在开发模式中解决此问题的一般方法是通过ActionDispatch回调。 将其添加到config/environments/development.rb : MyApp::Application.configure do ActionDispatch::Callbacks.before do load Rails.root.join('app', 'models', 'staff.rb') end end 您在该 ...