From a4ee1a3f098e97f0e6bdc0f3d20c3021d06cb343 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Wed, 4 Oct 2017 13:06:22 -0500 Subject: [PATCH] Merge tox, tests and other support files Change-Id: I5a4759e36089f1f4fab0c75412c94d051d8b16a7 --- .gitignore | 1 + .mailmap | 5 +- .stestr.conf | 3 + .testr.conf | 8 - CONTRIBUTING.rst | 47 +- HACKING.rst | 51 +- README.rst | 137 +++- shade/bindep.txt => bindep.txt | 0 devstack/plugin.sh | 54 ++ doc/source/conf.py | 34 +- .../{contributors => contributor}/clouds.yaml | 0 .../doc => doc}/source/contributor/coding.rst | 61 +- .../source/contributor/contributing.rst | 0 .../create/examples/resource/fake.py | 0 .../create/examples/resource/fake_service.py | 0 .../create/resource.rst | 0 .../{contributors => contributor}/index.rst | 19 + .../{contributors => contributor}/layout.rst | 0 .../{contributors => contributor}/layout.txt | 0 .../{contributors => contributor}/local.conf | 0 .../{contributors => contributor}/setup.rst | 0 .../{contributors => contributor}/testing.rst | 0 doc/source/history.rst | 1 - doc/source/index.rst | 10 +- doc/source/install/index.rst | 12 + doc/source/releasenotes.rst | 6 + .../source/user/config}/configuration.rst | 0 .../user => doc/source/user/config}/index.rst | 2 +- .../source/user/config}/network-config.rst | 0 .../source/user/config/reference.rst | 0 .../user => doc/source/user/config}/using.rst | 0 .../source/user/config}/vendor-support.rst | 0 .../source/user/examples/cleanup-servers.py | 0 .../user/examples/create-server-dict.py | 0 .../user/examples/create-server-name-or-id.py | 0 .../source/user/examples/debug-logging.py | 0 .../source/user/examples/find-an-image.py | 0 .../user/examples/http-debug-logging.py | 0 .../source/user/examples/munch-dict-object.py | 0 .../source/user/examples/normalization.py | 0 .../user/examples/server-information.py | 0 .../examples/service-conditional-overrides.py | 0 .../user/examples/service-conditionals.py | 0 .../source/user/examples/strict-mode.py | 0 .../user/examples/upload-large-object.py | 0 .../source/user/examples/upload-object.py | 0 .../source/user/examples/user-agent.py | 0 {shade/doc => doc}/source/user/index.rst | 1 + {shade/doc => doc}/source/user/logging.rst | 0 .../doc => doc}/source/user/microversions.rst | 0 {shade/doc => doc}/source/user/model.rst | 0 .../source/user/multi-cloud-demo.rst | 0 {shade/doc => doc}/source/user/usage.rst | 0 {shade/extras => extras}/delete-network.sh | 0 {shade/extras => extras}/install-tips.sh | 0 {shade/extras => extras}/run-ansible-tests.sh | 4 +- openstack/cloud/tests/unit/base.py | 646 ------------------ .../{cloud => }/tests/ansible/README.txt | 0 .../tests/ansible/hooks/post_test_hook.sh | 10 +- .../tests/ansible/roles/auth/tasks/main.yml | 0 .../roles/client_config/tasks/main.yml | 0 .../tests/ansible/roles/group/tasks/main.yml | 0 .../tests/ansible/roles/group/vars/main.yml | 0 .../tests/ansible/roles/image/tasks/main.yml | 0 .../tests/ansible/roles/image/vars/main.yml | 0 .../ansible/roles/keypair/tasks/main.yml | 0 .../tests/ansible/roles/keypair/vars/main.yml | 0 .../roles/keystone_domain/tasks/main.yml | 0 .../roles/keystone_domain/vars/main.yml | 0 .../roles/keystone_role/tasks/main.yml | 0 .../ansible/roles/keystone_role/vars/main.yml | 0 .../ansible/roles/network/tasks/main.yml | 0 .../tests/ansible/roles/network/vars/main.yml | 0 .../ansible/roles/nova_flavor/tasks/main.yml | 0 .../tests/ansible/roles/object/tasks/main.yml | 0 .../tests/ansible/roles/port/tasks/main.yml | 0 .../tests/ansible/roles/port/vars/main.yml | 0 .../tests/ansible/roles/router/tasks/main.yml | 0 .../tests/ansible/roles/router/vars/main.yml | 0 .../roles/security_group/tasks/main.yml | 0 .../roles/security_group/vars/main.yml | 0 .../tests/ansible/roles/server/tasks/main.yml | 0 .../tests/ansible/roles/server/vars/main.yaml | 0 .../tests/ansible/roles/subnet/tasks/main.yml | 0 .../tests/ansible/roles/subnet/vars/main.yml | 0 .../tests/ansible/roles/user/tasks/main.yml | 0 .../ansible/roles/user_group/tasks/main.yml | 0 .../tests/ansible/roles/volume/tasks/main.yml | 0 openstack/{cloud => }/tests/ansible/run.yml | 0 openstack/{cloud => }/tests/base.py | 0 openstack/{cloud => }/tests/fakes.py | 0 .../functional/cloud}/__init__.py | 0 .../functional/cloud}/base.py | 10 +- .../functional/cloud}/hooks/post_test_hook.sh | 10 +- .../functional/cloud}/test_aggregate.py | 0 .../cloud}/test_cluster_templates.py | 0 .../functional/cloud}/test_compute.py | 0 .../functional/cloud}/test_devstack.py | 5 +- .../functional/cloud}/test_domain.py | 0 .../functional/cloud}/test_endpoints.py | 0 .../functional/cloud}/test_flavor.py | 0 .../functional/cloud}/test_floating_ip.py | 0 .../cloud}/test_floating_ip_pool.py | 0 .../functional/cloud}/test_groups.py | 0 .../functional/cloud}/test_identity.py | 0 .../functional/cloud}/test_image.py | 0 .../functional/cloud}/test_inventory.py | 0 .../functional/cloud}/test_keypairs.py | 0 .../functional/cloud}/test_limits.py | 0 .../functional/cloud}/test_magnum_services.py | 0 .../functional/cloud}/test_network.py | 0 .../functional/cloud}/test_object.py | 0 .../functional/cloud}/test_port.py | 0 .../functional/cloud}/test_project.py | 0 .../cloud}/test_qos_bandwidth_limit_rule.py | 0 .../cloud}/test_qos_dscp_marking_rule.py | 0 .../cloud}/test_qos_minimum_bandwidth_rule.py | 0 .../functional/cloud}/test_qos_policy.py | 0 .../functional/cloud}/test_quotas.py | 0 .../functional/cloud}/test_range_search.py | 0 .../functional/cloud}/test_recordset.py | 0 .../functional/cloud}/test_router.py | 0 .../functional/cloud}/test_security_groups.py | 0 .../functional/cloud}/test_server_group.py | 0 .../functional/cloud}/test_services.py | 0 .../functional/cloud}/test_stack.py | 0 .../functional/cloud}/test_usage.py | 0 .../functional/cloud}/test_users.py | 0 .../functional/cloud}/test_volume.py | 0 .../functional/cloud}/test_volume_backup.py | 0 .../functional/cloud}/test_volume_type.py | 0 .../functional/cloud}/test_zone.py | 0 .../functional/cloud}/util.py | 2 +- openstack/tests/unit/base.py | 636 ++++++++++++++++- .../unit => tests/unit/cloud}/__init__.py | 0 .../unit/cloud}/test__adapter.py | 0 .../unit => tests/unit/cloud}/test__utils.py | 0 .../unit/cloud}/test_aggregate.py | 0 .../unit/cloud}/test_availability_zones.py | 0 .../unit/cloud}/test_baremetal_node.py | 0 .../unit => tests/unit/cloud}/test_caching.py | 0 .../unit/cloud}/test_cluster_templates.py | 0 .../unit/cloud}/test_create_server.py | 0 .../cloud}/test_create_volume_snapshot.py | 0 .../unit/cloud}/test_delete_server.py | 0 .../cloud}/test_delete_volume_snapshot.py | 0 .../unit/cloud}/test_domain_params.py | 0 .../unit => tests/unit/cloud}/test_domains.py | 0 .../unit/cloud}/test_endpoints.py | 0 .../unit => tests/unit/cloud}/test_flavors.py | 0 .../unit/cloud}/test_floating_ip_common.py | 0 .../unit/cloud}/test_floating_ip_neutron.py | 0 .../unit/cloud}/test_floating_ip_nova.py | 0 .../unit/cloud}/test_floating_ip_pool.py | 0 .../unit => tests/unit/cloud}/test_groups.py | 0 .../unit/cloud}/test_identity_roles.py | 0 .../unit => tests/unit/cloud}/test_image.py | 0 .../unit/cloud}/test_image_snapshot.py | 0 .../unit/cloud}/test_inventory.py | 0 .../unit => tests/unit/cloud}/test_keypair.py | 0 .../unit => tests/unit/cloud}/test_limits.py | 0 .../unit/cloud}/test_magnum_services.py | 0 .../unit => tests/unit/cloud}/test_meta.py | 0 .../unit => tests/unit/cloud}/test_network.py | 0 .../unit/cloud}/test_normalize.py | 0 .../unit => tests/unit/cloud}/test_object.py | 0 .../unit/cloud}/test_operator_noauth.py | 0 .../unit => tests/unit/cloud}/test_port.py | 0 .../unit => tests/unit/cloud}/test_project.py | 0 .../cloud}/test_qos_bandwidth_limit_rule.py | 0 .../unit/cloud}/test_qos_dscp_marking_rule.py | 0 .../cloud}/test_qos_minimum_bandwidth_rule.py | 0 .../unit/cloud}/test_qos_policy.py | 0 .../unit/cloud}/test_qos_rule_type.py | 0 .../unit => tests/unit/cloud}/test_quotas.py | 0 .../unit/cloud}/test_rebuild_server.py | 0 .../unit/cloud}/test_recordset.py | 0 .../unit/cloud}/test_role_assignment.py | 0 .../unit => tests/unit/cloud}/test_router.py | 0 .../unit/cloud}/test_security_groups.py | 0 .../unit/cloud}/test_server_console.py | 0 .../cloud}/test_server_delete_metadata.py | 0 .../unit/cloud}/test_server_group.py | 0 .../unit/cloud}/test_server_set_metadata.py | 0 .../unit/cloud}/test_services.py | 0 .../unit => tests/unit/cloud}/test_shade.py | 0 .../unit/cloud}/test_shade_operator.py | 0 .../unit => tests/unit/cloud}/test_stack.py | 0 .../unit => tests/unit/cloud}/test_subnet.py | 0 .../unit/cloud}/test_task_manager.py | 0 .../unit/cloud}/test_update_server.py | 0 .../unit => tests/unit/cloud}/test_usage.py | 0 .../unit => tests/unit/cloud}/test_users.py | 0 .../unit => tests/unit/cloud}/test_volume.py | 0 .../unit/cloud}/test_volume_access.py | 0 .../unit/cloud}/test_volume_backups.py | 0 .../unit => tests/unit/cloud}/test_zone.py | 0 .../tests/unit/fixtures/baremetal.json | 0 .../tests/unit/fixtures/catalog-v2.json | 0 .../tests/unit/fixtures/catalog-v3.json | 0 .../tests/unit/fixtures/clouds/clouds.yaml | 0 .../unit/fixtures/clouds/clouds_cache.yaml | 0 .../tests/unit/fixtures/discovery.json | 0 .../{cloud => }/tests/unit/fixtures/dns.json | 0 .../unit/fixtures/image-version-broken.json | 0 .../tests/unit/fixtures/image-version-v1.json | 0 .../tests/unit/fixtures/image-version-v2.json | 0 .../tests/unit/fixtures/image-version.json | 0 os-client-config/.coveragerc | 7 - os-client-config/.gitignore | 55 -- os-client-config/.gitreview | 4 - os-client-config/.mailmap | 3 - os-client-config/.stestr.conf | 3 - os-client-config/.testr.conf | 7 - os-client-config/CONTRIBUTING.rst | 16 - os-client-config/HACKING.rst | 4 - os-client-config/LICENSE | 175 ----- os-client-config/README.rst | 25 - os-client-config/doc/source/conf.py | 86 --- .../doc/source/contributor/index.rst | 4 - os-client-config/doc/source/index.rst | 32 - os-client-config/doc/source/install/index.rst | 12 - .../doc/source/user/releasenotes.rst | 6 - os-client-config/requirements.txt | 7 - os-client-config/setup.cfg | 35 - os-client-config/setup.py | 29 - os-client-config/test-requirements.txt | 21 - os-client-config/tox.ini | 45 -- releasenotes/source/conf.py | 8 +- requirements.txt | 18 +- setup.cfg | 1 - shade/.coveragerc | 7 - shade/.gitignore | 54 -- shade/.gitreview | 4 - shade/.mailmap | 4 - shade/.stestr.conf | 3 - shade/.zuul.yaml | 8 - shade/CONTRIBUTING.rst | 44 -- shade/HACKING.rst | 49 -- shade/LICENSE | 175 ----- shade/MANIFEST.in | 6 - shade/README.rst | 79 --- shade/devstack/plugin.sh | 54 -- shade/doc/source/conf.py | 47 -- shade/doc/source/contributor/index.rst | 9 - shade/doc/source/index.rst | 31 - shade/doc/source/install/index.rst | 12 - shade/doc/source/releasenotes/index.rst | 5 - shade/requirements.txt | 26 - shade/setup.cfg | 28 - shade/setup.py | 29 - shade/test-requirements.txt | 17 - shade/tools/tox_install.sh | 30 - shade/tox.ini | 80 --- test-requirements.txt | 12 +- .../tools => tools}/keystone_version.py | 0 .../tools => tools}/nova_version.py | 0 .../tools => tools}/tox_install.sh | 0 tox.ini | 61 +- 259 files changed, 1049 insertions(+), 2203 deletions(-) create mode 100644 .stestr.conf delete mode 100644 .testr.conf rename shade/bindep.txt => bindep.txt (100%) create mode 100644 devstack/plugin.sh rename doc/source/{contributors => contributor}/clouds.yaml (100%) rename {shade/doc => doc}/source/contributor/coding.rst (70%) rename {shade/doc => doc}/source/contributor/contributing.rst (100%) rename doc/source/{contributors => contributor}/create/examples/resource/fake.py (100%) rename doc/source/{contributors => contributor}/create/examples/resource/fake_service.py (100%) rename doc/source/{contributors => contributor}/create/resource.rst (100%) rename doc/source/{contributors => contributor}/index.rst (89%) rename doc/source/{contributors => contributor}/layout.rst (100%) rename doc/source/{contributors => contributor}/layout.txt (100%) rename doc/source/{contributors => contributor}/local.conf (100%) rename doc/source/{contributors => contributor}/setup.rst (100%) rename doc/source/{contributors => contributor}/testing.rst (100%) delete mode 100644 doc/source/history.rst create mode 100644 doc/source/install/index.rst create mode 100644 doc/source/releasenotes.rst rename {os-client-config/doc/source/user => doc/source/user/config}/configuration.rst (100%) rename {os-client-config/doc/source/user => doc/source/user/config}/index.rst (91%) rename {os-client-config/doc/source/user => doc/source/user/config}/network-config.rst (100%) rename os-client-config/doc/source/reference/index.rst => doc/source/user/config/reference.rst (100%) rename {os-client-config/doc/source/user => doc/source/user/config}/using.rst (100%) rename {os-client-config/doc/source/user => doc/source/user/config}/vendor-support.rst (100%) rename {shade/doc => doc}/source/user/examples/cleanup-servers.py (100%) rename {shade/doc => doc}/source/user/examples/create-server-dict.py (100%) rename {shade/doc => doc}/source/user/examples/create-server-name-or-id.py (100%) rename {shade/doc => doc}/source/user/examples/debug-logging.py (100%) rename {shade/doc => doc}/source/user/examples/find-an-image.py (100%) rename {shade/doc => doc}/source/user/examples/http-debug-logging.py (100%) rename {shade/doc => doc}/source/user/examples/munch-dict-object.py (100%) rename {shade/doc => doc}/source/user/examples/normalization.py (100%) rename {shade/doc => doc}/source/user/examples/server-information.py (100%) rename {shade/doc => doc}/source/user/examples/service-conditional-overrides.py (100%) rename {shade/doc => doc}/source/user/examples/service-conditionals.py (100%) rename {shade/doc => doc}/source/user/examples/strict-mode.py (100%) rename {shade/doc => doc}/source/user/examples/upload-large-object.py (100%) rename {shade/doc => doc}/source/user/examples/upload-object.py (100%) rename {shade/doc => doc}/source/user/examples/user-agent.py (100%) rename {shade/doc => doc}/source/user/index.rst (95%) rename {shade/doc => doc}/source/user/logging.rst (100%) rename {shade/doc => doc}/source/user/microversions.rst (100%) rename {shade/doc => doc}/source/user/model.rst (100%) rename {shade/doc => doc}/source/user/multi-cloud-demo.rst (100%) rename {shade/doc => doc}/source/user/usage.rst (100%) rename {shade/extras => extras}/delete-network.sh (100%) rename {shade/extras => extras}/install-tips.sh (100%) rename {shade/extras => extras}/run-ansible-tests.sh (92%) delete mode 100644 openstack/cloud/tests/unit/base.py rename openstack/{cloud => }/tests/ansible/README.txt (100%) rename openstack/{cloud => }/tests/ansible/hooks/post_test_hook.sh (81%) rename openstack/{cloud => }/tests/ansible/roles/auth/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/client_config/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/group/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/group/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/image/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/image/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/keypair/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/keypair/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/keystone_domain/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/keystone_domain/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/keystone_role/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/keystone_role/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/network/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/network/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/nova_flavor/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/object/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/port/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/port/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/router/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/router/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/security_group/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/security_group/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/server/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/server/vars/main.yaml (100%) rename openstack/{cloud => }/tests/ansible/roles/subnet/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/subnet/vars/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/user/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/user_group/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/roles/volume/tasks/main.yml (100%) rename openstack/{cloud => }/tests/ansible/run.yml (100%) rename openstack/{cloud => }/tests/base.py (100%) rename openstack/{cloud => }/tests/fakes.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/__init__.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/base.py (90%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/hooks/post_test_hook.sh (88%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_aggregate.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_cluster_templates.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_compute.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_devstack.py (89%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_domain.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_endpoints.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_flavor.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_floating_ip.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_floating_ip_pool.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_groups.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_identity.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_image.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_inventory.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_keypairs.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_limits.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_magnum_services.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_network.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_object.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_port.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_project.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_qos_bandwidth_limit_rule.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_qos_dscp_marking_rule.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_qos_minimum_bandwidth_rule.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_qos_policy.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_quotas.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_range_search.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_recordset.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_router.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_security_groups.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_server_group.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_services.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_stack.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_usage.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_users.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_volume.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_volume_backup.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_volume_type.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/test_zone.py (100%) rename openstack/{cloud/tests/functional => tests/functional/cloud}/util.py (95%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/__init__.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test__adapter.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test__utils.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_aggregate.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_availability_zones.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_baremetal_node.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_caching.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_cluster_templates.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_create_server.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_create_volume_snapshot.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_delete_server.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_delete_volume_snapshot.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_domain_params.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_domains.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_endpoints.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_flavors.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_floating_ip_common.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_floating_ip_neutron.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_floating_ip_nova.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_floating_ip_pool.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_groups.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_identity_roles.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_image.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_image_snapshot.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_inventory.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_keypair.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_limits.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_magnum_services.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_meta.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_network.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_normalize.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_object.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_operator_noauth.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_port.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_project.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_qos_bandwidth_limit_rule.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_qos_dscp_marking_rule.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_qos_minimum_bandwidth_rule.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_qos_policy.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_qos_rule_type.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_quotas.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_rebuild_server.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_recordset.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_role_assignment.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_router.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_security_groups.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_server_console.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_server_delete_metadata.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_server_group.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_server_set_metadata.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_services.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_shade.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_shade_operator.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_stack.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_subnet.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_task_manager.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_update_server.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_usage.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_users.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_volume.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_volume_access.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_volume_backups.py (100%) rename openstack/{cloud/tests/unit => tests/unit/cloud}/test_zone.py (100%) rename openstack/{cloud => }/tests/unit/fixtures/baremetal.json (100%) rename openstack/{cloud => }/tests/unit/fixtures/catalog-v2.json (100%) rename openstack/{cloud => }/tests/unit/fixtures/catalog-v3.json (100%) rename openstack/{cloud => }/tests/unit/fixtures/clouds/clouds.yaml (100%) rename openstack/{cloud => }/tests/unit/fixtures/clouds/clouds_cache.yaml (100%) rename openstack/{cloud => }/tests/unit/fixtures/discovery.json (100%) rename openstack/{cloud => }/tests/unit/fixtures/dns.json (100%) rename openstack/{cloud => }/tests/unit/fixtures/image-version-broken.json (100%) rename openstack/{cloud => }/tests/unit/fixtures/image-version-v1.json (100%) rename openstack/{cloud => }/tests/unit/fixtures/image-version-v2.json (100%) rename openstack/{cloud => }/tests/unit/fixtures/image-version.json (100%) delete mode 100644 os-client-config/.coveragerc delete mode 100644 os-client-config/.gitignore delete mode 100644 os-client-config/.gitreview delete mode 100644 os-client-config/.mailmap delete mode 100644 os-client-config/.stestr.conf delete mode 100644 os-client-config/.testr.conf delete mode 100644 os-client-config/CONTRIBUTING.rst delete mode 100644 os-client-config/HACKING.rst delete mode 100644 os-client-config/LICENSE delete mode 100644 os-client-config/README.rst delete mode 100755 os-client-config/doc/source/conf.py delete mode 100644 os-client-config/doc/source/contributor/index.rst delete mode 100644 os-client-config/doc/source/index.rst delete mode 100644 os-client-config/doc/source/install/index.rst delete mode 100644 os-client-config/doc/source/user/releasenotes.rst delete mode 100644 os-client-config/requirements.txt delete mode 100644 os-client-config/setup.cfg delete mode 100644 os-client-config/setup.py delete mode 100644 os-client-config/test-requirements.txt delete mode 100644 os-client-config/tox.ini delete mode 100644 shade/.coveragerc delete mode 100644 shade/.gitignore delete mode 100644 shade/.gitreview delete mode 100644 shade/.mailmap delete mode 100644 shade/.stestr.conf delete mode 100644 shade/.zuul.yaml delete mode 100644 shade/CONTRIBUTING.rst delete mode 100644 shade/HACKING.rst delete mode 100644 shade/LICENSE delete mode 100644 shade/MANIFEST.in delete mode 100644 shade/README.rst delete mode 100644 shade/devstack/plugin.sh delete mode 100755 shade/doc/source/conf.py delete mode 100644 shade/doc/source/contributor/index.rst delete mode 100644 shade/doc/source/index.rst delete mode 100644 shade/doc/source/install/index.rst delete mode 100644 shade/doc/source/releasenotes/index.rst delete mode 100644 shade/requirements.txt delete mode 100644 shade/setup.cfg delete mode 100644 shade/setup.py delete mode 100644 shade/test-requirements.txt delete mode 100755 shade/tools/tox_install.sh delete mode 100644 shade/tox.ini rename {os-client-config/tools => tools}/keystone_version.py (100%) rename {os-client-config/tools => tools}/nova_version.py (100%) rename {os-client-config/tools => tools}/tox_install.sh (100%) diff --git a/.gitignore b/.gitignore index f8b6eb209..70c3c4095 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ cover/* .tox nosetests.xml .testrepository +.stestr # Translations *.mo diff --git a/.mailmap b/.mailmap index cc92f17b8..c7b4804d7 100644 --- a/.mailmap +++ b/.mailmap @@ -1,3 +1,6 @@ # Format is: # -# \ No newline at end of file +# + + + diff --git a/.stestr.conf b/.stestr.conf new file mode 100644 index 000000000..9ac1db7de --- /dev/null +++ b/.stestr.conf @@ -0,0 +1,3 @@ +[DEFAULT] +test_path=./openstack/cloud/tests/unit +top_dir=./ diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index 499b7a370..000000000 --- a/.testr.conf +++ /dev/null @@ -1,8 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./openstack/tests/unit} $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list -group_regex=([^\.]+\.)+ diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 8fee79414..e74b8dc19 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,16 +1,45 @@ -If you would like to contribute to the development of OpenStack, -you must follow the steps in this page: +.. _contributing: - http://docs.openstack.org/infra/manual/developers.html +=================================== +Contributing to python-openstacksdk +=================================== -Once those steps have been completed, changes to OpenStack -should be submitted for review via the Gerrit tool, following -the workflow documented at: +If you're interested in contributing to the python-openstacksdk project, +the following will help get you started. - http://docs.openstack.org/infra/manual/developers.html#development-workflow +Contributor License Agreement +----------------------------- +.. index:: + single: license; agreement + +In order to contribute to the python-openstacksdk project, you need to have +signed OpenStack's contributor's agreement. + +Please read `DeveloperWorkflow`_ before sending your first patch for review. Pull requests submitted through GitHub will be ignored. -Bugs should be filed on Launchpad, not GitHub: +.. seealso:: - https://bugs.launchpad.net/python-openstacksdk \ No newline at end of file + * http://wiki.openstack.org/HowToContribute + * http://wiki.openstack.org/CLA + +.. _DeveloperWorkflow: http://docs.openstack.org/infra/manual/developers.html#development-workflow + +Project Hosting Details +------------------------- + +Project Documentation + http://docs.openstack.org/sdks/python/openstacksdk/ + +Bug tracker + http://storyboard.openstack.org + +Mailing list (prefix subjects with ``[sdk]`` for faster responses) + http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev + +Code Hosting + https://git.openstack.org/cgit/openstack/python-openstacksdk + +Code Review + https://review.openstack.org/#/q/status:open+project:openstack/python-openstacksdk,n,z diff --git a/HACKING.rst b/HACKING.rst index e7627c519..c9a0b9682 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -1,4 +1,49 @@ -python-openstacksdk Style Commandments -====================================== +openstacksdk Style Commandments +=============================== -Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ +Read the OpenStack Style Commandments +http://docs.openstack.org/developer/hacking/ + +Indentation +----------- + +PEP-8 allows for 'visual' indentation. Do not use it. Visual indentation looks +like this: + +.. code-block:: python + + return_value = self.some_method(arg1, arg1, + arg3, arg4) + +Visual indentation makes refactoring the code base unneccesarily hard. + +Instead of visual indentation, use this: + +.. code-block:: python + + return_value = self.some_method( + arg1, arg1, arg3, arg4) + +That way, if some_method ever needs to be renamed, the only line that needs +to be touched is the line with some_method. Additionaly, if you need to +line break at the top of a block, please indent the continuation line +an additional 4 spaces, like this: + +.. code-block:: python + + for val in self.some_method( + arg1, arg1, arg3, arg4): + self.do_something_awesome() + +Neither of these are 'mandated' by PEP-8. However, they are prevailing styles +within this code base. + +Unit Tests +---------- + +Unit tests should be virtually instant. If a unit test takes more than 1 second +to run, it is a bad unit test. Honestly, 1 second is too slow. + +All unit test classes should subclass `openstack.cloud.tests.unit.base.BaseTestCase`. The +base TestCase class takes care of properly creating `OpenStackCloud` objects +in a way that protects against local environment. diff --git a/README.rst b/README.rst index a75f448a6..88575d3b6 100644 --- a/README.rst +++ b/README.rst @@ -1,36 +1,119 @@ -OpenStack Python SDK -==================== +openstacksdk +============ -The ``python-openstacksdk`` is a collection of libraries for building -applications to work with OpenStack clouds. The project aims to provide -a consistent and complete set of interactions with OpenStack's many -services, along with complete documentation, examples, and tools. +openstacksdk is a client library for for building applications to work +with OpenStack clouds. The project aims to provide a consistent and +complete set of interactions with OpenStack's many services, along with +complete documentation, examples, and tools. -This SDK is under active development, and in the interests of providing -a high-quality interface, the APIs provided in this release may differ -from those provided in future release. +It also contains a simple interface layer. Clouds can do many things, but +there are probably only about 10 of them that most people care about with any +regularity. If you want to do complicated things, the per-service oriented +portions of the SDK are for you. However, if what you want is to be able to +write an application that talks to clouds no matter what crazy choices the +deployer has made in an attempt to be more hipster than their self-entitled +narcissist peers, then the ``openstack.cloud`` layer is for you. -Usage ------ +A Brief History +--------------- -The following example simply connects to an OpenStack cloud and lists -the containers in the Object Store service.:: +openstacksdk started its life as three different libraries: shade, +os-client-config and python-openstacksdk. - from openstack import connection - conn = connection.Connection(auth_url="http://openstack:5000/v3", - project_name="big_project", - username="SDK_user", - password="Super5ecretPassw0rd") - for container in conn.object_store.containers(): - print(container.name) +``shade`` started its life as some code inside of OpenStack Infra's nodepool +project, and as some code inside of Ansible. Ansible had a bunch of different +OpenStack related modules, and there was a ton of duplicated code. Eventually, +between refactoring that duplication into an internal library, and adding logic +and features that the OpenStack Infra team had developed to run client +applications at scale, it turned out that we'd written nine-tenths of what we'd +need to have a standalone library. -Documentation -------------- +``os-client-config`` was a library for collecting client configuration for +using an OpenStack cloud in a consistent and comprehensive manner. +In parallel, the python-openstacksdk team was working on a library to expose +the OpenStack APIs to developers in a consistent and predictable manner. After +a while it became clear that there was value in both a high-level layer that +contains business logic, a lower-level SDK that exposes services and their +resources as Python objects, and also to be able to make direct REST calls +when needed with a properly configured Session or Adapter from python-requests. +This led to the merger of the three projects. -Documentation is available at -http://developer.openstack.org/sdks/python/openstacksdk/ +The contents of the shade library have been moved into ``openstack.cloud`` +and os-client-config has been moved in to ``openstack.config``. The next +release of shade will be a thin compatibility layer that subclasses the objects +from ``openstack.cloud`` and provides different argument defaults where needed +for compat. Similarly the next release of os-client-config will be a compat +layer shim around ``openstack.config``. -License -------- +openstack.config +================ -Apache 2.0 +``openstack.config`` will find cloud configuration for as few as 1 clouds and +as many as you want to put in a config file. It will read environment variables +and config files, and it also contains some vendor specific default values so +that you don't have to know extra info to use OpenStack + +* If you have a config file, you will get the clouds listed in it +* If you have environment variables, you will get a cloud named `envvars` +* If you have neither, you will get a cloud named `defaults` with base defaults + +Sometimes an example is nice. + +Create a ``clouds.yaml`` file: + +.. code-block:: yaml + + clouds: + mordred: + region_name: Dallas + auth: + username: 'mordred' + password: XXXXXXX + project_name: 'shade' + auth_url: 'https://identity.example.com' + +Please note: ``openstack.config`` will look for a file called ``clouds.yaml`` +in the following locations: + +* Current Directory +* ``~/.config/openstack`` +* ``/etc/openstack`` + +More information at https://developer.openstack.org/sdks/python/openstacksdk/users/config + +openstack.cloud +=============== + +Create a server using objects configured with the ``clouds.yaml`` file: + +.. code-block:: python + + import openstack.cloud + + # Initialize and turn on debug logging + openstack.cloud.simple_logging(debug=True) + + # Initialize cloud + # Cloud configs are read with openstack.config + cloud = openstack.cloud.openstack_cloud(cloud='mordred') + + # Upload an image to the cloud + image = cloud.create_image( + 'ubuntu-trusty', filename='ubuntu-trusty.qcow2', wait=True) + + # Find a flavor with at least 512M of RAM + flavor = cloud.get_flavor_by_ram(512) + + # Boot a server, wait for it to boot, and then do whatever is needed + # to get a public ip for it. + cloud.create_server( + 'my-server', image=image, flavor=flavor, wait=True, auto_ip=True) + +Links +===== + +* `Issue Tracker `_ +* `Code Review `_ +* `Documentation `_ +* `PyPI `_ +* `Mailing list `_ diff --git a/shade/bindep.txt b/bindep.txt similarity index 100% rename from shade/bindep.txt rename to bindep.txt diff --git a/devstack/plugin.sh b/devstack/plugin.sh new file mode 100644 index 000000000..4a710af2f --- /dev/null +++ b/devstack/plugin.sh @@ -0,0 +1,54 @@ +# Install and configure **openstacksdk** library in devstack +# +# To enable openstacksdk in devstack add an entry to local.conf that looks like +# +# [[local|localrc]] +# enable_plugin openstacksdk git://git.openstack.org/openstack/python-openstacksdk + +function preinstall_openstacksdk { + : +} + +function install_openstacksdk { + if use_library_from_git "python-openstacksdk"; then + # don't clone, it'll be done by the plugin install + setup_dev_lib "python-openstacksdk" + else + pip_install "python-openstacksdk" + fi +} + +function configure_openstacksdk { + : +} + +function initialize_openstacksdk { + : +} + +function unstack_openstacksdk { + : +} + +function clean_openstacksdk { + : +} + +# This is the main for plugin.sh +if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then + preinstall_openstacksdk +elif [[ "$1" == "stack" && "$2" == "install" ]]; then + install_openstacksdk +elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then + configure_openstacksdk +elif [[ "$1" == "stack" && "$2" == "extra" ]]; then + initialize_openstacksdk +fi + +if [[ "$1" == "unstack" ]]; then + unstack_openstacksdk +fi + +if [[ "$1" == "clean" ]]; then + clean_openstacksdk +fi diff --git a/doc/source/conf.py b/doc/source/conf.py index 6c4cbcf16..31351b480 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -19,16 +19,24 @@ import openstackdocstheme sys.path.insert(0, os.path.abspath('../..')) sys.path.insert(0, os.path.abspath('.')) + # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', + 'openstackdocstheme', 'enforcer' ] +# openstackdocstheme options +repository_name = 'openstack/python-openstacksdk' +bug_project = '760' +bug_tag = '' +html_last_updated_fmt = '%Y-%m-%d %H:%M' +html_theme = 'openstackdocs' + # When True, this will raise an exception that kills sphinx-build. enforcer_warnings_as_errors = True @@ -47,18 +55,7 @@ master_doc = 'index' # General information about the project. project = u'python-openstacksdk' -copyright = u'2015, OpenStack Foundation' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# "version" and "release" are used by the "log-a-bug" feature -# -# The short X.Y version. -version = '1.0' -# The full version, including alpha/beta/rc tags. -release = '1.0' +copyright = u'2017, Various members of the OpenStack Foundation' # A few variables have to be set for the log-a-bug feature. # giturl: The location of conf.py on Git. Must be set manually. @@ -101,13 +98,6 @@ exclude_patterns = [] # -- Options for HTML output ---------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'openstackdocs' - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = [openstackdocstheme.get_html_theme_path()] - # Don't let openstackdocstheme insert TOCs automatically. theme_include_auto_toc = False @@ -124,9 +114,5 @@ latex_documents = [ u'OpenStack Foundation', 'manual'), ] -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/3/': None, - 'http://docs.python-requests.org/en/master/': None} - # Include both the class and __init__ docstrings when describing the class autoclass_content = "both" diff --git a/doc/source/contributors/clouds.yaml b/doc/source/contributor/clouds.yaml similarity index 100% rename from doc/source/contributors/clouds.yaml rename to doc/source/contributor/clouds.yaml diff --git a/shade/doc/source/contributor/coding.rst b/doc/source/contributor/coding.rst similarity index 70% rename from shade/doc/source/contributor/coding.rst rename to doc/source/contributor/coding.rst index 851c18b1e..1cb45b9cc 100644 --- a/shade/doc/source/contributor/coding.rst +++ b/doc/source/contributor/coding.rst @@ -1,24 +1,24 @@ -******************************** -Shade Developer Coding Standards -******************************** +======================================== +OpenStack SDK Developer Coding Standards +======================================== In the beginning, there were no guidelines. And it was good. But that didn't last long. As more and more people added more and more code, we realized that we needed a set of coding standards to make sure that -the shade API at least *attempted* to display some form of consistency. +the openstacksdk API at least *attempted* to display some form of consistency. Thus, these coding standards/guidelines were developed. Note that not -all of shade adheres to these standards just yet. Some older code has +all of openstacksdk adheres to these standards just yet. Some older code has not been updated because we need to maintain backward compatibility. Some of it just hasn't been changed yet. But be clear, all new code *must* adhere to these guidelines. -Below are the patterns that we expect Shade developers to follow. +Below are the patterns that we expect openstacksdk developers to follow. Release Notes ============= -Shade uses `reno `_ for +openstacksdk uses `reno `_ for managing its release notes. A new release note should be added to your contribution anytime you add new API calls, fix significant bugs, add new functionality or parameters to existing API calls, or make any @@ -29,8 +29,17 @@ It is *not* necessary to add release notes for minor fixes, such as correction of documentation typos, minor code cleanup or reorganization, or any other change that a user would not notice through normal usage. -API Methods -=========== +Exceptions +========== + +Exceptions should NEVER be wrapped and re-raised inside of a new exception. +This removes important debug information from the user. All of the exceptions +should be raised correctly the first time. + +openstack.cloud API Methods +=========================== + +The `openstack.cloud` layer has some specific rules: - When an API call acts on a resource that has both a unique ID and a name, that API call should accept either identifier with a name_or_id @@ -50,21 +59,8 @@ API Methods - Deleting a resource should return True if the delete succeeded, or False if the resource was not found. -Exceptions -========== - -All underlying client exceptions must be captured and converted to an -`OpenStackCloudException` or one of its derivatives. - -REST Calls -============ - -All interactions with the cloud should be done with direct REST using -the appropriate `keystoneauth1.adapter.Adapter`. See Glance and Swift -calls for examples. - Returned Resources -================== +------------------ Complex objects returned to the caller must be a `munch.Munch` type. The `openstack.cloud._adapter.Adapter` class makes resources into `munch.Munch`. @@ -72,19 +68,20 @@ Complex objects returned to the caller must be a `munch.Munch` type. The All objects should be normalized. It is shade's purpose in life to make OpenStack consistent for end users, and this means not trusting the clouds to return consistent objects. There should be a normalize function in -`shade/_normalize.py` that is applied to objects before returning them to -the user. See :doc:`../user/model` for further details on object model requirements. +`openstack/cloud/_normalize.py` that is applied to objects before returning +them to the user. See :doc:`../user/model` for further details on object model +requirements. Fields should not be in the normalization contract if we cannot commit to providing them to all users. Fields should be renamed in normalization to be consistent with -the rest of openstack.cloud. For instance, nothing in shade exposes the legacy OpenStack -concept of "tenant" to a user, but instead uses "project" even if the -cloud uses tenant. +the rest of `openstack.cloud`. For instance, nothing in `openstack.cloud` +exposes the legacy OpenStack concept of "tenant" to a user, but instead uses +"project" even if the cloud in question uses tenant. Nova vs. Neutron -================ +---------------- - Recognize that not all cloud providers support Neutron, so never assume it will be present. If a task can be handled by either @@ -101,8 +98,10 @@ Tests - New API methods *must* have unit tests! - New unit tests should only mock at the REST layer using `requests_mock`. - Any mocking of shade itself or of legacy client libraries should be - considered legacy and to be avoided. + Any mocking of openstacksdk itself should be considered legacy and to be + avoided. Exceptions to this rule can be made when attempting to test the + internals of a logical shim where the inputs and output of the method aren't + actually impacted by remote content. - Functional tests should be added, when possible. diff --git a/shade/doc/source/contributor/contributing.rst b/doc/source/contributor/contributing.rst similarity index 100% rename from shade/doc/source/contributor/contributing.rst rename to doc/source/contributor/contributing.rst diff --git a/doc/source/contributors/create/examples/resource/fake.py b/doc/source/contributor/create/examples/resource/fake.py similarity index 100% rename from doc/source/contributors/create/examples/resource/fake.py rename to doc/source/contributor/create/examples/resource/fake.py diff --git a/doc/source/contributors/create/examples/resource/fake_service.py b/doc/source/contributor/create/examples/resource/fake_service.py similarity index 100% rename from doc/source/contributors/create/examples/resource/fake_service.py rename to doc/source/contributor/create/examples/resource/fake_service.py diff --git a/doc/source/contributors/create/resource.rst b/doc/source/contributor/create/resource.rst similarity index 100% rename from doc/source/contributors/create/resource.rst rename to doc/source/contributor/create/resource.rst diff --git a/doc/source/contributors/index.rst b/doc/source/contributor/index.rst similarity index 89% rename from doc/source/contributors/index.rst rename to doc/source/contributor/index.rst index 8b246a245..93e1884f0 100644 --- a/doc/source/contributors/index.rst +++ b/doc/source/contributor/index.rst @@ -13,6 +13,14 @@ software development kit for the programs which make up the OpenStack community. It is a set of Python-based libraries, documentation, examples, and tools released under the Apache 2 license. +Contribution Mechanics +---------------------- + +.. toctree:: + :maxdepth: 2 + + contributing + Contacting the Developers ------------------------- @@ -33,6 +41,17 @@ mailing list fields questions of all types on OpenStack. Using the ``[python-openstacksdk]`` filter to begin your email subject will ensure that the message gets to SDK developers. +Coding Standards +---------------- + +We are a bit stricter than usual in the coding standards department. It's a +good idea to read through the :doc:`coding ` section. + +.. toctree:: + :maxdepth: 2 + + coding + Development Environment ----------------------- diff --git a/doc/source/contributors/layout.rst b/doc/source/contributor/layout.rst similarity index 100% rename from doc/source/contributors/layout.rst rename to doc/source/contributor/layout.rst diff --git a/doc/source/contributors/layout.txt b/doc/source/contributor/layout.txt similarity index 100% rename from doc/source/contributors/layout.txt rename to doc/source/contributor/layout.txt diff --git a/doc/source/contributors/local.conf b/doc/source/contributor/local.conf similarity index 100% rename from doc/source/contributors/local.conf rename to doc/source/contributor/local.conf diff --git a/doc/source/contributors/setup.rst b/doc/source/contributor/setup.rst similarity index 100% rename from doc/source/contributors/setup.rst rename to doc/source/contributor/setup.rst diff --git a/doc/source/contributors/testing.rst b/doc/source/contributor/testing.rst similarity index 100% rename from doc/source/contributors/testing.rst rename to doc/source/contributor/testing.rst diff --git a/doc/source/history.rst b/doc/source/history.rst deleted file mode 100644 index 69ed4fe6c..000000000 --- a/doc/source/history.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../ChangeLog diff --git a/doc/source/index.rst b/doc/source/index.rst index e2c2bb526..bf7edc804 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -13,6 +13,10 @@ For Users :maxdepth: 2 users/index + install/index + user/index + +.. TODO(shade) merge users/index and user/index into user/index For Contributors ---------------- @@ -20,7 +24,9 @@ For Contributors .. toctree:: :maxdepth: 2 - contributors/index + contributor/index + +.. include:: ../../README.rst General Information ------------------- @@ -31,4 +37,4 @@ General information about the SDK including a glossary and release history. :maxdepth: 1 Glossary of Terms - Release History + Release Notes diff --git a/doc/source/install/index.rst b/doc/source/install/index.rst new file mode 100644 index 000000000..5b06c9812 --- /dev/null +++ b/doc/source/install/index.rst @@ -0,0 +1,12 @@ +============ +Installation +============ + +At the command line:: + + $ pip install python-openstacksdk + +Or, if you have virtualenv wrapper installed:: + + $ mkvirtualenv python-openstacksdk + $ pip install python-openstacksdk diff --git a/doc/source/releasenotes.rst b/doc/source/releasenotes.rst new file mode 100644 index 000000000..a61e4d3e3 --- /dev/null +++ b/doc/source/releasenotes.rst @@ -0,0 +1,6 @@ +============= +Release Notes +============= + +Release notes for `python-openstacksdk` can be found at +http://docs.openstack.org/releasenotes/python-openstacksdk/ diff --git a/os-client-config/doc/source/user/configuration.rst b/doc/source/user/config/configuration.rst similarity index 100% rename from os-client-config/doc/source/user/configuration.rst rename to doc/source/user/config/configuration.rst diff --git a/os-client-config/doc/source/user/index.rst b/doc/source/user/config/index.rst similarity index 91% rename from os-client-config/doc/source/user/index.rst rename to doc/source/user/config/index.rst index ec31c102c..d09b28351 100644 --- a/os-client-config/doc/source/user/index.rst +++ b/doc/source/user/config/index.rst @@ -9,4 +9,4 @@ using vendor-support network-config - releasenotes + reference diff --git a/os-client-config/doc/source/user/network-config.rst b/doc/source/user/config/network-config.rst similarity index 100% rename from os-client-config/doc/source/user/network-config.rst rename to doc/source/user/config/network-config.rst diff --git a/os-client-config/doc/source/reference/index.rst b/doc/source/user/config/reference.rst similarity index 100% rename from os-client-config/doc/source/reference/index.rst rename to doc/source/user/config/reference.rst diff --git a/os-client-config/doc/source/user/using.rst b/doc/source/user/config/using.rst similarity index 100% rename from os-client-config/doc/source/user/using.rst rename to doc/source/user/config/using.rst diff --git a/os-client-config/doc/source/user/vendor-support.rst b/doc/source/user/config/vendor-support.rst similarity index 100% rename from os-client-config/doc/source/user/vendor-support.rst rename to doc/source/user/config/vendor-support.rst diff --git a/shade/doc/source/user/examples/cleanup-servers.py b/doc/source/user/examples/cleanup-servers.py similarity index 100% rename from shade/doc/source/user/examples/cleanup-servers.py rename to doc/source/user/examples/cleanup-servers.py diff --git a/shade/doc/source/user/examples/create-server-dict.py b/doc/source/user/examples/create-server-dict.py similarity index 100% rename from shade/doc/source/user/examples/create-server-dict.py rename to doc/source/user/examples/create-server-dict.py diff --git a/shade/doc/source/user/examples/create-server-name-or-id.py b/doc/source/user/examples/create-server-name-or-id.py similarity index 100% rename from shade/doc/source/user/examples/create-server-name-or-id.py rename to doc/source/user/examples/create-server-name-or-id.py diff --git a/shade/doc/source/user/examples/debug-logging.py b/doc/source/user/examples/debug-logging.py similarity index 100% rename from shade/doc/source/user/examples/debug-logging.py rename to doc/source/user/examples/debug-logging.py diff --git a/shade/doc/source/user/examples/find-an-image.py b/doc/source/user/examples/find-an-image.py similarity index 100% rename from shade/doc/source/user/examples/find-an-image.py rename to doc/source/user/examples/find-an-image.py diff --git a/shade/doc/source/user/examples/http-debug-logging.py b/doc/source/user/examples/http-debug-logging.py similarity index 100% rename from shade/doc/source/user/examples/http-debug-logging.py rename to doc/source/user/examples/http-debug-logging.py diff --git a/shade/doc/source/user/examples/munch-dict-object.py b/doc/source/user/examples/munch-dict-object.py similarity index 100% rename from shade/doc/source/user/examples/munch-dict-object.py rename to doc/source/user/examples/munch-dict-object.py diff --git a/shade/doc/source/user/examples/normalization.py b/doc/source/user/examples/normalization.py similarity index 100% rename from shade/doc/source/user/examples/normalization.py rename to doc/source/user/examples/normalization.py diff --git a/shade/doc/source/user/examples/server-information.py b/doc/source/user/examples/server-information.py similarity index 100% rename from shade/doc/source/user/examples/server-information.py rename to doc/source/user/examples/server-information.py diff --git a/shade/doc/source/user/examples/service-conditional-overrides.py b/doc/source/user/examples/service-conditional-overrides.py similarity index 100% rename from shade/doc/source/user/examples/service-conditional-overrides.py rename to doc/source/user/examples/service-conditional-overrides.py diff --git a/shade/doc/source/user/examples/service-conditionals.py b/doc/source/user/examples/service-conditionals.py similarity index 100% rename from shade/doc/source/user/examples/service-conditionals.py rename to doc/source/user/examples/service-conditionals.py diff --git a/shade/doc/source/user/examples/strict-mode.py b/doc/source/user/examples/strict-mode.py similarity index 100% rename from shade/doc/source/user/examples/strict-mode.py rename to doc/source/user/examples/strict-mode.py diff --git a/shade/doc/source/user/examples/upload-large-object.py b/doc/source/user/examples/upload-large-object.py similarity index 100% rename from shade/doc/source/user/examples/upload-large-object.py rename to doc/source/user/examples/upload-large-object.py diff --git a/shade/doc/source/user/examples/upload-object.py b/doc/source/user/examples/upload-object.py similarity index 100% rename from shade/doc/source/user/examples/upload-object.py rename to doc/source/user/examples/upload-object.py diff --git a/shade/doc/source/user/examples/user-agent.py b/doc/source/user/examples/user-agent.py similarity index 100% rename from shade/doc/source/user/examples/user-agent.py rename to doc/source/user/examples/user-agent.py diff --git a/shade/doc/source/user/index.rst b/doc/source/user/index.rst similarity index 95% rename from shade/doc/source/user/index.rst rename to doc/source/user/index.rst index 0e576834a..26f35a7af 100644 --- a/shade/doc/source/user/index.rst +++ b/doc/source/user/index.rst @@ -5,6 +5,7 @@ .. toctree:: :maxdepth: 2 + config usage logging model diff --git a/shade/doc/source/user/logging.rst b/doc/source/user/logging.rst similarity index 100% rename from shade/doc/source/user/logging.rst rename to doc/source/user/logging.rst diff --git a/shade/doc/source/user/microversions.rst b/doc/source/user/microversions.rst similarity index 100% rename from shade/doc/source/user/microversions.rst rename to doc/source/user/microversions.rst diff --git a/shade/doc/source/user/model.rst b/doc/source/user/model.rst similarity index 100% rename from shade/doc/source/user/model.rst rename to doc/source/user/model.rst diff --git a/shade/doc/source/user/multi-cloud-demo.rst b/doc/source/user/multi-cloud-demo.rst similarity index 100% rename from shade/doc/source/user/multi-cloud-demo.rst rename to doc/source/user/multi-cloud-demo.rst diff --git a/shade/doc/source/user/usage.rst b/doc/source/user/usage.rst similarity index 100% rename from shade/doc/source/user/usage.rst rename to doc/source/user/usage.rst diff --git a/shade/extras/delete-network.sh b/extras/delete-network.sh similarity index 100% rename from shade/extras/delete-network.sh rename to extras/delete-network.sh diff --git a/shade/extras/install-tips.sh b/extras/install-tips.sh similarity index 100% rename from shade/extras/install-tips.sh rename to extras/install-tips.sh diff --git a/shade/extras/run-ansible-tests.sh b/extras/run-ansible-tests.sh similarity index 92% rename from shade/extras/run-ansible-tests.sh rename to extras/run-ansible-tests.sh index 37573b29d..bda6007c9 100755 --- a/shade/extras/run-ansible-tests.sh +++ b/extras/run-ansible-tests.sh @@ -66,7 +66,7 @@ then echo "Using existing Ansible source repo" else echo "Installing Ansible source repo at $ENVDIR" - git clone --recursive git://github.com/ansible/ansible.git ${ENVDIR}/ansible + git clone --recursive https://github.com/ansible/ansible.git ${ENVDIR}/ansible fi source $ENVDIR/ansible/hacking/env-setup else @@ -91,4 +91,4 @@ then exit 1 fi -ansible-playbook -vvv ./shade/tests/ansible/run.yml -e "cloud=${CLOUD} image=${IMAGE}" ${tag_opt} +ansible-playbook -vvv ./openstack/tests/ansible/run.yml -e "cloud=${CLOUD} image=${IMAGE}" ${tag_opt} diff --git a/openstack/cloud/tests/unit/base.py b/openstack/cloud/tests/unit/base.py deleted file mode 100644 index ffeefe019..000000000 --- a/openstack/cloud/tests/unit/base.py +++ /dev/null @@ -1,646 +0,0 @@ -# Copyright 2010-2011 OpenStack Foundation -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import collections -import time -import uuid - -import fixtures -import mock -import os -import openstack.config as occ -from requests import structures -from requests_mock.contrib import fixture as rm_fixture -from six.moves import urllib -import tempfile - -import openstack.cloud.openstackcloud -from openstack.cloud.tests import base - - -_ProjectData = collections.namedtuple( - 'ProjectData', - 'project_id, project_name, enabled, domain_id, description, ' - 'json_response, json_request') - - -_UserData = collections.namedtuple( - 'UserData', - 'user_id, password, name, email, description, domain_id, enabled, ' - 'json_response, json_request') - - -_GroupData = collections.namedtuple( - 'GroupData', - 'group_id, group_name, domain_id, description, json_response, ' - 'json_request') - - -_DomainData = collections.namedtuple( - 'DomainData', - 'domain_id, domain_name, description, json_response, ' - 'json_request') - - -_ServiceData = collections.namedtuple( - 'Servicedata', - 'service_id, service_name, service_type, description, enabled, ' - 'json_response_v3, json_response_v2, json_request') - - -_EndpointDataV3 = collections.namedtuple( - 'EndpointData', - 'endpoint_id, service_id, interface, region, url, enabled, ' - 'json_response, json_request') - - -_EndpointDataV2 = collections.namedtuple( - 'EndpointData', - 'endpoint_id, service_id, region, public_url, internal_url, ' - 'admin_url, v3_endpoint_list, json_response, ' - 'json_request') - - -# NOTE(notmorgan): Shade does not support domain-specific roles -# This should eventually be fixed if it becomes a main-stream feature. -_RoleData = collections.namedtuple( - 'RoleData', - 'role_id, role_name, json_response, json_request') - - -class BaseTestCase(base.TestCase): - - def setUp(self, cloud_config_fixture='clouds.yaml'): - """Run before each test method to initialize test environment.""" - - super(BaseTestCase, self).setUp() - - # Sleeps are for real testing, but unit tests shouldn't need them - realsleep = time.sleep - - def _nosleep(seconds): - return realsleep(seconds * 0.0001) - - self.sleep_fixture = self.useFixture(fixtures.MonkeyPatch( - 'time.sleep', - _nosleep)) - self.fixtures_directory = 'shade/tests/unit/fixtures' - - # Isolate os-client-config from test environment - config = tempfile.NamedTemporaryFile(delete=False) - cloud_path = '%s/clouds/%s' % (self.fixtures_directory, - cloud_config_fixture) - with open(cloud_path, 'rb') as f: - content = f.read() - config.write(content) - config.close() - - vendor = tempfile.NamedTemporaryFile(delete=False) - vendor.write(b'{}') - vendor.close() - - # set record mode depending on environment - record_mode = os.environ.get('BETAMAX_RECORD_FIXTURES', False) - if record_mode: - self.record_fixtures = 'new_episodes' - else: - self.record_fixtures = None - - test_cloud = os.environ.get('SHADE_OS_CLOUD', '_test_cloud_') - self.config = occ.OpenStackConfig( - config_files=[config.name], - vendor_files=[vendor.name], - secure_files=['non-existant']) - self.cloud_config = self.config.get_one_cloud( - cloud=test_cloud, validate=False) - self.cloud = openstack.cloud.OpenStackCloud( - cloud_config=self.cloud_config, - log_inner_exceptions=True) - self.strict_cloud = openstack.cloud.OpenStackCloud( - cloud_config=self.cloud_config, - log_inner_exceptions=True, - strict=True) - self.op_cloud = openstack.cloud.OperatorCloud( - cloud_config=self.cloud_config, - log_inner_exceptions=True) - - -class TestCase(BaseTestCase): - - def setUp(self, cloud_config_fixture='clouds.yaml'): - - super(TestCase, self).setUp(cloud_config_fixture=cloud_config_fixture) - self.session_fixture = self.useFixture(fixtures.MonkeyPatch( - 'os_client_config.cloud_config.CloudConfig.get_session', - mock.Mock())) - - -class RequestsMockTestCase(BaseTestCase): - - def setUp(self, cloud_config_fixture='clouds.yaml'): - - super(RequestsMockTestCase, self).setUp( - cloud_config_fixture=cloud_config_fixture) - - # FIXME(notmorgan): Convert the uri_registry, discovery.json, and - # use of keystone_v3/v2 to a proper fixtures.Fixture. For now this - # is acceptable, but eventually this should become it's own fixture - # that encapsulates the registry, registering the URIs, and - # assert_calls (and calling assert_calls every test case that uses - # it on cleanup). Subclassing here could be 100% eliminated in the - # future allowing any class to simply - # self.useFixture(openstack.cloud.RequestsMockFixture) and get all - # the benefits. - - # NOTE(notmorgan): use an ordered dict here to ensure we preserve the - # order in which items are added to the uri_registry. This makes - # the behavior more consistent when dealing with ensuring the - # requests_mock uri/query_string matchers are ordered and parse the - # request in the correct orders. - self._uri_registry = collections.OrderedDict() - self.discovery_json = os.path.join( - self.fixtures_directory, 'discovery.json') - self.use_keystone_v3() - self.__register_uris_called = False - - def get_mock_url(self, service_type, interface='public', resource=None, - append=None, base_url_append=None, - qs_elements=None): - endpoint_url = self.cloud.endpoint_for( - service_type=service_type, interface=interface) - # Strip trailing slashes, so as not to produce double-slashes below - if endpoint_url.endswith('/'): - endpoint_url = endpoint_url[:-1] - to_join = [endpoint_url] - qs = '' - if base_url_append: - to_join.append(base_url_append) - if resource: - to_join.append(resource) - to_join.extend(append or []) - if qs_elements is not None: - qs = '?%s' % '&'.join(qs_elements) - return '%(uri)s%(qs)s' % {'uri': '/'.join(to_join), 'qs': qs} - - def mock_for_keystone_projects(self, project=None, v3=True, - list_get=False, id_get=False, - project_list=None, project_count=None): - if project: - assert not (project_list or project_count) - elif project_list: - assert not (project or project_count) - elif project_count: - assert not (project or project_list) - else: - raise Exception('Must specify a project, project_list, ' - 'or project_count') - assert list_get or id_get - - base_url_append = 'v3' if v3 else None - if project: - project_list = [project] - elif project_count: - # Generate multiple projects - project_list = [self._get_project_data(v3=v3) - for c in range(0, project_count)] - uri_mock_list = [] - if list_get: - uri_mock_list.append( - dict(method='GET', - uri=self.get_mock_url( - service_type='identity', - interface='admin', - resource='projects', - base_url_append=base_url_append), - status_code=200, - json={'projects': [p.json_response['project'] - for p in project_list]}) - ) - if id_get: - for p in project_list: - uri_mock_list.append( - dict(method='GET', - uri=self.get_mock_url( - service_type='identity', - interface='admin', - resource='projects', - append=[p.project_id], - base_url_append=base_url_append), - status_code=200, - json=p.json_response) - ) - self.__do_register_uris(uri_mock_list) - return project_list - - def _get_project_data(self, project_name=None, enabled=None, - domain_id=None, description=None, v3=True, - project_id=None): - project_name = project_name or self.getUniqueString('projectName') - project_id = uuid.UUID(project_id or uuid.uuid4().hex).hex - response = {'id': project_id, 'name': project_name} - request = {'name': project_name} - domain_id = (domain_id or uuid.uuid4().hex) if v3 else None - if domain_id: - request['domain_id'] = domain_id - response['domain_id'] = domain_id - if enabled is not None: - enabled = bool(enabled) - response['enabled'] = enabled - request['enabled'] = enabled - response.setdefault('enabled', True) - request.setdefault('enabled', True) - if description: - response['description'] = description - request['description'] = description - request.setdefault('description', None) - if v3: - project_key = 'project' - else: - project_key = 'tenant' - return _ProjectData(project_id, project_name, enabled, domain_id, - description, {project_key: response}, - {project_key: request}) - - def _get_group_data(self, name=None, domain_id=None, description=None): - group_id = uuid.uuid4().hex - name = name or self.getUniqueString('groupname') - domain_id = uuid.UUID(domain_id or uuid.uuid4().hex).hex - response = {'id': group_id, 'name': name, 'domain_id': domain_id} - request = {'name': name, 'domain_id': domain_id} - if description is not None: - response['description'] = description - request['description'] = description - - return _GroupData(group_id, name, domain_id, description, - {'group': response}, {'group': request}) - - def _get_user_data(self, name=None, password=None, **kwargs): - - name = name or self.getUniqueString('username') - password = password or self.getUniqueString('user_password') - user_id = uuid.uuid4().hex - - response = {'name': name, 'id': user_id} - request = {'name': name, 'password': password} - - if kwargs.get('domain_id'): - kwargs['domain_id'] = uuid.UUID(kwargs['domain_id']).hex - response['domain_id'] = kwargs.pop('domain_id') - request['domain_id'] = response['domain_id'] - - response['email'] = kwargs.pop('email', None) - request['email'] = response['email'] - - response['enabled'] = kwargs.pop('enabled', True) - request['enabled'] = response['enabled'] - - response['description'] = kwargs.pop('description', None) - if response['description']: - request['description'] = response['description'] - - self.assertIs(0, len(kwargs), message='extra key-word args received ' - 'on _get_user_data') - - return _UserData(user_id, password, name, response['email'], - response['description'], response.get('domain_id'), - response.get('enabled'), {'user': response}, - {'user': request}) - - def _get_domain_data(self, domain_name=None, description=None, - enabled=None): - domain_id = uuid.uuid4().hex - domain_name = domain_name or self.getUniqueString('domainName') - response = {'id': domain_id, 'name': domain_name} - request = {'name': domain_name} - if enabled is not None: - request['enabled'] = bool(enabled) - response['enabled'] = bool(enabled) - if description: - response['description'] = description - request['description'] = description - response.setdefault('enabled', True) - return _DomainData(domain_id, domain_name, description, - {'domain': response}, {'domain': request}) - - def _get_service_data(self, type=None, name=None, description=None, - enabled=True): - service_id = uuid.uuid4().hex - name = name or uuid.uuid4().hex - type = type or uuid.uuid4().hex - - response = {'id': service_id, 'name': name, 'type': type, - 'enabled': enabled} - if description is not None: - response['description'] = description - request = response.copy() - request.pop('id') - return _ServiceData(service_id, name, type, description, enabled, - {'service': response}, - {'OS-KSADM:service': response}, request) - - def _get_endpoint_v3_data(self, service_id=None, region=None, - url=None, interface=None, enabled=True): - endpoint_id = uuid.uuid4().hex - service_id = service_id or uuid.uuid4().hex - region = region or uuid.uuid4().hex - url = url or 'https://example.com/' - interface = interface or uuid.uuid4().hex - - response = {'id': endpoint_id, 'service_id': service_id, - 'region': region, 'interface': interface, - 'url': url, 'enabled': enabled} - request = response.copy() - request.pop('id') - response['region_id'] = response['region'] - return _EndpointDataV3(endpoint_id, service_id, interface, region, - url, enabled, {'endpoint': response}, - {'endpoint': request}) - - def _get_endpoint_v2_data(self, service_id=None, region=None, - public_url=None, admin_url=None, - internal_url=None): - endpoint_id = uuid.uuid4().hex - service_id = service_id or uuid.uuid4().hex - region = region or uuid.uuid4().hex - response = {'id': endpoint_id, 'service_id': service_id, - 'region': region} - v3_endpoints = {} - request = response.copy() - request.pop('id') - if admin_url: - response['adminURL'] = admin_url - v3_endpoints['admin'] = self._get_endpoint_v3_data( - service_id, region, public_url, interface='admin') - if internal_url: - response['internalURL'] = internal_url - v3_endpoints['internal'] = self._get_endpoint_v3_data( - service_id, region, internal_url, interface='internal') - if public_url: - response['publicURL'] = public_url - v3_endpoints['public'] = self._get_endpoint_v3_data( - service_id, region, public_url, interface='public') - request = response.copy() - request.pop('id') - for u in ('publicURL', 'internalURL', 'adminURL'): - if request.get(u): - request[u.lower()] = request.pop(u) - return _EndpointDataV2(endpoint_id, service_id, region, public_url, - internal_url, admin_url, v3_endpoints, - {'endpoint': response}, {'endpoint': request}) - - def _get_role_data(self, role_name=None): - role_id = uuid.uuid4().hex - role_name = role_name or uuid.uuid4().hex - request = {'name': role_name} - response = request.copy() - response['id'] = role_id - return _RoleData(role_id, role_name, {'role': response}, - {'role': request}) - - def use_keystone_v3(self, catalog='catalog-v3.json'): - self.adapter = self.useFixture(rm_fixture.Fixture()) - self.calls = [] - self._uri_registry.clear() - self.__do_register_uris([ - dict(method='GET', uri='https://identity.example.com/', - text=open(self.discovery_json, 'r').read()), - dict(method='POST', - uri='https://identity.example.com/v3/auth/tokens', - headers={ - 'X-Subject-Token': self.getUniqueString('KeystoneToken')}, - text=open(os.path.join( - self.fixtures_directory, catalog), 'r').read() - ), - ]) - self._make_test_cloud(identity_api_version='3') - - def use_keystone_v2(self): - self.adapter = self.useFixture(rm_fixture.Fixture()) - self.calls = [] - self._uri_registry.clear() - - self.__do_register_uris([ - dict(method='GET', uri='https://identity.example.com/', - text=open(self.discovery_json, 'r').read()), - dict(method='POST', uri='https://identity.example.com/v2.0/tokens', - text=open(os.path.join( - self.fixtures_directory, 'catalog-v2.json'), 'r').read() - ), - ]) - - self._make_test_cloud(cloud_name='_test_cloud_v2_', - identity_api_version='2.0') - - def _make_test_cloud(self, cloud_name='_test_cloud_', **kwargs): - test_cloud = os.environ.get('SHADE_OS_CLOUD', cloud_name) - self.cloud_config = self.config.get_one_cloud( - cloud=test_cloud, validate=True, **kwargs) - self.cloud = openstack.cloud.OpenStackCloud( - cloud_config=self.cloud_config, - log_inner_exceptions=True) - self.op_cloud = openstack.cloud.OperatorCloud( - cloud_config=self.cloud_config, - log_inner_exceptions=True) - - def get_glance_discovery_mock_dict( - self, image_version_json='image-version.json'): - discovery_fixture = os.path.join( - self.fixtures_directory, image_version_json) - return dict(method='GET', uri='https://image.example.com/', - status_code=300, - text=open(discovery_fixture, 'r').read()) - - def get_designate_discovery_mock_dict(self): - discovery_fixture = os.path.join( - self.fixtures_directory, "dns.json") - return dict(method='GET', uri="https://dns.example.com/", - text=open(discovery_fixture, 'r').read()) - - def get_ironic_discovery_mock_dict(self): - discovery_fixture = os.path.join( - self.fixtures_directory, "baremetal.json") - return dict(method='GET', uri="https://bare-metal.example.com/", - text=open(discovery_fixture, 'r').read()) - - def use_glance(self, image_version_json='image-version.json'): - # NOTE(notmorgan): This method is only meant to be used in "setUp" - # where the ordering of the url being registered is tightly controlled - # if the functionality of .use_glance is meant to be used during an - # actual test case, use .get_glance_discovery_mock and apply to the - # right location in the mock_uris when calling .register_uris - self.__do_register_uris([ - self.get_glance_discovery_mock_dict(image_version_json)]) - - def use_designate(self): - # NOTE(slaweq): This method is only meant to be used in "setUp" - # where the ordering of the url being registered is tightly controlled - # if the functionality of .use_designate is meant to be used during an - # actual test case, use .get_designate_discovery_mock and apply to the - # right location in the mock_uris when calling .register_uris - self.__do_register_uris([ - self.get_designate_discovery_mock_dict()]) - - def use_ironic(self): - # NOTE(TheJulia): This method is only meant to be used in "setUp" - # where the ordering of the url being registered is tightly controlled - # if the functionality of .use_ironic is meant to be used during an - # actual test case, use .get_ironic_discovery_mock and apply to the - # right location in the mock_uris when calling .register_uris - self.__do_register_uris([ - self.get_ironic_discovery_mock_dict()]) - - def register_uris(self, uri_mock_list=None): - """Mock a list of URIs and responses via requests mock. - - This method may be called only once per test-case to avoid odd - and difficult to debug interactions. Discovery and Auth request mocking - happens separately from this method. - - :param uri_mock_list: List of dictionaries that template out what is - passed to requests_mock fixture's `register_uri`. - Format is: - {'method': , - 'uri': , - ... - } - - Common keys to pass in the dictionary: - * json: the json response (dict) - * status_code: the HTTP status (int) - * validate: The request body (dict) to - validate with assert_calls - all key-word arguments that are valid to send to - requests_mock are supported. - - This list should be in the order in which calls - are made. When `assert_calls` is executed, order - here will be validated. Duplicate URIs and - Methods are allowed and will be collapsed into a - single matcher. Each response will be returned - in order as the URI+Method is hit. - :type uri_mock_list: list - :return: None - """ - assert not self.__register_uris_called - self.__do_register_uris(uri_mock_list or []) - self.__register_uris_called = True - - def __do_register_uris(self, uri_mock_list=None): - for to_mock in uri_mock_list: - kw_params = {k: to_mock.pop(k) - for k in ('request_headers', 'complete_qs', - '_real_http') - if k in to_mock} - - method = to_mock.pop('method') - uri = to_mock.pop('uri') - # NOTE(notmorgan): make sure the delimiter is non-url-safe, in this - # case "|" is used so that the split can be a bit easier on - # maintainers of this code. - key = '{method}|{uri}|{params}'.format( - method=method, uri=uri, params=kw_params) - validate = to_mock.pop('validate', {}) - valid_keys = set(['json', 'headers', 'params']) - invalid_keys = set(validate.keys()) - valid_keys - if invalid_keys: - raise TypeError( - "Invalid values passed to validate: {keys}".format( - keys=invalid_keys)) - headers = structures.CaseInsensitiveDict(to_mock.pop('headers', - {})) - if 'content-type' not in headers: - headers[u'content-type'] = 'application/json' - - to_mock['headers'] = headers - - self.calls += [ - dict( - method=method, - url=uri, **validate) - ] - self._uri_registry.setdefault( - key, {'response_list': [], 'kw_params': kw_params}) - if self._uri_registry[key]['kw_params'] != kw_params: - raise AssertionError( - 'PROGRAMMING ERROR: key-word-params ' - 'should be part of the uri_key and cannot change, ' - 'it will affect the matcher in requests_mock. ' - '%(old)r != %(new)r' % - {'old': self._uri_registry[key]['kw_params'], - 'new': kw_params}) - self._uri_registry[key]['response_list'].append(to_mock) - - for mocked, params in self._uri_registry.items(): - mock_method, mock_uri, _ignored = mocked.split('|', 2) - self.adapter.register_uri( - mock_method, mock_uri, params['response_list'], - **params['kw_params']) - - def assert_calls(self, stop_after=None, do_count=True): - for (x, (call, history)) in enumerate( - zip(self.calls, self.adapter.request_history)): - if stop_after and x > stop_after: - break - - call_uri_parts = urllib.parse.urlparse(call['url']) - history_uri_parts = urllib.parse.urlparse(history.url) - self.assertEqual( - (call['method'], call_uri_parts.scheme, call_uri_parts.netloc, - call_uri_parts.path, call_uri_parts.params, - urllib.parse.parse_qs(call_uri_parts.query)), - (history.method, history_uri_parts.scheme, - history_uri_parts.netloc, history_uri_parts.path, - history_uri_parts.params, - urllib.parse.parse_qs(history_uri_parts.query)), - ('REST mismatch on call %(index)d. Expected %(call)r. ' - 'Got %(history)r). ' - 'NOTE: query string order differences wont cause mismatch' % - { - 'index': x, - 'call': '{method} {url}'.format(method=call['method'], - url=call['url']), - 'history': '{method} {url}'.format( - method=history.method, - url=history.url)}) - ) - if 'json' in call: - self.assertEqual( - call['json'], history.json(), - 'json content mismatch in call {index}'.format(index=x)) - # headers in a call isn't exhaustive - it's checking to make sure - # a specific header or headers are there, not that they are the - # only headers - if 'headers' in call: - for key, value in call['headers'].items(): - self.assertEqual( - value, history.headers[key], - 'header mismatch in call {index}'.format(index=x)) - if do_count: - self.assertEqual( - len(self.calls), len(self.adapter.request_history)) - - -class IronicTestCase(RequestsMockTestCase): - - def setUp(self): - super(IronicTestCase, self).setUp() - self.use_ironic() - self.uuid = str(uuid.uuid4()) - self.name = self.getUniqueString('name') - - def get_mock_url(self, resource=None, append=None, qs_elements=None): - return super(IronicTestCase, self).get_mock_url( - service_type='baremetal', interface='public', resource=resource, - append=append, base_url_append='v1', qs_elements=qs_elements) diff --git a/openstack/cloud/tests/ansible/README.txt b/openstack/tests/ansible/README.txt similarity index 100% rename from openstack/cloud/tests/ansible/README.txt rename to openstack/tests/ansible/README.txt diff --git a/openstack/cloud/tests/ansible/hooks/post_test_hook.sh b/openstack/tests/ansible/hooks/post_test_hook.sh similarity index 81% rename from openstack/cloud/tests/ansible/hooks/post_test_hook.sh rename to openstack/tests/ansible/hooks/post_test_hook.sh index 0c2bbcfd2..6b511719a 100755 --- a/openstack/cloud/tests/ansible/hooks/post_test_hook.sh +++ b/openstack/tests/ansible/hooks/post_test_hook.sh @@ -12,14 +12,16 @@ # License for the specific language governing permissions and limitations # under the License. -export SHADE_DIR="$BASE/new/shade" +# TODO(shade) Rework for Zuul v3 -cd $SHADE_DIR -sudo chown -R jenkins:stack $SHADE_DIR +export OPENSTACKSDK_DIR="$BASE/new/python-openstacksdk" + +cd $OPENSTACKSDK_DIR +sudo chown -R jenkins:stack $OPENSTACKSDK_DIR echo "Running shade Ansible test suite" -if [ ${SHADE_ANSIBLE_DEV:-0} -eq 1 ] +if [ ${OPENSTACKSDK_ANSIBLE_DEV:-0} -eq 1 ] then # Use the upstream development version of Ansible set +e diff --git a/openstack/cloud/tests/ansible/roles/auth/tasks/main.yml b/openstack/tests/ansible/roles/auth/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/auth/tasks/main.yml rename to openstack/tests/ansible/roles/auth/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/client_config/tasks/main.yml b/openstack/tests/ansible/roles/client_config/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/client_config/tasks/main.yml rename to openstack/tests/ansible/roles/client_config/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/group/tasks/main.yml b/openstack/tests/ansible/roles/group/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/group/tasks/main.yml rename to openstack/tests/ansible/roles/group/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/group/vars/main.yml b/openstack/tests/ansible/roles/group/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/group/vars/main.yml rename to openstack/tests/ansible/roles/group/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/image/tasks/main.yml b/openstack/tests/ansible/roles/image/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/image/tasks/main.yml rename to openstack/tests/ansible/roles/image/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/image/vars/main.yml b/openstack/tests/ansible/roles/image/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/image/vars/main.yml rename to openstack/tests/ansible/roles/image/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/keypair/tasks/main.yml b/openstack/tests/ansible/roles/keypair/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/keypair/tasks/main.yml rename to openstack/tests/ansible/roles/keypair/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/keypair/vars/main.yml b/openstack/tests/ansible/roles/keypair/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/keypair/vars/main.yml rename to openstack/tests/ansible/roles/keypair/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/keystone_domain/tasks/main.yml b/openstack/tests/ansible/roles/keystone_domain/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/keystone_domain/tasks/main.yml rename to openstack/tests/ansible/roles/keystone_domain/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/keystone_domain/vars/main.yml b/openstack/tests/ansible/roles/keystone_domain/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/keystone_domain/vars/main.yml rename to openstack/tests/ansible/roles/keystone_domain/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/keystone_role/tasks/main.yml b/openstack/tests/ansible/roles/keystone_role/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/keystone_role/tasks/main.yml rename to openstack/tests/ansible/roles/keystone_role/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/keystone_role/vars/main.yml b/openstack/tests/ansible/roles/keystone_role/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/keystone_role/vars/main.yml rename to openstack/tests/ansible/roles/keystone_role/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/network/tasks/main.yml b/openstack/tests/ansible/roles/network/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/network/tasks/main.yml rename to openstack/tests/ansible/roles/network/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/network/vars/main.yml b/openstack/tests/ansible/roles/network/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/network/vars/main.yml rename to openstack/tests/ansible/roles/network/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/nova_flavor/tasks/main.yml b/openstack/tests/ansible/roles/nova_flavor/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/nova_flavor/tasks/main.yml rename to openstack/tests/ansible/roles/nova_flavor/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/object/tasks/main.yml b/openstack/tests/ansible/roles/object/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/object/tasks/main.yml rename to openstack/tests/ansible/roles/object/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/port/tasks/main.yml b/openstack/tests/ansible/roles/port/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/port/tasks/main.yml rename to openstack/tests/ansible/roles/port/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/port/vars/main.yml b/openstack/tests/ansible/roles/port/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/port/vars/main.yml rename to openstack/tests/ansible/roles/port/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/router/tasks/main.yml b/openstack/tests/ansible/roles/router/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/router/tasks/main.yml rename to openstack/tests/ansible/roles/router/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/router/vars/main.yml b/openstack/tests/ansible/roles/router/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/router/vars/main.yml rename to openstack/tests/ansible/roles/router/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/security_group/tasks/main.yml b/openstack/tests/ansible/roles/security_group/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/security_group/tasks/main.yml rename to openstack/tests/ansible/roles/security_group/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/security_group/vars/main.yml b/openstack/tests/ansible/roles/security_group/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/security_group/vars/main.yml rename to openstack/tests/ansible/roles/security_group/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/server/tasks/main.yml b/openstack/tests/ansible/roles/server/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/server/tasks/main.yml rename to openstack/tests/ansible/roles/server/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/server/vars/main.yaml b/openstack/tests/ansible/roles/server/vars/main.yaml similarity index 100% rename from openstack/cloud/tests/ansible/roles/server/vars/main.yaml rename to openstack/tests/ansible/roles/server/vars/main.yaml diff --git a/openstack/cloud/tests/ansible/roles/subnet/tasks/main.yml b/openstack/tests/ansible/roles/subnet/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/subnet/tasks/main.yml rename to openstack/tests/ansible/roles/subnet/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/subnet/vars/main.yml b/openstack/tests/ansible/roles/subnet/vars/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/subnet/vars/main.yml rename to openstack/tests/ansible/roles/subnet/vars/main.yml diff --git a/openstack/cloud/tests/ansible/roles/user/tasks/main.yml b/openstack/tests/ansible/roles/user/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/user/tasks/main.yml rename to openstack/tests/ansible/roles/user/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/user_group/tasks/main.yml b/openstack/tests/ansible/roles/user_group/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/user_group/tasks/main.yml rename to openstack/tests/ansible/roles/user_group/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/roles/volume/tasks/main.yml b/openstack/tests/ansible/roles/volume/tasks/main.yml similarity index 100% rename from openstack/cloud/tests/ansible/roles/volume/tasks/main.yml rename to openstack/tests/ansible/roles/volume/tasks/main.yml diff --git a/openstack/cloud/tests/ansible/run.yml b/openstack/tests/ansible/run.yml similarity index 100% rename from openstack/cloud/tests/ansible/run.yml rename to openstack/tests/ansible/run.yml diff --git a/openstack/cloud/tests/base.py b/openstack/tests/base.py similarity index 100% rename from openstack/cloud/tests/base.py rename to openstack/tests/base.py diff --git a/openstack/cloud/tests/fakes.py b/openstack/tests/fakes.py similarity index 100% rename from openstack/cloud/tests/fakes.py rename to openstack/tests/fakes.py diff --git a/openstack/cloud/tests/functional/__init__.py b/openstack/tests/functional/cloud/__init__.py similarity index 100% rename from openstack/cloud/tests/functional/__init__.py rename to openstack/tests/functional/cloud/__init__.py diff --git a/openstack/cloud/tests/functional/base.py b/openstack/tests/functional/cloud/base.py similarity index 90% rename from openstack/cloud/tests/functional/base.py rename to openstack/tests/functional/cloud/base.py index 32c07d7da..192a96b6e 100644 --- a/openstack/cloud/tests/functional/base.py +++ b/openstack/tests/functional/cloud/base.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +# TODO(shade) Merge this with openstack.tests.functional.base + import os import openstack.config as occ @@ -22,9 +24,9 @@ class BaseFunctionalTestCase(base.TestCase): def setUp(self): super(BaseFunctionalTestCase, self).setUp() - self._demo_name = os.environ.get('SHADE_DEMO_CLOUD', 'devstack') + self._demo_name = os.environ.get('OPENSTACKSDK_DEMO_CLOUD', 'devstack') self._op_name = os.environ.get( - 'SHADE_OPERATOR_CLOUD', 'devstack-admin') + 'OPENSTACKSDK_OPERATOR_CLOUD', 'devstack-admin') self.config = occ.OpenStackConfig() self._set_user_cloud() @@ -51,7 +53,7 @@ class BaseFunctionalTestCase(base.TestCase): images = self.user_cloud.list_images() self.add_info_on_exception('images', images) - image_name = os.environ.get('SHADE_IMAGE') + image_name = os.environ.get('OPENSTACKSDK_IMAGE') if image_name: for image in images: if image.name == image_name: @@ -80,7 +82,7 @@ class KeystoneBaseFunctionalTestCase(BaseFunctionalTestCase): def setUp(self): super(KeystoneBaseFunctionalTestCase, self).setUp() - use_keystone_v2 = os.environ.get('SHADE_USE_KEYSTONE_V2', False) + use_keystone_v2 = os.environ.get('OPENSTACKSDK_USE_KEYSTONE_V2', False) if use_keystone_v2: # keystone v2 has special behavior for the admin # interface and some of the operations, so make a new cloud diff --git a/openstack/cloud/tests/functional/hooks/post_test_hook.sh b/openstack/tests/functional/cloud/hooks/post_test_hook.sh similarity index 88% rename from openstack/cloud/tests/functional/hooks/post_test_hook.sh rename to openstack/tests/functional/cloud/hooks/post_test_hook.sh index 52037cd38..8092a6114 100755 --- a/openstack/cloud/tests/functional/hooks/post_test_hook.sh +++ b/openstack/tests/functional/cloud/hooks/post_test_hook.sh @@ -12,10 +12,12 @@ # License for the specific language governing permissions and limitations # under the License. -export SHADE_DIR="$BASE/new/shade" +# TODO(shade) Rework for zuul v3 -cd $SHADE_DIR -sudo chown -R jenkins:stack $SHADE_DIR +export OPENSTACKSDK_DIR="$BASE/new/shade" + +cd $OPENSTACKSDK_DIR +sudo chown -R jenkins:stack $OPENSTACKSDK_DIR CLOUDS_YAML=/etc/openstack/clouds.yaml @@ -30,7 +32,7 @@ fi # Devstack runs both keystone v2 and v3. An environment variable is set # within the shade keystone v2 job that tells us which version we should # test against. -if [ ${SHADE_USE_KEYSTONE_V2:-0} -eq 1 ] +if [ ${OPENSTACKSDK_USE_KEYSTONE_V2:-0} -eq 1 ] then sudo sed -ie "s/identity_api_version: '3'/identity_api_version: '2.0'/g" $CLOUDS_YAML sudo sed -ie '/^.*domain_id.*$/d' $CLOUDS_YAML diff --git a/openstack/cloud/tests/functional/test_aggregate.py b/openstack/tests/functional/cloud/test_aggregate.py similarity index 100% rename from openstack/cloud/tests/functional/test_aggregate.py rename to openstack/tests/functional/cloud/test_aggregate.py diff --git a/openstack/cloud/tests/functional/test_cluster_templates.py b/openstack/tests/functional/cloud/test_cluster_templates.py similarity index 100% rename from openstack/cloud/tests/functional/test_cluster_templates.py rename to openstack/tests/functional/cloud/test_cluster_templates.py diff --git a/openstack/cloud/tests/functional/test_compute.py b/openstack/tests/functional/cloud/test_compute.py similarity index 100% rename from openstack/cloud/tests/functional/test_compute.py rename to openstack/tests/functional/cloud/test_compute.py diff --git a/openstack/cloud/tests/functional/test_devstack.py b/openstack/tests/functional/cloud/test_devstack.py similarity index 89% rename from openstack/cloud/tests/functional/test_devstack.py rename to openstack/tests/functional/cloud/test_devstack.py index b48ba5d8c..c2a132bfe 100644 --- a/openstack/cloud/tests/functional/test_devstack.py +++ b/openstack/tests/functional/cloud/test_devstack.py @@ -38,14 +38,15 @@ class TestDevstack(base.BaseFunctionalTestCase): ] def test_has_service(self): - if os.environ.get('SHADE_HAS_{env}'.format(env=self.env), '0') == '1': + if os.environ.get( + 'OPENSTACKSDK_HAS_{env}'.format(env=self.env), '0') == '1': self.assertTrue(self.user_cloud.has_service(self.service)) class TestKeystoneVersion(base.BaseFunctionalTestCase): def test_keystone_version(self): - use_keystone_v2 = os.environ.get('SHADE_USE_KEYSTONE_V2', False) + use_keystone_v2 = os.environ.get('OPENSTACKSDK_USE_KEYSTONE_V2', False) if use_keystone_v2 and use_keystone_v2 != '0': self.assertEqual('2.0', self.identity_version) else: diff --git a/openstack/cloud/tests/functional/test_domain.py b/openstack/tests/functional/cloud/test_domain.py similarity index 100% rename from openstack/cloud/tests/functional/test_domain.py rename to openstack/tests/functional/cloud/test_domain.py diff --git a/openstack/cloud/tests/functional/test_endpoints.py b/openstack/tests/functional/cloud/test_endpoints.py similarity index 100% rename from openstack/cloud/tests/functional/test_endpoints.py rename to openstack/tests/functional/cloud/test_endpoints.py diff --git a/openstack/cloud/tests/functional/test_flavor.py b/openstack/tests/functional/cloud/test_flavor.py similarity index 100% rename from openstack/cloud/tests/functional/test_flavor.py rename to openstack/tests/functional/cloud/test_flavor.py diff --git a/openstack/cloud/tests/functional/test_floating_ip.py b/openstack/tests/functional/cloud/test_floating_ip.py similarity index 100% rename from openstack/cloud/tests/functional/test_floating_ip.py rename to openstack/tests/functional/cloud/test_floating_ip.py diff --git a/openstack/cloud/tests/functional/test_floating_ip_pool.py b/openstack/tests/functional/cloud/test_floating_ip_pool.py similarity index 100% rename from openstack/cloud/tests/functional/test_floating_ip_pool.py rename to openstack/tests/functional/cloud/test_floating_ip_pool.py diff --git a/openstack/cloud/tests/functional/test_groups.py b/openstack/tests/functional/cloud/test_groups.py similarity index 100% rename from openstack/cloud/tests/functional/test_groups.py rename to openstack/tests/functional/cloud/test_groups.py diff --git a/openstack/cloud/tests/functional/test_identity.py b/openstack/tests/functional/cloud/test_identity.py similarity index 100% rename from openstack/cloud/tests/functional/test_identity.py rename to openstack/tests/functional/cloud/test_identity.py diff --git a/openstack/cloud/tests/functional/test_image.py b/openstack/tests/functional/cloud/test_image.py similarity index 100% rename from openstack/cloud/tests/functional/test_image.py rename to openstack/tests/functional/cloud/test_image.py diff --git a/openstack/cloud/tests/functional/test_inventory.py b/openstack/tests/functional/cloud/test_inventory.py similarity index 100% rename from openstack/cloud/tests/functional/test_inventory.py rename to openstack/tests/functional/cloud/test_inventory.py diff --git a/openstack/cloud/tests/functional/test_keypairs.py b/openstack/tests/functional/cloud/test_keypairs.py similarity index 100% rename from openstack/cloud/tests/functional/test_keypairs.py rename to openstack/tests/functional/cloud/test_keypairs.py diff --git a/openstack/cloud/tests/functional/test_limits.py b/openstack/tests/functional/cloud/test_limits.py similarity index 100% rename from openstack/cloud/tests/functional/test_limits.py rename to openstack/tests/functional/cloud/test_limits.py diff --git a/openstack/cloud/tests/functional/test_magnum_services.py b/openstack/tests/functional/cloud/test_magnum_services.py similarity index 100% rename from openstack/cloud/tests/functional/test_magnum_services.py rename to openstack/tests/functional/cloud/test_magnum_services.py diff --git a/openstack/cloud/tests/functional/test_network.py b/openstack/tests/functional/cloud/test_network.py similarity index 100% rename from openstack/cloud/tests/functional/test_network.py rename to openstack/tests/functional/cloud/test_network.py diff --git a/openstack/cloud/tests/functional/test_object.py b/openstack/tests/functional/cloud/test_object.py similarity index 100% rename from openstack/cloud/tests/functional/test_object.py rename to openstack/tests/functional/cloud/test_object.py diff --git a/openstack/cloud/tests/functional/test_port.py b/openstack/tests/functional/cloud/test_port.py similarity index 100% rename from openstack/cloud/tests/functional/test_port.py rename to openstack/tests/functional/cloud/test_port.py diff --git a/openstack/cloud/tests/functional/test_project.py b/openstack/tests/functional/cloud/test_project.py similarity index 100% rename from openstack/cloud/tests/functional/test_project.py rename to openstack/tests/functional/cloud/test_project.py diff --git a/openstack/cloud/tests/functional/test_qos_bandwidth_limit_rule.py b/openstack/tests/functional/cloud/test_qos_bandwidth_limit_rule.py similarity index 100% rename from openstack/cloud/tests/functional/test_qos_bandwidth_limit_rule.py rename to openstack/tests/functional/cloud/test_qos_bandwidth_limit_rule.py diff --git a/openstack/cloud/tests/functional/test_qos_dscp_marking_rule.py b/openstack/tests/functional/cloud/test_qos_dscp_marking_rule.py similarity index 100% rename from openstack/cloud/tests/functional/test_qos_dscp_marking_rule.py rename to openstack/tests/functional/cloud/test_qos_dscp_marking_rule.py diff --git a/openstack/cloud/tests/functional/test_qos_minimum_bandwidth_rule.py b/openstack/tests/functional/cloud/test_qos_minimum_bandwidth_rule.py similarity index 100% rename from openstack/cloud/tests/functional/test_qos_minimum_bandwidth_rule.py rename to openstack/tests/functional/cloud/test_qos_minimum_bandwidth_rule.py diff --git a/openstack/cloud/tests/functional/test_qos_policy.py b/openstack/tests/functional/cloud/test_qos_policy.py similarity index 100% rename from openstack/cloud/tests/functional/test_qos_policy.py rename to openstack/tests/functional/cloud/test_qos_policy.py diff --git a/openstack/cloud/tests/functional/test_quotas.py b/openstack/tests/functional/cloud/test_quotas.py similarity index 100% rename from openstack/cloud/tests/functional/test_quotas.py rename to openstack/tests/functional/cloud/test_quotas.py diff --git a/openstack/cloud/tests/functional/test_range_search.py b/openstack/tests/functional/cloud/test_range_search.py similarity index 100% rename from openstack/cloud/tests/functional/test_range_search.py rename to openstack/tests/functional/cloud/test_range_search.py diff --git a/openstack/cloud/tests/functional/test_recordset.py b/openstack/tests/functional/cloud/test_recordset.py similarity index 100% rename from openstack/cloud/tests/functional/test_recordset.py rename to openstack/tests/functional/cloud/test_recordset.py diff --git a/openstack/cloud/tests/functional/test_router.py b/openstack/tests/functional/cloud/test_router.py similarity index 100% rename from openstack/cloud/tests/functional/test_router.py rename to openstack/tests/functional/cloud/test_router.py diff --git a/openstack/cloud/tests/functional/test_security_groups.py b/openstack/tests/functional/cloud/test_security_groups.py similarity index 100% rename from openstack/cloud/tests/functional/test_security_groups.py rename to openstack/tests/functional/cloud/test_security_groups.py diff --git a/openstack/cloud/tests/functional/test_server_group.py b/openstack/tests/functional/cloud/test_server_group.py similarity index 100% rename from openstack/cloud/tests/functional/test_server_group.py rename to openstack/tests/functional/cloud/test_server_group.py diff --git a/openstack/cloud/tests/functional/test_services.py b/openstack/tests/functional/cloud/test_services.py similarity index 100% rename from openstack/cloud/tests/functional/test_services.py rename to openstack/tests/functional/cloud/test_services.py diff --git a/openstack/cloud/tests/functional/test_stack.py b/openstack/tests/functional/cloud/test_stack.py similarity index 100% rename from openstack/cloud/tests/functional/test_stack.py rename to openstack/tests/functional/cloud/test_stack.py diff --git a/openstack/cloud/tests/functional/test_usage.py b/openstack/tests/functional/cloud/test_usage.py similarity index 100% rename from openstack/cloud/tests/functional/test_usage.py rename to openstack/tests/functional/cloud/test_usage.py diff --git a/openstack/cloud/tests/functional/test_users.py b/openstack/tests/functional/cloud/test_users.py similarity index 100% rename from openstack/cloud/tests/functional/test_users.py rename to openstack/tests/functional/cloud/test_users.py diff --git a/openstack/cloud/tests/functional/test_volume.py b/openstack/tests/functional/cloud/test_volume.py similarity index 100% rename from openstack/cloud/tests/functional/test_volume.py rename to openstack/tests/functional/cloud/test_volume.py diff --git a/openstack/cloud/tests/functional/test_volume_backup.py b/openstack/tests/functional/cloud/test_volume_backup.py similarity index 100% rename from openstack/cloud/tests/functional/test_volume_backup.py rename to openstack/tests/functional/cloud/test_volume_backup.py diff --git a/openstack/cloud/tests/functional/test_volume_type.py b/openstack/tests/functional/cloud/test_volume_type.py similarity index 100% rename from openstack/cloud/tests/functional/test_volume_type.py rename to openstack/tests/functional/cloud/test_volume_type.py diff --git a/openstack/cloud/tests/functional/test_zone.py b/openstack/tests/functional/cloud/test_zone.py similarity index 100% rename from openstack/cloud/tests/functional/test_zone.py rename to openstack/tests/functional/cloud/test_zone.py diff --git a/openstack/cloud/tests/functional/util.py b/openstack/tests/functional/cloud/util.py similarity index 95% rename from openstack/cloud/tests/functional/util.py rename to openstack/tests/functional/cloud/util.py index 180f08f76..fef67190f 100644 --- a/openstack/cloud/tests/functional/util.py +++ b/openstack/tests/functional/cloud/util.py @@ -24,7 +24,7 @@ def pick_flavor(flavors): """Given a flavor list pick the smallest one.""" # Enable running functional tests against rax - which requires # performance flavors be used for boot from volume - flavor_name = os.environ.get('SHADE_FLAVOR') + flavor_name = os.environ.get('OPENSTACKSDK_FLAVOR') if flavor_name: for flavor in flavors: if flavor.name == flavor_name: diff --git a/openstack/tests/unit/base.py b/openstack/tests/unit/base.py index eae41c16d..87f128da7 100644 --- a/openstack/tests/unit/base.py +++ b/openstack/tests/unit/base.py @@ -13,39 +13,627 @@ # License for the specific language governing permissions and limitations # under the License. -import os +import collections +import time +import uuid import fixtures -import testtools +import mock +import os +import openstack.config as occ +from requests import structures +from requests_mock.contrib import fixture as rm_fixture +from six.moves import urllib +import tempfile -_TRUE_VALUES = ('true', '1', 'yes') +import openstack.cloud.openstackcloud +from openstack.cloud.tests import base -class TestCase(testtools.TestCase): +_ProjectData = collections.namedtuple( + 'ProjectData', + 'project_id, project_name, enabled, domain_id, description, ' + 'json_response, json_request') - """Test case base class for all unit tests.""" - def setUp(self): +_UserData = collections.namedtuple( + 'UserData', + 'user_id, password, name, email, description, domain_id, enabled, ' + 'json_response, json_request') + + +_GroupData = collections.namedtuple( + 'GroupData', + 'group_id, group_name, domain_id, description, json_response, ' + 'json_request') + + +_DomainData = collections.namedtuple( + 'DomainData', + 'domain_id, domain_name, description, json_response, ' + 'json_request') + + +_ServiceData = collections.namedtuple( + 'Servicedata', + 'service_id, service_name, service_type, description, enabled, ' + 'json_response_v3, json_response_v2, json_request') + + +_EndpointDataV3 = collections.namedtuple( + 'EndpointData', + 'endpoint_id, service_id, interface, region, url, enabled, ' + 'json_response, json_request') + + +_EndpointDataV2 = collections.namedtuple( + 'EndpointData', + 'endpoint_id, service_id, region, public_url, internal_url, ' + 'admin_url, v3_endpoint_list, json_response, ' + 'json_request') + + +# NOTE(notmorgan): Shade does not support domain-specific roles +# This should eventually be fixed if it becomes a main-stream feature. +_RoleData = collections.namedtuple( + 'RoleData', + 'role_id, role_name, json_response, json_request') + + +class BaseTestCase(base.TestCase): + + def setUp(self, cloud_config_fixture='clouds.yaml'): """Run before each test method to initialize test environment.""" - super(TestCase, self).setUp() - test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) - try: - test_timeout = int(test_timeout) - except ValueError: - # If timeout value is invalid do not set a timeout. - test_timeout = 0 - if test_timeout > 0: - self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) + super(BaseTestCase, self).setUp() - self.useFixture(fixtures.NestedTempfile()) - self.useFixture(fixtures.TempHomeDir()) + # Sleeps are for real testing, but unit tests shouldn't need them + realsleep = time.sleep - if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) + def _nosleep(seconds): + return realsleep(seconds * 0.0001) - self.log_fixture = self.useFixture(fixtures.FakeLogger()) + self.sleep_fixture = self.useFixture(fixtures.MonkeyPatch( + 'time.sleep', + _nosleep)) + self.fixtures_directory = 'openstack/tests/unit/fixtures' + + # Isolate os-client-config from test environment + config = tempfile.NamedTemporaryFile(delete=False) + cloud_path = '%s/clouds/%s' % (self.fixtures_directory, + cloud_config_fixture) + with open(cloud_path, 'rb') as f: + content = f.read() + config.write(content) + config.close() + + vendor = tempfile.NamedTemporaryFile(delete=False) + vendor.write(b'{}') + vendor.close() + + test_cloud = os.environ.get('OPENSTACKSDK_OS_CLOUD', '_test_cloud_') + self.config = occ.OpenStackConfig( + config_files=[config.name], + vendor_files=[vendor.name], + secure_files=['non-existant']) + self.cloud_config = self.config.get_one_cloud( + cloud=test_cloud, validate=False) + self.cloud = openstack.cloud.OpenStackCloud( + cloud_config=self.cloud_config, + log_inner_exceptions=True) + self.strict_cloud = openstack.cloud.OpenStackCloud( + cloud_config=self.cloud_config, + log_inner_exceptions=True, + strict=True) + self.op_cloud = openstack.cloud.OperatorCloud( + cloud_config=self.cloud_config, + log_inner_exceptions=True) + + +class TestCase(BaseTestCase): + + def setUp(self, cloud_config_fixture='clouds.yaml'): + + super(TestCase, self).setUp(cloud_config_fixture=cloud_config_fixture) + self.session_fixture = self.useFixture(fixtures.MonkeyPatch( + 'os_client_config.cloud_config.CloudConfig.get_session', + mock.Mock())) + + +class RequestsMockTestCase(BaseTestCase): + + def setUp(self, cloud_config_fixture='clouds.yaml'): + + super(RequestsMockTestCase, self).setUp( + cloud_config_fixture=cloud_config_fixture) + + # FIXME(notmorgan): Convert the uri_registry, discovery.json, and + # use of keystone_v3/v2 to a proper fixtures.Fixture. For now this + # is acceptable, but eventually this should become it's own fixture + # that encapsulates the registry, registering the URIs, and + # assert_calls (and calling assert_calls every test case that uses + # it on cleanup). Subclassing here could be 100% eliminated in the + # future allowing any class to simply + # self.useFixture(openstack.cloud.RequestsMockFixture) and get all + # the benefits. + + # NOTE(notmorgan): use an ordered dict here to ensure we preserve the + # order in which items are added to the uri_registry. This makes + # the behavior more consistent when dealing with ensuring the + # requests_mock uri/query_string matchers are ordered and parse the + # request in the correct orders. + self._uri_registry = collections.OrderedDict() + self.discovery_json = os.path.join( + self.fixtures_directory, 'discovery.json') + self.use_keystone_v3() + self.__register_uris_called = False + + def get_mock_url(self, service_type, interface='public', resource=None, + append=None, base_url_append=None, + qs_elements=None): + endpoint_url = self.cloud.endpoint_for( + service_type=service_type, interface=interface) + # Strip trailing slashes, so as not to produce double-slashes below + if endpoint_url.endswith('/'): + endpoint_url = endpoint_url[:-1] + to_join = [endpoint_url] + qs = '' + if base_url_append: + to_join.append(base_url_append) + if resource: + to_join.append(resource) + to_join.extend(append or []) + if qs_elements is not None: + qs = '?%s' % '&'.join(qs_elements) + return '%(uri)s%(qs)s' % {'uri': '/'.join(to_join), 'qs': qs} + + def mock_for_keystone_projects(self, project=None, v3=True, + list_get=False, id_get=False, + project_list=None, project_count=None): + if project: + assert not (project_list or project_count) + elif project_list: + assert not (project or project_count) + elif project_count: + assert not (project or project_list) + else: + raise Exception('Must specify a project, project_list, ' + 'or project_count') + assert list_get or id_get + + base_url_append = 'v3' if v3 else None + if project: + project_list = [project] + elif project_count: + # Generate multiple projects + project_list = [self._get_project_data(v3=v3) + for c in range(0, project_count)] + uri_mock_list = [] + if list_get: + uri_mock_list.append( + dict(method='GET', + uri=self.get_mock_url( + service_type='identity', + interface='admin', + resource='projects', + base_url_append=base_url_append), + status_code=200, + json={'projects': [p.json_response['project'] + for p in project_list]}) + ) + if id_get: + for p in project_list: + uri_mock_list.append( + dict(method='GET', + uri=self.get_mock_url( + service_type='identity', + interface='admin', + resource='projects', + append=[p.project_id], + base_url_append=base_url_append), + status_code=200, + json=p.json_response) + ) + self.__do_register_uris(uri_mock_list) + return project_list + + def _get_project_data(self, project_name=None, enabled=None, + domain_id=None, description=None, v3=True, + project_id=None): + project_name = project_name or self.getUniqueString('projectName') + project_id = uuid.UUID(project_id or uuid.uuid4().hex).hex + response = {'id': project_id, 'name': project_name} + request = {'name': project_name} + domain_id = (domain_id or uuid.uuid4().hex) if v3 else None + if domain_id: + request['domain_id'] = domain_id + response['domain_id'] = domain_id + if enabled is not None: + enabled = bool(enabled) + response['enabled'] = enabled + request['enabled'] = enabled + response.setdefault('enabled', True) + request.setdefault('enabled', True) + if description: + response['description'] = description + request['description'] = description + request.setdefault('description', None) + if v3: + project_key = 'project' + else: + project_key = 'tenant' + return _ProjectData(project_id, project_name, enabled, domain_id, + description, {project_key: response}, + {project_key: request}) + + def _get_group_data(self, name=None, domain_id=None, description=None): + group_id = uuid.uuid4().hex + name = name or self.getUniqueString('groupname') + domain_id = uuid.UUID(domain_id or uuid.uuid4().hex).hex + response = {'id': group_id, 'name': name, 'domain_id': domain_id} + request = {'name': name, 'domain_id': domain_id} + if description is not None: + response['description'] = description + request['description'] = description + + return _GroupData(group_id, name, domain_id, description, + {'group': response}, {'group': request}) + + def _get_user_data(self, name=None, password=None, **kwargs): + + name = name or self.getUniqueString('username') + password = password or self.getUniqueString('user_password') + user_id = uuid.uuid4().hex + + response = {'name': name, 'id': user_id} + request = {'name': name, 'password': password} + + if kwargs.get('domain_id'): + kwargs['domain_id'] = uuid.UUID(kwargs['domain_id']).hex + response['domain_id'] = kwargs.pop('domain_id') + request['domain_id'] = response['domain_id'] + + response['email'] = kwargs.pop('email', None) + request['email'] = response['email'] + + response['enabled'] = kwargs.pop('enabled', True) + request['enabled'] = response['enabled'] + + response['description'] = kwargs.pop('description', None) + if response['description']: + request['description'] = response['description'] + + self.assertIs(0, len(kwargs), message='extra key-word args received ' + 'on _get_user_data') + + return _UserData(user_id, password, name, response['email'], + response['description'], response.get('domain_id'), + response.get('enabled'), {'user': response}, + {'user': request}) + + def _get_domain_data(self, domain_name=None, description=None, + enabled=None): + domain_id = uuid.uuid4().hex + domain_name = domain_name or self.getUniqueString('domainName') + response = {'id': domain_id, 'name': domain_name} + request = {'name': domain_name} + if enabled is not None: + request['enabled'] = bool(enabled) + response['enabled'] = bool(enabled) + if description: + response['description'] = description + request['description'] = description + response.setdefault('enabled', True) + return _DomainData(domain_id, domain_name, description, + {'domain': response}, {'domain': request}) + + def _get_service_data(self, type=None, name=None, description=None, + enabled=True): + service_id = uuid.uuid4().hex + name = name or uuid.uuid4().hex + type = type or uuid.uuid4().hex + + response = {'id': service_id, 'name': name, 'type': type, + 'enabled': enabled} + if description is not None: + response['description'] = description + request = response.copy() + request.pop('id') + return _ServiceData(service_id, name, type, description, enabled, + {'service': response}, + {'OS-KSADM:service': response}, request) + + def _get_endpoint_v3_data(self, service_id=None, region=None, + url=None, interface=None, enabled=True): + endpoint_id = uuid.uuid4().hex + service_id = service_id or uuid.uuid4().hex + region = region or uuid.uuid4().hex + url = url or 'https://example.com/' + interface = interface or uuid.uuid4().hex + + response = {'id': endpoint_id, 'service_id': service_id, + 'region': region, 'interface': interface, + 'url': url, 'enabled': enabled} + request = response.copy() + request.pop('id') + response['region_id'] = response['region'] + return _EndpointDataV3(endpoint_id, service_id, interface, region, + url, enabled, {'endpoint': response}, + {'endpoint': request}) + + def _get_endpoint_v2_data(self, service_id=None, region=None, + public_url=None, admin_url=None, + internal_url=None): + endpoint_id = uuid.uuid4().hex + service_id = service_id or uuid.uuid4().hex + region = region or uuid.uuid4().hex + response = {'id': endpoint_id, 'service_id': service_id, + 'region': region} + v3_endpoints = {} + request = response.copy() + request.pop('id') + if admin_url: + response['adminURL'] = admin_url + v3_endpoints['admin'] = self._get_endpoint_v3_data( + service_id, region, public_url, interface='admin') + if internal_url: + response['internalURL'] = internal_url + v3_endpoints['internal'] = self._get_endpoint_v3_data( + service_id, region, internal_url, interface='internal') + if public_url: + response['publicURL'] = public_url + v3_endpoints['public'] = self._get_endpoint_v3_data( + service_id, region, public_url, interface='public') + request = response.copy() + request.pop('id') + for u in ('publicURL', 'internalURL', 'adminURL'): + if request.get(u): + request[u.lower()] = request.pop(u) + return _EndpointDataV2(endpoint_id, service_id, region, public_url, + internal_url, admin_url, v3_endpoints, + {'endpoint': response}, {'endpoint': request}) + + def _get_role_data(self, role_name=None): + role_id = uuid.uuid4().hex + role_name = role_name or uuid.uuid4().hex + request = {'name': role_name} + response = request.copy() + response['id'] = role_id + return _RoleData(role_id, role_name, {'role': response}, + {'role': request}) + + def use_keystone_v3(self, catalog='catalog-v3.json'): + self.adapter = self.useFixture(rm_fixture.Fixture()) + self.calls = [] + self._uri_registry.clear() + self.__do_register_uris([ + dict(method='GET', uri='https://identity.example.com/', + text=open(self.discovery_json, 'r').read()), + dict(method='POST', + uri='https://identity.example.com/v3/auth/tokens', + headers={ + 'X-Subject-Token': self.getUniqueString('KeystoneToken')}, + text=open(os.path.join( + self.fixtures_directory, catalog), 'r').read() + ), + ]) + self._make_test_cloud(identity_api_version='3') + + def use_keystone_v2(self): + self.adapter = self.useFixture(rm_fixture.Fixture()) + self.calls = [] + self._uri_registry.clear() + + self.__do_register_uris([ + dict(method='GET', uri='https://identity.example.com/', + text=open(self.discovery_json, 'r').read()), + dict(method='POST', uri='https://identity.example.com/v2.0/tokens', + text=open(os.path.join( + self.fixtures_directory, 'catalog-v2.json'), 'r').read() + ), + ]) + + self._make_test_cloud(cloud_name='_test_cloud_v2_', + identity_api_version='2.0') + + def _make_test_cloud(self, cloud_name='_test_cloud_', **kwargs): + test_cloud = os.environ.get('OPENSTACKSDK_OS_CLOUD', cloud_name) + self.cloud_config = self.config.get_one_cloud( + cloud=test_cloud, validate=True, **kwargs) + self.cloud = openstack.cloud.OpenStackCloud( + cloud_config=self.cloud_config, + log_inner_exceptions=True) + self.op_cloud = openstack.cloud.OperatorCloud( + cloud_config=self.cloud_config, + log_inner_exceptions=True) + + def get_glance_discovery_mock_dict( + self, image_version_json='image-version.json'): + discovery_fixture = os.path.join( + self.fixtures_directory, image_version_json) + return dict(method='GET', uri='https://image.example.com/', + status_code=300, + text=open(discovery_fixture, 'r').read()) + + def get_designate_discovery_mock_dict(self): + discovery_fixture = os.path.join( + self.fixtures_directory, "dns.json") + return dict(method='GET', uri="https://dns.example.com/", + text=open(discovery_fixture, 'r').read()) + + def get_ironic_discovery_mock_dict(self): + discovery_fixture = os.path.join( + self.fixtures_directory, "baremetal.json") + return dict(method='GET', uri="https://bare-metal.example.com/", + text=open(discovery_fixture, 'r').read()) + + def use_glance(self, image_version_json='image-version.json'): + # NOTE(notmorgan): This method is only meant to be used in "setUp" + # where the ordering of the url being registered is tightly controlled + # if the functionality of .use_glance is meant to be used during an + # actual test case, use .get_glance_discovery_mock and apply to the + # right location in the mock_uris when calling .register_uris + self.__do_register_uris([ + self.get_glance_discovery_mock_dict(image_version_json)]) + + def use_designate(self): + # NOTE(slaweq): This method is only meant to be used in "setUp" + # where the ordering of the url being registered is tightly controlled + # if the functionality of .use_designate is meant to be used during an + # actual test case, use .get_designate_discovery_mock and apply to the + # right location in the mock_uris when calling .register_uris + self.__do_register_uris([ + self.get_designate_discovery_mock_dict()]) + + def use_ironic(self): + # NOTE(TheJulia): This method is only meant to be used in "setUp" + # where the ordering of the url being registered is tightly controlled + # if the functionality of .use_ironic is meant to be used during an + # actual test case, use .get_ironic_discovery_mock and apply to the + # right location in the mock_uris when calling .register_uris + self.__do_register_uris([ + self.get_ironic_discovery_mock_dict()]) + + def register_uris(self, uri_mock_list=None): + """Mock a list of URIs and responses via requests mock. + + This method may be called only once per test-case to avoid odd + and difficult to debug interactions. Discovery and Auth request mocking + happens separately from this method. + + :param uri_mock_list: List of dictionaries that template out what is + passed to requests_mock fixture's `register_uri`. + Format is: + {'method': , + 'uri': , + ... + } + + Common keys to pass in the dictionary: + * json: the json response (dict) + * status_code: the HTTP status (int) + * validate: The request body (dict) to + validate with assert_calls + all key-word arguments that are valid to send to + requests_mock are supported. + + This list should be in the order in which calls + are made. When `assert_calls` is executed, order + here will be validated. Duplicate URIs and + Methods are allowed and will be collapsed into a + single matcher. Each response will be returned + in order as the URI+Method is hit. + :type uri_mock_list: list + :return: None + """ + assert not self.__register_uris_called + self.__do_register_uris(uri_mock_list or []) + self.__register_uris_called = True + + def __do_register_uris(self, uri_mock_list=None): + for to_mock in uri_mock_list: + kw_params = {k: to_mock.pop(k) + for k in ('request_headers', 'complete_qs', + '_real_http') + if k in to_mock} + + method = to_mock.pop('method') + uri = to_mock.pop('uri') + # NOTE(notmorgan): make sure the delimiter is non-url-safe, in this + # case "|" is used so that the split can be a bit easier on + # maintainers of this code. + key = '{method}|{uri}|{params}'.format( + method=method, uri=uri, params=kw_params) + validate = to_mock.pop('validate', {}) + valid_keys = set(['json', 'headers', 'params']) + invalid_keys = set(validate.keys()) - valid_keys + if invalid_keys: + raise TypeError( + "Invalid values passed to validate: {keys}".format( + keys=invalid_keys)) + headers = structures.CaseInsensitiveDict(to_mock.pop('headers', + {})) + if 'content-type' not in headers: + headers[u'content-type'] = 'application/json' + + to_mock['headers'] = headers + + self.calls += [ + dict( + method=method, + url=uri, **validate) + ] + self._uri_registry.setdefault( + key, {'response_list': [], 'kw_params': kw_params}) + if self._uri_registry[key]['kw_params'] != kw_params: + raise AssertionError( + 'PROGRAMMING ERROR: key-word-params ' + 'should be part of the uri_key and cannot change, ' + 'it will affect the matcher in requests_mock. ' + '%(old)r != %(new)r' % + {'old': self._uri_registry[key]['kw_params'], + 'new': kw_params}) + self._uri_registry[key]['response_list'].append(to_mock) + + for mocked, params in self._uri_registry.items(): + mock_method, mock_uri, _ignored = mocked.split('|', 2) + self.adapter.register_uri( + mock_method, mock_uri, params['response_list'], + **params['kw_params']) + + def assert_calls(self, stop_after=None, do_count=True): + for (x, (call, history)) in enumerate( + zip(self.calls, self.adapter.request_history)): + if stop_after and x > stop_after: + break + + call_uri_parts = urllib.parse.urlparse(call['url']) + history_uri_parts = urllib.parse.urlparse(history.url) + self.assertEqual( + (call['method'], call_uri_parts.scheme, call_uri_parts.netloc, + call_uri_parts.path, call_uri_parts.params, + urllib.parse.parse_qs(call_uri_parts.query)), + (history.method, history_uri_parts.scheme, + history_uri_parts.netloc, history_uri_parts.path, + history_uri_parts.params, + urllib.parse.parse_qs(history_uri_parts.query)), + ('REST mismatch on call %(index)d. Expected %(call)r. ' + 'Got %(history)r). ' + 'NOTE: query string order differences wont cause mismatch' % + { + 'index': x, + 'call': '{method} {url}'.format(method=call['method'], + url=call['url']), + 'history': '{method} {url}'.format( + method=history.method, + url=history.url)}) + ) + if 'json' in call: + self.assertEqual( + call['json'], history.json(), + 'json content mismatch in call {index}'.format(index=x)) + # headers in a call isn't exhaustive - it's checking to make sure + # a specific header or headers are there, not that they are the + # only headers + if 'headers' in call: + for key, value in call['headers'].items(): + self.assertEqual( + value, history.headers[key], + 'header mismatch in call {index}'.format(index=x)) + if do_count: + self.assertEqual( + len(self.calls), len(self.adapter.request_history)) + + +class IronicTestCase(RequestsMockTestCase): + + def setUp(self): + super(IronicTestCase, self).setUp() + self.use_ironic() + self.uuid = str(uuid.uuid4()) + self.name = self.getUniqueString('name') + + def get_mock_url(self, resource=None, append=None, qs_elements=None): + return super(IronicTestCase, self).get_mock_url( + service_type='baremetal', interface='public', resource=resource, + append=append, base_url_append='v1', qs_elements=qs_elements) diff --git a/openstack/cloud/tests/unit/__init__.py b/openstack/tests/unit/cloud/__init__.py similarity index 100% rename from openstack/cloud/tests/unit/__init__.py rename to openstack/tests/unit/cloud/__init__.py diff --git a/openstack/cloud/tests/unit/test__adapter.py b/openstack/tests/unit/cloud/test__adapter.py similarity index 100% rename from openstack/cloud/tests/unit/test__adapter.py rename to openstack/tests/unit/cloud/test__adapter.py diff --git a/openstack/cloud/tests/unit/test__utils.py b/openstack/tests/unit/cloud/test__utils.py similarity index 100% rename from openstack/cloud/tests/unit/test__utils.py rename to openstack/tests/unit/cloud/test__utils.py diff --git a/openstack/cloud/tests/unit/test_aggregate.py b/openstack/tests/unit/cloud/test_aggregate.py similarity index 100% rename from openstack/cloud/tests/unit/test_aggregate.py rename to openstack/tests/unit/cloud/test_aggregate.py diff --git a/openstack/cloud/tests/unit/test_availability_zones.py b/openstack/tests/unit/cloud/test_availability_zones.py similarity index 100% rename from openstack/cloud/tests/unit/test_availability_zones.py rename to openstack/tests/unit/cloud/test_availability_zones.py diff --git a/openstack/cloud/tests/unit/test_baremetal_node.py b/openstack/tests/unit/cloud/test_baremetal_node.py similarity index 100% rename from openstack/cloud/tests/unit/test_baremetal_node.py rename to openstack/tests/unit/cloud/test_baremetal_node.py diff --git a/openstack/cloud/tests/unit/test_caching.py b/openstack/tests/unit/cloud/test_caching.py similarity index 100% rename from openstack/cloud/tests/unit/test_caching.py rename to openstack/tests/unit/cloud/test_caching.py diff --git a/openstack/cloud/tests/unit/test_cluster_templates.py b/openstack/tests/unit/cloud/test_cluster_templates.py similarity index 100% rename from openstack/cloud/tests/unit/test_cluster_templates.py rename to openstack/tests/unit/cloud/test_cluster_templates.py diff --git a/openstack/cloud/tests/unit/test_create_server.py b/openstack/tests/unit/cloud/test_create_server.py similarity index 100% rename from openstack/cloud/tests/unit/test_create_server.py rename to openstack/tests/unit/cloud/test_create_server.py diff --git a/openstack/cloud/tests/unit/test_create_volume_snapshot.py b/openstack/tests/unit/cloud/test_create_volume_snapshot.py similarity index 100% rename from openstack/cloud/tests/unit/test_create_volume_snapshot.py rename to openstack/tests/unit/cloud/test_create_volume_snapshot.py diff --git a/openstack/cloud/tests/unit/test_delete_server.py b/openstack/tests/unit/cloud/test_delete_server.py similarity index 100% rename from openstack/cloud/tests/unit/test_delete_server.py rename to openstack/tests/unit/cloud/test_delete_server.py diff --git a/openstack/cloud/tests/unit/test_delete_volume_snapshot.py b/openstack/tests/unit/cloud/test_delete_volume_snapshot.py similarity index 100% rename from openstack/cloud/tests/unit/test_delete_volume_snapshot.py rename to openstack/tests/unit/cloud/test_delete_volume_snapshot.py diff --git a/openstack/cloud/tests/unit/test_domain_params.py b/openstack/tests/unit/cloud/test_domain_params.py similarity index 100% rename from openstack/cloud/tests/unit/test_domain_params.py rename to openstack/tests/unit/cloud/test_domain_params.py diff --git a/openstack/cloud/tests/unit/test_domains.py b/openstack/tests/unit/cloud/test_domains.py similarity index 100% rename from openstack/cloud/tests/unit/test_domains.py rename to openstack/tests/unit/cloud/test_domains.py diff --git a/openstack/cloud/tests/unit/test_endpoints.py b/openstack/tests/unit/cloud/test_endpoints.py similarity index 100% rename from openstack/cloud/tests/unit/test_endpoints.py rename to openstack/tests/unit/cloud/test_endpoints.py diff --git a/openstack/cloud/tests/unit/test_flavors.py b/openstack/tests/unit/cloud/test_flavors.py similarity index 100% rename from openstack/cloud/tests/unit/test_flavors.py rename to openstack/tests/unit/cloud/test_flavors.py diff --git a/openstack/cloud/tests/unit/test_floating_ip_common.py b/openstack/tests/unit/cloud/test_floating_ip_common.py similarity index 100% rename from openstack/cloud/tests/unit/test_floating_ip_common.py rename to openstack/tests/unit/cloud/test_floating_ip_common.py diff --git a/openstack/cloud/tests/unit/test_floating_ip_neutron.py b/openstack/tests/unit/cloud/test_floating_ip_neutron.py similarity index 100% rename from openstack/cloud/tests/unit/test_floating_ip_neutron.py rename to openstack/tests/unit/cloud/test_floating_ip_neutron.py diff --git a/openstack/cloud/tests/unit/test_floating_ip_nova.py b/openstack/tests/unit/cloud/test_floating_ip_nova.py similarity index 100% rename from openstack/cloud/tests/unit/test_floating_ip_nova.py rename to openstack/tests/unit/cloud/test_floating_ip_nova.py diff --git a/openstack/cloud/tests/unit/test_floating_ip_pool.py b/openstack/tests/unit/cloud/test_floating_ip_pool.py similarity index 100% rename from openstack/cloud/tests/unit/test_floating_ip_pool.py rename to openstack/tests/unit/cloud/test_floating_ip_pool.py diff --git a/openstack/cloud/tests/unit/test_groups.py b/openstack/tests/unit/cloud/test_groups.py similarity index 100% rename from openstack/cloud/tests/unit/test_groups.py rename to openstack/tests/unit/cloud/test_groups.py diff --git a/openstack/cloud/tests/unit/test_identity_roles.py b/openstack/tests/unit/cloud/test_identity_roles.py similarity index 100% rename from openstack/cloud/tests/unit/test_identity_roles.py rename to openstack/tests/unit/cloud/test_identity_roles.py diff --git a/openstack/cloud/tests/unit/test_image.py b/openstack/tests/unit/cloud/test_image.py similarity index 100% rename from openstack/cloud/tests/unit/test_image.py rename to openstack/tests/unit/cloud/test_image.py diff --git a/openstack/cloud/tests/unit/test_image_snapshot.py b/openstack/tests/unit/cloud/test_image_snapshot.py similarity index 100% rename from openstack/cloud/tests/unit/test_image_snapshot.py rename to openstack/tests/unit/cloud/test_image_snapshot.py diff --git a/openstack/cloud/tests/unit/test_inventory.py b/openstack/tests/unit/cloud/test_inventory.py similarity index 100% rename from openstack/cloud/tests/unit/test_inventory.py rename to openstack/tests/unit/cloud/test_inventory.py diff --git a/openstack/cloud/tests/unit/test_keypair.py b/openstack/tests/unit/cloud/test_keypair.py similarity index 100% rename from openstack/cloud/tests/unit/test_keypair.py rename to openstack/tests/unit/cloud/test_keypair.py diff --git a/openstack/cloud/tests/unit/test_limits.py b/openstack/tests/unit/cloud/test_limits.py similarity index 100% rename from openstack/cloud/tests/unit/test_limits.py rename to openstack/tests/unit/cloud/test_limits.py diff --git a/openstack/cloud/tests/unit/test_magnum_services.py b/openstack/tests/unit/cloud/test_magnum_services.py similarity index 100% rename from openstack/cloud/tests/unit/test_magnum_services.py rename to openstack/tests/unit/cloud/test_magnum_services.py diff --git a/openstack/cloud/tests/unit/test_meta.py b/openstack/tests/unit/cloud/test_meta.py similarity index 100% rename from openstack/cloud/tests/unit/test_meta.py rename to openstack/tests/unit/cloud/test_meta.py diff --git a/openstack/cloud/tests/unit/test_network.py b/openstack/tests/unit/cloud/test_network.py similarity index 100% rename from openstack/cloud/tests/unit/test_network.py rename to openstack/tests/unit/cloud/test_network.py diff --git a/openstack/cloud/tests/unit/test_normalize.py b/openstack/tests/unit/cloud/test_normalize.py similarity index 100% rename from openstack/cloud/tests/unit/test_normalize.py rename to openstack/tests/unit/cloud/test_normalize.py diff --git a/openstack/cloud/tests/unit/test_object.py b/openstack/tests/unit/cloud/test_object.py similarity index 100% rename from openstack/cloud/tests/unit/test_object.py rename to openstack/tests/unit/cloud/test_object.py diff --git a/openstack/cloud/tests/unit/test_operator_noauth.py b/openstack/tests/unit/cloud/test_operator_noauth.py similarity index 100% rename from openstack/cloud/tests/unit/test_operator_noauth.py rename to openstack/tests/unit/cloud/test_operator_noauth.py diff --git a/openstack/cloud/tests/unit/test_port.py b/openstack/tests/unit/cloud/test_port.py similarity index 100% rename from openstack/cloud/tests/unit/test_port.py rename to openstack/tests/unit/cloud/test_port.py diff --git a/openstack/cloud/tests/unit/test_project.py b/openstack/tests/unit/cloud/test_project.py similarity index 100% rename from openstack/cloud/tests/unit/test_project.py rename to openstack/tests/unit/cloud/test_project.py diff --git a/openstack/cloud/tests/unit/test_qos_bandwidth_limit_rule.py b/openstack/tests/unit/cloud/test_qos_bandwidth_limit_rule.py similarity index 100% rename from openstack/cloud/tests/unit/test_qos_bandwidth_limit_rule.py rename to openstack/tests/unit/cloud/test_qos_bandwidth_limit_rule.py diff --git a/openstack/cloud/tests/unit/test_qos_dscp_marking_rule.py b/openstack/tests/unit/cloud/test_qos_dscp_marking_rule.py similarity index 100% rename from openstack/cloud/tests/unit/test_qos_dscp_marking_rule.py rename to openstack/tests/unit/cloud/test_qos_dscp_marking_rule.py diff --git a/openstack/cloud/tests/unit/test_qos_minimum_bandwidth_rule.py b/openstack/tests/unit/cloud/test_qos_minimum_bandwidth_rule.py similarity index 100% rename from openstack/cloud/tests/unit/test_qos_minimum_bandwidth_rule.py rename to openstack/tests/unit/cloud/test_qos_minimum_bandwidth_rule.py diff --git a/openstack/cloud/tests/unit/test_qos_policy.py b/openstack/tests/unit/cloud/test_qos_policy.py similarity index 100% rename from openstack/cloud/tests/unit/test_qos_policy.py rename to openstack/tests/unit/cloud/test_qos_policy.py diff --git a/openstack/cloud/tests/unit/test_qos_rule_type.py b/openstack/tests/unit/cloud/test_qos_rule_type.py similarity index 100% rename from openstack/cloud/tests/unit/test_qos_rule_type.py rename to openstack/tests/unit/cloud/test_qos_rule_type.py diff --git a/openstack/cloud/tests/unit/test_quotas.py b/openstack/tests/unit/cloud/test_quotas.py similarity index 100% rename from openstack/cloud/tests/unit/test_quotas.py rename to openstack/tests/unit/cloud/test_quotas.py diff --git a/openstack/cloud/tests/unit/test_rebuild_server.py b/openstack/tests/unit/cloud/test_rebuild_server.py similarity index 100% rename from openstack/cloud/tests/unit/test_rebuild_server.py rename to openstack/tests/unit/cloud/test_rebuild_server.py diff --git a/openstack/cloud/tests/unit/test_recordset.py b/openstack/tests/unit/cloud/test_recordset.py similarity index 100% rename from openstack/cloud/tests/unit/test_recordset.py rename to openstack/tests/unit/cloud/test_recordset.py diff --git a/openstack/cloud/tests/unit/test_role_assignment.py b/openstack/tests/unit/cloud/test_role_assignment.py similarity index 100% rename from openstack/cloud/tests/unit/test_role_assignment.py rename to openstack/tests/unit/cloud/test_role_assignment.py diff --git a/openstack/cloud/tests/unit/test_router.py b/openstack/tests/unit/cloud/test_router.py similarity index 100% rename from openstack/cloud/tests/unit/test_router.py rename to openstack/tests/unit/cloud/test_router.py diff --git a/openstack/cloud/tests/unit/test_security_groups.py b/openstack/tests/unit/cloud/test_security_groups.py similarity index 100% rename from openstack/cloud/tests/unit/test_security_groups.py rename to openstack/tests/unit/cloud/test_security_groups.py diff --git a/openstack/cloud/tests/unit/test_server_console.py b/openstack/tests/unit/cloud/test_server_console.py similarity index 100% rename from openstack/cloud/tests/unit/test_server_console.py rename to openstack/tests/unit/cloud/test_server_console.py diff --git a/openstack/cloud/tests/unit/test_server_delete_metadata.py b/openstack/tests/unit/cloud/test_server_delete_metadata.py similarity index 100% rename from openstack/cloud/tests/unit/test_server_delete_metadata.py rename to openstack/tests/unit/cloud/test_server_delete_metadata.py diff --git a/openstack/cloud/tests/unit/test_server_group.py b/openstack/tests/unit/cloud/test_server_group.py similarity index 100% rename from openstack/cloud/tests/unit/test_server_group.py rename to openstack/tests/unit/cloud/test_server_group.py diff --git a/openstack/cloud/tests/unit/test_server_set_metadata.py b/openstack/tests/unit/cloud/test_server_set_metadata.py similarity index 100% rename from openstack/cloud/tests/unit/test_server_set_metadata.py rename to openstack/tests/unit/cloud/test_server_set_metadata.py diff --git a/openstack/cloud/tests/unit/test_services.py b/openstack/tests/unit/cloud/test_services.py similarity index 100% rename from openstack/cloud/tests/unit/test_services.py rename to openstack/tests/unit/cloud/test_services.py diff --git a/openstack/cloud/tests/unit/test_shade.py b/openstack/tests/unit/cloud/test_shade.py similarity index 100% rename from openstack/cloud/tests/unit/test_shade.py rename to openstack/tests/unit/cloud/test_shade.py diff --git a/openstack/cloud/tests/unit/test_shade_operator.py b/openstack/tests/unit/cloud/test_shade_operator.py similarity index 100% rename from openstack/cloud/tests/unit/test_shade_operator.py rename to openstack/tests/unit/cloud/test_shade_operator.py diff --git a/openstack/cloud/tests/unit/test_stack.py b/openstack/tests/unit/cloud/test_stack.py similarity index 100% rename from openstack/cloud/tests/unit/test_stack.py rename to openstack/tests/unit/cloud/test_stack.py diff --git a/openstack/cloud/tests/unit/test_subnet.py b/openstack/tests/unit/cloud/test_subnet.py similarity index 100% rename from openstack/cloud/tests/unit/test_subnet.py rename to openstack/tests/unit/cloud/test_subnet.py diff --git a/openstack/cloud/tests/unit/test_task_manager.py b/openstack/tests/unit/cloud/test_task_manager.py similarity index 100% rename from openstack/cloud/tests/unit/test_task_manager.py rename to openstack/tests/unit/cloud/test_task_manager.py diff --git a/openstack/cloud/tests/unit/test_update_server.py b/openstack/tests/unit/cloud/test_update_server.py similarity index 100% rename from openstack/cloud/tests/unit/test_update_server.py rename to openstack/tests/unit/cloud/test_update_server.py diff --git a/openstack/cloud/tests/unit/test_usage.py b/openstack/tests/unit/cloud/test_usage.py similarity index 100% rename from openstack/cloud/tests/unit/test_usage.py rename to openstack/tests/unit/cloud/test_usage.py diff --git a/openstack/cloud/tests/unit/test_users.py b/openstack/tests/unit/cloud/test_users.py similarity index 100% rename from openstack/cloud/tests/unit/test_users.py rename to openstack/tests/unit/cloud/test_users.py diff --git a/openstack/cloud/tests/unit/test_volume.py b/openstack/tests/unit/cloud/test_volume.py similarity index 100% rename from openstack/cloud/tests/unit/test_volume.py rename to openstack/tests/unit/cloud/test_volume.py diff --git a/openstack/cloud/tests/unit/test_volume_access.py b/openstack/tests/unit/cloud/test_volume_access.py similarity index 100% rename from openstack/cloud/tests/unit/test_volume_access.py rename to openstack/tests/unit/cloud/test_volume_access.py diff --git a/openstack/cloud/tests/unit/test_volume_backups.py b/openstack/tests/unit/cloud/test_volume_backups.py similarity index 100% rename from openstack/cloud/tests/unit/test_volume_backups.py rename to openstack/tests/unit/cloud/test_volume_backups.py diff --git a/openstack/cloud/tests/unit/test_zone.py b/openstack/tests/unit/cloud/test_zone.py similarity index 100% rename from openstack/cloud/tests/unit/test_zone.py rename to openstack/tests/unit/cloud/test_zone.py diff --git a/openstack/cloud/tests/unit/fixtures/baremetal.json b/openstack/tests/unit/fixtures/baremetal.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/baremetal.json rename to openstack/tests/unit/fixtures/baremetal.json diff --git a/openstack/cloud/tests/unit/fixtures/catalog-v2.json b/openstack/tests/unit/fixtures/catalog-v2.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/catalog-v2.json rename to openstack/tests/unit/fixtures/catalog-v2.json diff --git a/openstack/cloud/tests/unit/fixtures/catalog-v3.json b/openstack/tests/unit/fixtures/catalog-v3.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/catalog-v3.json rename to openstack/tests/unit/fixtures/catalog-v3.json diff --git a/openstack/cloud/tests/unit/fixtures/clouds/clouds.yaml b/openstack/tests/unit/fixtures/clouds/clouds.yaml similarity index 100% rename from openstack/cloud/tests/unit/fixtures/clouds/clouds.yaml rename to openstack/tests/unit/fixtures/clouds/clouds.yaml diff --git a/openstack/cloud/tests/unit/fixtures/clouds/clouds_cache.yaml b/openstack/tests/unit/fixtures/clouds/clouds_cache.yaml similarity index 100% rename from openstack/cloud/tests/unit/fixtures/clouds/clouds_cache.yaml rename to openstack/tests/unit/fixtures/clouds/clouds_cache.yaml diff --git a/openstack/cloud/tests/unit/fixtures/discovery.json b/openstack/tests/unit/fixtures/discovery.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/discovery.json rename to openstack/tests/unit/fixtures/discovery.json diff --git a/openstack/cloud/tests/unit/fixtures/dns.json b/openstack/tests/unit/fixtures/dns.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/dns.json rename to openstack/tests/unit/fixtures/dns.json diff --git a/openstack/cloud/tests/unit/fixtures/image-version-broken.json b/openstack/tests/unit/fixtures/image-version-broken.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/image-version-broken.json rename to openstack/tests/unit/fixtures/image-version-broken.json diff --git a/openstack/cloud/tests/unit/fixtures/image-version-v1.json b/openstack/tests/unit/fixtures/image-version-v1.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/image-version-v1.json rename to openstack/tests/unit/fixtures/image-version-v1.json diff --git a/openstack/cloud/tests/unit/fixtures/image-version-v2.json b/openstack/tests/unit/fixtures/image-version-v2.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/image-version-v2.json rename to openstack/tests/unit/fixtures/image-version-v2.json diff --git a/openstack/cloud/tests/unit/fixtures/image-version.json b/openstack/tests/unit/fixtures/image-version.json similarity index 100% rename from openstack/cloud/tests/unit/fixtures/image-version.json rename to openstack/tests/unit/fixtures/image-version.json diff --git a/os-client-config/.coveragerc b/os-client-config/.coveragerc deleted file mode 100644 index 3c1292222..000000000 --- a/os-client-config/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -branch = True -source = os_client_config -omit = os_client_config/tests/*,os_client_config/openstack/* - -[report] -ignore_errors = True diff --git a/os-client-config/.gitignore b/os-client-config/.gitignore deleted file mode 100644 index c24b89b8a..000000000 --- a/os-client-config/.gitignore +++ /dev/null @@ -1,55 +0,0 @@ -*.py[cod] -.venv - -# C extensions -*.so - -# Packages -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib -lib64 - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -cover -.coverage -.tox -nosetests.xml -.stestr/ -.testrepository - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Complexity -output/*.html -output/*/index.html - -# Sphinx -doc/build - -# pbr generates these -AUTHORS -ChangeLog - -# Editors -*~ -.*.swp -.*sw? diff --git a/os-client-config/.gitreview b/os-client-config/.gitreview deleted file mode 100644 index 5ba7eddc1..000000000 --- a/os-client-config/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack/os-client-config.git diff --git a/os-client-config/.mailmap b/os-client-config/.mailmap deleted file mode 100644 index cc92f17b8..000000000 --- a/os-client-config/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -# Format is: -# -# \ No newline at end of file diff --git a/os-client-config/.stestr.conf b/os-client-config/.stestr.conf deleted file mode 100644 index 792382206..000000000 --- a/os-client-config/.stestr.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -test_path=. -top_dir=./ diff --git a/os-client-config/.testr.conf b/os-client-config/.testr.conf deleted file mode 100644 index fb622677a..000000000 --- a/os-client-config/.testr.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list \ No newline at end of file diff --git a/os-client-config/CONTRIBUTING.rst b/os-client-config/CONTRIBUTING.rst deleted file mode 100644 index 1990ecf25..000000000 --- a/os-client-config/CONTRIBUTING.rst +++ /dev/null @@ -1,16 +0,0 @@ -If you would like to contribute to the development of OpenStack, -you must follow the steps in this page: - - http://docs.openstack.org/infra/manual/developers.html - -Once those steps have been completed, changes to OpenStack -should be submitted for review via the Gerrit tool, following -the workflow documented at: - - http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad, not GitHub: - - https://bugs.launchpad.net/os-client-config \ No newline at end of file diff --git a/os-client-config/HACKING.rst b/os-client-config/HACKING.rst deleted file mode 100644 index aab08e34e..000000000 --- a/os-client-config/HACKING.rst +++ /dev/null @@ -1,4 +0,0 @@ -os-client-config Style Commandments -=============================================== - -Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest diff --git a/os-client-config/LICENSE b/os-client-config/LICENSE deleted file mode 100644 index 67db85882..000000000 --- a/os-client-config/LICENSE +++ /dev/null @@ -1,175 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. diff --git a/os-client-config/README.rst b/os-client-config/README.rst deleted file mode 100644 index 35ff07b43..000000000 --- a/os-client-config/README.rst +++ /dev/null @@ -1,25 +0,0 @@ -================ -os-client-config -================ - -.. image:: http://governance.openstack.org/badges/os-client-config.svg - :target: http://governance.openstack.org/reference/tags/index.html - -`os-client-config` is a library for collecting client configuration for -using an OpenStack cloud in a consistent and comprehensive manner. It -will find cloud config for as few as 1 cloud and as many as you want to -put in a config file. It will read environment variables and config files, -and it also contains some vendor specific default values so that you don't -have to know extra info to use OpenStack - -* If you have a config file, you will get the clouds listed in it -* If you have environment variables, you will get a cloud named `envvars` -* If you have neither, you will get a cloud named `defaults` with base defaults - -Source ------- - -* Free software: Apache license -* Documentation: http://docs.openstack.org/os-client-config/latest -* Source: http://git.openstack.org/cgit/openstack/os-client-config -* Bugs: http://bugs.launchpad.net/os-client-config diff --git a/os-client-config/doc/source/conf.py b/os-client-config/doc/source/conf.py deleted file mode 100755 index cbd9888d1..000000000 --- a/os-client-config/doc/source/conf.py +++ /dev/null @@ -1,86 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -import openstackdocstheme - -sys.path.insert(0, os.path.abspath('../..')) -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - #'sphinx.ext.intersphinx', - 'reno.sphinxext', - 'openstackdocstheme', -] - -# openstackdocstheme options -repository_name = 'openstack/os-client-config' -bug_project = 'os-client-config' -bug_tag = '' -html_last_updated_fmt = '%Y-%m-%d %H:%M' - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'os-client-config' -copyright = u'2015, various OpenStack developers' - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -# html_theme_path = ["."] -# html_theme = '_theme' -# html_static_path = ['static'] -html_theme = 'openstackdocs' -html_theme_path = [openstackdocstheme.get_html_theme_path()] - -# Output file base name for HTML help builder. -htmlhelp_basename = '%sdoc' % project - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', - '%s.tex' % project, - u'%s Documentation' % project, - u'OpenStack Foundation', 'manual'), -] - -# Example configuration for intersphinx: refer to the Python standard library. -#intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/os-client-config/doc/source/contributor/index.rst b/os-client-config/doc/source/contributor/index.rst deleted file mode 100644 index 2aa070771..000000000 --- a/os-client-config/doc/source/contributor/index.rst +++ /dev/null @@ -1,4 +0,0 @@ -============ -Contributing -============ -.. include:: ../../../CONTRIBUTING.rst diff --git a/os-client-config/doc/source/index.rst b/os-client-config/doc/source/index.rst deleted file mode 100644 index 5a407adcc..000000000 --- a/os-client-config/doc/source/index.rst +++ /dev/null @@ -1,32 +0,0 @@ -================ -os-client-config -================ - -.. image:: http://governance.openstack.org/badges/os-client-config.svg - :target: http://governance.openstack.org/reference/tags/index.html - -`os-client-config` is a library for collecting client configuration for -using an OpenStack cloud in a consistent and comprehensive manner. It -will find cloud config for as few as 1 cloud and as many as you want to -put in a config file. It will read environment variables and config files, -and it also contains some vendor specific default values so that you don't -have to know extra info to use OpenStack - -* If you have a config file, you will get the clouds listed in it -* If you have environment variables, you will get a cloud named `envvars` -* If you have neither, you will get a cloud named `defaults` with base defaults - -.. toctree:: - :maxdepth: 2 - - install/index - user/index - reference/index - contributor/index - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/os-client-config/doc/source/install/index.rst b/os-client-config/doc/source/install/index.rst deleted file mode 100644 index 48bbc2f20..000000000 --- a/os-client-config/doc/source/install/index.rst +++ /dev/null @@ -1,12 +0,0 @@ -============ -Installation -============ - -At the command line:: - - $ pip install os-client-config - -Or, if you have virtualenvwrapper installed:: - - $ mkvirtualenv os-client-config - $ pip install os-client-config \ No newline at end of file diff --git a/os-client-config/doc/source/user/releasenotes.rst b/os-client-config/doc/source/user/releasenotes.rst deleted file mode 100644 index 9f41b7e14..000000000 --- a/os-client-config/doc/source/user/releasenotes.rst +++ /dev/null @@ -1,6 +0,0 @@ -============= -Release Notes -============= - -Release notes for `os-client-config` can be found at -http://docs.openstack.org/releasenotes/os-client-config/ diff --git a/os-client-config/requirements.txt b/os-client-config/requirements.txt deleted file mode 100644 index 6c609105e..000000000 --- a/os-client-config/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -PyYAML>=3.10 # MIT -appdirs>=1.3.0 # MIT License -keystoneauth1>=3.2.0 # Apache-2.0 -requestsexceptions>=1.2.0 # Apache-2.0 diff --git a/os-client-config/setup.cfg b/os-client-config/setup.cfg deleted file mode 100644 index 7149cdf8e..000000000 --- a/os-client-config/setup.cfg +++ /dev/null @@ -1,35 +0,0 @@ -[metadata] -name = os-client-config -summary = OpenStack Client Configuation Library -description-file = - README.rst -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = https://docs.openstack.org/os-client-config/latest -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 - -[files] -packages = - os_client_config - -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 -warning-is-error = 1 - -[upload_sphinx] -upload-dir = doc/build/html - -[wheel] -universal = 1 diff --git a/os-client-config/setup.py b/os-client-config/setup.py deleted file mode 100644 index 566d84432..000000000 --- a/os-client-config/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=2.0.0'], - pbr=True) diff --git a/os-client-config/test-requirements.txt b/os-client-config/test-requirements.txt deleted file mode 100644 index 73d982263..000000000 --- a/os-client-config/test-requirements.txt +++ /dev/null @@ -1,21 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 - -coverage!=4.4,>=4.0 # Apache-2.0 -docutils>=0.11 # OSI-Approved Open Source, Public Domain -extras>=0.0.3 # MIT -fixtures>=3.0.0 # Apache-2.0/BSD -jsonschema<3.0.0,>=2.6.0 # MIT -mock>=2.0.0 # BSD -python-glanceclient>=2.8.0 # Apache-2.0 -python-subunit>=0.0.18 # Apache-2.0/BSD -sphinx>=1.6.2 # BSD -openstackdocstheme>=1.17.0 # Apache-2.0 -oslotest>=1.10.0 # Apache-2.0 -reno>=2.5.0 # Apache-2.0 -testrepository>=0.0.18 # Apache-2.0/BSD -testscenarios>=0.4 # Apache-2.0/BSD -testtools>=1.4.0 # MIT diff --git a/os-client-config/tox.ini b/os-client-config/tox.ini deleted file mode 100644 index 57feb6d0b..000000000 --- a/os-client-config/tox.ini +++ /dev/null @@ -1,45 +0,0 @@ -[tox] -minversion = 1.6 -envlist = py35,py27,pypy,pep8 -skipsdist = True - -[testenv] -usedevelop = True -passenv = ZUUL_CACHE_DIR - REQUIREMENTS_PIP_LOCATION -install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} -setenv = - VIRTUAL_ENV={envdir} - BRANCH_NAME=master - CLIENT_NAME=os-client-config - OS_STDOUT_CAPTURE=1 - OS_STDERR_CAPTURE=1 - OS_TEST_TIMEOUT=60 -deps = -r{toxinidir}/test-requirements.txt -commands = python setup.py testr --slowest --testr-args='{posargs}' - -[testenv:pep8] -commands = flake8 - -[testenv:venv] -commands = {posargs} - -[testenv:cover] -commands = python setup.py test --coverage --coverage-package-name=os_client_config --testr-args='{posargs}' - -[testenv:docs] -deps = - {[testenv]deps} - readme -commands = - python setup.py build_sphinx - python setup.py check -r -s - -[testenv:releasenotes] -commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html - -[flake8] -show-source = True -builtins = _ -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,releasenotes/source/conf.py - diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py index 8e1265344..1a6db74cd 100644 --- a/releasenotes/source/conf.py +++ b/releasenotes/source/conf.py @@ -43,7 +43,7 @@ extensions = [ ] # openstackdocstheme options -repository_name = 'openstack-infra/shade' +repository_name = 'openstack/python-openstacksdk' bug_project = '760' bug_tag = '' html_last_updated_fmt = '%Y-%m-%d %H:%M' @@ -61,15 +61,15 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'Shade Release Notes' -copyright = u'2017, Shade Developers' +project = u'OpenStack SDK Release Notes' +copyright = u'2017, Various members of the OpenStack Foundation' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # import pbr.version -version_info = pbr.version.VersionInfo('shade') +version_info = pbr.version.VersionInfo('openstacksdk') # The full version, including alpha/beta/rc tags. release = version_info.version_string_with_vcs() # The short X.Y version. diff --git a/requirements.txt b/requirements.txt index f9aea340e..1a7ad95d0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,9 +2,21 @@ # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. pbr!=2.1.0,>=2.0.0 # Apache-2.0 -jsonpatch>=1.1 # BSD +PyYAML>=3.10 # MIT +appdirs>=1.3.0 # MIT License +requestsexceptions>=1.2.0 # Apache-2.0 +jsonpatch>=1.16 # BSD six>=1.9.0 # MIT stevedore>=1.20.0 # Apache-2.0 -os-client-config>=1.28.0 # Apache-2.0 -keystoneauth1>=3.1.0 # Apache-2.0 +keystoneauth1>=3.2.0 # Apache-2.0 deprecation>=1.0 # Apache-2.0 + +munch>=2.1.0 # MIT +decorator>=3.4.0 # BSD +jmespath>=0.9.0 # MIT +ipaddress>=1.0.16;python_version<'3.3' # PSF +futures>=3.0;python_version=='2.7' or python_version=='2.6' # BSD +iso8601>=0.1.11 # MIT +netifaces>=0.10.4 # MIT + +dogpile.cache>=0.6.2 # BSD diff --git a/setup.cfg b/setup.cfg index 11118defb..37e19d4bb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,7 +16,6 @@ classifier = Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.5 [files] diff --git a/shade/.coveragerc b/shade/.coveragerc deleted file mode 100644 index ca361e59b..000000000 --- a/shade/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -branch = True -source = shade -omit = shade/tests/* - -[report] -ignore_errors = True diff --git a/shade/.gitignore b/shade/.gitignore deleted file mode 100644 index 1f0139551..000000000 --- a/shade/.gitignore +++ /dev/null @@ -1,54 +0,0 @@ -*.py[cod] - -# C extensions -*.so - -# Packages -.eggs -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib -lib64 - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -cover -.tox -nosetests.xml -.testrepository -.stestr - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Complexity -output/*.html -output/*/index.html - -# Sphinx -doc/build - -# pbr generates these -AUTHORS -ChangeLog - -# Editors -*~ -.*.swp diff --git a/shade/.gitreview b/shade/.gitreview deleted file mode 100644 index 650bebe84..000000000 --- a/shade/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack-infra/openstack.cloud.git diff --git a/shade/.mailmap b/shade/.mailmap deleted file mode 100644 index 4d8361ef0..000000000 --- a/shade/.mailmap +++ /dev/null @@ -1,4 +0,0 @@ -# Format is: -# -# - diff --git a/shade/.stestr.conf b/shade/.stestr.conf deleted file mode 100644 index d90a44466..000000000 --- a/shade/.stestr.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -test_path=./shade/tests/unit -top_dir=./ diff --git a/shade/.zuul.yaml b/shade/.zuul.yaml deleted file mode 100644 index eb219b914..000000000 --- a/shade/.zuul.yaml +++ /dev/null @@ -1,8 +0,0 @@ -- project: - name: openstack-infra/shade - templates: - - publish-to-pypi - - publish-openstack-python-docs - check: - jobs: - - openstack-tox-py35 diff --git a/shade/CONTRIBUTING.rst b/shade/CONTRIBUTING.rst deleted file mode 100644 index 798b5b5af..000000000 --- a/shade/CONTRIBUTING.rst +++ /dev/null @@ -1,44 +0,0 @@ -.. _contributing: - -===================== -Contributing to shade -===================== - -If you're interested in contributing to the shade project, -the following will help get you started. - -Contributor License Agreement ------------------------------ - -.. index:: - single: license; agreement - -In order to contribute to the shade project, you need to have -signed OpenStack's contributor's agreement. - -.. seealso:: - - * http://wiki.openstack.org/HowToContribute - * http://wiki.openstack.org/CLA - -Project Hosting Details -------------------------- - -Project Documentation - http://docs.openstack.org/infra/shade/ - -Bug tracker - http://storyboard.openstack.org - -Mailing list (prefix subjects with ``[shade]`` for faster responses) - http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-infra - -Code Hosting - https://git.openstack.org/cgit/openstack-infra/shade - -Code Review - https://review.openstack.org/#/q/status:open+project:openstack-infra/shade,n,z - - Please read `GerritWorkflow`_ before sending your first patch for review. - -.. _GerritWorkflow: https://wiki.openstack.org/wiki/GerritWorkflow diff --git a/shade/HACKING.rst b/shade/HACKING.rst deleted file mode 100644 index 9c8af4d35..000000000 --- a/shade/HACKING.rst +++ /dev/null @@ -1,49 +0,0 @@ -shade Style Commandments -======================== - -Read the OpenStack Style Commandments -http://docs.openstack.org/developer/hacking/ - -Indentation ------------ - -PEP-8 allows for 'visual' indentation. Do not use it. Visual indentation looks -like this: - -.. code-block:: python - - return_value = self.some_method(arg1, arg1, - arg3, arg4) - -Visual indentation makes refactoring the code base unneccesarily hard. - -Instead of visual indentation, use this: - -.. code-block:: python - - return_value = self.some_method( - arg1, arg1, arg3, arg4) - -That way, if some_method ever needs to be renamed, the only line that needs -to be touched is the line with some_method. Additionaly, if you need to -line break at the top of a block, please indent the continuation line -an additional 4 spaces, like this: - -.. code-block:: python - - for val in self.some_method( - arg1, arg1, arg3, arg4): - self.do_something_awesome() - -Neither of these are 'mandated' by PEP-8. However, they are prevailing styles -within this code base. - -Unit Tests ----------- - -Unit tests should be virtually instant. If a unit test takes more than 1 second -to run, it is a bad unit test. Honestly, 1 second is too slow. - -All unit test classes should subclass `openstack.cloud.tests.unit.base.BaseTestCase`. The -base TestCase class takes care of properly creating `OpenStackCloud` objects -in a way that protects against local environment. diff --git a/shade/LICENSE b/shade/LICENSE deleted file mode 100644 index 67db85882..000000000 --- a/shade/LICENSE +++ /dev/null @@ -1,175 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. diff --git a/shade/MANIFEST.in b/shade/MANIFEST.in deleted file mode 100644 index 90f8a7aef..000000000 --- a/shade/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -include AUTHORS -include ChangeLog -exclude .gitignore -exclude .gitreview - -global-exclude *.pyc \ No newline at end of file diff --git a/shade/README.rst b/shade/README.rst deleted file mode 100644 index c43a16699..000000000 --- a/shade/README.rst +++ /dev/null @@ -1,79 +0,0 @@ -Introduction -============ - -shade is a simple client library for interacting with OpenStack clouds. The -key word here is *simple*. Clouds can do many many many things - but there are -probably only about 10 of them that most people care about with any -regularity. If you want to do complicated things, you should probably use -the lower level client libraries - or even the REST API directly. However, -if what you want is to be able to write an application that talks to clouds -no matter what crazy choices the deployer has made in an attempt to be -more hipster than their self-entitled narcissist peers, then shade is for you. - -shade started its life as some code inside of ansible. ansible has a bunch -of different OpenStack related modules, and there was a ton of duplicated -code. Eventually, between refactoring that duplication into an internal -library, and adding logic and features that the OpenStack Infra team had -developed to run client applications at scale, it turned out that we'd written -nine-tenths of what we'd need to have a standalone library. - -.. _example: - -Example -======= - -Sometimes an example is nice. - -#. Create a ``clouds.yml`` file:: - - clouds: - mordred: - region_name: RegionOne - auth: - username: 'mordred' - password: XXXXXXX - project_name: 'shade' - auth_url: 'https://montytaylor-sjc.openstack.blueboxgrid.com:5001/v2.0' - - Please note: *os-client-config* will look for a file called ``clouds.yaml`` - in the following locations: - - * Current Directory - * ``~/.config/openstack`` - * ``/etc/openstack`` - - More information at https://pypi.python.org/pypi/os-client-config - - -#. Create a server with *shade*, configured with the ``clouds.yml`` file:: - - import openstack.cloud - - # Initialize and turn on debug logging - openstack.cloud.simple_logging(debug=True) - - # Initialize cloud - # Cloud configs are read with os-client-config - cloud = openstack.cloud.openstack_cloud(cloud='mordred') - - # Upload an image to the cloud - image = cloud.create_image( - 'ubuntu-trusty', filename='ubuntu-trusty.qcow2', wait=True) - - # Find a flavor with at least 512M of RAM - flavor = cloud.get_flavor_by_ram(512) - - # Boot a server, wait for it to boot, and then do whatever is needed - # to get a public ip for it. - cloud.create_server( - 'my-server', image=image, flavor=flavor, wait=True, auto_ip=True) - - -Links -===== - -* `Issue Tracker `_ -* `Code Review `_ -* `Documentation `_ -* `PyPI `_ -* `Mailing list `_ diff --git a/shade/devstack/plugin.sh b/shade/devstack/plugin.sh deleted file mode 100644 index 59c130be2..000000000 --- a/shade/devstack/plugin.sh +++ /dev/null @@ -1,54 +0,0 @@ -# Install and configure **shade** library in devstack -# -# To enable shade in devstack add an entry to local.conf that looks like -# -# [[local|localrc]] -# enable_plugin shade git://git.openstack.org/openstack-infra/shade - -function preinstall_shade { - : -} - -function install_shade { - if use_library_from_git "shade"; then - # don't clone, it'll be done by the plugin install - setup_dev_lib "shade" - else - pip_install "shade" - fi -} - -function configure_shade { - : -} - -function initialize_shade { - : -} - -function unstack_shade { - : -} - -function clean_shade { - : -} - -# This is the main for plugin.sh -if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then - preinstall_shade -elif [[ "$1" == "stack" && "$2" == "install" ]]; then - install_shade -elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then - configure_shade -elif [[ "$1" == "stack" && "$2" == "extra" ]]; then - initialize_shade -fi - -if [[ "$1" == "unstack" ]]; then - unstack_shade -fi - -if [[ "$1" == "clean" ]]; then - clean_shade -fi diff --git a/shade/doc/source/conf.py b/shade/doc/source/conf.py deleted file mode 100755 index aaf41b319..000000000 --- a/shade/doc/source/conf.py +++ /dev/null @@ -1,47 +0,0 @@ -import os -import sys - -sys.path.insert(0, os.path.abspath('../..')) - -extensions = [ - 'sphinx.ext.autodoc', - 'openstackdocstheme', - 'reno.sphinxext' -] - -# openstackdocstheme options -repository_name = 'openstack-infra/shade' -bug_project = '760' -bug_tag = '' -html_last_updated_fmt = '%Y-%m-%d %H:%M' -html_theme = 'openstackdocs' - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'shade' -copyright = u'2014 Hewlett-Packard Development Company, L.P.' - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# Output file base name for HTML help builder. -htmlhelp_basename = '%sdoc' % project - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', - '%s.tex' % project, - u'%s Documentation' % project, - u'Monty Taylor', 'manual'), -] diff --git a/shade/doc/source/contributor/index.rst b/shade/doc/source/contributor/index.rst deleted file mode 100644 index b032c3728..000000000 --- a/shade/doc/source/contributor/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -========================= - Shade Contributor Guide -========================= - -.. toctree:: - :maxdepth: 2 - - contributing - coding diff --git a/shade/doc/source/index.rst b/shade/doc/source/index.rst deleted file mode 100644 index 5235e1664..000000000 --- a/shade/doc/source/index.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. shade documentation master file, created by - sphinx-quickstart on Tue Jul 9 22:26:36 2013. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -================================= -Welcome to shade's documentation! -================================= - -Contents: - -.. toctree:: - :maxdepth: 2 - - install/index - user/index - contributor/index - -.. releasenotes contains a lot of sections, toctree with maxdepth 1 is used. -.. toctree:: - :maxdepth: 1 - - releasenotes/index - -.. include:: ../../README.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` diff --git a/shade/doc/source/install/index.rst b/shade/doc/source/install/index.rst deleted file mode 100644 index 9699e779e..000000000 --- a/shade/doc/source/install/index.rst +++ /dev/null @@ -1,12 +0,0 @@ -============ -Installation -============ - -At the command line:: - - $ pip install shade - -Or, if you have virtualenv wrapper installed:: - - $ mkvirtualenv shade - $ pip install shade diff --git a/shade/doc/source/releasenotes/index.rst b/shade/doc/source/releasenotes/index.rst deleted file mode 100644 index 2a4bceb4e..000000000 --- a/shade/doc/source/releasenotes/index.rst +++ /dev/null @@ -1,5 +0,0 @@ -============= -Release Notes -============= - -.. release-notes:: diff --git a/shade/requirements.txt b/shade/requirements.txt deleted file mode 100644 index 5a3916192..000000000 --- a/shade/requirements.txt +++ /dev/null @@ -1,26 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -pbr!=2.1.0,>=2.0.0 # Apache-2.0 - -munch>=2.1.0 # MIT -decorator>=3.4.0 # BSD -jmespath>=0.9.0 # MIT -jsonpatch>=1.16 # BSD -ipaddress>=1.0.16;python_version<'3.3' # PSF -os-client-config>=1.28.0 # Apache-2.0 -# These two are here to prevent issues with version pin mismatches from our -# client library transitive depends. -# Babel can be removed when ironicclient is removed (because of openstackclient -# transitive depend) -Babel!=2.4.0,>=2.3.4 # BSD -requestsexceptions>=1.2.0 # Apache-2.0 -six>=1.9.0 # MIT -futures>=3.0;python_version=='2.7' or python_version=='2.6' # BSD -iso8601>=0.1.11 # MIT - -keystoneauth1>=3.2.0 # Apache-2.0 -netifaces>=0.10.4 # MIT -python-ironicclient>=1.14.0 # Apache-2.0 - -dogpile.cache>=0.6.2 # BSD diff --git a/shade/setup.cfg b/shade/setup.cfg deleted file mode 100644 index 0ad4c36c8..000000000 --- a/shade/setup.cfg +++ /dev/null @@ -1,28 +0,0 @@ -[metadata] -name = shade -summary = Simple client library for interacting with OpenStack clouds -description-file = - README.rst -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = http://docs.openstack.org/shade/latest -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 -warning-is-error = 1 - -[upload_sphinx] -upload-dir = doc/build/html diff --git a/shade/setup.py b/shade/setup.py deleted file mode 100644 index 566d84432..000000000 --- a/shade/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=2.0.0'], - pbr=True) diff --git a/shade/test-requirements.txt b/shade/test-requirements.txt deleted file mode 100644 index b0b3d5028..000000000 --- a/shade/test-requirements.txt +++ /dev/null @@ -1,17 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -hacking<0.12,>=0.11.0 # Apache-2.0 - -coverage!=4.4,>=4.0 # Apache-2.0 -fixtures>=3.0.0 # Apache-2.0/BSD -mock>=2.0.0 # BSD -python-subunit>=0.0.18 # Apache-2.0/BSD -openstackdocstheme>=1.17.0 # Apache-2.0 -oslotest>=1.10.0 # Apache-2.0 -requests-mock>=1.1.0 # Apache-2.0 -sphinx>=1.6.2 # BSD -stestr>=1.0.0 # Apache-2.0 -testscenarios>=0.4 # Apache-2.0/BSD -testtools>=1.4.0 # MIT -reno>=2.5.0 # Apache-2.0 diff --git a/shade/tools/tox_install.sh b/shade/tools/tox_install.sh deleted file mode 100755 index 43468e450..000000000 --- a/shade/tools/tox_install.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -# Client constraint file contains this client version pin that is in conflict -# with installing the client from source. We should remove the version pin in -# the constraints file before applying it for from-source installation. - -CONSTRAINTS_FILE=$1 -shift 1 - -set -e - -# NOTE(tonyb): Place this in the tox enviroment's log dir so it will get -# published to logs.openstack.org for easy debugging. -localfile="$VIRTUAL_ENV/log/upper-constraints.txt" - -if [[ $CONSTRAINTS_FILE != http* ]]; then - CONSTRAINTS_FILE=file://$CONSTRAINTS_FILE -fi -# NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep -curl $CONSTRAINTS_FILE --insecure --progress-bar --output $localfile - -pip install -c$localfile openstack-requirements - -# This is the main purpose of the script: Allow local installation of -# the current repo. It is listed in constraints file and thus any -# install will be constrained and we need to unconstrain it. -edit-constraints $localfile -- $CLIENT_NAME - -pip install -c$localfile -U $* -exit $? diff --git a/shade/tox.ini b/shade/tox.ini deleted file mode 100644 index 52a9274c1..000000000 --- a/shade/tox.ini +++ /dev/null @@ -1,80 +0,0 @@ -[tox] -minversion = 1.6 -envlist = py35,py27,pep8 -skipsdist = True - -[testenv] -usedevelop = True -basepython = {env:SHADE_TOX_PYTHON:python2} -passenv = UPPER_CONSTRAINTS_FILE -install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} -setenv = - VIRTUAL_ENV={envdir} - LANG=en_US.UTF-8 - LANGUAGE=en_US:en - LC_ALL=C - BRANCH_NAME=master - CLIENT_NAME=shade -deps = -r{toxinidir}/test-requirements.txt -commands = stestr run {posargs} - stestr slowest - -[testenv:functional] -passenv = OS_* SHADE_* UPPER_CONSTRAINTS_FILE -commands = stestr --test-path ./shade/tests/functional run --serial {posargs} - stestr slowest - -[testenv:functional-tips] -passenv = OS_* SHADE_* UPPER_CONSTRAINTS_FILE -whitelist_externals = bash -commands = - bash -x {toxinidir}/extras/install-tips.sh - stestr --test-path ./shade/tests/functional run --serial {posargs} - stestr slowest - -[testenv:pep8] -commands = flake8 shade - -[testenv:venv] -commands = {posargs} - -[testenv:debug] -whitelist_externals = find -commands = - find . -type f -name "*.pyc" -delete - oslo_debug_helper {posargs} - -[testenv:cover] -setenv = - {[testenv]setenv} - PYTHON=coverage run --source shade --parallel-mode -commands = - stestr run {posargs} - coverage combine - coverage html -d cover - coverage xml -o cover/coverage.xml - -[testenv:ansible] -# Need to pass some env vars for the Ansible playbooks -passenv = HOME USER -commands = {toxinidir}/extras/run-ansible-tests.sh -e {envdir} {posargs} - -[testenv:docs] -skip_install = True -deps = -r{toxinidir}/test-requirements.txt -commands = python setup.py build_sphinx - -[testenv:releasenotes] -commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html - -[flake8] -# The following are ignored on purpose - please do not submit patches to "fix" -# without first verifying with a core that fixing them is non-disruptive. -# H103 Is about the Apache license. It's strangely strict about the use of -# single vs double quotes in the license text. Fixing is not worth it -# H306 Is about alphabetical imports - there's a lot to fix -# H4 Are about docstrings - and there's just too many of them to fix -ignore = H103,H306,H4 -show-source = True -builtins = _ -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build diff --git a/test-requirements.txt b/test-requirements.txt index 9c9ff8bdc..a4cd6f449 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,14 +5,18 @@ hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 beautifulsoup4>=4.6.0 # MIT coverage!=4.4,>=4.0 # Apache-2.0 +docutils>=0.11 # OSI-Approved Open Source, Public Domain +extras>=0.0.3 # MIT fixtures>=3.0.0 # Apache-2.0/BSD +jsonschema<3.0.0,>=2.6.0 # MIT mock>=2.0 # BSD python-subunit>=0.0.18 # Apache-2.0/BSD -openstackdocstheme>=1.16.0 # Apache-2.0 -os-testr>=0.8.0 # Apache-2.0 -requests>=2.14.2 # Apache-2.0 -requests-mock>=1.1 # Apache-2.0 +openstackdocstheme>=1.17.0 # Apache-2.0 +oslotest>=1.10.0 # Apache-2.0 +reno>=2.5.0 # Apache-2.0 +requests-mock>=1.1.0 # Apache-2.0 sphinx>=1.6.2 # BSD +stestr>=1.0.0 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=1.4.0 # MIT diff --git a/os-client-config/tools/keystone_version.py b/tools/keystone_version.py similarity index 100% rename from os-client-config/tools/keystone_version.py rename to tools/keystone_version.py diff --git a/os-client-config/tools/nova_version.py b/tools/nova_version.py similarity index 100% rename from os-client-config/tools/nova_version.py rename to tools/nova_version.py diff --git a/os-client-config/tools/tox_install.sh b/tools/tox_install.sh similarity index 100% rename from os-client-config/tools/tox_install.sh rename to tools/tox_install.sh diff --git a/tox.ini b/tox.ini index b6ab412d3..7661e9f33 100644 --- a/tox.ini +++ b/tox.ini @@ -5,29 +5,29 @@ skipsdist = True [testenv] usedevelop = True -install_command = pip install -U {opts} {packages} +basepython = {env:OPENSTACKSDK_TOX_PYTHON:python2} +passenv = UPPER_CONSTRAINTS_FILE +install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} setenv = - VIRTUAL_ENV={envdir} + VIRTUAL_ENV={envdir} + LANG=en_US.UTF-8 + LANGUAGE=en_US:en + LC_ALL=C + BRANCH_NAME=master + CLIENT_NAME=openstacksdk deps = -r{toxinidir}/test-requirements.txt -commands = ostestr {posargs} +commands = stestr run posargs} + stestr slowest [testenv:examples] -setenv = OS_TEST_PATH=./openstack/tests/examples -passenv = OS_* - -[functionalbase] -setenv = OS_TEST_PATH=./openstack/tests/functional -passenv = OS_* +passenv = OS_* OPENSTACKSDK_* UPPER_CONSTRAINTS_FILE +commands = stestr --test-path ./openstack/tests/examples run {posargs} + stestr slowest [testenv:functional] -basepython = python2.7 -setenv = {[functionalbase]setenv} -passenv = {[functionalbase]passenv} - -[testenv:functional3] -basepython = python3.4 -setenv = {[functionalbase]setenv} -passenv = {[functionalbase]passenv} +passenv = OS_* OPENSTACKSDK_* UPPER_CONSTRAINTS_FILE +commands = stestr --test-path ./openstack/tests/functional run --serial {posargs} + stestr slowest [testenv:pep8] commands = flake8 @@ -35,14 +35,35 @@ commands = flake8 [testenv:venv] commands = {posargs} -; If this fails for you, you may be running an old version of tox. -; Run 'pip install tox' to install a newer version of tox. +[testenv:debug] +whitelist_externals = find +commands = + find . -type f -name "*.pyc" -delete + oslo_debug_helper {posargs} + [testenv:cover] -commands = python setup.py test --coverage --coverage-package-name=openstack --testr-args='{posargs}' +setenv = + {[testenv]setenv} + PYTHON=coverage run --source shade --parallel-mode +commands = + stestr run {posargs} + coverage combine + coverage html -d cover + coverage xml -o cover/coverage.xml + +[testenv:ansible] +# Need to pass some env vars for the Ansible playbooks +passenv = HOME USER +commands = {toxinidir}/extras/run-ansible-tests.sh -e {envdir} {posargs} [testenv:docs] +skip_install = True +deps = -r{toxinidir}/test-requirements.txt commands = python setup.py build_sphinx +[testenv:releasenotes] +commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html + [flake8] # The following are ignored on purpose. It's not super worth it to fix them. # However, if you feel strongly about it, patches will be accepted to fix them