diff --git a/make/harbor.yml.tmpl b/make/harbor.yml.tmpl index 260fa7012..100ac8a5f 100644 --- a/make/harbor.yml.tmpl +++ b/make/harbor.yml.tmpl @@ -199,3 +199,19 @@ proxy: # enabled: false # port: 9090 # path: /metrics + +trace: + enabled: true + sample_rate: 1 + jaeger: + endpoint: http://localhost + username: http://localhost + password: + agent_host: localhost + agent_port: 6832 + otel: + endpoint: http://localhost + url_path: /v1/traces + compression: no + insecure: false + timeout: 10s diff --git a/make/photon/prepare/models.py b/make/photon/prepare/models.py index e3530acd5..2c75e2001 100644 --- a/make/photon/prepare/models.py +++ b/make/photon/prepare/models.py @@ -103,11 +103,10 @@ class InternalTLS: return raise Exception('cert file {} should include SAN'.format(filename)) - - def validate(self) -> bool: + def validate(self): if not self.enabled: # pass the validation if not enabled - return True + return if not internal_tls_dir.exists(): raise Exception('Internal dir for tls {} not exist'.format(internal_tls_dir)) @@ -115,8 +114,6 @@ class InternalTLS: for filename in self.required_filenames: self._check(filename) - return True - def prepare(self): """ Prepare moves certs in tls file to data volume with correct permission. @@ -140,7 +137,6 @@ class InternalTLS: else: os.chown(file, DEFAULT_UID, DEFAULT_GID) - class Metric: def __init__(self, enabled: bool = False, port: int = 8080, path: str = "metrics" ): self.enabled = enabled @@ -149,4 +145,50 @@ class Metric: def validate(self): if not port_number_valid(self.port): - raise Exception('Port number in metrics is not valid') \ No newline at end of file + raise Exception('Port number in metrics is not valid') + + +class JaegerExporter: + def __init__(self, config: dict): + if not config: + return None + self.endpoint = config.get('endpoint') + self.username = config.get('username') + self.password = config.get('password') + self.agent_host = config.get('agent_host') + self.agent_port = config.get('agent_port') + + def validate(self): + if not self.endpoint and self.agent_host is None: + raise Exception('Jaeger Colector Endpoint or Agent host not set') + +class OtelExporter: + def __init__(self, config: dict): + if not config: + return None + self.endpoint = config.get('endpoint') + self.url_path = config.get('url_path') + self.compression = config.get('compression') or False + self.insecure = config.get('insecure') or False + self.timeout = config.get('timeout') or '10s' + + def validate(self): + if not self.endpoint: + raise Exception('Trace endpoint not set') + if not self.url_path: + raise Exception('Trace url path not set') + +class Trace: + def __init__(self, config: dict): + self.enabled = config.get('enabled', False) + self.sample_rate = config.get('sample_rate', 1) + self.jaeger = config.get('jaeger', {}) + self.otel_exporter = config.get('otel_exporter', {}) + + def validate(self): + if self.jaeger is None and self.otel_exporter is None: + raise Exception('Trace enabled but no trace exporter set') + if self.jaeger is not None: + JaegerExporter(self.jaeger).validate() + if self.otel_exporter is not None: + OtelExporter(self.otel_exporter).validate() diff --git a/make/photon/prepare/templates/core/env.jinja b/make/photon/prepare/templates/core/env.jinja index c279d2504..c020ecf73 100644 --- a/make/photon/prepare/templates/core/env.jinja +++ b/make/photon/prepare/templates/core/env.jinja @@ -62,3 +62,26 @@ METRIC_PORT={{ metric.port }} METRIC_NAMESPACE=harbor METRIC_SUBSYSTEM=core {% endif %} + +{% if trace.enabled %} +TRACE_ENABLE=true +TRACE_SAMPLE_RATE={{ trace.sample_rate }} +{% if trace.jaeger is defined %} +TRACE_JAEGER_ENDPOINT={{ trace.jaeger.endpoint }} +TRACE_JAEGER_USERNAME={{ trace.jaeger.username }} +TRACE_JAEGER_PASSWORD={{ trace.jaeger.password }} +TRACE_JAEGER_AGENT_HOSTNAME={{ trace.jaeger.agent_host }} +TRACE_JAEGER_AGENT_PORT={{ trace.jaeger.agent_port }} +{% endif %} +{%if trace.otel is defined %} +TRACE_OTEL_TRACE_ENDPOINT={{ trace.otel.trace.endpoint }} +TRACE_OTEL_TRACE_URL_PATH={{ trace.otel.trace.url_path }} +TRACE_OTEL_TRACE_COMPRESSION={{ trace.otel.trace.compression }} +TRACE_OTEL_TRACE_INSECURE={{ trace.otel.trace.insecure }} +TRACE_OTEL_TRACE_TIMEOUT={{ trace.otel.trace.timeout }} +TRACE_OTEL_RETRY_ENABLED={{ trace.otel.retry.enabled }} +TRACE_OTEL_RETRY_INITIAL_INTERNAL={{ trace.otel.retry.initial_internal }} +TRACE_OTEL_RETRY_MAX_INTERNAL={{ trace.otel.retry.max_internal }} +TRACE_OTEL_RETRY_MAX_ELAPSED={{ trace.otel.retry.max_elapsed }} +{% endif %} +{% endif %} \ No newline at end of file diff --git a/make/photon/prepare/utils/configs.py b/make/photon/prepare/utils/configs.py index 6f1a7cf27..ca907d938 100644 --- a/make/photon/prepare/utils/configs.py +++ b/make/photon/prepare/utils/configs.py @@ -3,7 +3,7 @@ import os import yaml from urllib.parse import urlencode from g import versions_file_path, host_root_dir, DEFAULT_UID, INTERNAL_NO_PROXY_DN -from models import InternalTLS, Metric +from models import InternalTLS, Metric, Trace from utils.misc import generate_random_string, owner_can_read, other_can_read default_db_max_idle_conns = 2 # NOTE: https://golang.org/pkg/database/sql/#DB.SetMaxIdleConns @@ -327,6 +327,11 @@ def parse_yaml_config(config_file_path, with_notary, with_trivy, with_chartmuseu else: config_dict['metric'] = Metric() + # trace configs + trace_config = configs.get('trace') + if trace_config: + config_dict = Trace(trace_config) + if config_dict['internal_tls'].enabled: config_dict['portal_url'] = 'https://portal:8443' config_dict['registry_url'] = 'https://registry:5443'