=== modified file 'hooks/hooks.py'
--- hooks/hooks.py	2013-12-11 04:14:19 +0000
+++ hooks/hooks.py	2013-12-17 16:02:40 +0000
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 
+import base64
 import glob
 import os
 import re
@@ -34,6 +35,7 @@
 default_haproxy_config_dir = "/etc/haproxy"
 default_haproxy_config = "%s/haproxy.cfg" % default_haproxy_config_dir
 default_haproxy_service_config_dir = "/var/run/haproxy"
+default_haproxy_lib_dir = "/var/lib/haproxy"
 service_affecting_packages = ['haproxy']
 
 dupe_options = [
@@ -247,10 +249,14 @@
 #                                         server_ip
 #                                         server_port
 #                                         server_options
+#                       errorfiles: List of dicts
+#                                   http_status: status to handle
+#                                   content: base 64 content for HAProxy to
+#                                            write to socket
 #------------------------------------------------------------------------------
 def create_listen_stanza(service_name=None, service_ip=None,
                          service_port=None, service_options=None,
-                         server_entries=None):
+                         server_entries=None, service_errorfiles=None):
     if service_name is None or service_ip is None or service_port is None:
         return None
     fe_options = []
@@ -284,6 +290,13 @@
     service_config.append("backend %s" % (service_name,))
     service_config.extend("    %s" % service_option.strip()
                           for service_option in be_options)
+    if service_errorfiles is not None:
+        for errorfile in service_errorfiles:
+            path = os.path.join(default_haproxy_lib_dir,
+                                "service_%s" % service_name,
+                                "%s.http" % errorfile["http_status"])
+            service_config.append(
+                "    errorfile %s %s" % (errorfile["http_status"], path))
     if isinstance(server_entries, (list, tuple)):
         for (server_name, server_ip, server_port,
              server_options) in server_entries:
@@ -596,6 +609,17 @@
         log("Service: %s" % service_key)
         server_entries = service_config.get('servers')
 
+        errorfiles = service_config.get('errorfiles', [])
+        for errorfile in errorfiles:
+            service_name = services_dict[service_key]['service_name']
+            path = os.path.join(default_haproxy_lib_dir,
+                                "service_%s" % service_name)
+            if not os.path.exists(path):
+                os.makedirs(path)
+            full_path = os.path.join(path, "%s.http" % errorfile["http_status"])
+            with open(full_path, 'w') as f:
+                f.write(base64.b64decode(errorfile["content"]))
+
         service_name = service_config["service_name"]
         if not os.path.exists(default_haproxy_service_config_dir):
             os.mkdir(default_haproxy_service_config_dir, 0600)
@@ -606,11 +630,11 @@
                 service_config['service_host'],
                 service_config['service_port'],
                 service_config['service_options'],
-                server_entries))
+                server_entries, errorfiles))
 
 
 #------------------------------------------------------------------------------
-# load_services: Convenience function that load the service snippet
+# load_services: Convenience function that loads the service snippet
 #                configuration from the filesystem.
 #------------------------------------------------------------------------------
 def load_services(service_name=None):

=== modified file 'hooks/tests/test_helpers.py'
--- hooks/tests/test_helpers.py	2013-10-25 21:33:52 +0000
+++ hooks/tests/test_helpers.py	2013-12-17 16:02:40 +0000
@@ -1,3 +1,4 @@
+import base64
 import os
 
 from contextlib import contextmanager
@@ -352,6 +353,42 @@
 
         self.assertEqual(expected, result)
 
+    @patch.dict(os.environ, {"JUJU_UNIT_NAME": "haproxy/2"})
+    def test_creates_a_listen_stanza_with_errorfiles(self):
+        service_name = 'some-name'
+        service_ip = '10.11.12.13'
+        service_port = 1234
+        service_options = ('foo', 'bar')
+        server_entries = [
+            ('name-1', 'ip-1', 'port-1', ('foo1', 'bar1')),
+            ('name-2', 'ip-2', 'port-2', ('foo2', 'bar2')),
+        ]
+        content = ("HTTP/1.0 403 Forbidden\r\n"
+                   "Content-Type: text/html\r\n"
+                   "\r\n"
+                   "<html></html>")
+        errorfiles = [{'http_status': 403,
+                       'content': base64.b64encode(content)}]
+
+        result = hooks.create_listen_stanza(service_name, service_ip,
+                                            service_port, service_options,
+                                            server_entries, errorfiles)
+
+        expected = '\n'.join((
+            'frontend haproxy-2-1234',
+            '    bind 10.11.12.13:1234',
+            '    default_backend some-name',
+            '',
+            'backend some-name',
+            '    foo',
+            '    bar',
+            '    errorfile 403 /var/lib/haproxy/service_some-name/403.http',
+            '    server name-1 ip-1:port-1 foo1 bar1',
+            '    server name-2 ip-2:port-2 foo2 bar2',
+        ))
+
+        self.assertEqual(expected, result)
+
     def test_doesnt_create_listen_stanza_if_args_not_provided(self):
         self.assertIsNone(hooks.create_listen_stanza())
 

=== modified file 'hooks/tests/test_peer_hooks.py'
--- hooks/tests/test_peer_hooks.py	2013-09-19 12:45:40 +0000
+++ hooks/tests/test_peer_hooks.py	2013-12-17 16:02:40 +0000
@@ -1,3 +1,4 @@
+import base64
 import os
 import yaml
 
@@ -194,7 +195,40 @@
                 hooks.write_service_config(services_dict)
 
                 create_listen_stanza.assert_called_with(
-                    'bar', 'some-host', 'some-port', 'some-options', (1, 2))
+                    'bar', 'some-host', 'some-port', 'some-options', (1, 2), [])
                 mock_open.assert_called_with(
                     '/var/run/haproxy/bar.service', 'w')
                 mock_file.write.assert_called_with('some content')
+
+    @patch('hooks.create_listen_stanza')
+    def test_writes_errorfiles(self, create_listen_stanza):
+        create_listen_stanza.return_value = 'some content'
+
+        content = ("HTTP/1.0 403 Forbidden\r\n"
+                   "Content-Type: text/html\r\n"
+                   "\r\n"
+                   "<html></html>")
+        services_dict = {
+            'foo': {
+                'service_name': 'bar',
+                'service_host': 'some-host',
+                'service_port': 'some-port',
+                'service_options': 'some-options',
+                'servers': (1, 2),
+                'errorfiles': [{
+                    'http_status': 403,
+                    'content': base64.b64encode(content)
+                }]
+            },
+        }
+
+        with patch.object(os.path, "exists") as exists:
+            exists.return_value = True
+            with patch_open() as (mock_open, mock_file):
+                hooks.write_service_config(services_dict)
+
+                mock_open.assert_any_call(
+                    '/var/lib/haproxy/service_bar/403.http', 'w')
+                mock_file.write.assert_any_call(content)
+        self.assertTrue(create_listen_stanza.called)
+

