diff options
author | Jacob McGill <jacob@networktocode.com> | 2017-11-17 16:19:13 +0100 |
---|---|---|
committer | Dag Wieers <dag@wieers.com> | 2017-11-17 16:19:13 +0100 |
commit | 5747bf34d1f363cb5ed441e36bd782cc39c439db (patch) | |
tree | e7f752ce8adc308e54df3d24bae76b408b89be20 | |
parent | Handle virtual machine config element gracefully (#32924) (diff) | |
download | ansible-5747bf34d1f363cb5ed441e36bd782cc39c439db.tar.xz ansible-5747bf34d1f363cb5ed441e36bd782cc39c439db.zip |
Network ACI: Add integration tests for several module (#33016)
26 files changed, 2482 insertions, 0 deletions
diff --git a/test/integration/targets/aci_ap/aliases b/test/integration/targets/aci_ap/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_ap/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_ap/tasks/main.yml b/test/integration/targets/aci_ap/tasks/main.yml new file mode 100644 index 0000000000..eadced8d90 --- /dev/null +++ b/test/integration/targets/aci_ap/tasks/main.yml @@ -0,0 +1,164 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: create ap - check mode works + aci_ap: &aci_ap_present + <<: *aci_tenant_present + ap: anstest + description: Ansible Test + check_mode: yes + register: ap_present_check_mode + +- name: create ap - creation works + aci_ap: + <<: *aci_ap_present + register: ap_present + +- name: create ap - extra for query + aci_ap: + <<: *aci_tenant_present + ap: anstest2 + +- name: create ap - idempotency works + aci_ap: + <<: *aci_ap_present + register: ap_present_idempotent + +- name: update ap - update works + aci_ap: + <<: *aci_ap_present + description: Ansible Test Update + register: ap_present_update + +- name: create ap - creation works + aci_ap: + <<: *aci_tenant_present + ignore_errors: yes + register: ap_present_missing_param + +- name: present asserts + assert: + that: + - ap_present_check_mode.changed == true + - ap_present.changed == true + - ap_present.existing == [] + - ap_present.config == ap_present_check_mode.config + - 'ap_present.config == {"fvAp": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' + - ap_present_idempotent.changed == false + - ap_present_idempotent.existing != [] + - ap_present_idempotent.config == {} + - ap_present_update.changed == true + - 'ap_present_update.config.fvAp.attributes == {"descr": "Ansible Test Update"}' + - ap_present_missing_param.failed == true + - 'ap_present_missing_param.msg == "state is present but the following are missing: ap"' + +- name: get ap - query specific ap + aci_ap: &aci_ap_query + <<: *aci_ap_present + state: query + register: query_ap + +- name: get all ap for tenant - query tenant aps + aci_ap: + <<: *aci_ap_query + ap: "{{ fakevar | default(omit) }}" + register: query_ap_tenant + +- name: get all ap by name - query ap name + aci_ap: + <<: *aci_ap_query + tenant: "{{ fakevar | default(omit) }}" + register: query_ap_ap + +- name: get all aps - query general + aci_ap: + <<: *aci_ap_query + tenant: "{{ fakevar | default(omit) }}" + ap: "{{ fakevar | default(omit) }}" + register: query_all + +- name: query assertions + assert: + that: + - query_ap.changed == false + - query_ap.existing | length == 1 + - 'query_ap.existing.0.fvAp.attributes.name == "anstest"' + - '"tn-anstest/ap-anstest.json" in query_ap.url' + - query_ap_tenant.changed == false + - query_ap_tenant.existing | length == 1 + - query_ap_tenant.existing.0.fvTenant.children | length == 2 + - '"rsp-subtree-class=fvAp" in query_ap_tenant.filter_string' + - '"tn-anstest.json" in query_ap_tenant.url' + - query_ap_ap.changed == false + - query_ap_ap.existing != [] + - query_ap_ap.existing.0.fvAp is defined + - '"query-target-filter=eq(fvAp.name, \"anstest\")" in query_ap_ap.filter_string' + - '"class/fvAp.json" in query_ap_ap.url' + - query_all.changed == false + - query_all.existing | length > 1 + - '"class/fvAp.json" in query_all.url' + +- name: delete ap - check_mode works + aci_ap: &aci_ap_absent + <<: *aci_ap_present + state: absent + check_mode: yes + register: ap_delete_check_mode + +- name: delete ap - delete works + aci_ap: + <<: *aci_ap_absent + register: ap_delete + +- name: delete ap - delete idempotency works + aci_ap: + <<: *aci_ap_absent + register: ap_delete_idempotent + +- name: delete ap - missing param error + aci_ap: + <<: *aci_ap_absent + tenant: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: ap_delete_missing_param + +- name: delete ap remove ap used for query + aci_ap: + <<: *aci_ap_absent + ap: anstest2 + +- name: absent assertions + assert: + that: + - ap_delete_check_mode.changed == true + - ap_delete_check_mode.existing != [] + - '"tn-anstest/ap-anstest.json" in ap_delete_check_mode.url' + - ap_delete.changed == true + - ap_delete.existing == ap_delete_check_mode.existing + - ap_delete_idempotent.changed == false + - ap_delete_idempotent.existing == [] + - ap_delete_missing_param.failed == true + - 'ap_delete_missing_param.msg == "state is absent but the following are missing: tenant"' + +- name: delete tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true diff --git a/test/integration/targets/aci_bd/aliases b/test/integration/targets/aci_bd/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_bd/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_bd/tasks/main.yml b/test/integration/targets/aci_bd/tasks/main.yml new file mode 100644 index 0000000000..dd1ad2f142 --- /dev/null +++ b/test/integration/targets/aci_bd/tasks/main.yml @@ -0,0 +1,190 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: ensure vrf exists for tests to kick off + aci_vrf: &aci_vrf_present + <<: *aci_tenant_present + vrf: anstest + register: vrf_present + +- name: create bd - check mode works + aci_bd: &aci_bd_present + <<: *aci_tenant_present + bd: anstest + description: Ansible Test + check_mode: yes + register: bd_present_check_mode + +- name: create bd - creation works + aci_bd: + <<: *aci_bd_present + register: bd_present + +- name: create bd again - idempotency works + aci_bd: + <<: *aci_bd_present + register: bd_present_idempotent + +- name: update bd - update works + aci_bd: + <<: *aci_bd_present + vrf: anstest + description: Ansible Test Update + register: bd_update + +- name: create another bd - check more params + aci_bd: + <<: *aci_bd_present + bd: anstest2 + ip_learning: "no" + l2_unknown_unicast: flood + l3_unknown_multicast: opt-flood + multi_dest: drop + enable_routing: "no" + arp_flooding: "yes" + register: bd_present_2 + +- name: create bd without all necessary params - failure message works + aci_bd: + <<: *aci_bd_present + tenant: "{{ fake_var | default(omit) }}" + ignore_errors: yes + register: bd_present_missing_param + +- name: present asserts + assert: + that: + - bd_present_check_mode.changed == true + - 'bd_present_check_mode.config == {"fvBD": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' + - bd_present.changed == true + - bd_present.config == bd_present_check_mode.config + - bd_present.existing == [] + - bd_present_idempotent.changed == false + - bd_present_idempotent.existing != [] + - bd_update.changed == true + - bd_update.existing != [] + - bd_update.changed != bd_update.proposed + - 'bd_update.config == {"fvBD": {"attributes": {"descr": "Ansible Test Update"}, "children": [{"fvRsCtx": {"attributes": {"tnFvCtxName": "anstest"}}}]}}' + - 'bd_present_2.config.fvBD.attributes == {"arpFlood": "yes", "descr": "Ansible Test", "ipLearning": "no", "multiDstPktAct": "drop", "name": "anstest2", + "unicastRoute": "no", "unkMacUcastAct": "flood", "unkMcastAct": "opt-flood"}' + - bd_present_missing_param.failed == true + - 'bd_present_missing_param.msg == "state is present but the following are missing: tenant"' + +- name: get all bd + aci_bd: &aci_query + <<: *aci_tenant_present + state: query + tenant: "{{ fake_var | default(omit) }}" + register: query_all + +- name: get all in tenant + aci_bd: + <<: *aci_query + tenant: anstest + register: query_tenant + +- name: get all with name + aci_bd: + <<: *aci_query + bd: anstest + register: query_bd_bd + +- name: get bd + aci_bd: + <<: *aci_bd_present + state: query + register: query_bd + +- name: query asserts + assert: + that: + - query_all.changed == false + - query_all.existing | length > 1 + - query_all.existing.0.fvBD is defined + - '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_all.filter_string' + - '"class/fvBD.json" in query_all.url' + - query_tenant.changed == false + - query_tenant.existing | length == 1 + - query_tenant.existing.0.fvTenant.children | length == 2 + - '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet,fvBD" in query_tenant.filter_string' + - '"tn-anstest.json" in query_tenant.url' + - query_bd_bd.changed == false + - query_bd_bd.existing != [] + - '"query-target-filter=eq(fvBD.name, \"anstest\")" in query_bd_bd.filter_string' + - '"rsp-subtree=full&rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_bd_bd.filter_string' + - '"class/fvBD.json" in query_bd_bd.url' + - query_bd.changed == false + - query_bd.existing | length == 1 + - 'query_bd.existing.0.fvBD.attributes.name == "anstest"' + - '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_bd.filter_string' + - '"tn-anstest/BD-anstest.json" in query_bd.url' + +- name: delete bd - check mode works + aci_bd: &aci_bd_absent + <<: *aci_bd_present + state: absent + check_mode: yes + register: bd_absent_check_mode + +- name: delete bd - delete works + aci_bd: + <<: *aci_bd_absent + register: bd_absent + +- name: delete bd again - idempotency works + aci_bd: + <<: *aci_bd_absent + register: bd_absent_idempotent + +- name: delete bd - cleanup + aci_bd: + <<: *aci_bd_absent + name: anstest2 + +- name: delete bd missing param - fails properly + aci_bd: + <<: *aci_bd_absent + bd: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: bd_absent_missing_param + +- name: asserts for deletion task + assert: + that: + - bd_absent_check_mode.changed == true + - bd_absent_check_mode.proposed == {} + - bd_absent.changed == true + - bd_absent.existing != [] + - bd_absent_idempotent.changed == false + - bd_absent_idempotent.existing == [] + - bd_absent_missing_param.failed == true + - 'bd_absent_missing_param.msg == "state is absent but the following are missing: bd"' + +- name: delete vrf - cleanup before ending tests + aci_vrf: + <<: *aci_vrf_present + state: absent + when: vrf_present.changed == true + +- name: delete tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true diff --git a/test/integration/targets/aci_bd_subnet/aliases b/test/integration/targets/aci_bd_subnet/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_bd_subnet/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_bd_subnet/tasks/main.yml b/test/integration/targets/aci_bd_subnet/tasks/main.yml new file mode 100644 index 0000000000..8d176fcb94 --- /dev/null +++ b/test/integration/targets/aci_bd_subnet/tasks/main.yml @@ -0,0 +1,233 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: ensure bd exists for tests to kick off + aci_bd: &aci_bd_present + <<: *aci_tenant_present + bd: anstest + register: bd_present + +- name: ensure subnet does not exist for tests to kick off + aci_bd_subnet: &aci_subnet_absent + <<: *aci_bd_present + state: absent + gateway: 10.100.100.1 + mask: 24 + +- name: ensure subnet does not exist for tests to kick off + aci_bd_subnet: &aci_subnet2_absent + <<: *aci_subnet_absent + gateway: 10.100.101.1 + mask: 25 + +- name: create subnet - check mode works + aci_bd_subnet: &aci_subnet_present + <<: *aci_subnet_absent + state: present + subnet_name: anstest + descr: Ansible Test + check_mode: yes + register: create_check_mode + +- name: create subnet - creation works + aci_bd_subnet: + <<: *aci_subnet_present + register: create_subnet + +- name: create new subnet - creation works + aci_bd_subnet: &aci_subnet2_present + <<: *aci_subnet2_absent + state: present + descr: Ansible Test + scope: [private, shared] + route_profile: default + route_profile_l3_out: default + register: create_subnet2 + +- name: create subnet again - idempotency works + aci_bd_subnet: + <<: *aci_subnet2_present + register: create_idempotency + +- name: modify subnet - update works + aci_bd_subnet: + <<: *aci_subnet_present + scope: [shared, public] + subnet_control: querier_ip + register: modify_subnet + +- name: create subnet with bad scope - failure message works + aci_bd_subnet: + <<: *aci_subnet_present + scope: [private, public] + register: create_bad_scope + ignore_errors: yes + +- name: create subnet without all necessary params - failure message works + aci_bd_subnet: + <<: *aci_subnet_present + bd: "{{ fake_var | default(omit) }}" + register: create_incomplete_data + ignore_errors: yes + +- name: asserts for subnet creation tasks + assert: + that: + - create_check_mode.changed == true + - 'create_check_mode.config == {"fvSubnet": {"attributes": {"descr": "Ansible Test", "ip": "10.100.100.1/24", "name": "anstest"}}}' + - create_subnet.changed == true + - 'create_subnet.config == {"fvSubnet": {"attributes": {"descr": "Ansible Test", "ip": "10.100.100.1/24", "name": "anstest"}}}' + - 'create_subnet.existing == []' + - create_subnet2.changed == true + - create_subnet2.config == create_subnet2.proposed + - 'create_subnet2.config.fvSubnet.attributes.scope == "private,shared"' + - 'create_subnet2.config.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes == {"tnL3extOutName": "default", "tnRtctrlProfileName": "default"}' + - create_idempotency.changed == false + - create_idempotency.existing != [] + - modify_subnet.changed == true + - modify_subnet.existing != [] + - modify_subnet.changed != modify_subnet.proposed + - 'modify_subnet.config == {"fvSubnet": {"attributes": {"ctrl": "querier", "scope": "public,shared"}}}' + - create_bad_scope.failed == true + - 'create_bad_scope.msg.startswith("value of scope must be one of")' + - create_incomplete_data.failed == true + - 'create_incomplete_data.msg == "state is present but the following are missing: bd"' + +- name: get all subnets + aci_bd_subnet: &aci_query + <<: *aci_tenant_present + state: query + tenant: "{{ fake_var | default(omit) }}" + register: get_all + +- name: get all in tenant + aci_bd_subnet: + <<: *aci_query + tenant: anstest + register: get_all_tenant + +- name: get all in bd + aci_bd_subnet: + <<: *aci_query + bd: anstest + register: get_all_bd + +- name: get all tenant and bd + aci_bd_subnet: + <<: *aci_bd_present + state: query + register: get_all_tenant_bd + +- name: get subnet in tenant + aci_bd_subnet: + <<: *aci_subnet_present + state: query + bd: "{{ fake_var | default(omit) }}" + register: get_subnet_tenant + +- name: get subnet in bd + aci_bd_subnet: + <<: *aci_subnet_present + state: query + tenant: "{{ fake_var | default(omit) }}" + register: get_subnet_bd + +- name: get specific subnet + aci_bd_subnet: + <<: *aci_subnet_present + state: query + register: get_subnet + +- name: get all subnets matching gateway + aci_bd_subnet: + <<: *aci_subnet_present + state: query + tenant: "{{ fake_var | default(omit) }}" + bd: "{{ fake_var | default(omit) }}" + register: get_subnets_gateway + +- name: asserts for query tasks + assert: + that: + - get_all.changed == false + - get_all.existing | length > 1 + - get_all_tenant.changed == false + - '"tn-anstest.json" in get_all_tenant.url' + - get_all_bd.changed == false + - '"query-target-filter=eq(fvBD.name, \"anstest\")" in get_all_bd.filter_string' + - '"class/fvBD.json" in get_all_bd.url' + - get_all_tenant_bd.changed == false + - '"tn-anstest/BD-anstest.json" in get_all_tenant_bd.url' + - get_all_tenant_bd.existing.0.fvBD.children | length > 1 + - get_subnet_tenant.changed == false + - '"rsp-subtree-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnet_tenant.filter_string' + - '"tn-anstest.json" in get_subnet_tenant.url' + - get_subnet_bd.changed == false + - '"query-target-filter=eq(fvBD.name, \"anstest\")" and "rsp-subtree-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnet_bd.filter_string' + - '"class/fvBD.json" in get_subnet_bd.url' + - get_subnet.changed == false + - get_subnet.existing | length == 1 + - '"tn-anstest/BD-anstest/subnet-[10.100.100.1/24].json" in get_subnet.url' + - get_subnets_gateway.changed == false + - '"query-target-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnets_gateway.filter_string' + - '"class/fvSubnet.json" in get_subnets_gateway.url' + +- name: delete subnet - check mode works + aci_bd_subnet: + <<: *aci_subnet_absent + check_mode: yes + register: delete_check_mode + +- name: delete subnet - delete works + aci_bd_subnet: + <<: *aci_subnet_absent + register: delete_subnet + +- name: delete subnet - cleanup + aci_bd_subnet: + <<: *aci_subnet2_absent + +- name: delete subnet again - idempotency works + aci_bd_subnet: + <<: *aci_subnet2_absent + register: delete_idempotency + +- name: asserts for deletion task + assert: + that: + - delete_check_mode.changed == true + - delete_check_mode.proposed == {} + - delete_subnet.changed == true + - delete_subnet.existing != [] + - 'delete_subnet.method == "DELETE"' + - delete_idempotency.changed == false + - delete_idempotency.existing == [] + +- name: delete bd - cleanup before ending tests + aci_bd: + <<: *aci_bd_present + state: absent + when: bd_present.changed == true + +- name: delete tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true diff --git a/test/integration/targets/aci_config_rollback/aliases b/test/integration/targets/aci_config_rollback/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_config_rollback/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_config_rollback/tasks/main.yml b/test/integration/targets/aci_config_rollback/tasks/main.yml new file mode 100644 index 0000000000..1bbc09c448 --- /dev/null +++ b/test/integration/targets/aci_config_rollback/tasks/main.yml @@ -0,0 +1,91 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant does not exist for tests to kick off + aci_tenant: &aci_tenant_absent + hostname: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + tenant: anstest + state: absent + +- name: create a snapshot + aci_config_snapshot: &create_snapshot + <<: *aci_tenant_absent + state: present + tenant: "{{ fakevar | default(omit) }}" + export_policy: anstest + +- name: create a tenant - use for rollback + aci_tenant: &aci_tenant + <<: *create_snapshot + export_policy: "{{ fakevar | default(omit) }}" + tenant: anstest + register: tenant_present + +- name: create a new snapshot + aci_config_snapshot: + <<: *create_snapshot + +- name: get snapshots + aci_config_snapshot: + <<: *create_snapshot + state: query + register: snapshots + +- name: compare snapshots + aci_config_rollback: &preview_rollback + <<: *create_snapshot + state: preview + compare_export_policy: anstest + compare_snapshot: "{{ snapshots.existing.0.configSnapshotCont.children[-1].configSnapshot.attributes.name }}" + snapshot: "{{ snapshots.existing.0.configSnapshotCont.children[-2].configSnapshot.attributes.name }}" + register: rollback_preview + +- name: rollback to snapshot + aci_config_rollback: &aci_rollback + <<: *create_snapshot + state: rollback + snapshot: "{{ snapshots.existing.0.configSnapshotCont.children[-1].configSnapshot.attributes.name }}" + ignore_errors: yes + register: rollback_missing_param + +- name: rollback to snapshot + aci_config_rollback: + <<: *aci_rollback + import_policy: anstest + import_type: replace + import_mode: atomic + register: rollback_rollback + +- name: pause execution to let rollback take affect + pause: + seconds: 15 + +- name: ensure tenant doesn't exist after rollback + aci_tenant: + <<: *aci_tenant_absent + register: tenant_removed + +- name: rollback assertions + assert: + that: + - rollback_preview.changed == false + - '"<fvTenant name=\"anstest\" rn=\"tn-anstest\" status=\"deleted\">" in rollback_preview.diff' + - '"snapshots.diff.xml" in rollback_preview.url' + - rollback_missing_param.failed == true + - 'rollback_missing_param.msg == "state is rollback but the following are missing: import_policy"' + - rollback_rollback.changed == true + - '"ce2_" in rollback_rollback.config.configImportP.attributes.fileName' + - '".tar.gz" in rollback_rollback.config.configImportP.attributes.fileName' + - '"fabric/configimp-anstest.json" in rollback_rollback.url' + - tenant_removed.changed == false + - tenant_removed.existing == [] diff --git a/test/integration/targets/aci_config_snapshot/aliases b/test/integration/targets/aci_config_snapshot/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_config_snapshot/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_config_snapshot/tasks/main.yml b/test/integration/targets/aci_config_snapshot/tasks/main.yml new file mode 100644 index 0000000000..d6465783c0 --- /dev/null +++ b/test/integration/targets/aci_config_snapshot/tasks/main.yml @@ -0,0 +1,139 @@ +# Test code for the ACI modules +# Copyright 2017, Dag Wieers <dag@wieers.com> + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: create a snapshot - creation works + aci_config_snapshot: &create_snapshot + hostname: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + export_policy: anstest + max_count: 10 + include_secure: no + format: json + description: ansible test + register: create + +- name: update snapshot to include secure and use xml - update works + aci_config_snapshot: + <<: *create_snapshot + include_secure: "yes" + format: xml + register: create_update + +- name: create a snapshot invalid max_count - error message + aci_config_snapshot: + <<: *create_snapshot + max_count: 11 + ignore_errors: yes + register: invalid_max_count + +- name: create a snapshot invalid max_count - error message + aci_config_snapshot: + <<: *create_snapshot + export_policy: "{{ fake_var | default(omit) }}" + ignore_errors: yes + register: missing_param + +- name: present assertion tests + assert: + that: + - create.failed == false + - create.changed == true + - 'create.config.configExportP.attributes.adminSt == "triggered"' + - create_update.failed == false + - create_update.changed == true + - 'create_update.config == {"configExportP": {"attributes": {"adminSt": "triggered", "format": "xml", "includeSecureFields": "yes"}}}' + - invalid_max_count.failed == true + - 'invalid_max_count.msg == "The \"max_count\" must be a number between 1 and 10"' + - missing_param.failed == true + - 'missing_param.msg == "state is present but the following are missing: export_policy"' + +- name: query with export_policy + aci_config_snapshot: &query_snapshot + <<: *create_snapshot + state: query + register: query_export + +- name: generate snapshot name + set_fact: + test_snapshot: "{{ query_export.existing.0.configSnapshotCont.children.0.configSnapshot.attributes.rn.strip('snapshot-') }}" + +- name: query with export_policy and snapshot + aci_config_snapshot: &query_both + <<: *query_snapshot + snapshot: "{{ test_snapshot }}" + register: query_export_snapshot + +- name: query with snapshot - module add run- to snapshot + aci_config_snapshot: + <<: *query_snapshot + export_policy: "{{ fake_var | default(omit) }}" + snapshot: "{{ test_snapshot.strip('run-') }}" + register: query_snapshot + +- name: query no params + aci_config_snapshot: + <<: *query_snapshot + export_policy: "{{ fake_var | default(omit) }}" + register: query_all + +- name: query assertion tests + assert: + that: + - query_export.failed == false + - query_export.changed == false + - '"snapshots-[uni/fabric/configexp-anstest].json" in query_export.url' + - 'query_export.existing.0.configSnapshotCont.attributes.name == "anstest"' + - query_export.existing.0.configSnapshotCont.children | length > 1 + - query_export_snapshot.failed == false + - query_export_snapshot.changed == false + - '"snapshots-[uni/fabric/configexp-anstest]/snapshot-{{ test_snapshot }}.json" in query_export_snapshot.url' + - query_export_snapshot.existing | length == 1 + - query_snapshot.failed == false + - query_snapshot.changed == false + - '"class/configSnapshot.json" in query_snapshot.url' + - '"configSnapshot.name, \"{{ test_snapshot }}\"" in query_snapshot.filter_string' + - query_all.failed == false + - query_all.changed == false + - '"class/configSnapshot.json" in query_all.url' + - query_all.existing | length > 1 + +- name: delete works + aci_config_snapshot: &delete + <<: *query_both + state: absent + register: delete_snapshot + +- name: delete works - idempotency + aci_config_snapshot: + <<: *delete + register: delete_idempotent + +- name: delete missing param + aci_config_snapshot: + <<: *delete + snapshot: "{{ fake_var | default(omit) }}" + ignore_errors: yes + register: delete_missing_param + +- name: absent assertion tests + assert: + that: + - delete_snapshot.failed == false + - delete_snapshot.changed == true + - 'delete_snapshot.config == {"configSnapshot": {"attributes": {"retire": "yes"}}}' + - delete_snapshot.existing != [] + - delete_snapshot.existing.0.configSnapshot.attributes.name == test_snapshot + - delete_idempotent.failed == false + - delete_idempotent.changed == false + - delete_idempotent.existing == [] + - delete_missing_param.failed == true + - 'delete_missing_param.msg == "state is absent but the following are missing: snapshot"' diff --git a/test/integration/targets/aci_contract/aliases b/test/integration/targets/aci_contract/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_contract/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_contract/tasks/main.yml b/test/integration/targets/aci_contract/tasks/main.yml new file mode 100644 index 0000000000..9e65da63d2 --- /dev/null +++ b/test/integration/targets/aci_contract/tasks/main.yml @@ -0,0 +1,160 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: create contract - check mode works + aci_contract: &aci_contract_present + <<: *aci_tenant_present + contract: anstest + description: Ansible Test + check_mode: yes + register: present_check_mode + +- name: create contract - creation works + aci_contract: + <<: *aci_contract_present + register: contract_present + +- name: create contract - idempotency works + aci_contract: + <<: *aci_contract_present + register: present_idempotent + +- name: update contract - update works + aci_contract: + <<: *aci_contract_present + scope: application-profile + register: present_update + +- name: create contract - used for query + aci_contract: + <<: *aci_contract_present + contract: anstest2 + +- name: missing param - failure message works + aci_contract: + <<: *aci_tenant_present + ignore_errors: yes + register: present_missing_param + +- name: present assertions + assert: + that: + - present_check_mode.changed == true + - present_check_mode.existing == [] + - 'present_check_mode.config == {"vzBrCP": {"attributes": {"name": "anstest", "descr": "Ansible Test"}}}' + - contract_present.changed == true + - contract_present.config == present_check_mode.config + - present_idempotent.changed == false + - present_update.changed == true + - present_update.config != present_update.proposed + - 'present_update.config.vzBrCP.attributes.scope == "application-profile"' + - present_missing_param.failed == true + - 'present_missing_param.msg == "state is present but the following are missing: contract"' + +- name: query contract + aci_contract: &aci_contract_query + <<: *aci_contract_present + state: query + register: query_contract + +- name: query all in tenant + aci_contract: + <<: *aci_contract_query + contract: "{{ fakevar | default(omit) }}" + register: query_tenant + +- name: query all with name + aci_contract: + <<: *aci_contract_query + tenant: "{{ fakevar | default(omit) }}" + register: query_name + +- name: query all + aci_contract: + <<: *aci_contract_query + tenant: "{{ fakevar | default(omit) }}" + contract: "{{ fakevar | default(omit) }}" + register: query_all + +- name: query assertions + assert: + that: + - query_contract.changed == false + - query_contract.existing | length == 1 + - '"tn-anstest/brc-anstest.json" in query_contract.url' + - query_tenant.changed == false + - query_tenant.existing | length == 1 + - query_tenant.existing.0.fvTenant.children | length > 1 + - '"rsp-subtree-class=vzBrCP" in query_tenant.filter_string' + - '"tn-anstest.json" in query_tenant.url' + - query_name.changed == false + - query_name.existing != [] + - '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_name.filter_string' + - '"class/vzBrCP.json" in query_name.url' + - query_all.changed == false + - query_all.existing | length > 1 + - '"class/vzBrCP.json" in query_all.url' + +- name: delete contract - check mode works + aci_contract: &aci_contract_absent + <<: *aci_contract_present + state: absent + check_mode: yes + register: absent_check_mode + +- name: delete contract - deletion works + aci_contract: + <<: *aci_contract_absent + register: contract_absent + +- name: delete contract - idempotency works + aci_contract: + <<: *aci_contract_absent + register: absent_idempotent + +- name: delete contract - cleanup second contract + aci_contract: + <<: *aci_contract_absent + contract: anstest2 + +- name: missing param - fail message works + aci_contract: + <<: *aci_contract_absent + tenant: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: absent_missing_param + +- name: absent assertions + assert: + that: + - absent_check_mode.changed == true + - absent_check_mode.existing != [] + - contract_absent.changed == true + - contract_absent.existing == absent_check_mode.existing + - absent_idempotent.changed == false + - absent_idempotent.existing == [] + - absent_missing_param.failed == true + - 'absent_missing_param.msg == "state is absent but the following are missing: tenant"' + +- name: cleanup tenant + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true diff --git a/test/integration/targets/aci_contract_subject/aliases b/test/integration/targets/aci_contract_subject/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_contract_subject/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_contract_subject/tasks/main.yml b/test/integration/targets/aci_contract_subject/tasks/main.yml new file mode 100644 index 0000000000..6c3af06865 --- /dev/null +++ b/test/integration/targets/aci_contract_subject/tasks/main.yml @@ -0,0 +1,238 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: ensure contract exists for tests to kick off + aci_contract: &aci_contract_present + <<: *aci_tenant_present + contract: anstest + register: contract_present + +- name: create subject - check mode works + aci_contract_subject: &aci_subject_present + <<: *aci_contract_present + subject: anstest + description: Ansible Test + check_mode: yes + register: subject_present_check_mode + +- name: create subject - creation works + aci_contract_subject: + <<: *aci_subject_present + register: subject_present + +- name: create subject - idempotency works + aci_contract_subject: + <<: *aci_subject_present + register: subject_present_idempotent + +- name: update subject - update works + aci_contract_subject: + <<: *aci_subject_present + description: Ansible Test + reverse_filter: "yes" + provider_match: at_most_one + priority: level2 + register: subject_update + +- name: create subject - try additional params + aci_contract_subject: &aci_subject_present_2 + <<: *aci_contract_present + subject: anstest2 + reverse_filter: "no" + consumer_match: all + priority: level3 + register: subject_present_2 + +- name: missing param - failure message works + aci_contract_subject: + <<: *aci_tenant_present + ignore_errors: yes + register: present_missing_param + +- name: present assertions + assert: + that: + - subject_present_check_mode.changed == true + - 'subject_present_check_mode.config == {"vzSubj": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' + - subject_present.changed == true + - subject_present.existing == [] + - subject_present.config == subject_present_check_mode.config + - subject_present_idempotent.changed == false + - subject_present_idempotent.existing != [] + - subject_update.changed == true + - subject_update.config != subject_update.proposed + - 'subject_update.config.vzSubj.attributes == {"prio": "level2", "provMatchT": "AtmostOne"}' + - subject_present_2.changed == true + - 'subject_present_2.config.vzSubj.attributes == {"consMatchT": "All", "name": "anstest2", "prio": "level3", "revFltPorts": "no"}' + - present_missing_param.failed == true + - 'present_missing_param.msg == "state is present but the following are missing: contract,subject"' + +- name: query tenant contract subject + aci_contract_subject: &aci_query_subject + <<: *aci_subject_present + state: query + register: query_tenant_contract_subject + +- name: query tenant contract + aci_contract_subject: + <<: *aci_query_subject + subject: "{{ fakevar | default(omit) }}" + register: query_tenant_contract + +- name: query tenant subject + aci_contract_subject: + <<: *aci_query_subject + contract: "{{ fakevar | default(omit) }}" + register: query_tenant_subject + +- name: query contract subject + aci_contract_subject: + <<: *aci_query_subject + tenant: "{{ fakevar | default(omit) }}" + register: query_contract_subject + +- name: query tenant + aci_contract_subject: + <<: *aci_tenant_present + state: query + register: query_tenant + +- name: query contract + aci_contract_subject: + <<: *aci_contract_present + state: query + tenant: "{{ fakevar | default(omit) }}" + register: query_contract + +- name: query subject + aci_contract_subject: + <<: *aci_query_subject + tenant: "{{ fakevar | default(omit) }}" + contract: "{{ fakevar | default(omit) }}" + register: query_subject + +- name: query all + aci_contract_subject: + <<: *aci_tenant_present + state: query + tenant: "{{ fakevar | default(omit) }}" + register: query_all + +- name: query assertions + assert: + that: + - query_tenant_contract_subject.changed == false + - query_tenant_contract_subject.existing | length == 1 + - 'query_tenant_contract_subject.existing.0.vzSubj.attributes.name == "anstest"' + - '"tn-anstest/brc-anstest/subj-anstest.json" in query_tenant_contract_subject.url' + - query_tenant_contract.changed == false + - query_tenant_contract.existing | length == 1 + - 'query_tenant_contract.existing.0.vzBrCP.attributes.name == "anstest"' + - query_tenant_contract.existing.0.vzBrCP.children | length == 2 + - '"rsp-subtree-class=vzSubj" in query_tenant_contract.filter_string' + - '"tn-anstest/brc-anstest.json" in query_tenant_contract.url' + - query_tenant_subject.changed == false + - query_tenant_subject.existing | length == 1 + - 'query_tenant_subject.existing.0.fvTenant.attributes.name == "anstest"' + - query_tenant_subject.existing.0.fvTenant.children.0.vzBrCP.children | length == 1 + - 'query_tenant_subject.existing.0.fvTenant.children.0.vzBrCP.children.0.vzSubj.attributes.name == "anstest"' + - '"rsp-subtree-filter=eq(vzSubj.name, \"anstest\")" in query_tenant_subject.filter_string' + - '"rsp-subtree-class=vzSubj" in query_tenant_subject.filter_string' + - '"tn-anstest.json" in query_tenant_subject.url' + - query_contract_subject.changed == false + - 'query_contract_subject.existing.0.vzBrCP.attributes.name == "anstest"' + - query_contract_subject.existing.0.vzBrCP.children | length == 1 + - 'query_contract_subject.existing.0.vzBrCP.children.0.vzSubj.attributes.name == "anstest"' + - '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_contract_subject.filter_string' + - '"rsp-subtree-filter=eq(vzSubj.name, \"anstest\")" in query_contract_subject.filter_string' + - '"rsp-subtree-class=vzSubj" in query_contract_subject.filter_string' + - '"class/vzBrCP.json" in query_contract_subject.url' + - query_tenant.changed == false + - query_tenant.existing | length == 1 + - 'query_tenant.existing.0.fvTenant.attributes.name == "anstest"' + - '"rsp-subtree-class=vzBrCP,vzSubj" in query_tenant.filter_string' + - '"tn-anstest.json" in query_tenant.url' + - query_contract.changed == false + - 'query_contract.existing.0.vzBrCP.attributes.name == "anstest"' + - '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_contract.filter_string' + - '"rsp-subtree-class=vzSubj" in query_contract.filter_string' + - '"class/vzBrCP.json" in query_contract.url' + - query_subject.changed == false + - 'query_subject.existing.0.vzSubj.attributes.name == "anstest"' + - '"query-target-filter=eq(vzSubj.name, \"anstest\")" in query_subject.filter_string' + - '"class/vzSubj.json" in query_subject.url' + - query_all.changed == false + - query_all.existing > 1 + - query_all.existing.0.vzSubj is defined + - '"class/vzSubj.json" in query_all.url' + +- name: delete subject - check mode works + aci_contract_subject: &aci_subject_absent + <<: *aci_subject_present + state: absent + check_mode: yes + register: subject_absent_check_mode + +- name: delete subject - deletion works + aci_contract_subject: + <<: *aci_subject_absent + register: subject_absent + +- name: delete subject - idempotency works + aci_contract_subject: + <<: *aci_subject_absent + register: subject_absent_idempotent + +- name: delete subject - cleanup + aci_contract_subject: + <<: *aci_subject_present_2 + state: absent + +- name: missing params - failure message works + aci_contract_subject: + <<: *aci_subject_absent + subject: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: absent_missing_param + +- name: absent assertions + assert: + that: + - subject_absent_check_mode.changed == true + - subject_absent_check_mode.existing != [] + - subject_absent_check_mode.proposed == {} + - subject_absent.changed == true + - subject_absent.existing == subject_absent_check_mode.existing + - subject_absent_idempotent.changed == false + - subject_absent_idempotent.existing == [] + - absent_missing_param.failed == true + - 'absent_missing_param.msg == "state is absent but the following are missing: subject"' + +- name: cleanup contract + aci_contract: + <<: *aci_contract_present + state: absent + when: contract_present.changed == true + +- name: cleanup tenant + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true diff --git a/test/integration/targets/aci_contract_subject_to_filter/aliases b/test/integration/targets/aci_contract_subject_to_filter/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_contract_subject_to_filter/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_contract_subject_to_filter/tasks/main.yml b/test/integration/targets/aci_contract_subject_to_filter/tasks/main.yml new file mode 100644 index 0000000000..96876b5418 --- /dev/null +++ b/test/integration/targets/aci_contract_subject_to_filter/tasks/main.yml @@ -0,0 +1,190 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: ensure filter exists for tests to kick off + aci_filter: &aci_filter_present + <<: *aci_tenant_present + filter: anstest + register: filter_present + +- name: ensure filter exists for tests to kick off + aci_filter: &aci_filter_present_2 + <<: *aci_tenant_present + filter: anstest2 + register: filter_present_2 + +- name: ensure contract exists for tests to kick off + aci_contract: &aci_contract_present + <<: *aci_tenant_present + contract: anstest + register: contract_present + +- name: ensure subject exists for tests to kick off + aci_contract_subject: &aci_subject_present + <<: *aci_contract_present + subject: anstest + register: subject_present + +- name: create subject filter binding - check mode works + aci_contract_subject_to_filter: &aci_subject_filter_present + <<: *aci_subject_present + filter: anstest + log: log + check_mode: yes + register: subject_filter_present_check_mode + +- name: create subject filter binding - creation works + aci_contract_subject_to_filter: + <<: *aci_subject_filter_present + register: subject_filter_present + +- name: create subject filter binding - additional testing + aci_contract_subject_to_filter: &aci_subject_filter_present_2 + <<: *aci_subject_filter_present + filter: anstest2 + register: subject_filter_present_2 + +- name: create subject filter binding - idempotency works + aci_contract_subject_to_filter: + <<: *aci_subject_filter_present + register: subject_filter_present_idempotent + +- name: update subject filter binding - update works + aci_contract_subject_to_filter: + <<: *aci_subject_filter_present + log: none + register: subject_filter_update + +- name: missing param - failure message works + aci_contract_subject_to_filter: + <<: *aci_tenant_present + ignore_errors: yes + register: present_missing_param + +- name: present assertions + assert: + that: + - subject_filter_present_check_mode.changed == true + - subject_filter_present_check_mode.existing == [] + - 'subject_filter_present_check_mode.config == {"vzRsSubjFiltAtt": {"attributes": {"directives": "log", "tnVzFilterName": "anstest"}}}' + - subject_filter_present.changed == true + - subject_filter_present.existing == [] + - subject_filter_present.config == subject_filter_present_check_mode.config + - subject_filter_present_2.changed == true + - subject_filter_present_idempotent.changed == false + - subject_filter_present_idempotent.existing != [] + - subject_filter_update.changed == true + - 'subject_filter_update.config.vzRsSubjFiltAtt.attributes == {"directives": ""}' + - present_missing_param.failed == true + - 'present_missing_param.msg == "state is present but the following are missing: contract,filter,subject"' + +- name: query all + aci_contract_subject_to_filter: + <<: *aci_tenant_present + state: query + tenant: "{{ fakevar | default(omit) }}" + register: query_all + +- name: query binding + aci_contract_subject_to_filter: + <<: *aci_subject_filter_present + state: query + register: query_binding + +- name: query assertions + assert: + that: + - query_all.changed == false + - query_all.existing | length > 1 + - query_all.existing.0.vzRsSubjFiltAtt is defined + - query_binding.changed == false + - query_binding.existing != [] + +- name: delete subject filter binding - check mode works + aci_contract_subject_to_filter: &aci_subject_filter_absent + <<: *aci_subject_filter_present + state: absent + check_mode: yes + register: subject_filter_absent_check_mode + +- name: delete subject filter binding - deletion works + aci_contract_subject_to_filter: + <<: *aci_subject_filter_absent + register: subject_filter_absent + +- name: delete subject filter binding - idempotency works + aci_contract_subject_to_filter: + <<: *aci_subject_filter_absent + register: subject_filter_absent_idempotent + +- name: missing param - failure message works + aci_contract_subject_to_filter: + <<: *aci_subject_filter_absent + filter: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: absent_missing_param + +- name: cleanup subject filter binding + aci_contract_subject_to_filter: + <<: *aci_subject_filter_present_2 + state: absent + +- name: absent assertions + assert: + that: + - subject_filter_absent_check_mode.changed == true + - subject_filter_absent_check_mode.proposed == {} + - subject_filter_absent_check_mode.existing != [] + - subject_filter_absent.changed == true + - subject_filter_absent.existing != [] + - subject_filter_absent_idempotent.changed == false + - subject_filter_absent_idempotent.existing == [] + - absent_missing_param.failed == true + - 'absent_missing_param.msg == "state is absent but the following are missing: filter"' + +- name: cleanup subject + aci_contract_subject: + <<: *aci_subject_present + state: absent + when: subject_present.changed == true + +- name: cleanup contract + aci_contract: + <<: *aci_contract_present + state: absent + when: contract_present.changed == true + +- name: cleanup filter + aci_filter: + <<: *aci_filter_present + state: absent + when: filter_present.changed == true + +- name: cleanup filter + aci_filter: + <<: *aci_filter_present_2 + state: absent + when: filter_present_2.changed == true + +- name: cleanup tenant + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true diff --git a/test/integration/targets/aci_epg/aliases b/test/integration/targets/aci_epg/aliases new file mode 100644 index 0000000000..3c1de7e647 --- /dev/null +++ b/test/integration/targets/aci_epg/aliases @@ -0,0 +1 @@ +# No ACI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_epg/tasks/main.yml b/test/integration/targets/aci_epg/tasks/main.yml new file mode 100644 index 0000000000..64bb236f5e --- /dev/null +++ b/test/integration/targets/aci_epg/tasks/main.yml @@ -0,0 +1,168 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: ensure bd exists for tests to kick off + aci_bd: &aci_bd_present + <<: *aci_tenant_present + bd: anstest + register: bd_present + +- name: ensure ap exists for tests to kick off + aci_ap: &aci_ap_present + <<: *aci_tenant_present + ap: anstest + register: ap_present + +- name: create epg - check mode works + aci_epg: &aci_epg_present + <<: *aci_ap_present + epg: anstest + bd: anstest + description: Ansible Test + check_mode: yes + register: epg_present_check_mode + +- name: create epg - creation works + aci_epg: + <<: *aci_epg_present + register: epg_present + +- name: create epg - idempotency works + aci_epg: + <<: *aci_epg_present + register: epg_present_idempotent + +- name: update epg - update works + aci_epg: + <<: *aci_epg_present + description: Ansible Test Update + register: epg_present_update + +- name: create epg - missing param + aci_epg: + <<: *aci_epg_present + ap: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: epg_present_missing_param + +- name: create epg - used for query + aci_epg: + <<: *aci_epg_present + epg: anstest2 + +- name: present assertions + assert: + that: + - epg_present_check_mode.changed == true + - epg_present_check_mode.existing == [] + - epg_present_check_mode.config.fvAEPg.attributes != {} + - 'epg_present_check_mode.config.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == "anstest"' + - epg_present.changed == true + - epg_present.config == epg_present_check_mode.config + - epg_present_idempotent.changed == false + - epg_present_idempotent.config == {} + - epg_present_update.changed == true + - 'epg_present_update.config == {"fvAEPg": {"attributes": {"descr": "Ansible Test Update"}}}' + - epg_present_missing_param.failed == true + - 'epg_present_missing_param.msg == "state is present but the following are missing: ap"' + +- name: get specific epg + aci_epg: + <<: *aci_epg_present + state: query + register: epg_query + +- name: get all epgs + aci_epg: + <<: *aci_tenant_present + state: query + tenant: "{{ fakevar | default(omit) }}" + register: epg_query_all + +- name: query assertions + assert: + that: + - epg_query.changed == false + - epg_query.existing | length == 1 + - 'epg_query.existing.0.fvAEPg.attributes.name == "anstest"' + - '"tn-anstest/ap-anstest/epg-anstest.json" in epg_query.url' + - epg_query_all.changed == false + - epg_query_all.existing | length > 1 + - '"rsp-subtree-class=fvRsBd" in epg_query_all.filter_string' + - '"class/fvAEPg.json" in epg_query_all.url' + +- name: delete epg - check mode works + aci_epg: &aci_epg_absent + <<: *aci_epg_present + state: absent + check_mode: yes + register: delete_epg_check_mode + +- name: delete epg - delete works + aci_epg: + <<: *aci_epg_absent + register: delete_epg + +- name: delete epg - idempotency works + aci_epg: + <<: *aci_epg_absent + register: delete_epg_idempotent + +- name: delete epg - cleanup extra epg + aci_epg: + <<: *aci_epg_absent + epg: anstest2 + +- name: delete epg - missing param fails + aci_epg: + <<: *aci_epg_absent + tenant: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: delete_epg_missing_param + +- name: query assertions + assert: + that: + - delete_epg_check_mode.changed == true + - delete_epg_check_mode.existing != [] + - delete_epg.changed == true + - delete_epg.existing == delete_epg_check_mode.existing + - delete_epg_idempotent.changed == false + - delete_epg_idempotent.existing == [] + - delete_epg_missing_param.failed == true + - 'delete_epg_missing_param.msg == "state is absent but the following are missing: tenant"' + +- name: cleanup bd + aci_bd: + <<: *aci_bd_present + state: absent + when: bd_present.existing == [] + +- name: cleanup ap + aci_ap: + <<: *aci_ap_present + state: absent + when: ap_present.existing == [] + +- name: cleanup tenant + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.existing == [] diff --git a/test/integration/targets/aci_epg_to_contract/aliases b/test/integration/targets/aci_epg_to_contract/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_epg_to_contract/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_epg_to_contract/tasks/main.yml b/test/integration/targets/aci_epg_to_contract/tasks/main.yml new file mode 100644 index 0000000000..879bc1637e --- /dev/null +++ b/test/integration/targets/aci_epg_to_contract/tasks/main.yml @@ -0,0 +1,235 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: ensure contracts exist for tests to kick off + aci_contract: + <<: *aci_tenant_present + contract: "{{ item }}" + with_items: ["anstest_http", "anstest_https", "anstest_db"] + +- name: ensure ap exists + aci_ap: &aci_ap_present + <<: *aci_tenant_present + ap: anstest + register: ap_present + +- name: ensure epg exists + aci_epg: &aci_epg_present + <<: *aci_ap_present + epg: anstest + register: epg_present + +- name: bind contract to epg - check mode works + aci_epg_to_contract: &aci_epg_provide_present + <<: *aci_epg_present + contract_type: provider + contract: "anstest_http" + check_mode: yes + register: provide_present_check_mode + +- name: bind contract to epg - provide works + aci_epg_to_contract: + <<: *aci_epg_provide_present + register: provide_present + +- name: bind contract to epg - consume works + aci_epg_to_contract: &aci_epg_consume_present + <<: *aci_epg_provide_present + contract_type: consumer + contract: anstest_db + register: consume_present + +- name: bind contract to epg - add additional contract + aci_epg_to_contract: &aci_epg_provide_present2 + <<: *aci_epg_provide_present + contract: anstest_https + provider_match: at_most_one + register: provide_present2 + +- name: bind contract to epg - idempotency works + aci_epg_to_contract: + <<: *aci_epg_provide_present + register: idempotent_present + +- name: missing param - failure message works + aci_epg_to_contract: + <<: *aci_tenant_present + contract_type: provider + ignore_errors: yes + register: missing_param_present + +- name: missing required param - failure message works + aci_epg_to_contract: + <<: *aci_tenant_present + ignore_errors: yes + register: missing_required_present + +- name: incompatible param - failure message works + aci_epg_to_contract: + <<: *aci_epg_consume_present + provider_match: all + ignore_errors: yes + register: incompatible_present + +- name: present assertions + assert: + that: + - provide_present_check_mode.changed == true + - 'provide_present_check_mode.config == {"fvRsProv": {"attributes": {"tnVzBrCPName": "anstest_http"}}}' + - provide_present.changed == true + - provide_present.config == provide_present_check_mode.config + - provide_present.existing == [] + - consume_present.changed == true + - consume_present.existing == [] + - 'consume_present.config == {"fvRsCons": {"attributes": {"tnVzBrCPName": "anstest_db"}}}' + - provide_present2.changed == true + - provide_present2.existing == [] + - missing_param_present.failed == true + - 'missing_param_present.msg == "state is present but the following are missing: ap,contract,epg"' + - missing_required_present.failed == true + - 'missing_required_present.msg == "missing required arguments: contract_type"' + - incompatible_present.failed == true + - incompatible_present.msg == "the 'provider_match' is only configurable for Provided Contracts" + +- name: get binding + aci_epg_to_contract: + <<: *aci_epg_provide_present2 + state: query + register: query_provide_contract + +- name: get binding + aci_epg_to_contract: + <<: *aci_epg_consume_present + state: query + register: query_consume_contract + +- name: get all bindings + aci_epg_to_contract: + <<: *aci_tenant_present + state: query + tenant: "{{ fakevar | default(omit) }}" + contract_type: provider + register: query_all + +- name: missing required param - failure message works + aci_epg_to_contract: + <<: *aci_tenant_present + state: query + ignore_errors: yes + register: missing_required_query + +- name: query assertions + assert: + that: + - query_provide_contract.changed == false + - query_provide_contract.existing != [] + - '"class/fvRsProv.json" in query_provide_contract.url' + - query_consume_contract.changed == false + - query_consume_contract.existing != [] + - '"class/fvRsCons.json" in query_consume_contract.url' + - query_all.changed == false + - '"class/fvRsProv.json" in query_all.url' + - missing_required_query.failed == true + - 'missing_required_query.msg == "missing required arguments: contract_type"' + +- name: delete consume binding - check mode works + aci_epg_to_contract: &aci_epg_consume_absent + <<: *aci_epg_consume_present + state: absent + check_mode: yes + register: consume_absent_check_mode + +- name: delete consume binding - deletion works + aci_epg_to_contract: + <<: *aci_epg_consume_absent + register: consume_absent + +- name: delete provide binding - deletion works + aci_epg_to_contract: + <<: *aci_epg_provide_present + state: absent + register: provide_absent + +- name: delete provide binding - deletion works + aci_epg_to_contract: + <<: *aci_epg_provide_present2 + state: absent + register: provide_absent2 + +- name: delte consume binding - idempotency works + aci_epg_to_contract: + <<: *aci_epg_consume_absent + register: consume_absent_idempotent + +- name: missing param - failure message works + aci_epg_to_contract: + <<: *aci_epg_consume_absent + contract: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: missing_param_absent + +- name: missing required param - failure message works + aci_epg_to_contract: + <<: *aci_epg_consume_absent + contract_type: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: missing_required_absent + +- name: absent assertions + assert: + that: + - consume_absent_check_mode.changed == true + - consume_absent_check_mode.existing.0.fvRsCons is defined + - consume_absent.changed == true + - consume_absent.existing == consume_absent_check_mode.existing + - provide_absent.changed == true + - provide_absent.existing.0.fvRsProv is defined + - provide_absent2.changed == true + - consume_absent_idempotent.changed == false + - consume_absent_idempotent.existing == [] + - missing_param_absent.failed == true + - 'missing_param_absent.msg == "state is absent but the following are missing: contract"' + - missing_required_absent.failed == true + - 'missing_required_absent.msg == "missing required arguments: contract_type"' + +- name: cleanup contracts + aci_contract: + <<: *aci_tenant_present + state: absent + contract: "{{ item }}" + with_items: ["anstest_http", "anstest_https", "anstest_db"] + +- name: cleanup epg + aci_epg: + <<: *aci_epg_present + state: absent + when: epg_present.changed == true + +- name: cleanup ap + aci_ap: + <<: *aci_ap_present + state: absent + when: ap_present.changed == true + +- name: cleanup tenant + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true diff --git a/test/integration/targets/aci_epg_to_domain/aliases b/test/integration/targets/aci_epg_to_domain/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_epg_to_domain/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_epg_to_domain/tasks/main.yml b/test/integration/targets/aci_epg_to_domain/tasks/main.yml new file mode 100644 index 0000000000..188970a834 --- /dev/null +++ b/test/integration/targets/aci_epg_to_domain/tasks/main.yml @@ -0,0 +1,211 @@ +# Test code for the ACI modules +# Copyright 2017, Dag Wieers <dag@wieers.com> + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: ensure ap exists for tests to kick off + aci_ap: &aci_ap_present + <<: *aci_tenant_present + ap: anstest + register: ap_present + +- name: ensure epg exists for tests to kick off + aci_epg: &aci_epg_present + <<: *aci_ap_present + epg: anstest + register: epg_present + +- name: ensure phys domain exists for tests to kick off + aci_rest: &aci_rest_phys_domain + hostname: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + method: post + path: api/mo/uni/phys-anstest.json + content: {"physDomP": {"attributes": {}}} + register: phys_domain_post + +- name: ensure vmm domain exists for tests to kick off + aci_rest: &aci_rest_vmm_domain + <<: *aci_rest_phys_domain + path: api/mo/uni/vmmp-VMware/dom-anstest.json + content: {"vmmDomP": {"attributes": {}}} + register: vmm_domain_post + +- name: bind phys domain to epg - check mode works + aci_epg_to_domain: &aci_epg_to_domain_present + <<: *aci_epg_present + domain: anstest + domain_type: phys + check_mode: yes + register: phys_check_mode_present + +- name: bind phys domain to epg - creation works + aci_epg_to_domain: + <<: *aci_epg_to_domain_present + register: phys_present + +- name: bind phys domain to epg - idempotency works + aci_epg_to_domain: + <<: *aci_epg_to_domain_present + register: phys_idempotent + +- name: bind phys domain to epg - update works + aci_epg_to_domain: + <<: *aci_epg_to_domain_present + deploy_immediacy: immediate + register: phys_update + +- name: bind vmm domain to epg - creation works + aci_epg_to_domain: &aci_epg_to_domain_vmm_present + <<: *aci_epg_to_domain_present + domain_type: vmm + vm_provider: vmware + resolution_immediacy: pre-provision + register: vmm_present + +- name: bind vmm domain to epg - missing params + aci_epg_to_domain: + <<: *aci_epg_to_domain_vmm_present + vm_provider: "{{ fake_var | default(omit) }}" + ignore_errors: yes + register: present_missing_params + +- name: bind vmm domain to epg - invalid vlan + aci_epg_to_domain: + <<: *aci_epg_to_domain_present + encap: 4097 + ignore_errors: yes + register: invalid_vlan + +- name: bind vmm domain to epg - incompatible params + aci_epg_to_domain: + <<: *aci_epg_to_domain_present + vm_provider: vmware + ignore_errors: yes + register: incompatible_params + +- name: present assertions + assert: + that: + - phys_check_mode_present.changed == true + - phys_present.changed == true + - phys_present.existing == [] + - 'phys_present.config == {"fvRsDomAtt": {"attributes": {}}}' + - '"[uni/phys-anstest].json" in phys_present.url' + - phys_idempotent.changed == false + - phys_idempotent.config == {} + - phys_update.changed == true + - 'phys_update.config == {"fvRsDomAtt": {"attributes": {"instrImedcy": "immediate"}}}' + - vmm_present.changed == true + - 'vmm_present.config == {"fvRsDomAtt": {"attributes": {"resImedcy": "pre-provision"}}}' + - '"[uni/vmmp-VMware/dom-anstest].json" in vmm_present.url' + - present_missing_params.failed == true + - 'present_missing_params.msg == "domain_type is vmm but the following are missing: vm_provider"' + - invalid_vlan.failed == true + - 'invalid_vlan.msg == "Valid VLAN assigments are from 1 to 4096"' + - incompatible_params.failed == true + - incompatible_params.msg == "Domain type 'phys' cannot have a 'vm_provider'" + +- name: get domain epg binding + aci_epg_to_domain: &aci_epg_domain_query + <<: *aci_tenant_present + state: query + tenant: "{{ fake_var | default(omit) }}" + register: binding_query + +- name: query assertions + assert: + that: + - binding_query.changed == false + - binding_query.existing | length > 1 + - '"class/fvRsDomAtt.json" in binding_query.url' + +- name: delete domain epg binding - check mode + aci_epg_to_domain: &aci_epg_to_domain_absent + <<: *aci_epg_to_domain_present + state: absent + check_mode: yes + register: epg_domain_check_mode_absent + +- name: delete phys domain epg binding - delete works + aci_epg_to_domain: + <<: *aci_epg_to_domain_absent + register: epg_domain_absent + +- name: delete vmm domain epg binding - delete works + aci_epg_to_domain: + <<: *aci_epg_to_domain_vmm_present + state: absent + register: epg_vmm_domain_absent + +- name: delete domain epg binding - idempotency works + aci_epg_to_domain: + <<: *aci_epg_to_domain_absent + register: idempotency_absent + +- name: delete domain epg binding - missing param + aci_epg_to_domain: + <<: *aci_tenant_present + state: absent + ignore_errors: true + register: absent_missing_param + +- name: absent assertions + assert: + that: + - epg_domain_check_mode_absent.changed == true + - epg_domain_check_mode_absent.existing != [] + - epg_domain_absent.changed == true + - epg_domain_absent.existing == epg_domain_check_mode_absent.existing + - epg_vmm_domain_absent.changed == true + - idempotency_absent.changed == false + - idempotency_absent.existing == [] + - absent_missing_param.failed == true + - 'absent_missing_param.msg == "state is absent but the following are missing: ap,domain,domain_type,epg"' + +- name: remove vmm domain - cleanup + aci_rest: + <<: *aci_rest_vmm_domain + method: delete + when: vmm_domain_post.changed == true + +- name: remove phys domain - cleanup + aci_rest: + <<: *aci_rest_phys_domain + method: delete + when: phys_domain_post.changed == true + +- name: remove epg - cleanup + aci_epg: + <<: *aci_epg_present + state: absent + when: epg_present.changed == true + +- name: remove ap - cleanup + aci_ap: + <<: *aci_ap_present + state: absent + when: ap_present.changed == true + +- name: remove tenant - cleanup + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true
\ No newline at end of file diff --git a/test/integration/targets/aci_filter_entry/aliases b/test/integration/targets/aci_filter_entry/aliases new file mode 100644 index 0000000000..3c1de7e647 --- /dev/null +++ b/test/integration/targets/aci_filter_entry/aliases @@ -0,0 +1 @@ +# No ACI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_filter_entry/tasks/main.yml b/test/integration/targets/aci_filter_entry/tasks/main.yml new file mode 100644 index 0000000000..03599e94d5 --- /dev/null +++ b/test/integration/targets/aci_filter_entry/tasks/main.yml @@ -0,0 +1,279 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: absent + tenant: anstest + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: ensure filter exists for tests to kick off + aci_filter: &aci_filter_present + <<: *aci_tenant_present + filter: anstest + register: filter_present + +- name: create filter entry - check mode works + aci_filter_entry: &aci_entry_present + <<: *aci_filter_present + entry: anstest + description: Ansible Test + ether_type: ip + ip_protocol: tcp + dst_port_start: 80 + dst_port_end: 88 + check_mode: yes + register: entry_present_check_mode + +- name: create filter entry - creation works + aci_filter_entry: + <<: *aci_entry_present + register: entry_present + +- name: create filter entry - idempotency works + aci_filter_entry: + <<: *aci_entry_present + register: entry_present_idempotent + +- name: update filter entry - update works + aci_filter_entry: + <<: *aci_entry_present + description: Ansible Test Update + dst_port_start: 80 + dst_port_end: 90 + register: entry_present_update + +- name: create filter entry - test different types + aci_filter_entry: + <<: *aci_filter_present + entry: anstest2 + ether_type: arp + arp_flag: arp_reply + register: entry_present_2 + +- name: create filter entry - test different types + aci_filter_entry: + <<: *aci_filter_present + entry: anstest3 + ether_type: ip + ip_protocol: icmp + icmp_msg_type: echo + register: entry_present_3 + +- name: create filter entry - test different types + aci_filter_entry: + <<: *aci_filter_present + entry: anstest4 + ether_type: ip + ip_protocol: udp + dst_port: 1000 + register: entry_present_4 + +- name: missing param - failure message works + aci_filter_entry: + <<: *aci_filter_present + ignore_errors: yes + register: present_missing_param + +- name: incompatable params - failure message works + aci_filter_entry: + <<: *aci_entry_present + dst_port: 99 + ignore_errors: yes + register: present_incompatible_params + +- name: present assertions + assert: + that: + - entry_present_check_mode.changed == true + - entry_present_check_mode.existing == [] + - 'entry_present_check_mode.config == {"vzEntry": {"attributes": {"dFromPort": "http","dToPort": "88","descr": "Ansible Test","etherT": "ip","name": "anstest","prot": "tcp"}}}' + - entry_present.changed == true + - entry_present.existing == [] + - entry_present.config == entry_present_check_mode.config + - entry_present_idempotent.changed == false + - entry_present_idempotent.existing != [] + - entry_present_idempotent.config == {} + - entry_present_update.changed == true + - entry_present_update.existing != [] + - entry_present_update.config != entry_present_update.proposed + - entry_present_2.changed == true + - 'entry_present_2.config.vzEntry.attributes == {"arpOpc": "reply", "etherT": "arp", "name": "anstest2"}' + - entry_present_3.changed == true + - 'entry_present_3.config.vzEntry.attributes == {"etherT": "ip", "icmpv4T": "echo", "name": "anstest3", "prot": "icmp"}' + - entry_present_4.changed == true + - 'entry_present_4.config.vzEntry.attributes == {"dFromPort": "1000", "dToPort": "1000", "etherT": "ip", "name": "anstest4", "prot": "udp"}' + - present_missing_param.failed == true + - 'present_missing_param.msg == "state is present but the following are missing: entry"' + - present_incompatible_params.failed == true + - present_incompatible_params.msg.startswith("Parameter") + +- name: query tenant filter entry + aci_filter_entry: &aci_query_entry + <<: *aci_entry_present + state: query + register: query_tenant_filter_entry + +- name: query filter entry + aci_filter_entry: + <<: *aci_query_entry + tenant: "{{ fakevar | default(omit) }}" + register: query_filter_entry + +- name: query tenant entry + aci_filter_entry: + <<: *aci_query_entry + filter: "{{ fakevar | default(omit) }}" + register: query_tenant_entry + +- name: query tenant filter + aci_filter_entry: + <<: *aci_query_entry + entry: "{{ fakevar | default(omit) }}" + register: query_tenant_filter + +- name: query entry + aci_filter_entry: &aci_query_entry_2 + <<: *aci_query_entry + tenant: "{{ fakevar | default(omit) }}" + filter: "{{ fakevar | default(omit) }}" + register: query_entry + +- name: query filter + aci_filter_entry: + <<: *aci_query_entry + tenant: "{{ fakevar | default(omit) }}" + entry: "{{ fakevar | default(omit) }}" + register: query_filter + +- name: query tenant + aci_filter_entry: + <<: *aci_query_entry + filter: "{{ fakevar | default(omit) }}" + entry: "{{ fakevar | default(omit) }}" + register: query_tenant + +- name: query all + aci_filter_entry: + <<: *aci_query_entry_2 + entry: "{{ fakevar | default(omit) }}" + register: query_all + +- name: query assertions + assert: + that: + - query_tenant_filter_entry.changed == false + - query_tenant_filter_entry.existing | length == 1 + - 'query_tenant_filter_entry.existing.0.vzEntry.attributes.name == "anstest"' + - '"tn-anstest/flt-anstest/e-anstest.json" in query_tenant_filter_entry.url' + - query_filter_entry.changed == false + - 'query_filter_entry.existing.0.vzFilter.attributes.name == "anstest"' + - query_filter_entry.existing.0.vzFilter.children | length == 1 + - '"query-target-filter=eq(vzFilter.name, \"anstest\")" in query_filter_entry.filter_string' + - '"rsp-subtree-filter=eq(vzEntry.name, \"anstest\")" in query_filter_entry.filter_string' + - '"class/vzFilter.json" in query_filter_entry.url' + - query_tenant_entry.changed == false + - query_tenant_entry.existing | length == 1 + - 'query_tenant_entry.existing.0.fvTenant.attributes.name == "anstest"' + - '"rsp-subtree-filter=eq(vzEntry.name, \"anstest\")" in query_tenant_entry.filter_string' + - '"rsp-subtree-class=vzEntry" in query_tenant_entry.filter_string' + - '"tn-anstest.json" in query_tenant_entry.url' + - query_tenant_filter.changed == false + - query_tenant_filter.existing | length == 1 + - 'query_tenant_filter.existing.0.vzFilter.attributes.name == "anstest"' + - query_tenant_filter.existing.0.vzFilter.children | length == 4 + - '"rsp-subtree-class=vzEntry" in query_tenant_filter.filter_string' + - '"tn-anstest/flt-anstest.json" in query_tenant_filter.url' + - query_entry.changed == false + - 'query_entry.existing.0.vzEntry.attributes.name == "anstest"' + - '"query-target-filter=eq(vzEntry.name, \"anstest\")" in query_entry.filter_string' + - '"class/vzEntry.json" in query_entry.url' + - query_filter.changed == false + - 'query_filter.existing.0.vzFilter.attributes.name == "anstest"' + - '"query-target-filter=eq(vzFilter.name, \"anstest\")" in query_filter.filter_string' + - '"rsp-subtree-class=vzEntry" in query_filter.filter_string' + - '"class/vzFilter.json" in query_filter.url' + - query_tenant.changed == false + - query_tenant.existing | length == 1 + - 'query_tenant.existing.0.fvTenant.attributes.name == "anstest"' + - '"rsp-subtree-class=vzFilter,vzEntry" in query_tenant.filter_string' + - '"tn-anstest.json" in query_tenant.url' + - query_all.changed == false + - query_all.existing | length > 1 + - query_all.existing.0.vzEntry is defined + - '"class/vzEntry.json" in query_all.url' + +- name: delete entry - check mode works + aci_filter_entry: &aci_entry_absent + <<: *aci_entry_present + state: absent + check_mode: yes + register: entry_absent_check_mode + +- name: delete entry - deletion works + aci_filter_entry: + <<: *aci_entry_absent + register: entry_absent + +- name: delete entry - idempotency works + aci_filter_entry: + <<: *aci_entry_absent + register: entry_absent_idempotent + +- name: missing param - failure message works + aci_filter_entry: + <<: *aci_tenant_present + state: absent + ignore_errors: yes + register: absent_missing_param + +- name: cleanup remaining entries + aci_filter_entry: + <<: *aci_entry_absent + entry: "{{ item }}" + with_items: ["anstest2", "anstest3", "anstest4"] + +- name: absent assertions + assert: + that: + - entry_absent_check_mode.changed == true + - entry_absent_check_mode.existing != [] + - entry_absent.changed == true + - entry_absent.existing == entry_absent_check_mode.existing + - entry_absent.proposed == {} + - entry_absent_idempotent.changed == false + - entry_absent_idempotent.existing == [] + - absent_missing_param.failed == true + - 'absent_missing_param.msg == "state is absent but the following are missing: entry,filter"' + +- name: cleanup filter + aci_filter: + <<: *aci_filter_present + state: absent + when: filter_present.changed == true + +- name: cleanup tenant + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true diff --git a/test/integration/targets/aci_vrf/aliases b/test/integration/targets/aci_vrf/aliases new file mode 100644 index 0000000000..b4e2520c17 --- /dev/null +++ b/test/integration/targets/aci_vrf/aliases @@ -0,0 +1 @@ +# No AcI Simulator yet, so not enabled diff --git a/test/integration/targets/aci_vrf/tasks/main.yml b/test/integration/targets/aci_vrf/tasks/main.yml new file mode 100644 index 0000000000..fa9e1a4064 --- /dev/null +++ b/test/integration/targets/aci_vrf/tasks/main.yml @@ -0,0 +1,171 @@ +# Test code for the ACI modules +# Copyright 2017, Jacob McGill <jmcgill298 + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: ensure tenant exists for tests to kick off + aci_tenant: &aci_tenant_present + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: no + state: present + tenant: anstest + register: tenant_present + +- name: create vrf - check mode works + aci_vrf: &aci_vrf_present + <<: *aci_tenant_present + vrf: anstest + description: Ansible Test + check_mode: yes + register: vrf_present_check_mode + +- name: create vrf - creation works + aci_vrf: + <<: *aci_vrf_present + register: vrf_present + +- name: create vrf again - idempotency works + aci_vrf: + <<: *aci_vrf_present + register: vrf_present_idempotent + +- name: update vrf - update works + aci_vrf: + <<: *aci_vrf_present + description: Ansible Test Update + policy_control_preference: unenforced + register: vrf_update + +- name: create another vrf - check more params + aci_vrf: + <<: *aci_vrf_present + vrf: anstest2 + policy_control_direction: egress + register: vrf_present_2 + +- name: create vrf without all necessary params - failure message works + aci_vrf: + <<: *aci_vrf_present + tenant: "{{ fake_var | default(omit) }}" + ignore_errors: yes + register: vrf_present_missing_param + +- name: present asserts + assert: + that: + - vrf_present_check_mode.changed == true + - 'vrf_present_check_mode.config == {"fvCtx": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' + - vrf_present.changed == true + - vrf_present.config == vrf_present_check_mode.config + - vrf_present.existing == [] + - vrf_present_idempotent.changed == false + - vrf_present_idempotent.existing != [] + - vrf_update.changed == true + - vrf_update.existing != [] + - vrf_update.changed != vrf_update.proposed + - 'vrf_update.config == {"fvCtx": {"attributes": {"descr": "Ansible Test Update", "pcEnfPref": "unenforced"}}}' + - 'vrf_present_2.config.fvCtx.attributes == {"name": "anstest2", "pcEnfDir": "egress", "descr": "Ansible Test"}' + - vrf_present_missing_param.failed == true + - 'vrf_present_missing_param.msg == "state is present but the following are missing: tenant"' + +- name: get all vrf + aci_vrf: &aci_query + <<: *aci_tenant_present + state: query + tenant: "{{ fake_var | default(omit) }}" + register: query_all + +- name: get all in tenant + aci_vrf: + <<: *aci_query + tenant: anstest + register: query_tenant + +- name: get all with name + aci_vrf: + <<: *aci_query + vrf: anstest + register: query_vrf_vrf + +- name: get vrf + aci_vrf: + <<: *aci_vrf_present + state: query + register: query_vrf + +- name: query asserts + assert: + that: + - query_all.changed == false + - query_all.existing | length > 1 + - query_all.existing.0.fvCtx is defined + - '"class/fvCtx.json" in query_all.url' + - query_tenant.changed == false + - query_tenant.existing | length == 1 + - query_tenant.existing.0.fvTenant.children | length == 2 + - 'query_tenant.existing.0.fvTenant.attributes.name == "anstest"' + - '"rsp-subtree-class=fvCtx" in query_tenant.filter_string' + - '"tn-anstest.json" in query_tenant.url' + - query_vrf_vrf.changed == false + - query_vrf_vrf.existing != [] + - 'query_vrf_vrf.existing.0.fvCtx.attributes.name == "anstest"' + - '"query-target-filter=eq(fvCtx.name, \"anstest\")" in query_vrf_vrf.filter_string' + - '"class/fvCtx.json" in query_vrf_vrf.url' + - query_vrf.changed == false + - query_vrf.existing | length == 1 + - '"tn-anstest/ctx-anstest.json" in query_vrf.url' + +- name: delete vrf - check mode works + aci_vrf: &aci_vrf_absent + <<: *aci_vrf_present + state: absent + check_mode: yes + register: vrf_absent_check_mode + +- name: delete vrf - delete works + aci_vrf: + <<: *aci_vrf_absent + register: vrf_absent + +- name: delete vrf again - idempotency works + aci_vrf: + <<: *aci_vrf_absent + register: vrf_absent_idempotent + +- name: delete vrf - cleanup + aci_vrf: + <<: *aci_vrf_absent + name: anstest2 + +- name: delete vrf missing param - fails properly + aci_vrf: + <<: *aci_vrf_absent + vrf: "{{ fakevar | default(omit) }}" + ignore_errors: yes + register: vrf_absent_missing_param + +- name: asserts for deletion task + assert: + that: + - vrf_absent_check_mode.changed == true + - vrf_absent_check_mode.existing != [] + - vrf_absent_check_mode.proposed == {} + - vrf_absent.changed == true + - vrf_absent.existing == vrf_absent_check_mode.existing + - vrf_absent_idempotent.changed == false + - vrf_absent_idempotent.existing == [] + - vrf_absent_missing_param.failed == true + - 'vrf_absent_missing_param.msg == "state is absent but the following are missing: vrf"' + +- name: delete tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present.changed == true |