Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions docs/components/AWS.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import { CardGrid, LinkCard } from "@astrojs/starlight/components";
<LinkCard title="EC2 • Enable Image" href="#ec2-•-enable-image" description="Enable an EC2 AMI image" />
<LinkCard title="EC2 • Enable Image Deprecation" href="#ec2-•-enable-image-deprecation" description="Enable deprecation for an EC2 AMI image" />
<LinkCard title="EC2 • Get Image" href="#ec2-•-get-image" description="Get an EC2 AMI image by ID" />
<LinkCard title="EC2 • Get Instance" href="#ec2-•-get-instance" description="Fetch the current state and details of an EC2 instance" />
<LinkCard title="EC2 • Manage Instance Power" href="#ec2-•-manage-instance-power" description="Perform power operations on an EC2 instance" />
<LinkCard title="ECR • Get Image" href="#ecr-•-get-image" description="Get an ECR image by digest or tag" />
<LinkCard title="ECR • Get Image Scan Findings" href="#ecr-•-get-image-scan-findings" description="Get ECR image scan findings by digest or tag" />
<LinkCard title="ECR • Scan Image" href="#ecr-•-scan-image" description="Scan an ECR image for vulnerabilities" />
Expand Down Expand Up @@ -1403,6 +1405,117 @@ The Get Image component retrieves metadata for an EC2 AMI.
}
```

<a id="ec2-•-get-instance"></a>

## EC2 • Get Instance

**Component key:** `aws.ec2.getInstance`

The Get Instance component describes an EC2 instance and emits its current details.

### Use Cases

- **State inspection**: Check whether an instance is running or stopped before taking action
- **IP resolution**: Retrieve the public or private IP address of an instance at runtime
- **Metadata lookup**: Fetch instance type, AMI, VPC, and tags mid-workflow

### Configuration

- **Region**: AWS region where the instance runs
- **Instance**: EC2 instance to describe

### Output

Emits the instance details on the default output channel:
- `instanceId`, `state`, `instanceType`, `imageId`
- `publicIpAddress`, `privateIpAddress`, `publicDnsName`, `privateDnsName`
- `subnetId`, `vpcId`, `region`, `name`, `launchTime`

### Example Output

```json
{
"data": {
"imageId": "ami-07f0e4f3e9c123abc",
"instanceId": "i-0abc1234567890def",
"instanceType": "t3.micro",
"keyName": "my-key",
"launchTime": "2026-05-21T12:00:00.000Z",
"name": "my-server",
"privateDnsName": "ip-10-0-1-25.ec2.internal",
"privateIpAddress": "10.0.1.25",
"publicDnsName": "ec2-54-198-10-42.compute-1.amazonaws.com",
"publicIpAddress": "54.198.10.42",
"region": "us-east-1",
"state": "running",
"subnetId": "subnet-0abc1234567890def",
"vpcId": "vpc-0abc1234567890def"
},
"timestamp": "2026-05-21T12:01:00Z",
"type": "aws.ec2.instance"
}
```

<a id="ec2-•-manage-instance-power"></a>

## EC2 • Manage Instance Power

**Component key:** `aws.ec2.manageInstancePower`

The Manage Instance Power component performs power management operations on an EC2 instance.

### Use Cases

- **Scheduled workloads**: Start or stop instances on demand from a workflow
- **Cost optimisation**: Stop or hibernate non-production instances outside business hours
- **Maintenance workflows**: Stop an instance before resizing or patching, start it after
- **Recovery**: Reboot an instance experiencing issues

### Configuration

- **Region**: AWS region where the instance runs
- **Instance**: EC2 instance to manage
- **Operation**: The power operation to perform:
- **Start**: Start a stopped instance and wait for it to reach running state
- **Stop**: Gracefully stop a running instance and wait for stopped state
- **Reboot**: Reboot a running instance (completes once the reboot signal is sent)
- **Hibernate**: Stop an instance and save RAM to disk (instance must have hibernation enabled)

### Output

Emits instance details on the default output channel once the operation completes:
- `instanceId`, `state`, `region`
- `publicIpAddress`, `privateIpAddress` (start only)

### Important Notes

- **Hibernate** requires the instance to have been launched with hibernation enabled
- **Reboot** emits immediately after the reboot signal is accepted; it does not wait for the OS to come back online

### Example Output

```json
{
"data": {
"imageId": "ami-0215d085326c25744",
"instanceId": "i-0abc1234567890def",
"instanceType": "t3.micro",
"launchTime": "2026-05-28T09:41:14.000Z",
"name": "preview-pr-5",
"privateDnsName": "ip-10.0.1.25.eu-north-1.compute.internal",
"privateIpAddress": "10.0.1.25",
"publicDnsName": "ec2-54-198-10-42.eu-north-1.compute.amazonaws.com",
"publicIpAddress": "54.198.10.42",
"region": "eu-north-1",
"state": "running",
"subnetId": "subnet-0e7c8aa9b0a82aec5",
"vpcId": "vpc-0049650f5a479c14b"
},
"timestamp": "2026-05-28T09:41:26.29656651Z",
"type": "aws.ec2.instance.power.started"
}
```

<a id="ecr-•-get-image"></a>

## ECR • Get Image
Expand Down
2 changes: 2 additions & 0 deletions pkg/integrations/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ func (a *AWS) Actions() []core.Action {
&ec2.EnableImage{},
&ec2.EnableImageDeprecation{},
&ec2.GetImage{},
&ec2.GetInstance{},
&ec2.ManageInstancePower{},
&sns.GetTopic{},
&sns.GetSubscription{},
&sns.CreateTopic{},
Expand Down
104 changes: 104 additions & 0 deletions pkg/integrations/aws/ec2/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@ type TerminateInstancesOutput struct {
State string `json:"state" mapstructure:"state"`
}

type StopInstancesOutput struct {
RequestID string `json:"requestId" mapstructure:"requestId"`
InstanceID string `json:"instanceId" mapstructure:"instanceId"`
State string `json:"state" mapstructure:"state"`
}

type StartInstancesOutput struct {
RequestID string `json:"requestId" mapstructure:"requestId"`
InstanceID string `json:"instanceId" mapstructure:"instanceId"`
State string `json:"state" mapstructure:"state"`
}

type CreateImageInput struct {
InstanceID string
Name string
Expand Down Expand Up @@ -519,6 +531,78 @@ func (c *Client) TerminateInstances(instanceIDs ...string) (*TerminateInstancesO
}, nil
}

func (c *Client) StopInstances(instanceID string) (*StopInstancesOutput, error) {
return c.stopInstances(instanceID, false)
}

func (c *Client) HibernateInstances(instanceID string) (*StopInstancesOutput, error) {
return c.stopInstances(instanceID, true)
}

func (c *Client) stopInstances(instanceID string, hibernate bool) (*StopInstancesOutput, error) {
params := url.Values{}
params.Set("InstanceId.1", strings.TrimSpace(instanceID))
if hibernate {
params.Set("Hibernate", "true")
}

response := stopInstancesResponse{}
if err := c.postForm("StopInstances", params, &response); err != nil {
return nil, err
}

if len(response.Instances) == 0 {
return nil, fmt.Errorf("response did not include instance ID")
}

instance := response.Instances[0]
return &StopInstancesOutput{
RequestID: response.RequestID,
InstanceID: instance.InstanceID,
State: instance.CurrentState.Name,
}, nil
}

func (c *Client) RebootInstances(instanceID string) error {
params := url.Values{}
params.Set("InstanceId.1", strings.TrimSpace(instanceID))

response := struct {
RequestID string `xml:"requestId"`
Return bool `xml:"return"`
}{}
if err := c.postForm("RebootInstances", params, &response); err != nil {
return err
}

if !response.Return {
return fmt.Errorf("RebootInstances returned false")
}

return nil
}

func (c *Client) StartInstances(instanceID string) (*StartInstancesOutput, error) {
params := url.Values{}
params.Set("InstanceId.1", strings.TrimSpace(instanceID))

response := startInstancesResponse{}
if err := c.postForm("StartInstances", params, &response); err != nil {
return nil, err
}

if len(response.Instances) == 0 {
return nil, fmt.Errorf("response did not include instance ID")
}

instance := response.Instances[0]
return &StartInstancesOutput{
RequestID: response.RequestID,
InstanceID: instance.InstanceID,
State: instance.CurrentState.Name,
}, nil
}

func (c *Client) ListSubnets() ([]Subnet, error) {
subnets := []Subnet{}
nextToken := ""
Expand Down Expand Up @@ -1424,6 +1508,26 @@ type terminateInstancesResponse struct {
Instances []xmlInstance `xml:"instancesSet>item"`
}

type stopInstancesResponse struct {
RequestID string `xml:"requestId"`
Instances []xmlInstanceStateChange `xml:"instancesSet>item"`
}

type startInstancesResponse struct {
RequestID string `xml:"requestId"`
Instances []xmlInstanceStateChange `xml:"instancesSet>item"`
}

type xmlInstanceStateChange struct {
InstanceID string `xml:"instanceId"`
CurrentState struct {
Name string `xml:"name"`
} `xml:"currentState"`
PreviousState struct {
Name string `xml:"name"`
} `xml:"previousState"`
}

type describeSubnetsResponse struct {
Subnets []xmlSubnet `xml:"subnetSet>item"`
NextToken string `xml:"nextToken"`
Expand Down
9 changes: 7 additions & 2 deletions pkg/integrations/aws/ec2/ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ const (
)

const (
CreateInstancePayloadType = "aws.ec2.instance"
DeleteInstancePayloadType = "aws.ec2.instance.deleted"
CreateInstancePayloadType = "aws.ec2.instance"
DeleteInstancePayloadType = "aws.ec2.instance.deleted"
GetInstancePayloadType = "aws.ec2.instance"
ManageInstancePowerStartPayloadType = "aws.ec2.instance.power.started"
ManageInstancePowerStopPayloadType = "aws.ec2.instance.power.stopped"
ManageInstancePowerRebootPayloadType = "aws.ec2.instance.power.rebooted"
ManageInstancePowerHibernatePayloadType = "aws.ec2.instance.power.hibernated"

instancePollInterval = 10 * time.Second
maxInstancePollErrors = 10
Expand Down
28 changes: 28 additions & 0 deletions pkg/integrations/aws/ec2/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ var exampleOutputCreateInstanceBytes []byte
//go:embed example_output_delete_instance.json
var exampleOutputDeleteInstanceBytes []byte

//go:embed example_output_get_instance.json
var exampleOutputGetInstanceBytes []byte

//go:embed example_output_manage_instance_power.json
var exampleOutputManageInstancePowerBytes []byte

var exampleDataOnImageOnce sync.Once
var exampleDataOnImage map[string]any

Expand Down Expand Up @@ -73,6 +79,12 @@ var exampleOutputCreateInstance map[string]any
var exampleOutputDeleteInstanceOnce sync.Once
var exampleOutputDeleteInstance map[string]any

var exampleOutputGetInstanceOnce sync.Once
var exampleOutputGetInstance map[string]any

var exampleOutputManageInstancePowerOnce sync.Once
var exampleOutputManageInstancePower map[string]any

func (t *OnImage) ExampleData() map[string]any {
return utils.UnmarshalEmbeddedJSON(&exampleDataOnImageOnce, exampleDataOnImageBytes, &exampleDataOnImage)
}
Expand Down Expand Up @@ -136,3 +148,19 @@ func (c *DeleteInstance) ExampleOutput() map[string]any {
&exampleOutputDeleteInstance,
)
}

func (c *GetInstance) ExampleOutput() map[string]any {
return utils.UnmarshalEmbeddedJSON(
&exampleOutputGetInstanceOnce,
exampleOutputGetInstanceBytes,
&exampleOutputGetInstance,
)
}

func (c *ManageInstancePower) ExampleOutput() map[string]any {
return utils.UnmarshalEmbeddedJSON(
&exampleOutputManageInstancePowerOnce,
exampleOutputManageInstancePowerBytes,
&exampleOutputManageInstancePower,
)
}
20 changes: 20 additions & 0 deletions pkg/integrations/aws/ec2/example_output_get_instance.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"data": {
"instanceId": "i-0abc1234567890def",
"instanceType": "t3.micro",
"imageId": "ami-07f0e4f3e9c123abc",
"state": "running",
"name": "my-server",
"keyName": "my-key",
"launchTime": "2026-05-21T12:00:00.000Z",
"privateIpAddress": "10.0.1.25",
"publicIpAddress": "54.198.10.42",
"privateDnsName": "ip-10-0-1-25.ec2.internal",
"publicDnsName": "ec2-54-198-10-42.compute-1.amazonaws.com",
"subnetId": "subnet-0abc1234567890def",
"vpcId": "vpc-0abc1234567890def",
"region": "us-east-1"
},
"timestamp": "2026-05-21T12:01:00Z",
"type": "aws.ec2.instance"
}
19 changes: 19 additions & 0 deletions pkg/integrations/aws/ec2/example_output_manage_instance_power.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"data": {
"imageId": "ami-0215d085326c25744",
"instanceId": "i-0abc1234567890def",
"instanceType": "t3.micro",
"launchTime": "2026-05-28T09:41:14.000Z",
"name": "preview-pr-5",
"privateDnsName": "ip-10.0.1.25.eu-north-1.compute.internal",
"privateIpAddress": "10.0.1.25",
"publicDnsName": "ec2-54-198-10-42.eu-north-1.compute.amazonaws.com",
"publicIpAddress": "54.198.10.42",
"region": "eu-north-1",
"state": "running",
"subnetId": "subnet-0e7c8aa9b0a82aec5",
"vpcId": "vpc-0049650f5a479c14b"
},
"timestamp": "2026-05-28T09:41:26.29656651Z",
"type": "aws.ec2.instance.power.started"
}
Loading
Loading