[infra] Add service_account_json option to asset utils

Change-Id: If2686949009ba6fdf703ea794c0764c0e9966590
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252261
Auto-Submit: Ben Wagner aka dogben <benjaminwagner@google.com>
Reviewed-by: Eric Boren <borenet@google.com>
Commit-Queue: Ben Wagner aka dogben <benjaminwagner@google.com>
diff --git a/infra/bots/assets/asset_utils.py b/infra/bots/assets/asset_utils.py
index 686720c..834e696 100755
--- a/infra/bots/assets/asset_utils.py
+++ b/infra/bots/assets/asset_utils.py
@@ -44,11 +44,14 @@
 
 class CIPDStore(object):
   """Wrapper object for CIPD."""
-  def __init__(self, cipd_url=DEFAULT_CIPD_SERVICE_URL):
+  def __init__(self, cipd_url=DEFAULT_CIPD_SERVICE_URL,
+               service_account_json=None):
     self._cipd = 'cipd'
     if sys.platform == 'win32':
       self._cipd = 'cipd.bat'
     self._cipd_url = cipd_url
+    if service_account_json:
+      self._service_account_json = os.path.abspath(service_account_json)
     self._check_setup()
 
   def _check_setup(self):
@@ -67,7 +70,9 @@
     cipd_args = []
     if specify_service_url:
       cipd_args.extend(['--service-url', self._cipd_url])
-    if os.getenv('USE_CIPD_GCE_AUTH'):
+    if self._service_account_json:
+      cipd_args.extend(['-service-account-json', self._service_account_json])
+    elif os.getenv('USE_CIPD_GCE_AUTH'):
       # Enable automatic GCE authentication. For context see
       # https://bugs.chromium.org/p/skia/issues/detail?id=6385#c3
       cipd_args.extend(['-service-account-json', ':gce'])
@@ -153,7 +158,8 @@
 
 class GSStore(object):
   """Wrapper object for interacting with Google Storage."""
-  def __init__(self, gsutil=None, bucket=DEFAULT_GS_BUCKET):
+  def __init__(self, gsutil=None, bucket=DEFAULT_GS_BUCKET,
+               service_account_json=None):
     if gsutil:
       gsutil = os.path.abspath(gsutil)
     else:
@@ -171,6 +177,9 @@
     self._gsutil = [gsutil]
     if gsutil.endswith('.py'):
       self._gsutil = ['python', gsutil]
+    if service_account_json:
+      sa = os.path.abspath(service_account_json)
+      self._gsutil += ['-o', 'Credentials:gs_service_key_file=' + sa]
     self._gs_bucket = bucket
 
   def copy(self, src, dst):
@@ -230,9 +239,12 @@
 class MultiStore(object):
   """Wrapper object which uses CIPD as the primary store and GS for backup."""
   def __init__(self, cipd_url=DEFAULT_CIPD_SERVICE_URL,
+               service_account_json=None,
                gsutil=None, gs_bucket=DEFAULT_GS_BUCKET):
-    self._cipd = CIPDStore(cipd_url=cipd_url)
-    self._gs = GSStore(gsutil=gsutil, bucket=gs_bucket)
+    self._cipd = CIPDStore(cipd_url=cipd_url,
+                           service_account_json=service_account_json)
+    self._gs = GSStore(gsutil=gsutil, bucket=gs_bucket,
+                       service_account_json=service_account_json)
 
   def get_available_versions(self, name):
     return self._cipd.get_available_versions(name)
diff --git a/infra/bots/assets/assets.py b/infra/bots/assets/assets.py
index f29ddec..a5284dd 100755
--- a/infra/bots/assets/assets.py
+++ b/infra/bots/assets/assets.py
@@ -23,31 +23,43 @@
 import utils
 
 
+def _common_args(prs):
+  """Add common args to the given argparse.ArgumentParser."""
+  prs.add_argument('asset_name', help='Name of the asset.')
+  prs.add_argument('--gsutil')
+  prs.add_argument('--service_account_json')
+
+
+def _store(args):
+  """Return asset_utils.MultiStore based on args."""
+  return asset_utils.MultiStore(gsutil=args.gsutil,
+                                service_account_json=args.service_account_json)
+
+
+def _asset(args):
+  """Return asset_utils.Asset based on args."""
+  return asset_utils.Asset(args.asset_name, _store(args))
+
+
 def add(args):
   """Add a new asset."""
-  asset_utils.Asset.add(args.asset_name,
-                        asset_utils.MultiStore(gsutil=args.gsutil))
+  asset_utils.Asset.add(args.asset_name, _store(args))
 
 
 def remove(args):
   """Remove an asset."""
-  asset_utils.Asset(args.asset_name,
-                    asset_utils.MultiStore(gsutil=args.gsutil)).remove()
+  _asset(args).remove()
 
 
 def download(args):
   """Download the current version of an asset."""
-  asset = asset_utils.Asset(args.asset_name,
-                            asset_utils.MultiStore(gsutil=args.gsutil))
-  asset.download_current_version(args.target_dir)
+  _asset(args).download_current_version(args.target_dir)
 
 
 def upload(args):
   """Upload a new version of the asset."""
-  asset = asset_utils.Asset(args.asset_name,
-                            asset_utils.MultiStore(gsutil=args.gsutil))
-  asset.upload_new_version(args.target_dir, commit=args.commit,
-                           extra_tags=args.extra_tags)
+  _asset(args).upload_new_version(args.target_dir, commit=args.commit,
+                                  extra_tags=args.extra_tags)
 
 
 def main(argv):
@@ -56,27 +68,23 @@
 
   prs_add = subs.add_parser('add', help='Add a new asset.')
   prs_add.set_defaults(func=add)
-  prs_add.add_argument('asset_name', help='Name of the asset.')
-  prs_add.add_argument('--gsutil')
+  _common_args(prs_add)
 
   prs_remove = subs.add_parser('remove', help='Remove an asset.')
   prs_remove.set_defaults(func=remove)
-  prs_remove.add_argument('asset_name', help='Name of the asset.')
-  prs_remove.add_argument('--gsutil')
+  _common_args(prs_remove)
 
   prs_download = subs.add_parser(
       'download', help='Download the current version of an asset.')
   prs_download.set_defaults(func=download)
-  prs_download.add_argument('asset_name', help='Name of the asset.')
+  _common_args(prs_download)
   prs_download.add_argument('--target_dir', '-t', required=True)
-  prs_download.add_argument('--gsutil')
 
   prs_upload = subs.add_parser(
       'upload', help='Upload a new version of an asset.')
   prs_upload.set_defaults(func=upload)
-  prs_upload.add_argument('asset_name', help='Name of the asset.')
+  _common_args(prs_upload)
   prs_upload.add_argument('--target_dir', '-t', required=True)
-  prs_upload.add_argument('--gsutil')
   prs_upload.add_argument('--commit', action='store_true')
   prs_upload.add_argument(
     '--extra_tags', nargs='+',