await each()

in amplify/backend/function/awssyncroutes/src/app.js [259:373]


  await each(
    customRouteTables,
    async (customRouteTable, next) => {
      const customRouteTableRoute = await getRoute(customRouteTable, destinationCidrBlock);

      let snsParams = {
        Subject: (
          `{{status}}: {{action}} '${destinationCidrBlock}' from: '${mainRouteTable.RouteTableId}' ` +
          `to '${customRouteTable.RouteTableId}'`
        ),
        Message: (
          'NOTICE:\r\n' +
          `* Main route table ID: '${mainRouteTable.RouteTableId}'\r\n` +
          `* Custom route table ID: '${customRouteTable.RouteTableId}'\r\n` +
          `* Destination CIDR block: '${destinationCidrBlock}'\r\n`
        ),
        TopicArn: process.env.SNS_TOPIC_ARN
      };

      if (customRouteTableRoute === null) {
        // console.log('Create route in custom route table.');
        const params = {
          RouteTableId: customRouteTable.RouteTableId,
          DestinationCidrBlock: destinationCidrBlock,
          NetworkInterfaceId: mainRouteTableRoute.NetworkInterfaceId,
          DryRun: dryRun,
        };

        snsParams.Subject = snsParams.Subject.replace(/{{action}}/, 'Add');
        snsParams.Message +=
          `* Target ENI: '${mainRouteTableRoute.NetworkInterfaceId}'\r\n` +
          `* Start: ${start.toISOString()}\r\n` +
          `* End: ${new Date().toISOString()}\r\n`;

        await ec2.createRoute(params).promise()
          .then(async () => {
            updatedCustomRouteTableCount++;

            snsParams.Subject = snsParams.Subject
              .replace(/^{{status}}/, 'SUCCESS')
              .substring(0, snsSubjectLengthLimit);

            await sns.publish(snsParams).promise()
              .then(() => { next(); })
              .catch((snsErr) => { next(snsErr); });
          })
          .catch(async (err) => {
            const status = err.code === 'DryRunOperation' ? 'DRYRUN' : 'FAILED';
            snsParams.Subject = snsParams.Subject
              .replace(/^{{status}}/, status)
              .substring(0, snsSubjectLengthLimit);
            snsParams.Message += `\r\n\r\n${err}`;

            await sns.publish(snsParams).promise()
              .then(() => { next(err); })
              .catch((snsErr) => { next(snsErr); });
          });
      } else if (!(customRouteTableRoute.NetworkInterfaceId)) {
        // console.error(
        //   `The route with destination CIDR block: '${destinationCidrBlock}' ` +
        //   `in custom route table: '${customRouteTable.RouteTableId}' does not have an ENI target.`
        // );
        next();
      } else if (customRouteTableRoute.NetworkInterfaceId === mainRouteTableRoute.NetworkInterfaceId) {
        // console.log('Route synchronization not necessary.');
        next();
      } else if (!customRouteTableRoute.NetworkInterfaceId.match(/^eni-[a-f0-9]{8}(?:[a-f0-9]{9})?$/)) {
        // console.error(
        //   `The route with destination CIDR block: '${destinationCidrBlock}' ` +
        //   `in main route table: '${routeTableId}' ` +
        //   `has an unacceptable ENI target: '${networkInterfaceId}'.`
        // );
        next();
      } else {
        // console.log('Update route in custom route table.');
        const params = {
          RouteTableId: customRouteTable.RouteTableId,
          DestinationCidrBlock: destinationCidrBlock,
          NetworkInterfaceId: mainRouteTableRoute.NetworkInterfaceId,
          DryRun: dryRun,
        };

        snsParams.Subject = snsParams.Subject.replace(/{{action}}/, 'Sync');
        snsParams.Message +=
          `* Old target ENI: '${customRouteTableRoute.NetworkInterfaceId}'\r\n` +
          `* New target ENI: '${mainRouteTableRoute.NetworkInterfaceId}'\r\n` +
          `* Start: ${start.toISOString()}\r\n` +
          `* End: ${new Date().toISOString()}\r\n`;

        await ec2.replaceRoute(params).promise()
          .then(async () => {
            updatedCustomRouteTableCount++;

            snsParams.Subject = snsParams.Subject
              .replace(/^{{status}}/, 'SUCCESS')
              .substring(0, snsSubjectLengthLimit);

            await sns.publish(snsParams).promise()
              .then(() => { next(); })
              .catch((snsErr) => { next(snsErr); });
          })
          .catch(async (err) => {
            const status = err.code === 'DryRunOperation' ? 'DRYRUN' : 'FAILED';
            snsParams.Subject = snsParams.Subject
              .replace(/^{{status}}/, status)
              .substring(0, snsSubjectLengthLimit);

            snsParams.Message += `\r\n\r\n${err}`;

            await sns.publish(snsParams).promise()
              .then(() => { next(err); })
              .catch((snsErr) => { next(snsErr); });
          });
      }
    },