Pārlūkot izejas kodu

- New "environment" config file option allows you to add environment
variable values to supervisord environment from config file.

Chris McDonough 19 gadi atpakaļ
vecāks
revīzija
b01dea01a3

+ 3 - 0
CHANGES.txt

@@ -10,6 +10,9 @@ Next
   - supervisorctl "tail -f" didn't work with supervisorctl sections
     configured with an absolute unix:// URL
 
+  - New "environment" config file option allows you to add environment
+    variable values to supervisord environment from config file.
+
 2.0b1
 
   - fundamental rewrite based on 1.0.6, use distutils (only) for

+ 1 - 0
sample.conf

@@ -20,6 +20,7 @@ minprocs=200                ; (min. avail process descriptors;default 200)
 ;childlogdir=/tmp            ; ('AUTO' child log dir, default $TEMP)
 ;user=chrism                 ; (default is current user, required if root)
 ;directory=/tmp              ; (default is not to cd during start)
+;environment=KEY=value       ; (key value pairs to add to environment)
 
 [supervisorctl]
 serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket

+ 13 - 0
src/supervisor/datatypes.py

@@ -31,6 +31,19 @@ def list_of_ints(arg):
     else:
         return map(int, arg.split(","))
 
+def dict_of_key_value_pairs(arg):
+    """ parse KEY=val,KEY2=val2 into {'KEY':'val', 'KEY2':'val2'} """
+    D = {}
+    pairs = [ x.strip() for x in arg.split(',') ]
+    pairs = filter(None, pairs)
+    for pair in pairs:
+        try:
+            k, v = pair.split('=', 1)
+        except ValueError:
+            raise ValueError('Unknown key/value pair %s' % pair)
+        D[k] = v
+    return D
+
 class RangeCheckedConversion:
     """Conversion helper that range checks another conversion."""
 

+ 10 - 0
src/supervisor/options.py

@@ -435,6 +435,7 @@ class ServerOptions(Options):
     passwdfile = None
     nodaemon = None
     signal = None
+    environment = None
     AUTOMATIC = []
     TRACE = 5
 
@@ -482,6 +483,8 @@ class ServerOptions(Options):
 		 datatypes.octal_type, default=0700)
 	self.add("sockchown", "supervisord.sockchown", "o:", "socket-owner=",
 		 datatypes.dot_separated_user_group)
+	self.add("environment", "supervisord.environment", "b:", "environment=",
+		 datatypes.dict_of_key_value_pairs)
         self.pidhistory = {}
 
     def getLogger(self, filename, level, fmt, rotating=False,
@@ -656,6 +659,9 @@ class ServerOptions(Options):
             except (TypeError, ValueError):
                 raise ValueError('Invalid sockchmod value %s' % sockchmod)
 
+        environment = config.getdefault('environment', '')
+        section.environment = datatypes.dict_of_key_value_pairs(environment)
+
         section.programs = self.programs_from_config(config)
         return section
 
@@ -1119,6 +1125,10 @@ class ServerOptions(Options):
             data = ''
         return data
 
+    def process_environment(self):
+        os.environ.update(self.environment or {})
+        
+
 class ClientOptions(Options):
     positional_args_allowed = 1
 

+ 1 - 0
src/supervisor/supervisord.py

@@ -457,6 +457,7 @@ class Supervisor:
             name = program.name
             self.processes[name] = self.options.make_process(program)
         try:
+            self.options.process_environment()
             self.options.openhttpserver(self)
             self.options.setsignals()
             if not self.options.nodaemon:

+ 5 - 1
src/supervisor/tests.py

@@ -1538,6 +1538,7 @@ class SupervisordTests(unittest.TestCase):
         options.programs = [pconfig]
         supervisord.main(args='abc', test=True, first=True)
         self.assertEqual(options.realizeargs, 'abc')
+        self.assertEqual(options.environment_processed, True)
         self.assertEqual(options.fds_cleaned_up, True)
         self.assertEqual(options.rlimits_set, True)
         self.assertEqual(options.make_logger_messages,
@@ -2331,6 +2332,7 @@ class DummyOptions:
         self.setuid_msg = None
         self.privsdropped = None
         self.logs_reopened = False
+        self.environment_processed = False
 
     def getLogger(self, *args, **kw):
         logger = DummyLogger()
@@ -2452,7 +2454,9 @@ class DummyOptions:
 
     def reopenlogs(self):
         self.logs_reopened = True
-        
+
+    def process_environment(self):
+        self.environment_processed = True
 
 class DummyClientOptions:
     def __init__(self):