Cleanup E2E tests

This patch,
1. consolidates the default origin to be a single config value for
   all tests.
2. removes heat client etc. which are no longer used in the tests.

Change-Id: I1a3249b2bb0198e694b112f7ddffd5ffa6274e59
This commit is contained in:
Malini Kamalambal 2015-08-17 15:50:22 -04:00
parent b9a9e94c26
commit 309b6019c7
10 changed files with 239 additions and 262 deletions

View File

@ -24,7 +24,6 @@ import requests
from tests.api.utils import client
from tests.endtoend.utils import config
from tests.endtoend.utils import dnsclient
from tests.endtoend.utils import heatclient
from tests.endtoend.utils import wptclient
@ -58,8 +57,9 @@ class TestBase(fixtures.BaseTestFixture):
cls.auth_config.api_key)
cls.test_config = config.TestConfig()
cls.default_origin = cls.test_config.default_origin
cls.poppy_config = config.PoppyConfig()
cls.purge_config = config.PurgeRulesConfig()
if cls.poppy_config.project_id_in_url:
cls.url = cls.poppy_config.base_url + '/v1.0/' + project_id
@ -77,11 +77,6 @@ class TestBase(fixtures.BaseTestFixture):
api_key=cls.auth_config.api_key,
test_domain=cls.dns_config.test_domain)
cls.heat_config = config.OrchestrationConfig()
heat_url = cls.heat_config.base_url + '/' + project_id
cls.heat_client = heatclient.HeatClient(heat_url=heat_url,
token=auth_token)
cls.wpt_config = config.WebPageTestConfig()
cls.wpt_client = wptclient.WebpageTestClient(
wpt_url=cls.wpt_config.base_url, api_key=cls.wpt_config.api_key)

View File

@ -25,10 +25,9 @@ class TestCaching(base.TestBase):
def setUpClass(cls):
super(TestCaching, cls).setUpClass()
cls.default_origin = cls.test_config.default_origin
cls.caching_config = config.CachingConfig()
cls.default_origin = cls.caching_config.origin
cls.cacheable_endpoint = cls.caching_config.endpoint
cls.jpg_path = cls.caching_config.jpg_endpoint
cls.txt_path = cls.caching_config.txt_endpoint
@ -178,6 +177,84 @@ class TestCaching(base.TestBase):
cdn_url=cdn_zip_url,
status_list=['TCP_REFRESH_HIT', 'TCP_REFRESH_MISS', 'TCP_MISS'])
def test_update_cache_rules(self):
# Create a Poppy Service for the test website
domain_list = [{"domain": self.test_domain}]
origin_list = [{
"origin": self.default_origin, "port": 80, "ssl": False}]
jpg_ttl = self.caching_config.jpg_ttl
caching_list = [{
"name": "images", "ttl": jpg_ttl,
"rules":
[{"name": "image_rule", "request_url": self.jpg_path}]}]
self.service_name = base.random_string(prefix='testService-')
resp = self.setup_service(
service_name=self.service_name,
domain_list=domain_list,
origin_list=origin_list,
caching_list=caching_list,
flavor_id=self.poppy_config.flavor)
self.service_location = resp.headers['location']
resp = self.poppy_client.get_service(location=self.service_location)
links = resp.json()['links']
access_url = [link['href'] for link in links if
link['rel'] == 'access_url']
# Adds cname records corresponding to the test domains
rec = self.setup_cname(name=self.test_domain, cname=access_url[0])
if rec:
self.cname_rec.append(rec[0])
origin_jpg = 'http://' + self.default_origin + self.jpg_path
cdn_url = 'http://' + self.test_domain
cdn_jpg_url = cdn_url + self.jpg_path
self.assertSameContent(
origin_url=origin_jpg, cdn_url=cdn_jpg_url)
# Verify that content is cached after two requests
self.get_from_cdn_enabled_url(cdn_url=cdn_jpg_url, count=2)
self.assertCacheStatus(cdn_url=cdn_jpg_url,
status_list=['TCP_HIT', 'TCP_MEM_HIT'])
# Verify that content in cache is stale/removed after the ttl expires
time.sleep(jpg_ttl + 10)
self.assertCacheStatus(
cdn_url=cdn_jpg_url,
status_list=['TCP_REFRESH_HIT', 'TCP_REFRESH_MISS', 'TCP_MISS'])
# Update cache rules
new_ttl = 50
test_data = [{
"op": "replace",
"path": "/caching/0",
"value": {
"name": "cache_name",
"ttl": new_ttl,
"rules": [{"name": "image_rule",
"request_url": self.jpg_path}]}
}]
resp = self.poppy_client.patch_service(location=self.service_location,
request_body=test_data)
# Verify that content is cached after two requests
self.get_from_cdn_enabled_url(cdn_url=cdn_jpg_url, count=2)
self.assertCacheStatus(cdn_url=cdn_jpg_url,
status_list=['TCP_HIT', 'TCP_MEM_HIT'])
time.sleep(new_ttl)
# Verify that content in cache is stale/removed after the ttl expires
self.assertCacheStatus(
cdn_url=cdn_jpg_url,
status_list=['TCP_REFRESH_HIT', 'TCP_REFRESH_MISS', 'TCP_MISS'])
def tearDown(self):
self.poppy_client.delete_service(location=self.service_location)
for record in self.cname_rec:

View File

@ -190,76 +190,6 @@ class TestWebsiteCDN(base.TestBase):
# self.wait_for_CDN_status(cdn_url=cdn_enabled_url, status='TCP_MISS')
# self.assertCDNMiss(cdn_url=cdn_enabled_url + rule2)
def test_update_cache_rules(self):
# Create a Poppy Service for the test website
domain_list = [{"domain": self.test_domain}]
origin_list = [{"origin": self.origin, "port": 80, "ssl": False}]
rule1 = self.cacherules_config.cache_rule1
ttlrule1 = self.cacherules_config.ttl_rule1
caching_list = [{"name": "images", "ttl": ttlrule1, "rules":
[{"name": "image_rule", "request_url": rule1}]}]
self.service_name = base.random_string(prefix='testService-')
resp = self.setup_service(
service_name=self.service_name,
domain_list=domain_list,
origin_list=origin_list,
caching_list=caching_list,
flavor_id=self.poppy_config.flavor)
self.service_location = resp.headers['location']
resp = self.poppy_client.get_service(location=self.service_location)
links = resp.json()['links']
access_url = [link['href'] for link in links if
link['rel'] == 'access_url']
# Adds cname records corresponding to the test domains
rec = self.setup_cname(name=self.test_domain, cname=access_url[0])
if rec:
self.cname_rec.append(rec[0])
origin_url = 'http://' + self.origin
cdn_enabled_url = 'http://' + self.test_domain
self.assertSameContent(origin_url=origin_url, cdn_url=cdn_enabled_url)
# Verify that content is cached after two requests
self.get_from_cdn_enabled_url(cdn_url=cdn_enabled_url + rule1, count=2)
self.assertCacheStatus(cdn_url=cdn_enabled_url + rule1,
status_list=['TCP_HIT', 'TCP_MEM_HIT'])
# Verify that content in cache is stale/removed after the ttl expires
time.sleep(ttlrule1 + 10)
self.assertCacheStatus(
cdn_url=cdn_enabled_url + rule1,
status_list=['TCP_REFRESH_HIT', 'TCP_REFRESH_MISS', 'TCP_MISS'])
# Update cache rules
new_ttl = 50
test_data = [{"op": "replace",
"path": "/caching/0",
"value": {"name": "cache_name",
"ttl": new_ttl,
"rules": [{"name": "image_rule",
"request_url": rule1}]}}]
resp = self.poppy_client.patch_service(location=self.service_location,
request_body=test_data)
# Verify that content is cached after two requests
self.get_from_cdn_enabled_url(cdn_url=cdn_enabled_url + rule1, count=2)
self.assertCacheStatus(cdn_url=cdn_enabled_url + rule1,
status_list=['TCP_HIT', 'TCP_MEM_HIT'])
time.sleep(new_ttl)
# Verify that content in cache is stale/removed after the ttl expires
self.assertCacheStatus(
cdn_url=cdn_enabled_url + rule1,
status_list=['TCP_REFRESH_HIT', 'TCP_REFRESH_MISS', 'TCP_MISS'])
def tearDown(self):
self.poppy_client.delete_service(location=self.service_location)
for record in self.cname_rec:

View File

@ -25,7 +25,6 @@ class TestHostHeaders(base.TestBase):
cls.host_header_config = config.HostHeaderConfig()
cls.default_origin = cls.host_header_config.origin
cls.test_endpoint = cls.host_header_config.endpoint
cls.check_preconditions()

View File

@ -24,7 +24,6 @@ class TestMultipleOrigin(base.TestBase):
super(TestMultipleOrigin, cls).setUpClass()
cls.multiorigin_config = config.MultipleOriginConfig()
cls.default_origin = cls.multiorigin_config.default_origin
cls.images_origin = cls.multiorigin_config.images_origin
cls.image_path = cls.multiorigin_config.image_path
@ -52,8 +51,9 @@ class TestMultipleOrigin(base.TestBase):
def setUp(self):
super(TestMultipleOrigin, self).setUp()
self.test_domain = "{0}.{1}".format(
base.random_string('TestMultiOrigin'), self.dns_config.test_domain)
self.service_name = base.random_string('MultiOriginService')
base.random_string('test-multi-origin-'),
self.dns_config.test_domain)
self.service_name = base.random_string('E2E-MultiOrigin')
self.cname_rec = []
def test_multiple_origin_default_first(self):
@ -76,12 +76,13 @@ class TestMultipleOrigin(base.TestBase):
}]
}]
self.setup_service(
resp = self.setup_service(
service_name=self.service_name,
domain_list=domains,
origin_list=origins,
caching_list=[],
flavor_id=self.poppy_config.flavor)
self.service_location = resp.headers['location']
resp = self.poppy_client.get_service(location=self.service_location)
links = resp.json()['links']

View File

@ -27,7 +27,6 @@ class TestOriginHeaders(base.TestBase):
cls.origin_header_config = config.OriginHeaderConfig()
cls.default_origin = cls.origin_header_config.default_origin
cls.expires_path = cls.origin_header_config.expires_path
cls.cache_control_path = \
cls.origin_header_config.cache_control_path

View File

@ -0,0 +1,117 @@
# Copyright (c) 2015 Rackspace, Inc.
#
# 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 time
from tests.endtoend import base
from tests.endtoend.utils import config
class TestPurge(base.TestBase):
@classmethod
def setUpClass(cls):
super(TestPurge, cls).setUpClass()
cls.default_origin = cls.test_config.default_origin
cls.purge_config = config.PurgeConfig()
cls.purge_path = cls.purge_config.purge_path
cls.check_preconditions()
@classmethod
def check_preconditions(cls):
"""Ensure our environment meets our needs to ensure a valid test."""
origin = cls.http_client.get(
"http://" + cls.default_origin + cls.purge_path)
assert origin.status_code == 200
def setUp(self):
super(TestPurge, self).setUp()
self.test_domain = "{0}.{1}".format(
base.random_string('test-purge'),
self.dns_config.test_domain)
self.service_name = base.random_string('E2E-PurgeService')
self.cname_rec = []
def test_purge(self):
# Create a Poppy Service for the test website
domain_list = [{"domain": self.test_domain}]
origin_list = [{"origin": self.default_origin,
"port": 80,
"ssl": False}]
ttl = self.purge_config.cache_ttl
caching_list = [{
"name": "test_purge", "ttl": ttl,
"rules": [{
"name": "test_purge_rule", "request_url": self.purge_path}
]}]
resp = self.setup_service(
service_name=self.service_name,
domain_list=domain_list,
origin_list=origin_list,
caching_list=caching_list,
flavor_id=self.poppy_config.flavor)
self.service_location = resp.headers['location']
resp = self.poppy_client.get_service(location=self.service_location)
links = resp.json()['links']
access_url = [link['href'] for link in links if
link['rel'] == 'access_url']
# Adds cname records corresponding to the test domains
rec = self.setup_cname(name=self.test_domain, cname=access_url[0])
if rec:
self.cname_rec.append(rec[0])
origin_url = 'http://' + self.default_origin
cdn_url = 'http://' + self.test_domain
self.assertSameContent(origin_url=origin_url, cdn_url=cdn_url)
cdn_jpg_url = cdn_url + self.purge_path
# Purge object in rule 1 and ensure it gets a TCP_MISS
self.get_from_cdn_enabled_url(cdn_url=cdn_jpg_url, count=2)
self.assertCacheStatus(
cdn_url=cdn_jpg_url, status_list=['TCP_HIT', 'TCP_MEM_HIT'])
self.poppy_client.purge_asset(location=self.service_location,
asset_url=self.purge_path)
# Wait for purge to complete & verify that content is fetched from
# origin for subsequent call.
# @todo: Change the sleep to check the real status of purge. As is
# there is no way a poppy user can get the purge status.
time.sleep(self.purge_config.purge_wait_time)
self.assertCacheStatus(
cdn_url=cdn_jpg_url,
status_list=['TCP_REFRESH_HIT', 'TCP_REFRESH_MISS', 'TCP_MISS'])
# Currently not supported
# Purge all content and ensure rule 2 gets a TCP_MISS
# self.poppy_client.purge_asset(location=self.service_location)
# self.wait_for_CDN_status(cdn_url=cdn_enabled_url, status='TCP_MISS')
# self.assertCDNMiss(cdn_url=cdn_enabled_url + rule2)
def tearDown(self):
self.poppy_client.delete_service(location=self.service_location)
for record in self.cname_rec:
print("deleting dns record: {0}".format(record))
self.dns_client.delete_record(record)
super(TestPurge, self).tearDown()

View File

@ -50,6 +50,11 @@ class TestConfig(data_interfaces.ConfigSectionInterface):
"""Defines the config values specific to test execution."""
SECTION_NAME = 'test_configuration'
@property
def default_origin(self):
"""Default origin for all tests."""
return self.get('default_origin')
@property
def wordpress_origin(self):
"""IP address for wordpress origin."""
@ -101,21 +106,6 @@ class AuthConfig(data_interfaces.ConfigSectionInterface):
return self.get_raw('api_key')
class OrchestrationConfig(data_interfaces.ConfigSectionInterface):
"""Defines the Rackspace orchestration config values."""
SECTION_NAME = 'orchestration'
@property
def base_url(self):
"""Orchestration base url."""
return self.get('base_url')
@property
def yaml_path(self):
"""path to the heat yaml file."""
return self.get('yaml_path')
class WebPageTestConfig(data_interfaces.ConfigSectionInterface):
"""Defines the webpage test config values."""
SECTION_NAME = 'webpagetest'
@ -185,11 +175,6 @@ class CachingConfig(data_interfaces.ConfigSectionInterface):
"""Defines the config values for caching tests."""
SECTION_NAME = 'caching'
@property
def origin(self):
"""Default Origin for Caching Tests."""
return self.get('default_origin')
@property
def endpoint(self):
"""Path to cacheable content."""
@ -230,10 +215,6 @@ class MultipleOriginConfig(data_interfaces.ConfigSectionInterface):
"""Configuration for testing multiple origins."""
SECTION_NAME = 'multiple_origin'
@property
def default_origin(self):
return self.get('default_origin')
@property
def images_origin(self):
return self.get('images_origin')
@ -248,18 +229,22 @@ class HostHeaderConfig(data_interfaces.ConfigSectionInterface):
"""Configuration for testing multiple origins."""
SECTION_NAME = 'host_header'
@property
def origin(self):
return self.get('origin')
@property
def endpoint(self):
return self.get('endpoint')
class PurgeRulesConfig(data_interfaces.ConfigSectionInterface):
"""Configuration for purge wait time."""
SECTION_NAME = 'purgetime'
class PurgeConfig(data_interfaces.ConfigSectionInterface):
"""Configuration for purge tests."""
SECTION_NAME = 'purge'
@property
def purge_path(self):
return self.get('purge_path')
@property
def cache_ttl(self):
return int(self.get('cache_ttl'))
@property
def purge_wait_time(self):
@ -270,11 +255,6 @@ class OriginHeaderConfig(data_interfaces.ConfigSectionInterface):
"""Defines the origin header config values."""
SECTION_NAME = 'origin_headers'
@property
def default_origin(self):
"""Default Origin."""
return self.get('default_origin')
@property
def expires_ttl(self):
"""TTL for expires header."""

View File

@ -1,116 +0,0 @@
# Copyright (c) 2014 Rackspace, Inc.
#
# 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 json
import time
import requests
class HeatClient(object):
def __init__(self, heat_url, token):
self.heat_url = heat_url
self.headers = {
'content-type': 'application/json',
'Accept': 'application/json',
'X-Auth-Token': token
}
def create_stack(self, yaml_path, stack_name, domain_name):
"""Creates a HEAT stack
:param yaml_path: path to the uaml file relative to endtoend directory
(eg. endtoend/heat_file.yaml)
:param stack_name: name of the heat stack containing the test site
:param domain_name: domain name to use for the deployed website
:returns: response to HEAT API call
"""
url = self.heat_url + '/stacks'
template_file = open(yaml_path, 'r+')
template = template_file.read()
template = template.replace('example.com', domain_name)
request_data = {
"stack_name": stack_name,
"disable_rollback": True,
"parameters": {},
"template": template,
"timeout_mins": 60
}
response = requests.post(url,
data=json.dumps(request_data),
headers=self.headers)
return response
def get_stack_details(self, stack_name):
"""Gets details of the stack
:param stack_name: name of the stack to be queried
:returns: response containing stack details
"""
url = self.heat_url + '/stacks/' + stack_name
response = requests.get(url, headers=self.headers)
return response
def wait_for_stack_status(self, stack_name, status='CREATE_COMPLETE',
retry_timeout=6000, retry_interval=10):
"""Wait for the stack to reach the specified status
:param stack_name: name of the stack to be queried
:param status: desired stack status
:param retry_interval: how frequently to ping for status change(sec)
:param retry_interval: max number of seconds to wait for status change
:returns: None
"""
current_status = ''
start_time = int(time.time())
stop_time = start_time + retry_timeout
while current_status != status:
time.sleep(retry_interval)
stack_details = self.get_stack_details(stack_name=stack_name)
body = stack_details.json()
current_status = body['stack']['stack_status']
if (current_status == status):
return
current_time = int(time.time())
if current_time > stop_time:
return
def get_server_ip(self, stack_name):
"""Get the cloud server ip for the stack_name
:param stack_name: name of the stack
:returns: ip of the server that is part of the stack
"""
stack_details = self.get_stack_details(stack_name)
stack_details = stack_details.json()
outputs = stack_details['stack']['outputs']
server_ip = [output['output_value'] for
output in outputs if
output['output_key'] == 'server_ip']
return server_ip[0]
def delete_stack(self, stack_name):
"""Delete specified stack
:param stack_name: name of the stack
:returns: DELETE response
"""
url = self.heat_url + '/stacks/' + stack_name
response = requests.delete(url, headers=self.headers)
return response

View File

@ -7,27 +7,6 @@ user_name={user name of the cloud account}
api_key={api key for this user name}
base_url=https://identity.api.rackspacecloud.com/v2.0
[test_configuration]
wordpress_origin=1.2.3.4
ssl_origin=1.2.3.4
run_ssl_tests=False
webpagetest_enabled=False
referree_origin=2.3.4.5
referrer_request_url=/static/images/gorilla.jpeg
[host_header]
origin=1.3.5.7
endpoint=/test/host_header
[multiple_origin]
default_origin=127.0.0.1
images_origin=127.0.0.2
image_path=/static/images/gorilla.jpeg
[orchestration]
base_url=https://iad.orchestration.api.rackspacecloud.com/v1/{project_id}/
yaml_path=endtoend/wordpress-single.yaml
[poppy]
base_url=http://0.0.0.0:8888
project_id_in_url=True
@ -57,8 +36,23 @@ api_key={api key for webpagetest instance}
# GET http://www.webpagetest.org/getLocations.php - Use <id> tag
test_locations=Wellington:Chrome, Indore:Firefox, Stockholm:Safari, Dulles:Firefox, Miami:Chrome
[test_configuration]
default_origin=127.0.0.1
wordpress_origin=1.2.3.4
ssl_origin=1.2.3.4
run_ssl_tests=False
webpagetest_enabled=False
referree_origin=2.3.4.5
referrer_request_url=/static/images/gorilla.jpeg
[host_header]
endpoint=/test/host_header
[multiple_origin]
images_origin=127.0.0.2
image_path=/static/images/gorilla.jpeg
[caching]
default_origin=1.2.3.4
cache_path=/test/expires/expires.jpg
jpg_path=/test/camera.jpg
jpg_ttl=10
@ -67,12 +61,13 @@ txt_ttl=10
zip_path=/test/line.zip
zip_ttl=10
[purgetime]
[purge]
# Time to wait for purging content to complete
purge_path=/test/camera.jpg
cache_ttl=10
purge_wait_time=900
[origin_headers]
default_origin=1.2.3.4
cache_control_path=/test/cache-control/cache-control.jpg
cache_control_ttl=10
expires_path=/test/expires/expires.jpg