androidbuild: Search homedir of $PORTAGE_USERNAME for credentials.

This makes it possible to use `abutil` from within an ebuild file and
still find .ab_creds.json in the user's home directory.

BUG=b:24972874
TEST=Unittests pass.
TEST=Used abutil to successfully fetch an image.
TEST=Used an ab:// URL in an ebuild and confirmed emerge-$BOARD works.

Change-Id: Iaa9310de2eb44328d16bfe60e36d26017ea8575e
Signed-off-by: Filipe Brandenburger <filbranden@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/315942
Reviewed-by: Don Garrett <dgarrett@chromium.org>
diff --git a/lib/androidbuild.py b/lib/androidbuild.py
index b012b91..9d6b1d5 100644
--- a/lib/androidbuild.py
+++ b/lib/androidbuild.py
@@ -10,6 +10,7 @@
 import httplib2
 import oauth2client.client
 import os
+import pwd
 import urllib
 
 
@@ -68,6 +69,20 @@
     if os.path.exists(json_path):
       return json_path
 
+  # If not found, check at ~$PORTAGE_USERNAME. That might be the case if the
+  # tool is being used from within an ebuild script.
+  portage_username = os.environ.get('PORTAGE_USERNAME')
+  if portage_username:
+    try:
+      portage_homedir = pwd.getpwnam(portage_username).pw_dir
+    except KeyError:
+      # User $PORTAGE_USERNAME does not exist.
+      pass
+    else:
+      json_path = os.path.join(portage_homedir, homedir_json_credentials_path)
+      if os.path.exists(json_path):
+        return json_path
+
   raise CredentialsNotFoundError(
       'Could not find the JSON credentials at [%s] and no JSON file was '
       'specified in command line arguments.' % homedir_json_credentials_path)
diff --git a/lib/androidbuild_unittest.py b/lib/androidbuild_unittest.py
index 18b79e0..1641deb 100644
--- a/lib/androidbuild_unittest.py
+++ b/lib/androidbuild_unittest.py
@@ -11,6 +11,7 @@
 import mock
 import oauth2client
 import os
+import pwd
 
 from chromite.lib import androidbuild
 from chromite.lib import cros_test_lib
@@ -53,6 +54,31 @@
     self.assertEqual(os.path.abspath(json_path),
                      os.path.abspath(service_account_path))
 
+  def testFindCredentialsFile_PortageUsername(self):
+    """Checks that we can locate the JSON files under $PORTAGE_USERNAME."""
+    copy_environ = os.environ.copy()
+    copy_environ['HOME'] = '/nonexistent'
+    copy_environ['PORTAGE_USERNAME'] = 'fakeuser'
+
+    fakeuser_homedir = os.path.join(TESTDATA_PATH, 'androidbuild')
+    fakeuser_pwent = pwd.struct_passwd(('fakeuser', 'x', 1234, 1234,
+                                        'Fake User', fakeuser_homedir,
+                                        '/bin/sh'))
+
+    service_account_name = 'test_creds_authorized_user.json'
+
+    with mock.patch.dict(os.environ, copy_environ), \
+        mock.patch.object(pwd, 'getpwnam') as mock_getpwnam:
+      mock_getpwnam.return_value = fakeuser_pwent
+
+      json_path = androidbuild.FindCredentialsFile(
+          homedir_json_credentials_path=service_account_name)
+
+      mock_getpwnam.assert_called_once_with('fakeuser')
+
+      self.assertEqual(json_path,
+                       os.path.join(fakeuser_homedir, service_account_name))
+
   def testLoadCredentials_ServiceAccount(self):
     """Checks that loading a service account from JSON works."""
     creds = androidbuild.LoadCredentials(os.path.join(