Skip to content

Commit a13c49d

Browse files
Merge pull request #7207 from cristianoveiga/GCP-196
GCP-196: Implement GCPPrivateServiceObserver controller
2 parents 464342a + 4e4b601 commit a13c49d

12 files changed

Lines changed: 677 additions & 46 deletions

File tree

api/hypershift/v1beta1/gcpprivateserviceconnect_types.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,20 @@ const (
3838

3939
// GCPPrivateServiceConnectSpec defines the desired state of PSC infrastructure
4040
type GCPPrivateServiceConnectSpec struct {
41-
// forwardingRuleName is the name of the Internal Load Balancer forwarding rule
41+
// loadBalancerIP is the IP address of the Internal Load Balancer
42+
// Populated by the observer from service status
43+
// This value must be a valid IPv4 or IPv6 address.
4244
// +required
43-
// +kubebuilder:validation:MinLength=1
45+
// +kubebuilder:validation:XValidation:rule="self.matches('^((\\\\d{1,3}\\\\.){3}\\\\d{1,3})$') || self.matches('^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$')",message="loadBalancerIP must be a valid IPv4 or IPv6 address"
46+
// +kubebuilder:validation:MaxLength=45
47+
LoadBalancerIP string `json:"loadBalancerIP"`
48+
49+
// forwardingRuleName is the name of the Internal Load Balancer forwarding rule
50+
// Populated by the reconciler via GCP API lookup
51+
// +optional
4452
// +kubebuilder:validation:MaxLength=63
4553
// +kubebuilder:validation:Pattern=`^[a-z]([-a-z0-9]*[a-z0-9])?$`
46-
ForwardingRuleName string `json:"forwardingRuleName"`
54+
ForwardingRuleName string `json:"forwardingRuleName,omitempty"`
4755

4856
// consumerAcceptList specifies which customer projects can connect
4957
// Accepts both project IDs (e.g. "my-project-123") and project numbers (e.g. "123456789012")
@@ -91,9 +99,10 @@ type GCPPrivateServiceConnectStatus struct {
9199
// Customer Side Status (PSC Endpoint and DNS)
92100

93101
// endpointIP is the reserved IP address for the PSC endpoint
102+
// This value must be a valid IPv4 or IPv6 address.
94103
// +optional
95-
// +kubebuilder:validation:MaxLength=15
96-
// +kubebuilder:validation:Pattern=`^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$`
104+
// +kubebuilder:validation:XValidation:rule="self == '' || self.matches('^((\\\\d{1,3}\\\\.){3}\\\\d{1,3})$') || self.matches('^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$')",message="endpointIP must be a valid IPv4 or IPv6 address"
105+
// +kubebuilder:validation:MaxLength=45
97106
EndpointIP string `json:"endpointIP,omitempty"`
98107

99108
// dnsZoneName is the private DNS zone name
@@ -115,7 +124,7 @@ type GCPPrivateServiceConnectStatus struct {
115124
// +kubebuilder:subresource:status
116125
// +kubebuilder:printcolumn:name="Service Attachment",type="string",JSONPath=".status.serviceAttachmentName",description="Name of the Service Attachment"
117126
// +kubebuilder:printcolumn:name="Endpoint IP",type="string",JSONPath=".status.endpointIP",description="IP address of the PSC endpoint"
118-
// +kubebuilder:printcolumn:name="Available",type="string",JSONPath=".status.conditions[?(@.type==\"GCPPrivateServiceConnectAvailable\")].status",description="Overall PSC availability status"
127+
// +kubebuilder:printcolumn:name="Available",type="string",JSONPath=".status.conditions[?(@.type==\"GCPEndpointAvailable\")].status",description="PSC endpoint availability status"
119128
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
120129
// +openshift:enable:FeatureGate=GCPPlatform
121130

api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ gcpprivateserviceconnects.hypershift.openshift.io:
111111
jsonPath: .status.endpointIP
112112
name: Endpoint IP
113113
type: string
114-
- description: Overall PSC availability status
115-
jsonPath: .status.conditions[?(@.type=="GCPPrivateServiceConnectAvailable")].status
114+
- description: PSC endpoint availability status
115+
jsonPath: .status.conditions[?(@.type=="GCPEndpointAvailable")].status
116116
name: Available
117117
type: string
118118
- jsonPath: .metadata.creationTimestamp

api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/gcpprivateserviceconnects.hypershift.openshift.io/GCPPlatform.yaml

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ spec:
2424
jsonPath: .status.endpointIP
2525
name: Endpoint IP
2626
type: string
27-
- description: Overall PSC availability status
28-
jsonPath: .status.conditions[?(@.type=="GCPPrivateServiceConnectAvailable")].status
27+
- description: PSC endpoint availability status
28+
jsonPath: .status.conditions[?(@.type=="GCPEndpointAvailable")].status
2929
name: Available
3030
type: string
3131
- jsonPath: .metadata.creationTimestamp
@@ -70,12 +70,22 @@ spec:
7070
minItems: 1
7171
type: array
7272
forwardingRuleName:
73-
description: forwardingRuleName is the name of the Internal Load Balancer
74-
forwarding rule
73+
description: |-
74+
forwardingRuleName is the name of the Internal Load Balancer forwarding rule
75+
Populated by the reconciler via GCP API lookup
7576
maxLength: 63
76-
minLength: 1
7777
pattern: ^[a-z]([-a-z0-9]*[a-z0-9])?$
7878
type: string
79+
loadBalancerIP:
80+
description: |-
81+
loadBalancerIP is the IP address of the Internal Load Balancer
82+
Populated by the observer from service status
83+
This value must be a valid IPv4 or IPv6 address.
84+
maxLength: 45
85+
type: string
86+
x-kubernetes-validations:
87+
- message: loadBalancerIP must be a valid IPv4 or IPv6 address
88+
rule: self.matches('^((\\d{1,3}\\.){3}\\d{1,3})$') || self.matches('^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$')
7989
natSubnet:
8090
description: |-
8191
natSubnet is the subnet used for NAT by the Service Attachment
@@ -85,7 +95,7 @@ spec:
8595
type: string
8696
required:
8797
- consumerAcceptList
88-
- forwardingRuleName
98+
- loadBalancerIP
8999
type: object
90100
status:
91101
description: status is the status of the GCPPrivateServiceConnect.
@@ -165,10 +175,15 @@ spec:
165175
maxLength: 253
166176
type: string
167177
endpointIP:
168-
description: endpointIP is the reserved IP address for the PSC endpoint
169-
maxLength: 15
170-
pattern: ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
178+
description: |-
179+
endpointIP is the reserved IP address for the PSC endpoint
180+
This value must be a valid IPv4 or IPv6 address.
181+
maxLength: 45
171182
type: string
183+
x-kubernetes-validations:
184+
- message: endpointIP must be a valid IPv4 or IPv6 address
185+
rule: self == '' || self.matches('^((\\d{1,3}\\.){3}\\d{1,3})$')
186+
|| self.matches('^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$')
172187
serviceAttachmentName:
173188
description: serviceAttachmentName is the name of the created Service
174189
Attachment

client/applyconfiguration/hypershift/v1beta1/gcpprivateserviceconnectspec.go

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/gcpprivateserviceconnects-CustomNoUpgrade.crd.yaml

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ spec:
2727
jsonPath: .status.endpointIP
2828
name: Endpoint IP
2929
type: string
30-
- description: Overall PSC availability status
31-
jsonPath: .status.conditions[?(@.type=="GCPPrivateServiceConnectAvailable")].status
30+
- description: PSC endpoint availability status
31+
jsonPath: .status.conditions[?(@.type=="GCPEndpointAvailable")].status
3232
name: Available
3333
type: string
3434
- jsonPath: .metadata.creationTimestamp
@@ -73,12 +73,22 @@ spec:
7373
minItems: 1
7474
type: array
7575
forwardingRuleName:
76-
description: forwardingRuleName is the name of the Internal Load Balancer
77-
forwarding rule
76+
description: |-
77+
forwardingRuleName is the name of the Internal Load Balancer forwarding rule
78+
Populated by the reconciler via GCP API lookup
7879
maxLength: 63
79-
minLength: 1
8080
pattern: ^[a-z]([-a-z0-9]*[a-z0-9])?$
8181
type: string
82+
loadBalancerIP:
83+
description: |-
84+
loadBalancerIP is the IP address of the Internal Load Balancer
85+
Populated by the observer from service status
86+
This value must be a valid IPv4 or IPv6 address.
87+
maxLength: 45
88+
type: string
89+
x-kubernetes-validations:
90+
- message: loadBalancerIP must be a valid IPv4 or IPv6 address
91+
rule: self.matches('^((\\d{1,3}\\.){3}\\d{1,3})$') || self.matches('^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$')
8292
natSubnet:
8393
description: |-
8494
natSubnet is the subnet used for NAT by the Service Attachment
@@ -88,7 +98,7 @@ spec:
8898
type: string
8999
required:
90100
- consumerAcceptList
91-
- forwardingRuleName
101+
- loadBalancerIP
92102
type: object
93103
status:
94104
description: status is the status of the GCPPrivateServiceConnect.
@@ -168,10 +178,15 @@ spec:
168178
maxLength: 253
169179
type: string
170180
endpointIP:
171-
description: endpointIP is the reserved IP address for the PSC endpoint
172-
maxLength: 15
173-
pattern: ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
181+
description: |-
182+
endpointIP is the reserved IP address for the PSC endpoint
183+
This value must be a valid IPv4 or IPv6 address.
184+
maxLength: 45
174185
type: string
186+
x-kubernetes-validations:
187+
- message: endpointIP must be a valid IPv4 or IPv6 address
188+
rule: self == '' || self.matches('^((\\d{1,3}\\.){3}\\d{1,3})$')
189+
|| self.matches('^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$')
175190
serviceAttachmentName:
176191
description: serviceAttachmentName is the name of the created Service
177192
Attachment

cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/gcpprivateserviceconnects-TechPreviewNoUpgrade.crd.yaml

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ spec:
2727
jsonPath: .status.endpointIP
2828
name: Endpoint IP
2929
type: string
30-
- description: Overall PSC availability status
31-
jsonPath: .status.conditions[?(@.type=="GCPPrivateServiceConnectAvailable")].status
30+
- description: PSC endpoint availability status
31+
jsonPath: .status.conditions[?(@.type=="GCPEndpointAvailable")].status
3232
name: Available
3333
type: string
3434
- jsonPath: .metadata.creationTimestamp
@@ -73,12 +73,22 @@ spec:
7373
minItems: 1
7474
type: array
7575
forwardingRuleName:
76-
description: forwardingRuleName is the name of the Internal Load Balancer
77-
forwarding rule
76+
description: |-
77+
forwardingRuleName is the name of the Internal Load Balancer forwarding rule
78+
Populated by the reconciler via GCP API lookup
7879
maxLength: 63
79-
minLength: 1
8080
pattern: ^[a-z]([-a-z0-9]*[a-z0-9])?$
8181
type: string
82+
loadBalancerIP:
83+
description: |-
84+
loadBalancerIP is the IP address of the Internal Load Balancer
85+
Populated by the observer from service status
86+
This value must be a valid IPv4 or IPv6 address.
87+
maxLength: 45
88+
type: string
89+
x-kubernetes-validations:
90+
- message: loadBalancerIP must be a valid IPv4 or IPv6 address
91+
rule: self.matches('^((\\d{1,3}\\.){3}\\d{1,3})$') || self.matches('^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$')
8292
natSubnet:
8393
description: |-
8494
natSubnet is the subnet used for NAT by the Service Attachment
@@ -88,7 +98,7 @@ spec:
8898
type: string
8999
required:
90100
- consumerAcceptList
91-
- forwardingRuleName
101+
- loadBalancerIP
92102
type: object
93103
status:
94104
description: status is the status of the GCPPrivateServiceConnect.
@@ -168,10 +178,15 @@ spec:
168178
maxLength: 253
169179
type: string
170180
endpointIP:
171-
description: endpointIP is the reserved IP address for the PSC endpoint
172-
maxLength: 15
173-
pattern: ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
181+
description: |-
182+
endpointIP is the reserved IP address for the PSC endpoint
183+
This value must be a valid IPv4 or IPv6 address.
184+
maxLength: 45
174185
type: string
186+
x-kubernetes-validations:
187+
- message: endpointIP must be a valid IPv4 or IPv6 address
188+
rule: self == '' || self.matches('^((\\d{1,3}\\.){3}\\d{1,3})$')
189+
|| self.matches('^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$')
175190
serviceAttachmentName:
176191
description: serviceAttachmentName is the name of the created Service
177192
Attachment

0 commit comments

Comments
 (0)