Skip to content

Commit 35402f7

Browse files
authored
feat: Support dns name for connector names (#701)
Adds test cases to demonstrate that the DNS name may be used for the instance connection name for instances with DNS TXT records. Fixes #683
1 parent 61cf3b9 commit 35402f7

File tree

8 files changed

+161
-75
lines changed

8 files changed

+161
-75
lines changed

docs/api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ _Appears in:_
158158

159159
| Field | Description | Default | Validation |
160160
| --- | --- | --- | --- |
161-
| `connectionString` _string_ | ConnectionString is the connection string for the Cloud SQL Instance<br />in the format `project_id:region:instance_name` | | Pattern: `^([^:]+(:[^:]+)?):([^:]+):([^:]+)$` <br />Required: \{\} <br /> |
161+
| `connectionString` _string_ | ConnectionString is the connection string for the Cloud SQL Instance.<br />This may be an instance connection name in the format `project_id:region:instance_name`<br />or a DNS name for the instance. | | Required: \{\} <br /> |
162162
| `port` _integer_ | Port (optional) sets the tcp port for this instance. If not set, a value will<br />be automatically assigned by the operator and set as an environment variable<br />on all containers in the workload named according to PortEnvName. The operator will choose<br />a port so that it does not conflict with other ports on the workload. | | Minimum: 1 <br />Optional: \{\} <br /> |
163163
| `autoIAMAuthN` _boolean_ | AutoIAMAuthN (optional) Enables IAM Authentication for this instance.<br />Default value is false. | | Optional: \{\} <br /> |
164164
| `privateIP` _boolean_ | PrivateIP (optional) Enable connection to the Cloud SQL instance's private ip for this instance.<br />Default value is false. | | Optional: \{\} <br /> |

go.mod

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/GoogleCloudPlatform/cloud-sql-proxy-operator
33
go 1.24.0
44

55
require (
6+
cloud.google.com/go/cloudsqlconn v1.18.0
67
github.com/go-logr/logr v1.4.3
78
go.uber.org/zap v1.27.0
89
k8s.io/api v0.32.8
@@ -28,7 +29,7 @@ require (
2829
github.com/golang/protobuf v1.5.4 // indirect
2930
github.com/google/btree v1.1.3 // indirect
3031
github.com/google/gnostic-models v0.6.8 // indirect
31-
github.com/google/go-cmp v0.6.0 // indirect
32+
github.com/google/go-cmp v0.7.0 // indirect
3233
github.com/google/gofuzz v1.2.0 // indirect
3334
github.com/google/uuid v1.6.0 // indirect
3435
github.com/josharian/intern v1.0.0 // indirect
@@ -42,19 +43,21 @@ require (
4243
github.com/prometheus/client_model v0.6.1 // indirect
4344
github.com/prometheus/common v0.55.0 // indirect
4445
github.com/prometheus/procfs v0.15.1 // indirect
46+
github.com/rogpeppe/go-internal v1.13.1 // indirect
4547
github.com/spf13/pflag v1.0.5 // indirect
48+
github.com/stretchr/testify v1.10.0 // indirect
4649
github.com/x448/float16 v0.8.4 // indirect
4750
go.uber.org/multierr v1.11.0 // indirect
4851
go.yaml.in/yaml/v2 v2.4.2 // indirect
49-
golang.org/x/net v0.30.0 // indirect
50-
golang.org/x/oauth2 v0.23.0 // indirect
51-
golang.org/x/sync v0.8.0 // indirect
52-
golang.org/x/sys v0.26.0 // indirect
53-
golang.org/x/term v0.25.0 // indirect
54-
golang.org/x/text v0.19.0 // indirect
55-
golang.org/x/time v0.7.0 // indirect
52+
golang.org/x/net v0.43.0 // indirect
53+
golang.org/x/oauth2 v0.30.0 // indirect
54+
golang.org/x/sync v0.16.0 // indirect
55+
golang.org/x/sys v0.35.0 // indirect
56+
golang.org/x/term v0.34.0 // indirect
57+
golang.org/x/text v0.28.0 // indirect
58+
golang.org/x/time v0.12.0 // indirect
5659
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
57-
google.golang.org/protobuf v1.35.1 // indirect
60+
google.golang.org/protobuf v1.36.7 // indirect
5861
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
5962
gopkg.in/inf.v0 v0.9.1 // indirect
6063
gopkg.in/yaml.v3 v3.0.1 // indirect

go.sum

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
cloud.google.com/go/cloudsqlconn v1.18.0 h1:mP6TY/7I+nrnIh6vmbWCRJPxpFBZSL6AZhW6HaYC/OI=
2+
cloud.google.com/go/cloudsqlconn v1.18.0/go.mod h1:58bxZZ17Mz5D83ddMT8x6w56yKpcmVXyaOwGWkzGcMw=
13
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
24
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
35
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
@@ -40,8 +42,8 @@ github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76
4042
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
4143
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
4244
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
43-
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
44-
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
45+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
46+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
4547
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
4648
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
4749
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -88,8 +90,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G
8890
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
8991
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
9092
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
91-
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
92-
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
93+
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
94+
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
9395
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
9496
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
9597
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -99,8 +101,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
99101
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
100102
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
101103
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
102-
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
103-
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
104+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
105+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
104106
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
105107
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
106108
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -124,42 +126,42 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
124126
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
125127
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
126128
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
127-
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
128-
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
129-
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
130-
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
129+
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
130+
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
131+
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
132+
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
131133
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
132134
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
133135
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
134-
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
135-
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
136+
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
137+
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
136138
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
137139
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
138140
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
139-
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
140-
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
141-
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
142-
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
141+
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
142+
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
143+
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
144+
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
143145
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
144146
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
145-
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
146-
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
147-
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
148-
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
147+
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
148+
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
149+
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
150+
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
149151
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
150152
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
151153
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
152154
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
153-
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
154-
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
155+
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
156+
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
155157
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
156158
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
157159
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
158160
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
159161
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
160162
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
161-
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
162-
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
163+
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
164+
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
163165
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
164166
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
165167
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

internal/api/v1/authproxyworkload_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,30 @@ func TestAuthProxyWorkload_ValidateCreate_InstanceSpec(t *testing.T) {
111111
}},
112112
wantValid: false,
113113
},
114+
{
115+
desc: "Valid, Instance configured with valid instance name",
116+
spec: []cloudsqlapi.InstanceSpec{{
117+
ConnectionString: "proj:region:db2",
118+
Port: ptr(int32(5000)),
119+
}},
120+
wantValid: true,
121+
},
122+
{
123+
desc: "Valid, Instance configured with domain name name",
124+
spec: []cloudsqlapi.InstanceSpec{{
125+
ConnectionString: "proj:region:db2",
126+
Port: ptr(int32(5000)),
127+
}},
128+
wantValid: true,
129+
},
130+
{
131+
desc: "Invalid, Instance configured with malformed name",
132+
spec: []cloudsqlapi.InstanceSpec{{
133+
ConnectionString: "bad name!",
134+
Port: ptr(int32(5000)),
135+
}},
136+
wantValid: false,
137+
},
114138
}
115139
for _, tc := range data {
116140
t.Run(tc.desc, func(t *testing.T) {

internal/api/v1/authproxyworkload_types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,10 +345,10 @@ type TelemetrySpec struct {
345345
// `{ "connectionString":"my-project:us-central1:my-db-server", "port":5000 }`
346346
type InstanceSpec struct {
347347

348-
// ConnectionString is the connection string for the Cloud SQL Instance
349-
// in the format `project_id:region:instance_name`
348+
// ConnectionString is the connection string for the Cloud SQL Instance.
349+
// This may be an instance connection name in the format `project_id:region:instance_name`
350+
// or a DNS name for the instance.
350351
//+kubebuilder:validation:Required
351-
//+kubebuilder:validation:Pattern:="^([^:]+(:[^:]+)?):([^:]+):([^:]+)$"
352352
ConnectionString string `json:"connectionString,omitempty"`
353353

354354
// Port (optional) sets the tcp port for this instance. If not set, a value will

internal/api/v1/authproxyworkload_webhook.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"path"
2121
"reflect"
2222

23+
"cloud.google.com/go/cloudsqlconn/instance"
2324
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
2425

2526
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -281,6 +282,7 @@ func validateInstances(spec *[]InstanceSpec, f *field.Path) field.ErrorList {
281282
}
282283
for i, inst := range *spec {
283284
ff := f.Child(fmt.Sprintf("%d", i))
285+
errs = append(errs, validateConnectionString(inst, f)...)
284286
if inst.Port != nil {
285287
for _, s := range apivalidation.IsValidPortNum(int(*inst.Port)) {
286288
errs = append(errs, field.Invalid(ff.Child("port"), inst.Port, s))
@@ -311,6 +313,16 @@ func validateInstances(spec *[]InstanceSpec, f *field.Path) field.ErrorList {
311313
return errs
312314
}
313315

316+
func validateConnectionString(inst InstanceSpec, f *field.Path) field.ErrorList {
317+
if instance.IsValidDomain(inst.ConnectionString) {
318+
return nil
319+
}
320+
if _, err := instance.ParseConnName(inst.ConnectionString); err != nil {
321+
return []*field.Error{field.Invalid(f, inst.ConnectionString, "is not a valid instance connection name or dns name")}
322+
}
323+
return nil
324+
}
325+
314326
func validateEnvName(f *field.Path, envName string) field.ErrorList {
315327
var errs field.ErrorList
316328
if envName != "" {

internal/testintegration/integration_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,34 @@ func TestCreateAndDeleteResource(t *testing.T) {
8484

8585
}
8686

87+
// newTestCaseClient Creates a new TestCaseClient providing unique namespace and
88+
// other default values.
89+
func newDomainNameTestCaseClient(name string, c client.Client) *testhelpers.TestCaseClient {
90+
return &testhelpers.TestCaseClient{
91+
Client: c,
92+
Namespace: testhelpers.NewNamespaceName(name),
93+
ConnectionString: "db.example.com",
94+
}
95+
}
96+
97+
func TestCreateAndDeleteDomainNameResource(t *testing.T) {
98+
ctx := testintegration.TestContext()
99+
tcc := newDomainNameTestCaseClient("create", defaultClient)
100+
res, err := tcc.CreateResource(ctx)
101+
if err != nil {
102+
t.Fatal(err)
103+
}
104+
err = tcc.WaitForFinalizerOnResource(ctx, res)
105+
if err != nil {
106+
t.Fatal(err)
107+
}
108+
err = tcc.DeleteResourceAndWait(ctx, res)
109+
if err != nil {
110+
t.Fatal(err)
111+
}
112+
113+
}
114+
87115
func TestModifiesNewDeployment(t *testing.T) {
88116
ctx := testintegration.TestContext()
89117
tcc := newTestCaseClient("modifynew", defaultClient)

internal/workload/podspec_updates_test.go

Lines changed: 55 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -135,52 +135,69 @@ func configureProxies(u *workload.Updater, wl *workload.PodWorkload, proxies []*
135135
}
136136

137137
func TestUpdatePodWorkload(t *testing.T) {
138-
var (
139-
wantsName = "instance1"
140-
wantsPort int32 = 8080
141-
wantContainerName = "csql-default-" + wantsName
142-
wantsInstanceName = "project:server:db"
143-
wantsInstanceArg = fmt.Sprintf("%s?port=%d", wantsInstanceName, wantsPort)
144-
u = workload.NewUpdater("cloud-sql-proxy-operator/dev", workload.DefaultProxyImage, false)
145-
)
146-
var err error
138+
tcs := []struct {
139+
name string
140+
wantsName string
141+
wantsPort int32
142+
wantsInstanceName string
143+
}{{
144+
name: "WithInstanceConnectionString",
145+
wantsName: "instance1",
146+
wantsPort: int32(8080),
147+
wantsInstanceName: "project:server:db",
148+
}, {
149+
name: "WithDnsNameString",
150+
wantsName: "instance1",
151+
wantsPort: int32(8080),
152+
wantsInstanceName: "db.example.com",
153+
},
154+
}
155+
for _, tc := range tcs {
156+
t.Run(tc.name, func(t *testing.T) {
157+
u := workload.NewUpdater("cloud-sql-proxy-operator/dev", workload.DefaultProxyImage, false)
158+
wantsContainerName := "csql-default-" + tc.wantsName
159+
wantsInstanceArg := fmt.Sprintf("%s?port=%d", tc.wantsInstanceName, tc.wantsPort)
147160

148-
// Create a pod
149-
wl := podWorkload()
161+
var err error
150162

151-
// ensure that the deployment only has one container before
152-
// updating the deployment.
153-
if len(wl.Pod.Spec.Containers) != 1 {
154-
t.Fatalf("got %v, wants 1. deployment containers length", len(wl.Pod.Spec.Containers))
155-
}
163+
// Create a pod
164+
wl := podWorkload()
156165

157-
// Create a AuthProxyWorkload that matches the deployment
158-
proxy := simpleAuthProxy(wantsName, wantsInstanceName)
159-
proxy.Spec.Instances[0].Port = ptr(wantsPort)
166+
// ensure that the deployment only has one container before
167+
// updating the deployment.
168+
if len(wl.Pod.Spec.Containers) != 1 {
169+
t.Fatalf("got %v, wants 1. deployment containers length", len(wl.Pod.Spec.Containers))
170+
}
160171

161-
// Update the container with new markWorkloadNeedsUpdate
162-
err = configureProxies(u, wl, []*cloudsqlapi.AuthProxyWorkload{proxy})
163-
if err != nil {
164-
t.Fatal(err)
165-
}
172+
// Create a AuthProxyWorkload that matches the deployment
173+
proxy := simpleAuthProxy(tc.wantsName, tc.wantsInstanceName)
174+
proxy.Spec.Instances[0].Port = ptr(tc.wantsPort)
166175

167-
// test that there are now 2 containers
168-
if want, got := 2, len(wl.Pod.Spec.Containers); want != got {
169-
t.Fatalf("got %v want %v, number of deployment containers", got, want)
170-
}
176+
// Update the container with new markWorkloadNeedsUpdate
177+
err = configureProxies(u, wl, []*cloudsqlapi.AuthProxyWorkload{proxy})
178+
if err != nil {
179+
t.Fatal(err)
180+
}
171181

172-
t.Logf("Containers: {%v}", wl.Pod.Spec.Containers)
182+
// test that there are now 2 containers
183+
if want, got := 2, len(wl.Pod.Spec.Containers); want != got {
184+
t.Fatalf("got %v want %v, number of deployment containers", got, want)
185+
}
173186

174-
// test that the container has the proper name following the conventions
175-
foundContainer, err := findContainer(wl, wantContainerName)
176-
if err != nil {
177-
t.Fatal(err)
178-
}
187+
t.Logf("Containers: {%v}", wl.Pod.Spec.Containers)
179188

180-
// test that the container args have the expected args
181-
if gotArg, err := hasArg(wl, wantContainerName, wantsInstanceArg); err != nil || !gotArg {
182-
t.Errorf("wants connection string arg %v but it was not present in proxy container args %v",
183-
wantsInstanceArg, foundContainer.Args)
189+
// test that the container has the proper name following the conventions
190+
foundContainer, err := findContainer(wl, wantsContainerName)
191+
if err != nil {
192+
t.Fatal(err)
193+
}
194+
195+
// test that the container args have the expected args
196+
if gotArg, err := hasArg(wl, wantsContainerName, wantsInstanceArg); err != nil || !gotArg {
197+
t.Errorf("wants connection string arg %v but it was not present in proxy container args %v",
198+
wantsInstanceArg, foundContainer.Args)
199+
}
200+
})
184201
}
185202

186203
}

0 commit comments

Comments
 (0)