Skip to content

Commit 7dfeb62

Browse files
authored
feat: make tests run against environments other than prod (#883)
Made changes that override api endpoint information while triggering builds from kokoro . All tests against prod are still successful. Some system tests are currently incompatible with nonprod environments and hence are marked to be skipped if endpoint is being overriden.
1 parent 7c8a178 commit 7dfeb62

File tree

10 files changed

+93
-17
lines changed

10 files changed

+93
-17
lines changed

.kokoro/build.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json
3333
# Setup project id.
3434
export PROJECT_ID=$(cat "${KOKORO_GFILE_DIR}/project-id.json")
3535

36+
# Export variable to override api endpoint
37+
export API_ENDPOINT_OVERRIDE
38+
39+
# Export variable to override api endpoint version
40+
export API_VERSION_OVERRIDE
41+
42+
# Export dual region locations
43+
export DUAL_REGION_LOC_1
44+
export DUAL_REGION_LOC_2
45+
3646
# Remove old nox
3747
python3 -m pip uninstall --yes --quiet nox-automation
3848

google/cloud/storage/_helpers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,14 @@
3333
STORAGE_EMULATOR_ENV_VAR = "STORAGE_EMULATOR_HOST"
3434
"""Environment variable defining host for Storage emulator."""
3535

36-
_DEFAULT_STORAGE_HOST = "https://storage.googleapis.com"
36+
_DEFAULT_STORAGE_HOST = os.getenv(
37+
"API_ENDPOINT_OVERRIDE", "https://storage.googleapis.com"
38+
)
3739
"""Default storage host for JSON API."""
3840

41+
_API_VERSION = os.getenv("API_VERSION_OVERRIDE", "v1")
42+
"""API version of the default storage host"""
43+
3944
_BASE_STORAGE_URI = "storage.googleapis.com"
4045
"""Base request endpoint URI for JSON API."""
4146

google/cloud/storage/_http.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
"""Create / interact with Google Cloud Storage connections."""
1616

1717
import functools
18-
1918
from google.cloud import _http
2019
from google.cloud.storage import __version__
2120
from google.cloud.storage import _helpers
@@ -35,7 +34,7 @@ class Connection(_http.JSONConnection):
3534
:param api_endpoint: (Optional) api endpoint to use.
3635
"""
3736

38-
DEFAULT_API_ENDPOINT = "https://storage.googleapis.com"
37+
DEFAULT_API_ENDPOINT = _helpers._DEFAULT_STORAGE_HOST
3938
DEFAULT_API_MTLS_ENDPOINT = "https://storage.mtls.googleapis.com"
4039

4140
def __init__(self, client, client_info=None, api_endpoint=None):
@@ -52,7 +51,7 @@ def __init__(self, client, client_info=None, api_endpoint=None):
5251
if agent_version not in self._client_info.user_agent:
5352
self._client_info.user_agent += f" {agent_version} "
5453

55-
API_VERSION = "v1"
54+
API_VERSION = _helpers._API_VERSION
5655
"""The version of the API, used in building the API call's URL."""
5756

5857
API_URL_TEMPLATE = "{api_base_url}/storage/{api_version}{path}"

google/cloud/storage/blob.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
from google.cloud.storage._signing import generate_signed_url_v2
6161
from google.cloud.storage._signing import generate_signed_url_v4
6262
from google.cloud.storage._helpers import _NUM_RETRIES_MESSAGE
63+
from google.cloud.storage._helpers import _DEFAULT_STORAGE_HOST
64+
from google.cloud.storage._helpers import _API_VERSION
6365
from google.cloud.storage.acl import ACL
6466
from google.cloud.storage.acl import ObjectACL
6567
from google.cloud.storage.constants import _DEFAULT_TIMEOUT
@@ -78,10 +80,12 @@
7880
from google.cloud.storage.fileio import BlobWriter
7981

8082

81-
_API_ACCESS_ENDPOINT = "https://storage.googleapis.com"
83+
_API_ACCESS_ENDPOINT = _DEFAULT_STORAGE_HOST
8284
_DEFAULT_CONTENT_TYPE = "application/octet-stream"
83-
_DOWNLOAD_URL_TEMPLATE = "{hostname}/download/storage/v1{path}?alt=media"
84-
_BASE_UPLOAD_TEMPLATE = "{hostname}/upload/storage/v1{bucket_path}/o?uploadType="
85+
_DOWNLOAD_URL_TEMPLATE = "{hostname}/download/storage/{api_version}{path}?alt=media"
86+
_BASE_UPLOAD_TEMPLATE = (
87+
"{hostname}/upload/storage/{api_version}{bucket_path}/o?uploadType="
88+
)
8589
_MULTIPART_URL_TEMPLATE = _BASE_UPLOAD_TEMPLATE + "multipart"
8690
_RESUMABLE_URL_TEMPLATE = _BASE_UPLOAD_TEMPLATE + "resumable"
8791
# NOTE: "acl" is also writeable but we defer ACL management to
@@ -823,7 +827,9 @@ def _get_download_url(
823827
name_value_pairs = []
824828
if self.media_link is None:
825829
hostname = _get_host_name(client._connection)
826-
base_url = _DOWNLOAD_URL_TEMPLATE.format(hostname=hostname, path=self.path)
830+
base_url = _DOWNLOAD_URL_TEMPLATE.format(
831+
hostname=hostname, path=self.path, api_version=_API_VERSION
832+
)
827833
if self.generation is not None:
828834
name_value_pairs.append(("generation", f"{self.generation:d}"))
829835
else:
@@ -1838,7 +1844,7 @@ def _do_multipart_upload(
18381844

18391845
hostname = _get_host_name(client._connection)
18401846
base_url = _MULTIPART_URL_TEMPLATE.format(
1841-
hostname=hostname, bucket_path=self.bucket.path
1847+
hostname=hostname, bucket_path=self.bucket.path, api_version=_API_VERSION
18421848
)
18431849
name_value_pairs = []
18441850

@@ -2025,7 +2031,7 @@ def _initiate_resumable_upload(
20252031

20262032
hostname = _get_host_name(client._connection)
20272033
base_url = _RESUMABLE_URL_TEMPLATE.format(
2028-
hostname=hostname, bucket_path=self.bucket.path
2034+
hostname=hostname, bucket_path=self.bucket.path, api_version=_API_VERSION
20292035
)
20302036
name_value_pairs = []
20312037

noxfile.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ def system(session):
111111
"""Run the system test suite."""
112112
system_test_path = os.path.join("tests", "system.py")
113113
system_test_folder_path = os.path.join("tests", "system")
114+
rerun_count = 0
114115

115116
# Check the value of `RUN_SYSTEM_TESTS` env var. It defaults to true.
116117
if os.environ.get("RUN_SYSTEM_TESTS", "true") == "false":
@@ -121,6 +122,12 @@ def system(session):
121122
# mTLS tests requires pyopenssl.
122123
if os.environ.get("GOOGLE_API_USE_CLIENT_CERTIFICATE", "") == "true":
123124
session.install("pyopenssl")
125+
# Check if endpoint is being overriden for rerun_count
126+
if (
127+
os.getenv("API_ENDPOINT_OVERRIDE", "https://storage.googleapis.com")
128+
!= "https://storage.googleapis.com"
129+
):
130+
rerun_count = 3
124131

125132
system_test_exists = os.path.exists(system_test_path)
126133
system_test_folder_exists = os.path.exists(system_test_folder_path)
@@ -138,7 +145,7 @@ def system(session):
138145
# 2021-05-06: defer installing 'google-cloud-*' to after this package,
139146
# in order to work around Python 2.7 googolapis-common-protos
140147
# issue.
141-
session.install("mock", "pytest", "-c", constraints_path)
148+
session.install("mock", "pytest", "pytest-rerunfailures", "-c", constraints_path)
142149
session.install("-e", ".", "-c", constraints_path)
143150
session.install(
144151
"google-cloud-testutils",
@@ -151,9 +158,21 @@ def system(session):
151158

152159
# Run py.test against the system tests.
153160
if system_test_exists:
154-
session.run("py.test", "--quiet", system_test_path, *session.posargs)
161+
session.run(
162+
"py.test",
163+
"--quiet",
164+
"--reruns={}".format(rerun_count),
165+
system_test_path,
166+
*session.posargs,
167+
)
155168
if system_test_folder_exists:
156-
session.run("py.test", "--quiet", system_test_folder_path, *session.posargs)
169+
session.run(
170+
"py.test",
171+
"--quiet",
172+
"--reruns={}".format(rerun_count),
173+
system_test_folder_path,
174+
*session.posargs,
175+
)
157176

158177

159178
@nox.session(python=CONFORMANCE_TEST_PYTHON_VERSIONS)

tests/system/_helpers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from test_utils.retry import RetryErrors
2121
from test_utils.retry import RetryInstanceState
2222
from test_utils.system import unique_resource_id
23+
from google.cloud.storage._helpers import _DEFAULT_STORAGE_HOST
2324

2425
retry_429 = RetryErrors(exceptions.TooManyRequests)
2526
retry_429_harder = RetryErrors(exceptions.TooManyRequests, max_tries=10)
@@ -31,6 +32,7 @@
3132
user_project = os.environ.get("GOOGLE_CLOUD_TESTS_USER_PROJECT")
3233
testing_mtls = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE") == "true"
3334
signing_blob_content = b"This time for sure, Rocky!"
35+
is_api_endpoint_override = _DEFAULT_STORAGE_HOST != "https://storage.googleapis.com"
3436

3537

3638
def _bad_copy(bad_request):

tests/system/test__signing.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import hashlib
1818
import os
1919
import time
20-
20+
import pytest
2121
import requests
2222

2323
from google.api_core import path_template
@@ -41,7 +41,11 @@ def _create_signed_list_blobs_url_helper(
4141
expiration = _morph_expiration(version, expiration)
4242

4343
signed_url = bucket.generate_signed_url(
44-
expiration=expiration, method=method, client=client, version=version
44+
expiration=expiration,
45+
method=method,
46+
client=client,
47+
version=version,
48+
api_access_endpoint=_helpers._DEFAULT_STORAGE_HOST,
4549
)
4650

4751
response = requests.get(signed_url)
@@ -371,6 +375,10 @@ def test_create_signed_resumable_upload_url_v4(storage_client, signing_bucket, n
371375
)
372376

373377

378+
@pytest.mark.skipif(
379+
_helpers.is_api_endpoint_override,
380+
reason="Test does not yet support endpoint override",
381+
)
374382
def test_generate_signed_post_policy_v4(
375383
storage_client, buckets_to_delete, blobs_to_delete, service_account, no_mtls
376384
):

tests/system/test_blob.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ def test_large_file_write_from_stream_w_failed_checksum(
9797
assert not blob.exists()
9898

9999

100+
@pytest.mark.skipif(
101+
_helpers.is_api_endpoint_override,
102+
reason="Test does not yet support endpoint override",
103+
)
100104
def test_large_file_write_from_stream_w_encryption_key(
101105
storage_client,
102106
shared_bucket,

tests/system/test_bucket.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
# limitations under the License.
1414

1515
import datetime
16-
1716
import pytest
1817

1918
from google.api_core import exceptions
@@ -124,6 +123,10 @@ def test_bucket_lifecycle_rules(storage_client, buckets_to_delete):
124123
assert list(bucket.lifecycle_rules) == []
125124

126125

126+
@pytest.mark.skipif(
127+
_helpers.is_api_endpoint_override,
128+
reason="Test does not yet support endpoint override",
129+
)
127130
def test_bucket_update_labels(storage_client, buckets_to_delete):
128131
bucket_name = _helpers.unique_name("update-labels")
129132
bucket = _helpers.retry_429_503(storage_client.create_bucket)(bucket_name)
@@ -797,6 +800,10 @@ def test_bucket_lock_retention_policy(
797800
bucket.patch()
798801

799802

803+
@pytest.mark.skipif(
804+
_helpers.is_api_endpoint_override,
805+
reason="Test does not yet support endpoint override",
806+
)
800807
def test_new_bucket_w_ubla(
801808
storage_client,
802809
buckets_to_delete,
@@ -966,6 +973,10 @@ def test_new_bucket_created_w_enforced_pap(
966973
assert not bucket.iam_configuration.uniform_bucket_level_access_enabled
967974

968975

976+
@pytest.mark.skipif(
977+
_helpers.is_api_endpoint_override,
978+
reason="Test does not yet support endpoint override",
979+
)
969980
def test_new_bucket_with_rpo(
970981
storage_client,
971982
buckets_to_delete,

tests/system/test_client.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import io
1616
import re
17+
import os
1718
import tempfile
1819

1920
import pytest
@@ -23,9 +24,15 @@
2324
from . import _helpers
2425

2526

27+
dual_data_loc_1 = os.getenv("DUAL_REGION_LOC_1", "US-EAST1")
28+
dual_data_loc_2 = os.getenv("DUAL_REGION_LOC_2", "US-WEST1")
2629
public_bucket = "gcp-public-data-landsat"
2730

2831

32+
@pytest.mark.skipif(
33+
_helpers.is_api_endpoint_override,
34+
reason="Test does not yet support endpoint override",
35+
)
2936
@vpcsc_config.skip_if_inside_vpcsc
3037
def test_anonymous_client_access_to_public_bucket():
3138
from google.cloud.storage.client import Client
@@ -40,6 +47,10 @@ def test_anonymous_client_access_to_public_bucket():
4047
_helpers.retry_429_503(blob.download_to_file)(stream)
4148

4249

50+
@pytest.mark.skipif(
51+
_helpers.is_api_endpoint_override,
52+
reason="Test does not yet support endpoint override",
53+
)
4354
def test_get_service_account_email(storage_client, service_account):
4455
domain = "gs-project-accounts.iam.gserviceaccount.com"
4556
email = storage_client.get_service_account_email()
@@ -69,7 +80,8 @@ def test_create_bucket_dual_region(storage_client, buckets_to_delete):
6980

7081
new_bucket_name = _helpers.unique_name("dual-region-bucket")
7182
location = "US"
72-
data_locations = ["US-EAST1", "US-WEST1"]
83+
84+
data_locations = [dual_data_loc_1, dual_data_loc_2]
7385

7486
with pytest.raises(exceptions.NotFound):
7587
storage_client.get_bucket(new_bucket_name)

0 commit comments

Comments
 (0)