diff --git a/.gitignore b/.gitignore index 9f449ce4a..06827b584 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ dist/ .idea .coverage sponge_log.xml +.envrc +*.iml diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..fc85edff9 --- /dev/null +++ b/build.sh @@ -0,0 +1,168 @@ +#!/usr/bin/env bash + +# Copyright 2025 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 +# +# http=//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. + +# Set SCRIPT_DIR to the current directory of this file. +SCRIPT_DIR=$(cd -P "$(dirname "$0")" >/dev/null 2>&1 && pwd) +SCRIPT_FILE="${SCRIPT_DIR}/$(basename "$0")" + +## +## Local Development +## +## These functions should be used to run the local development process +## + +if [[ ! -d venv ]] ; then + echo "./venv not found. Setting up venv" + python3 -m venv "$PWD/venv" +fi +source "$PWD/venv/bin/activate" + +if which pip3 ; then + PIP_CMD=pip3 +elif which pip ; then + PIP_CMD=pip +else + echo "pip not found. Please add pip to your path." + exit 1 +fi +if ! which nox ; then + $PIP_CMD install nox +fi + + + +## clean - Cleans the build output +function clean() { + if [[ -d '.tools' ]] ; then + rm -rf .tools + fi +} + +## build - Builds the project without running tests. +function build() { + nox --sessions build +} + +## test - Runs local unit tests. +function test() { + nox --sessions unit --python=3.13 +} + +## e2e - Runs end-to-end integration tests. +function e2e() { + if [[ ! -f .envrc ]] ; then + write_e2e_env .envrc + fi + source .envrc + nox --sessions system --python=3.13 +} + +## fix - Fixes code format. +function fix() { + nox --sessions format +} + +## lint - runs the linters +function lint() { + # Check the commit includes a go.mod that is fully + # up to date. + nox --sessions lint +} + +## deps - updates project dependencies to latest +function deps() { + echo "Todo: deps" + exit 1 +} + +# write_e2e_env - Loads secrets from the gcloud project and writes +# them to target/e2e.env to run e2e tests. +function write_e2e_env(){ + # All secrets used by the e2e tests in the form = + secret_vars=( + MYSQL_CONNECTION_NAME=MYSQL_CONNECTION_NAME + MYSQL_USER=MYSQL_USER + MYSQL_USER_IAM=MYSQL_USER_IAM_GO + MYSQL_PASS=MYSQL_PASS + MYSQL_DB=MYSQL_DB + MYSQL_MCP_CONNECTION_NAME=MYSQL_MCP_CONNECTION_NAME + MYSQL_MCP_PASS=MYSQL_MCP_PASS + POSTGRES_CONNECTION_NAME=POSTGRES_CONNECTION_NAME + POSTGRES_USER=POSTGRES_USER + POSTGRES_USER_IAM=POSTGRES_USER_IAM_GO + POSTGRES_PASS=POSTGRES_PASS + POSTGRES_DB=POSTGRES_DB + POSTGRES_CAS_CONNECTION_NAME=POSTGRES_CAS_CONNECTION_NAME + POSTGRES_CAS_PASS=POSTGRES_CAS_PASS + POSTGRES_CUSTOMER_CAS_CONNECTION_NAME=POSTGRES_CUSTOMER_CAS_CONNECTION_NAME + POSTGRES_CUSTOMER_CAS_PASS=POSTGRES_CUSTOMER_CAS_PASS + POSTGRES_CUSTOMER_CAS_DOMAIN_NAME=POSTGRES_CUSTOMER_CAS_DOMAIN_NAME + POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME=POSTGRES_CUSTOMER_CAS_INVALID_DOMAIN_NAME + POSTGRES_MCP_CONNECTION_NAME=POSTGRES_MCP_CONNECTION_NAME + POSTGRES_MCP_PASS=POSTGRES_MCP_PASS + SQLSERVER_CONNECTION_NAME=SQLSERVER_CONNECTION_NAME + SQLSERVER_USER=SQLSERVER_USER + SQLSERVER_PASS=SQLSERVER_PASS + SQLSERVER_DB=SQLSERVER_DB + QUOTA_PROJECT=QUOTA_PROJECT + ) + + if [[ -z "$TEST_PROJECT" ]] ; then + echo "Set TEST_PROJECT environment variable to the project containing" + echo "the e2e test suite secrets." + exit 1 + fi + + echo "Getting test secrets from $TEST_PROJECT into $1" + { + for env_name in "${secret_vars[@]}" ; do + env_var_name="${env_name%%=*}" + secret_name="${env_name##*=}" + set -x + val=$(gcloud secrets versions access latest --project "$TEST_PROJECT" --secret="$secret_name") + echo "export $env_var_name='$val'" + done + } > "$1" + +} + +## help - prints the help details +## +function help() { + # This will print the comments beginning with ## above each function + # in this file. + + echo "build.sh " + echo + echo "Commands to assist with local development and CI builds." + echo + echo "Commands:" + echo + grep -e '^##' "$SCRIPT_FILE" | sed -e 's/##/ /' +} + +set -euo pipefail + +# Check CLI Arguments +if [[ "$#" -lt 1 ]] ; then + help + exit 1 +fi + +cd "$SCRIPT_DIR" + +"$@" + diff --git a/google/cloud/sql/connector/client.py b/google/cloud/sql/connector/client.py index 2e1fbc20d..11508ce17 100644 --- a/google/cloud/sql/connector/client.py +++ b/google/cloud/sql/connector/client.py @@ -22,9 +22,9 @@ import aiohttp from cryptography.hazmat.backends import default_backend from cryptography.x509 import load_pem_x509_certificate - from google.auth.credentials import TokenState from google.auth.transport import requests + from google.cloud.sql.connector.connection_info import ConnectionInfo from google.cloud.sql.connector.connection_name import ConnectionName from google.cloud.sql.connector.exceptions import AutoIAMAuthNotSupported diff --git a/google/cloud/sql/connector/connector.py b/google/cloud/sql/connector/connector.py index 05eaa51df..c76092a40 100755 --- a/google/cloud/sql/connector/connector.py +++ b/google/cloud/sql/connector/connector.py @@ -28,6 +28,7 @@ import google.auth from google.auth.credentials import Credentials from google.auth.credentials import with_scopes_if_required + import google.cloud.sql.connector.asyncpg as asyncpg from google.cloud.sql.connector.client import CloudSQLClient from google.cloud.sql.connector.enums import DriverMapping diff --git a/google/cloud/sql/connector/refresh_utils.py b/google/cloud/sql/connector/refresh_utils.py index 0ef7fcbf7..898f0f7a9 100644 --- a/google/cloud/sql/connector/refresh_utils.py +++ b/google/cloud/sql/connector/refresh_utils.py @@ -24,7 +24,6 @@ from typing import Any, Callable import aiohttp - from google.auth.credentials import Credentials from google.auth.credentials import Scoped import google.auth.transport.requests diff --git a/noxfile.py b/noxfile.py index f04756241..b0220f474 100644 --- a/noxfile.py +++ b/noxfile.py @@ -69,6 +69,15 @@ def format(session): *LINT_PATHS, ) +@nox.session() +def build(session): + """ + Just run the default tools to install requirements. + """ + # Install all test dependencies, then install this package in-place. + session.install("-r", "requirements-test.txt") + session.install("-e", ".") + session.install("-r", "requirements.txt") def default(session, path): # Install all test dependencies, then install this package in-place. diff --git a/tests/unit/mocks.py b/tests/unit/mocks.py index 28c2fc307..66bf64a32 100644 --- a/tests/unit/mocks.py +++ b/tests/unit/mocks.py @@ -31,10 +31,10 @@ from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.x509.oid import NameOID - from google.auth import _helpers from google.auth.credentials import Credentials from google.auth.credentials import TokenState + from google.cloud.sql.connector.connector import _DEFAULT_UNIVERSE_DOMAIN from google.cloud.sql.connector.utils import generate_keys from google.cloud.sql.connector.utils import write_to_file diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index 2ecefe220..cfe509470 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -17,10 +17,10 @@ from aiohttp import ClientResponseError from aioresponses import aioresponses +from google.auth.credentials import Credentials from mocks import FakeCredentials import pytest -from google.auth.credentials import Credentials from google.cloud.sql.connector.client import CloudSQLClient from google.cloud.sql.connector.utils import generate_keys from google.cloud.sql.connector.version import __version__ as version diff --git a/tests/unit/test_connector.py b/tests/unit/test_connector.py index 157697723..498c947cc 100644 --- a/tests/unit/test_connector.py +++ b/tests/unit/test_connector.py @@ -19,10 +19,10 @@ from typing import Union from aiohttp import ClientResponseError +from google.auth.credentials import Credentials from mock import patch import pytest # noqa F401 Needed to run the tests -from google.auth.credentials import Credentials from google.cloud.sql.connector import Connector from google.cloud.sql.connector import create_async_connector from google.cloud.sql.connector import IPTypes diff --git a/tests/unit/test_refresh_utils.py b/tests/unit/test_refresh_utils.py index 2d4cdb853..119e92c7a 100644 --- a/tests/unit/test_refresh_utils.py +++ b/tests/unit/test_refresh_utils.py @@ -20,19 +20,19 @@ import datetime from conftest import SCOPES # type: ignore +import google.auth +from google.auth.credentials import Credentials +from google.auth.credentials import TokenState +import google.oauth2.credentials from mock import Mock from mock import patch import pytest # noqa F401 Needed to run the tests -import google.auth -from google.auth.credentials import Credentials -from google.auth.credentials import TokenState from google.cloud.sql.connector.refresh_utils import _downscope_credentials from google.cloud.sql.connector.refresh_utils import _exponential_backoff from google.cloud.sql.connector.refresh_utils import _is_valid from google.cloud.sql.connector.refresh_utils import _seconds_until_refresh from google.cloud.sql.connector.refresh_utils import retry_50x -import google.oauth2.credentials @pytest.fixture