Skip to content

Commit

Permalink
Copy MGC DNS apis, controllers and packages
Browse files Browse the repository at this point in the history
Copy all DNS apis and logic from MGC (DNSRecord, ManagedZone and DNSHealthCheck).
MGC Version: https://github.com/Kuadrant/multicluster-gateway-controller/tree/d2e05a088a57bfb1ecb7c486d8fd6c48de439a4f

Add openshift-goimports make targets and hack/verify-imports.sh script.
  • Loading branch information
mikenairn committed Feb 2, 2024
1 parent 0f8c4ce commit 044942d
Show file tree
Hide file tree
Showing 41 changed files with 5,151 additions and 296 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ RUN go mod download
# Copy the go source
COPY cmd/main.go cmd/main.go
COPY api/ api/
COPY internal/controller/ internal/controller/
COPY internal/ internal/

# Build
# the GOARCH has not a default value to allow the binary be built according to the host where the command
Expand Down
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ fmt: ## Run go fmt against code.
vet: ## Run go vet against code.
go vet ./...

.PHONY: imports
imports: openshift-goimports ## Run openshift goimports against code.
$(OPENSHIFT_GOIMPORTS) -m github.com/kuadrant/kuadrant-dns-operator -i github.com/kuadrant/kuadrant-operator

.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out
Expand Down Expand Up @@ -188,10 +192,12 @@ KUBECTL ?= kubectl
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest
OPENSHIFT_GOIMPORTS ?= $(LOCALBIN)/openshift-goimports

## Tool Versions
KUSTOMIZE_VERSION ?= v5.0.1
CONTROLLER_TOOLS_VERSION ?= v0.12.0
OPENSHIFT_GOIMPORTS_VERSION ?= c70783e636f2213cac683f6865d88c5edace3157

.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading.
Expand Down Expand Up @@ -230,6 +236,11 @@ OPERATOR_SDK = $(shell which operator-sdk)
endif
endif

.PHONY: openshift-goimports
openshift-goimports: $(OPENSHIFT_GOIMPORTS) ## Download openshift-goimports locally if necessary
$(OPENSHIFT_GOIMPORTS):
GOBIN=$(LOCALBIN) go install github.com/openshift-eng/openshift-goimports@$(OPENSHIFT_GOIMPORTS_VERSION)

.PHONY: bundle
bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files.
$(OPERATOR_SDK) generate kustomize manifests -q
Expand Down
42 changes: 33 additions & 9 deletions api/v1alpha1/dnshealthcheckprobe_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,44 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// DNSHealthCheckProbeSpec defines the desired state of DNSHealthCheckProbe
type DNSHealthCheckProbeSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
Port int `json:"port,omitempty"`
Host string `json:"host,omitempty"`
Address string `json:"address,omitempty"`
Path string `json:"path,omitempty"`
Protocol HealthProtocol `json:"protocol,omitempty"`
Interval metav1.Duration `json:"interval,omitempty"`
AdditionalHeadersRef *AdditionalHeadersRef `json:"additionalHeadersRef,omitempty"`
FailureThreshold *int `json:"failureThreshold,omitempty"`
ExpectedResponses []int `json:"expectedResponses,omitempty"`
AllowInsecureCertificate bool `json:"allowInsecureCertificate,omitempty"`
}

// Foo is an example field of DNSHealthCheckProbe. Edit dnshealthcheckprobe_types.go to remove/update
Foo string `json:"foo,omitempty"`
type AdditionalHeadersRef struct {
Name string `json:"name"`
}

type AdditionalHeaders []AdditionalHeader

type AdditionalHeader struct {
Name string `json:"name"`
Value string `json:"value"`
}

// DNSHealthCheckProbeStatus defines the observed state of DNSHealthCheckProbe
type DNSHealthCheckProbeStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
LastCheckedAt metav1.Time `json:"lastCheckedAt"`
ConsecutiveFailures int `json:"consecutiveFailures,omitempty"`
Reason string `json:"reason,omitempty"`
Status int `json:"status,omitempty"`
Healthy *bool `json:"healthy"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="Healthy",type="boolean",JSONPath=".status.healthy",description="DNSHealthCheckProbe healthy."
//+kubebuilder:printcolumn:name="Last Checked",type="date",JSONPath=".status.lastCheckedAt",description="Last checked at."

// DNSHealthCheckProbe is the Schema for the dnshealthcheckprobes API
type DNSHealthCheckProbe struct {
Expand All @@ -59,6 +77,12 @@ type DNSHealthCheckProbeList struct {
Items []DNSHealthCheckProbe `json:"items"`
}

func (p *DNSHealthCheckProbe) Default() {
if p.Spec.Protocol == "" {
p.Spec.Protocol = HttpProtocol
}
}

func init() {
SchemeBuilder.Register(&DNSHealthCheckProbe{}, &DNSHealthCheckProbeList{})
}
141 changes: 132 additions & 9 deletions api/v1alpha1/dnsrecord_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,135 @@ limitations under the License.
package v1alpha1

import (
"fmt"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// ProviderSpecificProperty holds the name and value of a configuration which is specific to individual DNS providers
type ProviderSpecificProperty struct {
Name string `json:"name,omitempty"`
Value string `json:"value,omitempty"`
}

// Targets is a representation of a list of targets for an endpoint.
type Targets []string

// TTL is a structure defining the TTL of a DNS record
type TTL int64

// Labels store metadata related to the endpoint
// it is then stored in a persistent storage via serialization
type Labels map[string]string

// ProviderSpecific holds configuration which is specific to individual DNS providers
type ProviderSpecific []ProviderSpecificProperty

// Endpoint is a high-level way of a connection between a service and an IP
type Endpoint struct {
// The hostname of the DNS record
DNSName string `json:"dnsName,omitempty"`
// The targets the DNS record points to
Targets Targets `json:"targets,omitempty"`
// RecordType type of record, e.g. CNAME, A, SRV, TXT etc
RecordType string `json:"recordType,omitempty"`
// Identifier to distinguish multiple records with the same name and type (e.g. Route53 records with routing policies other than 'simple')
SetIdentifier string `json:"setIdentifier,omitempty"`
// TTL for the record
RecordTTL TTL `json:"recordTTL,omitempty"`
// Labels stores labels defined for the Endpoint
// +optional
Labels Labels `json:"labels,omitempty"`
// ProviderSpecific stores provider specific config
// +optional
ProviderSpecific ProviderSpecific `json:"providerSpecific,omitempty"`
}

// SetID returns an id that should be unique across a set of endpoints
func (e *Endpoint) SetID() string {
return e.DNSName + e.SetIdentifier
}

// WithSetIdentifier applies the given set identifier to the endpoint.
func (e *Endpoint) WithSetIdentifier(setIdentifier string) *Endpoint {
e.SetIdentifier = setIdentifier
return e
}

// GetProviderSpecificProperty returns a ProviderSpecificProperty if the property exists.
func (e *Endpoint) GetProviderSpecificProperty(key string) (ProviderSpecificProperty, bool) {
for _, providerSpecific := range e.ProviderSpecific {
if providerSpecific.Name == key {
return providerSpecific, true
}
}
return ProviderSpecificProperty{}, false
}

// SetProviderSpecific sets a provider specific key/value pair.
func (e *Endpoint) SetProviderSpecific(name, value string) {
if e.ProviderSpecific == nil {
e.ProviderSpecific = ProviderSpecific{}
}

for i, pair := range e.ProviderSpecific {
if pair.Name == name {
e.ProviderSpecific[i].Value = value
return
}
}

e.ProviderSpecific = append(e.ProviderSpecific, ProviderSpecificProperty{
Name: name,
Value: value,
})
}

func (e *Endpoint) String() string {
return fmt.Sprintf("%s %d IN %s %s %s %s", e.DNSName, e.RecordTTL, e.RecordType, e.SetIdentifier, e.Targets, e.ProviderSpecific)
}

// DNSRecordSpec defines the desired state of DNSRecord
type DNSRecordSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// Foo is an example field of DNSRecord. Edit dnsrecord_types.go to remove/update
Foo string `json:"foo,omitempty"`
// +kubebuilder:validation:Required
// +required
ManagedZoneRef *ManagedZoneReference `json:"managedZone,omitempty"`
// +kubebuilder:validation:MinItems=1
// +optional
Endpoints []*Endpoint `json:"endpoints,omitempty"`
}

// DNSRecordStatus defines the observed state of DNSRecord
type DNSRecordStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file

// conditions are any conditions associated with the record in the managed zone.
//
// If publishing the record fails, the "Failed" condition will be set with a
// reason and message describing the cause of the failure.
Conditions []metav1.Condition `json:"conditions,omitempty"`

// observedGeneration is the most recently observed generation of the
// DNSRecord. When the DNSRecord is updated, the controller updates the
// corresponding record in each managed zone. If an update for a
// particular zone fails, that failure is recorded in the status
// condition for the zone so that the controller can determine that it
// needs to retry the update for that specific zone.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`

// endpoints are the last endpoints that were successfully published by the provider
//
// Provides a simple mechanism to store the current provider records in order to
// delete any that are no longer present in DNSRecordSpec.Endpoints
//
// Note: This will not be required if/when we switch to using external-dns since when
// running with a "sync" policy it will clean up unused records automatically.
Endpoints []*Endpoint `json:"endpoints,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="DNSRecord ready."

// DNSRecord is the Schema for the dnsrecords API
type DNSRecord struct {
Expand All @@ -59,6 +165,23 @@ type DNSRecordList struct {
Items []DNSRecord `json:"items"`
}

// DNSRecordType is a DNS resource record type.
// +kubebuilder:validation:Enum=CNAME;A
type DNSRecordType string

const (
// CNAMERecordType is an RFC 1035 CNAME record.
CNAMERecordType DNSRecordType = "CNAME"

// ARecordType is an RFC 1035 A record.
ARecordType DNSRecordType = "A"

// NSRecordType is a name server record.
NSRecordType DNSRecordType = "NS"

DefaultGeo string = "default"
)

func init() {
SchemeBuilder.Register(&DNSRecord{}, &DNSRecordList{})
}
56 changes: 56 additions & 0 deletions api/v1alpha1/health_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright 2024.
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.
*/

package v1alpha1

import "strings"

// HealthProtocol represents the protocol to use when making a health check request
type HealthProtocol string

const (
HttpProtocol HealthProtocol = "HTTP"
HttpsProtocol HealthProtocol = "HTTPS"
)

func NewHealthProtocol(p string) HealthProtocol {
switch strings.ToUpper(p) {
case "HTTPS":
return HttpsProtocol
case "HTTP":
return HttpProtocol
}
return HttpProtocol
}

func (p HealthProtocol) ToScheme() string {
switch p {
case HttpProtocol:
return "http"
case HttpsProtocol:
return "https"
default:
return "http"
}
}

func (p HealthProtocol) IsHttp() bool {
return p == HttpProtocol
}

func (p HealthProtocol) IsHttps() bool {
return p == HttpsProtocol
}
Loading

0 comments on commit 044942d

Please sign in to comment.