From cf157b2ca4dcfe4c158751a751210b68ad4c17b2 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 31 Oct 2019 15:17:09 -0400 Subject: [PATCH 1/2] 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 b4a9475740e5e5b21b728542ae754b9525d5820f Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Tue, 5 Nov 2019 15:13:44 -0500 Subject: [PATCH 2/2] fix: bring tests into line with spec. See: https://docs.google.com/document/d/1qCRRNqzKn7YnssbB1g-RTkJH11S3vmJ97JjsLWo6alA In particular: - Ensure 'inside_vpcxc' returns True IFF env var is set, regardless of value. - Add 'bucket_outside' test and corresponding skip decorator. - Rename 'skip_*' decorators to clarify semantics. - Expand reason messages in skip decorators to clarify semantics, explain how to enable the skipped test. --- test_utils/test_utils/vpcsc_config.py | 64 +++++++++++++++++++-------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/test_utils/test_utils/vpcsc_config.py b/test_utils/test_utils/vpcsc_config.py index b3495585ed3b..b8854b2a46a4 100644 --- a/test_utils/test_utils/vpcsc_config.py +++ b/test_utils/test_utils/vpcsc_config.py @@ -22,23 +22,25 @@ INSIDE_VPCSC_ENVVAR = "GOOGLE_CLOUD_TESTS_IN_VPCSC" PROJECT_INSIDE_ENVVAR = "PROJECT_ID" PROJECT_OUTSIDE_ENVVAR = "GOOGLE_CLOUD_TESTS_VPCSC_OUTSIDE_PERIMETER_PROJECT" +BUCKET_OUTSIDE_ENVVVAR = "GOOGLE_CLOUD_TESTS_VPCSC_OUTSIDE_PERIMETER_BUCKET" 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. + """Test whether the test environment is configured to run inside VPCSC. Returns: - bool: true if the environment is inside VPCSC, else false. + bool: + true if the environment is configured to run inside VPCSC, + else false. """ - value = os.environ.get(INSIDE_VPCSC_ENVVAR, "true").lower() - return value == "true" + return INSIDE_VPCSC_ENVVAR in os.environ @property def project_inside(self): @@ -58,35 +60,59 @@ def project_outside(self): """ return os.environ.get(PROJECT_OUTSIDE_ENVVAR, None) - def skip_if_running_inside_vpcsc(self, testcase): + @property + def bucket_outside(self): + """GCS bucket for testing inside access. + + Returns: + str: bucket ID used for testing inside access; None if undefined. + """ + return os.environ.get(BUCKET_OUTSIDE_ENVVAR, None) + + def skip_if_inside_vpcsc(self, testcase): """Test decorator: skip if running inside VPCSC.""" - reason = "Running inside VPCSC" + reason = ( + "Running inside VPCSC. " + "Set the {} environment variable to enable this test." + ).format(INSIDE_VPCSC_ENVVAR) skip = pytest.mark.skipif(self.inside_vpcsc, reason=reason) return skip(testcase) - def skip_if_running_outside_vpcsc(self, testcase): + def skip_unless_inside_vpcsc(self, testcase): """Test decorator: skip if running outside VPCSC.""" - reason = "Running outside VPCSC" + reason = ( + "Running outside VPCSC. " + "Unset the {} environment variable to enable this test." + ).format(INSIDE_VPCSC_ENVVAR) skip = pytest.mark.skipif(not self.inside_vpcsc, reason=reason) return skip(testcase) - def skip_if_inside_vpcsc(self, testcase): + def skip_unless_inside_project(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) + reason = ( + "Project ID for running inside VPCSC not set. " + "Set the {} environment variable to enable this test." + ).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): + def skip_unless_outside_project(self, testcase): """Test decorator: skip if outside project env var not set.""" - reason = "Missing envvar: {}".format(PROJECT_OUTSIDE_ENVVAR) + reason = ( + "Project ID for running outside VPCSC not set. " + "Set the {} environment variable to enable this test." + ).format(PROJECT_OUTSIDE_ENVVAR) skip = pytest.mark.skipif(self.project_outside is None, reason=reason) return skip(testcase) + def skip_unless_outside_bucket(self, testcase): + """Test decorator: skip if outside bucket env var not set.""" + reason = ( + "Bucket ID for running outside VPCSC not set. " + "Set the {} environment variable to enable this test." + ).format(BUCKET_OUTSIDE_ENVVAR) + skip = pytest.mark.skipif(self.bucket_outside is None, reason=reason) + return skip(testcase) + vpcsc_config = VPCSCTestConfig()