You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js箭头函数中基于InstanceId获取EC2实例Platform值

解决AWS Lambda中提取EC2实例Platform字段的问题

问题核心分析

你遇到的问题主要源于两个关键点:

  • 代码存在函数名笔误:定义的实例信息查询函数是InstanceIds,但调用时误用了getInstanceInfo,导致逻辑混乱
  • 对Promise.all返回值结构理解有误:instances是实例对象的数组,不能直接通过instances.platform访问单个实例字段,需遍历数组或通过索引定位

另外要注意:CloudTrail的RunInstances事件响应中已经直接包含platform字段,完全不需要额外调用describeInstances,能大幅减少API调用开销。


方案一:直接从CloudTrail事件提取Platform(推荐)

既然event.detail.responseElements.instancesSet.items里的每个实例对象已经自带platform字段,直接提取即可:

const AWS = require('aws-sdk');

exports.handler = async (event) => {
    var newTags = [];
    newTags.push({ Key: 'Created', Value: event.detail.eventTime });

    if (event.source === 'aws.ec2' && event.detail.eventName === 'RunInstances') {
        // 遍历事件中的每个实例,直接提取platform字段
        await Promise.all(event.detail.responseElements.instancesSet.items.map(async (instanceItem) => {
            const platform = instanceItem.platform;
            // 拼接OS标签到现有标签列表
            const instanceTags = [...newTags, { Key: 'OS', Value: platform }];
            // 调用更新标签函数,传入必要的实例ID和VPC ID
            await ec2Update({ InstanceId: instanceItem.instanceId, VpcId: instanceItem.vpcId }, instanceTags);
        }));
    }
    return "tags have been set!";
};

// 以下保留你原有的ec2Update、getVpc、setTags、InstanceIds函数
var ec2Update = (instance, tags) => new Promise(async (resolve) => {
    var myTags = JSON.parse(JSON.stringify(tags));
    var ignoreKeysLowerCase = ['name','aws:cloudformation:stack-name','aws:cloudformation:stack-id','aws:cloudformation:logical-id'];
    var vpc = await getVpc({ VpcIds: [instance.VpcId] });
    vpc.Tags.map(x => { if (!ignoreKeysLowerCase.includes(x.Key.toLowerCase())) { myTags.push(x) } });
    await setTags(instance.InstanceId, myTags);
    resolve();
});

var InstanceIds = (params) => new Promise((resolve) => {
    var aws = new AWS.EC2({ region: process.env.AWS_REGION }).describeInstances(params);
    aws.on('success', r => {
        resolve(r.data.Reservations[0].Instances[0]);
    }).on('error', e => {
        console.log('error in describeInstances', e.message);
    }).send();
});

var getVpc = (params) => new Promise((resolve) => {
    var aws = new AWS.EC2({ region: process.env.AWS_REGION }).describeVpcs(params);
    aws.on('success', r => {
        resolve(r.data.Vpcs[0])
    }).on('error', e => {
        console.log('error in describeVpcs', e.message);
    }).send();
});

var setTags = (instanceId, tags) => new Promise((resolve) => {
    var params = { Resources: [instanceId], Tags: tags };
    console.log('setting the following tags', params);
    var aws = new AWS.EC2({ region: process.env.AWS_REGION }).createTags(params);
    aws.on('success', r => {
        resolve(r.data);
    }).on('error', e => {
        console.log('error in setTags', e.message);
    }).send();
});

方案二:通过describeInstances获取Platform(如需验证数据)

如果必须调用describeInstances获取最新实例信息,需先修正函数名笔误,同时注意AWS SDK返回的字段是首字母大写的Platform(而非CloudTrail事件里的小写platform):

const AWS = require('aws-sdk');

exports.handler = async (event) => {
    var newTags = [];
    newTags.push({ Key: 'Created', Value: event.detail.eventTime });

    if (event.source === 'aws.ec2' && event.detail.eventName === 'RunInstances') {
        // 修正函数名:将getInstanceInfo改为正确的InstanceIds
        var instances = await Promise.all(event.detail.responseElements.instancesSet.items.map(x => InstanceIds({ InstanceIds: [x.instanceId] })));
        
        await Promise.all(instances.map(instance => {
            // 提取Platform字段,Linux实例可能无该字段,需加默认值
            const platform = instance.Platform || 'linux';
            const instanceTags = [...newTags, { Key: 'OS', Value: platform }];
            return ec2Update(instance, instanceTags);
        }));
    }
    return "tags have been set!";
};

// 以下保留你原有的ec2Update、getVpc、setTags、InstanceIds函数
var ec2Update = (instance, tags) => new Promise(async (resolve) => {
    var myTags = JSON.parse(JSON.stringify(tags));
    var ignoreKeysLowerCase = ['name','aws:cloudformation:stack-name','aws:cloudformation:stack-id','aws:cloudformation:logical-id'];
    var vpc = await getVpc({ VpcIds: [instance.VpcId] });
    vpc.Tags.map(x => { if (!ignoreKeysLowerCase.includes(x.Key.toLowerCase())) { myTags.push(x) } });
    await setTags(instance.InstanceId, myTags);
    resolve();
});

var InstanceIds = (params) => new Promise((resolve) => {
    var aws = new AWS.EC2({ region: process.env.AWS_REGION }).describeInstances(params);
    aws.on('success', r => {
        resolve(r.data.Reservations[0].Instances[0]);
    }).on('error', e => {
        console.log('error in describeInstances', e.message);
    }).send();
});

var getVpc = (params) => new Promise((resolve) => {
    var aws = new AWS.EC2({ region: process.env.AWS_REGION }).describeVpcs(params);
    aws.on('success', r => {
        resolve(r.data.Vpcs[0])
    }).on('error', e => {
        console.log('error in describeVpcs', e.message);
    }).send();
});

var setTags = (instanceId, tags) => new Promise((resolve) => {
    var params = { Resources: [instanceId], Tags: tags };
    console.log('setting the following tags', params);
    var aws = new AWS.EC2({ region: process.env.AWS_REGION }).createTags(params);
    aws.on('success', r => {
        resolve(r.data);
    }).on('error', e => {
        console.log('error in setTags', e.message);
    }).send();
});

关键注意点

  • Linux实例的describeInstances响应通常不会返回Platform字段,需添加默认值避免undefined
  • 确保Lambda执行角色拥有ec2:DescribeInstances和ec2:CreateTags权限

之前尝试失败的原因

  1. 额外传递x.platform给getInstanceInfo:InstanceIds函数仅接收一个参数,多余参数不会被处理,因此无效
  2. 直接读取instances.platform:instances是数组,不是单个实例对象,必须遍历数组或通过索引(如instances[0].Platform)访问
  3. 将x.platform作为InstanceId传入:会导致describeInstances用windows作为实例ID调用,自然触发过滤条件错误

内容的提问来源于stack exchange,提问作者JParrish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:50:43