Skip to content

Commit 0343763

Browse files
authored
Exclude check for global in configuration.py (#59819)
1 parent f6a85c6 commit 0343763

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

airflow-core/src/airflow/configuration.py

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from collections.abc import Callable
3232
from configparser import ConfigParser
3333
from copy import deepcopy
34+
from inspect import ismodule
3435
from io import StringIO
3536
from re import Pattern
3637
from typing import IO, TYPE_CHECKING, Any
@@ -44,7 +45,7 @@
4445
ValueNotFound,
4546
)
4647
from airflow._shared.module_loading import import_string
47-
from airflow.exceptions import AirflowConfigException
48+
from airflow.exceptions import AirflowConfigException, RemovedInAirflow4Warning
4849
from airflow.secrets import DEFAULT_SECRETS_SEARCH_PATH
4950
from airflow.task.weight_rule import WeightRule
5051
from airflow.utils import yaml
@@ -70,6 +71,13 @@
7071
ENV_VAR_PREFIX = "AIRFLOW__"
7172

7273

74+
class _SecretKeys:
75+
"""Holds the secret keys used in Airflow during runtime."""
76+
77+
fernet_key: str | None = None
78+
jwt_secret_key: str | None = None
79+
80+
7381
class ConfigModifications:
7482
"""
7583
Holds modifications to be applied when writing out the config.
@@ -507,19 +515,18 @@ def load_test_config(self):
507515
the "unit_tests.cfg" configuration file in the ``airflow/config_templates`` folder
508516
and you need to change values there if you want to make some specific configuration to be used
509517
"""
510-
# We need those globals before we run "get_all_expansion_variables" because this is where
511-
# the variables are expanded from in the configuration
512-
global FERNET_KEY, JWT_SECRET_KEY
513518
from cryptography.fernet import Fernet
514519

515520
unit_test_config_file = pathlib.Path(__file__).parent / "config_templates" / "unit_tests.cfg"
516521
unit_test_config = unit_test_config_file.read_text()
517522
self.remove_all_read_configurations()
518523
with StringIO(unit_test_config) as test_config_file:
519524
self.read_file(test_config_file)
520-
# set fernet key to a random value
521-
FERNET_KEY = Fernet.generate_key().decode()
522-
JWT_SECRET_KEY = b64encode(os.urandom(16)).decode("utf-8")
525+
526+
# We need those globals before we run "get_all_expansion_variables" because this is where
527+
# the variables are expanded from in the configuration - set to random values for tests
528+
_SecretKeys.fernet_key = Fernet.generate_key().decode()
529+
_SecretKeys.jwt_secret_key = b64encode(os.urandom(16)).decode("utf-8")
523530
self.expand_all_configuration_values()
524531
log.info("Unit test configuration loaded from 'config_unit_tests.cfg'")
525532

@@ -647,7 +654,15 @@ def get_airflow_config(airflow_home: str) -> str:
647654

648655

649656
def get_all_expansion_variables() -> dict[str, Any]:
650-
return {k: v for d in [globals(), locals()] for k, v in d.items() if not k.startswith("_")}
657+
return {
658+
"FERNET_KEY": _SecretKeys.fernet_key,
659+
"JWT_SECRET_KEY": _SecretKeys.jwt_secret_key,
660+
**{
661+
k: v
662+
for k, v in globals().items()
663+
if not k.startswith("_") and not callable(v) and not ismodule(v)
664+
},
665+
}
651666

652667

653668
def _generate_fernet_key() -> str:
@@ -708,7 +723,6 @@ def create_provider_config_fallback_defaults() -> ConfigParser:
708723

709724

710725
def write_default_airflow_configuration_if_needed() -> AirflowConfigParser:
711-
global FERNET_KEY, JWT_SECRET_KEY
712726
airflow_config = pathlib.Path(AIRFLOW_CONFIG)
713727
if airflow_config.is_dir():
714728
msg = (
@@ -730,13 +744,17 @@ def write_default_airflow_configuration_if_needed() -> AirflowConfigParser:
730744
log.debug("Create directory %r for Airflow config", config_directory.__fspath__())
731745
config_directory.mkdir(parents=True, exist_ok=True)
732746
if conf.get("core", "fernet_key", fallback=None) in (None, ""):
733-
# We know that FERNET_KEY is not set, so we can generate it, set as global key
747+
# We know that fernet_key is not set, so we can generate it, set as global key
734748
# and also write it to the config file so that same key will be used next time
735-
FERNET_KEY = _generate_fernet_key()
736-
conf.configuration_description["core"]["options"]["fernet_key"]["default"] = FERNET_KEY
749+
_SecretKeys.fernet_key = _generate_fernet_key()
750+
conf.configuration_description["core"]["options"]["fernet_key"]["default"] = (
751+
_SecretKeys.fernet_key
752+
)
737753

738-
JWT_SECRET_KEY = b64encode(os.urandom(16)).decode("utf-8")
739-
conf.configuration_description["api_auth"]["options"]["jwt_secret"]["default"] = JWT_SECRET_KEY
754+
_SecretKeys.jwt_secret_key = b64encode(os.urandom(16)).decode("utf-8")
755+
conf.configuration_description["api_auth"]["options"]["jwt_secret"]["default"] = (
756+
_SecretKeys.jwt_secret_key
757+
)
740758
pathlib.Path(airflow_config.__fspath__()).touch()
741759
make_group_other_inaccessible(airflow_config.__fspath__())
742760
with open(airflow_config, "w") as file:
@@ -762,7 +780,7 @@ def load_standard_airflow_configuration(airflow_config_parser: AirflowConfigPars
762780
:param airflow_config_parser: parser to which the configuration will be loaded
763781
764782
"""
765-
global AIRFLOW_HOME
783+
global AIRFLOW_HOME # to be cleaned in Airflow 4.0
766784
log.info("Reading the config from %s", AIRFLOW_CONFIG)
767785
airflow_config_parser.read(AIRFLOW_CONFIG)
768786
if airflow_config_parser.has_option("core", "AIRFLOW_HOME"):
@@ -772,18 +790,18 @@ def load_standard_airflow_configuration(airflow_config_parser: AirflowConfigPars
772790
"environment variable and remove the config file entry."
773791
)
774792
if "AIRFLOW_HOME" in os.environ:
775-
warnings.warn(msg, category=DeprecationWarning, stacklevel=1)
793+
warnings.warn(msg, category=RemovedInAirflow4Warning, stacklevel=1)
776794
elif airflow_config_parser.get("core", "airflow_home") == AIRFLOW_HOME:
777795
warnings.warn(
778796
"Specifying airflow_home in the config file is deprecated. As you "
779797
"have left it at the default value you should remove the setting "
780798
"from your airflow.cfg and suffer no change in behaviour.",
781-
category=DeprecationWarning,
799+
category=RemovedInAirflow4Warning,
782800
stacklevel=1,
783801
)
784802
else:
785803
AIRFLOW_HOME = airflow_config_parser.get("core", "airflow_home")
786-
warnings.warn(msg, category=DeprecationWarning, stacklevel=1)
804+
warnings.warn(msg, category=RemovedInAirflow4Warning, stacklevel=1)
787805

788806

789807
def initialize_config() -> AirflowConfigParser:
@@ -913,8 +931,6 @@ def initialize_auth_manager() -> BaseAuthManager:
913931
TEST_PLUGINS_FOLDER = os.path.join(AIRFLOW_HOME, "plugins")
914932

915933
SECRET_KEY = b64encode(os.urandom(16)).decode("utf-8")
916-
FERNET_KEY = "" # Set only if needed when generating a new file
917-
JWT_SECRET_KEY = ""
918934

919935
conf: AirflowConfigParser = initialize_config()
920936
secrets_backend_list = initialize_secrets_backends()

airflow-core/tests/unit/core/test_configuration.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,8 +1952,8 @@ def test_write_default_config_contains_generated_secrets(tmp_path, monkeypatch):
19521952

19531953
cfgpath = tmp_path / "airflow-gneerated.cfg"
19541954
# Patch these globals so it gets reverted by monkeypath after this test is over.
1955-
monkeypatch.setattr(airflow.configuration, "FERNET_KEY", "")
1956-
monkeypatch.setattr(airflow.configuration, "JWT_SECRET_KEY", "")
1955+
monkeypatch.setattr(airflow.configuration._SecretKeys, "fernet_key", "")
1956+
monkeypatch.setattr(airflow.configuration._SecretKeys, "jwt_secret_key", "")
19571957
monkeypatch.setattr(airflow.configuration, "AIRFLOW_CONFIG", str(cfgpath))
19581958

19591959
# Create a new global conf object so our changes don't persist
@@ -1966,11 +1966,11 @@ def test_write_default_config_contains_generated_secrets(tmp_path, monkeypatch):
19661966

19671967
lines = cfgpath.read_text().splitlines()
19681968

1969-
assert airflow.configuration.FERNET_KEY
1970-
assert airflow.configuration.JWT_SECRET_KEY
1969+
assert airflow.configuration._SecretKeys.fernet_key
1970+
assert airflow.configuration._SecretKeys.jwt_secret_key
19711971

19721972
fernet_line = next(line for line in lines if line.startswith("fernet_key = "))
19731973
jwt_secret_line = next(line for line in lines if line.startswith("jwt_secret = "))
19741974

1975-
assert fernet_line == f"fernet_key = {airflow.configuration.FERNET_KEY}"
1976-
assert jwt_secret_line == f"jwt_secret = {airflow.configuration.JWT_SECRET_KEY}"
1975+
assert fernet_line == f"fernet_key = {airflow.configuration._SecretKeys.fernet_key}"
1976+
assert jwt_secret_line == f"jwt_secret = {airflow.configuration._SecretKeys.jwt_secret_key}"

0 commit comments

Comments
 (0)