dsub 0.5.2__tar.gz → 0.5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. {dsub-0.5.2/dsub.egg-info → dsub-0.5.4}/PKG-INFO +10 -9
  2. {dsub-0.5.2 → dsub-0.5.4}/README.md +9 -8
  3. {dsub-0.5.2 → dsub-0.5.4}/dsub/_dsub_version.py +1 -1
  4. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/param_util.py +10 -13
  5. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/providers_util.py +1 -1
  6. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_batch.py +12 -12
  7. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_utils.py +29 -29
  8. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_v2_base.py +4 -4
  9. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/local.py +43 -18
  10. {dsub-0.5.2 → dsub-0.5.4/dsub.egg-info}/PKG-INFO +10 -9
  11. {dsub-0.5.2 → dsub-0.5.4}/test/integration/e2e_after.py +1 -1
  12. {dsub-0.5.2 → dsub-0.5.4}/test/integration/e2e_env_list.py +1 -1
  13. {dsub-0.5.2 → dsub-0.5.4}/test/integration/e2e_io_tasks.py +2 -2
  14. {dsub-0.5.2 → dsub-0.5.4}/test/integration/test_setup_e2e.py +4 -4
  15. {dsub-0.5.2 → dsub-0.5.4}/test/integration/test_util.py +4 -4
  16. {dsub-0.5.2 → dsub-0.5.4}/LICENSE +0 -0
  17. {dsub-0.5.2 → dsub-0.5.4}/MANIFEST.in +0 -0
  18. {dsub-0.5.2 → dsub-0.5.4}/dsub/__init__.py +0 -0
  19. {dsub-0.5.2 → dsub-0.5.4}/dsub/commands/__init__.py +0 -0
  20. {dsub-0.5.2 → dsub-0.5.4}/dsub/commands/ddel.py +0 -0
  21. {dsub-0.5.2 → dsub-0.5.4}/dsub/commands/dstat.py +0 -0
  22. {dsub-0.5.2 → dsub-0.5.4}/dsub/commands/dsub.py +0 -0
  23. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/__init__.py +0 -0
  24. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/dsub_errors.py +0 -0
  25. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/dsub_util.py +0 -0
  26. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/job_model.py +0 -0
  27. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/output_formatter.py +0 -0
  28. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/resources.py +0 -0
  29. {dsub-0.5.2 → dsub-0.5.4}/dsub/lib/retry_util.py +0 -0
  30. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/__init__.py +0 -0
  31. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/base.py +0 -0
  32. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/batch_dummy.py +0 -0
  33. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_base.py +0 -0
  34. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_batch_operations.py +0 -0
  35. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_cls_v2.py +0 -0
  36. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_custom_machine.py +0 -0
  37. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_v2_operations.py +0 -0
  38. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_v2_pipelines.py +0 -0
  39. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/google_v2_versions.py +0 -0
  40. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/local/runner.sh +0 -0
  41. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/provider_base.py +0 -0
  42. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/stub.py +0 -0
  43. {dsub-0.5.2 → dsub-0.5.4}/dsub/providers/test_fails.py +0 -0
  44. {dsub-0.5.2 → dsub-0.5.4}/dsub.egg-info/SOURCES.txt +0 -0
  45. {dsub-0.5.2 → dsub-0.5.4}/dsub.egg-info/dependency_links.txt +0 -0
  46. {dsub-0.5.2 → dsub-0.5.4}/dsub.egg-info/entry_points.txt +0 -0
  47. {dsub-0.5.2 → dsub-0.5.4}/dsub.egg-info/requires.txt +0 -0
  48. {dsub-0.5.2 → dsub-0.5.4}/dsub.egg-info/top_level.txt +0 -0
  49. {dsub-0.5.2 → dsub-0.5.4}/setup.cfg +0 -0
  50. {dsub-0.5.2 → dsub-0.5.4}/setup.py +0 -0
  51. {dsub-0.5.2 → dsub-0.5.4}/test/__init__.py +0 -0
  52. {dsub-0.5.2 → dsub-0.5.4}/test/integration/__init__.py +0 -0
  53. {dsub-0.5.2 → dsub-0.5.4}/test/integration/e2e_after_fail.py +0 -0
  54. {dsub-0.5.2 → dsub-0.5.4}/test/integration/e2e_python_api.py +0 -0
  55. {dsub-0.5.2 → dsub-0.5.4}/test/integration/get_data_value.py +0 -0
  56. {dsub-0.5.2 → dsub-0.5.4}/test/integration/script_python.py +0 -0
  57. {dsub-0.5.2 → dsub-0.5.4}/test/integration/test_setup.py +0 -0
  58. {dsub-0.5.2 → dsub-0.5.4}/test/unit/__init__.py +0 -0
  59. {dsub-0.5.2 → dsub-0.5.4}/test/unit/batch_client_test.py +0 -0
  60. {dsub-0.5.2 → dsub-0.5.4}/test/unit/batch_handling_test.py +0 -0
  61. {dsub-0.5.2 → dsub-0.5.4}/test/unit/custom_machine_test.py +0 -0
  62. {dsub-0.5.2 → dsub-0.5.4}/test/unit/dstat_test.py +0 -0
  63. {dsub-0.5.2 → dsub-0.5.4}/test/unit/dsub_test.py +0 -0
  64. {dsub-0.5.2 → dsub-0.5.4}/test/unit/dsub_util_test.py +0 -0
  65. {dsub-0.5.2 → dsub-0.5.4}/test/unit/fake_time.py +0 -0
  66. {dsub-0.5.2 → dsub-0.5.4}/test/unit/fake_time_test.py +0 -0
  67. {dsub-0.5.2 → dsub-0.5.4}/test/unit/gpu_test.py +0 -0
  68. {dsub-0.5.2 → dsub-0.5.4}/test/unit/job_model_test.py +0 -0
  69. {dsub-0.5.2 → dsub-0.5.4}/test/unit/local_provider_test.py +0 -0
  70. {dsub-0.5.2 → dsub-0.5.4}/test/unit/logging_uri_test.py +0 -0
  71. {dsub-0.5.2 → dsub-0.5.4}/test/unit/param_util_test.py +0 -0
  72. {dsub-0.5.2 → dsub-0.5.4}/test/unit/retrying_test.py +0 -0
  73. {dsub-0.5.2 → dsub-0.5.4}/test/unit/rfc3339_test.py +0 -0
  74. {dsub-0.5.2 → dsub-0.5.4}/test/unit/stub_provider_test.py +0 -0
  75. {dsub-0.5.2 → dsub-0.5.4}/test/unit/wait_and_retry_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dsub
3
- Version: 0.5.2
3
+ Version: 0.5.4
4
4
  Summary: A command-line tool that makes it easy to submit and run batch scripts in the cloud
5
5
  Home-page: https://github.com/DataBiosphere/dsub
6
6
  Author: Verily
@@ -108,7 +108,7 @@ While not used directly by `dsub` for the `google-batch` provider, you are likel
108
108
  Cloud SDK](https://cloud.google.com/sdk/).
109
109
 
110
110
  If you will be using the `local` provider for faster job development,
111
- you *will* need to install the Google Cloud SDK, which uses `gsutil` to ensure
111
+ you *will* need to install the Google Cloud SDK, which uses `gcloud storage` to ensure
112
112
  file operation semantics consistent with the Google `dsub` providers.
113
113
 
114
114
  1. [Install the Google Cloud SDK](https://cloud.google.com/sdk/)
@@ -234,10 +234,10 @@ The steps for getting started differ slightly as indicated in the steps below:
234
234
 
235
235
  The dsub logs and output files will be written to a bucket. Create a
236
236
  bucket using the [storage browser](https://console.cloud.google.com/storage/browser?project=)
237
- or run the command-line utility [gsutil](https://cloud.google.com/storage/docs/gsutil),
237
+ or run the command-line utility [gcloud storage](https://cloud.google.com/sdk/gcloud/reference/storage),
238
238
  included in the Cloud SDK.
239
239
 
240
- gsutil mb gs://my-bucket
240
+ gcloud storage buckets create gs://my-bucket
241
241
 
242
242
  Change `my-bucket` to a unique name that follows the
243
243
  [bucket-naming conventions](https://cloud.google.com/storage/docs/bucket-naming).
@@ -267,7 +267,7 @@ The steps for getting started differ slightly as indicated in the steps below:
267
267
 
268
268
  1. View the output file.
269
269
 
270
- gsutil cat gs://my-bucket/output/out.txt
270
+ gcloud storage cat gs://my-bucket/output/out.txt
271
271
 
272
272
  ## Backend providers
273
273
 
@@ -403,9 +403,8 @@ by:
403
403
 
404
404
  To upload the files to Google Cloud Storage, you can use the
405
405
  [storage browser](https://console.cloud.google.com/storage/browser?project=) or
406
- [gsutil](https://cloud.google.com/storage/docs/gsutil). You can also run on data
407
- that’s public or shared with your service account, an email address that you
408
- can find in the [Google Cloud Console](https://console.cloud.google.com).
406
+ [gcloud storage](https://cloud.google.com/sdk/gcloud/reference/storage).
407
+ You can also run on data that’s public or shared with your service account, an email address that you can find in the [Google Cloud Console](https://console.cloud.google.com).
409
408
 
410
409
  #### Files
411
410
 
@@ -780,7 +779,9 @@ of the service account will be `sa-name@project-id.iam.gserviceaccount.com`.
780
779
 
781
780
  2. Grant IAM access on buckets, etc. to the service account.
782
781
 
783
- gsutil iam ch serviceAccount:sa-name@project-id.iam.gserviceaccount.com:roles/storage.objectAdmin gs://bucket-name
782
+ gcloud storage buckets add-iam-policy-binding gs://bucket-name \
783
+ --member=serviceAccount:sa-name@project-id.iam.gserviceaccount.com \
784
+ --role=roles/storage.objectAdmin
784
785
 
785
786
  3. Update your `dsub` command to include `--service-account`
786
787
 
@@ -56,7 +56,7 @@ While not used directly by `dsub` for the `google-batch` provider, you are likel
56
56
  Cloud SDK](https://cloud.google.com/sdk/).
57
57
 
58
58
  If you will be using the `local` provider for faster job development,
59
- you *will* need to install the Google Cloud SDK, which uses `gsutil` to ensure
59
+ you *will* need to install the Google Cloud SDK, which uses `gcloud storage` to ensure
60
60
  file operation semantics consistent with the Google `dsub` providers.
61
61
 
62
62
  1. [Install the Google Cloud SDK](https://cloud.google.com/sdk/)
@@ -182,10 +182,10 @@ The steps for getting started differ slightly as indicated in the steps below:
182
182
 
183
183
  The dsub logs and output files will be written to a bucket. Create a
184
184
  bucket using the [storage browser](https://console.cloud.google.com/storage/browser?project=)
185
- or run the command-line utility [gsutil](https://cloud.google.com/storage/docs/gsutil),
185
+ or run the command-line utility [gcloud storage](https://cloud.google.com/sdk/gcloud/reference/storage),
186
186
  included in the Cloud SDK.
187
187
 
188
- gsutil mb gs://my-bucket
188
+ gcloud storage buckets create gs://my-bucket
189
189
 
190
190
  Change `my-bucket` to a unique name that follows the
191
191
  [bucket-naming conventions](https://cloud.google.com/storage/docs/bucket-naming).
@@ -215,7 +215,7 @@ The steps for getting started differ slightly as indicated in the steps below:
215
215
 
216
216
  1. View the output file.
217
217
 
218
- gsutil cat gs://my-bucket/output/out.txt
218
+ gcloud storage cat gs://my-bucket/output/out.txt
219
219
 
220
220
  ## Backend providers
221
221
 
@@ -351,9 +351,8 @@ by:
351
351
 
352
352
  To upload the files to Google Cloud Storage, you can use the
353
353
  [storage browser](https://console.cloud.google.com/storage/browser?project=) or
354
- [gsutil](https://cloud.google.com/storage/docs/gsutil). You can also run on data
355
- that’s public or shared with your service account, an email address that you
356
- can find in the [Google Cloud Console](https://console.cloud.google.com).
354
+ [gcloud storage](https://cloud.google.com/sdk/gcloud/reference/storage).
355
+ You can also run on data that’s public or shared with your service account, an email address that you can find in the [Google Cloud Console](https://console.cloud.google.com).
357
356
 
358
357
  #### Files
359
358
 
@@ -728,7 +727,9 @@ of the service account will be `sa-name@project-id.iam.gserviceaccount.com`.
728
727
 
729
728
  2. Grant IAM access on buckets, etc. to the service account.
730
729
 
731
- gsutil iam ch serviceAccount:sa-name@project-id.iam.gserviceaccount.com:roles/storage.objectAdmin gs://bucket-name
730
+ gcloud storage buckets add-iam-policy-binding gs://bucket-name \
731
+ --member=serviceAccount:sa-name@project-id.iam.gserviceaccount.com \
732
+ --role=roles/storage.objectAdmin
732
733
 
733
734
  3. Update your `dsub` command to include `--service-account`
734
735
 
@@ -27,5 +27,5 @@ A typical release sequence will be versioned as:
27
27
  """
28
28
 
29
29
 
30
- DSUB_VERSION = '0.5.2'
30
+ DSUB_VERSION = '0.5.4'
31
31
 
@@ -827,25 +827,22 @@ def directory_fmt(directory):
827
827
 
828
828
  Multiple files copy, works as intended in all cases:
829
829
  $ touch a.txt b.txt
830
- $ gsutil cp ./*.txt gs://mybucket/text_dest
831
- $ gsutil ls gs://mybucket/text_dest/
832
- 0 2017-07-19T21:44:36Z gs://mybucket/text_dest/a.txt
833
- 0 2017-07-19T21:44:36Z gs://mybucket/text_dest/b.txt
834
- TOTAL: 2 objects, 0 bytes (0 B)
830
+ $ gcloud storage cp ./*.txt gs://mybucket/text_dest
831
+ $ gcloud storage ls gs://mybucket/text_dest/
832
+ gs://mybucket/text_dest/a.txt
833
+ gs://mybucket/text_dest/b.txt
835
834
 
836
835
  Single file copy fails to copy into a directory:
837
836
  $ touch 1.bam
838
- $ gsutil cp ./*.bam gs://mybucket/bad_dest
839
- $ gsutil ls gs://mybucket/bad_dest
840
- 0 2017-07-19T21:46:16Z gs://mybucket/bad_dest
841
- TOTAL: 1 objects, 0 bytes (0 B)
837
+ $ gcloud storage cp ./*.bam gs://mybucket/bad_dest
838
+ $ gcloud storage ls gs://mybucket/bad_dest
839
+ gs://mybucket/bad_dest
842
840
 
843
841
  Adding a trailing forward slash fixes this:
844
842
  $ touch my.sam
845
- $ gsutil cp ./*.sam gs://mybucket/good_folder
846
- $ gsutil ls gs://mybucket/good_folder
847
- 0 2017-07-19T21:46:16Z gs://mybucket/good_folder/my.sam
848
- TOTAL: 1 objects, 0 bytes (0 B)
843
+ $ gcloud storage cp ./*.sam gs://mybucket/good_folder
844
+ $ gcloud storage ls gs://mybucket/good_folder
845
+ gs://mybucket/good_folder/my.sam
849
846
 
850
847
  Args:
851
848
  directory (str): a uri without an blob or file basename.
@@ -20,7 +20,7 @@ from . import job_model
20
20
  from .._dsub_version import DSUB_VERSION
21
21
 
22
22
  _LOCALIZE_COMMAND_MAP = {
23
- job_model.P_GCS: 'gsutil -m rsync -r',
23
+ job_model.P_GCS: 'gcloud storage rsync -r',
24
24
  job_model.P_LOCAL: 'rsync -r',
25
25
  }
26
26
 
@@ -145,11 +145,11 @@ _LOG_CP = textwrap.dedent("""
145
145
  "${{LOGGING_DIR}}/stderr.txt" \
146
146
  "{user_action}"
147
147
 
148
- gsutil_cp "${{LOGGING_DIR}}/stdout.txt" "${{STDOUT_PATH}}" "text/plain" "${{USER_PROJECT}}" &
148
+ gcloud_cp "${{LOGGING_DIR}}/stdout.txt" "${{STDOUT_PATH}}" "text/plain" "${{USER_PROJECT}}" &
149
149
  STDOUT_PID=$!
150
- gsutil_cp "${{LOGGING_DIR}}/stderr.txt" "${{STDERR_PATH}}" "text/plain" "${{USER_PROJECT}}" &
150
+ gcloud_cp "${{LOGGING_DIR}}/stderr.txt" "${{STDERR_PATH}}" "text/plain" "${{USER_PROJECT}}" &
151
151
  STDERR_PID=$!
152
- gsutil_cp "${{LOGGING_DIR}}/log.txt" "${{LOGGING_PATH}}" "text/plain" "${{USER_PROJECT}}" &
152
+ gcloud_cp "${{LOGGING_DIR}}/log.txt" "${{LOGGING_PATH}}" "text/plain" "${{USER_PROJECT}}" &
153
153
  LOG_PID=$!
154
154
 
155
155
  wait "${{STDOUT_PID}}"
@@ -168,7 +168,7 @@ _FINAL_LOGGING_CMD = textwrap.dedent("""\
168
168
  touch "${{LOGGING_DIR}}/.stop_logging"
169
169
 
170
170
  {log_msg_fn}
171
- {gsutil_cp_fn}
171
+ {gcloud_cp_fn}
172
172
 
173
173
  {log_cp}
174
174
  """)
@@ -182,14 +182,14 @@ _CONTINUOUS_LOGGING_CMD = textwrap.dedent("""\
182
182
  readonly LOGGING_DIR="{logging_dir}"
183
183
 
184
184
  {log_msg_fn}
185
- {gsutil_cp_fn}
185
+ {gcloud_cp_fn}
186
186
 
187
187
  # Make sure the logging work directory exists
188
188
  mkdir -p "${{LOGGING_DIR}}"
189
189
 
190
190
  # Prep the log filter script
191
191
  echo "${{{log_filter_var}}}" \
192
- | python -c '{python_decode_script}' \
192
+ | python3 -c '{python_decode_script}' \
193
193
  > "{log_filter_script_path}"
194
194
  chmod a+x "{log_filter_script_path}"
195
195
 
@@ -609,7 +609,7 @@ class GoogleBatchJobProvider(google_utils.GoogleJobProviderBase):
609
609
 
610
610
  continuous_logging_cmd = _CONTINUOUS_LOGGING_CMD.format(
611
611
  log_msg_fn=google_utils.LOG_MSG_FN,
612
- gsutil_cp_fn=google_utils.GSUTIL_CP_FN,
612
+ gcloud_cp_fn=google_utils.GCLOUD_CP_FN,
613
613
  log_filter_var=_LOG_FILTER_VAR,
614
614
  log_filter_script_path=_LOG_FILTER_SCRIPT_PATH,
615
615
  python_decode_script=google_utils.PYTHON_DECODE_SCRIPT,
@@ -623,7 +623,7 @@ class GoogleBatchJobProvider(google_utils.GoogleJobProviderBase):
623
623
 
624
624
  logging_cmd = _FINAL_LOGGING_CMD.format(
625
625
  log_msg_fn=google_utils.LOG_MSG_FN,
626
- gsutil_cp_fn=google_utils.GSUTIL_CP_FN,
626
+ gcloud_cp_fn=google_utils.GCLOUD_CP_FN,
627
627
  log_filter_var=_LOG_FILTER_VAR,
628
628
  log_filter_script_path=_LOG_FILTER_SCRIPT_PATH,
629
629
  python_decode_script=google_utils.PYTHON_DECODE_SCRIPT,
@@ -729,8 +729,8 @@ class GoogleBatchJobProvider(google_utils.GoogleJobProviderBase):
729
729
  '-c',
730
730
  google_utils.LOCALIZATION_CMD.format(
731
731
  log_msg_fn=google_utils.LOG_MSG_FN,
732
- recursive_cp_fn=google_utils.GSUTIL_RSYNC_FN,
733
- cp_fn=google_utils.GSUTIL_CP_FN,
732
+ recursive_cp_fn=google_utils.GCLOUD_RSYNC_FN,
733
+ cp_fn=google_utils.GCLOUD_CP_FN,
734
734
  cp_loop=google_utils.LOCALIZATION_LOOP,
735
735
  ),
736
736
  ],
@@ -778,8 +778,8 @@ class GoogleBatchJobProvider(google_utils.GoogleJobProviderBase):
778
778
  '-c',
779
779
  google_utils.LOCALIZATION_CMD.format(
780
780
  log_msg_fn=google_utils.LOG_MSG_FN,
781
- recursive_cp_fn=google_utils.GSUTIL_RSYNC_FN,
782
- cp_fn=google_utils.GSUTIL_CP_FN,
781
+ recursive_cp_fn=google_utils.GCLOUD_RSYNC_FN,
782
+ cp_fn=google_utils.GCLOUD_CP_FN,
783
783
  cp_loop=google_utils.DELOCALIZATION_LOOP,
784
784
  ),
785
785
  ],
@@ -68,9 +68,9 @@ def make_runtime_dirs_command(script_dir: str, tmp_dir: str,
68
68
  # pylint: enable=g-complex-comprehension
69
69
 
70
70
 
71
- # Action steps that interact with GCS need gsutil and Python.
71
+ # Action steps that interact with GCS need gcloud and Python.
72
72
  # Use the 'slim' variant of the cloud-sdk image as it is much smaller.
73
- CLOUD_SDK_IMAGE = 'gcr.io/google.com/cloudsdktool/cloud-sdk:294.0.0-slim'
73
+ CLOUD_SDK_IMAGE = 'gcr.io/google.com/cloudsdktool/cloud-sdk:499.0.0-slim'
74
74
 
75
75
  # Name of the data disk
76
76
  DATA_DISK_NAME = 'datadisk'
@@ -94,10 +94,10 @@ LOG_MSG_FN = textwrap.dedent("""\
94
94
  }
95
95
  """)
96
96
 
97
- # Define a bash function for "gsutil cp" to be used by the logging,
97
+ # Define a bash function for "gcloud storage cp" to be used by the logging,
98
98
  # localization, and delocalization actions.
99
- GSUTIL_CP_FN = textwrap.dedent("""\
100
- function gsutil_cp() {
99
+ GCLOUD_CP_FN = textwrap.dedent("""\
100
+ function gcloud_cp() {
101
101
  local src="${1}"
102
102
  local dst="${2}"
103
103
  local content_type="${3}"
@@ -105,33 +105,33 @@ GSUTIL_CP_FN = textwrap.dedent("""\
105
105
 
106
106
  local headers=""
107
107
  if [[ -n "${content_type}" ]]; then
108
- headers="-h Content-Type:${content_type}"
108
+ headers="--content-type=${content_type}"
109
109
  fi
110
110
 
111
111
  local user_project_flag=""
112
112
  if [[ -n "${user_project_name}" ]]; then
113
- user_project_flag="-u ${user_project_name}"
113
+ user_project_flag="--billing-project=${user_project_name}"
114
114
  fi
115
115
 
116
116
  local attempt
117
117
  for ((attempt = 0; attempt < 4; attempt++)); do
118
- log_info "gsutil ${headers} ${user_project_flag} -mq cp \"${src}\" \"${dst}\""
119
- if gsutil ${headers} ${user_project_flag} -mq cp "${src}" "${dst}"; then
118
+ log_info "gcloud storage cp --no-user-output-enabled ${headers} ${user_project_flag} \"${src}\" \"${dst}\""
119
+ if gcloud storage cp --no-user-output-enabled ${headers} ${user_project_flag} "${src}" "${dst}"; then
120
120
  return
121
121
  fi
122
122
  if (( attempt < 3 )); then
123
- log_warning "Sleeping 10s before the next attempt of failed gsutil command"
124
- log_warning "gsutil ${headers} ${user_project_flag} -mq cp \"${src}\" \"${dst}\""
123
+ log_warning "Sleeping 10s before the next attempt of failed gcloud command"
124
+ log_warning "gcloud storage cp --no-user-output-enabled ${headers} ${user_project_flag} \"${src}\" \"${dst}\""
125
125
  sleep 10s
126
126
  fi
127
127
  done
128
128
 
129
- log_error "gsutil ${headers} ${user_project_flag} -mq cp \"${src}\" \"${dst}\""
129
+ log_error "gcloud storage cp --no-user-output-enabled ${headers} ${user_project_flag} \"${src}\" \"${dst}\""
130
130
  exit 1
131
131
  }
132
132
  """)
133
133
 
134
- LOG_CP_FN = GSUTIL_CP_FN + textwrap.dedent("""\
134
+ LOG_CP_FN = GCLOUD_CP_FN + textwrap.dedent("""\
135
135
 
136
136
  function log_cp() {
137
137
  local src="${1}"
@@ -144,43 +144,43 @@ LOG_CP_FN = GSUTIL_CP_FN + textwrap.dedent("""\
144
144
  return
145
145
  fi
146
146
 
147
- # Copy the log files to a local temporary location so that our "gsutil cp" is never
147
+ # Copy the log files to a local temporary location so that our "gcloud storage cp" is never
148
148
  # executed on a file that is changing.
149
149
 
150
150
  local tmp_path="${tmp}/$(basename ${src})"
151
151
  cp "${src}" "${tmp_path}"
152
152
 
153
- gsutil_cp "${tmp_path}" "${dst}" "text/plain" "${user_project_name}"
153
+ gcloud_cp "${tmp_path}" "${dst}" "text/plain" "${user_project_name}"
154
154
  }
155
155
  """)
156
156
 
157
- # Define a bash function for "gsutil rsync" to be used by the logging,
157
+ # Define a bash function for "gcloud rsync" to be used by the logging,
158
158
  # localization, and delocalization actions.
159
- GSUTIL_RSYNC_FN = textwrap.dedent("""\
160
- function gsutil_rsync() {
159
+ GCLOUD_RSYNC_FN = textwrap.dedent("""\
160
+ function gcloud_rsync() {
161
161
  local src="${1}"
162
162
  local dst="${2}"
163
163
  local user_project_name="${3}"
164
164
 
165
165
  local user_project_flag=""
166
166
  if [[ -n "${user_project_name}" ]]; then
167
- user_project_flag="-u ${user_project_name}"
167
+ user_project_flag="--billing-project=${user_project_name}"
168
168
  fi
169
169
 
170
170
  local attempt
171
171
  for ((attempt = 0; attempt < 4; attempt++)); do
172
- log_info "gsutil ${user_project_flag} -mq rsync -r \"${src}\" \"${dst}\""
173
- if gsutil ${user_project_flag} -mq rsync -r "${src}" "${dst}"; then
172
+ log_info "gcloud storage rsync -r --no-user-output-enabled ${user_project_flag} \"${src}\" \"${dst}\""
173
+ if gcloud storage rsync -r --no-user-output-enabled ${user_project_flag} "${src}" "${dst}"; then
174
174
  return
175
175
  fi
176
176
  if (( attempt < 3 )); then
177
- log_warning "Sleeping 10s before the next attempt of failed gsutil command"
178
- log_warning "gsutil ${user_project_flag} -mq rsync -r \"${src}\" \"${dst}\""
177
+ log_warning "Sleeping 10s before the next attempt of failed gcloud command"
178
+ log_warning "gcloud storage rsync -r --no-user-output-enabled ${user_project_flag} \"${src}\" \"${dst}\""
179
179
  sleep 10s
180
180
  fi
181
181
  done
182
182
 
183
- log_error "gsutil ${user_project_flag} -mq rsync -r \"${src}\" \"${dst}\""
183
+ log_error "gcloud storage rsync -r --no-user-output-enabled ${user_project_flag} \"${src}\" \"${dst}\""
184
184
  exit 1
185
185
  }
186
186
  """)
@@ -198,9 +198,9 @@ LOCALIZATION_LOOP = textwrap.dedent("""\
198
198
 
199
199
  log_info "Localizing ${!INPUT_VAR}"
200
200
  if [[ "${!INPUT_RECURSIVE}" -eq "1" ]]; then
201
- gsutil_rsync "${!INPUT_SRC}" "${!INPUT_DST}" "${USER_PROJECT}"
201
+ gcloud_rsync "${!INPUT_SRC}" "${!INPUT_DST}" "${USER_PROJECT}"
202
202
  else
203
- gsutil_cp "${!INPUT_SRC}" "${!INPUT_DST}" "" "${USER_PROJECT}"
203
+ gcloud_cp "${!INPUT_SRC}" "${!INPUT_DST}" "" "${USER_PROJECT}"
204
204
  fi
205
205
  done
206
206
  """)
@@ -218,9 +218,9 @@ DELOCALIZATION_LOOP = textwrap.dedent("""\
218
218
 
219
219
  log_info "Delocalizing ${!OUTPUT_VAR}"
220
220
  if [[ "${!OUTPUT_RECURSIVE}" -eq "1" ]]; then
221
- gsutil_rsync "${!OUTPUT_SRC}" "${!OUTPUT_DST}" "${USER_PROJECT}"
221
+ gcloud_rsync "${!OUTPUT_SRC}" "${!OUTPUT_DST}" "${USER_PROJECT}"
222
222
  else
223
- gsutil_cp "${!OUTPUT_SRC}" "${!OUTPUT_DST}" "" "${USER_PROJECT}"
223
+ gcloud_cp "${!OUTPUT_SRC}" "${!OUTPUT_DST}" "" "${USER_PROJECT}"
224
224
  fi
225
225
  done
226
226
  """)
@@ -274,7 +274,7 @@ PREPARE_CMD = textwrap.dedent("""\
274
274
  {mk_runtime_dirs}
275
275
 
276
276
  echo "${{{script_var}}}" \
277
- | python -c '{python_decode_script}' \
277
+ | python3 -c '{python_decode_script}' \
278
278
  > "{script_path}"
279
279
  chmod a+x "{script_path}"
280
280
 
@@ -529,8 +529,8 @@ class GoogleV2JobProviderBase(google_utils.GoogleJobProviderBase):
529
529
  '-c',
530
530
  google_utils.LOCALIZATION_CMD.format(
531
531
  log_msg_fn=google_utils.LOG_MSG_FN,
532
- recursive_cp_fn=google_utils.GSUTIL_RSYNC_FN,
533
- cp_fn=google_utils.GSUTIL_CP_FN,
532
+ recursive_cp_fn=google_utils.GCLOUD_RSYNC_FN,
533
+ cp_fn=google_utils.GCLOUD_CP_FN,
534
534
  cp_loop=google_utils.LOCALIZATION_LOOP,
535
535
  ),
536
536
  ],
@@ -566,8 +566,8 @@ class GoogleV2JobProviderBase(google_utils.GoogleJobProviderBase):
566
566
  '-c',
567
567
  google_utils.LOCALIZATION_CMD.format(
568
568
  log_msg_fn=google_utils.LOG_MSG_FN,
569
- recursive_cp_fn=google_utils.GSUTIL_RSYNC_FN,
570
- cp_fn=google_utils.GSUTIL_CP_FN,
569
+ recursive_cp_fn=google_utils.GCLOUD_RSYNC_FN,
570
+ cp_fn=google_utils.GCLOUD_CP_FN,
571
571
  cp_loop=google_utils.DELOCALIZATION_LOOP,
572
572
  ),
573
573
  ],
@@ -712,9 +712,9 @@ class LocalJobProvider(base.JobProvider):
712
712
  elif logging_path.file_provider == job_model.P_GCS:
713
713
  mkdir_cmd = ''
714
714
  if user_project:
715
- cp_cmd = 'gsutil -u {} -mq cp'.format(user_project)
715
+ cp_cmd = 'gcloud storage cp --billing-project={}'.format(user_project)
716
716
  else:
717
- cp_cmd = 'gsutil -mq cp'
717
+ cp_cmd = 'gcloud storage cp'
718
718
  else:
719
719
  assert False
720
720
 
@@ -773,7 +773,7 @@ class LocalJobProvider(base.JobProvider):
773
773
  return '\n'.join(provider_commands)
774
774
 
775
775
  def _get_input_target_path(self, local_file_path):
776
- """Returns a directory or file path to be the target for "gsutil cp".
776
+ """Returns a directory or file path to be the target for "gcloud storage cp".
777
777
 
778
778
  If the filename contains a wildcard, then the target path must
779
779
  be a directory in order to ensure consistency whether the source pattern
@@ -784,7 +784,7 @@ class LocalJobProvider(base.JobProvider):
784
784
  local_file_path: A full path terminating in a file or a file wildcard.
785
785
 
786
786
  Returns:
787
- The path to use as the "gsutil cp" target.
787
+ The path to use as the "gcloud storage cp" target.
788
788
  """
789
789
 
790
790
  path, filename = os.path.split(local_file_path)
@@ -806,21 +806,34 @@ class LocalJobProvider(base.JobProvider):
806
806
 
807
807
  commands.append('mkdir -p "%s"' % os.path.dirname(local_file_path))
808
808
 
809
- if i.file_provider in [job_model.P_LOCAL, job_model.P_GCS]:
810
- # The semantics that we expect here are implemented consistently in
811
- # "gsutil cp", and are a bit different than "cp" when it comes to
812
- # wildcard handling, so use it for both local and GCS:
813
- #
814
- # - `cp path/* dest/` will error if "path" has subdirectories.
815
- # - `cp "path/*" "dest/"` will fail (it expects wildcard expansion
816
- # to come from shell).
809
+ if i.file_provider == job_model.P_GCS:
810
+ # `cp path/* dest/` will error if "path" has subdirectories, and
811
+ # `cp "path/*" "dest/"` will fail (it expects wildcard expansion
812
+ # to come from shell), so use "gcloud storage cp" instead.
817
813
  if user_project:
818
- command = 'gsutil -u %s -mq cp "%s" "%s"' % (
814
+ command = 'gcloud storage cp --billing-project=%s "%s" "%s"' % (
819
815
  user_project, source_file_path, dest_file_path)
820
816
  else:
821
- command = 'gsutil -mq cp "%s" "%s"' % (source_file_path,
817
+ command = 'gcloud storage cp "%s" "%s"' % (source_file_path,
822
818
  dest_file_path)
823
819
  commands.append(command)
820
+ elif i.file_provider == job_model.P_LOCAL:
821
+ # "gcloud storage cp" does not support local-to-local copies, so use
822
+ # rsync (without "-r", since this path is non-recursive) instead.
823
+ # It matches the wildcard semantics we need: like the old "gsutil
824
+ # cp", it silently skips subdirectories rather than erroring like
825
+ # plain "cp" does. rsync does not expand a quoted wildcard itself,
826
+ # so for a wildcard filename, only the directory portion is quoted,
827
+ # leaving the wildcard for the shell to expand. A non-wildcard
828
+ # filename is quoted as a whole so that spaces in it are preserved
829
+ # as a single rsync argument.
830
+ source_dir, source_filename = os.path.split(source_file_path)
831
+ if '*' in source_filename:
832
+ command = 'rsync "%s"/%s "%s"' % (source_dir, source_filename,
833
+ dest_file_path)
834
+ else:
835
+ command = 'rsync "%s" "%s"' % (source_file_path, dest_file_path)
836
+ commands.append(command)
824
837
 
825
838
  return '\n'.join(commands)
826
839
 
@@ -865,13 +878,25 @@ class LocalJobProvider(base.JobProvider):
865
878
  if o.file_provider == job_model.P_LOCAL:
866
879
  commands.append('mkdir -p "%s"' % dest_path)
867
880
 
868
- # Use gsutil even for local files (explained in _localize_inputs_command).
869
- if o.file_provider in [job_model.P_LOCAL, job_model.P_GCS]:
881
+ if o.file_provider == job_model.P_GCS:
870
882
  if user_project:
871
- command = 'gsutil -u %s -mq cp "%s" "%s"' % (user_project, local_path,
883
+ command = 'gcloud storage cp --billing-project=%s "%s" "%s"' % (user_project, local_path,
872
884
  dest_path)
873
885
  else:
874
- command = 'gsutil -mq cp "%s" "%s"' % (local_path, dest_path)
886
+ command = 'gcloud storage cp "%s" "%s"' % (local_path, dest_path)
887
+ commands.append(command)
888
+ elif o.file_provider == job_model.P_LOCAL:
889
+ # "gcloud storage cp" does not support local-to-local copies (see
890
+ # _localize_inputs_command), so use rsync instead. As there, only
891
+ # quote the directory portion for a wildcard filename so the shell
892
+ # can expand it; a non-wildcard filename is quoted as a whole so
893
+ # that spaces in it are preserved as a single rsync argument.
894
+ local_dir, local_filename = os.path.split(local_path)
895
+ if '*' in local_filename:
896
+ command = 'rsync "%s"/%s "%s"' % (local_dir, local_filename,
897
+ dest_path)
898
+ else:
899
+ command = 'rsync "%s" "%s"' % (local_path, dest_path)
875
900
  commands.append(command)
876
901
 
877
902
  return '\n'.join(commands)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dsub
3
- Version: 0.5.2
3
+ Version: 0.5.4
4
4
  Summary: A command-line tool that makes it easy to submit and run batch scripts in the cloud
5
5
  Home-page: https://github.com/DataBiosphere/dsub
6
6
  Author: Verily
@@ -108,7 +108,7 @@ While not used directly by `dsub` for the `google-batch` provider, you are likel
108
108
  Cloud SDK](https://cloud.google.com/sdk/).
109
109
 
110
110
  If you will be using the `local` provider for faster job development,
111
- you *will* need to install the Google Cloud SDK, which uses `gsutil` to ensure
111
+ you *will* need to install the Google Cloud SDK, which uses `gcloud storage` to ensure
112
112
  file operation semantics consistent with the Google `dsub` providers.
113
113
 
114
114
  1. [Install the Google Cloud SDK](https://cloud.google.com/sdk/)
@@ -234,10 +234,10 @@ The steps for getting started differ slightly as indicated in the steps below:
234
234
 
235
235
  The dsub logs and output files will be written to a bucket. Create a
236
236
  bucket using the [storage browser](https://console.cloud.google.com/storage/browser?project=)
237
- or run the command-line utility [gsutil](https://cloud.google.com/storage/docs/gsutil),
237
+ or run the command-line utility [gcloud storage](https://cloud.google.com/sdk/gcloud/reference/storage),
238
238
  included in the Cloud SDK.
239
239
 
240
- gsutil mb gs://my-bucket
240
+ gcloud storage buckets create gs://my-bucket
241
241
 
242
242
  Change `my-bucket` to a unique name that follows the
243
243
  [bucket-naming conventions](https://cloud.google.com/storage/docs/bucket-naming).
@@ -267,7 +267,7 @@ The steps for getting started differ slightly as indicated in the steps below:
267
267
 
268
268
  1. View the output file.
269
269
 
270
- gsutil cat gs://my-bucket/output/out.txt
270
+ gcloud storage cat gs://my-bucket/output/out.txt
271
271
 
272
272
  ## Backend providers
273
273
 
@@ -403,9 +403,8 @@ by:
403
403
 
404
404
  To upload the files to Google Cloud Storage, you can use the
405
405
  [storage browser](https://console.cloud.google.com/storage/browser?project=) or
406
- [gsutil](https://cloud.google.com/storage/docs/gsutil). You can also run on data
407
- that’s public or shared with your service account, an email address that you
408
- can find in the [Google Cloud Console](https://console.cloud.google.com).
406
+ [gcloud storage](https://cloud.google.com/sdk/gcloud/reference/storage).
407
+ You can also run on data that’s public or shared with your service account, an email address that you can find in the [Google Cloud Console](https://console.cloud.google.com).
409
408
 
410
409
  #### Files
411
410
 
@@ -780,7 +779,9 @@ of the service account will be `sa-name@project-id.iam.gserviceaccount.com`.
780
779
 
781
780
  2. Grant IAM access on buckets, etc. to the service account.
782
781
 
783
- gsutil iam ch serviceAccount:sa-name@project-id.iam.gserviceaccount.com:roles/storage.objectAdmin gs://bucket-name
782
+ gcloud storage buckets add-iam-policy-binding gs://bucket-name \
783
+ --member=serviceAccount:sa-name@project-id.iam.gserviceaccount.com \
784
+ --role=roles/storage.objectAdmin
784
785
 
785
786
  3. Update your `dsub` command to include `--service-account`
786
787
 
@@ -56,7 +56,7 @@ next_job = test.run_dsub([
56
56
 
57
57
  print('\nChecking output...')
58
58
 
59
- RESULT = test_util.gsutil_cat(TEST_FILE_PATH_2)
59
+ RESULT = test_util.gcloud_cat(TEST_FILE_PATH_2)
60
60
  if 'hello world' not in RESULT:
61
61
  print('Output file does not match expected', file=sys.stderr)
62
62
  sys.exit(1)
@@ -73,7 +73,7 @@ VAR4=VAL4
73
73
  VAR5=VAL5
74
74
  """.lstrip()
75
75
 
76
- RESULT = test_util.gsutil_cat(test.STDOUT_LOG)
76
+ RESULT = test_util.gcloud_cat(test.STDOUT_LOG)
77
77
  if not test_util.diff(RESULT_EXPECTED, RESULT):
78
78
  print('Output file does not match expected')
79
79
  sys.exit(1)
@@ -104,7 +104,7 @@ for i in range(TASKS_COUNT):
104
104
  '--output OUTPUT_PATH')
105
105
  OUTPUT_FILE = '%s/%s.md5' % (OUTPUT_PATH[:-len('/*.md5')],
106
106
  os.path.basename(INPUT_BAM))
107
- RESULT = test_util.gsutil_cat(OUTPUT_FILE)
107
+ RESULT = test_util.gcloud_cat(OUTPUT_FILE)
108
108
 
109
109
  if not test_util.diff(RESULT_EXPECTED.strip(), RESULT.strip()):
110
110
  print('Output file does not match expected')
@@ -119,7 +119,7 @@ for i in range(TASKS_COUNT):
119
119
  RESULT_EXPECTED = POPULATION_MD5
120
120
  for i in range(TASKS_COUNT):
121
121
  OUTPUT_FILE = '%s/TASK_%s.md5' % (test.OUTPUTS, (i + 1))
122
- RESULT = test_util.gsutil_cat(OUTPUT_FILE)
122
+ RESULT = test_util.gcloud_cat(OUTPUT_FILE)
123
123
 
124
124
  if not test_util.diff(RESULT_EXPECTED.strip(), RESULT.strip()):
125
125
  print('Output file does not match expected')
@@ -100,9 +100,9 @@ else:
100
100
  print(" Bucket detected as: %s" % DSUB_BUCKET)
101
101
 
102
102
  print(" Checking if bucket exists")
103
- if not test_util.gsutil_ls_check("gs://%s" % DSUB_BUCKET):
103
+ if not test_util.gcloud_ls_check("gs://%s" % DSUB_BUCKET):
104
104
  print("Bucket does not exist: %s" % DSUB_BUCKET, file=sys.stderr)
105
- print("Create the bucket with \"gsutil mb\".", file=sys.stderr)
105
+ print("Create the bucket with \"gcloud storage buckets create\".", file=sys.stderr)
106
106
  sys.exit(1)
107
107
 
108
108
  # Set standard LOGGING, INPUTS, and OUTPUTS values
@@ -130,10 +130,10 @@ print("Input path: %s" % INPUTS)
130
130
  print("Output path: %s" % OUTPUTS)
131
131
 
132
132
  print(" Checking if remote test files already exists")
133
- if test_util.gsutil_ls_check("%s/**" % TEST_GCS_ROOT):
133
+ if test_util.gcloud_ls_check("%s/**" % TEST_GCS_ROOT):
134
134
  print("Test files exist: %s" % TEST_GCS_ROOT, file=sys.stderr)
135
135
  print("Remove contents:", file=sys.stderr)
136
- print(" gsutil -m rm %s/**" % TEST_GCS_ROOT, file=sys.stderr)
136
+ print(" gcloud storage rm %s/**" % TEST_GCS_ROOT, file=sys.stderr)
137
137
  sys.exit(1)
138
138
 
139
139
  if TASKS_FILE:
@@ -29,13 +29,13 @@ def to_string(stdoutbytes):
29
29
  return stdoutbytes.decode(encoding)
30
30
 
31
31
 
32
- def gsutil_ls_check(path):
33
- return not subprocess.call('gsutil ls "%s" 2>/dev/null' % path, shell=True)
32
+ def gcloud_ls_check(path):
33
+ return not subprocess.call('gcloud storage ls "%s" 2>/dev/null' % path, shell=True)
34
34
 
35
35
 
36
- def gsutil_cat(path):
36
+ def gcloud_cat(path):
37
37
  return to_string(
38
- subprocess.check_output('gsutil cat "%s"' % path, shell=True))
38
+ subprocess.check_output('gcloud storage cat "%s"' % path, shell=True))
39
39
 
40
40
 
41
41
  def diff(str1, str2):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes