diff --git a/foundationdb/assets/configuration/spec.yaml b/foundationdb/assets/configuration/spec.yaml index 45195eddfe6c1..9ee6e7184b0f6 100644 --- a/foundationdb/assets/configuration/spec.yaml +++ b/foundationdb/assets/configuration/spec.yaml @@ -16,6 +16,18 @@ files: value: example: /var/lib/foundationdb/fdb.cluster type: string + - name: copy_cluster_file + description: | + Whether to make a writable copy of the given `cluster_file` before + passing it to the FoundationDB client. FoundationDB clients generally + need to be able to write to cluster files in the event of cluster + topology changes. This option can be useful in environments where + making a writable file available to the FoundationDB integration is + difficult (i.e. mounting a `ConfigMap` in a Kubernetes deployment). + This option has no effect if `cluster_file` is not specified. + value: + example: false + type: boolean - name: tls_certificate_file description: Path to the file from which the local certificates can be loaded value: diff --git a/foundationdb/changelog.d/19684.added b/foundationdb/changelog.d/19684.added new file mode 100644 index 0000000000000..0d2e1ee0d6bdd --- /dev/null +++ b/foundationdb/changelog.d/19684.added @@ -0,0 +1 @@ +Add an option to copy FoundationDB cluster files to a writable temporary file diff --git a/foundationdb/datadog_checks/foundationdb/check.py b/foundationdb/datadog_checks/foundationdb/check.py index cf8c01a68787e..55c91be497bb8 100644 --- a/foundationdb/datadog_checks/foundationdb/check.py +++ b/foundationdb/datadog_checks/foundationdb/check.py @@ -3,6 +3,8 @@ # Licensed under a 3-clause BSD style license (see LICENSE) import json +import shutil +import tempfile import fdb @@ -31,7 +33,13 @@ def construct_database(self): fdb.options.set_tls_verify_peers(self.instance.get('tls_verify_peers').encode('latin-1')) if 'cluster_file' in self.instance: - self._db = fdb.open(cluster_file=self.instance.get('cluster_file')) + cluster_file = self.instance.get('cluster_file') + + if self.instance.get('copy_cluster_file'): + _, cluster_file = tempfile.mkstemp(suffix=".cluster") + shutil.copyfile(self.instance.get('cluster_file'), cluster_file) + + self._db = fdb.open(cluster_file=cluster_file) else: self._db = fdb.open() diff --git a/foundationdb/datadog_checks/foundationdb/config_models/defaults.py b/foundationdb/datadog_checks/foundationdb/config_models/defaults.py index ccf94d4e25a15..b5b9ff6313a1c 100644 --- a/foundationdb/datadog_checks/foundationdb/config_models/defaults.py +++ b/foundationdb/datadog_checks/foundationdb/config_models/defaults.py @@ -12,6 +12,10 @@ def instance_cluster_file(): return '/var/lib/foundationdb/fdb.cluster' +def instance_copy_cluster_file(): + return False + + def instance_disable_generic_tags(): return False diff --git a/foundationdb/datadog_checks/foundationdb/config_models/instance.py b/foundationdb/datadog_checks/foundationdb/config_models/instance.py index a24e8ba7fde80..33458ecc8e482 100644 --- a/foundationdb/datadog_checks/foundationdb/config_models/instance.py +++ b/foundationdb/datadog_checks/foundationdb/config_models/instance.py @@ -36,6 +36,7 @@ class InstanceConfig(BaseModel): frozen=True, ) cluster_file: Optional[str] = None + copy_cluster_file: Optional[bool] = None custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None diff --git a/foundationdb/datadog_checks/foundationdb/data/conf.yaml.example b/foundationdb/datadog_checks/foundationdb/data/conf.yaml.example index 2854e210e3786..fe7eb18e7a17f 100644 --- a/foundationdb/datadog_checks/foundationdb/data/conf.yaml.example +++ b/foundationdb/datadog_checks/foundationdb/data/conf.yaml.example @@ -22,6 +22,17 @@ instances: # # cluster_file: /var/lib/foundationdb/fdb.cluster + ## @param copy_cluster_file - boolean - optional - default: false + ## Whether to make a writable copy of the given `cluster_file` before + ## passing it to the FoundationDB client. FoundationDB clients generally + ## need to be able to write to cluster files in the event of cluster + ## topology changes. This option can be useful in environments where + ## making a writable file available to the FoundationDB integration is + ## difficult (i.e. mounting a `ConfigMap` in a Kubernetes deployment). + ## This option has no effect if `cluster_file` is not specified. + # + # copy_cluster_file: false + ## @param tls_certificate_file - string - optional ## Path to the file from which the local certificates can be loaded # diff --git a/foundationdb/tests/common.py b/foundationdb/tests/common.py index cc039e75e8a20..2d33c5e9523f8 100644 --- a/foundationdb/tests/common.py +++ b/foundationdb/tests/common.py @@ -22,6 +22,14 @@ 'tls_verify_peers': 'Check.Valid=0', } +COPY_CLUSTER_FILE_INSTANCE = { + 'cluster_file': CLUSTER_FILE, + 'copy_cluster_file': True, + 'tls_certificate_file': TLS_CERT_FILE, + 'tls_key_file': TLS_KEY_FILE, + 'tls_verify_peers': 'Check.Valid=0', +} + TLS_INSTANCE = { 'cluster_file': TLS_CLUSTER_FILE, 'tls_certificate_file': TLS_CERT_FILE, diff --git a/foundationdb/tests/conftest.py b/foundationdb/tests/conftest.py index 1736cb5d534d2..6f2a0c3941716 100644 --- a/foundationdb/tests/conftest.py +++ b/foundationdb/tests/conftest.py @@ -9,7 +9,16 @@ from datadog_checks.dev import WaitFor, docker_run, run_command -from .common import E2E_CONFIG, E2E_METADATA, E2E_TLS_CONFIG, HERE, INSTANCE, PROTOCOL, TLS_INSTANCE +from .common import ( + COPY_CLUSTER_FILE_INSTANCE, + E2E_CONFIG, + E2E_METADATA, + E2E_TLS_CONFIG, + HERE, + INSTANCE, + PROTOCOL, + TLS_INSTANCE, +) @pytest.fixture(scope='session') @@ -29,6 +38,11 @@ def instance(): return INSTANCE +@pytest.fixture +def copy_cluster_file_instance(): + return COPY_CLUSTER_FILE_INSTANCE + + @pytest.fixture def tls_instance(): return TLS_INSTANCE