Skip to content
This repository was archived by the owner on Feb 5, 2024. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 72 additions & 83 deletions fastly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,41 @@
# Author: Chris Zacharias (chris@imgix.com)
# Copyright (c) 2012, Zebrafish Labs Inc.
# All rights reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

from datetime import datetime
import httplib2
import urllib
import re
import json
from datetime import datetime
import re
import urllib

FASTLY_SCHEME = "https"
FASTLY_HOST = "api.fastly.com"

FASTLY_SESSION_REGEX = re.compile("(fastly\.session=[^;]+);")


class FastlyRoles(object):
USER = "user"
BILLING = "billing"
Expand All @@ -51,52 +52,52 @@ class FastlyCacheSettingsAction(object):


class FastlyConditionType(object):
RESPONSE="response"
CACHE="cache"
REQUEST="request"
FETCH="fetch"
RESPONSE = "response"
CACHE = "cache"
REQUEST = "request"
FETCH = "fetch"


class FastlyHeaderAction(object):
SET="set"
APPEND="append"
DELETE="delete"
REGEX="regex"
REGEX_ALL="regex_repeat"
SET = "set"
APPEND = "append"
DELETE = "delete"
REGEX = "regex"
REGEX_ALL = "regex_repeat"


class FastlyHeaderType(object):
RESPONSE="response"
FETCH="fetch"
CACHE="cache"
REQUEST="request"
RESPONSE = "response"
FETCH = "fetch"
CACHE = "cache"
REQUEST = "request"


class FastlyRequestSettingAction(object):
LOOKUP="lookup"
PASS="pass"
LOOKUP = "lookup"
PASS = "pass"


class FastlyForwardedForAction(object):
CLEAR="clear"
LEAVE="leave"
APPEND="append"
APPEND_ALL="append_all"
OVERWRITE="overwrite"
CLEAR = "clear"
LEAVE = "leave"
APPEND = "append"
APPEND_ALL = "append_all"
OVERWRITE = "overwrite"


class FastlyStatsType(object):
ALL="all"
DAILY="daily"
HOURLY="hourly"
MINUTELY="minutely"
ALL = "all"
DAILY = "daily"
HOURLY = "hourly"
MINUTELY = "minutely"


class FastlyDirectorType(object):
RANDOM=1
ROUNDROBIN=2
HASH=3
CLIENT=4
RANDOM = 1
ROUNDROBIN = 2
HASH = 3
CLIENT = 4


class FastlyConnection(object):
Expand All @@ -109,7 +110,6 @@ def __init__(self, api_key):
def fully_authed(self):
return self._fully_authed


def login(self, user, password):
body = self._formdata({
"user": user,
Expand All @@ -119,18 +119,15 @@ def login(self, user, password):
self._fully_authed = True
return FastlySession(self, content)


def list_backends(self, service_id, version_number):
"""List all backends for a particular service and version."""

content = self._fetch("/service/%s/version/%d/backend" % (service_id, version_number))
return map(lambda x: FastlyBackend(self, x), content)


def create_backend(self,
def create_backend(self,
service_id,
version_number,
name,
version_number,
name,
address,
use_ssl=False,
port=80,
Expand Down Expand Up @@ -166,42 +163,36 @@ def create_backend(self,
content = self._fetch("/service/%s/version/%d/backend" % (service_id, version_number), method="POST", body=body)
return FastlyBackend(self, content)


def get_backend(self, service_id, version_number, name):
"""Get the backend for a particular service and version."""
content = self._fetch("/service/%s/version/%d/backend/%s" % (service_id, version_number, urllib.quote(name)))
return FastlyBackend(self, content)


def update_backend(self, service_id, version_number, name_key, **kwargs):
"""Update the backend for a particular service and version."""
body = self._formdata(kwargs, FastlyBackend.FIELDS)
content = self._fetch("/service/%s/version/%d/backend/%s" % (service_id, version_number, urllib.quote(name_key)), method="PUT", body=body)
return FastlyBackend(self, content)


def delete_backend(self, service_id, version_number, name):
"""Delete the backend for a particular service and version."""
content = self._fetch("/service/%s/version/%d/backend/%s" % (service_id, version_number, urllib.quote(name)), method="DELETE")
return self._status(content)


def check_backends(self, service_id, version_number):
"""Performs a health check against each backend in version. If the backend has a specific type of healthcheck, that one is performed, otherwise a HEAD request to / is performed. The first item is the details on the Backend itself. The second item is details of the specific HTTP request performed as a health check. The third item is the response details."""
content = self._fetch("/service/%s/version/%d/backend/check_all" % (service_id, version_number))
# TODO: Use a strong-typed class for output?
return content


def list_cache_settings(self, service_id, version_number):
"""Get a list of all cache settings for a particular service and version."""
content = self._fetch("/service/%s/version/%d/cache_settings" % (service_id, version_number))
return map(lambda x: FastlyCacheSettings(self, x), content)


def create_cache_settings(self,
service_id,
version_number,
def create_cache_settings(self,
service_id,
version_number,
name,
action,
ttl=None,
Expand All @@ -218,32 +209,27 @@ def create_cache_settings(self,
content = self._fetch("/service/%s/version/%d/cache_settings" % (service_id, version_number), method="POST", body=body)
return FastlyCacheSettings(self, content)


def get_cache_settings(self, service_id, version_number, name):
"""Get a specific cache settings object."""
content = self._fetch("/service/%s/version/%d/cache_settings/%s" % (service_id, version_number, urllib.quote(name)))
return FastlyCacheSettings(self, content)


def update_cache_settings(self, service_id, version_number, name_key, **kwargs):
"""Update a specific cache settings object."""
body = self._formdata(kwargs, FastlyCacheSettings.FIELDS)
content = self._fetch("/service/%s/version/%d/cache_settings/%s" % (service_id, version_number, urllib.quote(name_key)), method="PUT", body=body)
return FastlyCacheSettings(self, content)


def delete_cache_settings(self, service_id, version_number, name):
"""Delete a specific cache settings object."""
content = self._fetch("/service/%s/version/%d/cache_settings/%s" % (service_id, version_number, urllib.quote(name)), method="DELETE")
return self._status(content)


def list_conditions(self, service_id, version_number):
"""Gets all conditions for a particular service and version."""
content = self._fetch("/service/%s/version/%d/condition" % (service_id, version_number))
return map(lambda x: FastlyCondition(self, x), content)


def create_condition(self,
service_id,
version_number,
Expand All @@ -263,20 +249,17 @@ def create_condition(self,
content = self._fetch("/service/%s/version/%d/condition" % (service_id, version_number), method="POST", body=body)
return FastlyCondition(self, content)


def get_condition(self, service_id, version_number, name):
"""Gets a specified condition."""
content = self._fetch("/service/%s/version/%d/condition/%s" % (service_id, version_number, urllib.quote(name)))
return FastlyCondition(self, content)


def update_condition(self, service_id, version_number, name_key, **kwargs):
"""Updates the specified condition."""
body = self._formdata(kwargs, FastlyCondition.FIELDS)
content = self._fetch("/service/%s/version/%d/condition/%s" % (service_id, version_number, urllib.quote(name_key)), method="PUT", body=body)
return FastlyCondition(self, content)


def delete_condition(self, service_id, version_number, name):
"""Deletes the specified condition."""
content = self._fetch("/service/%s/version/%d/condition/%s" % (service_id, version_number, urllib.quote(name)), method="DELETE")
Expand Down Expand Up @@ -1498,19 +1481,25 @@ class FastlySettings(FastlyObject, IServiceVersionObject):
class FastlySyslog(FastlyObject, IServiceVersionObject, IDateStampedObject):
"""Fastly will stream log messages to the location, and in the format, specified in the Syslog object."""
FIELDS = [
"name",
"service_id",
"version",
"address",
"created_at",
"deleted_at",
"format",
"format_version",
"hostname",
"ipv4",
"message_type",
"name",
"placement",
"port",
"use_tls",
"response_condition",
"service_id",
"tls_ca_cert",
"tls_hostname",
"token",
"format",
"response_condition",
"created",
"updated",
"deleted",
"updated_at",
"use_tls",
"version",
]


Expand Down Expand Up @@ -1573,31 +1562,31 @@ def settings(self):

@property
def backends(self):
return dict([ (b.name, b) for b in self._conn.list_backends(self.service_id, int(self.number))])
return dict([(b.name, b) for b in self._conn.list_backends(self.service_id, int(self.number))])

@property
def healthchecks(self):
return dict([ (h.name, h) for h in self._conn.list_healthchecks(self.service_id, int(self.number))])
return dict([(h.name, h) for h in self._conn.list_healthchecks(self.service_id, int(self.number))])

@property
def domains(self):
return dict([ (d.name, d) for d in self._conn.list_domains(self.service_id, int(self.number))])
return dict([(d.name, d) for d in self._conn.list_domains(self.service_id, int(self.number))])

@property
def directors(self):
return dict([ (d.name, d) for d in self._conn.list_directors(self.service_id, int(self.number))])
return dict([(d.name, d) for d in self._conn.list_directors(self.service_id, int(self.number))])

@property
def origins(self):
return dict([ (o.name, o) for o in self._conn.list_origins(self.service_id, int(self.number))])
return dict([(o.name, o) for o in self._conn.list_origins(self.service_id, int(self.number))])

@property
def syslogs(self):
return dict([ (s.name, s) for s in self._conn.list_syslogs(self.service_id, int(self.number))])
return dict([(s.name, s) for s in self._conn.list_syslogs(self.service_id, int(self.number))])

@property
def vcls(self):
return dict([ (v.name, v) for v in self._conn.list_vcls(self.service_id, int(self.number))])
return dict([(v.name, v) for v in self._conn.list_vcls(self.service_id, int(self.number))])


class FastlyWordpress(FastlyObject, IServiceVersionObject):
Expand Down