pkg/model/core/httproute.go (286 lines of code) (raw):
package core
import (
"context"
"reflect"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
"github.com/aws/aws-application-networking-k8s/pkg/utils"
)
const (
HttpRouteType RouteType = "http"
)
type HTTPRoute struct {
r gwv1.HTTPRoute
}
func NewHTTPRoute(route gwv1.HTTPRoute) *HTTPRoute {
return &HTTPRoute{r: route}
}
func GetHTTPRoute(ctx context.Context, client client.Client, routeNamespacedName types.NamespacedName) (Route, error) {
httpRoute := &gwv1.HTTPRoute{}
err := client.Get(ctx, routeNamespacedName, httpRoute)
if err != nil {
return nil, err
}
return NewHTTPRoute(*httpRoute), nil
}
func ListHTTPRoutes(context context.Context, client client.Client) ([]Route, error) {
routeList := &gwv1.HTTPRouteList{}
if err := client.List(context, routeList); err != nil {
return nil, err
}
var routes []Route
for _, route := range routeList.Items {
routes = append(routes, NewHTTPRoute(route))
}
return routes, nil
}
func (r *HTTPRoute) Spec() RouteSpec {
return &HTTPRouteSpec{r.r.Spec}
}
func (r *HTTPRoute) Status() RouteStatus {
return &HTTPRouteStatus{&r.r.Status}
}
func (r *HTTPRoute) Name() string {
return r.r.Name
}
func (r *HTTPRoute) Namespace() string {
return r.r.Namespace
}
func (r *HTTPRoute) DeletionTimestamp() *metav1.Time {
return r.r.DeletionTimestamp
}
func (r *HTTPRoute) DeepCopy() Route {
return &HTTPRoute{r: *r.r.DeepCopy()}
}
func (r *HTTPRoute) K8sObject() client.Object {
return &r.r
}
func (r *HTTPRoute) Inner() *gwv1.HTTPRoute {
return &r.r
}
func (r *HTTPRoute) GroupKind() metav1.GroupKind {
return metav1.GroupKind{
Group: gwv1.GroupName,
Kind: "HTTPRoute",
}
}
type HTTPRouteSpec struct {
s gwv1.HTTPRouteSpec
}
func (s *HTTPRouteSpec) ParentRefs() []gwv1.ParentReference {
return s.s.ParentRefs
}
func (s *HTTPRouteSpec) Hostnames() []gwv1.Hostname {
return s.s.Hostnames
}
func (s *HTTPRouteSpec) Rules() []RouteRule {
var rules []RouteRule
for _, rule := range s.s.Rules {
rules = append(rules, &HTTPRouteRule{rule})
}
return rules
}
func (s *HTTPRouteSpec) Equals(routeSpec RouteSpec) bool {
_, ok := routeSpec.(*HTTPRouteSpec)
if !ok {
return false
}
if !reflect.DeepEqual(s.ParentRefs(), routeSpec.ParentRefs()) {
return false
}
if !reflect.DeepEqual(s.Hostnames(), routeSpec.Hostnames()) {
return false
}
if len(s.Rules()) != len(routeSpec.Rules()) {
return false
}
for i, rule := range s.Rules() {
otherRule := routeSpec.Rules()[i]
if !rule.Equals(otherRule) {
return false
}
}
return true
}
type HTTPRouteStatus struct {
s *gwv1.HTTPRouteStatus
}
func (s *HTTPRouteStatus) Parents() []gwv1.RouteParentStatus {
return s.s.Parents
}
func (s *HTTPRouteStatus) SetParents(parents []gwv1.RouteParentStatus) {
s.s.Parents = parents
}
func (s *HTTPRouteStatus) UpdateParentRefs(parent gwv1.ParentReference, controllerName gwv1.GatewayController) {
for i, p := range s.Parents() {
if p.ParentRef.Name == parent.Name {
s.Parents()[i].ParentRef = parent
s.Parents()[i].ControllerName = controllerName
return
}
}
s.SetParents(append(s.Parents(), gwv1.RouteParentStatus{
ParentRef: parent,
ControllerName: controllerName,
}))
}
func (s *HTTPRouteStatus) UpdateRouteCondition(parent gwv1.ParentReference, condition metav1.Condition) {
for i, p := range s.Parents() {
if p.ParentRef.Name == parent.Name {
s.Parents()[i].Conditions = utils.GetNewConditions(p.Conditions, condition)
return
}
}
}
type HTTPRouteRule struct {
r gwv1.HTTPRouteRule
}
func (r *HTTPRouteRule) BackendRefs() []BackendRef {
var backendRefs []BackendRef
for _, backendRef := range r.r.BackendRefs {
backendRefs = append(backendRefs, &HTTPBackendRef{backendRef})
}
return backendRefs
}
func (r *HTTPRouteRule) Matches() []RouteMatch {
var routeMatches []RouteMatch
for _, routeMatch := range r.r.Matches {
routeMatches = append(routeMatches, &HTTPRouteMatch{routeMatch})
}
return routeMatches
}
func (r *HTTPRouteRule) Equals(routeRule RouteRule) bool {
other, ok := routeRule.(*HTTPRouteRule)
if !ok {
return false
}
if len(r.BackendRefs()) != len(other.BackendRefs()) {
return false
}
for i, backendRef := range r.BackendRefs() {
otherBackendRef := other.BackendRefs()[i]
if !backendRef.Equals(otherBackendRef) {
return false
}
}
if len(r.Matches()) != len(other.Matches()) {
return false
}
for i, match := range r.Matches() {
otherMatch := other.Matches()[i]
if !match.Equals(otherMatch) {
return false
}
}
return true
}
type HTTPBackendRef struct {
r gwv1.HTTPBackendRef
}
func NewHTTPBackendRef(r gwv1.HTTPBackendRef) HTTPBackendRef {
return HTTPBackendRef{r: r}
}
func (r *HTTPBackendRef) Weight() *int32 {
return r.r.Weight
}
func (r *HTTPBackendRef) Group() *gwv1.Group {
return r.r.Group
}
func (r *HTTPBackendRef) Kind() *gwv1.Kind {
return r.r.Kind
}
func (r *HTTPBackendRef) Name() gwv1.ObjectName {
return r.r.Name
}
func (r *HTTPBackendRef) Namespace() *gwv1.Namespace {
return r.r.Namespace
}
func (r *HTTPBackendRef) Port() *gwv1.PortNumber {
return r.r.Port
}
func (r *HTTPBackendRef) Equals(backendRef BackendRef) bool {
other, ok := backendRef.(*HTTPBackendRef)
if !ok {
return false
}
if (r.Weight() == nil && other.Weight() != nil) || (r.Weight() != nil && other.Weight() == nil) {
return false
}
if r.Weight() != nil && other.Weight() != nil && *r.Weight() != *other.Weight() {
return false
}
if !reflect.DeepEqual(r.Group(), other.Group()) ||
!reflect.DeepEqual(r.Kind(), other.Kind()) ||
!reflect.DeepEqual(r.Name(), other.Name()) ||
!reflect.DeepEqual(r.Namespace(), other.Namespace()) ||
!reflect.DeepEqual(r.Port(), other.Port()) {
return false
}
return true
}
type HTTPRouteMatch struct {
m gwv1.HTTPRouteMatch
}
func (m *HTTPRouteMatch) Headers() []HeaderMatch {
var headerMatches []HeaderMatch
for _, headerMatch := range m.m.Headers {
headerMatches = append(headerMatches, &HTTPHeaderMatch{headerMatch})
}
return headerMatches
}
func (m *HTTPRouteMatch) Path() *gwv1.HTTPPathMatch {
return m.m.Path
}
func (m *HTTPRouteMatch) QueryParams() []gwv1.HTTPQueryParamMatch {
return m.m.QueryParams
}
func (m *HTTPRouteMatch) Method() *gwv1.HTTPMethod {
return m.m.Method
}
func (m *HTTPRouteMatch) Equals(routeMatch RouteMatch) bool {
other, ok := routeMatch.(*HTTPRouteMatch)
if !ok {
return false
}
if len(m.Headers()) != len(other.Headers()) {
return false
}
for i, header := range m.Headers() {
if !header.Equals(other.Headers()[i]) {
return false
}
}
if !reflect.DeepEqual(m.Path(), other.Path()) {
return false
}
if !reflect.DeepEqual(m.QueryParams(), other.QueryParams()) {
return false
}
if !reflect.DeepEqual(m.Method(), other.Method()) {
return false
}
return true
}
type HTTPHeaderMatch struct {
m gwv1.HTTPHeaderMatch
}
func (m *HTTPHeaderMatch) Type() *gwv1.HeaderMatchType {
return m.m.Type
}
func (m *HTTPHeaderMatch) Name() string {
return string(m.m.Name)
}
func (m *HTTPHeaderMatch) Value() string {
return m.m.Value
}
func (m *HTTPHeaderMatch) Equals(headerMatch HeaderMatch) bool {
other, ok := headerMatch.(*HTTPHeaderMatch)
if !ok {
return false
}
return m.Type() == other.Type() &&
m.Name() == other.Name() &&
m.Value() == other.Value()
}