From dcaa7b5fd5663781cfa31cef0c8defdbfc590e8e Mon Sep 17 00:00:00 2001 From: Jill Rouleau Date: Thu, 19 Nov 2020 11:43:08 -0700 Subject: [PATCH 1/6] Create initial test suite for ec2_metadata_facts Create an instance, run metadata on the remote instance, and teardown. --- .../targets/ec2_metadata_facts/aliases | 2 +- .../ec2_metadata_facts/defaults/main.yml | 2 - .../targets/ec2_metadata_facts/meta/main.yml | 3 - .../ec2_metadata_facts/playbooks/setup.yml | 139 ++++++++++++++++++ .../ec2_metadata_facts/playbooks/teardown.yml | 70 +++++++++ .../playbooks/test_initial_metadata.yml | 12 ++ .../targets/ec2_metadata_facts/runme.sh | 14 ++ .../targets/ec2_metadata_facts/tasks/main.yml | 2 - .../ec2_metadata_facts/templates/inventory.j2 | 20 +++ .../targets/ec2_metadata_facts/vars/main.yml | 2 - 10 files changed, 256 insertions(+), 10 deletions(-) delete mode 100644 tests/integration/targets/ec2_metadata_facts/defaults/main.yml delete mode 100644 tests/integration/targets/ec2_metadata_facts/meta/main.yml create mode 100644 tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml create mode 100644 tests/integration/targets/ec2_metadata_facts/playbooks/teardown.yml create mode 100644 tests/integration/targets/ec2_metadata_facts/playbooks/test_initial_metadata.yml create mode 100755 tests/integration/targets/ec2_metadata_facts/runme.sh delete mode 100644 tests/integration/targets/ec2_metadata_facts/tasks/main.yml create mode 100644 tests/integration/targets/ec2_metadata_facts/templates/inventory.j2 delete mode 100644 tests/integration/targets/ec2_metadata_facts/vars/main.yml diff --git a/tests/integration/targets/ec2_metadata_facts/aliases b/tests/integration/targets/ec2_metadata_facts/aliases index 6e3860bee23..72a9fb4f570 100644 --- a/tests/integration/targets/ec2_metadata_facts/aliases +++ b/tests/integration/targets/ec2_metadata_facts/aliases @@ -1,2 +1,2 @@ cloud/aws -shippable/aws/group2 +shippable/aws/group4 diff --git a/tests/integration/targets/ec2_metadata_facts/defaults/main.yml b/tests/integration/targets/ec2_metadata_facts/defaults/main.yml deleted file mode 100644 index c25743914a6..00000000000 --- a/tests/integration/targets/ec2_metadata_facts/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# defaults file for test_ec2_facts diff --git a/tests/integration/targets/ec2_metadata_facts/meta/main.yml b/tests/integration/targets/ec2_metadata_facts/meta/main.yml deleted file mode 100644 index 1f64f1169a9..00000000000 --- a/tests/integration/targets/ec2_metadata_facts/meta/main.yml +++ /dev/null @@ -1,3 +0,0 @@ -dependencies: - - prepare_tests - - setup_ec2 diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml new file mode 100644 index 00000000000..18d43b046e1 --- /dev/null +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml @@ -0,0 +1,139 @@ +--- +- 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 }}" + + hosts: localhost + + collections: + - community.aws + + vars: + vpc_name: '{{ resource_prefix }}-vpc' + vpc_seed: '{{ resource_prefix }}' + vpc_cidr: '10.{{ 256 | random(seed=vpc_seed) }}.0.0/16' + subnet_cidr: '10.{{ 256 | random(seed=vpc_seed) }}.32.0/24' + ec2_ami_name: 'amzn2-ami-hvm-2.*-x86_64-gp2' + sshkey_file: '{{ resource_prefix }}_key' + + tasks: + + - name: Create an ssh key + shell: echo 'y' | ssh-keygen -P '' -f {{ sshkey_file }} + + - name: Get available AZs + aws_az_info: + filters: + region-name: "{{ aws_region }}" + register: az_info + + - name: Pick an AZ + set_fact: + availability_zone: "{{ az_info['availability_zones'][0]['zone_name'] }}" + + # ============================================================ + - name: create a VPC + ec2_vpc_net: + name: "{{ resource_prefix }}-vpc" + state: present + cidr_block: "{{ vpc_cidr }}" + tags: + Name: "{{ resource_prefix }}-vpc" + Description: "Created by ansible-test" + register: vpc_result + + - set_fact: + vpc_id: "{{ vpc_result.vpc.id }}" + + - name: create an internet gateway + ec2_vpc_igw: + vpc_id: "{{ vpc_id }}" + state: present + tags: + "Name": "{{ resource_prefix }}" + register: igw_result + + - name: create a subnet + ec2_vpc_subnet: + cidr: "{{ vpc_cidr }}" + az: "{{ availability_zone }}" + vpc_id: "{{ vpc_id }}" + tags: + Name: "{{ resource_prefix }}-vpc" + Description: "Created by ansible-test" + state: present + register: vpc_subnet_result + + - name: create a public route table + ec2_vpc_route_table: + vpc_id: "{{ vpc_id }}" + tags: + "Name": "{{ resource_prefix }}" + subnets: + - "{{ vpc_subnet_result.subnet.id }}" + routes: + - dest: 0.0.0.0/0 + gateway_id: "{{ igw_result.gateway_id }}" + register: public_route_table + + - name: create a security group + ec2_group: + name: "{{ resource_prefix }}-sg" + description: "Created by {{ resource_prefix }}" + rules: + - proto: tcp + ports: 22 + cidr_ip: 0.0.0.0/0 + state: present + vpc_id: "{{ vpc_result.vpc.id }}" + register: vpc_sg_result + + - name: Create a key + ec2_key: + name: '{{ resource_prefix }}' + key_material: "{{ lookup('file', sshkey_file ~ '.pub') }}" + state: present + register: ec2_key_result + + - name: Get a list of images + ec2_ami_info: + filters: + owner-alias: amazon + name: "amzn2-ami-minimal-hvm-*" + description: "Amazon Linux 2 AMI *" + register: images_info + + - name: Set facts to simplify use of extra resources + set_fact: + vpc_subnet_id: "{{ vpc_subnet_result.subnet.id }}" + vpc_sg_id: "{{ vpc_sg_result.group_id }}" + vpc_igw_id: "{{ igw_result.gateway_id }}" + vpc_route_table_id: "{{ public_route_table.route_table.id }}" + image_id: "{{ images_info.images | sort(attribute='creation_date') | reverse | first | json_query('image_id') }}" + ec2_key_name: "{{ ec2_key_result.key.name }}" + + - name: Create an instance to test with + ec2_instance: + name: "{{ resource_prefix }}-ec2-metadata-facts" + image_id: "{{ image_id }}" + vpc_subnet_id: "{{ vpc_subnet_id }}" + security_group: "{{ vpc_sg_id }}" + instance_type: t2.micro + key_name: "{{ ec2_key_name }}" + network: + assign_public_ip: true + wait: true + wait_timeout: 120 + register: ec2_instance + + - set_fact: + ec2_instance_id: "{{ ec2_instance.instances[0].instance_id }}" + + - name: Create inventory file + template: + src: ../templates/inventory.j2 + dest: ../inventory + diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/teardown.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/teardown.yml new file mode 100644 index 00000000000..cda4043ca4a --- /dev/null +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/teardown.yml @@ -0,0 +1,70 @@ +--- +- 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 }}" + + hosts: localhost + + collections: + - community.aws + + tasks: + # ============================================================ + + - name: terminate the instance + ec2_instance: + state: absent + instance_ids: + - "{{ ec2_instance_id }}" + wait: True + ignore_errors: true + retries: 5 + + - name: remove ssh key + ec2_key: + name: "{{ ec2_key_name }}" + state: absent + ignore_errors: true + + - name: remove the security group + ec2_group: + group_id: "{{ vpc_sg_id }}" + state: absent + ignore_errors: true + retries: 5 + + - name: remove the public route table + ec2_vpc_route_table: + vpc_id: "{{ vpc_id }}" + route_table_id: "{{ vpc_route_table_id }}" + lookup: id + state: absent + ignore_errors: true + retries: 5 + + - name: remove the subnet + ec2_vpc_subnet: + cidr: "{{ vpc_cidr }}" + az: "{{ availability_zone }}" + vpc_id: "{{ vpc_id }}" + state: absent + ignore_errors: true + retries: 5 + + - name: remove the internet gateway + ec2_vpc_igw: + vpc_id: "{{ vpc_id }}" + state: absent + ignore_errors: true + retries: 5 + + - name: remove the VPC + ec2_vpc_net: + name: "{{ resource_prefix }}-vpc" + cidr_block: "{{ vpc_cidr }}" + state: absent + ignore_errors: true + retries: 5 diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/test_initial_metadata.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/test_initial_metadata.yml new file mode 100644 index 00000000000..6c4edd12214 --- /dev/null +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/test_initial_metadata.yml @@ -0,0 +1,12 @@ +--- +- hosts: testhost + tasks: + - amazon.aws.ec2_metadata_facts: + + - name: Assert initial metadata for the instance + assert: + that: + - ansible_ec2_ami_id == image_id + - ansible_ec2_placement_availability_zone == "{{ availability_zone }}" + - ansible_ec2_security_groups == "{{ resource_prefix }}-sg" + - ansible_ec2_user_data == "None" diff --git a/tests/integration/targets/ec2_metadata_facts/runme.sh b/tests/integration/targets/ec2_metadata_facts/runme.sh new file mode 100755 index 00000000000..58bdc7bd128 --- /dev/null +++ b/tests/integration/targets/ec2_metadata_facts/runme.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -eux +export ANSIBLE_HOST_KEY_CHECKING=False +export ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null' + +# create test resources and inventory +ansible-playbook playbooks/setup.yml -c local "$@" + +# test ec2_instance_metadata +ansible-playbook playbooks/test_initial_metadata.yml -i inventory "$@" + +# teardown +ansible-playbook playbooks/teardown.yml -i inventory -c local "$@" diff --git a/tests/integration/targets/ec2_metadata_facts/tasks/main.yml b/tests/integration/targets/ec2_metadata_facts/tasks/main.yml deleted file mode 100644 index 8ea9fcf1f85..00000000000 --- a/tests/integration/targets/ec2_metadata_facts/tasks/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# tasks file for test_ec2_facts diff --git a/tests/integration/targets/ec2_metadata_facts/templates/inventory.j2 b/tests/integration/targets/ec2_metadata_facts/templates/inventory.j2 new file mode 100644 index 00000000000..8aad1020dc4 --- /dev/null +++ b/tests/integration/targets/ec2_metadata_facts/templates/inventory.j2 @@ -0,0 +1,20 @@ +[testhost] +"{{ ec2_instance.instances[0].public_ip_address }}" + +[testhost:vars] +ansible_user=ec2-user +ansible_ssh_private_key_file="playbooks/{{ sshkey_file }}" +ansible_python_interpreter=/usr/bin/env python + +[all:vars] +# Template vars that will need to be used in used in tests and teardown +vpc_id="{{ vpc_id }}" +vpc_subnet_id="{{ vpc_subnet_id }}" +vpc_sg_id="{{ vpc_sg_id }}" +vpc_cidr="{{ vpc_cidr }}" +vpc_igw="{{ vpc_igw_id }}" +vpc_route_table_id="{{ vpc_route_table_id }}" +ec2_key_name="{{ ec2_key_name }}" +availability_zone="{{ availability_zone }}" +image_id="{{ image_id }}" +ec2_instance_id="{{ ec2_instance_id }}" diff --git a/tests/integration/targets/ec2_metadata_facts/vars/main.yml b/tests/integration/targets/ec2_metadata_facts/vars/main.yml deleted file mode 100644 index bb8f6c18752..00000000000 --- a/tests/integration/targets/ec2_metadata_facts/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for test_ec2_facts From 18fc84f459ce022c317f306287c4733f76d48a04 Mon Sep 17 00:00:00 2001 From: jillr Date: Tue, 1 Dec 2020 23:41:43 +0000 Subject: [PATCH 2/6] sanity fix --- tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml index 18d43b046e1..e6f19972cb8 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml @@ -136,4 +136,3 @@ template: src: ../templates/inventory.j2 dest: ../inventory - From de0cf476dde0f07933632733a337efcc0f506743 Mon Sep 17 00:00:00 2001 From: jillr Date: Wed, 2 Dec 2020 17:14:44 +0000 Subject: [PATCH 3/6] Trap cleanup so it always runs Add a wait_for_connection to test playbook Some minor cleanup --- .../targets/ec2_metadata_facts/playbooks/setup.yml | 2 +- ...{test_initial_metadata.yml => test_metadata.yml} | 4 ++++ .../integration/targets/ec2_metadata_facts/runme.sh | 13 ++++++++++--- 3 files changed, 15 insertions(+), 4 deletions(-) rename tests/integration/targets/ec2_metadata_facts/playbooks/{test_initial_metadata.yml => test_metadata.yml} (82%) diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml index e6f19972cb8..fb602cc54f7 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml @@ -126,7 +126,7 @@ network: assign_public_ip: true wait: true - wait_timeout: 120 + wait_timeout: 180 register: ec2_instance - set_fact: diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/test_initial_metadata.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml similarity index 82% rename from tests/integration/targets/ec2_metadata_facts/playbooks/test_initial_metadata.yml rename to tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml index 6c4edd12214..3121c644460 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/test_initial_metadata.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml @@ -1,6 +1,10 @@ --- - hosts: testhost tasks: + - name: Wait for EC2 to be available + wait_for_connection: + delay: 300 + - amazon.aws.ec2_metadata_facts: - name: Assert initial metadata for the instance diff --git a/tests/integration/targets/ec2_metadata_facts/runme.sh b/tests/integration/targets/ec2_metadata_facts/runme.sh index 58bdc7bd128..a1ab9e0bb54 100755 --- a/tests/integration/targets/ec2_metadata_facts/runme.sh +++ b/tests/integration/targets/ec2_metadata_facts/runme.sh @@ -4,11 +4,18 @@ set -eux export ANSIBLE_HOST_KEY_CHECKING=False export ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null' +CMD_ARGS=("$@") + +# Destroy Environment +cleanup() { + # teardown + ansible-playbook playbooks/teardown.yml -i inventory -c local "${CMD_ARGS[@]}" +} +trap "cleanup" EXIT + # create test resources and inventory ansible-playbook playbooks/setup.yml -c local "$@" # test ec2_instance_metadata -ansible-playbook playbooks/test_initial_metadata.yml -i inventory "$@" +ansible-playbook playbooks/test_metadata.yml -i inventory "$@" -# teardown -ansible-playbook playbooks/teardown.yml -i inventory -c local "$@" From 99e66fc5dbb33a2bde650f2280c1454eedb1f3c4 Mon Sep 17 00:00:00 2001 From: jillr Date: Thu, 3 Dec 2020 00:14:41 +0000 Subject: [PATCH 4/6] set tmp dirs for ec2 instance general cleanup --- .../targets/ec2_metadata_facts/playbooks/setup.yml | 4 ++-- .../targets/ec2_metadata_facts/playbooks/test_metadata.yml | 4 ---- tests/integration/targets/ec2_metadata_facts/runme.sh | 6 ++++-- .../targets/ec2_metadata_facts/templates/inventory.j2 | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml index fb602cc54f7..343063247e0 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml @@ -22,7 +22,7 @@ tasks: - name: Create an ssh key - shell: echo 'y' | ssh-keygen -P '' -f {{ sshkey_file }} + shell: echo 'y' | ssh-keygen -P '' -f ../{{ sshkey_file }} - name: Get available AZs aws_az_info: @@ -94,7 +94,7 @@ - name: Create a key ec2_key: name: '{{ resource_prefix }}' - key_material: "{{ lookup('file', sshkey_file ~ '.pub') }}" + key_material: "{{ lookup('file', '../' ~ sshkey_file ~ '.pub') }}" state: present register: ec2_key_result diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml index 3121c644460..6c4edd12214 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml @@ -1,10 +1,6 @@ --- - hosts: testhost tasks: - - name: Wait for EC2 to be available - wait_for_connection: - delay: 300 - - amazon.aws.ec2_metadata_facts: - name: Assert initial metadata for the instance diff --git a/tests/integration/targets/ec2_metadata_facts/runme.sh b/tests/integration/targets/ec2_metadata_facts/runme.sh index a1ab9e0bb54..e67405676bd 100755 --- a/tests/integration/targets/ec2_metadata_facts/runme.sh +++ b/tests/integration/targets/ec2_metadata_facts/runme.sh @@ -17,5 +17,7 @@ trap "cleanup" EXIT ansible-playbook playbooks/setup.yml -c local "$@" # test ec2_instance_metadata -ansible-playbook playbooks/test_metadata.yml -i inventory "$@" - +ansible-playbook playbooks/test_metadata.yml -i inventory \ + -e local_tmp=/tmp/ansible-local \ + -e remote_tmp=/tmp/ansible-remote \ + "$@" diff --git a/tests/integration/targets/ec2_metadata_facts/templates/inventory.j2 b/tests/integration/targets/ec2_metadata_facts/templates/inventory.j2 index 8aad1020dc4..186edb8f52f 100644 --- a/tests/integration/targets/ec2_metadata_facts/templates/inventory.j2 +++ b/tests/integration/targets/ec2_metadata_facts/templates/inventory.j2 @@ -3,7 +3,7 @@ [testhost:vars] ansible_user=ec2-user -ansible_ssh_private_key_file="playbooks/{{ sshkey_file }}" +ansible_ssh_private_key_file="{{ sshkey_file }}" ansible_python_interpreter=/usr/bin/env python [all:vars] From 24045e36ea99a0ed5b70db885891bbd374ff7387 Mon Sep 17 00:00:00 2001 From: jillr Date: Thu, 3 Dec 2020 17:01:40 +0000 Subject: [PATCH 5/6] wait longer --- .../integration/targets/ec2_metadata_facts/playbooks/setup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml index 343063247e0..39b129eeb1b 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml @@ -126,7 +126,7 @@ network: assign_public_ip: true wait: true - wait_timeout: 180 + wait_timeout: 300 register: ec2_instance - set_fact: From dcd93b201bb1a22579bb8ba93887cde9b2896a36 Mon Sep 17 00:00:00 2001 From: jillr Date: Thu, 3 Dec 2020 18:09:41 +0000 Subject: [PATCH 6/6] run non_local; disabled coverage --- tests/integration/targets/ec2_metadata_facts/aliases | 1 + .../targets/ec2_metadata_facts/playbooks/setup.yml | 3 +++ .../targets/ec2_metadata_facts/playbooks/test_metadata.yml | 4 ++++ tests/integration/targets/ec2_metadata_facts/runme.sh | 1 - 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/integration/targets/ec2_metadata_facts/aliases b/tests/integration/targets/ec2_metadata_facts/aliases index 72a9fb4f570..412ce2c05d2 100644 --- a/tests/integration/targets/ec2_metadata_facts/aliases +++ b/tests/integration/targets/ec2_metadata_facts/aliases @@ -1,2 +1,3 @@ +non_local cloud/aws shippable/aws/group4 diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml index 39b129eeb1b..df73cf79328 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml @@ -87,6 +87,9 @@ - proto: tcp ports: 22 cidr_ip: 0.0.0.0/0 + - proto: icmp + from_port: -1 + to_port: -1 state: present vpc_id: "{{ vpc_result.vpc.id }}" register: vpc_sg_result diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml index 6c4edd12214..fd49844b72d 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml @@ -1,6 +1,10 @@ --- - hosts: testhost tasks: + + - name: Wait for EC2 to be available + wait_for_connection: + - amazon.aws.ec2_metadata_facts: - name: Assert initial metadata for the instance diff --git a/tests/integration/targets/ec2_metadata_facts/runme.sh b/tests/integration/targets/ec2_metadata_facts/runme.sh index e67405676bd..6f2bc466032 100755 --- a/tests/integration/targets/ec2_metadata_facts/runme.sh +++ b/tests/integration/targets/ec2_metadata_facts/runme.sh @@ -8,7 +8,6 @@ CMD_ARGS=("$@") # Destroy Environment cleanup() { - # teardown ansible-playbook playbooks/teardown.yml -i inventory -c local "${CMD_ARGS[@]}" } trap "cleanup" EXIT