The answer to this is to use Terraform to launch the EC2 instance you're running the software on rather than the Console. Terraform can run commands on the new instance to do what you want done on it, but only when invoked.
Without knowing the details, this is how I would recommend you solve this problem:
1. Create an AMI that has the software installed on it.
2. Write Terraform config (perhaps make it a module) that defines and launches an instance of that AMI, and executes the necessary commands and makes any changes to your AWS resources such as routing tables and security groups.
3. Use Terraform plan/apply to manage the setup.
As far as importing existing resources, this isn't difficult and if you use Terraform to manage them only needed once.
For example, lets assume a base directory of "terraform". We'll also assume for the example that you're using S3 to store state, using a bucket named "my.terraform.states". Inside the terraform directory create a directory called "networking". Inside the networking directory you store terraform configs for security groups, subnets, VPCs, etc.. Each directory under the terraform has its own remote state as defined in a "
backend.tf" file that looks something like this:
terraform {
backend "s3" {
key = "networking"
encrypt = true
region = "us-east-1"
}
}
This will allow you to reference the resources defined at the root and exported herein in other states. In here you could have a "
vpc.tf" file which defines your VPC, make sure it matches the existing one precisely. Then you import it as described at
https://www.terraform.io/docs/providers/aws/r/vpc.html. Now that it is stored in the state file for networking you can reference it via remote states. You could then follow the same process for subnets, security groups, etc.. Some people like to put each resource type in its own state, but that is up to you.
Once you've translated your existing AWS networking resources into a defined terraform state under "terraform/networking", you can turn your attention to your "router" definition. Assuming you've got an AMI ID properly tagged, you can use a data source to automatically pull the current AMI ID other than coding it into your Terraform config. For details on that, see
https://www.terraform.io/docs/providers/aws/d/ami.html. Let us assume you name this state "my_router", placed under "terraform" ("terraform/my_router/"). I prefer to define all of my data sources in "
data.tf", so I'd put it in that file.
From there you define your router instance, we'll call it "
my_router.tf". In there you use the ec2 instance resource. You use the data source for the AMI ID noted above to pull the AMI Id at plan/apply time, and define a remote state for "terraform/networking" in a "
remotes.tf" file to reference what exists in that state. For example it might look like this:
data "terraform_remote_state" "networking" {
backend = "s3"
config {
key = "networking"
encrypt = true
region = "us-east-1"
}
}
From there you can reference your network resources without hard-coding or additional importing or data filtering via "${data.terraform_remote_state.networking.SOMETHING}" where SOMETHING is the name of what you're after.
resource "aws_instance" "my_router" {
instance_type = "t2.micro"
region = "${data.terraform_remote_state.networking.region}"
provisioner "remote-exec" {
inline = [
"/usr/local/bin/some_script_here.sh}",
]
}
}
Notice we pull the AMI Id from the data source, and the region from our networking state.
The provisioner is an example of executing shell commands on the image when you create the instance. Any alterations to existing network resources can be made via standard Terraform rules, and you can specify the security group(s) to spin the instance up with in Terraform automatically as you can reference your remote states to get current data.
Taking the time to import your existing resources once and then reference them via state will save you a lot of complexity and headache later on, and doesn't take much time at all. A critical difference between that and data sources is that by defining them as Terraform managed resources you'll benefit from terraform's dependency tree. Using a data source doesn't let you say "this resource needs that one" - instead if the resource doesn't exist the data source query says it didn't find a match and it won't necessarily show in the plan depending on what it is and where.
Anyway, I hope that gets you down the path you need.
Cheers,
Bill