소스 검색

Validate the 'expose' option

Signed-off-by: Aanand Prasad <[email protected]>
Aanand Prasad 10 년 전
부모
커밋
ccf548b98c
3개의 변경된 파일44개의 추가작업 그리고 2개의 파일을 삭제
  1. 4 1
      compose/config/fields_schema.json
  2. 13 1
      compose/config/validation.py
  3. 27 0
      tests/unit/config/config_test.py

+ 4 - 1
compose/config/fields_schema.json

@@ -41,7 +41,10 @@
 
         "expose": {
           "type": "array",
-          "items": {"type": ["string", "number"]},
+          "items": {
+            "type": ["string", "number"],
+            "format": "expose"
+          },
           "uniqueItems": true
         },
 

+ 13 - 1
compose/config/validation.py

@@ -1,6 +1,7 @@
 import json
 import logging
 import os
+import re
 import sys
 
 import six
@@ -34,6 +35,7 @@ DOCKER_CONFIG_HINTS = {
 
 
 VALID_NAME_CHARS = '[a-zA-Z0-9\._\-]'
+VALID_EXPOSE_FORMAT = r'^\d+(\/[a-zA-Z]+)?$'
 
 
 @FormatChecker.cls_checks(format="ports", raises=ValidationError)
@@ -45,6 +47,16 @@ def format_ports(instance):
     return True
 
 
[email protected]_checks(format="expose", raises=ValidationError)
+def format_expose(instance):
+    if isinstance(instance, six.string_types):
+        if not re.match(VALID_EXPOSE_FORMAT, instance):
+            raise ValidationError(
+                "should be of the format 'PORT[/PROTOCOL]'")
+
+    return True
+
+
 @FormatChecker.cls_checks(format="bool-value-in-mapping")
 def format_boolean_in_environment(instance):
     """
@@ -273,7 +285,7 @@ def validate_against_fields_schema(config, filename):
     _validate_against_schema(
         config,
         "fields_schema.json",
-        format_checker=["ports", "bool-value-in-mapping"],
+        format_checker=["ports", "expose", "bool-value-in-mapping"],
         filename=filename)
 
 

+ 27 - 0
tests/unit/config/config_test.py

@@ -590,6 +590,33 @@ class PortsTest(unittest.TestCase):
         for valid_ports in self.VALID_SINGLE_PORTS + self.VALID_PORT_MAPPINGS:
             self.check_config({'ports': valid_ports})
 
+    def test_config_invalid_expose_type_validation(self):
+        for invalid_expose in self.INVALID_PORTS_TYPES:
+            with pytest.raises(ConfigurationError) as exc:
+                self.check_config({'expose': invalid_expose})
+
+            assert "contains an invalid type" in exc.value.msg
+
+    def test_config_non_unique_expose_validation(self):
+        for invalid_expose in self.NON_UNIQUE_SINGLE_PORTS:
+            with pytest.raises(ConfigurationError) as exc:
+                self.check_config({'expose': invalid_expose})
+
+            assert "non-unique" in exc.value.msg
+
+    def test_config_invalid_expose_format_validation(self):
+        # Valid port mappings ARE NOT valid 'expose' entries
+        for invalid_expose in self.INVALID_PORT_MAPPINGS + self.VALID_PORT_MAPPINGS:
+            with pytest.raises(ConfigurationError) as exc:
+                self.check_config({'expose': invalid_expose})
+
+            assert "should be of the format" in exc.value.msg
+
+    def test_config_valid_expose_format_validation(self):
+        # Valid single ports ARE valid 'expose' entries
+        for valid_expose in self.VALID_SINGLE_PORTS:
+            self.check_config({'expose': valid_expose})
+
     def check_config(self, cfg):
         config.load(
             build_config_details(