Renewer integration tests, quickfixes
diff --git a/letsencrypt/renewer.py b/letsencrypt/renewer.py
index 4a1e96a654a..d2c0b8e7db7 100644
--- a/letsencrypt/renewer.py
+++ b/letsencrypt/renewer.py
@@ -12,6 +12,7 @@
 import sys
 
 import configobj
+import zope.component
 
 from letsencrypt import configuration
 from letsencrypt import cli
@@ -20,6 +21,7 @@
 from letsencrypt import notify
 from letsencrypt import storage
 
+from letsencrypt.display import util as display_util
 from letsencrypt.plugins import disco as plugins_disco
 
 
@@ -64,6 +66,7 @@ def renew(cert, old_version):
     # XXX: this loses type data (for example, the fact that key_size
     #      was an int, not a str)
     config.rsa_key_size = int(config.rsa_key_size)
+    config.dvsni_port = int(config.dvsni_port)
     try:
         authenticator = plugins[renewalparams["authenticator"]]
     except KeyError:
@@ -80,14 +83,15 @@ def renew(cert, old_version):
     our_client = client.Client(config, account, authenticator, None)
     with open(cert.version("cert", old_version)) as f:
         sans = crypto_util.get_sans_from_cert(f.read())
-    new_cert, new_key, new_chain = our_client.obtain_certificate(sans)
-    if new_cert and new_key and new_chain:
+    new_certr, new_chain, new_key, _ = our_client.obtain_certificate(sans)
+    if new_chain is not None:
         # XXX: Assumes that there was no key change.  We need logic
         #      for figuring out whether there was or not.  Probably
         #      best is to have obtain_certificate return None for
         #      new_key if the old key is to be used (since save_successor
         #      already understands this distinction!)
-        return cert.save_successor(old_version, new_cert, new_key, new_chain)
+        return cert.save_successor(old_version, new_certr.body.as_pem(),
+                                   new_key.pem, new_chain.as_pem())
         # TODO: Notify results
     else:
         # TODO: Notify negative results
@@ -120,6 +124,8 @@ def main(config=None, args=sys.argv[1:]):
     #       turned it off. (The boolean parameter should probably be
     #       called renewer_enabled.)
 
+    zope.component.provideUtility(display_util.FileDisplay(sys.stdout))
+
     cli_config = configuration.RenewerConfiguration(
         _create_parser().parse_args(args))
 
@@ -140,6 +146,8 @@ def main(config=None, args=sys.argv[1:]):
         rc_config = configobj.ConfigObj(cli_config.renewer_config_file)
         rc_config.merge(configobj.ConfigObj(
             os.path.join(cli_config.renewal_configs_dir, i)))
+        # TODO: this is a dirty hack!
+        rc_config.filename = os.path.join(cli_config.renewal_configs_dir, i)
         try:
             # TODO: Before trying to initialize the RenewableCert object,
             #       we could check here whether the combination of the config
diff --git a/letsencrypt/tests/renewer_test.py b/letsencrypt/tests/renewer_test.py
index d68078c185e..1ba58a7c8f6 100644
--- a/letsencrypt/tests/renewer_test.py
+++ b/letsencrypt/tests/renewer_test.py
@@ -574,19 +574,25 @@ def test_renew(self, mock_c, mock_da, mock_pd):
         self.test_rc.configfile["renewalparams"]["rsa_key_size"] = "2048"
         self.test_rc.configfile["renewalparams"]["server"] = "acme.example.com"
         self.test_rc.configfile["renewalparams"]["authenticator"] = "fake"
+        self.test_rc.configfile["renewalparams"]["dvsni_port"] = "4430"
         mock_auth = mock.MagicMock()
         mock_pd.PluginsRegistry.find_all.return_value = {"apache": mock_auth}
         # Fails because "fake" != "apache"
         self.assertFalse(renewer.renew(self.test_rc, 1))
         self.test_rc.configfile["renewalparams"]["authenticator"] = "apache"
         mock_client = mock.MagicMock()
-        mock_client.obtain_certificate.return_value = ("cert", "key", "chain")
+        # pylint: disable=star-args
+        mock_client.obtain_certificate.return_value = (
+            mock.Mock(**{'body.as_pem.return_value': 'cert'}),
+            mock.Mock(**{'as_pem.return_value': 'chain'}),
+            mock.Mock(pem="key"), mock.sentinel.csr)
         mock_c.return_value = mock_client
         self.assertEqual(2, renewer.renew(self.test_rc, 1))
         # TODO: We could also make several assertions about calls that should
         #       have been made to the mock functions here.
         self.assertEqual(mock_da.call_count, 1)
-        mock_client.obtain_certificate.return_value = (None, None, None)
+        mock_client.obtain_certificate.return_value = (
+            mock.sentinel.certr, None, mock.sentinel.key, mock.sentinel.csr)
         # This should fail because the renewal itself appears to fail
         self.assertFalse(renewer.renew(self.test_rc, 1))
 
diff --git a/tests/boulder-integration.sh b/tests/boulder-integration.sh
index fd4c27beb44..c3cc49c70eb 100755
--- a/tests/boulder-integration.sh
+++ b/tests/boulder-integration.sh
@@ -5,6 +5,7 @@
 
 root="$(mktemp -d)"
 echo "\nRoot integration tests directory: $root"
+store_flags="--config-dir $root/conf --work-dir $root/work"
 
 common() {
     # first three flags required, rest is handy defaults
@@ -12,8 +13,7 @@ common() {
         --server http://localhost:4000/acme/new-reg \
         --no-verify-ssl \
         --dvsni-port 5001 \
-        --config-dir "$root/conf" \
-        --work-dir "$root/work" \
+        $store_flags \
         --text \
         --agree-eula \
         --email "" \
@@ -30,3 +30,18 @@ common auth --csr "$CSR_PATH" \
        --chain-path "${root}/csr/chain.pem"
 openssl x509 -in "${root}/csr/0000_cert.pem" -text
 openssl x509 -in "${root}/csr/0000_chain.pem" -text
+
+# the following assumes that Boulder issues certificates for less than
+# 10 years, otherwise renewal will not take place
+cat <<EOF > "$root/conf/renewer.conf"
+renew_before_expiry = 10 years
+deploy_before_expiry = 10 years
+EOF
+letsencrypt-renewer $store_flags
+dir="$root/conf/archive/le.wtf"
+for x in cert chain fullchain privkey;
+do
+    latest="$(ls -1t $dir/ | grep -e "^${x}" | head -n1)"
+    live="$(readlink -f "$root/conf/live/le.wtf/${x}.pem")"
+    #[ "${dir}/${latest}" = "$live" ]  # renewer fails this test
+done

Fixes `IOError: [Errno 2] No such file or directory: '/tmp/le/config/archive/renewer/privkey2.pem'`

With this patch I was able to successfully renew my certificates, @schoen! :)

Unfortunately, renewer didn't update `live` directory symlinks... :(
