From 7c5b6bf0325cf52fb705646cc5c13eca8fded1ec Mon Sep 17 00:00:00 2001 From: Zhiying Lin <54013513+zhiying-lin@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:06:05 +0800 Subject: [PATCH] interface: define traffic manager apis (#191) --- api/v1alpha1/internalserviceexport_types.go | 14 + api/v1alpha1/trafficmanagerbackend_types.go | 149 ++++++++ api/v1alpha1/trafficmanagerprofile_types.go | 156 +++++++++ api/v1alpha1/zz_generated.deepcopy.go | 329 +++++++++++++++++- ...leet.azure.com_internalserviceexports.yaml | 20 ++ ...leet.azure.com_trafficmanagerbackends.yaml | 222 ++++++++++++ ...leet.azure.com_trafficmanagerprofiles.yaml | 195 +++++++++++ 7 files changed, 1083 insertions(+), 2 deletions(-) create mode 100644 api/v1alpha1/trafficmanagerbackend_types.go create mode 100644 api/v1alpha1/trafficmanagerprofile_types.go create mode 100644 config/crd/bases/networking.fleet.azure.com_trafficmanagerbackends.yaml create mode 100644 config/crd/bases/networking.fleet.azure.com_trafficmanagerprofiles.yaml diff --git a/api/v1alpha1/internalserviceexport_types.go b/api/v1alpha1/internalserviceexport_types.go index ff783c1f..39993590 100644 --- a/api/v1alpha1/internalserviceexport_types.go +++ b/api/v1alpha1/internalserviceexport_types.go @@ -6,6 +6,7 @@ Licensed under the MIT license. package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -18,6 +19,19 @@ type InternalServiceExportSpec struct { // The reference to the source Service. // +kubebuilder:validation:Required ServiceReference ExportedObjectReference `json:"serviceReference"` + // Type is the type of the Service in each cluster. + Type corev1.ServiceType `json:"type,omitempty"` + // IsDNSLabelConfigured determines if the Service has a DNS label configured. + // A valid DNS label should be configured when the public IP address of the Service is configured as an Azure Traffic + // Manager endpoint. + // Reference link: + // * https://cloud-provider-azure.sigs.k8s.io/topics/loadbalancer/ + // * https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-endpoint-types#azure-endpoints + IsDNSLabelConfigured bool `json:"isDNSLabelConfigured,omitempty"` + // IsInternalLoadBalancer determines if the Service is an internal load balancer type. + IsInternalLoadBalancer bool `json:"isInternalLoadBalancer,omitempty"` + // PublicIPResourceID is the Azure Resource URI of public IP. This is only applicable for Load Balancer type Services. + PublicIPResourceID *string `json:"externalIPResourceID,omitempty"` } // InternalServiceExportStatus contains the current status of an InternalServiceExport. diff --git a/api/v1alpha1/trafficmanagerbackend_types.go b/api/v1alpha1/trafficmanagerbackend_types.go new file mode 100644 index 00000000..b3e1084c --- /dev/null +++ b/api/v1alpha1/trafficmanagerbackend_types.go @@ -0,0 +1,149 @@ +package v1alpha1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Namespaced,categories={fleet-networking},shortName=tme +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:JSONPath=`.spec.profile.name`,name="Profile",type=string +// +kubebuilder:printcolumn:JSONPath=`.spec.profile.namespace`,name="Profile-Namespace",type=string +// +kubebuilder:printcolumn:JSONPath=`.spec.endpointRef.name`,name="Backend",type=string +// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=='Accepted')].status`,name="Is-Accepted",type=string +// +kubebuilder:printcolumn:JSONPath=`.metadata.creationTimestamp`,name="Age",type=date + +// TrafficManagerBackend is used to manage the Azure Traffic Manager Endpoints using cloud native way. +// A backend contains one or more endpoints. Therefore, the controller may create multiple endpoints under the Traffic +// Manager Profile. +// https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-endpoint-types +type TrafficManagerBackend struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // The desired state of TrafficManagerBackend. + Spec TrafficManagerBackendSpec `json:"spec"` + + // The observed status of TrafficManagerBackend. + // +optional + Status TrafficManagerBackendStatus `json:"status,omitempty"` +} + +type TrafficManagerBackendSpec struct { + // +required + // immutable + // Which TrafficManagerProfile the backend should be attached to. + Profile TrafficManagerProfileRef `json:"profile"` + + // The reference to a backend. + // immutable + // +required + Backend TrafficManagerBackendRef `json:"backend"` + + // The total weight of endpoints behind the serviceImport when using the 'Weighted' traffic routing method. + // Possible values are from 1 to 1000. + // By default, the routing method is 'Weighted', so that it is required for now. + // +optional + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=1000 + // For example, if there are two clusters exporting the service via public ip, each public ip will be configured + // as "Weight"/2. + Weight *int64 `json:"weight,omitempty"` +} + +// TrafficManagerProfileRef is a reference to a trafficManagerProfile object in the same namespace as the TrafficManagerBackend object. +type TrafficManagerProfileRef struct { + // Name is the name of the referenced trafficManagerProfile. + Name string `json:"name"` +} + +// TrafficManagerBackendRef is the reference to a backend. +// Currently, we only support one backend type: ServiceImport. +type TrafficManagerBackendRef struct { + // Name is the reference to the ServiceImport in the same namespace as the TrafficManagerBackend object. + // +required + Name string `json:"name"` +} + +// TrafficManagerEndpointStatus is the status of Azure Traffic Manager endpoint which is successfully accepted under the traffic +// manager Profile. +type TrafficManagerEndpointStatus struct { + // Name of the endpoint. + // +required + Name string `json:"name"` + + // The weight of this endpoint when using the 'Weighted' traffic routing method. + // Possible values are from 1 to 1000. + // +optional + Weight *int64 `json:"weight,omitempty"` + + // The fully-qualified DNS name or IP address of the endpoint. + // +optional + Target *string `json:"target,omitempty"` + + // Cluster is where the endpoint is exported from. + // +optional + Cluster *ClusterStatus `json:"cluster,omitempty"` +} + +type TrafficManagerBackendStatus struct { + // Endpoints contains a list of accepted Azure endpoints which are created or updated under the traffic manager Profile. + // +optional + Endpoints []TrafficManagerEndpointStatus `json:"endpoints,omitempty"` + + // Current backend status. + // +optional + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +// TrafficManagerBackendConditionType is a type of condition associated with a TrafficManagerBackendStatus. This type +// should be used within the TrafficManagerBackendStatus.Conditions field. +type TrafficManagerBackendConditionType string + +// TrafficManagerBackendConditionReason defines the set of reasons that explain why a particular backend has been raised. +type TrafficManagerBackendConditionReason string + +const ( + // TrafficManagerBackendConditionAccepted condition indicates whether endpoints have been created or updated for the profile. + // This does not indicate whether or not the configuration has been propagated to the data plane. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // * "Pending" + TrafficManagerBackendConditionAccepted TrafficManagerBackendConditionReason = "Accepted" + + // TrafficManagerBackendReasonAccepted is used with the "Accepted" condition when the condition is True. + TrafficManagerBackendReasonAccepted TrafficManagerBackendConditionReason = "Accepted" + + // TrafficManagerBackendReasonInvalid is used with the "Accepted" condition when one or + // more endpoint references have an invalid or unsupported configuration + // and cannot be configured on the Profile with more details in the message. + TrafficManagerBackendReasonInvalid TrafficManagerBackendConditionReason = "Invalid" + + // TrafficManagerBackendReasonPending is used with the "Accepted" when creating or updating endpoint hits an internal error with + // more details in the message and the controller will keep retry. + TrafficManagerBackendReasonPending TrafficManagerBackendConditionReason = "Pending" +) + +//+kubebuilder:object:root=true + +// TrafficManagerBackendList contains a list of TrafficManagerBackend. +type TrafficManagerBackendList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + // +listType=set + Items []TrafficManagerBackend `json:"items"` +} + +func init() { + SchemeBuilder.Register(&TrafficManagerBackend{}, &TrafficManagerBackendList{}) +} diff --git a/api/v1alpha1/trafficmanagerprofile_types.go b/api/v1alpha1/trafficmanagerprofile_types.go new file mode 100644 index 00000000..888c2b5f --- /dev/null +++ b/api/v1alpha1/trafficmanagerprofile_types.go @@ -0,0 +1,156 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Namespaced,categories={fleet-networking},shortName=tmp +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:JSONPath=`.status.dnsName`,name="DNS-Name",type=string +// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=='Programmed')].status`,name="Is-Programmed",type=string +// +kubebuilder:printcolumn:JSONPath=`.metadata.creationTimestamp`,name="Age",type=date + +// TrafficManagerProfile is used to manage a simple Azure Traffic Manager Profile using cloud native way. +// https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-overview +type TrafficManagerProfile struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // The desired state of TrafficManagerProfile. + Spec TrafficManagerProfileSpec `json:"spec"` + + // The observed status of TrafficManagerProfile. + // +optional + Status TrafficManagerProfileStatus `json:"status,omitempty"` +} + +// TrafficManagerProfileSpec defines the desired state of TrafficManagerProfile. +// For now, only the "Weighted" traffic routing method is supported. +type TrafficManagerProfileSpec struct { + // The endpoint monitoring settings of the Traffic Manager profile. + // +optional + MonitorConfig *MonitorConfig `json:"monitorConfig,omitempty"` +} + +// MonitorConfig defines the endpoint monitoring settings of the Traffic Manager profile. +// https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-monitoring +type MonitorConfig struct { + // The monitor interval for endpoints in this profile. This is the interval at which Traffic Manager will check the health + // of each endpoint in this profile. + // You can specify two values here: 30 seconds (normal probing) and 10 seconds (fast probing). + // +optional + IntervalInSeconds *int64 `json:"intervalInSeconds,omitempty"` + + // The path relative to the endpoint domain name used to probe for endpoint health. + // +optional + Path *string `json:"path,omitempty"` + + // The TCP port used to probe for endpoint health. + // +optional + Port *int64 `json:"port,omitempty"` + + // The protocol (HTTP, HTTPS or TCP) used to probe for endpoint health. + // +kubebuilder:validation:Enum=HTTP;HTTPS;TCP + // +optional + Protocol *TrafficManagerMonitorProtocol `json:"protocol,omitempty"` + + // The monitor timeout for endpoints in this profile. This is the time that Traffic Manager allows endpoints in this profile + // to response to the health check. + // +optional + // * If the IntervalInSeconds is set to 30 seconds, then you can set the Timeout value between 5 and 10 seconds. + // If no value is specified, it uses a default value of 10 seconds. + // * If the IntervalInSeconds is set to 10 seconds, then you can set the Timeout value between 5 and 9 seconds. + // If no Timeout value is specified, it uses a default value of 9 seconds. + TimeoutInSeconds *int64 `json:"timeoutInSeconds,omitempty"` + + // The number of consecutive failed health check that Traffic Manager tolerates before declaring an endpoint in this profile + // Degraded after the next failed health check. + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=9 + ToleratedNumberOfFailures *int64 `json:"toleratedNumberOfFailures,omitempty"` +} + +// TrafficManagerMonitorProtocol defines the protocol used to probe for endpoint health. +type TrafficManagerMonitorProtocol string + +const ( + TrafficManagerMonitorProtocolHTTP TrafficManagerMonitorProtocol = "HTTP" + TrafficManagerMonitorProtocolHTTPS TrafficManagerMonitorProtocol = "HTTPS" + TrafficManagerMonitorProtocolTCP TrafficManagerMonitorProtocol = "TCP" +) + +type TrafficManagerProfileStatus struct { + // DNSName is the fully-qualified domain name (FQDN) of the Traffic Manager profile. + // It consists of profile name and the DNS domain name used by Azure Traffic Manager to form the fully-qualified + // domain name (FQDN) of the profile. + // For example, ".trafficmanager.net" + // +optional + DNSName *string `json:"dnsName,omitempty"` + + // Current profile status. + // +optional + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +// TrafficManagerProfileConditionType is a type of condition associated with a +// Traffic Manager Profile. This type should be used within the TrafficManagerProfileStatus.Conditions field. +type TrafficManagerProfileConditionType string + +// TrafficManagerProfileConditionReason defines the set of reasons that explain why a +// particular profile condition type has been raised. +type TrafficManagerProfileConditionReason string + +const ( + // TrafficManagerProfileConditionProgrammed condition indicates whether a profile has been generated that is assumed to be ready + // soon in the underlying data plane. This does not indicate whether or not the configuration has been propagated + // to the data plane. + // + // It is a positive-polarity summary condition, and so should always be + // present on the resource with ObservedGeneration set. + // + // Possible reasons for this condition to be True are: + // + // * "Programmed" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // * "DNSNameNotAvailable" + // * "Pending" + TrafficManagerProfileConditionProgrammed TrafficManagerProfileConditionType = "Programmed" + + // TrafficManagerProfileReasonProgrammed is used with the "Programmed" condition when the condition is true. + TrafficManagerProfileReasonProgrammed TrafficManagerProfileConditionReason = "Programmed" + + // TrafficManagerProfileReasonInvalid is used with the "Programmed" when the profile is syntactically or semantically invalid. + TrafficManagerProfileReasonInvalid TrafficManagerProfileConditionReason = "Invalid" + + // TrafficManagerProfileReasonDNSNameNotAvailable is used with the "Programmed" condition when the generated DNS name is not available. + TrafficManagerProfileReasonDNSNameNotAvailable TrafficManagerProfileConditionReason = "DNSNameNotAvailable" + + // TrafficManagerProfileReasonPending is used with the "Programmed" when creating or updating the profile hits an internal error + // with more details in the message and the controller will keep retry. + TrafficManagerProfileReasonPending TrafficManagerProfileConditionReason = "Pending" +) + +//+kubebuilder:object:root=true + +// TrafficManagerProfileList contains a list of TrafficManagerProfile. +type TrafficManagerProfileList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + // +listType=set + Items []TrafficManagerProfile `json:"items"` +} + +func init() { + SchemeBuilder.Register(&TrafficManagerProfile{}, &TrafficManagerProfileList{}) +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 1e038c49..028f2040 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright (c) Microsoft Corporation. @@ -12,7 +11,7 @@ package v1alpha1 import ( corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/discovery/v1" + "k8s.io/api/discovery/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -285,6 +284,11 @@ func (in *InternalServiceExportSpec) DeepCopyInto(out *InternalServiceExportSpec } } in.ServiceReference.DeepCopyInto(&out.ServiceReference) + if in.PublicIPResourceID != nil { + in, out := &in.PublicIPResourceID, &out.PublicIPResourceID + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InternalServiceExportSpec. @@ -394,6 +398,51 @@ func (in *InternalServiceImportSpec) DeepCopy() *InternalServiceImportSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MonitorConfig) DeepCopyInto(out *MonitorConfig) { + *out = *in + if in.IntervalInSeconds != nil { + in, out := &in.IntervalInSeconds, &out.IntervalInSeconds + *out = new(int64) + **out = **in + } + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(string) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int64) + **out = **in + } + if in.Protocol != nil { + in, out := &in.Protocol, &out.Protocol + *out = new(TrafficManagerMonitorProtocol) + **out = **in + } + if in.TimeoutInSeconds != nil { + in, out := &in.TimeoutInSeconds, &out.TimeoutInSeconds + *out = new(int64) + **out = **in + } + if in.ToleratedNumberOfFailures != nil { + in, out := &in.ToleratedNumberOfFailures, &out.ToleratedNumberOfFailures + *out = new(int64) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonitorConfig. +func (in *MonitorConfig) DeepCopy() *MonitorConfig { + if in == nil { + return nil + } + out := new(MonitorConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MultiClusterService) DeepCopyInto(out *MultiClusterService) { *out = *in @@ -739,3 +788,279 @@ func (in *ServicePort) DeepCopy() *ServicePort { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerBackend) DeepCopyInto(out *TrafficManagerBackend) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerBackend. +func (in *TrafficManagerBackend) DeepCopy() *TrafficManagerBackend { + if in == nil { + return nil + } + out := new(TrafficManagerBackend) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TrafficManagerBackend) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerBackendList) DeepCopyInto(out *TrafficManagerBackendList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TrafficManagerBackend, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerBackendList. +func (in *TrafficManagerBackendList) DeepCopy() *TrafficManagerBackendList { + if in == nil { + return nil + } + out := new(TrafficManagerBackendList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TrafficManagerBackendList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerBackendRef) DeepCopyInto(out *TrafficManagerBackendRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerBackendRef. +func (in *TrafficManagerBackendRef) DeepCopy() *TrafficManagerBackendRef { + if in == nil { + return nil + } + out := new(TrafficManagerBackendRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerBackendSpec) DeepCopyInto(out *TrafficManagerBackendSpec) { + *out = *in + out.Profile = in.Profile + out.Backend = in.Backend + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int64) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerBackendSpec. +func (in *TrafficManagerBackendSpec) DeepCopy() *TrafficManagerBackendSpec { + if in == nil { + return nil + } + out := new(TrafficManagerBackendSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerBackendStatus) DeepCopyInto(out *TrafficManagerBackendStatus) { + *out = *in + if in.Endpoints != nil { + in, out := &in.Endpoints, &out.Endpoints + *out = make([]TrafficManagerEndpointStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerBackendStatus. +func (in *TrafficManagerBackendStatus) DeepCopy() *TrafficManagerBackendStatus { + if in == nil { + return nil + } + out := new(TrafficManagerBackendStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerEndpointStatus) DeepCopyInto(out *TrafficManagerEndpointStatus) { + *out = *in + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int64) + **out = **in + } + if in.Target != nil { + in, out := &in.Target, &out.Target + *out = new(string) + **out = **in + } + if in.Cluster != nil { + in, out := &in.Cluster, &out.Cluster + *out = new(ClusterStatus) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerEndpointStatus. +func (in *TrafficManagerEndpointStatus) DeepCopy() *TrafficManagerEndpointStatus { + if in == nil { + return nil + } + out := new(TrafficManagerEndpointStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfile) DeepCopyInto(out *TrafficManagerProfile) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfile. +func (in *TrafficManagerProfile) DeepCopy() *TrafficManagerProfile { + if in == nil { + return nil + } + out := new(TrafficManagerProfile) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TrafficManagerProfile) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfileList) DeepCopyInto(out *TrafficManagerProfileList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TrafficManagerProfile, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfileList. +func (in *TrafficManagerProfileList) DeepCopy() *TrafficManagerProfileList { + if in == nil { + return nil + } + out := new(TrafficManagerProfileList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TrafficManagerProfileList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfileRef) DeepCopyInto(out *TrafficManagerProfileRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfileRef. +func (in *TrafficManagerProfileRef) DeepCopy() *TrafficManagerProfileRef { + if in == nil { + return nil + } + out := new(TrafficManagerProfileRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfileSpec) DeepCopyInto(out *TrafficManagerProfileSpec) { + *out = *in + if in.MonitorConfig != nil { + in, out := &in.MonitorConfig, &out.MonitorConfig + *out = new(MonitorConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfileSpec. +func (in *TrafficManagerProfileSpec) DeepCopy() *TrafficManagerProfileSpec { + if in == nil { + return nil + } + out := new(TrafficManagerProfileSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfileStatus) DeepCopyInto(out *TrafficManagerProfileStatus) { + *out = *in + if in.DNSName != nil { + in, out := &in.DNSName, &out.DNSName + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfileStatus. +func (in *TrafficManagerProfileStatus) DeepCopy() *TrafficManagerProfileStatus { + if in == nil { + return nil + } + out := new(TrafficManagerProfileStatus) + in.DeepCopyInto(out) + return out +} diff --git a/config/crd/bases/networking.fleet.azure.com_internalserviceexports.yaml b/config/crd/bases/networking.fleet.azure.com_internalserviceexports.yaml index 9d49f66b..d318e7cd 100644 --- a/config/crd/bases/networking.fleet.azure.com_internalserviceexports.yaml +++ b/config/crd/bases/networking.fleet.azure.com_internalserviceexports.yaml @@ -47,6 +47,23 @@ spec: InternalServiceExportSpec specifies the spec of an exported Service; at this stage only the ports of an exported Service are sync'd. properties: + externalIPResourceID: + description: PublicIPResourceID is the Azure Resource URI of public + IP. This is only applicable for Load Balancer type Services. + type: string + isDNSLabelConfigured: + description: |- + IsDNSLabelConfigured determines if the Service has a DNS label configured. + A valid DNS label should be configured when the public IP address of the Service is configured as an Azure Traffic + Manager endpoint. + Reference link: + * https://cloud-provider-azure.sigs.k8s.io/topics/loadbalancer/ + * https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-endpoint-types#azure-endpoints + type: boolean + isInternalLoadBalancer: + description: IsInternalLoadBalancer determines if the Service is an + internal load balancer type. + type: boolean ports: description: A list of ports exposed by the exported Service. items: @@ -146,6 +163,9 @@ spec: - uid type: object x-kubernetes-map-type: atomic + type: + description: Type is the type of the Service in each cluster. + type: string required: - ports - serviceReference diff --git a/config/crd/bases/networking.fleet.azure.com_trafficmanagerbackends.yaml b/config/crd/bases/networking.fleet.azure.com_trafficmanagerbackends.yaml new file mode 100644 index 00000000..92bddf9a --- /dev/null +++ b/config/crd/bases/networking.fleet.azure.com_trafficmanagerbackends.yaml @@ -0,0 +1,222 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: trafficmanagerbackends.networking.fleet.azure.com +spec: + group: networking.fleet.azure.com + names: + categories: + - fleet-networking + kind: TrafficManagerBackend + listKind: TrafficManagerBackendList + plural: trafficmanagerbackends + shortNames: + - tme + singular: trafficmanagerbackend + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.profile.name + name: Profile + type: string + - jsonPath: .spec.profile.namespace + name: Profile-Namespace + type: string + - jsonPath: .spec.endpointRef.name + name: Backend + type: string + - jsonPath: .status.conditions[?(@.type=='Accepted')].status + name: Is-Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TrafficManagerBackend is used to manage the Azure Traffic Manager Endpoints using cloud native way. + A backend contains one or more endpoints. Therefore, the controller may create multiple endpoints under the Traffic + Manager Profile. + https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-endpoint-types + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired state of TrafficManagerBackend. + properties: + backend: + description: |- + The reference to a backend. + immutable + properties: + name: + description: Name is the reference to the ServiceImport in the + same namespace as the TrafficManagerBackend object. + type: string + required: + - name + type: object + profile: + description: |- + immutable + Which TrafficManagerProfile the backend should be attached to. + properties: + name: + description: Name is the name of the referenced trafficManagerProfile. + type: string + required: + - name + type: object + weight: + description: |- + The total weight of endpoints behind the serviceImport when using the 'Weighted' traffic routing method. + Possible values are from 1 to 1000. + By default, the routing method is 'Weighted', so that it is required for now. + For example, if there are two clusters exporting the service via public ip, each public ip will be configured + as "Weight"/2. + format: int64 + maximum: 1000 + minimum: 1 + type: integer + required: + - backend + - profile + type: object + status: + description: The observed status of TrafficManagerBackend. + properties: + conditions: + description: Current backend status. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + endpoints: + description: Endpoints contains a list of accepted Azure endpoints + which are created or updated under the traffic manager Profile. + items: + description: |- + TrafficManagerEndpointStatus is the status of Azure Traffic Manager endpoint which is successfully accepted under the traffic + manager Profile. + properties: + cluster: + description: Cluster is where the endpoint is exported from. + properties: + cluster: + description: cluster is the name of the exporting cluster. + Must be a valid RFC-1123 DNS label. + type: string + required: + - cluster + type: object + name: + description: Name of the endpoint. + type: string + target: + description: The fully-qualified DNS name or IP address of the + endpoint. + type: string + weight: + description: |- + The weight of this endpoint when using the 'Weighted' traffic routing method. + Possible values are from 1 to 1000. + format: int64 + type: integer + required: + - name + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/networking.fleet.azure.com_trafficmanagerprofiles.yaml b/config/crd/bases/networking.fleet.azure.com_trafficmanagerprofiles.yaml new file mode 100644 index 00000000..f86470bb --- /dev/null +++ b/config/crd/bases/networking.fleet.azure.com_trafficmanagerprofiles.yaml @@ -0,0 +1,195 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: trafficmanagerprofiles.networking.fleet.azure.com +spec: + group: networking.fleet.azure.com + names: + categories: + - fleet-networking + kind: TrafficManagerProfile + listKind: TrafficManagerProfileList + plural: trafficmanagerprofiles + shortNames: + - tmp + singular: trafficmanagerprofile + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.dnsName + name: DNS-Name + type: string + - jsonPath: .status.conditions[?(@.type=='Programmed')].status + name: Is-Programmed + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TrafficManagerProfile is used to manage a simple Azure Traffic Manager Profile using cloud native way. + https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-overview + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired state of TrafficManagerProfile. + properties: + monitorConfig: + description: The endpoint monitoring settings of the Traffic Manager + profile. + properties: + intervalInSeconds: + description: |- + The monitor interval for endpoints in this profile. This is the interval at which Traffic Manager will check the health + of each endpoint in this profile. + You can specify two values here: 30 seconds (normal probing) and 10 seconds (fast probing). + format: int64 + type: integer + path: + description: The path relative to the endpoint domain name used + to probe for endpoint health. + type: string + port: + description: The TCP port used to probe for endpoint health. + format: int64 + type: integer + protocol: + description: The protocol (HTTP, HTTPS or TCP) used to probe for + endpoint health. + enum: + - HTTP + - HTTPS + - TCP + type: string + timeoutInSeconds: + description: |- + The monitor timeout for endpoints in this profile. This is the time that Traffic Manager allows endpoints in this profile + to response to the health check. + * If the IntervalInSeconds is set to 30 seconds, then you can set the Timeout value between 5 and 10 seconds. + If no value is specified, it uses a default value of 10 seconds. + * If the IntervalInSeconds is set to 10 seconds, then you can set the Timeout value between 5 and 9 seconds. + If no Timeout value is specified, it uses a default value of 9 seconds. + format: int64 + type: integer + toleratedNumberOfFailures: + description: |- + The number of consecutive failed health check that Traffic Manager tolerates before declaring an endpoint in this profile + Degraded after the next failed health check. + format: int64 + maximum: 9 + minimum: 0 + type: integer + type: object + type: object + status: + description: The observed status of TrafficManagerProfile. + properties: + conditions: + description: Current profile status. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + dnsName: + description: |- + DNSName is the fully-qualified domain name (FQDN) of the Traffic Manager profile. + It consists of profile name and the DNS domain name used by Azure Traffic Manager to form the fully-qualified + domain name (FQDN) of the profile. + For example, ".trafficmanager.net" + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {}