Repository: benoitc/gunicorn

Issue:
--config doesn't work in GUNICORN_CMD_ARGS
Specifying `--config` in the `GUNICORN_CMD_ARGS` environment variable quietly fails as config file loading only happens when it is passed as an argument:
https://github.com/benoitc/gunicorn/blob/328e509260ae70de6c04c5ba885ee17960b3ced5/gunicorn/app/base.py#L137-L175


Discussion:
It looks like we parse the command options from the environment only after loading from a config file. We would have to parse these first, to get the config file option.

Good find.
yeah the env should probably checked first and then the rest. At least it's seems to be the common pattern. Would you mind to provide a PR for it?


Resolving patch:
diff --git a/gunicorn/app/base.py b/gunicorn/app/base.py
--- a/gunicorn/app/base.py
+++ b/gunicorn/app/base.py
@@ -147,26 +147,26 @@ def load_config(self):
             for k, v in cfg.items():
                 self.cfg.set(k.lower(), v)
 
+        env_args = parser.parse_args(self.cfg.get_cmd_args_from_env())
+
         if args.config:
             self.load_config_from_file(args.config)
+        elif env_args.config:
+            self.load_config_from_file(env_args.config)
         else:
             default_config = get_default_config_file()
             if default_config is not None:
                 self.load_config_from_file(default_config)
 
         # Load up environment configuration
-        env_vars = self.cfg.get_cmd_args_from_env()
-        if env_vars:
-            env_args = parser.parse_args(env_vars)
-            for k, v in vars(env_args).items():
-                if v is None:
-                    continue
-                if k == "args":
-                    continue
-                self.cfg.set(k.lower(), v)
+        for k, v in vars(env_args).items():
+            if v is None:
+                continue
+            if k == "args":
+                continue
+            self.cfg.set(k.lower(), v)
 
-        # Lastly, update the configuration with any command line
-        # settings.
+        # Lastly, update the configuration with any command line settings.
         for k, v in vars(args).items():
             if v is None:
                 continue


Test patch:
diff --git a/tests/config/test_cfg_alt.py b/tests/config/test_cfg_alt.py
new file mode 100644
--- /dev/null
+++ b/tests/config/test_cfg_alt.py
@@ -0,0 +1 @@
+proc_name = "not-fooey"
diff --git a/tests/test_config.py b/tests/test_config.py
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -18,8 +18,12 @@
 dirname = os.path.dirname(__file__)
 def cfg_module():
     return 'config.test_cfg'
+def alt_cfg_module():
+    return 'config.test_cfg_alt'
 def cfg_file():
     return os.path.join(dirname, "config", "test_cfg.py")
+def alt_cfg_file():
+    return os.path.join(dirname, "config", "test_cfg_alt.py")
 def paster_ini():
     return os.path.join(dirname, "..", "examples", "frameworks", "pylonstest", "nose.ini")
 
@@ -329,6 +333,16 @@ def test_load_enviroment_variables_config(monkeypatch):
         app = NoConfigApp()
     assert app.cfg.workers == 4
 
+def test_config_file_environment_variable(monkeypatch):
+    monkeypatch.setenv("GUNICORN_CMD_ARGS", "--config=" + alt_cfg_file())
+    with AltArgs():
+        app = NoConfigApp()
+    assert app.cfg.proc_name == "not-fooey"
+    assert app.cfg.config == alt_cfg_file()
+    with AltArgs(["prog_name", "--config", cfg_file()]):
+        app = NoConfigApp()
+    assert app.cfg.proc_name == "fooey"
+    assert app.cfg.config == cfg_file()
 
 def test_invalid_enviroment_variables_config(monkeypatch, capsys):
     monkeypatch.setenv("GUNICORN_CMD_ARGS", "--foo=bar")