Skip to content

Conversation

@Deepcode643
Copy link

Added Terraform-based EC2 stop/start control using null_resource and AWS CLI.
Updated README with usage instructions.

@madebygps
Copy link
Collaborator

hello, thank you for the contribution, please verify that you've tested this addition by attaching screenshots of launching lab and then of using start/stop control.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR attempts to add EC2 instance start/stop control functionality using Terraform null_resource blocks with AWS CLI commands, and updates the README with usage instructions. However, the implementation has fundamental design flaws that prevent it from working as intended.

Changes:

  • Added Terraform required_providers block specifying AWS provider version ~> 6.0
  • Added two null_resource blocks (stop_instance and start_instance) using local-exec provisioners with AWS CLI commands
  • Updated README with EC2 instance control instructions

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
aws/main.tf Added required_providers block and two null_resource blocks for EC2 instance lifecycle control using AWS CLI
aws/README.md Added documentation section for EC2 instance control with usage examples (contains formatting errors)
Comments suppressed due to low confidence (2)

aws/main.tf:216

  • These null_resource blocks will execute their provisioners immediately during terraform apply, which is not the intended behavior for instance control. The local-exec provisioner runs when the resource is created, not when it's targeted. This means:
  1. Both resources will try to execute during initial apply, causing conflicts (trying to stop and start simultaneously)
  2. The triggers only cause recreation when the instance ID changes, not when you want to control the instance
  3. Using terraform apply -target on these resources will recreate them, running the commands, but this is an anti-pattern

Consider using Terraform's lifecycle management with terraform destroy to stop instances, or implement a proper state-driven approach where an input variable controls the desired state (running/stopped) and the configuration responds accordingly.

resource "null_resource" "stop_instance" {
  triggers = {
    instance_id = aws_instance.ctf_instance.id
  }

  provisioner "local-exec" {
    command = "aws ec2 stop-instances --instance-ids ${aws_instance.ctf_instance.id}"
  }
}

# Start EC2 instance
resource "null_resource" "start_instance" {
  triggers = {
    instance_id = aws_instance.ctf_instance.id
  }

  provisioner "local-exec" {
    command = "aws ec2 start-instances --instance-ids ${aws_instance.ctf_instance.id}"
  }
}

aws/main.tf:215

  • The AWS CLI commands lack proper error handling and don't specify the region. The commands should include the --region parameter to ensure they operate on the correct AWS region, and should use the when = destroy attribute to control when they execute. Additionally, there's no validation that the AWS CLI is installed or that the user has the necessary permissions.
  provisioner "local-exec" {
    command = "aws ec2 start-instances --instance-ids ${aws_instance.ctf_instance.id}"
  }

Comment on lines +66 to +79
## EC2 Instance Control
You can control the EC2 instance lifecycle (stop/start) using Terraform.
### Stop the EC2 instance
```bash
terraform apply -target=null_resource.stop_instance
Add this:
```md
### Start the EC2 instance
```bash
terraform apply -target=null_resource.start_instance
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documented commands will not achieve the intended behavior. Using terraform apply -target on these null_resource blocks will attempt to create or recreate them, not simply execute the commands. This approach is misleading because:

  1. The first time these resources are targeted, they will be created and the command will run
  2. Subsequent targeting will have no effect unless the triggers change
  3. To make the commands run again, users would need to taint the resources first

The documentation should either explain a different approach or clarify the actual behavior and prerequisites for using these commands.

Copilot uses AI. Check for mistakes.
aws/main.tf Outdated
Comment on lines 196 to 215
# Stop EC2 instance
resource "null_resource" "stop_instance" {
triggers = {
instance_id = aws_instance.ctf_instance.id
}

provisioner "local-exec" {
command = "aws ec2 stop-instances --instance-ids ${aws_instance.ctf_instance.id}"
}
}

# Start EC2 instance
resource "null_resource" "start_instance" {
triggers = {
instance_id = aws_instance.ctf_instance.id
}

provisioner "local-exec" {
command = "aws ec2 start-instances --instance-ids ${aws_instance.ctf_instance.id}"
}
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using local-exec provisioner with AWS CLI for instance lifecycle management is an anti-pattern. Terraform is designed to manage resource state declaratively, not imperatively through CLI commands. This approach:

  1. Bypasses Terraform's state management
  2. Creates drift between actual state and Terraform state
  3. Can cause race conditions during apply
  4. Doesn't leverage Terraform's native EC2 instance state management capabilities

Consider using the aws_ec2_instance_state resource (available in AWS provider 4.x+) or implementing a variable-driven approach where instance state is controlled through configuration.

This issue also appears in the following locations of the same file:

  • line 197
Suggested change
# Stop EC2 instance
resource "null_resource" "stop_instance" {
triggers = {
instance_id = aws_instance.ctf_instance.id
}
provisioner "local-exec" {
command = "aws ec2 stop-instances --instance-ids ${aws_instance.ctf_instance.id}"
}
}
# Start EC2 instance
resource "null_resource" "start_instance" {
triggers = {
instance_id = aws_instance.ctf_instance.id
}
provisioner "local-exec" {
command = "aws ec2 start-instances --instance-ids ${aws_instance.ctf_instance.id}"
}
# Control EC2 instance state declaratively
variable "ctf_instance_state" {
description = "Desired state of the CTF EC2 instance (e.g., running or stopped)"
type = string
default = "running"
}
resource "aws_ec2_instance_state" "ctf_instance_state" {
instance_id = aws_instance.ctf_instance.id
state = var.ctf_instance_state

Copilot uses AI. Check for mistakes.
aws/main.tf Outdated
Comment on lines 202 to 204
provisioner "local-exec" {
command = "aws ec2 stop-instances --instance-ids ${aws_instance.ctf_instance.id}"
}
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AWS CLI commands lack proper error handling and don't specify the region. The commands should include the --region parameter to ensure they operate on the correct AWS region, and should use the when = destroy attribute to control when they execute. Additionally, there's no validation that the AWS CLI is installed or that the user has the necessary permissions.

This issue also appears in the following locations of the same file:

  • line 213

Copilot uses AI. Check for mistakes.
Comment on lines +70 to +80
### Stop the EC2 instance
```bash
terraform apply -target=null_resource.stop_instance
Add this:
```md
### Start the EC2 instance
```bash
terraform apply -target=null_resource.start_instance
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation has malformed markdown structure. Lines 74-76 contain "Add this:" followed by an incomplete code fence, breaking the markdown formatting. The code blocks for stop and start commands are not properly closed, and line 74 appears to be an editing artifact that should be removed.

Copilot uses AI. Check for mistakes.
Comment on lines 64 to 82
## Security Note
## EC2 Instance Control
You can control the EC2 instance lifecycle (stop/start) using Terraform.
### Stop the EC2 instance
```bash
terraform apply -target=null_resource.stop_instance
Add this:
```md
### Start the EC2 instance
```bash
terraform apply -target=null_resource.start_instance
This lab uses password authentication for simplicity. In production, use key-based authentication.
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Security Note" section on line 82 is now orphaned from its original context. The new "EC2 Instance Control" section was inserted before the security note content was completed, separating the header from its body text about password authentication.

Copilot uses AI. Check for mistakes.
@Deepcode643
Copy link
Author

Hi, thanks for the review!

I’ve tested the EC2 start/stop functionality using the declarative
aws_ec2_instance_state approach.

Proof:

  1. Terraform apply creating the infrastructure
  2. Instance running in AWS console
  3. Terraform apply with:
    terraform apply -var="ctf_instance_state=stopped"
  4. Instance stopped in AWS console

Screenshots attached below.
WhatsApp Image 2026-01-22 at 14 36 44
WhatsApp Image 2026-01-22 at 14 36 54
Screenshot 2026-01-22 at 2 37 12 PM
Screenshot 2026-01-22 at 2 35 19 PM
Screenshot 2026-01-22 at 2 46 59 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants