From 74ee7042878004f7f6080570db2a203e55af7385 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 20 Nov 2024 18:21:00 -0800 Subject: [PATCH] add integration tests --- roles/ec2_instance_create/README.md | 9 +- roles/ec2_instance_create/tasks/main.yml | 53 ++++----- .../targets/test_ec2_instance_create/aliases | 2 + .../defaults/main.yml | 17 +++ .../test_ec2_instance_create/tasks/main.yml | 21 ++++ .../test_ec2_instance_create/tasks/setup.yml | 49 ++++++++ .../tasks/teardown.yml | 25 ++++ .../tasks/test_ec2_only.yml | 44 +++++++ .../tasks/test_ec2_with_igw_sg_eip.yml | 107 ++++++++++++++++++ 9 files changed, 297 insertions(+), 30 deletions(-) create mode 100644 tests/integration/targets/test_ec2_instance_create/aliases create mode 100644 tests/integration/targets/test_ec2_instance_create/defaults/main.yml create mode 100644 tests/integration/targets/test_ec2_instance_create/tasks/main.yml create mode 100644 tests/integration/targets/test_ec2_instance_create/tasks/setup.yml create mode 100644 tests/integration/targets/test_ec2_instance_create/tasks/teardown.yml create mode 100644 tests/integration/targets/test_ec2_instance_create/tasks/test_ec2_only.yml create mode 100644 tests/integration/targets/test_ec2_instance_create/tasks/test_ec2_with_igw_sg_eip.yml diff --git a/roles/ec2_instance_create/README.md b/roles/ec2_instance_create/README.md index 94c6bf07..05f22b7e 100644 --- a/roles/ec2_instance_create/README.md +++ b/roles/ec2_instance_create/README.md @@ -40,11 +40,18 @@ The following variables can be set in the role to customize EC2 instance creatio * **ec2_instance_create_associate_eip**: (Optional) Whether to create an Elastic IP (EIP) and associate it with the EC2 instance. Default is `false`. + If set to `true` and provided VPC doesn't have an Internet Gateway (IGW) attached, please set `ec2_instance_create_associate_igw` to true to avoid failure due to VPC not having IGW attached. + +* **ec2_instance_create_eip_tags**: (Optional) + Tags to assign to the elastic IP. * **ec2_instance_create_associate_igw**: (Optional) Whether to create and associate an internet gateway with the EC2 instance. Default is `false`. If set to `true`, an internet gateway will be created or associated with the instance. +* **ec2_instance_create_igw_tags**: (Optional) + Tags to assign to the internet gateway. + * **ec2_instance_create_associate_external_sg**: (Optional) Whether to create and associate a security group with the EC2 instance for external access. Default is `false`. If set to `true`, a security group will be created or associated with the instance. @@ -101,7 +108,7 @@ Here’s an example of how to use the role in a playbook. # Optionally, enable Elastic IP association ec2_instance_create_associate_eip: true ec2_instance_create_eip_tags: - Component: my-test-eip + Component: my-custom-eip Environment: Testing License diff --git a/roles/ec2_instance_create/tasks/main.yml b/roles/ec2_instance_create/tasks/main.yml index 780f3388..713e5cb3 100644 --- a/roles/ec2_instance_create/tasks/main.yml +++ b/roles/ec2_instance_create/tasks/main.yml @@ -2,7 +2,6 @@ - name: Run 'ec2_instance_create' role module_defaults: group/aws: "{{ aws_setup_credentials__output }}" - block: - name: Create EC2 instance with provided configuration amazon.aws.ec2_instance: @@ -19,12 +18,13 @@ - name: Create security group if enabled when: ec2_instance_create_associate_external_sg is true block: - - name: Define security group with default SSH access rule + - name: Define security group amazon.aws.ec2_security_group: name: "{{ ec2_instance_create_external_sg_name | default('default-external-sg') }}" description: "{{ ec2_instance_create_external_sg_description | default('Security group for external access') }}" vpc_id: "{{ ec2_instance_create_vpc_id }}" rules: "{{ ec2_instance_create_external_sg_rules }}" + tags: "{{ ec2_instance_create_sg_tags | default(omit) }}" register: ec2_group_creation - name: Associate security group with EC2 instance @@ -33,26 +33,10 @@ - "{{ ec2_instance.instance_ids[0] }}" security_groups: - "{{ ec2_instance_create_external_sg_name | default('default-external-sg') }}" + vpc_subnet_id: "{{ ec2_instance_create_vpc_subnet_id }}" register: ec2_instance_associate_external_sg - - name: Create and associate Elastic IP if enabled - when: ec2_instance_create_associate_eip is true - block: - - name: Allocate and associate Elastic IP - amazon.aws.ec2_eip: - device_id: "{{ ec2_instance.instance_ids[0] }}" - state: present - release_on_disassociation: true - tags: "{{ ec2_instance_create_tags | default(omit) }}" - register: instance_eip - - - name: Output details of associated Elastic IP - ansible.builtin.debug: - msg: - - "Elastic IP {{ instance_eip.public_ip }} created and associated with EC2 instance {{ ec2_instance.instance_ids[0] }}" - - "Details: {{ instance_eip }}" - - - name: Create and Attach Internet Gateway if required + - name: Create and Attach Internet Gateway if enabled when: ec2_instance_create_associate_igw is true block: - name: Create an Internet Gateway @@ -60,26 +44,37 @@ region: "{{ ec2_instance_create_aws_region }}" vpc_id: "{{ ec2_instance_create_vpc_id }}" state: present + tags: "{{ ec2_instance_create_igw_tags | default(omit) }}" register: internet_gateway - - name: Attach Internet Gateway to VPC - amazon.aws.ec2_vpc_igw: - region: "{{ ec2_instance_create_aws_region }}" - vpc_id: "{{ ec2_instance_create_vpc_id }}" - internet_gateway_id: "{{ internet_gateway.id }}" - state: attached - - name: Modify the route table to route internet traffic to Internet Gateway amazon.aws.ec2_vpc_route_table: region: "{{ ec2_instance_create_aws_region }}" vpc_id: "{{ ec2_instance_create_vpc_id }}" routes: - dest: "0.0.0.0/0" - gateway_id: "{{ internet_gateway.id }}" + gateway_id: "{{ internet_gateway.gateway_id }}" + state: present + + - name: Create and associate Elastic IP if enabled + when: ec2_instance_create_associate_eip is true + block: + - name: Allocate and associate Elastic IP + amazon.aws.ec2_eip: + device_id: "{{ ec2_instance.instance_ids[0] }}" state: present + release_on_disassociation: true + tags: "{{ ec2_instance_create_eip_tags | default(omit) }}" + register: instance_eip + + - name: Get EC2 instance info + amazon.aws.ec2_instance_info: + instance_ids: "{{ ec2_instance.instance_ids[0] }}" + region: "{{ ec2_instance_create_aws_region }}" + register: _ec2_instance - name: Output details of the created EC2 instance ansible.builtin.debug: msg: - "EC2 instance {{ ec2_instance.instance_ids[0] }} created successfully" - - "Instance details: {{ ec2_instance.instances[0] }}" + - "Instance details: {{ _ec2_instance.instances[0] }}" diff --git a/tests/integration/targets/test_ec2_instance_create/aliases b/tests/integration/targets/test_ec2_instance_create/aliases new file mode 100644 index 00000000..5f4238a0 --- /dev/null +++ b/tests/integration/targets/test_ec2_instance_create/aliases @@ -0,0 +1,2 @@ +cloud/aws +role/ec2_instance_create diff --git a/tests/integration/targets/test_ec2_instance_create/defaults/main.yml b/tests/integration/targets/test_ec2_instance_create/defaults/main.yml new file mode 100644 index 00000000..0f87eb10 --- /dev/null +++ b/tests/integration/targets/test_ec2_instance_create/defaults/main.yml @@ -0,0 +1,17 @@ +--- +aws_security_token: "{{ security_token | default(omit) }}" +resource_prefix: mandkulkt1 + +# VPC and Subnet Configuration +vpc_name: "{{ resource_prefix }}-vpc" +test_vpc_name: 'vpc-{{ resource_prefix }}' +test_vpc_cidr: '101.{{ 255 | random(seed=resource_prefix) }}.0.0/16' +test_subnet_cidr: '101.{{ 255 | random(seed=resource_prefix) }}.0.0/24' + +# EC2 Instance Configuration +ec2_instance_type: t2.micro +ec2_key_name: "{{ resource_prefix }}-ec2-key" # SSH key name for EC2 instances + +# External Security Group Configuration +external_sg_name: "{{ resource_prefix }}-external-sg" +external_sg_description: "External Security Group for EC2" diff --git a/tests/integration/targets/test_ec2_instance_create/tasks/main.yml b/tests/integration/targets/test_ec2_instance_create/tasks/main.yml new file mode 100644 index 00000000..21dde032 --- /dev/null +++ b/tests/integration/targets/test_ec2_instance_create/tasks/main.yml @@ -0,0 +1,21 @@ +--- +- name: Integration tests for ec2_networking_resources role + module_defaults: + group/aws: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token | default(omit) }}" + region: "{{ aws_region }}" + block: + - name: Create resources required for test + include_tasks: setup.yml + + - name: Run tests for case 1 - EC2 with no external sg, igw, eip + include_tasks: tasks/test_ec2_only.yml + + - name: Run tests for case 2 - EC2 with external sg, igw, eip + include_tasks: tasks/test_ec2_with_igw_sg_eip.yml + + always: + - name: Delete resources required for test + ansible.builtin.include_tasks: teardown.yml diff --git a/tests/integration/targets/test_ec2_instance_create/tasks/setup.yml b/tests/integration/targets/test_ec2_instance_create/tasks/setup.yml new file mode 100644 index 00000000..1ec44460 --- /dev/null +++ b/tests/integration/targets/test_ec2_instance_create/tasks/setup.yml @@ -0,0 +1,49 @@ +--- +- name: Setup + block: + - name: Get AMI image ID using filters + amazon.aws.ec2_ami_info: + region: "{{ aws_region }}" + filters: + architecture: x86_64 + # CentOS Community Platform Engineering (CPE) + owner-id: "125523088429" + virtualization-type: hvm + root-device-type: ebs + name: Fedora-Cloud-Base-* + register: images + # very spammy + no_log: true + + - name: Create vpc to work in + amazon.aws.ec2_vpc_net: + cidr_block: "{{ test_vpc_cidr }}" + name: "{{ test_vpc_name }}" + state: present + region: "{{ aws_region }}" + register: vpc + + - name: Define VPC id + ansible.builtin.set_fact: + test_vpc_id: "{{ vpc.vpc.id }}" + + - name: Create EC2 subnet + amazon.aws.ec2_vpc_subnet: + vpc_id: "{{ test_vpc_id }}" + cidr: "{{ test_subnet_cidr }}" + az: "{{ aws_region }}a" + region: "{{ aws_region }}" + register: subnet + + - name: Create a key + amazon.aws.ec2_key: + name: "{{ ec2_key_name }}" + state: present + region: "{{ aws_region }}" + register: ec2_key_result + + - name: Set facts for test resources + ansible.builtin.set_fact: + image_id: "ami-0bcda2433f3dabc41" #"{{ images.images.0.image_id }}" + subnet_id: "{{ subnet.subnet.id }}" + vpc_id: "{{ vpc.vpc.id }}" diff --git a/tests/integration/targets/test_ec2_instance_create/tasks/teardown.yml b/tests/integration/targets/test_ec2_instance_create/tasks/teardown.yml new file mode 100644 index 00000000..f1c60a95 --- /dev/null +++ b/tests/integration/targets/test_ec2_instance_create/tasks/teardown.yml @@ -0,0 +1,25 @@ +--- +- name: Teardown + block: + - name: Delete Subnets + amazon.aws.ec2_vpc_subnet: + vpc_id: "{{ test_vpc_id }}" + cidr: "{{ test_subnet_cidr }}" + region: "{{ aws_region }}" + state: absent + ignore_errors: true + + - name: Delete a VPC + amazon.aws.ec2_vpc_net: + cidr_block: "{{ test_vpc_cidr }}" + vpc_id: "{{ test_vpc_id }}" + region: "{{ aws_region }}" + state: absent + ignore_errors: true + + - name: Delete a key + amazon.aws.ec2_key: + name: "{{ resource_prefix }}-ec2-key" + region: "{{ aws_region }}" + state: absent + ignore_errors: true \ No newline at end of file diff --git a/tests/integration/targets/test_ec2_instance_create/tasks/test_ec2_only.yml b/tests/integration/targets/test_ec2_instance_create/tasks/test_ec2_only.yml new file mode 100644 index 00000000..54f419ec --- /dev/null +++ b/tests/integration/targets/test_ec2_instance_create/tasks/test_ec2_only.yml @@ -0,0 +1,44 @@ +--- +- block: + - name: Create EC2 instance with no external SG, no IGW, no EIP + ansible.builtin.include_role: + name: cloud.aws_ops.ec2_instance_create + vars: + ec2_instance_create_aws_region: "{{ aws_region }}" + ec2_instance_create_instance_name: "only-ec2-{{ resource_prefix }}" + ec2_instance_create_instance_type: "{{ ec2_instance_type }}" + ec2_instance_create_ami_id: "{{ image_id }}" + ec2_instance_create_vpc_subnet_id: "{{ subnet_id }}" + ec2_instance_create_key_name: "{{ ec2_key_name }}" + ec2_instance_create_associate_external_sg: false + ec2_instance_create_associate_eip: false + ec2_instance_create_associate_igw: false + ec2_instance_create_tags: + Environment: Testing + Name: "{{ resource_prefix }}-instance" + + - name: Get EC2 instance info + amazon.aws.ec2_instance_info: + filters: + "tag:Name": "only-ec2-{{ resource_prefix }}" + register: _ec2_instance + until: _ec2_instance.instances[0].state.name == 'running' + retries: 12 + delay: 5 + + - name: Validate EC2 creation (no SG, no IGW, no EIP) + ansible.builtin.assert: + that: + - _ec2_instance.instances | length == 1 + - _ec2_instance.instances[0].state.name == 'running' + - _ec2_instance.instances[0].tags.Name == "only-ec2-{{ resource_prefix }}" + - _ec2_instance.instances[0].network_interfaces[0].groups[0].group_name == "default" + - _ec2_instance.instances[0].key_name == ec2_key_name + + always: + - name: Terminate EC2 instance + amazon.aws.ec2_instance: + state: absent + instance_ids: "{{ _ec2_instance.instances[0].instance_id }}" + wait: true + ignore_errors: true diff --git a/tests/integration/targets/test_ec2_instance_create/tasks/test_ec2_with_igw_sg_eip.yml b/tests/integration/targets/test_ec2_instance_create/tasks/test_ec2_with_igw_sg_eip.yml new file mode 100644 index 00000000..500a9f75 --- /dev/null +++ b/tests/integration/targets/test_ec2_instance_create/tasks/test_ec2_with_igw_sg_eip.yml @@ -0,0 +1,107 @@ +--- +- block: + - name: Create EC2 instance with no external SG, no IGW, no EIP + ansible.builtin.include_role: + name: cloud.aws_ops.ec2_instance_create + vars: + ec2_instance_create_aws_region: "{{ aws_region }}" + ec2_instance_create_instance_name: "ec2-all-enabled-{{ resource_prefix }}" + ec2_instance_create_instance_type: "{{ ec2_instance_type }}" + ec2_instance_create_ami_id: "{{ image_id }}" + ec2_instance_create_vpc_subnet_id: "{{ subnet_id }}" + ec2_instance_create_key_name: "{{ ec2_key_name }}" + ec2_instance_create_vpc_id: "{{ vpc_id }}" + ec2_instance_create_tags: + Environment: Testing + Name: "{{ resource_prefix }}-instance" + + # Optional: external security group + ec2_instance_create_associate_external_sg: true + ec2_instance_create_external_sg_name: "{{ external_sg_name }}" + ec2_instance_create_external_sg_description: "{{ external_sg_description }}" + ec2_instance_create_external_sg_rules: + - proto: tcp + ports: 22 + cidr_ip: 10.0.1.0/16 + - proto: tcp + ports: 8000 + cidr_ip: 10.0.1.0/16 + ec2_instance_create_sg_tags: + Environment: Testing + Name: "{{ resource_prefix }}-sg" + + # Optional: EIP + ec2_instance_create_associate_eip: true + ec2_instance_create_eip_tags: + Environment: Testing + Name: "{{ resource_prefix }}-eip" + + # Optional: Internet Gateway + ec2_instance_create_associate_igw: true + ec2_instance_create_igw_tags: + Environment: Testing + Name: "{{ resource_prefix }}-igw" + + - name: Get EC2 instance info + amazon.aws.ec2_instance_info: + filters: + "tag:Name": "ec2-all-enabled-{{ resource_prefix }}" + register: _ec2_instance + until: _ec2_instance.instances[0].state.name == 'running' + retries: 12 + delay: 5 + + - name: Gather information about Internet Gateway + amazon.aws.ec2_vpc_igw_info: + filters: + "tag:Name": "{{ resource_prefix }}-igw" + register: igw_info + + - name: Gather information about security group + amazon.aws.ec2_security_group_info: + filters: + "tag:Name": "{{ resource_prefix }}-sg" + register: sg_info + + - name: Gather information about route table + amazon.aws.ec2_vpc_route_table_info: + filters: + vpc-id: "{{ vpc_id }}" + register: rtb_info + + - name: Validate EC2 creation (SG, IGW, EIP) + ansible.builtin.assert: + that: + - _ec2_instance.instances | length == 1 + - _ec2_instance.instances[0].state.name == 'running' + - _ec2_instance.instances[0].tags.Name == "ec2-all-enabled-{{ resource_prefix }}" + - _ec2_instance.instances[0].network_interfaces[0].groups[0].group_name == "{{ external_sg_name }}" + - _ec2_instance.instances[0].key_name == ec2_key_name + + always: + - name: Terminate EC2 instance + amazon.aws.ec2_instance: + state: absent + instance_ids: "{{ _ec2_instance.instances[0].instance_id }}" + wait: true + ignore_errors: true + + - name: Delete Internet gateway ensuring attached VPC is correct + amazon.aws.ec2_vpc_igw: + state: absent + internet_gateway_id: "{{ igw_info.internet_gateways[0].internet_gateway_id }}" + vpc_id: "{{ vpc_id }}" + ignore_errors: true + + - name: Delete security group + amazon.aws.ec2_security_group: + group_id: "{{ sg_info.security_groups[0].group_id }}" + state: absent + ignore_errors: true + + - name: Delete route table + amazon.aws.ec2_vpc_route_table: + vpc_id: "{{ vpc_id }}" + route_table_id: "{{ rtb_info.route_tables[0].id }}" + lookup: id + state: absent