Browse Source

Merge pull request #2658 from dnephin/warn_on_caps

Error when the project name is invalid for the default image name
Aanand Prasad 10 years ago
parent
commit
493df49d55
2 changed files with 29 additions and 10 deletions
  1. 22 10
      compose/config/config.py
  2. 7 0
      tests/unit/config/config_test.py

+ 22 - 10
compose/config/config.py

@@ -6,6 +6,7 @@ import functools
 import logging
 import operator
 import os
+import string
 import sys
 from collections import namedtuple
 
@@ -312,15 +313,11 @@ def load_services(working_dir, filename, service_configs, version):
         resolver = ServiceExtendsResolver(service_config, version)
         service_dict = process_service(resolver.run())
 
-        # TODO: move to validate_service()
-        validate_against_service_schema(service_dict, service_config.name, version)
-        validate_paths(service_dict)
-
+        validate_service(service_dict, service_config.name, version)
         service_dict = finalize_service(
             service_config._replace(config=service_dict),
             service_names,
             version)
-        service_dict['name'] = service_config.name
         return service_dict
 
     def build_services(service_config):
@@ -494,7 +491,21 @@ def validate_ulimits(ulimit_config):
                     "than 'hard' value".format(ulimit_config))
 
 
-# TODO: rename to normalize_service
+def validate_service(service_dict, service_name, version):
+    validate_against_service_schema(service_dict, service_name, version)
+    validate_paths(service_dict)
+
+    if 'ulimits' in service_dict:
+        validate_ulimits(service_dict['ulimits'])
+
+    if not service_dict.get('image') and has_uppercase(service_name):
+        raise ConfigurationError(
+            "Service '{name}' contains uppercase characters which are not valid "
+            "as part of an image name. Either use a lowercase service name or "
+            "use the `image` field to set a custom name for the service image."
+            .format(name=service_name))
+
+
 def process_service(service_config):
     working_dir = service_config.working_dir
     service_dict = dict(service_config.config)
@@ -525,10 +536,6 @@ def process_service(service_config):
         if field in service_dict:
             service_dict[field] = to_list(service_dict[field])
 
-    # TODO: move to a validate_service()
-    if 'ulimits' in service_dict:
-        validate_ulimits(service_dict['ulimits'])
-
     return service_dict
 
 
@@ -554,6 +561,7 @@ def finalize_service(service_config, service_names, version):
 
     normalize_build(service_dict, service_config.working_dir)
 
+    service_dict['name'] = service_config.name
     return normalize_v1_service_format(service_dict)
 
 
@@ -861,6 +869,10 @@ def to_list(value):
         return value
 
 
+def has_uppercase(name):
+    return any(char in string.ascii_uppercase for char in name)
+
+
 def load_yaml(filename):
     try:
         with open(filename, 'r') as fh:

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

@@ -544,6 +544,13 @@ class ConfigTest(unittest.TestCase):
                 )
             )
 
+    def test_load_errors_on_uppercase_with_no_image(self):
+        with pytest.raises(ConfigurationError) as exc:
+            config.load(build_config_details({
+                'Foo': {'build': '.'},
+            }, 'tests/fixtures/build-ctx'))
+            assert "Service 'Foo' contains uppercase characters" in exc.exconly()
+
     def test_invalid_config_build_and_image_specified(self):
         expected_error_msg = "Service 'foo' has both an image and build path specified."
         with self.assertRaisesRegexp(ConfigurationError, expected_error_msg):