Skip to content

Commit 2afc44b

Browse files
committed
Merge branch 'main' into feature/nso-slo
2 parents 59eaf9b + 16de28e commit 2afc44b

48 files changed

Lines changed: 3245 additions & 714 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

PROJECT

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,13 @@ resources:
9797
kind: HTTPProxy
9898
path: go.datum.net/network-services-operator/api/v1alpha
9999
version: v1alpha
100+
- api:
101+
crdVersion: v1
102+
namespaced: true
103+
controller: true
104+
domain: datumapis.com
105+
group: networking
106+
kind: Domain
107+
path: go.datum.net/network-services-operator/api/v1alpha
108+
version: v1alpha
100109
version: "3"

api/v1alpha/domain_types.go

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,34 @@ import (
88

99
// +kubebuilder:object:root=true
1010
// +kubebuilder:subresource:status
11-
// +kubebuilder:printcolumn:name="Domain",type="string",JSONPath=".spec.domainName"
12-
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
13-
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=`.status.conditions[?(@.type=="Ready")].status`
14-
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=`.status.conditions[?(@.type=="Ready")].reason`
15-
// +kubebuilder:printcolumn:name="Registrar",type="string",JSONPath=".status.registrar.ianaName"
16-
// +kubebuilder:printcolumn:name="DNSSEC",type="boolean",JSONPath=".status.registrar.dnssec.signed"
17-
// +kubebuilder:printcolumn:name="Expires",type="date",JSONPath=".status.registrar.expirationDate"
18-
// +kubebuilder:printcolumn:name="DNS-Verify",type="string",JSONPath=".status.verification.requiredDNSRecords[0].content"
1911

2012
// Domain represents a domain name in the Datum system
13+
//
14+
// +kubebuilder:printcolumn:name="Domain Name",type="string",JSONPath=".spec.domainName"
15+
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
16+
// +kubebuilder:printcolumn:name="Verified",type="string",JSONPath=`.status.conditions[?(@.type=="Verified")].status`
17+
// +kubebuilder:printcolumn:name="Verification Message",type="string",JSONPath=`.status.conditions[?(@.type=="Verified")].message`,priority=1
2118
type Domain struct {
2219
metav1.TypeMeta `json:",inline"`
2320
metav1.ObjectMeta `json:"metadata,omitempty"`
2421

25-
Spec DomainSpec `json:"spec,omitempty"`
22+
// +kubebuilder:validation:Required
23+
Spec DomainSpec `json:"spec,omitempty"`
24+
25+
// +kubebuilder:default={conditions: {{type: "Verified", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "VerifiedDNS", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "VerifiedHTTP", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}}
2626
Status DomainStatus `json:"status,omitempty"`
2727
}
2828

2929
// DomainSpec defines the desired state of Domain
3030
type DomainSpec struct {
3131
// DomainName is the fully qualified domain name (FQDN) to be managed
32+
//
3233
// +kubebuilder:validation:Required
3334
// +kubebuilder:validation:MinLength=1
3435
// +kubebuilder:validation:MaxLength=253
3536
// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
37+
// +kubebuilder:validation:XValidation:message="A domain name is immutable and cannot be changed after creation",rule="oldSelf == '' || self == oldSelf"
38+
// +kubebuilder:validation:XValidation:message="Must have at least two segments separated by dots",rule="self.indexOf('.') != -1"
3639
DomainName string `json:"domainName"`
3740
}
3841

@@ -43,9 +46,49 @@ type DomainStatus struct {
4346
Conditions []metav1.Condition `json:"conditions,omitempty"`
4447
}
4548

49+
const (
50+
// This condition is true when Domain ownership has been verified via either
51+
// DNS or HTTP.
52+
DomainConditionVerified = "Verified"
53+
54+
// This condition tracks verification attempts via DNS.
55+
DomainConditionVerifiedDNS = "VerifiedDNS"
56+
57+
// This condition tracks verification attempts via HTTP.
58+
DomainConditionVerifiedHTTP = "VerifiedHTTP"
59+
)
60+
61+
const (
62+
// DomainReasonPendingVerification indicates domain verification is in
63+
// progress
64+
DomainReasonPendingVerification = "PendingVerification"
65+
66+
// DomainReasonVerificationRecordContentMismatch indicates the
67+
// verification record content does not match expected values
68+
DomainReasonVerificationRecordContentMismatch = "VerificationRecordContentMismatch"
69+
70+
// DomainReasonVerificationRecordNotFound indicates the verification record
71+
// was not found
72+
DomainReasonVerificationRecordNotFound = "RecordNotFound"
73+
74+
// DomainReasonVerificationUnexpectedResponse indicates that an unexpected
75+
// response was encountered during verification.
76+
DomainReasonVerificationUnexpectedResponse = "UnexpectedResponse"
77+
78+
// DomainReasonVerificationInternalError indicates that an internal error
79+
// was encountered during verification.
80+
DomainReasonVerificationInternalError = "InternalError"
81+
82+
// DomainReasonVerified indicates domain ownership has been successfully
83+
// verified
84+
DomainReasonVerified = "Verified"
85+
)
86+
4687
// DomainVerificationStatus represents the verification status of a domain
4788
type DomainVerificationStatus struct {
48-
RequiredDNSRecords []DNSVerificationExpectedRecord `json:"requiredDNSRecords,omitempty"`
89+
DNSRecord DNSVerificationRecord `json:"dnsRecord,omitempty"`
90+
HTTPToken HTTPVerificationToken `json:"httpToken,omitempty"`
91+
NextVerificationAttempt metav1.Time `json:"nextVerificationAttempt,omitempty"`
4992
}
5093

5194
// DomainRegistrarStatus represents the registrar information for a domain
@@ -66,13 +109,18 @@ type DNSSECStatus struct {
66109
Signed bool `json:"signed"`
67110
}
68111

69-
// DNSVerificationExpectedRecord represents a DNS record required for verification
70-
type DNSVerificationExpectedRecord struct {
112+
// DNSVerificationRecord represents a DNS record required for verification
113+
type DNSVerificationRecord struct {
71114
Name string `json:"name"`
72115
Type string `json:"type"`
73116
Content string `json:"content"`
74117
}
75118

119+
type HTTPVerificationToken struct {
120+
URL string `json:"url"`
121+
Body string `json:"body"`
122+
}
123+
76124
// +kubebuilder:object:root=true
77125

78126
// DomainList contains a list of Domain

api/v1alpha/httpproxy_types.go

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,46 @@ import (
1010

1111
// HTTPProxySpec defines the desired state of HTTPProxy.
1212
type HTTPProxySpec struct {
13+
14+
// Hostnames defines a set of hostnames that should match against the HTTP
15+
// Host header to select a HTTPProxy used to process the request.
16+
//
17+
// Valid values for Hostnames are determined by RFC 1123 definition of a
18+
// hostname with 1 notable exception:
19+
//
20+
// 1. IPs are not allowed.
21+
//
22+
// Hostnames must be verified before being programmed. This is accomplished
23+
// via the use of `Domain` resources. A hostname is considered verified if any
24+
// verified `Domain` resource exists in the same namespace where the
25+
// `spec.domainName` of the resource either exactly matches the hostname, or
26+
// is a suffix match of the hostname. That means that a Domain with a
27+
// `spec.domainName` of `example.com` will match a hostname of
28+
// `test.example.com`, `foo.test.example.com`, and exactly `example.com`, but
29+
// not a hostname of `test-example.com`. If a `Domain` resource does not exist
30+
// that matches a hostname, one will automatically be created when the system
31+
// attempts to program the HTTPProxy.
32+
//
33+
// In addition to verifying ownership, hostnames must be unique across the
34+
// platform. If a hostname is already programmed on another resource, a
35+
// conflict will be encountered and communicated in the `HostnamesVerified`
36+
// condition.
37+
//
38+
// Hostnames which have been programmed will be listed in the
39+
// `status.hostnames` field. Any hostname which has not been programmed will
40+
// be listed in the `message` field of the `HostnamesVerified` condition with
41+
// an indication as to why it was not programmed.
42+
//
43+
// The system may automatically generate and associate hostnames with the
44+
// HTTPProxy. In such cases, these will be listed in the `status.hostnames`
45+
// field and do not require additional configuration by the user.
46+
//
47+
// Wildcard hostnames are not supported at this time.
48+
//
49+
// +kubebuilder:validation:Optional
50+
// +kubebuilder:validation:MaxItems=16
51+
Hostnames []gatewayv1.Hostname `json:"hostnames,omitempty"`
52+
1353
// Rules are a list of HTTP matchers, filters and actions.
1454
//
1555
// +kubebuilder:validation:Required
@@ -107,7 +147,7 @@ type HTTPProxyStatus struct {
107147
// Hostnames lists the hostnames that have been bound to the HTTPProxy.
108148
//
109149
// If this list does not match that defined in the HTTPProxy, see the
110-
// `Programmed` condition message for details.
150+
// `HostnamesVerified` condition message for details.
111151
Hostnames []gatewayv1.Hostname `json:"hostnames,omitempty"`
112152

113153
// Conditions describe the current conditions of the HTTPProxy.
@@ -126,6 +166,14 @@ const (
126166
// programmed into underlying Gateway resources, and those resources have also
127167
// been programmed.
128168
HTTPProxyConditionProgrammed = "Programmed"
169+
170+
// This condition is true when all hostnames defined in an HTTPProxy or a
171+
// Gateway listener have been verified.
172+
HTTPProxyConditionHostnamesVerified = "HostnamesVerified"
173+
174+
// This condition is present and true when a hostname defined in an HTTPProxy
175+
// is in use by another resource.
176+
HTTPProxyConditionHostnamesInUse = "HostnamesInUse"
129177
)
130178

131179
const (
@@ -144,6 +192,18 @@ const (
144192
// conditions when the status is "Unknown" and no controller has reconciled
145193
// the HTTPProxy.
146194
HTTPProxyReasonPending = "Pending"
195+
196+
// This reason is used with the "HostnamesVerified" condition when all hostnames
197+
// defined in an HTTPProxy or Gateway listener have been verified.
198+
HTTPProxyReasonHostnamesVerified = "HostnamesVerified"
199+
200+
// This reason is used with the a hostname defined in an HTTPProxy or Gateway
201+
// has not been verified.
202+
UnverifiedHostnamesPresent = "UnverifiedHostnamesPresent"
203+
204+
// This reason is used with the a hostname defined in an HTTPProxy or Gateway
205+
// is in use by another resource.
206+
HostnameInUseReason = "HostnameInUse"
147207
)
148208

149209
// +kubebuilder:object:root=true

api/v1alpha/zz_generated.deepcopy.go

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

cmd/main.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ func main() {
227227
os.Exit(1)
228228
}
229229

230-
if err := (&controller.DomainReconciler{}).SetupWithManager(mgr); err != nil {
230+
if err := (&controller.DomainReconciler{
231+
Config: serverConfig,
232+
}).SetupWithManager(mgr); err != nil {
231233
setupLog.Error(err, "unable to create controller", "controller", "Domain")
232234
os.Exit(1)
233235
}
@@ -238,11 +240,10 @@ func main() {
238240
}
239241

240242
validationOpts := validation.GatewayValidationOptions{
241-
ControllerName: serverConfig.Gateway.ControllerName,
242-
PermittedTLSOptions: serverConfig.Gateway.PermittedTLSOptions,
243-
ValidPortNumbers: serverConfig.Gateway.ValidPortNumbers,
244-
ValidProtocolTypes: serverConfig.Gateway.ValidProtocolTypes,
245-
CustomHostnameAllowList: serverConfig.Gateway.CustomHostnameAllowList,
243+
ControllerName: serverConfig.Gateway.ControllerName,
244+
PermittedTLSOptions: serverConfig.Gateway.PermittedTLSOptions,
245+
ValidPortNumbers: serverConfig.Gateway.ValidPortNumbers,
246+
ValidProtocolTypes: serverConfig.Gateway.ValidProtocolTypes,
246247
}
247248

248249
if err := networkinggatewayv1webhooks.SetupGatewayWebhookWithManager(mgr, validationOpts); err != nil {

0 commit comments

Comments
 (0)