2626from .schemas .autoscale import SCHEMA as AUTOSCALE_SCHEMA
2727from .schemas .healthcheck import SCHEMA as HEALTHCHECK_SCHEMA
2828from .schemas .dryccfile import (SCHEMA as DRYCCFILE_SCHEMA , PROCTYPE_REGEX , CONFIGKEY_REGEX )
29+ from .schemas .gateway import PORT_SCHEMA as GATEWAY_PORT_SCHEMA
30+ from .schemas .route import PARENT_REF_SCHEMA as ROUTE_PARENT_REF_SCHEMA
2931
3032
3133User = get_user_model ()
3638GATEWAY_PROTOCOL_MATCH = re .compile (r'^(HTTP|HTTPS|TCP|TLS|UDP)$' )
3739GATEWAY_PROTOCOL_MISMATCH_MSG = (
3840 "the gateway protocol only supports: %s" % GATEWAY_PROTOCOL_MATCH .pattern )
39- ROUTE_PROTOCOL_MATCH = re .compile (r'^(HTTPRoute|TCPRoute|UDPRoute|TLSRoute)$' )
41+ ROUTE_PROTOCOL_MATCH = re .compile (r'^(HTTPRoute|TCPRoute|UDPRoute|GRPCRoute| TLSRoute)$' )
4042ROUTE_PROTOCOL_MISMATCH_MSG = (
4143 "the route kind only supports: %s" % ROUTE_PROTOCOL_MATCH .pattern )
4244PROCTYPE_MATCH = re .compile (PROCTYPE_REGEX )
@@ -735,16 +737,15 @@ def validate(self, attrs):
735737 return attrs
736738
737739
738- class GatewaySerializer (serializers .Serializer ):
740+ class GatewaySerializer (serializers .ModelSerializer ):
739741 app = serializers .SlugRelatedField (slug_field = 'id' , queryset = models .app .App .objects .all ())
740742 name = serializers .CharField (max_length = 63 , required = True )
741- listeners = serializers .JSONField (required = False )
743+ ports = serializers .JSONField (required = True )
742744 addresses = serializers .JSONField (read_only = True )
743745
744- def to_representation (self , instance ):
745- representation = super ().to_representation (instance )
746- representation ['addresses' ] = instance .addresses
747- return representation
746+ class Meta :
747+ model = models .gateway .Gateway
748+ fields = '__all__'
748749
749750 validate_name = staticmethod (validate_name )
750751
@@ -757,13 +758,35 @@ def validate_protocol(value):
757758 validate_port = staticmethod (validate_port )
758759 validate_ptype = staticmethod (validate_ptype )
759760
761+ @staticmethod
762+ def validate_ports (value ):
763+ if not isinstance (value , list ):
764+ raise serializers .ValidationError ("ports must be a list" )
765+ for item in value :
766+ validate_json (item , GATEWAY_PORT_SCHEMA , serializers .ValidationError )
767+ return value
768+
769+ def validate (self , attrs ):
770+ attrs = super ().validate (attrs )
771+ gateway = self .instance or models .gateway .Gateway (** attrs )
772+ new_ports = []
773+ for item in attrs .get ("ports" , gateway .ports ):
774+ port , protocol = item ["port" ], item ["protocol" ]
775+ gateway .ports = new_ports
776+ if not gateway ._check_port (port , protocol ):
777+ raise serializers .ValidationError ({"detail" : "port is occupied" })
778+ new_ports .append ({"port" : port , "protocol" : protocol })
779+ attrs ["ports" ] = new_ports
780+ return attrs
781+
760782
761783class RouteSerializer (serializers .ModelSerializer ):
762784 app = serializers .SlugRelatedField (slug_field = 'id' , queryset = models .app .App .objects .all ())
763785 kind = serializers .CharField (max_length = 15 , required = True )
764786 name = serializers .CharField (max_length = 63 , required = True )
765- rules = serializers .JSONField (required = False )
766- parent_refs = serializers .JSONField (required = False )
787+ rules = serializers .JSONField (required = True )
788+ routable = serializers .BooleanField (read_only = True )
789+ parent_refs = serializers .JSONField (required = True )
767790
768791 class Meta :
769792 """Metadata options for a :class:`RouteSerializer`."""
@@ -778,14 +801,35 @@ def validate_kind(value):
778801 raise serializers .ValidationError (ROUTE_PROTOCOL_MISMATCH_MSG )
779802 return value
780803
781- def validate_rules (self , value ):
782- kind = getattr (self , "initial_data" , {}).get ("kind" , None )
804+ def validate_rules (self , value , kind = None ):
805+ if kind is None :
806+ kind = getattr (self , "initial_data" , {}).get ("kind" , None )
783807 if kind :
784- schema = getattr (rules , f"{ kind .replace (" Route" , "" )} _RULES_SCHEMA" , " SCHEMA" )
808+ schema = getattr (rules , f"{ kind .replace (' Route' , '' )} _RULES_SCHEMA" , rules . SCHEMA )
785809 else :
786810 schema = rules .SCHEMA
787811 return validate_json (value , schema , serializers .ValidationError )
788812
813+ @staticmethod
814+ def validate_parent_refs (value ):
815+ if not isinstance (value , list ):
816+ raise serializers .ValidationError ("parent_refs must be a list" )
817+ for item in value :
818+ validate_json (item , ROUTE_PARENT_REF_SCHEMA , serializers .ValidationError )
819+ return value
820+
821+ def validate (self , attrs ):
822+ attrs = super ().validate (attrs )
823+ self .validate_rules (attrs .get ("rules" ), kind = attrs .get ("kind" ))
824+ route = self .instance or models .gateway .Route (** attrs )
825+ if self .instance and self .instance .kind != attrs .get ("kind" ):
826+ raise serializers .ValidationError ({"detail" : "route kind cannot be changed" })
827+ for parent_ref in attrs .get ("parent_refs" , route .parent_refs ):
828+ ok , msg = route ._check_parent (parent_ref ["name" ], parent_ref ["port" ])
829+ if not ok :
830+ raise serializers .ValidationError (msg )
831+ return attrs
832+
789833
790834class WorkspaceSerializer (serializers .ModelSerializer ):
791835 """Serialize Workspace model."""
0 commit comments