def test_service_does_exist_and_configuration_is_equal(self): new_configuration = self.configuration_fixture.copy() old_configuration = FastlyConfiguration(self.configuration_fixture) new_configuration = FastlyConfiguration(new_configuration) old_service = self.enforcer.apply_configuration( self.FASTLY_TEST_SERVICE, old_configuration).service new_service = self.enforcer.apply_configuration( self.FASTLY_TEST_SERVICE, new_configuration).service self.assertEqual(old_service.active_version.number, new_service.active_version.number)
def test_fastly_director_with_one_backend(self): director_configuration = self.minimal_configuration.copy() director_configuration.update({ 'directors': [{ 'name': 'client_director', 'type': '4', 'backends': ['localhost'], }] }) configuration = FastlyConfiguration(director_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual( service.active_version.configuration.directors[0].name, 'client_director') self.assertEqual( service.active_version.configuration.directors[0].type, 4) self.assertEqual( service.active_version.configuration.directors[0].backends[0], 'localhost') self.assertEqual(service.active_version.configuration, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_vcl_snippets_deliver_stale_content(self): content = ''' if (resp.status >= 500 && resp.status < 600) { if (stale.exists) { restart; } } ''' vcl_snippets_configuration = self.minimal_configuration.copy() vcl_snippets_configuration.update({ 'snippets': [{ 'name': self.VCL_SNIPPETS_NAME, 'dynamic': 0, 'type': 'deliver', 'content': content, }] }) configuration = FastlyConfiguration(vcl_snippets_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.configuration.snippets[0].name, self.VCL_SNIPPETS_NAME) self.assertEqual(service.active_version.configuration.snippets[0].dynamic, 0) self.assertEqual(service.active_version.configuration.snippets[0].type, 'deliver') self.assertEqual(service.active_version.configuration.snippets[0].content, content) self.assertEqual(service.active_version.configuration, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_response_object_content_content_type(self): healthcheck_configuration = self.minimal_configuration.copy() healthcheck_configuration.update({ 'response_objects': [{ 'name': 'Set 200 status code', 'status': 200, 'response': 'Ok', 'content': 'Hello from Fastly', 'content_type': 'text/plain', }] }) configuration = FastlyConfiguration(healthcheck_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.configuration.response_objects[0].name, 'Set 200 status code') self.assertEqual(service.active_version.configuration.response_objects[0].status, '200') self.assertEqual(service.active_version.configuration.response_objects[0].response, 'Ok') self.assertEqual(service.active_version.configuration.response_objects[0].content, 'Hello from Fastly') self.assertEqual(service.active_version.configuration.response_objects[0].content_type, 'text/plain') self.assertEqual(service.active_version.configuration, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_cache_condition(self): condition_configuration = self.minimal_configuration.copy() condition_configuration.update({ 'headers': [{ 'name': 'Set cache control header', 'dst': 'http.Cache-Control', 'type': 'cache', 'src': '"public, max-age=86400"', 'cache_condition': self.CONDITION_NAME }], 'conditions': [{ 'name': self.CONDITION_NAME, 'priority': 0, 'statement': 'req.url ~ "^/some_asset.js"', 'type': 'CACHE' }] }) configuration = FastlyConfiguration(condition_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual( service.active_version.configuration.conditions[0].name, self.CONDITION_NAME) self.assertEqual(service.active_version.configuration, configuration)
def test_fastly_response_object_defaults(self): response_object_configuration = self.minimal_configuration.copy() response_object_configuration.update( {'response_objects': [{ 'name': 'Set 200 status code', }]}) configuration = FastlyConfiguration(response_object_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual( service.active_version.configuration.response_objects[0].name, 'Set 200 status code') self.assertEqual( service.active_version.configuration.response_objects[0].status, '200') self.assertEqual( service.active_version.configuration.response_objects[0].response, 'Ok') self.assertEqual(service.active_version.configuration, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_header_priority_not_required(self): configuration = FastlyConfiguration({ 'domains': [{ 'name': self.FASTLY_TEST_DOMAIN, }], 'backends': [{ 'name': 'localhost', 'address': '127.0.0.1' }], 'headers': [{ 'name': 'Set Location header', 'dst': 'http.Location', 'type': 'response', 'action': 'set', 'src': '"https://u.jimcdn.com" req.url.path', 'ignore_if_set': False }], 'response_objects': [{ 'name': 'Set 302 status code', 'status': 302 }] }) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.configuration, configuration)
def test_service_does_not_exist(self): self.client.delete_service(self.FASTLY_TEST_SERVICE) test_configuration = FastlyConfiguration(self.configuration_fixture) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, test_configuration).service self.assertTrue(service.active_version.active) self.assertEqual(service.active_version.configuration.response_objects, test_configuration.response_objects)
def test_service_does_not_exist_and_activate_new_version_is_disabled(self): self.client.delete_service(self.FASTLY_TEST_SERVICE) test_configuration = FastlyConfiguration(self.configuration_fixture) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, test_configuration, False).service self.assertFalse(service.latest_version.active) self.assertEqual(service.latest_version.configuration.response_objects, test_configuration.response_objects)
def test_fastly_s3s_remove(self): s3s_configuration = self.minimal_configuration.copy() s3s_configuration.update({ 's3': [{ 'name': 'test_s3', }], }) configuration = FastlyConfiguration(s3s_configuration) # Configure S3 logging self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service # Now apply a configuration without S3 logging service = self.enforcer.apply_configuration( self.FASTLY_TEST_SERVICE, FastlyConfiguration(self.minimal_configuration.copy())).service svc_conf = service.active_version.configuration self.assertEqual(svc_conf.s3s, [])
def test_fastly_logging_syslog_remove(self): logging_configuration = self.minimal_configuration.copy() logging_configuration.update({ 'syslogs': [{ 'name': 'test_syslog', 'address': 'syslog.example.com', 'port': 514, }], }) configuration = FastlyConfiguration(logging_configuration) # Configure with logging self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service # Now apply a configuration without logging service = self.enforcer.apply_configuration( self.FASTLY_TEST_SERVICE, FastlyConfiguration(self.minimal_configuration.copy())).service svc_conf = service.active_version.configuration self.assertEqual(svc_conf.syslogs, [])
def test_service_does_exist_and_activate_new_version_is_disabled(self): new_configuration = self.configuration_fixture.copy() new_configuration.update({ 'response_objects': [{ 'name': 'Set 301 status code', 'status': 301 }] }) old_configuration = FastlyConfiguration(self.configuration_fixture) new_configuration = FastlyConfiguration(new_configuration) old_service = self.enforcer.apply_configuration( self.FASTLY_TEST_SERVICE, old_configuration, True).service new_service = self.enforcer.apply_configuration( self.FASTLY_TEST_SERVICE, new_configuration, False).service self.assertNotEqual(old_service.latest_version.number, new_service.latest_version.number) self.assertNotEqual( old_service.latest_version.configuration.response_objects, new_service.latest_version.configuration.response_objects) self.assertFalse(new_service.latest_version.active)
def test_fastly_backend_empty_ssl_ca_cert(self): configuration = FastlyConfiguration({ 'domains': [{ 'name': self.FASTLY_TEST_DOMAIN, }], 'backends': [{ 'name': 'my-backend.example.net', 'port': 443, 'address': 'my-backend.example.net', 'ssl_hostname': 'my-backend.example.net', 'ssl_ca_cert': '' }] }) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.configuration, configuration)
def test_fastly_gzip(self): gzip_configuration = self.minimal_configuration.copy() gzip_configuration.update({ 'gzips': [{ 'name': self.GZIP_NAME, 'content_types': 'text/html text/css application/javascript', 'extensions': 'html css js' }] }) configuration = FastlyConfiguration(gzip_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.configuration.gzips[0].name, self.GZIP_NAME) self.assertEqual(service.active_version.configuration, configuration)
def test_fastly_backend_weight_even(self): configuration = FastlyConfiguration({ 'domains': [{ 'name': self.FASTLY_TEST_DOMAIN, }], 'backends': [{ 'name': 'my-backend1.example.net', 'address': 'my-backend1.example.net', 'weight': 50 }, { 'name': 'my-backend2.example.net', 'address': 'my-backend2.example.net', 'weight': 50 }] }) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.configuration, configuration)
def test_fastly_request_condition(self): condition_configuration = self.minimal_configuration.copy() condition_configuration.update({ 'conditions': [{ 'name': self.CONDITION_NAME, 'priority': 0, 'statement': 'req.url ~ "^/robots.txt"', 'type': 'REQUEST' }] }) configuration = FastlyConfiguration(condition_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual( service.active_version.configuration.conditions[0].name, self.CONDITION_NAME) self.assertEqual(service.active_version.configuration, configuration)
def test_fastly_settings(self): settings_configuration = self.minimal_configuration.copy() settings_configuration.update( {'settings': { 'general.default_ttl': 1000 }}) settings_configuration = FastlyConfiguration(settings_configuration) service = self.enforcer.apply_configuration( self.FASTLY_TEST_SERVICE, settings_configuration).service self.assertEqual( service.active_version.configuration.settings.general_default_ttl, 1000) self.assertEqual(service.active_version.configuration, settings_configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration( self.FASTLY_TEST_SERVICE, settings_configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_header_type_required(self): with self.assertRaises(FastlyValidationError): FastlyConfiguration({ 'domains': [{ 'name': self.FASTLY_TEST_DOMAIN, }], 'backends': [{ 'name': 'localhost', 'address': '127.0.0.1' }], 'headers': [{ 'name': 'Set Location header', 'dst': 'http.Location', 'action': 'set', 'src': '"https://u.jimcdn.com" req.url.path', }], 'response_objects': [{ 'name': 'Set 302 status code', 'status': 302 }] })
def test_fastly_s3s(self): s3s_configuration = self.minimal_configuration.copy() s3s_configuration.update({ 's3s': [{ 'name': 'test_s3', 'domain': self.FASTLY_TEST_DOMAIN, 'secret_key': 'SECRET', 'period': 60, 'bucket_name': 'prod-fastly-logs', 'timestamp_format': '%Y-%m-%dT%H:%M:%S.000', 'redundancy': 'standard', 'access_key': 'ACCESS_KEY', 'format': '%{%Y-%m-%dT%H:%S.000}t %h "%r" %>s %b', }], }) configuration = FastlyConfiguration(s3s_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service svc_conf = service.active_version.configuration self.assertEqual(svc_conf.s3s[0].name, 'test_s3') self.assertEqual(svc_conf.s3s[0].domain, self.FASTLY_TEST_DOMAIN) self.assertEqual(svc_conf.s3s[0].secret_key, 'SECRET') self.assertEqual(svc_conf.s3s[0].period, 60) self.assertEqual(svc_conf.s3s[0].bucket_name, 'prod-fastly-logs') self.assertEqual(svc_conf.s3s[0].timestamp_format, '%Y-%m-%dT%H:%M:%S.000') self.assertEqual(svc_conf.s3s[0].redundancy, 'standard') self.assertEqual(svc_conf.s3s[0].access_key, 'ACCESS_KEY') self.assertEqual(svc_conf.s3s[0].format, '%{%Y-%m-%dT%H:%S.000}t %h "%r" %>s %b') self.assertEqual(svc_conf, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_cache_settings_with_action(self): cache_settings_configuration = self.minimal_configuration.copy() cache_settings_configuration.update({ 'cache_settings': [{ 'name': self.CACHE_SETTINGS_NAME, 'action': 'pass', 'stale_ttl': 10 }] }) configuration = FastlyConfiguration(cache_settings_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual( service.active_version.configuration.cache_settings[0].action, 'pass') self.assertEqual(service.active_version.configuration, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_request_setting_defaults(self): request_setting_configuration = self.minimal_configuration.copy() request_setting_configuration.update({ 'request_settings': [{ 'name': self.REQUEST_SETTING_NAME, 'action': 'pass', 'xff': 'append', 'hash_keys': 'req.url,req.http.host,req.http.Fastly-SSL', 'max_stale_age': 30, 'force_miss': 1, 'force_ssl': 1, 'timer_support': 1, 'geo_headers': 1, 'bypass_busy_wait': 1, 'default_host': 'example.net', }] }) configuration = FastlyConfiguration(request_setting_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.configuration.request_settings[0].name, self.REQUEST_SETTING_NAME) self.assertEqual(service.active_version.configuration.request_settings[0].action, 'pass') self.assertEqual(service.active_version.configuration.request_settings[0].xff, 'append') self.assertEqual(service.active_version.configuration.request_settings[0].hash_keys, 'req.url,req.http.host,req.http.Fastly-SSL') self.assertEqual(service.active_version.configuration.request_settings[0].max_stale_age, 30) self.assertEqual(service.active_version.configuration.request_settings[0].force_miss, 1) self.assertEqual(service.active_version.configuration.request_settings[0].force_ssl, 1) self.assertEqual(service.active_version.configuration.request_settings[0].timer_support, 1) self.assertEqual(service.active_version.configuration.request_settings[0].geo_headers, 1) self.assertEqual(service.active_version.configuration.request_settings[0].bypass_busy_wait, 1) self.assertEqual(service.active_version.configuration.request_settings[0].default_host, 'example.net') self.assertEqual(service.active_version.configuration, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_logging_syslog(self): logging_configuration = self.minimal_configuration.copy() logging_configuration.update({ 'syslogs': [{ 'name': 'test_syslog', 'address': 'syslog.example.com', 'port': 514, 'use_tls': 0, 'token': '[abc 123]', 'format': '%h %l %u %t "%r" %>s %b', }], }) configuration = FastlyConfiguration(logging_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service svc_conf = service.active_version.configuration self.assertEqual(svc_conf.syslogs[0].hostname, 'syslog.example.com'), self.assertEqual(svc_conf.syslogs[0].response_condition, None), self.assertEqual(svc_conf.syslogs[0].address, 'syslog.example.com'), self.assertEqual(svc_conf.syslogs[0].message_type, 'classic'), self.assertEqual(svc_conf.syslogs[0].name, 'test_syslog'), self.assertEqual(svc_conf.syslogs[0].port, 514), self.assertEqual(svc_conf.syslogs[0].use_tls, 0), self.assertEqual(svc_conf.syslogs[0].token, '[abc 123]'), self.assertEqual(svc_conf.syslogs[0].format, '%h %l %u %t "%r" %>s %b'), self.assertEqual(svc_conf, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_healthchecks(self): healthcheck_configuration = self.minimal_configuration.copy() healthcheck_configuration.update({ 'healthchecks': [{ 'name': 'test_healthcheck', 'host': self.FASTLY_TEST_DOMAIN, 'method': 'GET', 'path': '/healthcheck', 'expected_response': 200, # Fastly Medium setup: 'threshold': 3, 'window': 5, 'initial': 4, 'check_interval': 15000, 'timeout': 5000, }], 'backends': [{ 'name': 'localhost', 'address': '127.0.0.1', 'healthcheck': 'test_healthcheck' }], }) configuration = FastlyConfiguration(healthcheck_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual( service.active_version.configuration.healthchecks[0].name, 'test_healthcheck') self.assertEqual( service.active_version.configuration.healthchecks[0].host, self.FASTLY_TEST_DOMAIN) self.assertEqual( service.active_version.configuration.healthchecks[0].method, 'GET') self.assertEqual( service.active_version.configuration.healthchecks[0].path, '/healthcheck') self.assertEqual( service.active_version.configuration.healthchecks[0]. expected_response, 200) self.assertEqual( service.active_version.configuration.healthchecks[0].threshold, 3) self.assertEqual( service.active_version.configuration.healthchecks[0].window, 5) self.assertEqual( service.active_version.configuration.healthchecks[0].initial, 4) self.assertEqual( service.active_version.configuration.healthchecks[0]. check_interval, 15000) self.assertEqual( service.active_version.configuration.healthchecks[0].timeout, 5000) self.assertEqual( service.active_version.configuration.backends[0].healthcheck, 'test_healthcheck') self.assertEqual(service.active_version.configuration, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_configuration_normalization(self): configuration = FastlyConfiguration(self.configuration_fixture) self.assertEqual(configuration.response_objects[0].status, '302') self.assertNotEqual(configuration.response_objects[0].status, 302)
def test_fastly_vcl_main(self): content = ''' sub vcl_recv { #FASTLY recv if (req.method != "HEAD" && req.method != "GET" && req.method != "FASTLYPURGE") { return(pass); } return(lookup); } sub vcl_fetch { #FASTLY fetch if ((beresp.status == 500 || beresp.status == 503) && req.restarts < 1 && (req.method == "GET" || req.method == "HEAD")) { restart; } if (req.restarts > 0) { set beresp.http.Fastly-Restarts = req.restarts; } if (beresp.http.Set-Cookie) { set req.http.Fastly-Cachetype = "SETCOOKIE"; return(pass); } if (beresp.http.Cache-Control ~ "private") { set req.http.Fastly-Cachetype = "PRIVATE"; return(pass); } if (beresp.status == 500 || beresp.status == 503) { set req.http.Fastly-Cachetype = "ERROR"; set beresp.ttl = 1s; set beresp.grace = 5s; return(deliver); } if (beresp.http.Expires || beresp.http.Surrogate-Control ~ "max-age" || beresp.http.Cache-Control ~ "(s-maxage|max-age)") { # keep the ttl here } else { # apply the default ttl set beresp.ttl = 3600s; } return(deliver); } sub vcl_hit { #FASTLY hit if (!obj.cacheable) { return(pass); } return(deliver); } sub vcl_miss { #FASTLY miss return(fetch); } sub vcl_deliver { #FASTLY deliver return(deliver); } sub vcl_error { #FASTLY error } sub vcl_pass { #FASTLY pass } sub vcl_log { #FASTLY log } ''' vcls_configuration = self.minimal_configuration.copy() vcls_configuration.update({ 'snippets': [{ 'name': self.VCLS_NAME, 'dynamic': 0, 'type': 'deliver', 'content': content, }] }) configuration = FastlyConfiguration(vcls_configuration) service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.configuration.vcls[0].name, self.VCLS_NAME) self.assertEqual(service.active_version.configuration.vcls[0].dynamic, 0) self.assertEqual(service.active_version.configuration.vcls[0].type, 'deliver') self.assertEqual(service.active_version.configuration.vcls[0].content, content) self.assertEqual(service.active_version.configuration, configuration) active_version_number = service.active_version.number service = self.enforcer.apply_configuration(self.FASTLY_TEST_SERVICE, configuration).service self.assertEqual(service.active_version.number, active_version_number)
def test_fastly_configuration_validation(self): new_configuration = self.configuration_fixture.copy() new_configuration.update({'response_objects': [{'status': 302}]}) with self.assertRaises(FastlyValidationError): FastlyConfiguration(new_configuration)