EC2Amazon-Beispiele SDK für die Verwendung von for JavaScript (v3) - AWS SDKCode-Beispiele

Weitere AWS SDK Beispiele sind im Repo AWS Doc SDK Examples GitHub verfügbar.

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

EC2Amazon-Beispiele SDK für die Verwendung von for JavaScript (v3)

Die folgenden Codebeispiele zeigen Ihnen, wie Sie mithilfe von AWS SDK for JavaScript (v3) mit Amazon Aktionen ausführen und allgemeine Szenarien implementierenEC2.

Basics sind Codebeispiele, die Ihnen zeigen, wie Sie die wesentlichen Operationen innerhalb eines Services ausführen.

Aktionen sind Codeauszüge aus größeren Programmen und müssen im Kontext ausgeführt werden. Aktionen zeigen Ihnen zwar, wie Sie einzelne Servicefunktionen aufrufen, aber Sie können Aktionen im Kontext der zugehörigen Szenarien sehen.

Szenarien sind Codebeispiele, die Ihnen zeigen, wie Sie bestimmte Aufgaben ausführen, indem Sie mehrere Funktionen innerhalb eines Dienstes oder in Kombination mit anderen aufrufen AWS-Services.

Jedes Beispiel enthält einen Link zum vollständigen Quellcode, in dem Sie Anweisungen zum Einrichten und Ausführen des Codes im Kontext finden.

Erste Schritte

Die folgenden Codebeispiele zeigen, wie Sie mit Amazon beginnen könnenEC2.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { DescribeSecurityGroupsCommand, EC2Client } from "@aws-sdk/client-ec2"; // Call DescribeSecurityGroups and display the result. export const main = async () => { const client = new EC2Client(); try { const { SecurityGroups } = await client.send( new DescribeSecurityGroupsCommand({}), ); const securityGroupList = SecurityGroups.slice(0, 9) .map((sg) => ` • ${sg.GroupId}: ${sg.GroupName}`) .join("\n"); console.log( "Hello, Amazon EC2! Let's list up to 10 of your security groups:", ); console.log(securityGroupList); } catch (err) { console.error(err); } }; // Call function if run directly. import { fileURLToPath } from "node:url"; if (process.argv[1] === fileURLToPath(import.meta.url)) { main(); }

Grundlagen

Wie das aussehen kann, sehen Sie am nachfolgenden Beispielcode:

  • Erstellen Sie ein Schlüsselpaar und eine Sicherheitsgruppe.

  • Wählen Sie ein Amazon Machine Image (AMI) und einen kompatiblen Instance-Typ aus und erstellen Sie dann eine Instance.

  • Halten Sie die Instance an und starten Sie sie neu.

  • Verknüpfen einer Elastic-IP-Adresse mit der Instance.

  • Connect zu Ihrer Instance mit her SSH und bereinigen Sie anschließend die Ressourcen.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

Diese Datei enthält eine Liste gängiger Aktionen, die mit verwendet werdenEC2. Die Schritte werden mit einem Szenario-Framework erstellt, das die Ausführung eines interaktiven Beispiels vereinfacht. Den vollständigen Kontext finden Sie im GitHub Repository.

import { tmpdir } from "node:os"; import { writeFile, mkdtemp, rm } from "node:fs/promises"; import { join } from "node:path"; import { get } from "node:http"; import { AllocateAddressCommand, AssociateAddressCommand, AuthorizeSecurityGroupIngressCommand, CreateKeyPairCommand, CreateSecurityGroupCommand, DeleteKeyPairCommand, DeleteSecurityGroupCommand, DisassociateAddressCommand, paginateDescribeImages, paginateDescribeInstances, paginateDescribeInstanceTypes, ReleaseAddressCommand, RunInstancesCommand, StartInstancesCommand, StopInstancesCommand, TerminateInstancesCommand, waitUntilInstanceStatusOk, waitUntilInstanceStopped, waitUntilInstanceTerminated, } from "@aws-sdk/client-ec2"; import { ScenarioAction, ScenarioInput, ScenarioOutput, } from "@aws-doc-sdk-examples/lib/scenario/index.js"; import { paginateGetParametersByPath, SSMClient } from "@aws-sdk/client-ssm"; /** * @typedef {{ * ec2Client: import('@aws-sdk/client-ec2').EC2Client, * errors: Error[], * keyPairId?: string, * tmpDirectory?: string, * securityGroupId?: string, * ipAddress?: string, * images?: import('@aws-sdk/client-ec2').Image[], * image?: import('@aws-sdk/client-ec2').Image, * instanceTypes?: import('@aws-sdk/client-ec2').InstanceTypeInfo[], * instanceId?: string, * instanceIpAddress?: string, * allocationId?: string, * allocatedIpAddress?: string, * associationId?: string, * }} State */ /** * A skip function provided to the `skipWhen` of a Step when you want * to ignore that step if any errors have occurred. * @param {State} state */ const skipWhenErrors = (state) => state.errors.length > 0; const MAX_WAITER_TIME_IN_SECONDS = 60 * 8; export const confirm = new ScenarioInput("confirmContinue", "Continue?", { type: "confirm", skipWhen: skipWhenErrors, }); export const exitOnNoConfirm = new ScenarioAction( "exitOnConfirmContinueFalse", (/** @type { { earlyExit: boolean } & Record<string, any>} */ state) => { if (!state[confirm.name]) { state.earlyExit = true; } }, { skipWhen: skipWhenErrors, }, ); export const greeting = new ScenarioOutput( "greeting", ` Welcome to the Amazon EC2 basic usage scenario. Before you launch an instances, you'll need to provide a few things: - A key pair - This is for SSH access to your EC2 instance. You only need to provide the name. - A security group - This is used for configuring access to your instance. Again, only the name is needed. - An IP address - Your public IP address will be fetched. - An Amazon Machine Image (AMI) - A compatible instance type`, { header: true, preformatted: true, skipWhen: skipWhenErrors }, ); export const provideKeyPairName = new ScenarioInput( "keyPairName", "Provide a name for a new key pair.", { type: "input", default: "ec2-example-key-pair", skipWhen: skipWhenErrors }, ); export const createKeyPair = new ScenarioAction( "createKeyPair", async (/** @type {State} */ state) => { try { // Create a key pair in Amazon EC2. const { KeyMaterial, KeyPairId } = await state.ec2Client.send( // A unique name for the key pair. Up to 255 ASCII characters. new CreateKeyPairCommand({ KeyName: state[provideKeyPairName.name] }), ); state.keyPairId = KeyPairId; // Save the private key in a temporary location. state.tmpDirectory = await mkdtemp(join(tmpdir(), "ec2-scenario-tmp")); await writeFile( `${state.tmpDirectory}/${state[provideKeyPairName.name]}.pem`, KeyMaterial, { mode: 0o400, }, ); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidKeyPair.Duplicate" ) { caught.message = `${caught.message}. Try another key name.`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const logKeyPair = new ScenarioOutput( "logKeyPair", (/** @type {State} */ state) => `Created the key pair ${state[provideKeyPairName.name]}.`, { skipWhen: skipWhenErrors }, ); export const confirmDeleteKeyPair = new ScenarioInput( "confirmDeleteKeyPair", "Do you want to delete the key pair?", { type: "confirm", // Don't do anything when a key pair was never created. skipWhen: (/** @type {State} */ state) => !state.keyPairId, }, ); export const maybeDeleteKeyPair = new ScenarioAction( "deleteKeyPair", async (/** @type {State} */ state) => { try { // Delete a key pair by name from EC2 await state.ec2Client.send( new DeleteKeyPairCommand({ KeyName: state[provideKeyPairName.name] }), ); } catch (caught) { if ( caught instanceof Error && // Occurs when a required parameter (e.g. KeyName) is undefined. caught.name === "MissingParameter" ) { caught.message = `${caught.message}. Did you provide the required value?`; } state.errors.push(caught); } }, { // Don't do anything when there's no key pair to delete or the user chooses // to keep it. skipWhen: (/** @type {State} */ state) => !state.keyPairId || !state[confirmDeleteKeyPair.name], }, ); export const provideSecurityGroupName = new ScenarioInput( "securityGroupName", "Provide a name for a new security group.", { type: "input", default: "ec2-scenario-sg", skipWhen: skipWhenErrors }, ); export const createSecurityGroup = new ScenarioAction( "createSecurityGroup", async (/** @type {State} */ state) => { try { // Create a new security group that will be used to configure ingress/egress for // an EC2 instance. const { GroupId } = await state.ec2Client.send( new CreateSecurityGroupCommand({ GroupName: state[provideSecurityGroupName.name], Description: "A security group for the Amazon EC2 example.", }), ); state.securityGroupId = GroupId; } catch (caught) { if (caught instanceof Error && caught.name === "InvalidGroup.Duplicate") { caught.message = `${caught.message}. Please provide a different name for your security group.`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const logSecurityGroup = new ScenarioOutput( "logSecurityGroup", (/** @type {State} */ state) => `Created the security group ${state.securityGroupId}.`, { skipWhen: skipWhenErrors }, ); export const confirmDeleteSecurityGroup = new ScenarioInput( "confirmDeleteSecurityGroup", "Do you want to delete the security group?", { type: "confirm", // Don't do anything when a security group was never created. skipWhen: (/** @type {State} */ state) => !state.securityGroupId, }, ); export const maybeDeleteSecurityGroup = new ScenarioAction( "deleteSecurityGroup", async (/** @type {State} */ state) => { try { // Delete the security group if the 'skipWhen' condition below is not met. await state.ec2Client.send( new DeleteSecurityGroupCommand({ GroupId: state.securityGroupId, }), ); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidGroupId.Malformed" ) { caught.message = `${caught.message}. Please provide a valid GroupId.`; } state.errors.push(caught); } }, { // Don't do anything when there's no security group to delete // or the user chooses to keep it. skipWhen: (/** @type {State} */ state) => !state.securityGroupId || !state[confirmDeleteSecurityGroup.name], }, ); export const authorizeSecurityGroupIngress = new ScenarioAction( "authorizeSecurity", async (/** @type {State} */ state) => { try { // Get the public IP address of the machine running this example. const ipAddress = await new Promise((res, rej) => { get("http://checkip.amazonaws.com", (response) => { let data = ""; response.on("data", (chunk) => { data += chunk; }); response.on("end", () => res(data.trim())); }).on("error", (err) => { rej(err); }); }); state.ipAddress = ipAddress; // Allow ingress from the IP address above to the security group. // This will allow you to SSH into the EC2 instance. const command = new AuthorizeSecurityGroupIngressCommand({ GroupId: state.securityGroupId, IpPermissions: [ { IpProtocol: "tcp", FromPort: 22, ToPort: 22, IpRanges: [{ CidrIp: `${ipAddress}/32` }], }, ], }); await state.ec2Client.send(command); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidGroupId.Malformed" ) { caught.message = `${caught.message}. Please provide a valid GroupId.`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const logSecurityGroupIngress = new ScenarioOutput( "logSecurityGroupIngress", (/** @type {State} */ state) => `Allowed SSH access from your public IP: ${state.ipAddress}.`, { skipWhen: skipWhenErrors }, ); export const getImages = new ScenarioAction( "images", async (/** @type {State} */ state) => { const AMIs = []; // Some AWS services publish information about common artifacts as AWS Systems Manager (SSM) // public parameters. For example, the Amazon Elastic Compute Cloud (Amazon EC2) // service publishes information about Amazon Machine Images (AMIs) as public parameters. // Create the paginator for getting images. Actions that return multiple pages of // results have paginators to simplify those calls. const getParametersByPathPaginator = paginateGetParametersByPath( { // Not storing this client in state since it's only used once. client: new SSMClient({}), }, { // The path to the public list of the latest amazon-linux instances. Path: "/aws/service/ami-amazon-linux-latest", }, ); try { for await (const page of getParametersByPathPaginator) { for (const param of page.Parameters) { // Filter by Amazon Linux 2 if (param.Name.includes("amzn2")) { AMIs.push(param.Value); } } } } catch (caught) { if (caught instanceof Error && caught.name === "InvalidFilterValue") { caught.message = `${caught.message} Please provide a valid filter value for paginateGetParametersByPath.`; } state.errors.push(caught); return; } const imageDetails = []; const describeImagesPaginator = paginateDescribeImages( { client: state.ec2Client }, // The images found from the call to SSM. { ImageIds: AMIs }, ); try { // Get more details for the images found above. for await (const page of describeImagesPaginator) { imageDetails.push(...(page.Images || [])); } // Store the image details for later use. state.images = imageDetails; } catch (caught) { if (caught instanceof Error && caught.name === "InvalidAMIID.NotFound") { caught.message = `${caught.message}. Please provide a valid image id.`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const provideImage = new ScenarioInput( "image", "Select one of the following images.", { type: "select", choices: (/** @type { State } */ state) => state.images.map((image) => ({ name: `${image.Description}`, value: image, })), default: (/** @type { State } */ state) => state.images[0], skipWhen: skipWhenErrors, }, ); export const getCompatibleInstanceTypes = new ScenarioAction( "getCompatibleInstanceTypes", async (/** @type {State} */ state) => { // Get more details about instance types that match the architecture of // the provided image. const paginator = paginateDescribeInstanceTypes( { client: state.ec2Client, pageSize: 25 }, { Filters: [ { Name: "processor-info.supported-architecture", // The value selected from provideImage() Values: [state.image.Architecture], }, // Filter for smaller, less expensive, types. { Name: "instance-type", Values: ["*.micro", "*.small"] }, ], }, ); const instanceTypes = []; try { for await (const page of paginator) { if (page.InstanceTypes.length) { instanceTypes.push(...(page.InstanceTypes || [])); } } if (!instanceTypes.length) { state.errors.push( "No instance types matched the instance type filters.", ); } } catch (caught) { if (caught instanceof Error && caught.name === "InvalidParameterValue") { caught.message = `${caught.message}. Please check the provided values and try again.`; } state.errors.push(caught); } state.instanceTypes = instanceTypes; }, { skipWhen: skipWhenErrors }, ); export const provideInstanceType = new ScenarioInput( "instanceType", "Select an instance type.", { choices: (/** @type {State} */ state) => state.instanceTypes.map((instanceType) => ({ name: `${instanceType.InstanceType} - Memory:${instanceType.MemoryInfo.SizeInMiB}`, value: instanceType.InstanceType, })), type: "select", default: (/** @type {State} */ state) => state.instanceTypes[0].InstanceType, skipWhen: skipWhenErrors, }, ); export const runInstance = new ScenarioAction( "runInstance", async (/** @type { State } */ state) => { const { Instances } = await state.ec2Client.send( new RunInstancesCommand({ KeyName: state[provideKeyPairName.name], SecurityGroupIds: [state.securityGroupId], ImageId: state.image.ImageId, InstanceType: state[provideInstanceType.name], // Availability Zones have capacity limitations that may impact your ability to launch instances. // The `RunInstances` operation will only succeed if it can allocate at least the `MinCount` of instances. // However, EC2 will attempt to launch up to the `MaxCount` of instances, even if the full request cannot be satisfied. // If you need a specific number of instances, use `MinCount` and `MaxCount` set to the same value. // If you want to launch up to a certain number of instances, use `MaxCount` and let EC2 provision as many as possible. // If you require a minimum number of instances, but do not want to exceed a maximum, use both `MinCount` and `MaxCount`. MinCount: 1, MaxCount: 1, }), ); state.instanceId = Instances[0].InstanceId; try { // Poll `DescribeInstanceStatus` until status is "ok". await waitUntilInstanceStatusOk( { client: state.ec2Client, maxWaitTime: MAX_WAITER_TIME_IN_SECONDS, }, { InstanceIds: [Instances[0].InstanceId] }, ); } catch (caught) { if (caught instanceof Error && caught.name === "TimeoutError") { caught.message = `${caught.message}. Try increasing the maxWaitTime in the waiter.`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const logRunInstance = new ScenarioOutput( "logRunInstance", "The next step is to run your EC2 instance for the first time. This can take a few minutes.", { header: true, skipWhen: skipWhenErrors }, ); export const describeInstance = new ScenarioAction( "describeInstance", async (/** @type { State } */ state) => { /** @type { import("@aws-sdk/client-ec2").Instance[] } */ const instances = []; try { const paginator = paginateDescribeInstances( { client: state.ec2Client, }, { // Only get our created instance. InstanceIds: [state.instanceId], }, ); for await (const page of paginator) { for (const reservation of page.Reservations) { instances.push(...reservation.Instances); } } if (instances.length !== 1) { throw new Error(`Instance ${state.instanceId} not found.`); } // The only info we need is the IP address for SSH purposes. state.instanceIpAddress = instances[0].PublicIpAddress; } catch (caught) { if (caught instanceof Error && caught.name === "InvalidParameterValue") { caught.message = `${caught.message}. Please check provided values and try again.`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const logSSHConnectionInfo = new ScenarioOutput( "logSSHConnectionInfo", (/** @type { State } */ state) => `You can now SSH into your instance using the following command: ssh -i ${state.tmpDirectory}/${state[provideKeyPairName.name]}.pem ec2-user@${state.instanceIpAddress}`, { preformatted: true, skipWhen: skipWhenErrors }, ); export const logStopInstance = new ScenarioOutput( "logStopInstance", "Stopping your EC2 instance.", { skipWhen: skipWhenErrors }, ); export const stopInstance = new ScenarioAction( "stopInstance", async (/** @type { State } */ state) => { try { await state.ec2Client.send( new StopInstancesCommand({ InstanceIds: [state.instanceId], }), ); await waitUntilInstanceStopped( { client: state.ec2Client, maxWaitTime: MAX_WAITER_TIME_IN_SECONDS, }, { InstanceIds: [state.instanceId] }, ); } catch (caught) { if (caught instanceof Error && caught.name === "TimeoutError") { caught.message = `${caught.message}. Try increasing the maxWaitTime in the waiter.`; } state.errors.push(caught); } }, // Don't try to stop an instance that doesn't exist. { skipWhen: (/** @type { State } */ state) => !state.instanceId }, ); export const logIpAddressBehavior = new ScenarioOutput( "logIpAddressBehavior", [ "When you run an instance, by default it's assigned an IP address.", "That IP address is not static. It will change every time the instance is restarted.", "The next step is to stop and restart your instance to demonstrate this behavior.", ].join(" "), { header: true, skipWhen: skipWhenErrors }, ); export const logStartInstance = new ScenarioOutput( "logStartInstance", (/** @type { State } */ state) => `Starting instance ${state.instanceId}`, { skipWhen: skipWhenErrors }, ); export const startInstance = new ScenarioAction( "startInstance", async (/** @type { State } */ state) => { try { await state.ec2Client.send( new StartInstancesCommand({ InstanceIds: [state.instanceId], }), ); await waitUntilInstanceStatusOk( { client: state.ec2Client, maxWaitTime: MAX_WAITER_TIME_IN_SECONDS, }, { InstanceIds: [state.instanceId] }, ); } catch (caught) { if (caught instanceof Error && caught.name === "TimeoutError") { caught.message = `${caught.message}. Try increasing the maxWaitTime in the waiter.`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const logIpAllocation = new ScenarioOutput( "logIpAllocation", [ "It is possible to have a static IP address.", "To demonstrate this, an IP will be allocated and associated to your EC2 instance.", ].join(" "), { header: true, skipWhen: skipWhenErrors }, ); export const allocateIp = new ScenarioAction( "allocateIp", async (/** @type { State } */ state) => { try { // An Elastic IP address is allocated to your AWS account, and is yours until you release it. const { AllocationId, PublicIp } = await state.ec2Client.send( new AllocateAddressCommand({}), ); state.allocationId = AllocationId; state.allocatedIpAddress = PublicIp; } catch (caught) { if (caught instanceof Error && caught.name === "MissingParameter") { caught.message = `${caught.message}. Did you provide these values?`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const associateIp = new ScenarioAction( "associateIp", async (/** @type { State } */ state) => { try { // Associate an allocated IP address to an EC2 instance. An IP address can be allocated // with the AllocateAddress action. const { AssociationId } = await state.ec2Client.send( new AssociateAddressCommand({ AllocationId: state.allocationId, InstanceId: state.instanceId, }), ); state.associationId = AssociationId; // Update the IP address that is being tracked to match // the one just associated. state.instanceIpAddress = state.allocatedIpAddress; } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidAllocationID.NotFound" ) { caught.message = `${caught.message}. Did you provide the ID of a valid Elastic IP address AllocationId?`; } state.errors.push(caught); } }, { skipWhen: skipWhenErrors }, ); export const logStaticIpProof = new ScenarioOutput( "logStaticIpProof", "The IP address should remain the same even after stopping and starting the instance.", { header: true, skipWhen: skipWhenErrors }, ); export const logCleanUp = new ScenarioOutput( "logCleanUp", "That's it! You can choose to clean up the resources now, or clean them up on your own later.", { header: true, skipWhen: skipWhenErrors }, ); export const confirmDisassociateAddress = new ScenarioInput( "confirmDisassociateAddress", "Do you want to disassociate and release the static IP address created earlier?", { type: "confirm", skipWhen: (/** @type { State } */ state) => !state.associationId, }, ); export const maybeDisassociateAddress = new ScenarioAction( "maybeDisassociateAddress", async (/** @type { State } */ state) => { try { await state.ec2Client.send( new DisassociateAddressCommand({ AssociationId: state.associationId, }), ); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidAssociationID.NotFound" ) { caught.message = `${caught.message}. Please provide a valid association ID.`; } state.errors.push(caught); } }, { skipWhen: (/** @type { State } */ state) => !state[confirmDisassociateAddress.name] || !state.associationId, }, ); export const maybeReleaseAddress = new ScenarioAction( "maybeReleaseAddress", async (/** @type { State } */ state) => { try { await state.ec2Client.send( new ReleaseAddressCommand({ AllocationId: state.allocationId, }), ); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidAllocationID.NotFound" ) { caught.message = `${caught.message}. Please provide a valid AllocationID.`; } state.errors.push(caught); } }, { skipWhen: (/** @type { State } */ state) => !state[confirmDisassociateAddress.name] || !state.allocationId, }, ); export const confirmTerminateInstance = new ScenarioInput( "confirmTerminateInstance", "Do you want to terminate the instance?", // Don't do anything when an instance was never run. { skipWhen: (/** @type { State } */ state) => !state.instanceId, type: "confirm", }, ); export const maybeTerminateInstance = new ScenarioAction( "terminateInstance", async (/** @type { State } */ state) => { try { await state.ec2Client.send( new TerminateInstancesCommand({ InstanceIds: [state.instanceId], }), ); await waitUntilInstanceTerminated( { client: state.ec2Client }, { InstanceIds: [state.instanceId] }, ); } catch (caught) { if (caught instanceof Error && caught.name === "TimeoutError") { caught.message = `${caught.message}. Try increasing the maxWaitTime in the waiter.`; } state.errors.push(caught); } }, { // Don't do anything when there's no instance to terminate or the // use chooses not to terminate. skipWhen: (/** @type { State } */ state) => !state.instanceId || !state[confirmTerminateInstance.name], }, ); export const deleteTemporaryDirectory = new ScenarioAction( "deleteTemporaryDirectory", async (/** @type { State } */ state) => { try { await rm(state.tmpDirectory, { recursive: true }); } catch (caught) { state.errors.push(caught); } }, ); export const logErrors = new ScenarioOutput( "logErrors", (/** @type {State}*/ state) => { const errorList = state.errors .map((err) => ` - ${err.name}: ${err.message}`) .join("\n"); return `Scenario errors found:\n${errorList}`; }, { preformatted: true, header: true, // Don't log errors when there aren't any! skipWhen: (/** @type {State} */ state) => state.errors.length === 0, }, );

Aktionen

Das folgende Codebeispiel zeigt die VerwendungAllocateAddress.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { AllocateAddressCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Allocates an Elastic IP address to your AWS account. */ export const main = async () => { const client = new EC2Client({}); const command = new AllocateAddressCommand({}); try { const { AllocationId, PublicIp } = await client.send(command); console.log("A new IP address has been allocated to your account:"); console.log(`ID: ${AllocationId} Public IP: ${PublicIp}`); console.log( "You can view your IP addresses in the AWS Management Console for Amazon EC2. Look under Network & Security > Elastic IPs", ); } catch (caught) { if (caught instanceof Error && caught.name === "MissingParameter") { console.warn(`${caught.message}. Did you provide these values?`); } else { throw caught; } } }; import { fileURLToPath } from "node:url"; // Call function if run directly. if (process.argv[1] === fileURLToPath(import.meta.url)) { main(); }
  • APIEinzelheiten finden Sie AllocateAddressunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungAssociateAddress.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { AssociateAddressCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Associates an Elastic IP address, or carrier IP address (for instances that are in subnets in Wavelength Zones) * with an instance or a network interface. * @param {{ instanceId: string, allocationId: string }} options */ export const main = async ({ instanceId, allocationId }) => { const client = new EC2Client({}); const command = new AssociateAddressCommand({ // You need to allocate an Elastic IP address before associating it with an instance. // You can do that with the AllocateAddressCommand. AllocationId: allocationId, // You need to create an EC2 instance before an IP address can be associated with it. // You can do that with the RunInstancesCommand. InstanceId: instanceId, }); try { const { AssociationId } = await client.send(command); console.log( `Address with allocation ID ${allocationId} is now associated with instance ${instanceId}.`, `The association ID is ${AssociationId}.`, ); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidAllocationID.NotFound" ) { console.warn( `${caught.message}. Did you provide the ID of a valid Elastic IP address AllocationId?`, ); } else { throw caught; } } };
  • APIEinzelheiten finden Sie AssociateAddressunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungAuthorizeSecurityGroupIngress.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { AuthorizeSecurityGroupIngressCommand, EC2Client, } from "@aws-sdk/client-ec2"; /** * Adds the specified inbound (ingress) rules to a security group. * @param {{ groupId: string, ipAddress: string }} options */ export const main = async ({ groupId, ipAddress }) => { const client = new EC2Client({}); const command = new AuthorizeSecurityGroupIngressCommand({ // Use a group ID from the AWS console or // the DescribeSecurityGroupsCommand. GroupId: groupId, IpPermissions: [ { IpProtocol: "tcp", FromPort: 22, ToPort: 22, // The IP address to authorize. // For more information on this notation, see // https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation IpRanges: [{ CidrIp: `${ipAddress}/32` }], }, ], }); try { const { SecurityGroupRules } = await client.send(command); console.log(JSON.stringify(SecurityGroupRules, null, 2)); } catch (caught) { if (caught instanceof Error && caught.name === "InvalidGroupId.Malformed") { console.warn(`${caught.message}. Please provide a valid GroupId.`); } else { throw caught; } } };

Das folgende Codebeispiel zeigt die VerwendungCreateKeyPair.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { CreateKeyPairCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Creates an ED25519 or 2048-bit RSA key pair with the specified name and in the specified PEM or PPK format. * Amazon EC2 stores the public key and displays the private key for you to save to a file. * @param {{ keyName: string }} options */ export const main = async ({ keyName }) => { const client = new EC2Client({}); const command = new CreateKeyPairCommand({ KeyName: keyName, }); try { const { KeyMaterial, KeyName } = await client.send(command); console.log(KeyName); console.log(KeyMaterial); } catch (caught) { if (caught instanceof Error && caught.name === "InvalidKeyPair.Duplicate") { console.warn(`${caught.message}. Try another key name.`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie CreateKeyPairunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungCreateLaunchTemplate.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

const ssmClient = new SSMClient({}); const { Parameter } = await ssmClient.send( new GetParameterCommand({ Name: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2", }), ); const ec2Client = new EC2Client({}); await ec2Client.send( new CreateLaunchTemplateCommand({ LaunchTemplateName: NAMES.launchTemplateName, LaunchTemplateData: { InstanceType: "t3.micro", ImageId: Parameter.Value, IamInstanceProfile: { Name: NAMES.instanceProfileName }, UserData: readFileSync( join(RESOURCES_PATH, "server_startup_script.sh"), ).toString("base64"), KeyName: NAMES.keyPairName, }, }),

Das folgende Codebeispiel zeigt die VerwendungCreateSecurityGroup.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { CreateSecurityGroupCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Creates a security group. * @param {{ groupName: string, description: string }} options */ export const main = async ({ groupName, description }) => { const client = new EC2Client({}); const command = new CreateSecurityGroupCommand({ // Up to 255 characters in length. Cannot start with sg-. GroupName: groupName, // Up to 255 characters in length. Description: description, }); try { const { GroupId } = await client.send(command); console.log(GroupId); } catch (caught) { if (caught instanceof Error && caught.name === "InvalidParameterValue") { console.warn(`${caught.message}.`); } else { throw caught; } } };

Das folgende Codebeispiel zeigt die VerwendungDeleteKeyPair.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { DeleteKeyPairCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Deletes the specified key pair, by removing the public key from Amazon EC2. * @param {{ keyName: string }} options */ export const main = async ({ keyName }) => { const client = new EC2Client({}); const command = new DeleteKeyPairCommand({ KeyName: keyName, }); try { await client.send(command); console.log("Successfully deleted key pair."); } catch (caught) { if (caught instanceof Error && caught.name === "MissingParameter") { console.warn(`${caught.message}. Did you provide the required value?`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie DeleteKeyPairunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungDeleteLaunchTemplate.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

await client.send( new DeleteLaunchTemplateCommand({ LaunchTemplateName: NAMES.launchTemplateName, }), );

Das folgende Codebeispiel zeigt die VerwendungDeleteSecurityGroup.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { DeleteSecurityGroupCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Deletes a security group. * @param {{ groupId: string }} options */ export const main = async ({ groupId }) => { const client = new EC2Client({}); const command = new DeleteSecurityGroupCommand({ GroupId: groupId, }); try { await client.send(command); console.log("Security group deleted successfully."); } catch (caught) { if (caught instanceof Error && caught.name === "InvalidGroupId.Malformed") { console.warn(`${caught.message}. Please provide a valid GroupId.`); } else { throw caught; } } };

Das folgende Codebeispiel zeigt die VerwendungDescribeAddresses.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { DescribeAddressesCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Describes the specified Elastic IP addresses or all of your Elastic IP addresses. * @param {{ allocationId: string }} options */ export const main = async ({ allocationId }) => { const client = new EC2Client({}); const command = new DescribeAddressesCommand({ // You can omit this property to show all addresses. AllocationIds: [allocationId], }); try { const { Addresses } = await client.send(command); const addressList = Addresses.map((address) => ` • ${address.PublicIp}`); console.log("Elastic IP addresses:"); console.log(addressList.join("\n")); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidAllocationID.NotFound" ) { console.warn(`${caught.message}. Please provide a valid AllocationId.`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie DescribeAddressesunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungDescribeIamInstanceProfileAssociations.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

const ec2Client = new EC2Client({}); const { IamInstanceProfileAssociations } = await ec2Client.send( new DescribeIamInstanceProfileAssociationsCommand({ Filters: [ { Name: "instance-id", Values: [state.targetInstance.InstanceId] }, ], }), );

Das folgende Codebeispiel zeigt die VerwendungDescribeImages.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, paginateDescribeImages } from "@aws-sdk/client-ec2"; /** * Describes the specified images (AMIs, AKIs, and ARIs) available to you or all of the images available to you. * @param {{ architecture: string, pageSize: number }} options */ export const main = async ({ architecture, pageSize }) => { pageSize = Number.parseInt(pageSize); const client = new EC2Client({}); // The paginate function is a wrapper around the base command. const paginator = paginateDescribeImages( // Without limiting the page size, this call can take a long time. pageSize is just sugar for // the MaxResults property in the base command. { client, pageSize }, { // There are almost 70,000 images available. Be specific with your filtering // to increase efficiency. // See https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-ec2/interfaces/describeimagescommandinput.html#filters Filters: [{ Name: "architecture", Values: [architecture] }], }, ); /** * @type {import('@aws-sdk/client-ec2').Image[]} */ const images = []; let recordsScanned = 0; try { for await (const page of paginator) { recordsScanned += pageSize; if (page.Images.length) { images.push(...page.Images); break; } console.log( `No matching image found yet. Searched ${recordsScanned} records.`, ); } if (images.length) { console.log( `Found ${images.length} images:\n\n${images.map((image) => image.Name).join("\n")}\n`, ); } else { console.log( `No matching images found. Searched ${recordsScanned} records.\n`, ); } return images; } catch (caught) { if (caught instanceof Error && caught.name === "InvalidParameterValue") { console.warn(`${caught.message}`); return []; } throw caught; } };
  • APIEinzelheiten finden Sie DescribeImagesunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungDescribeInstanceTypes.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, paginateDescribeInstanceTypes } from "@aws-sdk/client-ec2"; /** * Describes the specified instance types. By default, all instance types for the * current Region are described. Alternatively, you can filter the results. * @param {{ pageSize: string, supportedArch: string[], freeTier: boolean }} options */ export const main = async ({ pageSize, supportedArch, freeTier }) => { pageSize = Number.parseInt(pageSize); const client = new EC2Client({}); // The paginate function is a wrapper around the underlying command. const paginator = paginateDescribeInstanceTypes( // Without limiting the page size, this call can take a long time. pageSize is just sugar for // the MaxResults property in the underlying command. { client, pageSize }, { Filters: [ { Name: "processor-info.supported-architecture", Values: supportedArch, }, { Name: "free-tier-eligible", Values: [freeTier ? "true" : "false"] }, ], }, ); try { /** * @type {import('@aws-sdk/client-ec2').InstanceTypeInfo[]} */ const instanceTypes = []; for await (const page of paginator) { if (page.InstanceTypes.length) { instanceTypes.push(...page.InstanceTypes); // When we have at least 1 result, we can stop. if (instanceTypes.length >= 1) { break; } } } console.log( `Memory size in MiB for matching instance types:\n\n${instanceTypes.map((it) => `${it.InstanceType}: ${it.MemoryInfo.SizeInMiB} MiB`).join("\n")}`, ); } catch (caught) { if (caught instanceof Error && caught.name === "InvalidParameterValue") { console.warn(`${caught.message}`); return []; } throw caught; } };

Das folgende Codebeispiel zeigt die VerwendungDescribeInstances.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, paginateDescribeInstances } from "@aws-sdk/client-ec2"; /** * List all of your EC2 instances running with the provided architecture that * were launched in the past month. * @param {{ pageSize: string, architectures: string[] }} options */ export const main = async ({ pageSize, architectures }) => { pageSize = Number.parseInt(pageSize); const client = new EC2Client({}); const d = new Date(); const year = d.getFullYear(); const month = `0${d.getMonth() + 1}`.slice(-2); const launchTimePattern = `${year}-${month}-*`; const paginator = paginateDescribeInstances( { client, pageSize, }, { Filters: [ { Name: "architecture", Values: architectures }, { Name: "instance-state-name", Values: ["running"] }, { Name: "launch-time", Values: [launchTimePattern], }, ], }, ); try { /** * @type {import('@aws-sdk/client-ec2').Instance[]} */ const instanceList = []; for await (const page of paginator) { const { Reservations } = page; for (const reservation of Reservations) { instanceList.push(...reservation.Instances); } } console.log( `Running instances launched this month:\n\n${instanceList.map((instance) => instance.InstanceId).join("\n")}`, ); } catch (caught) { if (caught instanceof Error && caught.name === "InvalidParameterValue") { console.warn(`${caught.message}.`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie DescribeInstancesunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungDescribeKeyPairs.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { DescribeKeyPairsCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * List all key pairs in the current AWS account. * @param {{ dryRun: boolean }} */ export const main = async ({ dryRun }) => { const client = new EC2Client({}); const command = new DescribeKeyPairsCommand({ DryRun: dryRun }); try { const { KeyPairs } = await client.send(command); const keyPairList = KeyPairs.map( (kp) => ` • ${kp.KeyPairId}: ${kp.KeyName}`, ).join("\n"); console.log("The following key pairs were found in your account:"); console.log(keyPairList); } catch (caught) { if (caught instanceof Error && caught.name === "DryRunOperation") { console.log(`${caught.message}`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie DescribeKeyPairsunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungDescribeRegions.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { DescribeRegionsCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * List all available AWS regions. * @param {{ regionNames: string[], includeOptInRegions: boolean }} options */ export const main = async ({ regionNames, includeOptInRegions }) => { const client = new EC2Client({}); const command = new DescribeRegionsCommand({ // By default this command will not show regions that require you to opt-in. // When AllRegions is true, even the regions that require opt-in will be returned. AllRegions: includeOptInRegions, // You can omit the Filters property if you want to get all regions. Filters: regionNames?.length ? [ { Name: "region-name", // You can specify multiple values for a filter. // You can also use '*' as a wildcard. This will return all // of the regions that start with `us-east-`. Values: regionNames, }, ] : undefined, }); try { const { Regions } = await client.send(command); const regionsList = Regions.map((reg) => ` • ${reg.RegionName}`); console.log("Found regions:"); console.log(regionsList.join("\n")); } catch (caught) { if (caught instanceof Error && caught.name === "DryRunOperation") { console.log(`${caught.message}`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie DescribeRegionsunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungDescribeSecurityGroups.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { DescribeSecurityGroupsCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Describes the specified security groups or all of your security groups. * @param {{ groupIds: string[] }} options */ export const main = async ({ groupIds = [] }) => { const client = new EC2Client({}); const command = new DescribeSecurityGroupsCommand({ GroupIds: groupIds, }); try { const { SecurityGroups } = await client.send(command); const sgList = SecurityGroups.map( (sg) => `• ${sg.GroupName} (${sg.GroupId}): ${sg.Description}`, ).join("\n"); if (sgList.length) { console.log(`Security groups:\n${sgList}`); } else { console.log("No security groups found."); } } catch (caught) { if (caught instanceof Error && caught.name === "InvalidGroupId.Malformed") { console.warn(`${caught.message}. Please provide a valid GroupId.`); } else if ( caught instanceof Error && caught.name === "InvalidGroup.NotFound" ) { console.warn(caught.message); } else { throw caught; } } };

Das folgende Codebeispiel zeigt die VerwendungDescribeSubnets.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

const client = new EC2Client({}); const { Subnets } = await client.send( new DescribeSubnetsCommand({ Filters: [ { Name: "vpc-id", Values: [state.defaultVpc] }, { Name: "availability-zone", Values: state.availabilityZoneNames }, { Name: "default-for-az", Values: ["true"] }, ], }), );
  • APIEinzelheiten finden Sie DescribeSubnetsunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungDescribeVpcs.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

const client = new EC2Client({}); const { Vpcs } = await client.send( new DescribeVpcsCommand({ Filters: [{ Name: "is-default", Values: ["true"] }], }), );
  • APIEinzelheiten finden Sie DescribeVpcsunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungDisassociateAddress.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { DisassociateAddressCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Disassociate an Elastic IP address from an instance. * @param {{ associationId: string }} options */ export const main = async ({ associationId }) => { const client = new EC2Client({}); const command = new DisassociateAddressCommand({ // You can also use PublicIp, but that is for EC2 classic which is being retired. AssociationId: associationId, }); try { await client.send(command); console.log("Successfully disassociated address"); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidAssociationID.NotFound" ) { console.warn(`${caught.message}.`); } else { throw caught; } } };

Das folgende Codebeispiel zeigt die VerwendungMonitorInstances.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, MonitorInstancesCommand } from "@aws-sdk/client-ec2"; /** * Turn on detailed monitoring for the selected instance. * By default, metrics are sent to Amazon CloudWatch every 5 minutes. * For a cost you can enable detailed monitoring which sends metrics every minute. * @param {{ instanceIds: string[] }} options */ export const main = async ({ instanceIds }) => { const client = new EC2Client({}); const command = new MonitorInstancesCommand({ InstanceIds: instanceIds, }); try { const { InstanceMonitorings } = await client.send(command); const instancesBeingMonitored = InstanceMonitorings.map( (im) => ` • Detailed monitoring state for ${im.InstanceId} is ${im.Monitoring.State}.`, ); console.log("Monitoring status:"); console.log(instancesBeingMonitored.join("\n")); } catch (caught) { if (caught instanceof Error && caught.name === "InvalidParameterValue") { console.warn(`${caught.message}`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie MonitorInstancesunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungRebootInstances.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, RebootInstancesCommand } from "@aws-sdk/client-ec2"; /** * Requests a reboot of the specified instances. This operation is asynchronous; * it only queues a request to reboot the specified instances. * @param {{ instanceIds: string[] }} options */ export const main = async ({ instanceIds }) => { const client = new EC2Client({}); const command = new RebootInstancesCommand({ InstanceIds: instanceIds, }); try { await client.send(command); console.log("Instance rebooted successfully."); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidInstanceID.NotFound" ) { console.warn( `${caught.message}. Please provide the InstanceId of a valid instance to reboot.`, ); } else { throw caught; } } };
  • APIEinzelheiten finden Sie RebootInstancesunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungReleaseAddress.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { ReleaseAddressCommand, EC2Client } from "@aws-sdk/client-ec2"; /** * Release an Elastic IP address. * @param {{ allocationId: string }} options */ export const main = async ({ allocationId }) => { const client = new EC2Client({}); const command = new ReleaseAddressCommand({ // You can also use PublicIp, but that is for EC2 classic which is being retired. AllocationId: allocationId, }); try { await client.send(command); console.log("Successfully released address."); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidAllocationID.NotFound" ) { console.warn(`${caught.message}. Please provide a valid AllocationID.`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie ReleaseAddressunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungReplaceIamInstanceProfileAssociation.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

await retry({ intervalInMs: 1000, maxRetries: 30 }, () => ec2Client.send( new ReplaceIamInstanceProfileAssociationCommand({ AssociationId: state.instanceProfileAssociationId, IamInstanceProfile: { Name: NAMES.ssmOnlyInstanceProfileName }, }), ), );

Das folgende Codebeispiel zeigt die VerwendungRunInstances.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, RunInstancesCommand } from "@aws-sdk/client-ec2"; /** * Create new EC2 instances. * @param {{ * keyName: string, * securityGroupIds: string[], * imageId: string, * instanceType: import('@aws-sdk/client-ec2')._InstanceType, * minCount?: number, * maxCount?: number }} options */ export const main = async ({ keyName, securityGroupIds, imageId, instanceType, minCount = "1", maxCount = "1", }) => { const client = new EC2Client({}); minCount = Number.parseInt(minCount); maxCount = Number.parseInt(maxCount); const command = new RunInstancesCommand({ // Your key pair name. KeyName: keyName, // Your security group. SecurityGroupIds: securityGroupIds, // An Amazon Machine Image (AMI). There are multiple ways to search for AMIs. For more information, see: // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html ImageId: imageId, // An instance type describing the resources provided to your instance. There are multiple // ways to search for instance types. For more information see: // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-discovery.html InstanceType: instanceType, // Availability Zones have capacity limitations that may impact your ability to launch instances. // The `RunInstances` operation will only succeed if it can allocate at least the `MinCount` of instances. // However, EC2 will attempt to launch up to the `MaxCount` of instances, even if the full request cannot be satisfied. // If you need a specific number of instances, use `MinCount` and `MaxCount` set to the same value. // If you want to launch up to a certain number of instances, use `MaxCount` and let EC2 provision as many as possible. // If you require a minimum number of instances, but do not want to exceed a maximum, use both `MinCount` and `MaxCount`. MinCount: minCount, MaxCount: maxCount, }); try { const { Instances } = await client.send(command); const instanceList = Instances.map( (instance) => `• ${instance.InstanceId}`, ).join("\n"); console.log(`Launched instances:\n${instanceList}`); } catch (caught) { if (caught instanceof Error && caught.name === "ResourceCountExceeded") { console.warn(`${caught.message}`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie RunInstancesunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungStartInstances.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, StartInstancesCommand } from "@aws-sdk/client-ec2"; import { fileURLToPath } from "node:url"; import { parseArgs } from "node:util"; /** * Starts an Amazon EBS-backed instance that you've previously stopped. * @param {{ instanceIds }} options */ export const main = async ({ instanceIds }) => { const client = new EC2Client({}); const command = new StartInstancesCommand({ InstanceIds: instanceIds, }); try { const { StartingInstances } = await client.send(command); const instanceIdList = StartingInstances.map( (instance) => ` • ${instance.InstanceId}`, ); console.log("Starting instances:"); console.log(instanceIdList.join("\n")); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidInstanceID.NotFound" ) { console.warn(`${caught.message}`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie StartInstancesunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungStopInstances.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, StopInstancesCommand } from "@aws-sdk/client-ec2"; import { fileURLToPath } from "node:url"; import { parseArgs } from "node:util"; /** * Stop one or more EC2 instances. * @param {{ instanceIds: string[] }} options */ export const main = async ({ instanceIds }) => { const client = new EC2Client({}); const command = new StopInstancesCommand({ InstanceIds: instanceIds, }); try { const { StoppingInstances } = await client.send(command); const instanceIdList = StoppingInstances.map( (instance) => ` • ${instance.InstanceId}`, ); console.log("Stopping instances:"); console.log(instanceIdList.join("\n")); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidInstanceID.NotFound" ) { console.warn(`${caught.message}`); } else { throw caught; } } };
  • APIEinzelheiten finden Sie StopInstancesunter AWS SDK for JavaScript APIReferenz.

Das folgende Codebeispiel zeigt die VerwendungTerminateInstances.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, TerminateInstancesCommand } from "@aws-sdk/client-ec2"; import { fileURLToPath } from "node:url"; import { parseArgs } from "node:util"; /** * Terminate one or more EC2 instances. * @param {{ instanceIds: string[] }} options */ export const main = async ({ instanceIds }) => { const client = new EC2Client({}); const command = new TerminateInstancesCommand({ InstanceIds: instanceIds, }); try { const { TerminatingInstances } = await client.send(command); const instanceList = TerminatingInstances.map( (instance) => ` • ${instance.InstanceId}`, ); console.log("Terminating instances:"); console.log(instanceList.join("\n")); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidInstanceID.NotFound" ) { console.warn(`${caught.message}`); } else { throw caught; } } };

Das folgende Codebeispiel zeigt die VerwendungUnmonitorInstances.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

import { EC2Client, UnmonitorInstancesCommand } from "@aws-sdk/client-ec2"; import { fileURLToPath } from "node:url"; import { parseArgs } from "node:util"; /** * Turn off detailed monitoring for the selected instance. * @param {{ instanceIds: string[] }} options */ export const main = async ({ instanceIds }) => { const client = new EC2Client({}); const command = new UnmonitorInstancesCommand({ InstanceIds: instanceIds, }); try { const { InstanceMonitorings } = await client.send(command); const instanceMonitoringsList = InstanceMonitorings.map( (im) => ` • Detailed monitoring state for ${im.InstanceId} is ${im.Monitoring.State}.`, ); console.log("Monitoring status:"); console.log(instanceMonitoringsList.join("\n")); } catch (caught) { if ( caught instanceof Error && caught.name === "InvalidInstanceID.NotFound" ) { console.warn(`${caught.message}`); } else { throw caught; } } };

Szenarien

Das folgende Codebeispiel zeigt, wie Sie einen Webservice mit Load Balancing erstellen, der Buch-, Film- und Liedempfehlungen zurückgibt. Das Beispiel zeigt, wie der Service auf Fehler reagiert und wie der Service für mehr Ausfallsicherheit umstrukturiert werden kann.

  • Verwenden Sie eine Amazon EC2 Auto Scaling Scaling-Gruppe, um Amazon Elastic Compute Cloud (AmazonEC2) -Instances auf der Grundlage einer Startvorlage zu erstellen und die Anzahl der Instances in einem bestimmten Bereich zu halten.

  • Bearbeiten und verteilen Sie HTTP Anfragen mit Elastic Load Balancing.

  • Überwachen Sie den Zustand von Instances in einer Auto-Scaling-Gruppe und leiten Sie Anfragen nur an fehlerfreie Instances weiter.

  • Führen Sie auf jeder EC2 Instanz einen Python-Webserver aus, um HTTP Anfragen zu bearbeiten. Der Webserver reagiert mit Empfehlungen und Zustandsprüfungen.

  • Simulieren Sie einen Empfehlungsservice mit einer Amazon DynamoDB-Tabelle.

  • Steuern Sie die Antwort des Webservers auf Anfragen und Zustandsprüfungen, indem Sie die AWS Systems Manager Parameter aktualisieren.

SDKfür JavaScript (v3)
Anmerkung

Es gibt noch mehr dazu GitHub. Sie sehen das vollständige Beispiel und erfahren, wie Sie das AWS -Code-Beispiel-Repository einrichten und ausführen.

Führen Sie ein interaktives Szenario an einer Eingabeaufforderung aus.

#!/usr/bin/env node // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import { Scenario, parseScenarioArgs, } from "@aws-doc-sdk-examples/lib/scenario/index.js"; /** * The workflow steps are split into three stages: * - deploy * - demo * - destroy * * Each of these stages has a corresponding file prefixed with steps-*. */ import { deploySteps } from "./steps-deploy.js"; import { demoSteps } from "./steps-demo.js"; import { destroySteps } from "./steps-destroy.js"; /** * The context is passed to every scenario. Scenario steps * will modify the context. */ const context = {}; /** * Three Scenarios are created for the workflow. A Scenario is an orchestration class * that simplifies running a series of steps. */ export const scenarios = { // Deploys all resources necessary for the workflow. deploy: new Scenario("Resilient Workflow - Deploy", deploySteps, context), // Demonstrates how a fragile web service can be made more resilient. demo: new Scenario("Resilient Workflow - Demo", demoSteps, context), // Destroys the resources created for the workflow. destroy: new Scenario("Resilient Workflow - Destroy", destroySteps, context), }; // Call function if run directly import { fileURLToPath } from "node:url"; if (process.argv[1] === fileURLToPath(import.meta.url)) { parseScenarioArgs(scenarios, { name: "Resilient Workflow", synopsis: "node index.js --scenario <deploy | demo | destroy> [-h|--help] [-y|--yes] [-v|--verbose]", description: "Deploy and interact with scalable EC2 instances.", }); }

Erstellen Sie Schritte, um alle Ressourcen bereitzustellen.

import { join } from "node:path"; import { readFileSync, writeFileSync } from "node:fs"; import axios from "axios"; import { BatchWriteItemCommand, CreateTableCommand, DynamoDBClient, waitUntilTableExists, } from "@aws-sdk/client-dynamodb"; import { EC2Client, CreateKeyPairCommand, CreateLaunchTemplateCommand, DescribeAvailabilityZonesCommand, DescribeVpcsCommand, DescribeSubnetsCommand, DescribeSecurityGroupsCommand, AuthorizeSecurityGroupIngressCommand, } from "@aws-sdk/client-ec2"; import { IAMClient, CreatePolicyCommand, CreateRoleCommand, CreateInstanceProfileCommand, AddRoleToInstanceProfileCommand, AttachRolePolicyCommand, waitUntilInstanceProfileExists, } from "@aws-sdk/client-iam"; import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm"; import { CreateAutoScalingGroupCommand, AutoScalingClient, AttachLoadBalancerTargetGroupsCommand, } from "@aws-sdk/client-auto-scaling"; import { CreateListenerCommand, CreateLoadBalancerCommand, CreateTargetGroupCommand, ElasticLoadBalancingV2Client, waitUntilLoadBalancerAvailable, } from "@aws-sdk/client-elastic-load-balancing-v2"; import { ScenarioOutput, ScenarioInput, ScenarioAction, } from "@aws-doc-sdk-examples/lib/scenario/index.js"; import { saveState } from "@aws-doc-sdk-examples/lib/scenario/steps-common.js"; import { retry } from "@aws-doc-sdk-examples/lib/utils/util-timers.js"; import { MESSAGES, NAMES, RESOURCES_PATH, ROOT } from "./constants.js"; import { initParamsSteps } from "./steps-reset-params.js"; /** * @type {import('@aws-doc-sdk-examples/lib/scenario.js').Step[]} */ export const deploySteps = [ new ScenarioOutput("introduction", MESSAGES.introduction, { header: true }), new ScenarioInput("confirmDeployment", MESSAGES.confirmDeployment, { type: "confirm", }), new ScenarioAction( "handleConfirmDeployment", (c) => c.confirmDeployment === false && process.exit(), ), new ScenarioOutput( "creatingTable", MESSAGES.creatingTable.replace("${TABLE_NAME}", NAMES.tableName), ), new ScenarioAction("createTable", async () => { const client = new DynamoDBClient({}); await client.send( new CreateTableCommand({ TableName: NAMES.tableName, ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5, }, AttributeDefinitions: [ { AttributeName: "MediaType", AttributeType: "S", }, { AttributeName: "ItemId", AttributeType: "N", }, ], KeySchema: [ { AttributeName: "MediaType", KeyType: "HASH", }, { AttributeName: "ItemId", KeyType: "RANGE", }, ], }), ); await waitUntilTableExists({ client }, { TableName: NAMES.tableName }); }), new ScenarioOutput( "createdTable", MESSAGES.createdTable.replace("${TABLE_NAME}", NAMES.tableName), ), new ScenarioOutput( "populatingTable", MESSAGES.populatingTable.replace("${TABLE_NAME}", NAMES.tableName), ), new ScenarioAction("populateTable", () => { const client = new DynamoDBClient({}); /** * @type {{ default: import("@aws-sdk/client-dynamodb").PutRequest['Item'][] }} */ const recommendations = JSON.parse( readFileSync(join(RESOURCES_PATH, "recommendations.json")), ); return client.send( new BatchWriteItemCommand({ RequestItems: { [NAMES.tableName]: recommendations.map((item) => ({ PutRequest: { Item: item }, })), }, }), ); }), new ScenarioOutput( "populatedTable", MESSAGES.populatedTable.replace("${TABLE_NAME}", NAMES.tableName), ), new ScenarioOutput( "creatingKeyPair", MESSAGES.creatingKeyPair.replace("${KEY_PAIR_NAME}", NAMES.keyPairName), ), new ScenarioAction("createKeyPair", async () => { const client = new EC2Client({}); const { KeyMaterial } = await client.send( new CreateKeyPairCommand({ KeyName: NAMES.keyPairName, }), ); writeFileSync(`${NAMES.keyPairName}.pem`, KeyMaterial, { mode: 0o600 }); }), new ScenarioOutput( "createdKeyPair", MESSAGES.createdKeyPair.replace("${KEY_PAIR_NAME}", NAMES.keyPairName), ), new ScenarioOutput( "creatingInstancePolicy", MESSAGES.creatingInstancePolicy.replace( "${INSTANCE_POLICY_NAME}", NAMES.instancePolicyName, ), ), new ScenarioAction("createInstancePolicy", async (state) => { const client = new IAMClient({}); const { Policy: { Arn }, } = await client.send( new CreatePolicyCommand({ PolicyName: NAMES.instancePolicyName, PolicyDocument: readFileSync( join(RESOURCES_PATH, "instance_policy.json"), ), }), ); state.instancePolicyArn = Arn; }), new ScenarioOutput("createdInstancePolicy", (state) => MESSAGES.createdInstancePolicy .replace("${INSTANCE_POLICY_NAME}", NAMES.instancePolicyName) .replace("${INSTANCE_POLICY_ARN}", state.instancePolicyArn), ), new ScenarioOutput( "creatingInstanceRole", MESSAGES.creatingInstanceRole.replace( "${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName, ), ), new ScenarioAction("createInstanceRole", () => { const client = new IAMClient({}); return client.send( new CreateRoleCommand({ RoleName: NAMES.instanceRoleName, AssumeRolePolicyDocument: readFileSync( join(ROOT, "assume-role-policy.json"), ), }), ); }), new ScenarioOutput( "createdInstanceRole", MESSAGES.createdInstanceRole.replace( "${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName, ), ), new ScenarioOutput( "attachingPolicyToRole", MESSAGES.attachingPolicyToRole .replace("${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName) .replace("${INSTANCE_POLICY_NAME}", NAMES.instancePolicyName), ), new ScenarioAction("attachPolicyToRole", async (state) => { const client = new IAMClient({}); await client.send( new AttachRolePolicyCommand({ RoleName: NAMES.instanceRoleName, PolicyArn: state.instancePolicyArn, }), ); }), new ScenarioOutput( "attachedPolicyToRole", MESSAGES.attachedPolicyToRole .replace("${INSTANCE_POLICY_NAME}", NAMES.instancePolicyName) .replace("${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName), ), new ScenarioOutput( "creatingInstanceProfile", MESSAGES.creatingInstanceProfile.replace( "${INSTANCE_PROFILE_NAME}", NAMES.instanceProfileName, ), ), new ScenarioAction("createInstanceProfile", async (state) => { const client = new IAMClient({}); const { InstanceProfile: { Arn }, } = await client.send( new CreateInstanceProfileCommand({ InstanceProfileName: NAMES.instanceProfileName, }), ); state.instanceProfileArn = Arn; await waitUntilInstanceProfileExists( { client }, { InstanceProfileName: NAMES.instanceProfileName }, ); }), new ScenarioOutput("createdInstanceProfile", (state) => MESSAGES.createdInstanceProfile .replace("${INSTANCE_PROFILE_NAME}", NAMES.instanceProfileName) .replace("${INSTANCE_PROFILE_ARN}", state.instanceProfileArn), ), new ScenarioOutput( "addingRoleToInstanceProfile", MESSAGES.addingRoleToInstanceProfile .replace("${INSTANCE_PROFILE_NAME}", NAMES.instanceProfileName) .replace("${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName), ), new ScenarioAction("addRoleToInstanceProfile", () => { const client = new IAMClient({}); return client.send( new AddRoleToInstanceProfileCommand({ RoleName: NAMES.instanceRoleName, InstanceProfileName: NAMES.instanceProfileName, }), ); }), new ScenarioOutput( "addedRoleToInstanceProfile", MESSAGES.addedRoleToInstanceProfile .replace("${INSTANCE_PROFILE_NAME}", NAMES.instanceProfileName) .replace("${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName), ), ...initParamsSteps, new ScenarioOutput("creatingLaunchTemplate", MESSAGES.creatingLaunchTemplate), new ScenarioAction("createLaunchTemplate", async () => { const ssmClient = new SSMClient({}); const { Parameter } = await ssmClient.send( new GetParameterCommand({ Name: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2", }), ); const ec2Client = new EC2Client({}); await ec2Client.send( new CreateLaunchTemplateCommand({ LaunchTemplateName: NAMES.launchTemplateName, LaunchTemplateData: { InstanceType: "t3.micro", ImageId: Parameter.Value, IamInstanceProfile: { Name: NAMES.instanceProfileName }, UserData: readFileSync( join(RESOURCES_PATH, "server_startup_script.sh"), ).toString("base64"), KeyName: NAMES.keyPairName, }, }), ); }), new ScenarioOutput( "createdLaunchTemplate", MESSAGES.createdLaunchTemplate.replace( "${LAUNCH_TEMPLATE_NAME}", NAMES.launchTemplateName, ), ), new ScenarioOutput( "creatingAutoScalingGroup", MESSAGES.creatingAutoScalingGroup.replace( "${AUTO_SCALING_GROUP_NAME}", NAMES.autoScalingGroupName, ), ), new ScenarioAction("createAutoScalingGroup", async (state) => { const ec2Client = new EC2Client({}); const { AvailabilityZones } = await ec2Client.send( new DescribeAvailabilityZonesCommand({}), ); state.availabilityZoneNames = AvailabilityZones.map((az) => az.ZoneName); const autoScalingClient = new AutoScalingClient({}); await retry({ intervalInMs: 1000, maxRetries: 30 }, () => autoScalingClient.send( new CreateAutoScalingGroupCommand({ AvailabilityZones: state.availabilityZoneNames, AutoScalingGroupName: NAMES.autoScalingGroupName, LaunchTemplate: { LaunchTemplateName: NAMES.launchTemplateName, Version: "$Default", }, MinSize: 3, MaxSize: 3, }), ), ); }), new ScenarioOutput( "createdAutoScalingGroup", /** * @param {{ availabilityZoneNames: string[] }} state */ (state) => MESSAGES.createdAutoScalingGroup .replace("${AUTO_SCALING_GROUP_NAME}", NAMES.autoScalingGroupName) .replace( "${AVAILABILITY_ZONE_NAMES}", state.availabilityZoneNames.join(", "), ), ), new ScenarioInput("confirmContinue", MESSAGES.confirmContinue, { type: "confirm", }), new ScenarioOutput("loadBalancer", MESSAGES.loadBalancer), new ScenarioOutput("gettingVpc", MESSAGES.gettingVpc), new ScenarioAction("getVpc", async (state) => { const client = new EC2Client({}); const { Vpcs } = await client.send( new DescribeVpcsCommand({ Filters: [{ Name: "is-default", Values: ["true"] }], }), ); state.defaultVpc = Vpcs[0].VpcId; }), new ScenarioOutput("gotVpc", (state) => MESSAGES.gotVpc.replace("${VPC_ID}", state.defaultVpc), ), new ScenarioOutput("gettingSubnets", MESSAGES.gettingSubnets), new ScenarioAction("getSubnets", async (state) => { const client = new EC2Client({}); const { Subnets } = await client.send( new DescribeSubnetsCommand({ Filters: [ { Name: "vpc-id", Values: [state.defaultVpc] }, { Name: "availability-zone", Values: state.availabilityZoneNames }, { Name: "default-for-az", Values: ["true"] }, ], }), ); state.subnets = Subnets.map((subnet) => subnet.SubnetId); }), new ScenarioOutput( "gotSubnets", /** * @param {{ subnets: string[] }} state */ (state) => MESSAGES.gotSubnets.replace("${SUBNETS}", state.subnets.join(", ")), ), new ScenarioOutput( "creatingLoadBalancerTargetGroup", MESSAGES.creatingLoadBalancerTargetGroup.replace( "${TARGET_GROUP_NAME}", NAMES.loadBalancerTargetGroupName, ), ), new ScenarioAction("createLoadBalancerTargetGroup", async (state) => { const client = new ElasticLoadBalancingV2Client({}); const { TargetGroups } = await client.send( new CreateTargetGroupCommand({ Name: NAMES.loadBalancerTargetGroupName, Protocol: "HTTP", Port: 80, HealthCheckPath: "/healthcheck", HealthCheckIntervalSeconds: 10, HealthCheckTimeoutSeconds: 5, HealthyThresholdCount: 2, UnhealthyThresholdCount: 2, VpcId: state.defaultVpc, }), ); const targetGroup = TargetGroups[0]; state.targetGroupArn = targetGroup.TargetGroupArn; state.targetGroupProtocol = targetGroup.Protocol; state.targetGroupPort = targetGroup.Port; }), new ScenarioOutput( "createdLoadBalancerTargetGroup", MESSAGES.createdLoadBalancerTargetGroup.replace( "${TARGET_GROUP_NAME}", NAMES.loadBalancerTargetGroupName, ), ), new ScenarioOutput( "creatingLoadBalancer", MESSAGES.creatingLoadBalancer.replace("${LB_NAME}", NAMES.loadBalancerName), ), new ScenarioAction("createLoadBalancer", async (state) => { const client = new ElasticLoadBalancingV2Client({}); const { LoadBalancers } = await client.send( new CreateLoadBalancerCommand({ Name: NAMES.loadBalancerName, Subnets: state.subnets, }), ); state.loadBalancerDns = LoadBalancers[0].DNSName; state.loadBalancerArn = LoadBalancers[0].LoadBalancerArn; await waitUntilLoadBalancerAvailable( { client }, { Names: [NAMES.loadBalancerName] }, ); }), new ScenarioOutput("createdLoadBalancer", (state) => MESSAGES.createdLoadBalancer .replace("${LB_NAME}", NAMES.loadBalancerName) .replace("${DNS_NAME}", state.loadBalancerDns), ), new ScenarioOutput( "creatingListener", MESSAGES.creatingLoadBalancerListener .replace("${LB_NAME}", NAMES.loadBalancerName) .replace("${TARGET_GROUP_NAME}", NAMES.loadBalancerTargetGroupName), ), new ScenarioAction("createListener", async (state) => { const client = new ElasticLoadBalancingV2Client({}); const { Listeners } = await client.send( new CreateListenerCommand({ LoadBalancerArn: state.loadBalancerArn, Protocol: state.targetGroupProtocol, Port: state.targetGroupPort, DefaultActions: [ { Type: "forward", TargetGroupArn: state.targetGroupArn }, ], }), ); const listener = Listeners[0]; state.loadBalancerListenerArn = listener.ListenerArn; }), new ScenarioOutput("createdListener", (state) => MESSAGES.createdLoadBalancerListener.replace( "${LB_LISTENER_ARN}", state.loadBalancerListenerArn, ), ), new ScenarioOutput( "attachingLoadBalancerTargetGroup", MESSAGES.attachingLoadBalancerTargetGroup .replace("${TARGET_GROUP_NAME}", NAMES.loadBalancerTargetGroupName) .replace("${AUTO_SCALING_GROUP_NAME}", NAMES.autoScalingGroupName), ), new ScenarioAction("attachLoadBalancerTargetGroup", async (state) => { const client = new AutoScalingClient({}); await client.send( new AttachLoadBalancerTargetGroupsCommand({ AutoScalingGroupName: NAMES.autoScalingGroupName, TargetGroupARNs: [state.targetGroupArn], }), ); }), new ScenarioOutput( "attachedLoadBalancerTargetGroup", MESSAGES.attachedLoadBalancerTargetGroup, ), new ScenarioOutput("verifyingInboundPort", MESSAGES.verifyingInboundPort), new ScenarioAction( "verifyInboundPort", /** * * @param {{ defaultSecurityGroup: import('@aws-sdk/client-ec2').SecurityGroup}} state */ async (state) => { const client = new EC2Client({}); const { SecurityGroups } = await client.send( new DescribeSecurityGroupsCommand({ Filters: [{ Name: "group-name", Values: ["default"] }], }), ); if (!SecurityGroups) { state.verifyInboundPortError = new Error(MESSAGES.noSecurityGroups); } state.defaultSecurityGroup = SecurityGroups[0]; /** * @type {string} */ const ipResponse = (await axios.get("http://checkip.amazonaws.com")).data; state.myIp = ipResponse.trim(); const myIpRules = state.defaultSecurityGroup.IpPermissions.filter( ({ IpRanges }) => IpRanges.some( ({ CidrIp }) => CidrIp.startsWith(state.myIp) || CidrIp === "0.0.0.0/0", ), ) .filter(({ IpProtocol }) => IpProtocol === "tcp") .filter(({ FromPort }) => FromPort === 80); state.myIpRules = myIpRules; }, ), new ScenarioOutput( "verifiedInboundPort", /** * @param {{ myIpRules: any[] }} state */ (state) => { if (state.myIpRules.length > 0) { return MESSAGES.foundIpRules.replace( "${IP_RULES}", JSON.stringify(state.myIpRules, null, 2), ); } return MESSAGES.noIpRules; }, ), new ScenarioInput( "shouldAddInboundRule", /** * @param {{ myIpRules: any[] }} state */ (state) => { if (state.myIpRules.length > 0) { return false; } return MESSAGES.noIpRules; }, { type: "confirm" }, ), new ScenarioAction( "addInboundRule", /** * @param {{ defaultSecurityGroup: import('@aws-sdk/client-ec2').SecurityGroup }} state */ async (state) => { if (!state.shouldAddInboundRule) { return; } const client = new EC2Client({}); await client.send( new AuthorizeSecurityGroupIngressCommand({ GroupId: state.defaultSecurityGroup.GroupId, CidrIp: `${state.myIp}/32`, FromPort: 80, ToPort: 80, IpProtocol: "tcp", }), ); }, ), new ScenarioOutput("addedInboundRule", (state) => { if (state.shouldAddInboundRule) { return MESSAGES.addedInboundRule.replace("${IP_ADDRESS}", state.myIp); } return false; }), new ScenarioOutput("verifyingEndpoint", (state) => MESSAGES.verifyingEndpoint.replace("${DNS_NAME}", state.loadBalancerDns), ), new ScenarioAction("verifyEndpoint", async (state) => { try { const response = await retry({ intervalInMs: 2000, maxRetries: 30 }, () => axios.get(`http://${state.loadBalancerDns}`), ); state.endpointResponse = JSON.stringify(response.data, null, 2); } catch (e) { state.verifyEndpointError = e; } }), new ScenarioOutput("verifiedEndpoint", (state) => { if (state.verifyEndpointError) { console.error(state.verifyEndpointError); } else { return MESSAGES.verifiedEndpoint.replace( "${ENDPOINT_RESPONSE}", state.endpointResponse, ); } }), saveState, ];

Erstellen Sie Schritte, um die Demo auszuführen.

import { readFileSync } from "node:fs"; import { join } from "node:path"; import axios from "axios"; import { DescribeTargetGroupsCommand, DescribeTargetHealthCommand, ElasticLoadBalancingV2Client, } from "@aws-sdk/client-elastic-load-balancing-v2"; import { DescribeInstanceInformationCommand, PutParameterCommand, SSMClient, SendCommandCommand, } from "@aws-sdk/client-ssm"; import { IAMClient, CreatePolicyCommand, CreateRoleCommand, AttachRolePolicyCommand, CreateInstanceProfileCommand, AddRoleToInstanceProfileCommand, waitUntilInstanceProfileExists, } from "@aws-sdk/client-iam"; import { AutoScalingClient, DescribeAutoScalingGroupsCommand, TerminateInstanceInAutoScalingGroupCommand, } from "@aws-sdk/client-auto-scaling"; import { DescribeIamInstanceProfileAssociationsCommand, EC2Client, RebootInstancesCommand, ReplaceIamInstanceProfileAssociationCommand, } from "@aws-sdk/client-ec2"; import { ScenarioAction, ScenarioInput, ScenarioOutput, } from "@aws-doc-sdk-examples/lib/scenario/scenario.js"; import { retry } from "@aws-doc-sdk-examples/lib/utils/util-timers.js"; import { MESSAGES, NAMES, RESOURCES_PATH } from "./constants.js"; import { findLoadBalancer } from "./shared.js"; const getRecommendation = new ScenarioAction( "getRecommendation", async (state) => { const loadBalancer = await findLoadBalancer(NAMES.loadBalancerName); if (loadBalancer) { state.loadBalancerDnsName = loadBalancer.DNSName; try { state.recommendation = ( await axios.get(`http://${state.loadBalancerDnsName}`) ).data; } catch (e) { state.recommendation = e instanceof Error ? e.message : e; } } else { throw new Error(MESSAGES.demoFindLoadBalancerError); } }, ); const getRecommendationResult = new ScenarioOutput( "getRecommendationResult", (state) => `Recommendation:\n${JSON.stringify(state.recommendation, null, 2)}`, { preformatted: true }, ); const getHealthCheck = new ScenarioAction("getHealthCheck", async (state) => { const client = new ElasticLoadBalancingV2Client({}); const { TargetGroups } = await client.send( new DescribeTargetGroupsCommand({ Names: [NAMES.loadBalancerTargetGroupName], }), ); const { TargetHealthDescriptions } = await client.send( new DescribeTargetHealthCommand({ TargetGroupArn: TargetGroups[0].TargetGroupArn, }), ); state.targetHealthDescriptions = TargetHealthDescriptions; }); const getHealthCheckResult = new ScenarioOutput( "getHealthCheckResult", /** * @param {{ targetHealthDescriptions: import('@aws-sdk/client-elastic-load-balancing-v2').TargetHealthDescription[]}} state */ (state) => { const status = state.targetHealthDescriptions .map((th) => `${th.Target.Id}: ${th.TargetHealth.State}`) .join("\n"); return `Health check:\n${status}`; }, { preformatted: true }, ); const loadBalancerLoop = new ScenarioAction( "loadBalancerLoop", getRecommendation.action, { whileConfig: { whileFn: ({ loadBalancerCheck }) => loadBalancerCheck, input: new ScenarioInput( "loadBalancerCheck", MESSAGES.demoLoadBalancerCheck, { type: "confirm", }, ), output: getRecommendationResult, }, }, ); const healthCheckLoop = new ScenarioAction( "healthCheckLoop", getHealthCheck.action, { whileConfig: { whileFn: ({ healthCheck }) => healthCheck, input: new ScenarioInput("healthCheck", MESSAGES.demoHealthCheck, { type: "confirm", }), output: getHealthCheckResult, }, }, ); const statusSteps = [ getRecommendation, getRecommendationResult, getHealthCheck, getHealthCheckResult, ]; /** * @type {import('@aws-doc-sdk-examples/lib/scenario.js').Step[]} */ export const demoSteps = [ new ScenarioOutput("header", MESSAGES.demoHeader, { header: true }), new ScenarioOutput("sanityCheck", MESSAGES.demoSanityCheck), ...statusSteps, new ScenarioInput( "brokenDependencyConfirmation", MESSAGES.demoBrokenDependencyConfirmation, { type: "confirm" }, ), new ScenarioAction("brokenDependency", async (state) => { if (!state.brokenDependencyConfirmation) { process.exit(); } else { const client = new SSMClient({}); state.badTableName = `fake-table-${Date.now()}`; await client.send( new PutParameterCommand({ Name: NAMES.ssmTableNameKey, Value: state.badTableName, Overwrite: true, Type: "String", }), ); } }), new ScenarioOutput("testBrokenDependency", (state) => MESSAGES.demoTestBrokenDependency.replace( "${TABLE_NAME}", state.badTableName, ), ), ...statusSteps, new ScenarioInput( "staticResponseConfirmation", MESSAGES.demoStaticResponseConfirmation, { type: "confirm" }, ), new ScenarioAction("staticResponse", async (state) => { if (!state.staticResponseConfirmation) { process.exit(); } else { const client = new SSMClient({}); await client.send( new PutParameterCommand({ Name: NAMES.ssmFailureResponseKey, Value: "static", Overwrite: true, Type: "String", }), ); } }), new ScenarioOutput("testStaticResponse", MESSAGES.demoTestStaticResponse), ...statusSteps, new ScenarioInput( "badCredentialsConfirmation", MESSAGES.demoBadCredentialsConfirmation, { type: "confirm" }, ), new ScenarioAction("badCredentialsExit", (state) => { if (!state.badCredentialsConfirmation) { process.exit(); } }), new ScenarioAction("fixDynamoDBName", async () => { const client = new SSMClient({}); await client.send( new PutParameterCommand({ Name: NAMES.ssmTableNameKey, Value: NAMES.tableName, Overwrite: true, Type: "String", }), ); }), new ScenarioAction( "badCredentials", /** * @param {{ targetInstance: import('@aws-sdk/client-auto-scaling').Instance }} state */ async (state) => { await createSsmOnlyInstanceProfile(); const autoScalingClient = new AutoScalingClient({}); const { AutoScalingGroups } = await autoScalingClient.send( new DescribeAutoScalingGroupsCommand({ AutoScalingGroupNames: [NAMES.autoScalingGroupName], }), ); state.targetInstance = AutoScalingGroups[0].Instances[0]; const ec2Client = new EC2Client({}); const { IamInstanceProfileAssociations } = await ec2Client.send( new DescribeIamInstanceProfileAssociationsCommand({ Filters: [ { Name: "instance-id", Values: [state.targetInstance.InstanceId] }, ], }), ); state.instanceProfileAssociationId = IamInstanceProfileAssociations[0].AssociationId; await retry({ intervalInMs: 1000, maxRetries: 30 }, () => ec2Client.send( new ReplaceIamInstanceProfileAssociationCommand({ AssociationId: state.instanceProfileAssociationId, IamInstanceProfile: { Name: NAMES.ssmOnlyInstanceProfileName }, }), ), ); await ec2Client.send( new RebootInstancesCommand({ InstanceIds: [state.targetInstance.InstanceId], }), ); const ssmClient = new SSMClient({}); await retry({ intervalInMs: 20000, maxRetries: 15 }, async () => { const { InstanceInformationList } = await ssmClient.send( new DescribeInstanceInformationCommand({}), ); const instance = InstanceInformationList.find( (info) => info.InstanceId === state.targetInstance.InstanceId, ); if (!instance) { throw new Error("Instance not found."); } }); await ssmClient.send( new SendCommandCommand({ InstanceIds: [state.targetInstance.InstanceId], DocumentName: "AWS-RunShellScript", Parameters: { commands: ["cd / && sudo python3 server.py 80"] }, }), ); }, ), new ScenarioOutput( "testBadCredentials", /** * @param {{ targetInstance: import('@aws-sdk/client-ssm').InstanceInformation}} state */ (state) => MESSAGES.demoTestBadCredentials.replace( "${INSTANCE_ID}", state.targetInstance.InstanceId, ), ), loadBalancerLoop, new ScenarioInput( "deepHealthCheckConfirmation", MESSAGES.demoDeepHealthCheckConfirmation, { type: "confirm" }, ), new ScenarioAction("deepHealthCheckExit", (state) => { if (!state.deepHealthCheckConfirmation) { process.exit(); } }), new ScenarioAction("deepHealthCheck", async () => { const client = new SSMClient({}); await client.send( new PutParameterCommand({ Name: NAMES.ssmHealthCheckKey, Value: "deep", Overwrite: true, Type: "String", }), ); }), new ScenarioOutput("testDeepHealthCheck", MESSAGES.demoTestDeepHealthCheck), healthCheckLoop, loadBalancerLoop, new ScenarioInput( "killInstanceConfirmation", /** * @param {{ targetInstance: import('@aws-sdk/client-ssm').InstanceInformation }} state */ (state) => MESSAGES.demoKillInstanceConfirmation.replace( "${INSTANCE_ID}", state.targetInstance.InstanceId, ), { type: "confirm" }, ), new ScenarioAction("killInstanceExit", (state) => { if (!state.killInstanceConfirmation) { process.exit(); } }), new ScenarioAction( "killInstance", /** * @param {{ targetInstance: import('@aws-sdk/client-ssm').InstanceInformation }} state */ async (state) => { const client = new AutoScalingClient({}); await client.send( new TerminateInstanceInAutoScalingGroupCommand({ InstanceId: state.targetInstance.InstanceId, ShouldDecrementDesiredCapacity: false, }), ); }, ), new ScenarioOutput("testKillInstance", MESSAGES.demoTestKillInstance), healthCheckLoop, loadBalancerLoop, new ScenarioInput("failOpenConfirmation", MESSAGES.demoFailOpenConfirmation, { type: "confirm", }), new ScenarioAction("failOpenExit", (state) => { if (!state.failOpenConfirmation) { process.exit(); } }), new ScenarioAction("failOpen", () => { const client = new SSMClient({}); return client.send( new PutParameterCommand({ Name: NAMES.ssmTableNameKey, Value: `fake-table-${Date.now()}`, Overwrite: true, Type: "String", }), ); }), new ScenarioOutput("testFailOpen", MESSAGES.demoFailOpenTest), healthCheckLoop, loadBalancerLoop, new ScenarioInput( "resetTableConfirmation", MESSAGES.demoResetTableConfirmation, { type: "confirm" }, ), new ScenarioAction("resetTableExit", (state) => { if (!state.resetTableConfirmation) { process.exit(); } }), new ScenarioAction("resetTable", async () => { const client = new SSMClient({}); await client.send( new PutParameterCommand({ Name: NAMES.ssmTableNameKey, Value: NAMES.tableName, Overwrite: true, Type: "String", }), ); }), new ScenarioOutput("testResetTable", MESSAGES.demoTestResetTable), healthCheckLoop, loadBalancerLoop, ]; async function createSsmOnlyInstanceProfile() { const iamClient = new IAMClient({}); const { Policy } = await iamClient.send( new CreatePolicyCommand({ PolicyName: NAMES.ssmOnlyPolicyName, PolicyDocument: readFileSync( join(RESOURCES_PATH, "ssm_only_policy.json"), ), }), ); await iamClient.send( new CreateRoleCommand({ RoleName: NAMES.ssmOnlyRoleName, AssumeRolePolicyDocument: JSON.stringify({ Version: "2012-10-17", Statement: [ { Effect: "Allow", Principal: { Service: "ec2.amazonaws.com" }, Action: "sts:AssumeRole", }, ], }), }), ); await iamClient.send( new AttachRolePolicyCommand({ RoleName: NAMES.ssmOnlyRoleName, PolicyArn: Policy.Arn, }), ); await iamClient.send( new AttachRolePolicyCommand({ RoleName: NAMES.ssmOnlyRoleName, PolicyArn: "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore", }), ); const { InstanceProfile } = await iamClient.send( new CreateInstanceProfileCommand({ InstanceProfileName: NAMES.ssmOnlyInstanceProfileName, }), ); await waitUntilInstanceProfileExists( { client: iamClient }, { InstanceProfileName: NAMES.ssmOnlyInstanceProfileName }, ); await iamClient.send( new AddRoleToInstanceProfileCommand({ InstanceProfileName: NAMES.ssmOnlyInstanceProfileName, RoleName: NAMES.ssmOnlyRoleName, }), ); return InstanceProfile; }

Erstellen Sie Schritte, um alle Ressourcen zu vernichten.

import { unlinkSync } from "node:fs"; import { DynamoDBClient, DeleteTableCommand } from "@aws-sdk/client-dynamodb"; import { EC2Client, DeleteKeyPairCommand, DeleteLaunchTemplateCommand, RevokeSecurityGroupIngressCommand, } from "@aws-sdk/client-ec2"; import { IAMClient, DeleteInstanceProfileCommand, RemoveRoleFromInstanceProfileCommand, DeletePolicyCommand, DeleteRoleCommand, DetachRolePolicyCommand, paginateListPolicies, } from "@aws-sdk/client-iam"; import { AutoScalingClient, DeleteAutoScalingGroupCommand, TerminateInstanceInAutoScalingGroupCommand, UpdateAutoScalingGroupCommand, paginateDescribeAutoScalingGroups, } from "@aws-sdk/client-auto-scaling"; import { DeleteLoadBalancerCommand, DeleteTargetGroupCommand, DescribeTargetGroupsCommand, ElasticLoadBalancingV2Client, } from "@aws-sdk/client-elastic-load-balancing-v2"; import { ScenarioOutput, ScenarioInput, ScenarioAction, } from "@aws-doc-sdk-examples/lib/scenario/index.js"; import { loadState } from "@aws-doc-sdk-examples/lib/scenario/steps-common.js"; import { retry } from "@aws-doc-sdk-examples/lib/utils/util-timers.js"; import { MESSAGES, NAMES } from "./constants.js"; import { findLoadBalancer } from "./shared.js"; /** * @type {import('@aws-doc-sdk-examples/lib/scenario.js').Step[]} */ export const destroySteps = [ loadState, new ScenarioInput("destroy", MESSAGES.destroy, { type: "confirm" }), new ScenarioAction( "abort", (state) => state.destroy === false && process.exit(), ), new ScenarioAction("deleteTable", async (c) => { try { const client = new DynamoDBClient({}); await client.send(new DeleteTableCommand({ TableName: NAMES.tableName })); } catch (e) { c.deleteTableError = e; } }), new ScenarioOutput("deleteTableResult", (state) => { if (state.deleteTableError) { console.error(state.deleteTableError); return MESSAGES.deleteTableError.replace( "${TABLE_NAME}", NAMES.tableName, ); } return MESSAGES.deletedTable.replace("${TABLE_NAME}", NAMES.tableName); }), new ScenarioAction("deleteKeyPair", async (state) => { try { const client = new EC2Client({}); await client.send( new DeleteKeyPairCommand({ KeyName: NAMES.keyPairName }), ); unlinkSync(`${NAMES.keyPairName}.pem`); } catch (e) { state.deleteKeyPairError = e; } }), new ScenarioOutput("deleteKeyPairResult", (state) => { if (state.deleteKeyPairError) { console.error(state.deleteKeyPairError); return MESSAGES.deleteKeyPairError.replace( "${KEY_PAIR_NAME}", NAMES.keyPairName, ); } return MESSAGES.deletedKeyPair.replace( "${KEY_PAIR_NAME}", NAMES.keyPairName, ); }), new ScenarioAction("detachPolicyFromRole", async (state) => { try { const client = new IAMClient({}); const policy = await findPolicy(NAMES.instancePolicyName); if (!policy) { state.detachPolicyFromRoleError = new Error( `Policy ${NAMES.instancePolicyName} not found.`, ); } else { await client.send( new DetachRolePolicyCommand({ RoleName: NAMES.instanceRoleName, PolicyArn: policy.Arn, }), ); } } catch (e) { state.detachPolicyFromRoleError = e; } }), new ScenarioOutput("detachedPolicyFromRole", (state) => { if (state.detachPolicyFromRoleError) { console.error(state.detachPolicyFromRoleError); return MESSAGES.detachPolicyFromRoleError .replace("${INSTANCE_POLICY_NAME}", NAMES.instancePolicyName) .replace("${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName); } return MESSAGES.detachedPolicyFromRole .replace("${INSTANCE_POLICY_NAME}", NAMES.instancePolicyName) .replace("${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName); }), new ScenarioAction("deleteInstancePolicy", async (state) => { const client = new IAMClient({}); const policy = await findPolicy(NAMES.instancePolicyName); if (!policy) { state.deletePolicyError = new Error( `Policy ${NAMES.instancePolicyName} not found.`, ); } else { return client.send( new DeletePolicyCommand({ PolicyArn: policy.Arn, }), ); } }), new ScenarioOutput("deletePolicyResult", (state) => { if (state.deletePolicyError) { console.error(state.deletePolicyError); return MESSAGES.deletePolicyError.replace( "${INSTANCE_POLICY_NAME}", NAMES.instancePolicyName, ); } return MESSAGES.deletedPolicy.replace( "${INSTANCE_POLICY_NAME}", NAMES.instancePolicyName, ); }), new ScenarioAction("removeRoleFromInstanceProfile", async (state) => { try { const client = new IAMClient({}); await client.send( new RemoveRoleFromInstanceProfileCommand({ RoleName: NAMES.instanceRoleName, InstanceProfileName: NAMES.instanceProfileName, }), ); } catch (e) { state.removeRoleFromInstanceProfileError = e; } }), new ScenarioOutput("removeRoleFromInstanceProfileResult", (state) => { if (state.removeRoleFromInstanceProfile) { console.error(state.removeRoleFromInstanceProfileError); return MESSAGES.removeRoleFromInstanceProfileError .replace("${INSTANCE_PROFILE_NAME}", NAMES.instanceProfileName) .replace("${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName); } return MESSAGES.removedRoleFromInstanceProfile .replace("${INSTANCE_PROFILE_NAME}", NAMES.instanceProfileName) .replace("${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName); }), new ScenarioAction("deleteInstanceRole", async (state) => { try { const client = new IAMClient({}); await client.send( new DeleteRoleCommand({ RoleName: NAMES.instanceRoleName, }), ); } catch (e) { state.deleteInstanceRoleError = e; } }), new ScenarioOutput("deleteInstanceRoleResult", (state) => { if (state.deleteInstanceRoleError) { console.error(state.deleteInstanceRoleError); return MESSAGES.deleteInstanceRoleError.replace( "${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName, ); } return MESSAGES.deletedInstanceRole.replace( "${INSTANCE_ROLE_NAME}", NAMES.instanceRoleName, ); }), new ScenarioAction("deleteInstanceProfile", async (state) => { try { const client = new IAMClient({}); await client.send( new DeleteInstanceProfileCommand({ InstanceProfileName: NAMES.instanceProfileName, }), ); } catch (e) { state.deleteInstanceProfileError = e; } }), new ScenarioOutput("deleteInstanceProfileResult", (state) => { if (state.deleteInstanceProfileError) { console.error(state.deleteInstanceProfileError); return MESSAGES.deleteInstanceProfileError.replace( "${INSTANCE_PROFILE_NAME}", NAMES.instanceProfileName, ); } return MESSAGES.deletedInstanceProfile.replace( "${INSTANCE_PROFILE_NAME}", NAMES.instanceProfileName, ); }), new ScenarioAction("deleteAutoScalingGroup", async (state) => { try { await terminateGroupInstances(NAMES.autoScalingGroupName); await retry({ intervalInMs: 60000, maxRetries: 60 }, async () => { await deleteAutoScalingGroup(NAMES.autoScalingGroupName); }); } catch (e) { state.deleteAutoScalingGroupError = e; } }), new ScenarioOutput("deleteAutoScalingGroupResult", (state) => { if (state.deleteAutoScalingGroupError) { console.error(state.deleteAutoScalingGroupError); return MESSAGES.deleteAutoScalingGroupError.replace( "${AUTO_SCALING_GROUP_NAME}", NAMES.autoScalingGroupName, ); } return MESSAGES.deletedAutoScalingGroup.replace( "${AUTO_SCALING_GROUP_NAME}", NAMES.autoScalingGroupName, ); }), new ScenarioAction("deleteLaunchTemplate", async (state) => { const client = new EC2Client({}); try { await client.send( new DeleteLaunchTemplateCommand({ LaunchTemplateName: NAMES.launchTemplateName, }), ); } catch (e) { state.deleteLaunchTemplateError = e; } }), new ScenarioOutput("deleteLaunchTemplateResult", (state) => { if (state.deleteLaunchTemplateError) { console.error(state.deleteLaunchTemplateError); return MESSAGES.deleteLaunchTemplateError.replace( "${LAUNCH_TEMPLATE_NAME}", NAMES.launchTemplateName, ); } return MESSAGES.deletedLaunchTemplate.replace( "${LAUNCH_TEMPLATE_NAME}", NAMES.launchTemplateName, ); }), new ScenarioAction("deleteLoadBalancer", async (state) => { try { const client = new ElasticLoadBalancingV2Client({}); const loadBalancer = await findLoadBalancer(NAMES.loadBalancerName); await client.send( new DeleteLoadBalancerCommand({ LoadBalancerArn: loadBalancer.LoadBalancerArn, }), ); await retry({ intervalInMs: 1000, maxRetries: 60 }, async () => { const lb = await findLoadBalancer(NAMES.loadBalancerName); if (lb) { throw new Error("Load balancer still exists."); } }); } catch (e) { state.deleteLoadBalancerError = e; } }), new ScenarioOutput("deleteLoadBalancerResult", (state) => { if (state.deleteLoadBalancerError) { console.error(state.deleteLoadBalancerError); return MESSAGES.deleteLoadBalancerError.replace( "${LB_NAME}", NAMES.loadBalancerName, ); } return MESSAGES.deletedLoadBalancer.replace( "${LB_NAME}", NAMES.loadBalancerName, ); }), new ScenarioAction("deleteLoadBalancerTargetGroup", async (state) => { const client = new ElasticLoadBalancingV2Client({}); try { const { TargetGroups } = await client.send( new DescribeTargetGroupsCommand({ Names: [NAMES.loadBalancerTargetGroupName], }), ); await retry({ intervalInMs: 1000, maxRetries: 30 }, () => client.send( new DeleteTargetGroupCommand({ TargetGroupArn: TargetGroups[0].TargetGroupArn, }), ), ); } catch (e) { state.deleteLoadBalancerTargetGroupError = e; } }), new ScenarioOutput("deleteLoadBalancerTargetGroupResult", (state) => { if (state.deleteLoadBalancerTargetGroupError) { console.error(state.deleteLoadBalancerTargetGroupError); return MESSAGES.deleteLoadBalancerTargetGroupError.replace( "${TARGET_GROUP_NAME}", NAMES.loadBalancerTargetGroupName, ); } return MESSAGES.deletedLoadBalancerTargetGroup.replace( "${TARGET_GROUP_NAME}", NAMES.loadBalancerTargetGroupName, ); }), new ScenarioAction("detachSsmOnlyRoleFromProfile", async (state) => { try { const client = new IAMClient({}); await client.send( new RemoveRoleFromInstanceProfileCommand({ InstanceProfileName: NAMES.ssmOnlyInstanceProfileName, RoleName: NAMES.ssmOnlyRoleName, }), ); } catch (e) { state.detachSsmOnlyRoleFromProfileError = e; } }), new ScenarioOutput("detachSsmOnlyRoleFromProfileResult", (state) => { if (state.detachSsmOnlyRoleFromProfileError) { console.error(state.detachSsmOnlyRoleFromProfileError); return MESSAGES.detachSsmOnlyRoleFromProfileError .replace("${ROLE_NAME}", NAMES.ssmOnlyRoleName) .replace("${PROFILE_NAME}", NAMES.ssmOnlyInstanceProfileName); } return MESSAGES.detachedSsmOnlyRoleFromProfile .replace("${ROLE_NAME}", NAMES.ssmOnlyRoleName) .replace("${PROFILE_NAME}", NAMES.ssmOnlyInstanceProfileName); }), new ScenarioAction("detachSsmOnlyCustomRolePolicy", async (state) => { try { const iamClient = new IAMClient({}); const ssmOnlyPolicy = await findPolicy(NAMES.ssmOnlyPolicyName); await iamClient.send( new DetachRolePolicyCommand({ RoleName: NAMES.ssmOnlyRoleName, PolicyArn: ssmOnlyPolicy.Arn, }), ); } catch (e) { state.detachSsmOnlyCustomRolePolicyError = e; } }), new ScenarioOutput("detachSsmOnlyCustomRolePolicyResult", (state) => { if (state.detachSsmOnlyCustomRolePolicyError) { console.error(state.detachSsmOnlyCustomRolePolicyError); return MESSAGES.detachSsmOnlyCustomRolePolicyError .replace("${ROLE_NAME}", NAMES.ssmOnlyRoleName) .replace("${POLICY_NAME}", NAMES.ssmOnlyPolicyName); } return MESSAGES.detachedSsmOnlyCustomRolePolicy .replace("${ROLE_NAME}", NAMES.ssmOnlyRoleName) .replace("${POLICY_NAME}", NAMES.ssmOnlyPolicyName); }), new ScenarioAction("detachSsmOnlyAWSRolePolicy", async (state) => { try { const iamClient = new IAMClient({}); await iamClient.send( new DetachRolePolicyCommand({ RoleName: NAMES.ssmOnlyRoleName, PolicyArn: "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore", }), ); } catch (e) { state.detachSsmOnlyAWSRolePolicyError = e; } }), new ScenarioOutput("detachSsmOnlyAWSRolePolicyResult", (state) => { if (state.detachSsmOnlyAWSRolePolicyError) { console.error(state.detachSsmOnlyAWSRolePolicyError); return MESSAGES.detachSsmOnlyAWSRolePolicyError .replace("${ROLE_NAME}", NAMES.ssmOnlyRoleName) .replace("${POLICY_NAME}", "AmazonSSMManagedInstanceCore"); } return MESSAGES.detachedSsmOnlyAWSRolePolicy .replace("${ROLE_NAME}", NAMES.ssmOnlyRoleName) .replace("${POLICY_NAME}", "AmazonSSMManagedInstanceCore"); }), new ScenarioAction("deleteSsmOnlyInstanceProfile", async (state) => { try { const iamClient = new IAMClient({}); await iamClient.send( new DeleteInstanceProfileCommand({ InstanceProfileName: NAMES.ssmOnlyInstanceProfileName, }), ); } catch (e) { state.deleteSsmOnlyInstanceProfileError = e; } }), new ScenarioOutput("deleteSsmOnlyInstanceProfileResult", (state) => { if (state.deleteSsmOnlyInstanceProfileError) { console.error(state.deleteSsmOnlyInstanceProfileError); return MESSAGES.deleteSsmOnlyInstanceProfileError.replace( "${INSTANCE_PROFILE_NAME}", NAMES.ssmOnlyInstanceProfileName, ); } return MESSAGES.deletedSsmOnlyInstanceProfile.replace( "${INSTANCE_PROFILE_NAME}", NAMES.ssmOnlyInstanceProfileName, ); }), new ScenarioAction("deleteSsmOnlyPolicy", async (state) => { try { const iamClient = new IAMClient({}); const ssmOnlyPolicy = await findPolicy(NAMES.ssmOnlyPolicyName); await iamClient.send( new DeletePolicyCommand({ PolicyArn: ssmOnlyPolicy.Arn, }), ); } catch (e) { state.deleteSsmOnlyPolicyError = e; } }), new ScenarioOutput("deleteSsmOnlyPolicyResult", (state) => { if (state.deleteSsmOnlyPolicyError) { console.error(state.deleteSsmOnlyPolicyError); return MESSAGES.deleteSsmOnlyPolicyError.replace( "${POLICY_NAME}", NAMES.ssmOnlyPolicyName, ); } return MESSAGES.deletedSsmOnlyPolicy.replace( "${POLICY_NAME}", NAMES.ssmOnlyPolicyName, ); }), new ScenarioAction("deleteSsmOnlyRole", async (state) => { try { const iamClient = new IAMClient({}); await iamClient.send( new DeleteRoleCommand({ RoleName: NAMES.ssmOnlyRoleName, }), ); } catch (e) { state.deleteSsmOnlyRoleError = e; } }), new ScenarioOutput("deleteSsmOnlyRoleResult", (state) => { if (state.deleteSsmOnlyRoleError) { console.error(state.deleteSsmOnlyRoleError); return MESSAGES.deleteSsmOnlyRoleError.replace( "${ROLE_NAME}", NAMES.ssmOnlyRoleName, ); } return MESSAGES.deletedSsmOnlyRole.replace( "${ROLE_NAME}", NAMES.ssmOnlyRoleName, ); }), new ScenarioAction( "revokeSecurityGroupIngress", async ( /** @type {{ myIp: string, defaultSecurityGroup: { GroupId: string } }} */ state, ) => { const ec2Client = new EC2Client({}); try { await ec2Client.send( new RevokeSecurityGroupIngressCommand({ GroupId: state.defaultSecurityGroup.GroupId, CidrIp: `${state.myIp}/32`, FromPort: 80, ToPort: 80, IpProtocol: "tcp", }), ); } catch (e) { state.revokeSecurityGroupIngressError = e; } }, ), new ScenarioOutput("revokeSecurityGroupIngressResult", (state) => { if (state.revokeSecurityGroupIngressError) { console.error(state.revokeSecurityGroupIngressError); return MESSAGES.revokeSecurityGroupIngressError.replace( "${IP}", state.myIp, ); } return MESSAGES.revokedSecurityGroupIngress.replace("${IP}", state.myIp); }), ]; /** * @param {string} policyName */ async function findPolicy(policyName) { const client = new IAMClient({}); const paginatedPolicies = paginateListPolicies({ client }, {}); for await (const page of paginatedPolicies) { const policy = page.Policies.find((p) => p.PolicyName === policyName); if (policy) { return policy; } } } /** * @param {string} groupName */ async function deleteAutoScalingGroup(groupName) { const client = new AutoScalingClient({}); try { await client.send( new DeleteAutoScalingGroupCommand({ AutoScalingGroupName: groupName, }), ); } catch (err) { if (!(err instanceof Error)) { throw err; } console.log(err.name); throw err; } } /** * @param {string} groupName */ async function terminateGroupInstances(groupName) { const autoScalingClient = new AutoScalingClient({}); const group = await findAutoScalingGroup(groupName); await autoScalingClient.send( new UpdateAutoScalingGroupCommand({ AutoScalingGroupName: group.AutoScalingGroupName, MinSize: 0, }), ); for (const i of group.Instances) { await retry({ intervalInMs: 1000, maxRetries: 30 }, () => autoScalingClient.send( new TerminateInstanceInAutoScalingGroupCommand({ InstanceId: i.InstanceId, ShouldDecrementDesiredCapacity: true, }), ), ); } } async function findAutoScalingGroup(groupName) { const client = new AutoScalingClient({}); const paginatedGroups = paginateDescribeAutoScalingGroups({ client }, {}); for await (const page of paginatedGroups) { const group = page.AutoScalingGroups.find( (g) => g.AutoScalingGroupName === groupName, ); if (group) { return group; } } throw new Error(`Auto scaling group ${groupName} not found.`); }