Merge remote-tracking branch 'upstream/release-v1.67'

This commit is contained in:
Tulir Asokan 2022-09-06 08:22:38 -04:00
commit ca9515d2c7
133 changed files with 3557 additions and 2185 deletions

View file

@ -20,6 +20,7 @@ import logging
import os
import re
from collections import OrderedDict
from enum import Enum, auto
from hashlib import sha256
from textwrap import dedent
from typing import (
@ -603,18 +604,44 @@ class RootConfig:
" may specify directories containing *.yaml files.",
)
generate_group = parser.add_argument_group("Config generation")
generate_group.add_argument(
"--generate-config",
action="store_true",
help="Generate a config file, then exit.",
# we nest the mutually-exclusive group inside another group so that the help
# text shows them in their own group.
generate_mode_group = parser.add_argument_group(
"Config generation mode",
)
generate_group.add_argument(
generate_mode_exclusive = generate_mode_group.add_mutually_exclusive_group()
generate_mode_exclusive.add_argument(
# hidden option to make the type and default work
"--generate-mode",
help=argparse.SUPPRESS,
type=_ConfigGenerateMode,
default=_ConfigGenerateMode.GENERATE_MISSING_AND_RUN,
)
generate_mode_exclusive.add_argument(
"--generate-config",
help="Generate a config file, then exit.",
action="store_const",
const=_ConfigGenerateMode.GENERATE_EVERYTHING_AND_EXIT,
dest="generate_mode",
)
generate_mode_exclusive.add_argument(
"--generate-missing-configs",
"--generate-keys",
action="store_true",
help="Generate any missing additional config files, then exit.",
action="store_const",
const=_ConfigGenerateMode.GENERATE_MISSING_AND_EXIT,
dest="generate_mode",
)
generate_mode_exclusive.add_argument(
"--generate-missing-and-run",
help="Generate any missing additional config files, then run. This is the "
"default behaviour.",
action="store_const",
const=_ConfigGenerateMode.GENERATE_MISSING_AND_RUN,
dest="generate_mode",
)
generate_group = parser.add_argument_group("Details for --generate-config")
generate_group.add_argument(
"-H", "--server-name", help="The server name to generate a config file for."
)
@ -670,11 +697,12 @@ class RootConfig:
config_dir_path = os.path.abspath(config_dir_path)
data_dir_path = os.getcwd()
generate_missing_configs = config_args.generate_missing_configs
obj = cls(config_files)
if config_args.generate_config:
if (
config_args.generate_mode
== _ConfigGenerateMode.GENERATE_EVERYTHING_AND_EXIT
):
if config_args.report_stats is None:
parser.error(
"Please specify either --report-stats=yes or --report-stats=no\n\n"
@ -732,11 +760,14 @@ class RootConfig:
)
% (config_path,)
)
generate_missing_configs = True
config_dict = read_config_files(config_files)
if generate_missing_configs:
obj.generate_missing_files(config_dict, config_dir_path)
obj.generate_missing_files(config_dict, config_dir_path)
if config_args.generate_mode in (
_ConfigGenerateMode.GENERATE_EVERYTHING_AND_EXIT,
_ConfigGenerateMode.GENERATE_MISSING_AND_EXIT,
):
return None
obj.parse_config_dict(
@ -965,6 +996,12 @@ def read_file(file_path: Any, config_path: Iterable[str]) -> str:
raise ConfigError("Error accessing file %r" % (file_path,), config_path) from e
class _ConfigGenerateMode(Enum):
GENERATE_MISSING_AND_RUN = auto()
GENERATE_MISSING_AND_EXIT = auto()
GENERATE_EVERYTHING_AND_EXIT = auto()
__all__ = [
"Config",
"RootConfig",

View file

@ -32,9 +32,6 @@ class ExperimentalConfig(Config):
# MSC2716 (importing historical messages)
self.msc2716_enabled: bool = experimental.get("msc2716_enabled", False)
# MSC2285 (unstable private read receipts)
self.msc2285_enabled: bool = experimental.get("msc2285_enabled", False)
# MSC3244 (room version capabilities)
self.msc3244_enabled: bool = experimental.get("msc3244_enabled", True)
@ -74,6 +71,9 @@ class ExperimentalConfig(Config):
self.msc3720_enabled: bool = experimental.get("msc3720_enabled", False)
# MSC2654: Unread counts
#
# Note that enabling this will result in an incorrect unread count for
# previously calculated push actions.
self.msc2654_enabled: bool = experimental.get("msc2654_enabled", False)
# MSC2815 (allow room moderators to view redacted event content)

View file

@ -42,6 +42,35 @@ class MetricsConfig(Config):
def read_config(self, config: JsonDict, **kwargs: Any) -> None:
self.enable_metrics = config.get("enable_metrics", False)
"""
### `enable_legacy_metrics` (experimental)
**Experimental: this option may be removed or have its behaviour
changed at any time, with no notice.**
Set to `true` to publish both legacy and non-legacy Prometheus metric names,
or to `false` to only publish non-legacy Prometheus metric names.
Defaults to `true`. Has no effect if `enable_metrics` is `false`.
Legacy metric names include:
- metrics containing colons in the name, such as `synapse_util_caches_response_cache:hits`, because colons are supposed to be reserved for user-defined recording rules;
- counters that don't end with the `_total` suffix, such as `synapse_federation_client_sent_edus`, therefore not adhering to the OpenMetrics standard.
These legacy metric names are unconventional and not compliant with OpenMetrics standards.
They are included for backwards compatibility.
Example configuration:
```yaml
enable_legacy_metrics: false
```
See https://github.com/matrix-org/synapse/issues/11106 for context.
*Since v1.67.0.*
"""
self.enable_legacy_metrics = config.get("enable_legacy_metrics", True)
self.report_stats = config.get("report_stats", None)
self.report_stats_endpoint = config.get(
"report_stats_endpoint", "https://matrix.org/report-usage-stats/push"

View file

@ -13,10 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
from typing import Any, Optional
from typing import Any, Dict, Optional
from synapse.api.constants import RoomCreationPreset
from synapse.config._base import Config, ConfigError
from synapse.config._base import Config, ConfigError, read_file
from synapse.types import JsonDict, RoomAlias, UserID
from synapse.util.stringutils import random_string_with_symbols, strtobool
@ -27,6 +27,11 @@ password resets, configure Synapse with an SMTP server via the `email` setting,
remove `account_threepid_delegates.email`.
"""
CONFLICTING_SHARED_SECRET_OPTS_ERROR = """\
You have configured both `registration_shared_secret` and
`registration_shared_secret_path`. These are mutually incompatible.
"""
class RegistrationConfig(Config):
section = "registration"
@ -53,7 +58,16 @@ class RegistrationConfig(Config):
self.enable_registration_token_3pid_bypass = config.get(
"enable_registration_token_3pid_bypass", False
)
# read the shared secret, either inline or from an external file
self.registration_shared_secret = config.get("registration_shared_secret")
registration_shared_secret_path = config.get("registration_shared_secret_path")
if registration_shared_secret_path:
if self.registration_shared_secret:
raise ConfigError(CONFLICTING_SHARED_SECRET_OPTS_ERROR)
self.registration_shared_secret = read_file(
registration_shared_secret_path, ("registration_shared_secret_path",)
).strip()
self.bcrypt_rounds = config.get("bcrypt_rounds", 12)
@ -218,6 +232,21 @@ class RegistrationConfig(Config):
else:
return ""
def generate_files(self, config: Dict[str, Any], config_dir_path: str) -> None:
# if 'registration_shared_secret_path' is specified, and the target file
# does not exist, generate it.
registration_shared_secret_path = config.get("registration_shared_secret_path")
if registration_shared_secret_path and not self.path_exists(
registration_shared_secret_path
):
print(
"Generating registration shared secret file "
+ registration_shared_secret_path
)
secret = random_string_with_symbols(50)
with open(registration_shared_secret_path, "w") as f:
f.write(f"{secret}\n")
@staticmethod
def add_arguments(parser: argparse.ArgumentParser) -> None:
reg_group = parser.add_argument_group("registration")

View file

@ -36,6 +36,12 @@ from ._util import validate_config
logger = logging.Logger(__name__)
DIRECT_TCP_ERROR = """
Using direct TCP replication for workers is no longer supported.
Please see https://matrix-org.github.io/synapse/latest/upgrade.html#direct-tcp-replication-is-no-longer-supported-migrate-to-redis
"""
# by default, we attempt to listen on both '::' *and* '0.0.0.0' because some OSes
# (Windows, macOS, other BSD/Linux where net.ipv6.bindv6only is set) will only listen
# on IPv6 when '::' is set.
@ -165,7 +171,6 @@ KNOWN_LISTENER_TYPES = {
"http",
"metrics",
"manhole",
"replication",
}
KNOWN_RESOURCES = {
@ -515,7 +520,9 @@ class ServerConfig(Config):
):
raise ConfigError("allowed_avatar_mimetypes must be a list")
self.listeners = [parse_listener_def(x) for x in config.get("listeners", [])]
self.listeners = [
parse_listener_def(i, x) for i, x in enumerate(config.get("listeners", []))
]
# no_tls is not really supported any more, but let's grandfather it in
# here.
@ -880,9 +887,12 @@ def read_gc_thresholds(
)
def parse_listener_def(listener: Any) -> ListenerConfig:
def parse_listener_def(num: int, listener: Any) -> ListenerConfig:
"""parse a listener config from the config file"""
listener_type = listener["type"]
# Raise a helpful error if direct TCP replication is still configured.
if listener_type == "replication":
raise ConfigError(DIRECT_TCP_ERROR, ("listeners", str(num), "type"))
port = listener.get("port")
if not isinstance(port, int):

View file

@ -27,7 +27,7 @@ from ._base import (
RoutableShardedWorkerHandlingConfig,
ShardedWorkerHandlingConfig,
)
from .server import ListenerConfig, parse_listener_def
from .server import DIRECT_TCP_ERROR, ListenerConfig, parse_listener_def
_FEDERATION_SENDER_WITH_SEND_FEDERATION_ENABLED_ERROR = """
The send_federation config option must be disabled in the main
@ -128,7 +128,8 @@ class WorkerConfig(Config):
self.worker_app = None
self.worker_listeners = [
parse_listener_def(x) for x in config.get("worker_listeners", [])
parse_listener_def(i, x)
for i, x in enumerate(config.get("worker_listeners", []))
]
self.worker_daemonize = bool(config.get("worker_daemonize"))
self.worker_pid_file = config.get("worker_pid_file")
@ -142,7 +143,8 @@ class WorkerConfig(Config):
self.worker_replication_host = config.get("worker_replication_host", None)
# The port on the main synapse for TCP replication
self.worker_replication_port = config.get("worker_replication_port", None)
if "worker_replication_port" in config:
raise ConfigError(DIRECT_TCP_ERROR, ("worker_replication_port",))
# The port on the main synapse for HTTP replication endpoint
self.worker_replication_http_port = config.get("worker_replication_http_port")