fix(source/cloud-sql-mssql): remove ip address field (#1822)

## Description

Removing the `ipAddress` field since it is not an input for Cloud SQL
SQL Server source.

Kept the variable in Source's config but removed this variable from
everywhere else in the code. This will PREVENT a breaking change since
the validator won't flag it as an "extra field".

**Will have to update the following as well:**
(1) Cloud docs
https://cloud.google.com/sql/docs/sqlserver/pre-built-tools-with-mcp-toolbox
(2) gemini-cli-extensions
https://github.com/gemini-cli-extensions/cloud-sql-sqlserver

## PR Checklist

> Thank you for opening a Pull Request! Before submitting your PR, there
are a
> few things you can do to make sure it goes smoothly:

- [x] Make sure you reviewed

[CONTRIBUTING.md](https://github.com/googleapis/genai-toolbox/blob/main/CONTRIBUTING.md)
- [x] Make sure to open an issue as a

[bug/issue](https://github.com/googleapis/genai-toolbox/issues/new/choose)
  before writing your code! That way we can discuss the change, evaluate
  designs, and agree on the general idea
- [x] Ensure the tests and linter pass
- [x] Code coverage does not decrease (if any source code was changed)
- [x] Appropriate docs were updated (if necessary)
- [x] Make sure to add `!` if this involve a breaking change

🛠️ Fixes #1549
This commit is contained in:
Yuan Teoh
2025-10-30 17:14:19 -07:00
committed by GitHub
parent ef28e39e90
commit 38d535de34
7 changed files with 53 additions and 41 deletions

View File

@@ -264,7 +264,6 @@ details on how to connect your AI tools (IDEs) to databases via Toolbox and MCP.
* `CLOUD_SQL_MSSQL_REGION`: The region of your Cloud SQL instance.
* `CLOUD_SQL_MSSQL_INSTANCE`: The ID of your Cloud SQL instance.
* `CLOUD_SQL_MSSQL_DATABASE`: The name of the database to connect to.
* `CLOUD_SQL_MSSQL_IP_ADDRESS`: The IP address of the Cloud SQL instance.
* `CLOUD_SQL_MSSQL_USER`: The database username.
* `CLOUD_SQL_MSSQL_PASSWORD`: The password for the database user.
* `CLOUD_SQL_MSSQL_IP_TYPE`: (Optional) The IP type i.e. "Public" or

View File

@@ -94,7 +94,6 @@ sources:
region: my-region
instance: my-instance
database: my_db
ipAddress: localhost
user: ${USER_NAME}
password: ${PASSWORD}
# ipType: private
@@ -114,7 +113,6 @@ instead of hardcoding your secrets into the configuration file.
| region | string | true | Name of the GCP region that the cluster was created in (e.g. "us-central1"). |
| instance | string | true | Name of the Cloud SQL instance within the cluster (e.g. "my-instance"). |
| database | string | true | Name of the Cloud SQL database to connect to (e.g. "my_db"). |
| ipAddress | string | true | IP address of the Cloud SQL instance to connect to. |
| user | string | true | Name of the SQL Server user to connect as (e.g. "my-pg-user"). |
| password | string | true | Password of the SQL Server user (e.g. "my-password"). |
| ipType | string | false | IP Type of the Cloud SQL instance, must be either `public`, `private`, or `psc`. Default: `public`. |

View File

@@ -19,7 +19,6 @@ sources:
region: ${CLOUD_SQL_MSSQL_REGION}
instance: ${CLOUD_SQL_MSSQL_INSTANCE}
database: ${CLOUD_SQL_MSSQL_DATABASE}
ipAddress: ${CLOUD_SQL_MSSQL_IP_ADDRESS}
user: ${CLOUD_SQL_MSSQL_USER}
password: ${CLOUD_SQL_MSSQL_PASSWORD}
ipType: ${CLOUD_SQL_MSSQL_IP_TYPE:public}

View File

@@ -54,7 +54,7 @@ type Config struct {
Project string `yaml:"project" validate:"required"`
Region string `yaml:"region" validate:"required"`
Instance string `yaml:"instance" validate:"required"`
IPAddress string `yaml:"ipAddress" validate:"required"`
IPAddress string `yaml:"ipAddress"` // Deprecated: kept for backwards compatibility
IPType sources.IPType `yaml:"ipType" validate:"required"`
User string `yaml:"user" validate:"required"`
Password string `yaml:"password" validate:"required"`
@@ -68,7 +68,7 @@ func (r Config) SourceConfigKind() string {
func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) {
// Initializes a Cloud SQL MSSQL source
db, err := initCloudSQLMssqlConnection(ctx, tracer, r.Name, r.Project, r.Region, r.Instance, r.IPAddress, r.IPType.String(), r.User, r.Password, r.Database)
db, err := initCloudSQLMssqlConnection(ctx, tracer, r.Name, r.Project, r.Region, r.Instance, r.IPType.String(), r.User, r.Password, r.Database)
if err != nil {
return nil, fmt.Errorf("unable to create db connection: %w", err)
}
@@ -106,7 +106,7 @@ func (s *Source) MSSQLDB() *sql.DB {
return s.Db
}
func initCloudSQLMssqlConnection(ctx context.Context, tracer trace.Tracer, name, project, region, instance, ipAddress, ipType, user, pass, dbname string) (*sql.DB, error) {
func initCloudSQLMssqlConnection(ctx context.Context, tracer trace.Tracer, name, project, region, instance, ipType, user, pass, dbname string) (*sql.DB, error) {
//nolint:all // Reassigned ctx
ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name)
defer span.End()
@@ -125,7 +125,6 @@ func initCloudSQLMssqlConnection(ctx context.Context, tracer trace.Tracer, name,
url := &url.URL{
Scheme: "sqlserver",
User: url.UserPassword(user, pass),
Host: ipAddress,
RawQuery: query.Encode(),
}

View File

@@ -40,22 +40,20 @@ func TestParseFromYamlCloudSQLMssql(t *testing.T) {
region: my-region
instance: my-instance
database: my_db
ipAddress: localhost
user: my_user
password: my_pass
`,
want: server.SourceConfigs{
"my-instance": cloudsqlmssql.Config{
Name: "my-instance",
Kind: cloudsqlmssql.SourceKind,
Project: "my-project",
Region: "my-region",
Instance: "my-instance",
IPAddress: "localhost",
IPType: "public",
Database: "my_db",
User: "my_user",
Password: "my_pass",
Name: "my-instance",
Kind: cloudsqlmssql.SourceKind,
Project: "my-project",
Region: "my-region",
Instance: "my-instance",
IPType: "public",
Database: "my_db",
User: "my_user",
Password: "my_pass",
},
},
},
@@ -69,11 +67,38 @@ func TestParseFromYamlCloudSQLMssql(t *testing.T) {
region: my-region
instance: my-instance
database: my_db
ipAddress: localhost
user: my_user
password: my_pass
ipType: psc
`,
want: server.SourceConfigs{
"my-instance": cloudsqlmssql.Config{
Name: "my-instance",
Kind: cloudsqlmssql.SourceKind,
Project: "my-project",
Region: "my-region",
Instance: "my-instance",
IPType: "psc",
Database: "my_db",
User: "my_user",
Password: "my_pass",
},
},
},
{
desc: "with deprecated ipAddress",
in: `
sources:
my-instance:
kind: cloud-sql-mssql
project: my-project
region: my-region
instance: my-instance
ipAddress: random
database: my_db
user: my_user
password: my_pass
`,
want: server.SourceConfigs{
"my-instance": cloudsqlmssql.Config{
Name: "my-instance",
@@ -81,8 +106,8 @@ func TestParseFromYamlCloudSQLMssql(t *testing.T) {
Project: "my-project",
Region: "my-region",
Instance: "my-instance",
IPAddress: "localhost",
IPType: "psc",
IPAddress: "random",
IPType: "public",
Database: "my_db",
User: "my_user",
Password: "my_pass",
@@ -125,7 +150,6 @@ func TestFailParseFromYaml(t *testing.T) {
instance: my-instance
ipType: fail
database: my_db
ipAddress: localhost
user: my_user
password: my_pass
`,
@@ -141,12 +165,11 @@ func TestFailParseFromYaml(t *testing.T) {
region: my-region
instance: my-instance
database: my_db
ipAddress: localhost
user: my_user
password: my_pass
foo: bar
`,
err: "unable to parse source \"my-instance\" as \"cloud-sql-mssql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | ipAddress: localhost\n 5 | kind: cloud-sql-mssql\n 6 | ",
err: "unable to parse source \"my-instance\" as \"cloud-sql-mssql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | kind: cloud-sql-mssql\n 5 | password: my_pass\n 6 | ",
},
{
desc: "missing required field",
@@ -157,7 +180,6 @@ func TestFailParseFromYaml(t *testing.T) {
region: my-region
instance: my-instance
database: my_db
ipAddress: localhost
user: my_user
password: my_pass
`,

View File

@@ -40,7 +40,6 @@ var (
CloudSQLMSSQLRegion = os.Getenv("CLOUD_SQL_MSSQL_REGION")
CloudSQLMSSQLInstance = os.Getenv("CLOUD_SQL_MSSQL_INSTANCE")
CloudSQLMSSQLDatabase = os.Getenv("CLOUD_SQL_MSSQL_DATABASE")
CloudSQLMSSQLIp = os.Getenv("CLOUD_SQL_MSSQL_IP")
CloudSQLMSSQLUser = os.Getenv("CLOUD_SQL_MSSQL_USER")
CloudSQLMSSQLPass = os.Getenv("CLOUD_SQL_MSSQL_PASS")
)
@@ -53,8 +52,6 @@ func getCloudSQLMSSQLVars(t *testing.T) map[string]any {
t.Fatal("'CLOUD_SQL_MSSQL_REGION' not set")
case CloudSQLMSSQLInstance:
t.Fatal("'CLOUD_SQL_MSSQL_INSTANCE' not set")
case CloudSQLMSSQLIp:
t.Fatal("'CLOUD_SQL_MSSQL_IP' not set")
case CloudSQLMSSQLDatabase:
t.Fatal("'CLOUD_SQL_MSSQL_DATABASE' not set")
case CloudSQLMSSQLUser:
@@ -64,25 +61,23 @@ func getCloudSQLMSSQLVars(t *testing.T) map[string]any {
}
return map[string]any{
"kind": CloudSQLMSSQLSourceKind,
"project": CloudSQLMSSQLProject,
"instance": CloudSQLMSSQLInstance,
"ipAddress": CloudSQLMSSQLIp,
"region": CloudSQLMSSQLRegion,
"database": CloudSQLMSSQLDatabase,
"user": CloudSQLMSSQLUser,
"password": CloudSQLMSSQLPass,
"kind": CloudSQLMSSQLSourceKind,
"project": CloudSQLMSSQLProject,
"instance": CloudSQLMSSQLInstance,
"region": CloudSQLMSSQLRegion,
"database": CloudSQLMSSQLDatabase,
"user": CloudSQLMSSQLUser,
"password": CloudSQLMSSQLPass,
}
}
// Copied over from cloud_sql_mssql.go
func initCloudSQLMSSQLConnection(project, region, instance, ipAddress, ipType, user, pass, dbname string) (*sql.DB, error) {
func initCloudSQLMSSQLConnection(project, region, instance, ipType, user, pass, dbname string) (*sql.DB, error) {
// Create dsn
query := fmt.Sprintf("database=%s&cloudsql=%s:%s:%s", dbname, project, region, instance)
url := &url.URL{
Scheme: "sqlserver",
User: url.UserPassword(user, pass),
Host: ipAddress,
RawQuery: query,
}
@@ -118,7 +113,7 @@ func TestCloudSQLMSSQLToolEndpoints(t *testing.T) {
var args []string
db, err := initCloudSQLMSSQLConnection(CloudSQLMSSQLProject, CloudSQLMSSQLRegion, CloudSQLMSSQLInstance, CloudSQLMSSQLIp, "public", CloudSQLMSSQLUser, CloudSQLMSSQLPass, CloudSQLMSSQLDatabase)
db, err := initCloudSQLMSSQLConnection(CloudSQLMSSQLProject, CloudSQLMSSQLRegion, CloudSQLMSSQLInstance, "public", CloudSQLMSSQLUser, CloudSQLMSSQLPass, CloudSQLMSSQLDatabase)
if err != nil {
t.Fatalf("unable to create Cloud SQL connection pool: %s", err)
}