|
| 1 | +''' |
| 2 | +''' |
| 3 | +# Licensed to the Apache Software Foundation (ASF) under one |
| 4 | +# or more contributor license agreements. See the NOTICE file |
| 5 | +# distributed with this work for additional information |
| 6 | +# regarding copyright ownership. The ASF licenses this file |
| 7 | +# to you under the Apache License, Version 2.0 (the |
| 8 | +# "License"); you may not use this file except in compliance |
| 9 | +# with the License. You may obtain a copy of the License at |
| 10 | +# |
| 11 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 12 | +# |
| 13 | +# Unless required by applicable law or agreed to in writing, software |
| 14 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 15 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 16 | +# See the License for the specific language governing permissions and |
| 17 | +# limitations under the License. |
| 18 | + |
| 19 | +import os |
| 20 | + |
| 21 | +Test.Summary = ''' |
| 22 | +Verify that when runroot is active, path records from records.yaml are |
| 23 | +overridden by the resolved Layout paths (precedence: env var > runroot > records.yaml). |
| 24 | +
|
| 25 | +When --run-root (or TS_RUNROOT) is set and the PROXY_CONFIG_* environment |
| 26 | +variables for path records are unset, RecConfigOverrideFromEnvironment() |
| 27 | +returns the actual Layout path (e.g. Layout::bindir, Layout::logdir) which |
| 28 | +was populated from runroot.yaml — effectively making runroot.yaml override |
| 29 | +records.yaml for these path records. |
| 30 | +''' |
| 31 | +Test.ContinueOnFail = True |
| 32 | +Test.SkipUnless( |
| 33 | + Test.Variables.BINDIR.startswith(Test.Variables.PREFIX), "need to guarantee bin path starts with prefix for runroot") |
| 34 | + |
| 35 | +ts = Test.MakeATSProcess("ts") |
| 36 | +ts_dir = os.path.join(Test.RunDirectory, "ts") |
| 37 | + |
| 38 | +# Set deliberately WRONG values in records.yaml for all 4 runroot-managed |
| 39 | +# path records. If runroot override works, these values must NOT be used. |
| 40 | +ts.Disk.records_config.append_to_document( |
| 41 | + ''' |
| 42 | + bin_path: wrong_bin_path |
| 43 | + local_state_dir: wrong_runtime |
| 44 | + log: |
| 45 | + logfile_dir: wrong_log |
| 46 | + plugin: |
| 47 | + plugin_dir: wrong_plugin |
| 48 | +''') |
| 49 | + |
| 50 | +# Build the ATS command: |
| 51 | +# - Unset the 4 path env vars (the test framework always sets them, |
| 52 | +# which masks the runroot code path). |
| 53 | +# - Set TS_RUNROOT to the sandbox dir so the runroot mechanism activates. |
| 54 | +original_cmd = ts.Command |
| 55 | +ts.Command = ( |
| 56 | + "env" |
| 57 | + " -u PROXY_CONFIG_BIN_PATH" |
| 58 | + " -u PROXY_CONFIG_LOCAL_STATE_DIR" |
| 59 | + " -u PROXY_CONFIG_LOG_LOGFILE_DIR" |
| 60 | + " -u PROXY_CONFIG_PLUGIN_PLUGIN_DIR" |
| 61 | + f" TS_RUNROOT={ts_dir}" |
| 62 | + f" {original_cmd}") |
| 63 | + |
| 64 | +# --------------------------------------------------------------------------- |
| 65 | +# Test 0: Create runroot.yaml that maps to the sandbox layout, then start ATS. |
| 66 | +# |
| 67 | +# The runroot.yaml must exist before ATS starts because TS_RUNROOT triggers |
| 68 | +# Layout::runroot_setup() during initialization. We write a runroot.yaml |
| 69 | +# whose paths match the sandbox structure the test framework already created |
| 70 | +# (traffic_layout init would create a different FHS-style layout that does |
| 71 | +# not match the sandbox, so we write it manually). |
| 72 | +# --------------------------------------------------------------------------- |
| 73 | +runroot_yaml = os.path.join(ts_dir, 'runroot.yaml') |
| 74 | + |
| 75 | +runroot_lines = [ |
| 76 | + f"prefix: {ts_dir}", |
| 77 | + f"bindir: {os.path.join(ts_dir, 'bin')}", |
| 78 | + f"sbindir: {os.path.join(ts_dir, 'bin')}", |
| 79 | + f"sysconfdir: {os.path.join(ts_dir, 'config')}", |
| 80 | + f"logdir: {os.path.join(ts_dir, 'log')}", |
| 81 | + f"libexecdir: {os.path.join(ts_dir, 'plugin')}", |
| 82 | + f"localstatedir: {os.path.join(ts_dir, 'runtime')}", |
| 83 | + f"runtimedir: {os.path.join(ts_dir, 'runtime')}", |
| 84 | + f"cachedir: {os.path.join(ts_dir, 'cache')}", |
| 85 | +] |
| 86 | +runroot_content = "\\n".join(runroot_lines) + "\\n" |
| 87 | + |
| 88 | +tr = Test.AddTestRun("Create runroot.yaml") |
| 89 | +tr.Processes.Default.Command = f"mkdir -p {ts_dir} && printf '{runroot_content}' > {runroot_yaml}" |
| 90 | +tr.Processes.Default.ReturnCode = 0 |
| 91 | + |
| 92 | +# --------------------------------------------------------------------------- |
| 93 | +# Test 1: Start ATS with runroot active |
| 94 | +# --------------------------------------------------------------------------- |
| 95 | +tr = Test.AddTestRun("Start ATS with runroot") |
| 96 | +tr.Processes.Default.Command = 'echo start' |
| 97 | +tr.Processes.Default.ReturnCode = 0 |
| 98 | +tr.Processes.Default.StartBefore(ts) |
| 99 | +tr.StillRunningAfter = ts |
| 100 | + |
| 101 | +# ATS must not crash (the original nullptr bug) and must complete startup. |
| 102 | +ts.Disk.traffic_out.Content = Testers.ExcludesExpression( |
| 103 | + "basic_string", "must not crash with 'basic_string: construction from null'") |
| 104 | +ts.Disk.traffic_out.Content += Testers.ContainsExpression("records parsing completed", "ATS should complete records parsing") |
| 105 | + |
| 106 | +# Verify the override log messages appear in traffic.out. |
| 107 | +# The errata notes from RecYAMLDecoder are printed by RecCoreInit(). |
| 108 | +ts.Disk.traffic_out.Content += Testers.ContainsExpression( |
| 109 | + "'proxy.config.bin_path' overridden with .* by runroot", "bin_path override by runroot must be logged") |
| 110 | +ts.Disk.traffic_out.Content += Testers.ContainsExpression( |
| 111 | + "'proxy.config.local_state_dir' overridden with .* by runroot", "local_state_dir override by runroot must be logged") |
| 112 | +ts.Disk.traffic_out.Content += Testers.ContainsExpression( |
| 113 | + "'proxy.config.log.logfile_dir' overridden with .* by runroot", "logfile_dir override by runroot must be logged") |
| 114 | +ts.Disk.traffic_out.Content += Testers.ContainsExpression( |
| 115 | + "'proxy.config.plugin.plugin_dir' overridden with .* by runroot", "plugin_dir override by runroot must be logged") |
| 116 | +ts.Disk.traffic_out.Content += Testers.ContainsExpression( |
| 117 | + "'proxy.config.diags.debug.tags' overridden with 'env_wins' by environment variable", |
| 118 | + "diags.debug.tags override by environment variable must be logged") |
| 119 | + |
| 120 | +# --------------------------------------------------------------------------- |
| 121 | +# Test 2: Verify path records do NOT contain the records.yaml values. |
| 122 | +# |
| 123 | +# Because runroot is active and env vars are unset, the records should hold |
| 124 | +# the resolved Layout paths from runroot.yaml, not the records.yaml values. |
| 125 | +# --------------------------------------------------------------------------- |
| 126 | +tr = Test.AddTestRun("Verify runroot overrides records.yaml for path records") |
| 127 | +tr.Processes.Default.Command = ( |
| 128 | + 'traffic_ctl config get' |
| 129 | + ' proxy.config.bin_path' |
| 130 | + ' proxy.config.local_state_dir' |
| 131 | + ' proxy.config.log.logfile_dir' |
| 132 | + ' proxy.config.plugin.plugin_dir') |
| 133 | +tr.Processes.Default.Env = ts.Env |
| 134 | +tr.Processes.Default.ReturnCode = 0 |
| 135 | +tr.StillRunningAfter = ts |
| 136 | + |
| 137 | +# The deliberately wrong records.yaml values must NOT appear. |
| 138 | +tr.Processes.Default.Streams.stdout = Testers.ExcludesExpression( |
| 139 | + 'wrong_bin_path', 'bin_path must be overridden by runroot, not records.yaml') |
| 140 | +tr.Processes.Default.Streams.stdout += Testers.ExcludesExpression( |
| 141 | + 'wrong_runtime', 'local_state_dir must be overridden by runroot, not records.yaml') |
| 142 | +tr.Processes.Default.Streams.stdout += Testers.ExcludesExpression( |
| 143 | + 'wrong_log', 'logfile_dir must be overridden by runroot, not records.yaml') |
| 144 | +tr.Processes.Default.Streams.stdout += Testers.ExcludesExpression( |
| 145 | + 'wrong_plugin', 'plugin_dir must be overridden by runroot, not records.yaml') |
| 146 | + |
| 147 | +# --------------------------------------------------------------------------- |
| 148 | +# Test 3: Verify env vars still take highest precedence over runroot. |
| 149 | +# |
| 150 | +# Set PROXY_CONFIG_DIAGS_DEBUG_TAGS via env and a different value in |
| 151 | +# records.yaml. The env value must win regardless of runroot. |
| 152 | +# --------------------------------------------------------------------------- |
| 153 | +ts.Env['PROXY_CONFIG_DIAGS_DEBUG_TAGS'] = 'env_wins' |
| 154 | +ts.Disk.records_config.update(''' |
| 155 | + diags: |
| 156 | + debug: |
| 157 | + enabled: 0 |
| 158 | + tags: config_value |
| 159 | + ''') |
| 160 | + |
| 161 | +tr = Test.AddTestRun("Verify env var overrides both runroot and records.yaml") |
| 162 | +tr.Processes.Default.Command = 'traffic_ctl config get proxy.config.diags.debug.tags' |
| 163 | +tr.Processes.Default.Env = ts.Env |
| 164 | +tr.Processes.Default.ReturnCode = 0 |
| 165 | +tr.StillRunningAfter = ts |
| 166 | +tr.Processes.Default.Streams.stdout = Testers.ContainsExpression( |
| 167 | + 'proxy.config.diags.debug.tags: env_wins', 'Env var must override both runroot and records.yaml') |
0 commit comments