diff --git a/README.md b/README.md
index 54227d5..d52a818 100644
--- a/README.md
+++ b/README.md
@@ -23,8 +23,8 @@ The ACME provider that most people are likely to use is [Let's Encrypt](https://
 
 ```
 > $ docker run --rm praekeltfoundation/marathon-acme:develop marathon-acme --help
-usage: marathon-acme [-h] [-a ACME] [-m MARATHON] [-l LB [LB ...]] [-g GROUP]
-                     [--listen LISTEN]
+usage: marathon-acme [-h] [-a ACME] [-m MARATHON [MARATHON ...]]
+                     [-l LB [LB ...]] [-g GROUP] [--listen LISTEN]
                      [--log-level {debug,info,warn,error,critical}]
                      storage-dir
 
@@ -37,7 +37,7 @@ optional arguments:
   -h, --help            show this help message and exit
   -a ACME, --acme ACME  The address for the ACME Directory Resource (default:
                         https://acme-v01.api.letsencrypt.org/directory)
-  -m MARATHON, --marathon MARATHON
+  -m MARATHON [MARATHON ...], --marathon MARATHON [MARATHON ...]
                         The address for the Marathon HTTP API (default:
                         http://marathon.mesos:8080)
   -l LB [LB ...], --lb LB [LB ...]
@@ -119,15 +119,15 @@ The `marathon-acme` Docker container can be configured either using command-line
 
 The environment variables available correspond to the CLI options as follows:
 
-| Environment variable      | CLI option    |
-|---------------------------|---------------|
-| `MARATHON_ACME_ACME`      | `--acme`      |
-| `MARATHON_ACME_MARATHON`  | `--marathon`  |
-| `MARATHON_ACME_LBS`*      | `--lb`        |
-| `MARATHON_ACME_GROUP`     | `--group`     |
-| `MARATHON_ACME_LOG_LEVEL` | `--log-level` |
+| Environment variable       | CLI option    |
+|----------------------------|---------------|
+| `MARATHON_ACME_ACME`       | `--acme`      |
+| `MARATHON_ACME_MARATHONS`* | `--marathon`  |
+| `MARATHON_ACME_LBS`*       | `--lb`        |
+| `MARATHON_ACME_GROUP`      | `--group`     |
+| `MARATHON_ACME_LOG_LEVEL`  | `--log-level` |
 
-\*Multiple load balancers can be set using multiple spaces-separated addresses.
+\*Multiple addresses should be space-separated.
 
 #### Volumes and ports
 The `marathon-acme` container defaults to the `/var/lib/marathon-acme` directory to store certificates and the ACME client private key. This is the path inside the container that should be mounted as a shared volume.
diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh
index 5527ac9..e20ed32 100755
--- a/docker-entrypoint.sh
+++ b/docker-entrypoint.sh
@@ -2,7 +2,7 @@
 
 # Options can be set using environment variables:
 # MARATHON_ACME_ACME:      --acme
-# MARATHON_ACME_MARATHON:  --marathon
+# MARATHON_ACME_MARATHONS:  --marathon
 # MARATHON_ACME_LBS:       --lb
 # MARATHON_ACME_GROUP:     --group
 # MARATHON_ACME_LOG_LEVEL: --log-level
@@ -13,7 +13,7 @@
 
 exec marathon-acme \
   ${MARATHON_ACME_ACME:+--acme "$MARATHON_ACME_ACME"} \
-  ${MARATHON_ACME_MARATHON:+--marathon "$MARATHON_ACME_MARATHON"} \
+  ${MARATHON_ACME_MARATHONS:+--marathon $MARATHON_ACME_MARATHONS} \
   ${MARATHON_ACME_LBS:+--lb $MARATHON_ACME_LBS} \
   ${MARATHON_ACME_GROUP:+--group "$MARATHON_ACME_GROUP"} \
   ${MARATHON_ACME_LOG_LEVEL:+--log-level "$MARATHON_ACME_LOG_LEVEL"} \
diff --git a/marathon_acme/cli.py b/marathon_acme/cli.py
index 1414237..84be6ca 100644
--- a/marathon_acme/cli.py
+++ b/marathon_acme/cli.py
@@ -22,7 +22,7 @@ parser.add_argument('-a', '--acme',
                          '(default: %(default)s)',
                     default=(
                         'https://acme-v01.api.letsencrypt.org/directory'))
-parser.add_argument('-m', '--marathon',
+parser.add_argument('-m', '--marathon', nargs='+',
                     help='The address for the Marathon HTTP API (default: '
                          '%(default)s)',
                     default='http://marathon.mesos:8080')
@@ -69,7 +69,7 @@ def main(reactor, raw_args=sys.argv[1:]):
 
 
 def create_marathon_acme(storage_dir, acme_directory,
-                         marathon_addr, mlb_addrs, group,
+                         marathon_addrs, mlb_addrs, group,
                          reactor):
     """
     Create a marathon-acme instance.
@@ -93,7 +93,7 @@ def create_marathon_acme(storage_dir, acme_directory,
     key = maybe_key(storage_path)
 
     return MarathonAcme(
-        MarathonClient(marathon_addr, reactor=reactor),
+        MarathonClient(marathon_addrs, reactor=reactor),
         group,
         DirectoryStore(certs_path),
         MarathonLbClient(mlb_addrs, reactor=reactor),
diff --git a/marathon_acme/clients.py b/marathon_acme/clients.py
index 4987d31..4e742a9 100644
--- a/marathon_acme/clients.py
+++ b/marathon_acme/clients.py
@@ -259,6 +259,44 @@ def sse_content(response, handler):
 
 class MarathonClient(JsonClient):
 
+    def __init__(self, endpoints, *args, **kwargs):
+        """
+        :param endpoints:
+            A priority-ordered list of Marathon endpoints. Each endpoint will
+            be tried one-by-one until the request succeeds or all endpoints
+            fail.
+        """
+        super(MarathonClient, self).__init__(*args, **kwargs)
+        self.endpoints = endpoints
+
+    def request(self, *args, **kwargs):
+        d = self._request(None, list(self.endpoints), *args, **kwargs)
+        d.addErrback(self._log_all_endpoints_failed)
+        return d
+
+    def _request(self, failure, endpoints, *args, **kwargs):
+        """
+        Recursively make requests to each endpoint in ``endpoints``.
+        """
+        # We've run out of endpoints, fail
+        if not endpoints:
+            return failure
+
+        endpoint = endpoints.pop(0)
+        d = super(MarathonClient, self).request(*args, url=endpoint, **kwargs)
+
+        # If something goes wrong, call ourselves again with the remaining
+        # endpoints
+        d.addErrback(self._request, endpoints, *args, **kwargs)
+        return d
+
+    def _log_all_endpoints_failed(self, failure):
+        # Just log an error so it is clear what has happened and return the
+        # final failure. Individual failures should have been logged via
+        # _log_request_error().
+        self.log.error('Failed to make a request to all Marathon endpoints')
+        return failure
+
     def get_json_field(self, field, **kwargs):
         """
         Perform a GET request and get the contents of the JSON response.

Support multiple Marathon endpoints and fail over to a different one if one goes down
Currently only support a single Marathon endpoint. Related: #46 
diff --git a/marathon_acme/tests/helpers.py b/marathon_acme/tests/helpers.py
index 24b3ff6..a16a49c 100644
--- a/marathon_acme/tests/helpers.py
+++ b/marathon_acme/tests/helpers.py
@@ -1,12 +1,39 @@
 from treq.client import HTTPClient
 from twisted.internet.defer import fail
+from uritools import urisplit
 
 
 class FailingAgent(object):
+    def __init__(self, error=RuntimeError()):
+        self.error = error
+
     """ A twisted.web.iweb.IAgent that does nothing but fail. """
     def request(self, method, uri, headers=None, bodyProducer=None):
-        return fail(RuntimeError())
+        return fail(self.error)
 
 
 """ A Treq client that will fail with a RuntimeError for any request made. """
 failing_client = HTTPClient(FailingAgent())
+
+
+class PerLocationAgent(object):
+    """
+    A twisted.web.iweb.IAgent that delegates to other agents for specific URI
+    locations.
+    """
+    def __init__(self):
+        self.agents = {}
+
+    def add_agent(self, location, agent):
+        """
+        Add an agent for URIs with the specified location.
+        :param bytes location:
+            The URI authority/location (e.g. b'example.com:80')
+        :param agent: The twisted.web.iweb.IAgent to use for the location
+        """
+        self.agents[location] = agent
+
+    def request(self, method, uri, headers=None, bodyProducer=None):
+        agent = self.agents[urisplit(uri).authority]
+        return agent.request(
+            method, uri, headers=headers, bodyProducer=bodyProducer)
diff --git a/marathon_acme/tests/test_clients.py b/marathon_acme/tests/test_clients.py
index 6eb67f9..24c3f3a 100644
--- a/marathon_acme/tests/test_clients.py
+++ b/marathon_acme/tests/test_clients.py
@@ -22,7 +22,8 @@ from marathon_acme.clients import (
     json_content, JsonClient, MarathonClient, MarathonLbClient,
     raise_for_status)
 from marathon_acme.server import write_request_json
-from marathon_acme.tests.helpers import failing_client
+from marathon_acme.tests.helpers import (
+    failing_client, FailingAgent, PerLocationAgent)
 from marathon_acme.tests.matchers import (
     HasHeader, HasRequestProperties, WithErrorTypeAndMessage)
 
@@ -127,10 +128,10 @@ class TestHTTPClientBase(TestCase):
         super(TestHTTPClientBase, self).setUp()
 
         self.requests = DeferredQueue()
-        fake_server = FakeHttpServer(self.handle_request)
+        self.fake_server = FakeHttpServer(self.handle_request)
 
-        inner_client = treq_HTTPClient(fake_server.get_agent())
-        self.client = self.get_client(inner_client)
+        fake_client = treq_HTTPClient(self.fake_server.get_agent())
+        self.client = self.get_client(fake_client)
 
         # Spin the reactor once at the end of each test to clean up any
         # cancelled deferreds
@@ -519,7 +520,82 @@ class TestJsonClient(TestHTTPClientBase):
 
 class TestMarathonClient(TestHTTPClientBase):
     def get_client(self, client):
-        return MarathonClient('http://localhost:8080', client=client)
+        return MarathonClient(['http://localhost:8080'], client=client)
+
+    def uri(self, path, index=0):
+        return ''.join((self.client.endpoints[index], path))
+
+    @inlineCallbacks
+    def test_request_success(self):
+        """
+        When we make a request and there are multiple Marathon endpoints
+        specified, the first endpoint is used.
+        """
+        agent = PerLocationAgent()
+        agent.add_agent(b'localhost:8080', self.fake_server.get_agent())
+        agent.add_agent(b'localhost:9090', FailingAgent())
+        client = MarathonClient(
+            ['http://localhost:8080', 'http://localhost:9090'],
+            client=treq_HTTPClient(agent))
+
+        d = self.cleanup_d(client.request('GET', path='/my-path'))
+
+        request = yield self.requests.get()
+        self.assertThat(request, HasRequestProperties(
+            method='GET', url='http://localhost:8080/my-path'))
+
+        request.setResponseCode(200)
+        request.finish()
+
+        yield d
+
+    @inlineCallbacks
+    def test_request_fallback(self):
+        """
+        When we make a request and there are multiple Marathon endpoints
+        specified, and an endpoint fails, the next endpoint is used.
+        """
+        agent = PerLocationAgent()
+        agent.add_agent(b'localhost:8080', FailingAgent())
+        agent.add_agent(b'localhost:9090', self.fake_server.get_agent())
+        client = MarathonClient(
+            ['http://localhost:8080', 'http://localhost:9090'],
+            client=treq_HTTPClient(agent))
+
+        d = self.cleanup_d(client.request('GET', path='/my-path'))
+
+        request = yield self.requests.get()
+        self.assertThat(request, HasRequestProperties(
+            method='GET', url='http://localhost:9090/my-path'))
+
+        request.setResponseCode(200)
+        request.finish()
+
+        yield d
+
+        flush_logged_errors(RuntimeError)
+
+    @inlineCallbacks
+    def test_request_fallback_all_failed(self):
+        """
+        When we make a request and there are multiple Marathon endpoints
+        specified, and all the endpoints fail, the last failure should be
+        returned.
+        """
+        agent = PerLocationAgent()
+        agent.add_agent(b'localhost:8080', FailingAgent(RuntimeError('8080')))
+        agent.add_agent(b'localhost:9090', FailingAgent(RuntimeError('9090')))
+        client = MarathonClient(
+            ['http://localhost:8080', 'http://localhost:9090'],
+            client=treq_HTTPClient(agent))
+
+        d = self.cleanup_d(client.request('GET', path='/my-path'))
+
+        yield wait0()
+        self.assertThat(d, failed(WithErrorTypeAndMessage(
+            RuntimeError, '9090')))
+
+        flush_logged_errors(RuntimeError)
 
     @inlineCallbacks
     def test_get_json_field(self):
diff --git a/marathon_acme/tests/test_service.py b/marathon_acme/tests/test_service.py
index bfb3375..d1fda60 100644
--- a/marathon_acme/tests/test_service.py
+++ b/marathon_acme/tests/test_service.py
@@ -92,7 +92,7 @@ class TestMarathonAcme(object):
         self.fake_marathon = FakeMarathon()
         self.fake_marathon_api = FakeMarathonAPI(self.fake_marathon)
         marathon_client = MarathonClient(
-            'http://localhost:8080', client=self.fake_marathon_api.client)
+            ['http://localhost:8080'], client=self.fake_marathon_api.client)
 
         self.cert_store = MemoryStore()
 
@@ -154,7 +154,7 @@ class TestMarathonAcme(object):
 
         # Some other client attaches
         other_client = MarathonClient(
-            'http://localhost:8080', client=self.fake_marathon_api.client)
+            ['http://localhost:8080'], client=self.fake_marathon_api.client)
         other_client_events = []
         other_client.get_events(
             {'event_stream_attached': other_client_events.append})
diff --git a/marathon_acme/tests/test_test_helpers.py b/marathon_acme/tests/test_test_helpers.py
new file mode 100644
index 0000000..141f241
--- /dev/null
+++ b/marathon_acme/tests/test_test_helpers.py
@@ -0,0 +1,81 @@
+import pytest
+from testtools import ExpectedException
+from testtools.assertions import assert_that
+from testtools.matchers import (
+    Equals, Is, IsInstance, MatchesAll, MatchesDict, MatchesListwise,
+    MatchesPredicate, MatchesStructure)
+from testtools.twistedsupport import failed, succeeded
+from twisted.internet.defer import succeed
+
+from marathon_acme.tests.helpers import FailingAgent, PerLocationAgent
+
+
+class DummyAgent(object):
+    def request(self, *args, **kwargs):
+        return succeed((args, kwargs))
+
+
+class TestPerLocationAgent(object):
+    @pytest.fixture
+    def agent(self):
+        return PerLocationAgent()
+
+    def test_keyerror_if_location_unset(self, agent):
+        """
+        When a request is made using the agent and no delegate agent has been
+        added for the URI location/authority, a KeyError is expected.
+        """
+        with ExpectedException(KeyError, r"b?'foo:8080'"):
+            agent.request(b'GET', b'http://foo:8080')
+
+    def test_delegates_to_agent_for_location(self, agent):
+        """
+        When a request is made using the agent, the added agents are delegated
+        to based on the URI location/authority.
+        """
+        agent.add_agent(b'foo:8080', DummyAgent())
+        agent.add_agent(b'bar:8080', FailingAgent(RuntimeError('bar')))
+        agent.add_agent(b'foo:9090', FailingAgent(RuntimeError('9090')))
+
+        d = agent.request(b'GET', b'http://foo:8080')
+        assert_that(d, succeeded(MatchesListwise([
+            MatchesListwise([Equals(b'GET'), Equals(b'http://foo:8080')]),
+            MatchesDict({'headers': Is(None), 'bodyProducer': Is(None)})
+        ])))
+
+        # Scheme doesn't matter
+        d = agent.request(b'GET', b'https://foo:8080')
+        assert_that(d, succeeded(MatchesListwise([
+            MatchesListwise([Equals(b'GET'), Equals(b'https://foo:8080')]),
+            MatchesDict({'headers': Is(None), 'bodyProducer': Is(None)})
+        ])))
+
+        # Path doesn't matter
+        d = agent.request(b'GET', b'http://foo:8080/bar/baz')
+        assert_that(d, succeeded(MatchesListwise([
+            MatchesListwise([
+                Equals(b'GET'), Equals(b'http://foo:8080/bar/baz')]),
+            MatchesDict({'headers': Is(None), 'bodyProducer': Is(None)})
+        ])))
+
+        # Hostname *does* matter
+        d = agent.request(b'GET', b'http://bar:8080')
+        assert_that(d, failed(MatchesStructure(value=MatchesAll(
+            IsInstance(RuntimeError),
+            MatchesPredicate(str, Equals('bar'))
+        ))))
+
+        # Port *does* matter
+        d = agent.request(b'GET', b'http://foo:9090')
+        assert_that(d, failed(MatchesStructure(value=MatchesAll(
+            IsInstance(RuntimeError),
+            MatchesPredicate(str, Equals('9090'))
+        ))))
+
+        # Other args passed through
+        d = agent.request(b'GET', b'http://foo:8080', 'bar', 'baz')
+        assert_that(d, succeeded(MatchesListwise([
+            MatchesListwise([Equals(b'GET'), Equals(b'http://foo:8080')]),
+            MatchesDict(
+                {'headers': Equals('bar'), 'bodyProducer': Equals('baz')})
+        ])))

pip install -e .
parse_log_pytest
requirements.txt
pytest pytest-coverage flake8
apt-get update apt-get install -y gcc
3.9
requirements-dev.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
acme==0.40.1
attrs==25.3.0
Automat==24.8.1
boltons==25.0.0
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
constantly==23.10.4
coverage==7.8.0
cryptography==44.0.2
eliot==1.17.5
exceptiongroup==1.2.2
fixtures==4.2.4.post1
flake8==7.2.0
hyperlink==21.0.0
idna==3.10
incremental==24.7.2
iniconfig==2.1.0
josepy==2.0.0
klein==15.3.1
-e git+https://github.com/praekeltfoundation/marathon-acme.git@20c5a3c00ef8c1521ccdc20aa650a13fd6361d8d#egg=marathon_acme
MarkupSafe==3.0.2
mccabe==0.7.0
mock==5.2.0
orjson==3.10.16
packaging==24.2
pem==23.1.0
pluggy==1.5.0
pyasn1==0.6.1
pyasn1_modules==0.4.2
pycodestyle==2.13.0
pycparser==2.22
pyflakes==3.3.1
pyOpenSSL==25.0.0
pyRFC3339==2.0.1
pyrsistent==0.20.0
pytest==8.3.5
pytest-cov==6.0.0
pytest-cover==3.0.0
pytest-coverage==0.0
pytz==2025.2
requests==2.32.3
requests-toolbelt==1.0.0
service-identity==24.2.0
six==1.17.0
testtools==2.7.2
tomli==2.2.1
treq==24.9.1
Twisted==24.11.0
txacme==0.9.3
txfake==0.1.1
TxSNI==0.2.0
typing_extensions==4.13.0
uritools==4.0.3
urllib3==2.3.0
Werkzeug==3.1.3
zope.interface==7.2

name: marathon-acme
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - acme==0.40.1
      - attrs==25.3.0
      - automat==24.8.1
      - boltons==25.0.0
      - certifi==2025.1.31
      - cffi==1.17.1
      - charset-normalizer==3.4.1
      - constantly==23.10.4
      - coverage==7.8.0
      - cryptography==44.0.2
      - eliot==1.17.5
      - exceptiongroup==1.2.2
      - fixtures==4.2.4.post1
      - flake8==7.2.0
      - hyperlink==21.0.0
      - idna==3.10
      - incremental==24.7.2
      - iniconfig==2.1.0
      - josepy==2.0.0
      - klein==15.3.1
      - markupsafe==3.0.2
      - mccabe==0.7.0
      - mock==5.2.0
      - orjson==3.10.16
      - packaging==24.2
      - pem==23.1.0
      - pluggy==1.5.0
      - pyasn1==0.6.1
      - pyasn1-modules==0.4.2
      - pycodestyle==2.13.0
      - pycparser==2.22
      - pyflakes==3.3.1
      - pyopenssl==25.0.0
      - pyrfc3339==2.0.1
      - pyrsistent==0.20.0
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - pytest-cover==3.0.0
      - pytest-coverage==0.0
      - pytz==2025.2
      - requests==2.32.3
      - requests-toolbelt==1.0.0
      - service-identity==24.2.0
      - six==1.17.0
      - testtools==2.7.2
      - tomli==2.2.1
      - treq==24.9.1
      - twisted==24.11.0
      - txacme==0.9.3
      - txfake==0.1.1
      - txsni==0.2.0
      - typing-extensions==4.13.0
      - uritools==4.0.3
      - urllib3==2.3.0
      - werkzeug==3.1.3
      - zope-interface==7.2
prefix: /opt/conda/envs/marathon-acme

marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_apps marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_events marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_events_incorrect_content_type marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_events_multiple_callbacks marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_events_multiple_events marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_events_non_200 marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_json_field marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_json_field_error marathon_acme/tests/test_clients.py::TestMarathonClient::test_get_json_field_missing marathon_acme/tests/test_clients.py::TestMarathonClient::test_request_fallback marathon_acme/tests/test_clients.py::TestMarathonClient::test_request_fallback_all_failed marathon_acme/tests/test_clients.py::TestMarathonClient::test_request_success
marathon_acme/tests/test_service.py::TestMarathonAcme::test_listen_events_attach_initial_sync marathon_acme/tests/test_service.py::TestMarathonAcme::test_listen_events_attach_only_first marathon_acme/tests/test_service.py::TestMarathonAcme::test_listen_events_api_request_triggers_sync marathon_acme/tests/test_service.py::TestMarathonAcme::test_listen_events_reconnects marathon_acme/tests/test_service.py::TestMarathonAcme::test_listen_events_syncs_each_reconnect marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_app marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_app_multiple_ports marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_multiple_apps marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_apps_common_domains marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_app_multiple_domains marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_no_apps marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_app_no_domains marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_app_group_mismatch marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_app_port_group_mismatch marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_app_existing_cert marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_acme_server_failure_acceptable marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_acme_server_failure_unacceptable marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_other_issue_failure
marathon_acme/tests/test_clients.py::TestGetSingleHeader::test_single_value marathon_acme/tests/test_clients.py::TestGetSingleHeader::test_multiple_values marathon_acme/tests/test_clients.py::TestGetSingleHeader::test_value_with_params marathon_acme/tests/test_clients.py::TestGetSingleHeader::test_value_missing marathon_acme/tests/test_clients.py::TestDefaultReactor::test_default_reactor marathon_acme/tests/test_clients.py::TestDefaultReactor::test_default_reactor_not_provided marathon_acme/tests/test_clients.py::TestDefaultClient::test_default_client marathon_acme/tests/test_clients.py::TestDefaultClient::test_default_client_not_provided marathon_acme/tests/test_clients.py::TestHTTPClient::test_auth marathon_acme/tests/test_clients.py::TestHTTPClient::test_auth_precedence_over_url_userinfo marathon_acme/tests/test_clients.py::TestHTTPClient::test_client_error_response marathon_acme/tests/test_clients.py::TestHTTPClient::test_failure_during_request marathon_acme/tests/test_clients.py::TestHTTPClient::test_params marathon_acme/tests/test_clients.py::TestHTTPClient::test_params_precedence_over_url_query marathon_acme/tests/test_clients.py::TestHTTPClient::test_request marathon_acme/tests/test_clients.py::TestHTTPClient::test_request_debug_log marathon_acme/tests/test_clients.py::TestHTTPClient::test_request_url marathon_acme/tests/test_clients.py::TestHTTPClient::test_server_error_response marathon_acme/tests/test_clients.py::TestHTTPClient::test_url_overrides marathon_acme/tests/test_clients.py::TestHTTPClient::test_url_query_as_params marathon_acme/tests/test_clients.py::TestHTTPClient::test_url_userinfo_as_auth marathon_acme/tests/test_clients.py::TestJsonClient::test_json_content marathon_acme/tests/test_clients.py::TestJsonClient::test_json_content_incorrect_content_type marathon_acme/tests/test_clients.py::TestJsonClient::test_json_content_missing_content_type marathon_acme/tests/test_clients.py::TestJsonClient::test_json_data_and_data_not_allowed marathon_acme/tests/test_clients.py::TestJsonClient::test_request_json_data marathon_acme/tests/test_clients.py::TestMarathonLbClient::test_mlb_signal_hup marathon_acme/tests/test_clients.py::TestMarathonLbClient::test_mlb_signal_usr1 marathon_acme/tests/test_clients.py::TestMarathonLbClient::test_request_failure marathon_acme/tests/test_clients.py::TestMarathonLbClient::test_request_partial_failure marathon_acme/tests/test_clients.py::TestMarathonLbClient::test_request_success marathon_acme/tests/test_service.py::TestParseDomainLabel::test_single_domain marathon_acme/tests/test_service.py::TestParseDomainLabel::test_whitespace marathon_acme/tests/test_service.py::TestParseDomainLabel::test_multiple_domains marathon_acme/tests/test_service.py::TestParseDomainLabel::test_multiple_domains_whitespace marathon_acme/tests/test_service.py::TestMarathonAcme::test_sync_failure marathon_acme/tests/test_test_helpers.py::TestPerLocationAgent::test_keyerror_if_location_unset marathon_acme/tests/test_test_helpers.py::TestPerLocationAgent::test_delegates_to_agent_for_location
marathon_acme/cli.py marathon_acme/clients.py README.md docker-entrypoint.sh
marathon_acme/cli.py marathon_acme/clients.py README.md docker-entrypoint.sh