Skip to content

Commit 9cc6dea

Browse files
committed
chore(controller): add route rules serializer
1 parent e3e342a commit 9cc6dea

2 files changed

Lines changed: 215 additions & 0 deletions

File tree

rootfs/api/serializers.py

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,3 +788,217 @@ def validate_procfile_type(value):
788788
raise serializers.ValidationError(PROCTYPE_MISMATCH_MSG)
789789

790790
return value
791+
792+
@staticmethod
793+
def validate_rules(value):
794+
http_header_filter_properties = {
795+
"set": {
796+
"type": "array",
797+
"items": {
798+
"type": "object",
799+
"properties": {
800+
"name": {"type": "string"},
801+
"value": {"type": "string"}
802+
}
803+
}
804+
},
805+
"add": {
806+
"type": "array",
807+
"items": {
808+
"type": "object",
809+
"properties": {
810+
"name": {"type": "string"},
811+
"value": {"type": "string"}
812+
}
813+
}
814+
},
815+
"remove": {"type": "array"}
816+
}
817+
filter_properties = {
818+
# Type identifies the type of filter to apply.
819+
# As with other API fields, types are classified into three conformance levels:
820+
"type": {
821+
"type": "string",
822+
"enum": ["ExtensionRef", "RequestHeaderModifier", "RequestMirror", "RequestRedirect", "ResponseHeaderModifier", "URLRewrite"], # noqa
823+
},
824+
# ExtensionRef is an optional, implementation-specific extension to the “filter” behavior. # noqa
825+
# For example, resource “myroutefilter” in group “networking.example.net”).
826+
# ExtensionRef MUST NOT be used for core and extended filters.
827+
"extensionRef": {
828+
"type": "object",
829+
"properties": {
830+
"group": {"type": "string"},
831+
"kind": {"type": "string"},
832+
"name": {"type": "string"}
833+
},
834+
"required": ["group", "kind", "name"],
835+
"additionalProperties": False
836+
},
837+
# RequestHeaderModifier defines a schema for a filter that modifies request headers.
838+
"requestHeaderModifier": {
839+
"type": "object",
840+
"properties": http_header_filter_properties,
841+
"additionalProperties": False
842+
},
843+
# ResponseHeaderModifier defines a schema for a filter that modifies response headers.
844+
"responseHeaderModifier": {
845+
"type": "object",
846+
"properties": http_header_filter_properties,
847+
"additionalProperties": False
848+
},
849+
# RequestMirror defines a schema for a filter that mirrors requests.
850+
# Requests are sent to the specified destination, but responses from that destination are ignored. # noqa
851+
"requestMirror": {
852+
"type": "object",
853+
"properties": {
854+
"backendRef": {
855+
"properties": {
856+
"group": {"type": "string"},
857+
"kind": {"type": "string"},
858+
"name": {"type": "string"},
859+
"namespace": {"type": "string"},
860+
"port": {"type": "integer"},
861+
},
862+
"required": ["name"],
863+
"additionalProperties": False
864+
},
865+
},
866+
"required": ["backendRef"],
867+
"additionalProperties": False
868+
},
869+
# RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. # noqa
870+
"requestRedirect": {
871+
"type": "object",
872+
"properties": {
873+
"scheme": {"type": "string"},
874+
"hostname": {"type": "string"},
875+
"path": {"type": "string"},
876+
"port": {"type": "integer"},
877+
"statusCode": {"type": "integer"}
878+
}
879+
},
880+
# URLRewrite defines a schema for a filter that modifies a request during forwarding
881+
"urlRewrite": {
882+
"hostname": {"type": "string"},
883+
"path": {"type": "string"},
884+
}
885+
}
886+
887+
# More info: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io%2fv1beta1.HTTPRouteRule # noqa
888+
HTTP_RULES_SCHEMA = {
889+
"$schema": "http://json-schema.org/draft-07/schema#",
890+
891+
"type": "array",
892+
"items": {
893+
"properties": {
894+
# Matches define conditions used for matching the rule against incoming HTTP requests. # noqa
895+
# Each match is independent, i.e. this rule will be matched if any one of the matches is satisfied. # noqa
896+
# More info: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteMatch # noqa
897+
"matches": {
898+
"type": "array",
899+
"items": {
900+
"properties": {
901+
# Path specifies a HTTP request path matcher.
902+
# If this field is not specified, a default prefix match on the “/” path is provided. # noqa
903+
"path": {
904+
"type": "object",
905+
"properties": {
906+
"type": {
907+
"type": "string",
908+
"enum": ["Exact", "PathPrefix", "RegularExpression"],
909+
"default": "PathPrefix"
910+
},
911+
"value": {"type": "string"}
912+
},
913+
"additionalProperties": False
914+
},
915+
# Headers specifies HTTP request header matchers. Multiple match values are ANDed together, # noqa
916+
# meaning, a request must match all the specified headers to select the route. # noqa
917+
# gateway.networking.k8s.io/v1beta1.HTTPHeaderMatch
918+
# More info: https: // gateway-api.sigs.k8s.io/references/spec /
919+
"headers": {
920+
"type": "array",
921+
"items": {
922+
"properties": {
923+
"type": {
924+
"type": "string",
925+
"enum": ["Exact", "RegularExpression"],
926+
"default": "Exact"
927+
},
928+
"name": {"type": "string"},
929+
"value": {"type": "string"}
930+
},
931+
"additionalProperties": False
932+
}
933+
},
934+
# QueryParams specifies HTTP query parameter matchers. Multiple match values are ANDed together, # noqa
935+
# meaning, a request must match all the specified query parameters to select the route. # noqa
936+
"queryParams": {
937+
"type": "array",
938+
"items": {
939+
"properties": {
940+
"type": {
941+
"type": "string",
942+
"enum": ["Exact", "RegularExpression"],
943+
"default": "Exact"
944+
},
945+
"name": {"type": "string"},
946+
"value": {"type": "string"}
947+
},
948+
"additionalProperties": False
949+
}
950+
},
951+
"method": {
952+
"type": "string",
953+
"enum": ["CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"], # noqa
954+
}
955+
},
956+
"additionalProperties": False
957+
}
958+
},
959+
# Filters define the filters that are applied to requests that match this rule.
960+
# More info: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteFilter # noqa
961+
"filters": {
962+
"type": "array",
963+
"items": {
964+
"properties": filter_properties,
965+
"additionalProperties": False
966+
},
967+
},
968+
# BackendRefs defines the backend(s) where matching requests should be sent.
969+
# More info: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPBackendRef # noqa
970+
"backendRefs": {
971+
"type": "array",
972+
"items": {
973+
"properties": {
974+
"filters": {
975+
"type": "array",
976+
"items": {
977+
"properties": filter_properties,
978+
"additionalProperties": False
979+
},
980+
},
981+
"group": {"type": "string"},
982+
"kind": {"type": "string"},
983+
"name": {"type": "string"},
984+
"namespace": {"type": "string"},
985+
"port": {"type": "integer"},
986+
"weight": {"type": "integer"}
987+
},
988+
"required": ["name"],
989+
"additionalProperties": False
990+
}
991+
}
992+
},
993+
"required": ["backendRefs"],
994+
"additionalProperties": False
995+
}
996+
}
997+
998+
try:
999+
jsonschema.validate(value, HTTP_RULES_SCHEMA)
1000+
except jsonschema.ValidationError as e:
1001+
raise serializers.ValidationError(
1002+
"could not validate {}: {}".format(value, e.message)
1003+
)
1004+
return value

rootfs/api/views.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ def set(self, request, *args, **kwargs):
898898
rules = request.data
899899
if isinstance(rules, str):
900900
rules = json.loads(rules)
901+
rules = self.get_serializer().validate_rules(rules)
901902
route.rules = rules
902903
ok, msg = route.check_rules()
903904
if not ok:

0 commit comments

Comments
 (0)