summaryrefslogtreecommitdiffstats
path: root/nixos/tests/opentelemetry-collector-validate.nix
blob: c06d5d76e6941c141e26249755b24e3cc1fef60d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# Build-time test for the configuration validation of the
# services.opentelemetry-collector module. It needs no VM: everything under
# test happens while the configuration is evaluated and built.
{
  lib,
  runCommand,
  testers,
  writeText,
  evalSystem,
}:
let
  evalService =
    module:
    (evalSystem {
      services.opentelemetry-collector = {
        enable = true;
      }
      // module;
    }).config;

  optionsOf = config: config.services.opentelemetry-collector;
  execStartOf = config: config.systemd.services.opentelemetry-collector.serviceConfig.ExecStart;
  confOf = config: config.system.build.opentelemetryCollectorConfig;

  minimalSettings = {
    receivers.otlp.protocols.http = { };
    exporters.debug = { };
    service.pipelines.logs = {
      receivers = [ "otlp" ];
      exporters = [ "debug" ];
    };
  };

  secretRef = "\${file:/var/lib/secrets/otel-token}";

  # A configuration that reads a secret through a confmap provider. Validation
  # fails on it unless the property is overridden, because the file does not
  # exist in the build sandbox.
  secretSettings = {
    receivers.otlp.protocols.http = { };
    exporters.otlphttp = {
      endpoint = "http://localhost:4318";
      headers.authorization = "Bearer ${secretRef}";
    };
    service.pipelines.logs = {
      receivers = [ "otlp" ];
      exporters = [ "otlphttp" ];
    };
  };

  # A pipeline that references an exporter nobody configured.
  invalidSettings = {
    receivers.otlp.protocols.http = { };
    exporters.debug = { };
    service.pipelines.logs = {
      receivers = [ "otlp" ];
      exporters = [ "nonexistent" ];
    };
  };

  fromSettings = evalService { settings = minimalSettings; };
  fromStoreConfigFile = evalService {
    configFile = writeText "config.yaml" (builtins.toJSON minimalSettings);
  };
  fromExternalConfigFile = evalService {
    configFile = "/etc/opentelemetry-collector/config.yaml";
  };
  withOverrides = evalService {
    settings = secretSettings;
    validateConfigOverrides = [ "exporters::otlphttp::headers::authorization=stub" ];
  };
  withoutOverrides = evalService { settings = secretSettings; };
  invalid = evalService { settings = invalidSettings; };
in
# A configuration built from `settings` is always a store path, so it is always
# validated. This is the regression that motivated the option: the default used
# to be `isStorePath cfg.configFile`, which is false when `configFile` is null.
assert (optionsOf fromSettings).validateConfigFile;
assert (optionsOf fromStoreConfigFile).validateConfigFile;
# A configFile outside the store does not exist at build time, so validation
# must stay off and the service must point at the path verbatim.
assert !(optionsOf fromExternalConfigFile).validateConfigFile;
assert lib.hasSuffix "--config=file:/etc/opentelemetry-collector/config.yaml" (
  execStartOf fromExternalConfigFile
);

runCommand "opentelemetry-collector-validate-test"
  {
    # Building `validated` runs `otelcol validate`, which only passes because
    # the `--set` override replaces the file provider reference.
    validated = confOf withOverrides;
    invalidFailure = testers.testBuildFailure (confOf invalid);
    unresolvableFailure = testers.testBuildFailure (confOf withoutOverrides);
  }
  ''
    # The override applies to validation only: the deployed configuration keeps
    # the provider reference.
    grep -F ${lib.escapeShellArg secretRef} $validated
    ! grep -F stub $validated

    # Validation rejects a config whose pipeline references an undefined
    # component.
    grep -F nonexistent $invalidFailure/testBuildFailure.log

    # Without an override, validation resolves the file provider and fails,
    # because the secret does not exist in the sandbox.
    grep -F /var/lib/secrets/otel-token $unresolvableFailure/testBuildFailure.log

    touch $out
  ''