From cf157b2ca4dcfe4c158751a751210b68ad4c17b2 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 31 Oct 2019 15:17:09 -0400 Subject: [PATCH 1/4] tests: add centralized VPCSC config detection Toward #9580. --- test_utils/test_utils/vpcsc_config.py | 92 +++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 test_utils/test_utils/vpcsc_config.py diff --git a/test_utils/test_utils/vpcsc_config.py b/test_utils/test_utils/vpcsc_config.py new file mode 100644 index 000000000000..b3495585ed3b --- /dev/null +++ b/test_utils/test_utils/vpcsc_config.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2019 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +import pytest + + +INSIDE_VPCSC_ENVVAR = "GOOGLE_CLOUD_TESTS_IN_VPCSC" +PROJECT_INSIDE_ENVVAR = "PROJECT_ID" +PROJECT_OUTSIDE_ENVVAR = "GOOGLE_CLOUD_TESTS_VPCSC_OUTSIDE_PERIMETER_PROJECT" + + +class VPCSCTestConfig(object): + """System test utility for VPCSC detection. + + See: https://cloud.google.com/vpc-service-controls/docs/ + """ + + @property + def inside_vpcsc(self): + """Is the test environment inside VPCSC. + + Returns: + bool: true if the environment is inside VPCSC, else false. + """ + value = os.environ.get(INSIDE_VPCSC_ENVVAR, "true").lower() + return value == "true" + + @property + def project_inside(self): + """Project ID for testing outside access. + + Returns: + str: project ID used for testing outside access; None if undefined. + """ + return os.environ.get(PROJECT_INSIDE_ENVVAR, None) + + @property + def project_outside(self): + """Project ID for testing inside access. + + Returns: + str: project ID used for testing inside access; None if undefined. + """ + return os.environ.get(PROJECT_OUTSIDE_ENVVAR, None) + + def skip_if_running_inside_vpcsc(self, testcase): + """Test decorator: skip if running inside VPCSC.""" + reason = "Running inside VPCSC" + skip = pytest.mark.skipif(self.inside_vpcsc, reason=reason) + return skip(testcase) + + def skip_if_running_outside_vpcsc(self, testcase): + """Test decorator: skip if running outside VPCSC.""" + reason = "Running outside VPCSC" + skip = pytest.mark.skipif(not self.inside_vpcsc, reason=reason) + return skip(testcase) + + def skip_if_inside_vpcsc(self, testcase): + """Test decorator: skip if inside project env var not set.""" + reason = "Running inside VPCSC" + skip = pytest.mark.skipif(self.inside_vpcsc, reason=reason) + return skip(testcase) + + def skip_if_no_inside_project(self, testcase): + """Test decorator: skip if inside project env var not set.""" + reason = "Missing envvar: {}".format(PROJECT_INSIDE_ENVVAR) + skip = pytest.mark.skipif(self.project_inside is None, reason=reason) + return skip(testcase) + + def skip_if_no_outside_project(self, testcase): + """Test decorator: skip if outside project env var not set.""" + reason = "Missing envvar: {}".format(PROJECT_OUTSIDE_ENVVAR) + skip = pytest.mark.skipif(self.project_outside is None, reason=reason) + return skip(testcase) + + +vpcsc_config = VPCSCTestConfig() From 47dbd648b5041c5e717b1b69352850191e5a111b Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 31 Oct 2019 15:22:08 -0400 Subject: [PATCH 2/4] tests(asset): don't force VPCSC env vars in noxfile Toward #9580. --- asset/noxfile.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/asset/noxfile.py b/asset/noxfile.py index 393f4b64a33c..3d92df19084f 100644 --- a/asset/noxfile.py +++ b/asset/noxfile.py @@ -118,20 +118,11 @@ def system(session): session.install("-e", "../test_utils/") session.install("-e", ".") - # Additional setup for VPCSC system tests - env = { - "PROJECT_ID": os.environ.get("PROJECT_ID"), - "GOOGLE_CLOUD_TESTS_VPCSC_OUTSIDE_PERIMETER_PROJECT": "secure-gcp-test-project-4", - "GOOGLE_CLOUD_TESTS_IN_VPCSC": "true", - } - # Run py.test against the system tests. if system_test_exists: - session.run("py.test", "--quiet", system_test_path, env=env, *session.posargs) + session.run("py.test", "--quiet", system_test_path, *session.posargs) if system_test_folder_exists: - session.run( - "py.test", "--quiet", system_test_folder_path, env=env, *session.posargs - ) + session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) @nox.session(python="3.7") From 487ffc67613aa9ac0b7e624cd9d5fad3b707b8ba Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 31 Oct 2019 15:22:50 -0400 Subject: [PATCH 3/4] tests(asset): use standard VPCSC config detection --- asset/tests/system/test_vpcsc.py | 54 +++++++++++--------------------- 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/asset/tests/system/test_vpcsc.py b/asset/tests/system/test_vpcsc.py index e3336bfe4f4f..fdc784ee433d 100644 --- a/asset/tests/system/test_vpcsc.py +++ b/asset/tests/system/test_vpcsc.py @@ -16,18 +16,11 @@ # flake8: noqa -import os -import pytest - from google.api_core import exceptions from google.cloud import asset_v1 from google.cloud.asset_v1 import enums -PROJECT_INSIDE = os.environ.get("PROJECT_ID", None) -PROJECT_OUTSIDE = os.environ.get( - "GOOGLE_CLOUD_TESTS_VPCSC_OUTSIDE_PERIMETER_PROJECT", None -) -IS_INSIDE_VPCSC = os.environ.get("GOOGLE_CLOUD_TESTS_IN_VPCSC", "true") +from test_utils.vpcsc_config import vpcsc_config class TestVPCServiceControl(object): @@ -38,51 +31,40 @@ def _is_rejected(call): except exceptions.PermissionDenied as e: return e.message == "Request is prohibited by organization's policy" except: - pass + pass # XXX raise? return False - @staticmethod - def _do_test(delayed_inside, delayed_outside): - if IS_INSIDE_VPCSC.lower() == "true": - assert TestVPCServiceControl._is_rejected(delayed_outside) - assert not (TestVPCServiceControl._is_rejected(delayed_inside)) + def _do_test(self, delayed_inside, delayed_outside): + if vpcsc_config.inside_vpcsc: + assert self._is_rejected(delayed_outside) + assert not self._is_rejected(delayed_inside) else: - assert not (TestVPCServiceControl._is_rejected(delayed_outside)) - assert TestVPCServiceControl._is_rejected(delayed_inside) + assert not self._is_rejected(delayed_outside) + assert self._is_rejected(delayed_inside) - @pytest.mark.skipif( - PROJECT_INSIDE is None, reason="Missing environment variable: PROJECT_ID" - ) - @pytest.mark.skipif( - PROJECT_OUTSIDE is None, - reason="Missing environment variable: GOOGLE_CLOUD_TESTS_VPCSC_OUTSIDE_PERIMETER_PROJECT", - ) + @vpcsc_config.skip_if_no_inside_project + @vpcsc_config.skip_if_no_outside_project def test_export_assets(self): client = asset_v1.AssetServiceClient() output_config = {} - parent_inside = "projects/" + PROJECT_INSIDE + parent_inside = "projects/" + vpcsc_config.project_inside delayed_inside = lambda: client.export_assets(parent_inside, output_config) - parent_outside = "projects/" + PROJECT_OUTSIDE + parent_outside = "projects/" + vpcsc_config.project_outside delayed_outside = lambda: client.export_assets(parent_outside, output_config) - TestVPCServiceControl._do_test(delayed_inside, delayed_outside) + self._do_test(delayed_inside, delayed_outside) - @pytest.mark.skipif( - PROJECT_INSIDE is None, reason="Missing environment variable: PROJECT_ID" - ) - @pytest.mark.skipif( - PROJECT_OUTSIDE is None, - reason="Missing environment variable: GOOGLE_CLOUD_TESTS_VPCSC_OUTSIDE_PERIMETER_PROJECT", - ) + @vpcsc_config.skip_if_no_inside_project + @vpcsc_config.skip_if_no_outside_project def test_batch_get_assets_history(self): client = asset_v1.AssetServiceClient() content_type = enums.ContentType.CONTENT_TYPE_UNSPECIFIED read_time_window = {} - parent_inside = "projects/" + PROJECT_INSIDE + parent_inside = "projects/" + vpcsc_config.project_inside delayed_inside = lambda: client.batch_get_assets_history( parent_inside, content_type, read_time_window ) - parent_outside = "projects/" + PROJECT_OUTSIDE + parent_outside = "projects/" + vpcsc_config.project_outside delayed_outside = lambda: client.batch_get_assets_history( parent_outside, content_type, read_time_window ) - TestVPCServiceControl._do_test(delayed_inside, delayed_outside) + self._do_test(delayed_inside, delayed_outside) From 45294fc08b8696f19a8f52298e470056446c39f3 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 31 Oct 2019 15:40:59 -0400 Subject: [PATCH 4/4] fix: blacken --- asset/tests/system/test_vpcsc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asset/tests/system/test_vpcsc.py b/asset/tests/system/test_vpcsc.py index fdc784ee433d..39a6ba61be7a 100644 --- a/asset/tests/system/test_vpcsc.py +++ b/asset/tests/system/test_vpcsc.py @@ -31,7 +31,7 @@ def _is_rejected(call): except exceptions.PermissionDenied as e: return e.message == "Request is prohibited by organization's policy" except: - pass # XXX raise? + pass # XXX raise? return False def _do_test(self, delayed_inside, delayed_outside):