pkg/model/core/grpcroute.go (281 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 (
GrpcRouteType RouteType = "grpc"
)
type GRPCRoute struct {
r gwv1.GRPCRoute
}
func NewGRPCRoute(route gwv1.GRPCRoute) *GRPCRoute {
return &GRPCRoute{r: route}
}
func GetGRPCRoute(ctx context.Context, client client.Client, routeNamespacedName types.NamespacedName) (Route, error) {
grpcRoute := &gwv1.GRPCRoute{}
err := client.Get(ctx, routeNamespacedName, grpcRoute)
if err != nil {
return nil, err
}
return NewGRPCRoute(*grpcRoute), nil
}
func ListGRPCRoutes(context context.Context, client client.Client) ([]Route, error) {
routeList := &gwv1.GRPCRouteList{}
if err := client.List(context, routeList); err != nil {
return nil, err
}
var routes []Route
for _, route := range routeList.Items {
routes = append(routes, NewGRPCRoute(route))
}
return routes, nil
}
func (r *GRPCRoute) Spec() RouteSpec {
return &GRPCRouteSpec{r.r.Spec}
}
func (r *GRPCRoute) Status() RouteStatus {
return &GRPCRouteStatus{&r.r.Status}
}
func (r *GRPCRoute) Name() string {
return r.r.Name
}
func (r *GRPCRoute) Namespace() string {
return r.r.Namespace
}
func (r *GRPCRoute) DeletionTimestamp() *metav1.Time {
return r.r.DeletionTimestamp
}
func (r *GRPCRoute) DeepCopy() Route {
return &GRPCRoute{r: *r.r.DeepCopy()}
}
func (r *GRPCRoute) K8sObject() client.Object {
return &r.r
}
func (r *GRPCRoute) Inner() *gwv1.GRPCRoute {
return &r.r
}
func (r *GRPCRoute) GroupKind() metav1.GroupKind {
return metav1.GroupKind{
Group: gwv1.GroupName,
Kind: "GRPCRoute",
}
}
type GRPCRouteSpec struct {
s gwv1.GRPCRouteSpec
}
func (s *GRPCRouteSpec) ParentRefs() []gwv1.ParentReference {
return s.s.ParentRefs
}
func (s *GRPCRouteSpec) Hostnames() []gwv1.Hostname {
return s.s.Hostnames
}
func (s *GRPCRouteSpec) Rules() []RouteRule {
var rules []RouteRule
for _, rule := range s.s.Rules {
rules = append(rules, &GRPCRouteRule{rule})
}
return rules
}
func (s *GRPCRouteSpec) Equals(routeSpec RouteSpec) bool {
_, ok := routeSpec.(*GRPCRouteSpec)
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 GRPCRouteStatus struct {
s *gwv1.GRPCRouteStatus
}
func (s *GRPCRouteStatus) Parents() []gwv1.RouteParentStatus {
return s.s.Parents
}
func (s *GRPCRouteStatus) SetParents(parents []gwv1.RouteParentStatus) {
s.s.Parents = parents
}
func (s *GRPCRouteStatus) 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 *GRPCRouteStatus) 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 GRPCRouteRule struct {
r gwv1.GRPCRouteRule
}
func (r *GRPCRouteRule) BackendRefs() []BackendRef {
var backendRefs []BackendRef
for _, backendRef := range r.r.BackendRefs {
backendRefs = append(backendRefs, &GRPCBackendRef{backendRef})
}
return backendRefs
}
func (r *GRPCRouteRule) Matches() []RouteMatch {
var routeMatches []RouteMatch
for _, routeMatch := range r.r.Matches {
routeMatches = append(routeMatches, &GRPCRouteMatch{routeMatch})
}
return routeMatches
}
func (r *GRPCRouteRule) Equals(routeRule RouteRule) bool {
other, ok := routeRule.(*GRPCRouteRule)
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 GRPCBackendRef struct {
r gwv1.GRPCBackendRef
}
func (r *GRPCBackendRef) Weight() *int32 {
return r.r.Weight
}
func (r *GRPCBackendRef) Group() *gwv1.Group {
return r.r.Group
}
func (r *GRPCBackendRef) Kind() *gwv1.Kind {
return r.r.Kind
}
func (r *GRPCBackendRef) Name() gwv1.ObjectName {
return r.r.Name
}
func (r *GRPCBackendRef) Namespace() *gwv1.Namespace {
return r.r.Namespace
}
func (r *GRPCBackendRef) Port() *gwv1.PortNumber {
return r.r.Port
}
func (r *GRPCBackendRef) Equals(backendRef BackendRef) bool {
other, ok := backendRef.(*GRPCBackendRef)
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 GRPCRouteMatch struct {
m gwv1.GRPCRouteMatch
}
func (m *GRPCRouteMatch) Headers() []HeaderMatch {
var headerMatches []HeaderMatch
for _, headerMatch := range m.m.Headers {
headerMatches = append(headerMatches, &GRPCHeaderMatch{headerMatch})
}
return headerMatches
}
func (m *GRPCRouteMatch) Method() *gwv1.GRPCMethodMatch {
return m.m.Method
}
func (m *GRPCRouteMatch) Equals(routeMatch RouteMatch) bool {
other, ok := routeMatch.(*GRPCRouteMatch)
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
}
}
return reflect.DeepEqual(m.Method(), other.Method())
}
type GRPCHeaderMatch struct {
m gwv1.GRPCHeaderMatch
}
func (m *GRPCHeaderMatch) Type() *gwv1.HeaderMatchType {
if m.m.Type == nil {
return nil
}
// at some point, these may not match up. For now, Exact and RegularExpression are shared values
hmt := gwv1.HeaderMatchType(*m.m.Type)
return &hmt
}
func (m *GRPCHeaderMatch) Name() string {
return string(m.m.Name)
}
func (m *GRPCHeaderMatch) Value() string {
return m.m.Value
}
func (m *GRPCHeaderMatch) Equals(headerMatch HeaderMatch) bool {
other, ok := headerMatch.(*GRPCHeaderMatch)
if !ok {
return false
}
if m.Name() != other.Name() ||
m.Value() != other.Value() {
return false
}
mType := m.Type()
otherType := other.Type()
if (mType == nil && otherType != nil) ||
(mType != nil && otherType == nil) {
return false
}
return (mType == nil && otherType == nil) ||
*mType == *otherType
}