-
Notifications
You must be signed in to change notification settings - Fork 85
Add EC2 start/stop instance control using Terraform #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
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. |
There was a problem hiding this 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. Thelocal-execprovisioner runs when the resource is created, not when it's targeted. This means:
- Both resources will try to execute during initial apply, causing conflicts (trying to stop and start simultaneously)
- The triggers only cause recreation when the instance ID changes, not when you want to control the instance
- Using
terraform apply -targeton 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
--regionparameter to ensure they operate on the correct AWS region, and should use thewhen = destroyattribute 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}"
}
| ## 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 |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
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:
- The first time these resources are targeted, they will be created and the command will run
- Subsequent targeting will have no effect unless the triggers change
- 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.
aws/main.tf
Outdated
| # 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}" | ||
| } |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
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:
- Bypasses Terraform's state management
- Creates drift between actual state and Terraform state
- Can cause race conditions during apply
- 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
| # 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 |
aws/main.tf
Outdated
| provisioner "local-exec" { | ||
| command = "aws ec2 stop-instances --instance-ids ${aws_instance.ctf_instance.id}" | ||
| } |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
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
| ### 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 | ||
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
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.
| ## 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. |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
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.
|
Hi, thanks for the review! I’ve tested the EC2 start/stop functionality using the declarative Proof:
|





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