Skip to content

Commit

Permalink
Add support of Healthcheck's (#29)
Browse files Browse the repository at this point in the history
* Add support of Fastly healthchecks

* Update README

* Make flake8 happy

* Make healthcheck.expected_status default value - int
  • Loading branch information
cono authored and fstehle committed Sep 7, 2017
1 parent af27513 commit dcb7e79
Show file tree
Hide file tree
Showing 5 changed files with 306 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea/
*.pyc
.*.sw?
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ $ ansible-galaxy install Jimdo.fastly
| directors | false | List of directors | |
| gzips | false | List of gzip configurations | |
| headers | false | List of headers to manipulate for each request | |
| healthchecks | false | List of healthchecks for the backend purpose | |
| response_objects | false | List of response objects | |
| settings | false | Settings object | |
| vcl_snippets | false | List of VCL snippets | |
Expand All @@ -43,6 +44,7 @@ $ ansible-galaxy install Jimdo.fastly
| ssl_ca_cert | false | string | |
| ssl_cert_hostname | false | string | |
| shield | false | string | |
| healthcheck | false | string | |

### Cache Settings

Expand Down Expand Up @@ -101,6 +103,25 @@ $ ansible-galaxy install Jimdo.fastly
| substitution | false | string | |
| type | true | enum ('request', 'fetch', 'cache', 'response') | |

### Healthcheck

[Fastly documentation](https://docs.fastly.com/api/config#healthcheck)

| Field | Required | Type | Default |
|:-------------------|:---------|:----------------------------------------------------------|:--------|
| name | true | string | |
| check_interval | false | integer | |
| comment | false | string | '' |
| expected_response | false | integer | 200 |
| host | true | string | |
| http_version | false | string | 1.1 |
| initial | false | integer | |
| method | false | string | HEAD |
| path | false | string | '/' |
| threshold | false | integer | |
| timeout | false | integer | |
| window | false | integer | |

### Response Object

[Fastly documentation](https://docs.fastly.com/api/config#response_object)
Expand Down Expand Up @@ -179,6 +200,6 @@ FASTLY_API_KEY=some_secret python -m unittest discover tests
```

#### Updating the VCR cassettes
[VCR.py](https://vcrpy.readthedocs.io/en/latest/) is used in the tests for mocking HTTP requests.
[VCR.py](https://vcrpy.readthedocs.io/en/latest/) is used in the tests for mocking HTTP requests.

In order to update the cassettes just delete the `tests/fixtures/cassettes` directory and run the tests as usual. You have to use a valid Fastly API key for the recording to work.
66 changes: 63 additions & 3 deletions library/fastly_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
required: false
description:
- List of headers to manipulate for each request
healthchecks:
required: false
description:
- List of healthchecks to manipulate for each request
response_objects:
required: false
description:
Expand Down Expand Up @@ -239,7 +243,8 @@ class FastlyBackend(FastlyObject):
'ssl_hostname': dict(required=False, type='str', default=None),
'ssl_ca_cert': dict(required=False, type='str', default=None, exclude_empty_str=True),
'ssl_cert_hostname': dict(required=False, type='str', default=None, exclude_empty_str=True),
'shield': dict(required=False, type='str', default=None, exclude_empty_str=True)
'shield': dict(required=False, type='str', default=None, exclude_empty_str=True),
'healthcheck': dict(required=False, type='str', default=None, exclude_empty_str=True),
}

def __init__(self, config, validate_choices):
Expand All @@ -251,6 +256,7 @@ def __init__(self, config, validate_choices):
self.ssl_ca_cert = self.read_config(config, validate_choices, 'ssl_ca_cert')
self.ssl_cert_hostname = self.read_config(config, validate_choices, 'ssl_cert_hostname')
self.shield = self.read_config(config, validate_choices, 'shield')
self.healthcheck = self.read_config(config, validate_choices, 'healthcheck')

def sort_key(f):
return f.name
Expand Down Expand Up @@ -375,6 +381,40 @@ def sort_key(f):
return f.name


class FastlyHealthcheck(FastlyObject):
schema = {
'name': dict(required=True, type='str', default=None),
'check_interval': dict(required=False, type='int', default=None),
'comment': dict(required=False, type='str', default=''),
'expected_response': dict(required=False, type='int', default=200),
'host': dict(required=True, type='str', default=None),
'http_version': dict(required=False, type='str', default='1.1'),
'initial': dict(required=False, type='int', default=None),
'method': dict(required=False, type='str', default='HEAD'),
'path': dict(required=False, type='str', default='/'),
'threshold': dict(required=False, type='int', default=None),
'timeout': dict(required=False, type='int', default=None),
'window': dict(required=False, type='int', default=None),
}

def __init__(self, config, validate_choices):
self.name = self.read_config(config, validate_choices, 'name')
self.check_interval = self.read_config(config, validate_choices, 'check_interval')
self.comment = self.read_config(config, validate_choices, 'comment')
self.expected_response = self.read_config(config, validate_choices, 'expected_response')
self.host = self.read_config(config, validate_choices, 'host')
self.http_version = self.read_config(config, validate_choices, 'http_version')
self.initial = self.read_config(config, validate_choices, 'initial')
self.method = self.read_config(config, validate_choices, 'method')
self.path = self.read_config(config, validate_choices, 'path')
self.threshold = self.read_config(config, validate_choices, 'threshold')
self.timeout = self.read_config(config, validate_choices, 'timeout')
self.window = self.read_config(config, validate_choices, 'window')

def sort_key(f):
return f.name


class FastlyResponseObject(FastlyObject):
schema = {
'name': dict(required=True, type='str', default=None),
Expand Down Expand Up @@ -430,6 +470,7 @@ def to_json(self):
class FastlyConfiguration(object):
def __init__(self, configuration, validate_choices=True):
self.domains = []
self.healthchecks = []
self.backends = []
self.cache_settings = []
self.conditions = []
Expand All @@ -444,6 +485,10 @@ def __init__(self, configuration, validate_choices=True):
for domain in configuration['domains']:
self.domains.append(FastlyDomain(domain, validate_choices))

if 'healthchecks' in configuration and configuration['healthchecks'] is not None:
for healthcheck in configuration['healthchecks']:
self.healthchecks.append(FastlyHealthcheck(healthcheck, validate_choices))

if 'backends' in configuration and configuration['backends'] is not None:
for backend in configuration['backends']:
self.backends.append(FastlyBackend(backend, validate_choices))
Expand Down Expand Up @@ -481,6 +526,7 @@ def __init__(self, configuration, validate_choices=True):

def __eq__(self, other):
return sorted(self.domains, key=FastlyDomain.sort_key) == sorted(other.domains, key=FastlyDomain.sort_key) \
and sorted(self.healthchecks, key=FastlyHealthcheck.sort_key) == sorted(other.healthchecks, key=FastlyHealthcheck.sort_key) \
and sorted(self.backends, key=FastlyBackend.sort_key) == sorted(other.backends, key=FastlyBackend.sort_key) \
and sorted(self.cache_settings, key=FastlyCacheSettings.sort_key) == sorted(other.cache_settings, key=FastlyCacheSettings.sort_key) \
and sorted(self.conditions, key=FastlyCondition.sort_key) == sorted(other.conditions, key=FastlyCondition.sort_key) \
Expand Down Expand Up @@ -606,15 +652,23 @@ def create_domain(self, service_id, version, domain):
if response.status == 200:
return response.payload
else:
raise Exception("Error creating domain for for service %s, version %s (%s)" % (
raise Exception("Error creating domain for service %s, version %s (%s)" % (
service_id, version, response.payload['detail']))

def create_healthcheck(self, service_id, version, healthcheck):
response = self._request('/service/%s/version/%s/healthcheck' % (service_id, version), 'POST', healthcheck)
if response.status == 200:
return response.payload
else:
raise Exception("Error creating healthcheck for service %s, version %s (%s)" % (
service_id, version, response.payload['detail']))

def create_backend(self, service_id, version, backend):
response = self._request('/service/%s/version/%s/backend' % (service_id, version), 'POST', backend)
if response.status == 200:
return response.payload
else:
raise Exception("Error creating backend for for service %s, version %s (%s)" % (
raise Exception("Error creating backend for service %s, version %s (%s)" % (
service_id, version, response.payload['detail']))

def create_director(self, service_id, version, director):
Expand Down Expand Up @@ -735,6 +789,10 @@ def deploy_version_with_configuration(self, service_id, configuration, activate_
for domain in configuration.domains:
self.client.create_domain(service_id, version_number, domain)

# create healthchecks before backends
for healthcheck in configuration.healthchecks:
self.client.create_healthcheck(service_id, version_number, healthcheck)

# create conditions before dependencies (e.g. cache_settings)
for condition in configuration.conditions:
self.client.create_condition(service_id, version_number, condition)
Expand Down Expand Up @@ -791,6 +849,7 @@ def __init__(self):
fastly_api_key=dict(no_log=True, type='str'),
name=dict(required=True, type='str'),
activate_new_version=dict(required=False, type='bool', default=True),
healthchecks=dict(default=None, required=False, type='list'),
domains=dict(default=None, required=True, type='list'),
backends=dict(default=None, required=True, type='list'),
cache_settings=dict(default=None, required=False, type='list'),
Expand Down Expand Up @@ -818,6 +877,7 @@ def configuration(self):
try:
return FastlyConfiguration({
'domains': self.module.params['domains'],
'healthchecks': self.module.params['healthchecks'],
'backends': self.module.params['backends'],
'cache_settings': self.module.params['cache_settings'],
'conditions': self.module.params['conditions'],
Expand Down

0 comments on commit dcb7e79

Please sign in to comment.