constructor()

in packages/@aws-cdk/aws-ec2/lib/launch-template.ts [485:653]


  constructor(scope: Construct, id: string, props: LaunchTemplateProps = {}) {
    super(scope, id);

    // Basic validation of the provided spot block duration
    const spotDuration = props?.spotOptions?.blockDuration?.toHours({ integral: true });
    if (spotDuration !== undefined && (spotDuration < 1 || spotDuration > 6)) {
      // See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances
      Annotations.of(this).addError('Spot block duration must be exactly 1, 2, 3, 4, 5, or 6 hours.');
    }

    this.role = props.role;
    this._grantPrincipal = this.role;
    const iamProfile: iam.CfnInstanceProfile | undefined = this.role ? new iam.CfnInstanceProfile(this, 'Profile', {
      roles: [this.role!.roleName],
    }) : undefined;

    if (props.securityGroup) {
      this._connections = new Connections({ securityGroups: [props.securityGroup] });
    }
    const securityGroupsToken = Lazy.list({
      produce: () => {
        if (this._connections && this._connections.securityGroups.length > 0) {
          return this._connections.securityGroups.map(sg => sg.securityGroupId);
        }
        return undefined;
      },
    });

    if (props.userData) {
      this.userData = props.userData;
    }
    const userDataToken = Lazy.string({
      produce: () => {
        if (this.userData) {
          return Fn.base64(this.userData.render());
        }
        return undefined;
      },
    });

    const imageConfig: MachineImageConfig | undefined = props.machineImage?.getImage(this);
    if (imageConfig) {
      this.osType = imageConfig.osType;
    }

    let marketOptions: any = undefined;
    if (props?.spotOptions) {
      marketOptions = {
        marketType: 'spot',
        spotOptions: {
          blockDurationMinutes: spotDuration !== undefined ? spotDuration * 60 : undefined,
          instanceInterruptionBehavior: props.spotOptions.interruptionBehavior,
          maxPrice: props.spotOptions.maxPrice?.toString(),
          spotInstanceType: props.spotOptions.requestType,
          validUntil: props.spotOptions.validUntil?.date.toUTCString(),
        },
      };
      // Remove SpotOptions if there are none.
      if (Object.keys(marketOptions.spotOptions).filter(k => marketOptions.spotOptions[k]).length == 0) {
        marketOptions.spotOptions = undefined;
      }
    }

    this.tags = new TagManager(TagType.KEY_VALUE, 'AWS::EC2::LaunchTemplate');
    const tagsToken = Lazy.any({
      produce: () => {
        if (this.tags.hasTags()) {
          const renderedTags = this.tags.renderTags();
          const lowerCaseRenderedTags = renderedTags.map( (tag: { [key: string]: string}) => {
            return {
              key: tag.Key,
              value: tag.Value,
            };
          });
          return [
            {
              resourceType: 'instance',
              tags: lowerCaseRenderedTags,
            },
            {
              resourceType: 'volume',
              tags: lowerCaseRenderedTags,
            },
          ];
        }
        return undefined;
      },
    });

    const resource = new CfnLaunchTemplate(this, 'Resource', {
      launchTemplateName: props?.launchTemplateName,
      launchTemplateData: {
        blockDeviceMappings: props?.blockDevices !== undefined ? launchTemplateBlockDeviceMappings(this, props.blockDevices) : undefined,
        creditSpecification: props?.cpuCredits !== undefined ? {
          cpuCredits: props.cpuCredits,
        } : undefined,
        disableApiTermination: props?.disableApiTermination,
        ebsOptimized: props?.ebsOptimized,
        enclaveOptions: props?.nitroEnclaveEnabled !== undefined ? {
          enabled: props.nitroEnclaveEnabled,
        } : undefined,
        hibernationOptions: props?.hibernationConfigured !== undefined ? {
          configured: props.hibernationConfigured,
        } : undefined,
        iamInstanceProfile: iamProfile !== undefined ? {
          arn: iamProfile.getAtt('Arn').toString(),
        } : undefined,
        imageId: imageConfig?.imageId,
        instanceType: props?.instanceType?.toString(),
        instanceInitiatedShutdownBehavior: props?.instanceInitiatedShutdownBehavior,
        instanceMarketOptions: marketOptions,
        keyName: props?.keyName,
        monitoring: props?.detailedMonitoring !== undefined ? {
          enabled: props.detailedMonitoring,
        } : undefined,
        securityGroupIds: securityGroupsToken,
        tagSpecifications: tagsToken,
        userData: userDataToken,

        // Fields not yet implemented:
        // ==========================
        // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-capacityreservationspecification.html
        // Will require creating an L2 for AWS::EC2::CapacityReservation
        // capacityReservationSpecification: undefined,

        // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-cpuoptions.html
        // cpuOptions: undefined,

        // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-elasticgpuspecification.html
        // elasticGpuSpecifications: undefined,

        // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata.html#cfn-ec2-launchtemplate-launchtemplatedata-elasticinferenceaccelerators
        // elasticInferenceAccelerators: undefined,

        // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata.html#cfn-ec2-launchtemplate-launchtemplatedata-kernelid
        // kernelId: undefined,
        // ramDiskId: undefined,

        // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata.html#cfn-ec2-launchtemplate-launchtemplatedata-licensespecifications
        // Also not implemented in Instance L2
        // licenseSpecifications: undefined,

        // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata.html#cfn-ec2-launchtemplate-launchtemplatedata-metadataoptions
        // metadataOptions: undefined,

        // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata.html#cfn-ec2-launchtemplate-launchtemplatedata-tagspecifications
        // Should be implemented via the Tagging aspect in CDK core. Complication will be that this tagging interface is very unique to LaunchTemplates.
        // tagSpecification: undefined

        // CDK has no abstraction for Network Interfaces yet.
        // networkInterfaces: undefined,

        // CDK has no abstraction for Placement yet.
        // placement: undefined,

      },
    });

    Tags.of(this).add(NAME_TAG, this.node.path);

    this.defaultVersionNumber = resource.attrDefaultVersionNumber;
    this.latestVersionNumber = resource.attrLatestVersionNumber;
    this.launchTemplateId = resource.ref;
    this.versionNumber = Token.asString(resource.getAtt('LatestVersionNumber'));

    if (props.requireImdsv2) {
      Aspects.of(this).add(new LaunchTemplateRequireImdsv2Aspect());
    }
  }