This is an automated email from the ASF dual-hosted git repository.

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 692223c50 Add configuration to require minimum number of rules in 
remap.config. (#8802)
692223c50 is described below

commit 692223c506aa8e08b9700e00741125bd5081c35c
Author: Alan M. Carroll <[email protected]>
AuthorDate: Thu May 5 21:14:15 2022 -0500

    Add configuration to require minimum number of rules in remap.config. 
(#8802)
---
 doc/admin-guide/files/records.config.en.rst        |  9 +++
 doc/admin-guide/files/remap.config.en.rst          |  6 +-
 mgmt/RecordsConfig.cc                              |  2 +
 proxy/ReverseProxy.cc                              |  2 +-
 proxy/http/remap/RemapConfig.cc                    |  3 +
 proxy/http/remap/UrlRewrite.cc                     | 22 +++---
 proxy/http/remap/UrlRewrite.h                      |  8 +++
 tests/gold_tests/remap/reload_1.replay.yaml        | 39 ++++++++++
 tests/gold_tests/remap/reload_2.replay.yaml        | 39 ++++++++++
 tests/gold_tests/remap/reload_3.replay.yaml        | 39 ++++++++++
 tests/gold_tests/remap/reload_4.replay.yaml        | 39 ++++++++++
 tests/gold_tests/remap/reload_server.replay.yaml   | 51 +++++++++++++
 .../remap/remap_load_empty_failure.test.py         | 30 ++++++++
 .../remap/remap_load_empty_success.test.py         | 33 +++++++++
 .../remap/remap_load_missing_failure.test.py       | 29 ++++++++
 .../remap/remap_load_missing_success.test.py       | 35 +++++++++
 tests/gold_tests/remap/remap_reload.test.py        | 83 ++++++++++++++++++++++
 17 files changed, 458 insertions(+), 11 deletions(-)

diff --git a/doc/admin-guide/files/records.config.en.rst 
b/doc/admin-guide/files/records.config.en.rst
index e359a3cef..94330a9ba 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -3490,6 +3490,15 @@ URL Remap Rules
    Set this variable to ``1`` if you want to retain the client host
    header in a request during remapping.
 
+.. ts:cv:: CONFIG proxy.config.url_remap.min_rules_required INT 0
+   :reloadable:
+
+   The minimum number of rules :file:`remap.config` must have to be considered 
valid. An otherwise
+   valid configuration with fewer than this many rules is considered to be 
invalid as if it had a syntax
+   error. A value of zero allows :file:`remap.config` to be empty or absent.
+
+   This is dynamic to enable different requirements for startup and reloading.
+
 .. _records-config-ssl-termination:
 
 SSL Termination
diff --git a/doc/admin-guide/files/remap.config.en.rst 
b/doc/admin-guide/files/remap.config.en.rst
index 6df6863ce..aba51f79f 100644
--- a/doc/admin-guide/files/remap.config.en.rst
+++ b/doc/admin-guide/files/remap.config.en.rst
@@ -44,7 +44,11 @@ Refer to  :ref:`reverse-proxy-and-http-redirects`, for 
information about
 redirecting HTTP requests and using reverse proxy.
 
 After you modify the :file:`remap.config` run the
-:option:`traffic_ctl config reload` to apply the changes.
+:option:`traffic_ctl config reload` to apply the changes. The current 
configuration is replaced
+with the new configuration only if there are no errors in the file. Any syntax 
error will prevent
+an update. Even if syntactically correct the file is considered valid only if 
it has at least :ts:cv:`proxy.config.url_remap.min_rules_required`
+rules in it. This defaults to 0, but can be set higher if it is desirable to 
prevent loading an
+empty or missing file.
 
 Format
 ======
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index 9cf5bc01b..2be112110 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -1102,6 +1102,8 @@ static const RecordElement RecordsConfig[] =
   ,
   {RECT_CONFIG, "proxy.config.plugin.dynamic_reload_mode", RECD_INT, "1", 
RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.url_remap.min_rules_required", RECD_INT, "0", 
RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-9]+", RECA_NULL}
+  ,
 
   
//##############################################################################
   //#
diff --git a/proxy/ReverseProxy.cc b/proxy/ReverseProxy.cc
index c04f6cdfb..8c0dddd7b 100644
--- a/proxy/ReverseProxy.cc
+++ b/proxy/ReverseProxy.cc
@@ -67,7 +67,7 @@ init_reverse_proxy()
 
   Note("%s loading ...", ts::filename::REMAP);
   if (!rewrite_table->load()) {
-    Warning("%s failed to load", ts::filename::REMAP);
+    Emergency("%s failed to load", ts::filename::REMAP);
   } else {
     Note("%s finished loading", ts::filename::REMAP);
   }
diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc
index 61afbd702..03e50203c 100644
--- a/proxy/http/remap/RemapConfig.cc
+++ b/proxy/http/remap/RemapConfig.cc
@@ -944,6 +944,9 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO 
*bti)
 
   std::error_code ec;
   std::string content{ts::file::load(ts::file::path{path}, ec)};
+  if (ec.value() == ENOENT) { // a missing file is ok - treat as empty, no 
rules.
+    return true;
+  }
   if (ec.value()) {
     Warning("Failed to open remapping configuration file %s - %s", path, 
strerror(ec.value()));
     return false;
diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc
index 96de22b3a..fcd4f39ae 100644
--- a/proxy/http/remap/UrlRewrite.cc
+++ b/proxy/http/remap/UrlRewrite.cc
@@ -89,10 +89,17 @@ UrlRewrite::load()
   Debug("url_rewrite_regex", "strategyFactory file: %s", sf.c_str());
   strategyFactory = new NextHopStrategyFactory(sf.c_str());
 
-  if (0 == this->BuildTable(config_file_path)) {
-    _valid = true;
-    if (is_debug_tag_set("url_rewrite")) {
-      Print();
+  if (TS_SUCCESS == this->BuildTable(config_file_path)) {
+    int n_rules = this->rule_count(); // Minimum # of rules to be considered a 
valid configuration.
+    int required_rules;
+    REC_ReadConfigInteger(required_rules, 
"proxy.config.url_remap.min_rules_required");
+    if (n_rules >= required_rules) {
+      _valid = true;
+      if (is_debug_tag_set("url_rewrite")) {
+        Print();
+      }
+    } else {
+      Warning("%s %d rules defined but %d rules required, configuration is 
invalid.", modulePrefix, n_rules, required_rules);
     }
   } else {
     Warning("something failed during BuildTable() -- check your remap 
plugins!");
@@ -698,11 +705,8 @@ UrlRewrite::BuildTable(const char *path)
   temporary_redirects.hash_lookup.reset(new URLTable);
   forward_mappings_with_recv_port.hash_lookup.reset(new URLTable);
 
-  int zret = 0;
-
   if (!remap_parse_config(path, this)) {
-    // XXX handle file reload error
-    zret = 3;
+    return TS_ERROR;
   }
 
   // Destroy unused tables
@@ -730,7 +734,7 @@ UrlRewrite::BuildTable(const char *path)
     forward_mappings_with_recv_port.hash_lookup.reset(nullptr);
   }
 
-  return zret;
+  return TS_SUCCESS;
 }
 
 /**
diff --git a/proxy/http/remap/UrlRewrite.h b/proxy/http/remap/UrlRewrite.h
index aa5d32d25..b413825ad 100644
--- a/proxy/http/remap/UrlRewrite.h
+++ b/proxy/http/remap/UrlRewrite.h
@@ -108,6 +108,14 @@ public:
     return _valid;
   };
 
+  /// @return  Number of rules defined.
+  int
+  rule_count() const
+  {
+    return num_rules_forward + num_rules_reverse + 
num_rules_redirect_permanent + num_rules_redirect_temporary +
+           num_rules_forward_with_recv_port;
+  }
+
   static constexpr int MAX_REGEX_SUBS = 10;
 
   struct RegexMapping {
diff --git a/tests/gold_tests/remap/reload_1.replay.yaml 
b/tests/gold_tests/remap/reload_1.replay.yaml
new file mode 100644
index 000000000..a65574262
--- /dev/null
+++ b/tests/gold_tests/remap/reload_1.replay.yaml
@@ -0,0 +1,39 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+#
+# This replay file assumes that caching is enabled and
+# proxy.config.http.cache.ignore_client_cc_max_age is set to 0 so that we can
+# test max-age in the client requests.
+#
+
+meta:
+  version: "1.0"
+
+sessions:
+- transactions:
+  - all: { headers: { fields: [[ uuid, success ]]}}
+    client-request:
+      method: "GET"
+      version: "1.1"
+      scheme: "http"
+      url: /index.html
+      headers:
+        fields:
+        - [ Host, charlie.ex ]
+
+    proxy-response:
+      status: 200
diff --git a/tests/gold_tests/remap/reload_2.replay.yaml 
b/tests/gold_tests/remap/reload_2.replay.yaml
new file mode 100644
index 000000000..a65574262
--- /dev/null
+++ b/tests/gold_tests/remap/reload_2.replay.yaml
@@ -0,0 +1,39 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+#
+# This replay file assumes that caching is enabled and
+# proxy.config.http.cache.ignore_client_cc_max_age is set to 0 so that we can
+# test max-age in the client requests.
+#
+
+meta:
+  version: "1.0"
+
+sessions:
+- transactions:
+  - all: { headers: { fields: [[ uuid, success ]]}}
+    client-request:
+      method: "GET"
+      version: "1.1"
+      scheme: "http"
+      url: /index.html
+      headers:
+        fields:
+        - [ Host, charlie.ex ]
+
+    proxy-response:
+      status: 200
diff --git a/tests/gold_tests/remap/reload_3.replay.yaml 
b/tests/gold_tests/remap/reload_3.replay.yaml
new file mode 100644
index 000000000..ac49c7b65
--- /dev/null
+++ b/tests/gold_tests/remap/reload_3.replay.yaml
@@ -0,0 +1,39 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+#
+# This replay file assumes that caching is enabled and
+# proxy.config.http.cache.ignore_client_cc_max_age is set to 0 so that we can
+# test max-age in the client requests.
+#
+
+meta:
+  version: "1.0"
+
+sessions:
+- transactions:
+  - all: { headers: { fields: [[ uuid, success ]]}}
+    client-request:
+      method: "GET"
+      version: "1.1"
+      scheme: "http"
+      url: /index.html
+      headers:
+        fields:
+        - [ Host, charlie.ex ]
+
+    proxy-response:
+      status: 404
diff --git a/tests/gold_tests/remap/reload_4.replay.yaml 
b/tests/gold_tests/remap/reload_4.replay.yaml
new file mode 100644
index 000000000..fc1e00261
--- /dev/null
+++ b/tests/gold_tests/remap/reload_4.replay.yaml
@@ -0,0 +1,39 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+#
+# This replay file assumes that caching is enabled and
+# proxy.config.http.cache.ignore_client_cc_max_age is set to 0 so that we can
+# test max-age in the client requests.
+#
+
+meta:
+  version: "1.0"
+
+sessions:
+- transactions:
+  - all: { headers: { fields: [[ uuid, success ]]}}
+    client-request:
+      method: "GET"
+      version: "1.1"
+      scheme: "http"
+      url: /index.html
+      headers:
+        fields:
+        - [ Host, golf.ex ]
+
+    proxy-response:
+      status: 200
diff --git a/tests/gold_tests/remap/reload_server.replay.yaml 
b/tests/gold_tests/remap/reload_server.replay.yaml
new file mode 100644
index 000000000..c7045e63f
--- /dev/null
+++ b/tests/gold_tests/remap/reload_server.replay.yaml
@@ -0,0 +1,51 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+#
+# This replay file assumes that caching is enabled and
+# proxy.config.http.cache.ignore_client_cc_max_age is set to 0 so that we can
+# test max-age in the client requests.
+#
+
+meta:
+  version: "1.0"
+
+  blocks:
+  - 200_ok_response: &200_ok_response
+      server-response:
+        status: 200
+        reason: OK
+        headers:
+          fields:
+          - [ Content-Length, 16 ]
+          - [ Cache-Control, max-age=300 ]
+
+sessions:
+- transactions:
+  - all: { headers: { fields: [[ uuid, success ]]}}
+    client-request:
+      method: "GET"
+      version: "1.1"
+      scheme: "http"
+      url: /index.html
+      headers:
+        fields:
+        - [ Host, charlie.ex ]
+
+    <<: *200_ok_response
+
+    proxy-response:
+      status: 200
diff --git a/tests/gold_tests/remap/remap_load_empty_failure.test.py 
b/tests/gold_tests/remap/remap_load_empty_failure.test.py
new file mode 100644
index 000000000..29dbfb996
--- /dev/null
+++ b/tests/gold_tests/remap/remap_load_empty_failure.test.py
@@ -0,0 +1,30 @@
+'''
+Verify correct behavior of regex_map in remap.config.
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+Test.Summary = '''
+Test minimum rules on load - fail on missing file.
+'''
+ts = Test.MakeATSProcess("ts")
+ts.Disk.remap_config.AddLine(f"")  # empty file
+ts.Disk.records_config.update({'proxy.config.url_remap.min_rules_required': 1})
+ts.ReturnCode = 33  # expect to Emergency fail due to empty "remap.config".
+
+tr = Test.AddTestRun("test")
+tr.Processes.Default.Command = "echo"
+tr.Processes.Default.StartAfter(ts, ready=When.FileExists(ts.Disk.diags_log))
diff --git a/tests/gold_tests/remap/remap_load_empty_success.test.py 
b/tests/gold_tests/remap/remap_load_empty_success.test.py
new file mode 100644
index 000000000..17dce500c
--- /dev/null
+++ b/tests/gold_tests/remap/remap_load_empty_success.test.py
@@ -0,0 +1,33 @@
+'''
+Verify correct behavior of regex_map in remap.config.
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+Test.Summary = '''
+Test minimum rules on load - succeed on empty file.
+'''
+
+ts = Test.MakeATSProcess("ts")
+ts.Disk.remap_config.AddLine(f"")  # empty file
+ts.Disk.records_config.update({f'proxy.config.url_remap.min_rules_required': 
0})
+
+tr = Test.AddTestRun("startup")
+p = tr.Processes.Default
+p.Command = "sh -c echo"
+p.ReturnCode = 0
+p.StartBefore(Test.Processes.ts)
+tr.StillRunningAfter = ts
diff --git a/tests/gold_tests/remap/remap_load_missing_failure.test.py 
b/tests/gold_tests/remap/remap_load_missing_failure.test.py
new file mode 100644
index 000000000..880d953c7
--- /dev/null
+++ b/tests/gold_tests/remap/remap_load_missing_failure.test.py
@@ -0,0 +1,29 @@
+'''
+Verify correct behavior of regex_map in remap.config.
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+Test.Summary = '''
+Test minimum rules on load - fail on missing file.
+'''
+ts = Test.MakeATSProcess("ts")
+ts.Disk.records_config.update({'proxy.config.url_remap.min_rules_required': 1})
+ts.ReturnCode = 33  # expect to Emergency fail due to empty "remap.config".
+
+tr = Test.AddTestRun("test")
+tr.Processes.Default.Command = "echo"
+tr.Processes.Default.StartAfter(ts, ready=When.FileExists(ts.Disk.diags_log))
diff --git a/tests/gold_tests/remap/remap_load_missing_success.test.py 
b/tests/gold_tests/remap/remap_load_missing_success.test.py
new file mode 100644
index 000000000..fe63f67ee
--- /dev/null
+++ b/tests/gold_tests/remap/remap_load_missing_success.test.py
@@ -0,0 +1,35 @@
+'''
+Verify correct behavior of regex_map in remap.config.
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+Test.Summary = '''
+Test minimum rules on load - succeed on missing file.
+'''
+
+ts = Test.MakeATSProcess("ts")
+
+ts.Disk.records_config.update({
+    f'proxy.config.url_remap.min_rules_required': 0
+})
+
+tr = Test.AddTestRun("startup")
+p = tr.Processes.Default
+p.Command = "sh -c echo"
+p.ReturnCode = 0
+p.StartBefore(Test.Processes.ts)
+tr.StillRunningAfter = ts
diff --git a/tests/gold_tests/remap/remap_reload.test.py 
b/tests/gold_tests/remap/remap_reload.test.py
new file mode 100644
index 000000000..0c5f74873
--- /dev/null
+++ b/tests/gold_tests/remap/remap_reload.test.py
@@ -0,0 +1,83 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+import os
+
+Test.Summary = '''
+Test remap reloading
+'''
+Test.testName = 'remap_reload'
+
+replay_file_1 = "reload_1.replay.yaml"
+replay_file_2 = "reload_2.replay.yaml"
+replay_file_3 = "reload_3.replay.yaml"
+replay_file_4 = "reload_4.replay.yaml"
+
+tm = Test.MakeATSProcess("tm", command="traffic_manager", select_ports=True)
+tm.Disk.diags_log.Content = Testers.ContainsExpression("remap.config failed to 
load", "Remap should fail to load")
+remap_cfg_path = os.path.join(tm.Variables.CONFIGDIR, 'remap.config')
+
+pv = Test.MakeVerifierServerProcess("pv", "reload_server.replay.yaml")
+pv_port = pv.Variables.http_port
+tm.Disk.remap_config.AddLines([f"map http://alpha.ex 
http://alpha.ex:{pv_port}";,
+                               f"map http://bravo.ex 
http://bravo.ex:{pv_port}";,
+                               f"map http://charlie.ex 
http://charlie.ex:{pv_port}";,
+                               f"map http://delta.ex 
http://delta.ex:{pv_port}";])
+tm.Disk.records_config.update({'proxy.config.url_remap.min_rules_required': 3})
+
+nameserver = Test.MakeDNServer("dns", default='127.0.0.1')
+tm.Disk.records_config.update({
+    'proxy.config.dns.nameservers': f"127.0.0.1:{nameserver.Variables.Port}", 
'proxy.config.dns.resolv_conf': 'NULL'
+})
+
+tr_1 = Test.AddTestRun("verify load")
+tr_1.Processes.Default.StartBefore(pv)
+tr_1.Processes.Default.StartBefore(nameserver)
+tr_1.Processes.Default.StartBefore(tm)
+tr_1.AddVerifierClientProcess("client", replay_file_1, 
http_ports=[tm.Variables.port])
+
+tr_2 = Test.AddTestRun("reload-fail")
+tr_2.Processes.Default.Command = 'traffic_ctl config reload'
+tr_2.Processes.Default.Env = tm.Env
+tr_2.Disk.File(remap_cfg_path).WriteOn("")
+tr_2.Disk.File(remap_cfg_path, typename="ats:config").AddLines([
+    f"map http://alpha.ex http://alpha.ex:{pv_port}";, f"map http://bravo.ex 
http://bravo.ex:{pv_port}";
+])
+
+tr_3 = Test.AddTestRun("pause")
+tr_3.Processes.Default.Command = 'sleep 5'
+
+tr_4 = Test.AddTestRun("after first reload")
+tr_4.AddVerifierClientProcess("client_2", replay_file_2, 
http_ports=[tm.Variables.port])
+
+tr_5 = Test.AddTestRun("reload-succeed")
+tr_5.Processes.Default.Command = 'traffic_ctl config reload'
+tr_5.Processes.Default.Env = tm.Env
+tr_5.Disk.File(remap_cfg_path).WriteOn("")
+tr_5.Disk.File(remap_cfg_path,
+               typename="ats:config").AddLines([f"map http://echo.ex 
http://echo.ex:{pv_port}";,
+                                                f"map http://foxtrot.ex 
http://foxtrot.ex:{pv_port}";,
+                                                f"map http://golf.ex 
http://golf.ex:{pv_port}";,
+                                                f"map http://hotel.ex 
http://hotel.ex:{pv_port}";,
+                                                f"map http://india.ex 
http://india.ex:{pv_port}";])
+
+tr_6 = Test.AddTestRun("pause")
+tr_6.Processes.Default.Command = 'sleep 5'
+
+tr_7 = Test.AddTestRun("post update charlie")
+tr_7.AddVerifierClientProcess("client_3", replay_file_3, 
http_ports=[tm.Variables.port])
+
+tr_8 = Test.AddTestRun("post update golf")
+tr_8.AddVerifierClientProcess("client_4", replay_file_4, 
http_ports=[tm.Variables.port])

Reply via email to